]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Memcached_DataObject.php
Merge branch '1.0.x' of gitorious.org:statusnet/mainline into 1.0.x
[quix0rs-gnu-social.git] / classes / Memcached_DataObject.php
index c361ba878313f0ddbf51ab0d0125d76ea6e5c6fe..e1610c56b214e34205c380dc1c187d2453c3c0a2 100644 (file)
@@ -63,7 +63,154 @@ class Memcached_DataObject extends Safe_DataObject
         }
         return $i;
     }
+    
+    /**
+     * Get multiple items from the database by key
+     * 
+     * @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)
+    {
+       $result = self::pivotGet($cls, $keyCol, $keyVals);
+       
+       $values = array_values($result);
+       
+       if ($skipNulls) {
+               $tmp = array();
+               foreach ($values as $value) {
+                       if (!empty($value)) {
+                               $tmp[] = $value;
+                       }
+               }
+               $values = $tmp;
+       }
+       
+       return new ArrayWrapper($values);
+    }
+    
+    /**
+     * Get multiple items from the database by key
+     * 
+     * @param string  $cls       Class to fetch
+     * @param string  $keyCol    name of column for key
+     * @param array   $keyVals   key values to fetch
+     * @param boolean $otherCols Other columns to hold fixed
+     * 
+     * @return array Array mapping $keyVals to objects, or null if not found
+     */
+    static function pivotGet($cls, $keyCol, $keyVals, $otherCols = array())
+    {
+       $result = array_fill_keys($keyVals, null);
+       
+       $toFetch = array();
+       
+       foreach ($keyVals as $keyVal) {
+               
+               $kv = array_merge($otherCols, array($keyCol => $keyVal));
+               
+               $i = self::multicache($cls, $kv);
+               
+               if ($i !== false) {
+                       $result[$keyVal] = $i;
+               } else if (!empty($keyVal)) {
+                       $toFetch[] = $keyVal;
+               }
+       }
+       
+       if (count($toFetch) > 0) {
+            $i = DB_DataObject::factory($cls);
+            if (empty($i)) {
+               throw new Exception(_('Cannot instantiate class ' . $cls));
+            }
+            foreach ($otherCols as $otherKeyCol => $otherKeyVal) {
+                $i->$otherKeyCol = $otherKeyVal;
+            }
+               $i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
+               if ($i->find()) {
+                       while ($i->fetch()) {
+                               $copy = clone($i);
+                               $copy->encache();
+                               $result[$i->$keyCol] = $copy;
+                       }
+               }
+               
+               // Save state of DB misses
+               
+               foreach ($toFetch as $keyVal) {
+                       if (empty($result[$keyVal])) {
+                               $kv = array_merge($otherCols, array($keyCol => $keyVal));
+                       // save the fact that no such row exists
+                       $c = self::memcache();
+                       if (!empty($c)) {
+                       $ck = self::multicacheKey($cls, $kv);
+                       $c->set($ck, null);
+                       }       
+                       }
+               }
+       }
+       
+       return $result;
+    }
+    
+    function listGet($cls, $keyCol, $keyVals)
+    {
+       $result = array_fill_keys($keyVals, array());
+       
+       $toFetch = array();
+       
+       foreach ($keyVals as $keyVal) {
+           $l = self::cacheGet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal));
+           if ($l !== false) {
+               $result[$keyVal] = $l;
+           } else {
+               $toFetch[] = $keyVal;
+           }
+       }
+        
+        if (count($toFetch) > 0) {
+               $i = DB_DataObject::factory($cls);
+               if (empty($i)) {
+                       throw new Exception(_('Cannot instantiate class ' . $cls));
+               }
+                       $i->whereAddIn($keyCol, $toFetch, $i->columnType($keyCol));
+                       if ($i->find()) {
+                               while ($i->fetch()) {
+                                       $copy = clone($i);
+                                       $copy->encache();
+                                       $result[$i->$keyCol][] = $copy;
+                               }
+                       }        
+               foreach ($toFetch as $keyVal)
+               {
+                       self::cacheSet(sprintf("%s:list:%s:%s", $cls, $keyCol, $keyVal),
+                                                  $result[$keyVal]);   
+               }      
+        }
+       
+       return $result;        
+    }
 
+       function columnType($columnName)
+       {
+               $keys = $this->table();
+               if (!array_key_exists($columnName, $keys)) {
+                       throw new Exception('Unknown key column ' . $columnName . ' in ' . join(',', array_keys($keys)));
+               }
+               
+               $def = $keys[$columnName];
+               
+               if ($def & DB_DATAOBJECT_INT) {
+                       return 'integer';
+               } else {
+                       return 'string';
+               }
+       }
+       
     /**
      * @fixme Should this return false on lookup fail to match staticGet?
      */
@@ -78,7 +225,13 @@ class Memcached_DataObject extends Safe_DataObject
                 return false;
             }
             foreach ($kv as $k => $v) {
-                $i->$k = $v;
+               if (is_null($v)) {
+                       // XXX: possible SQL injection...? Don't 
+                       // pass keys from the browser, eh.
+                       $i->whereAdd("$k is null");
+               } else {
+                       $i->$k = $v;
+               }
             }
             if ($i->find(true)) {
                 $i->encache();