X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=classes%2FMemcached_DataObject.php;h=41ce715210bec85bcf8f4cf314475a99a34c084c;hb=be0c10e8f6f9c60b1cb840cda9ac6f42c8289738;hp=262f83b83ccfb99b137d33099c21d135ff073b61;hpb=fac7371179278e9a2d702056f1bfe4b756497796;p=quix0rs-gnu-social.git diff --git a/classes/Memcached_DataObject.php b/classes/Memcached_DataObject.php index 262f83b83c..41ce715210 100644 --- a/classes/Memcached_DataObject.php +++ b/classes/Memcached_DataObject.php @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -if (!defined('STATUSNET') && !defined('LACONICA')) { exit(1); } +if (!defined('GNUSOCIAL')) { exit(1); } class Memcached_DataObject extends Safe_DataObject { @@ -32,12 +32,9 @@ class Memcached_DataObject extends Safe_DataObject */ static function getClassKV($cls, $k, $v=null) { - if (!is_a($cls, __CLASS__, true)) { - throw new Exception('Trying to fetch ' . __CLASS__ . ' into a non-related class'); - } if (is_null($v)) { $v = $k; - $keys = self::pkeyCols($cls); + $keys = static::pkeyCols(); if (count($keys) > 1) { // FIXME: maybe call pkeyGetClass() ourselves? throw new Exception('Use pkeyGetClass() for compound primary keys'); @@ -70,27 +67,35 @@ class Memcached_DataObject extends Safe_DataObject * @param string $cls Class to fetch * @param string $keyCol name of column for key * @param array $keyVals key values to fetch - * @param boolean $skipNulls return only non-null results? * * @return array Array of objects, in order */ - function multiGet($cls, $keyCol, $keyVals, $skipNulls=true) + static function multiGetClass($cls, $keyCol, array $keyVals) { - $result = self::pivotGetClass($cls, $keyCol, $keyVals); + $obj = new $cls; - $values = array_values($result); + // PHP compatible datatype for settype() below + $colType = $obj->columnType($keyCol); - if ($skipNulls) { - $tmp = array(); - foreach ($values as $value) { - if (!empty($value)) { - $tmp[] = $value; - } - } - $values = $tmp; + if (!in_array($colType, array('integer', 'int'))) { + // This is because I'm afraid to escape strings incorrectly + // in the way we use them below in FIND_IN_SET for MariaDB + throw new ServerException('Cannot do multiGet on anything but integer columns'); } - return new ArrayWrapper($values); + $obj->whereAddIn($keyCol, $keyVals, $colType); + + // Since we're inputting straight to a query: format and escape + foreach ($keyVals as $key=>$val) { + settype($val, $colType); + $keyVals[$key] = $obj->escape($val); + } + + // FIND_IN_SET will make sure we keep the desired order + $obj->orderBy(sprintf("FIND_IN_SET(%s, '%s')", $keyCol, implode(',', $keyVals))); + $obj->find(); + + return $obj; } /** @@ -105,9 +110,6 @@ class Memcached_DataObject extends Safe_DataObject */ static function pivotGetClass($cls, $keyCol, array $keyVals, array $otherCols = array()) { - if (!is_a($cls, __CLASS__, true)) { - throw new Exception('Trying to fetch ' . __CLASS__ . ' into a non-related class'); - } if (is_array($keyCol)) { foreach ($keyVals as $keyVal) { $result[implode(',', $keyVal)] = null; @@ -244,11 +246,8 @@ class Memcached_DataObject extends Safe_DataObject return $query; } - static function pkeyCols($cls) + static function pkeyColsClass($cls) { - if (!is_a($cls, __CLASS__, true)) { - throw new Exception('Trying to fetch ' . __CLASS__ . ' into a non-related class'); - } $i = new $cls; $types = $i->keyTypes(); ksort($types); @@ -264,15 +263,23 @@ class Memcached_DataObject extends Safe_DataObject return $pkey; } - static function listGetClass($cls, $keyCol, $keyVals) + static function listFindClass($cls, $keyCol, array $keyVals) { - if (!is_a($cls, __CLASS__, true)) { - throw new Exception('Trying to fetch ' . __CLASS__ . ' into a non-related class'); + $i = new $cls; + $i->whereAddIn($keyCol, $keyVals, $i->columnType($keyCol)); + if (!$i->find()) { + throw new NoResultException($i); } + + return $i; + } + + static function listGetClass($cls, $keyCol, array $keyVals) + { $pkeyMap = array_fill_keys($keyVals, array()); $result = array_fill_keys($keyVals, array()); - $pkeyCols = self::pkeyCols($cls); + $pkeyCols = static::pkeyCols(); $toFetch = array(); $allPkeys = array(); @@ -305,10 +312,9 @@ class Memcached_DataObject extends Safe_DataObject } if (count($toFetch) > 0) { - $i = new $cls; - $i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol)); - if ($i->find()) { - sprintf(__CLASS__ . "() got {$i->N} results for class $cls key $keyCol"); + try { + $i = self::listFindClass($cls, $keyCol, $toFetch); + while ($i->fetch()) { $copy = clone($i); $copy->encache(); @@ -319,6 +325,8 @@ class Memcached_DataObject extends Safe_DataObject } $pkeyMap[$i->$keyCol][] = $pkeyVal; } + } catch (NoResultException $e) { + // no results found for our keyVals, so we leave them as empty arrays } foreach ($toFetch as $keyVal) { self::cacheSet(sprintf("%s:list-ids:%s:%s", strtolower($cls), $keyCol, $keyVal), @@ -348,12 +356,9 @@ class Memcached_DataObject extends Safe_DataObject /** * @todo FIXME: Should this return false on lookup fail to match getKV? */ - static function pkeyGetClass($cls, $kv) + static function pkeyGetClass($cls, array $kv) { - if (!is_a($cls, __CLASS__, true)) { - throw new Exception('Trying to fetch ' . __CLASS__ . ' into a non-related class'); - } - $i = Memcached_DataObject::multicache($cls, $kv); + $i = self::multicache($cls, $kv); if ($i !== false) { // false == cache miss return $i; } else { @@ -391,23 +396,23 @@ class Memcached_DataObject extends Safe_DataObject return $result; } - function update($orig=null) + function update($dataObject=false) { - if (is_object($orig) && $orig instanceof Memcached_DataObject) { - $orig->decache(); # might be different keys + if (is_object($dataObject) && $dataObject instanceof Memcached_DataObject) { + $dataObject->decache(); # might be different keys } - $result = parent::update($orig); - if ($result) { + $result = parent::update($dataObject); + if ($result !== false) { $this->fixupTimestamps(); $this->encache(); } return $result; } - function delete() + function delete($useWhere=false) { $this->decache(); # while we still have the values! - return parent::delete(); + return parent::delete($useWhere); } static function memcache() { @@ -425,16 +430,16 @@ class Memcached_DataObject extends Safe_DataObject } static function getcached($cls, $k, $v) { - $c = Memcached_DataObject::memcache(); + $c = self::memcache(); if (!$c) { return false; } else { - $obj = $c->get(Memcached_DataObject::cacheKey($cls, $k, $v)); + $obj = $c->get(self::cacheKey($cls, $k, $v)); if (0 == strcasecmp($cls, 'User')) { // Special case for User if (is_object($obj) && is_object($obj->id)) { common_log(LOG_ERR, "User " . $obj->nickname . " was cached with User as ID; deleting"); - $c->delete(Memcached_DataObject::cacheKey($cls, $k, $v)); + $c->delete(self::cacheKey($cls, $k, $v)); return false; } } @@ -456,16 +461,16 @@ class Memcached_DataObject extends Safe_DataObject } global $_DB_DATAOBJECT; - if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"])) { + if (!isset($_DB_DATAOBJECT['INI'][$this->_database][$this->tableName()."__keys"])) { $this->databaseStructure(); } - return $_DB_DATAOBJECT['INI'][$this->_database][$this->__table."__keys"]; + return $_DB_DATAOBJECT['INI'][$this->_database][$this->tableName()."__keys"]; } function encache() { - $c = $this->memcache(); + $c = self::memcache(); if (!$c) { return false; @@ -486,7 +491,7 @@ class Memcached_DataObject extends Safe_DataObject function decache() { - $c = $this->memcache(); + $c = self::memcache(); if (!$c) { return false; @@ -517,7 +522,7 @@ class Memcached_DataObject extends Safe_DataObject if (empty($this->$key)) { continue; } - $ckeys[] = $this->cacheKey($this->tableName(), $key, self::valueString($this->$key)); + $ckeys[] = self::cacheKey($this->tableName(), $key, self::valueString($this->$key)); } else if ($type == 'K' || $type == 'N') { $pkey[] = $key; $pval[] = self::valueString($this->$key); @@ -533,7 +538,7 @@ class Memcached_DataObject extends Safe_DataObject $pvals = implode(',', $pval); $pkeys = implode(',', $pkey); - $ckeys[] = $this->cacheKey($this->tableName(), $pkeys, $pvals); + $ckeys[] = self::cacheKey($this->tableName(), $pkeys, $pvals); return $ckeys; } @@ -582,7 +587,7 @@ class Memcached_DataObject extends Safe_DataObject static function cachedQuery($cls, $qry, $expiry=3600) { - $c = Memcached_DataObject::memcache(); + $c = self::memcache(); if (!$c) { $inst = new $cls(); $inst->query($qry); @@ -729,17 +734,17 @@ class Memcached_DataObject extends Safe_DataObject return $string; } - // We overload so that 'SET NAMES "utf8"' is called for + // We overload so that 'SET NAMES "utf8mb4"' is called for // each connection function _connect() { - global $_DB_DATAOBJECT; + global $_DB_DATAOBJECT, $_PEAR; $sum = $this->_getDbDsnMD5(); if (!empty($_DB_DATAOBJECT['CONNECTIONS'][$sum]) && - !PEAR::isError($_DB_DATAOBJECT['CONNECTIONS'][$sum])) { + !$_PEAR->isError($_DB_DATAOBJECT['CONNECTIONS'][$sum])) { $exists = true; } else { $exists = false; @@ -761,7 +766,9 @@ class Memcached_DataObject extends Safe_DataObject // we'll need some fancier logic here. if (!$exists && !empty($_DB_DATAOBJECT['CONNECTIONS']) && php_sapi_name() == 'cli') { foreach ($_DB_DATAOBJECT['CONNECTIONS'] as $index => $conn) { - if (!empty($conn)) { + if ($_PEAR->isError($conn)) { + common_log(LOG_WARNING, __METHOD__ . " cannot disconnect failed DB connection: '".$conn->getMessage()."'."); + } elseif (!empty($conn)) { $conn->disconnect(); } unset($_DB_DATAOBJECT['CONNECTIONS'][$index]); @@ -776,10 +783,10 @@ class Memcached_DataObject extends Safe_DataObject common_config('db', 'utf8')) { $conn = $DB->connection; if (!empty($conn)) { - if ($DB instanceof DB_mysqli) { - mysqli_set_charset($conn, 'utf8'); - } else if ($DB instanceof DB_mysql) { - mysql_set_charset('utf8', $conn); + if ($DB instanceof DB_mysqli || $DB instanceof MDB2_Driver_mysqli) { + mysqli_set_charset($conn, 'utf8mb4'); + } else if ($DB instanceof DB_mysql || $DB instanceof MDB2_Driver_mysql) { + mysql_set_charset('utf8mb4', $conn); } } } @@ -817,7 +824,7 @@ class Memcached_DataObject extends Safe_DataObject global $_DB_DATAOBJECT; if (empty($_DB_DATAOBJECT['CONFIG'])) { - DB_DataObject::_loadConfig(); + self::_loadConfig(); } $options = &$_DB_DATAOBJECT['CONFIG']; @@ -829,7 +836,7 @@ class Memcached_DataObject extends Safe_DataObject if (!$dsn) { if (!$this->_database) { - $this->_database = isset($options["table_{$this->__table}"]) ? $options["table_{$this->__table}"] : null; + $this->_database = isset($options["table_{$this->tableName()}"]) ? $options["table_{$this->tableName()}"] : null; } if ($this->_database && !empty($options["database_{$this->_database}"])) {