extend usage of in-class cache in Tinebase_Container
[tine20] / tine20 / Tinebase / Container.php
index fb2ea5c..298d594 100644 (file)
@@ -80,12 +80,6 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
      */
     protected $_defaultCountCol = 'id';
     
-    protected $_classCache = array(
-        'getContainerByACL' => array(),
-        'getContainerById'  => array(),
-        'hasGrant'          => array()
-    );
-
     /**
      * cache timeout for ACL related cache entries (in seconds)
      * 
@@ -376,7 +370,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
     {
         $select = $this->_getSelect();
         $select->where($this->_db->quoteIdentifier('uuid') . ' = ' . $this->_db->quoteIdentifier('name'));
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $rows = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
         
         $result = new Tinebase_Record_RecordSet('Tinebase_Model_Container', $rows, TRUE);
@@ -412,8 +406,10 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         
         $classCacheId = convertCacheId($accountId . $applicationId . implode('', (array)$grant) . (int)$onlyIds . (int)$ignoreACL);
         
-        if (isset($this->_classCache[__FUNCTION__][$classCacheId])) {
-            return $this->_classCache[__FUNCTION__][$classCacheId];
+        try {
+            return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            // continue...
         }
         
         $select = $this->_getSelect($onlyIds ? 'id' : '*')
@@ -432,7 +428,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         
         $this->addGrantsSql($select, $accountId, $grant);
         
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         
         if ($onlyIds) {
             $result = $stmt->fetchAll(Zend_Db::FETCH_COLUMN);
@@ -451,7 +447,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             }
         }
         
-        $this->_classCache[__FUNCTION__][$classCacheId] = $result;
+        $this->saveInClassCache(__FUNCTION__, $classCacheId, $result);
         
         return $result;
     }
@@ -474,8 +470,10 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         $classCacheId = $containerId . 'd' . (int)$_getDeleted;
         $cacheId      = 'getContainerById' . $classCacheId;
         
-        if (isset($this->_classCache[__FUNCTION__][$classCacheId])) {
-            return $this->_classCache[__FUNCTION__][$classCacheId];
+        try {
+            return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            // continue...
         }
         
         // load from cache
@@ -487,7 +485,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             $cache->save($result, $cacheId, array('container'));
         }
         
-        $this->_classCache[__FUNCTION__][$classCacheId] = $result;
+        $this->saveInClassCache(__FUNCTION__, $classCacheId, $result);
         
         return $result;
     }
@@ -544,7 +542,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             $select->where("{$this->_db->quoteIdentifier('owner.account_id')} = ?", $ownerId);
         }
         
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $containersData = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
         
         if (count($containersData) == 0) {
@@ -578,7 +576,22 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         $ownerId     = Tinebase_Model_User::convertUserIdToInt($_owner);
         $grant       = $_ignoreACL ? '*' : $_grant;
         $application = Tinebase_Application::getInstance()->getApplicationByName($meta['appName']);
-
+        
+        $classCacheId = convertCacheId(
+            $accountId .
+            $application->getId() .
+            ($meta['recordClass'] ? $meta['recordClass'] : null) .
+            $ownerId .
+            implode('', (array)$grant) .
+            (int)$_ignoreACL
+        );
+        
+        try {
+            return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            // continue...
+        }
+        
         $select = $this->_db->select()
             ->distinct()
             ->from(array('owner' => SQL_TABLE_PREFIX . 'container_acl'), array())
@@ -607,7 +620,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             $select->where("{$this->_db->quoteIdentifier('container.model')} = ?", $meta['recordClass']);
         }
         
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $containersData = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
         
         // if no containers where found, maybe something went wrong when creating the initial folder
@@ -621,6 +634,8 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         }
 
         $containers = new Tinebase_Record_RecordSet('Tinebase_Model_Container', $containersData, TRUE);
+        
+        $this->saveInClassCache(__FUNCTION__, $classCacheId, $containers);
 
         return $containers;
     }
@@ -751,9 +766,23 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
      */
     public function getSharedContainer($_accountId, $_application, $_grant, $_ignoreACL = FALSE)
     {
+        $accountId   = Tinebase_Model_User::convertUserIdToInt($_accountId);
         $application = Tinebase_Application::getInstance()->getApplicationByName($_application);
         $grant       = $_ignoreACL ? '*' : $_grant;
         
+        $classCacheId = convertCacheId(
+            $accountId .
+            $application->getId() .
+            implode('', (array)$grant) .
+            (int)$_ignoreACL
+        );
+        
+        try {
+            return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            // continue...
+        }
+        
         $select = $this->_getSelect()
             ->distinct()
             ->join(array(
@@ -767,12 +796,14 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             
             ->order('container.name');
         
-        $this->addGrantsSql($select, $_accountId, $grant);
+        $this->addGrantsSql($select, $accountId, $grant);
+        
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         
-        $stmt = $this->_db->query($select);
-
         $containers = new Tinebase_Record_RecordSet('Tinebase_Model_Container', $stmt->fetchAll(Zend_Db::FETCH_ASSOC), TRUE);
         
+        $this->saveInClassCache(__FUNCTION__, $classCacheId, $containers);
+        
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ 
             . ' Found ' . count($containers) . ' shared container(s) in application ' . $application->name);
         
@@ -828,7 +859,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             
         $this->addGrantsSql($select, $accountId, $grant);
         
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $containerIds = $stmt->fetchAll(Zend_Db::FETCH_COLUMN);
         
         // no container ids found / can stop here
@@ -855,7 +886,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             ->where("{$this->_db->quoteIdentifier('container_acl.account_grant')} = ?", Tinebase_Model_Grants::GRANT_ADMIN)
             ->where("{$this->_db->quoteIdentifier('accounts.status')} = ?", 'enabled');
             
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $accountIds = $stmt->fetchAll(Zend_Db::FETCH_COLUMN);
         
         return $accountIds;
@@ -872,8 +903,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
      */
     public function getOtherUsersContainer($_accountId, $_application, $_grant, $_ignoreACL = FALSE)
     {
-        $containerData = $this->_getOtherUsersContainerData($_accountId, $_application, $_grant, $_ignoreACL);
-        $result = new Tinebase_Record_RecordSet('Tinebase_Model_Container', $containerData, TRUE);
+        $result = $this->_getOtherUsersContainerData($_accountId, $_application, $_grant, $_ignoreACL);
         
         return $result;
     }
@@ -885,7 +915,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
      * @param   string|Tinebase_Model_Application   $_application
      * @param   array|string                        $_grant
      * @param   bool                                $_ignoreACL
-     * @return  array of array of containerData
+     * @return  Tinebase_Record_RecordSet set of Tinebase_Model_Container
      */
     protected function _getOtherUsersContainerData($_accountId, $_application, $_grant, $_ignoreACL = FALSE)
     {
@@ -893,6 +923,19 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         $application = Tinebase_Application::getInstance()->getApplicationByName($_application);
         $grant       = $_ignoreACL ? '*' : $_grant;
         
+        $classCacheId = convertCacheId(
+            $accountId .
+            $application->getId() .
+            implode('', (array)$grant) .
+            (int)$_ignoreACL
+        );
+        
+        try {
+            return $this->loadFromClassCache(__FUNCTION__, $classCacheId);
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            // continue...
+        }
+        
         $select = $this->_db->select()
             ->from(array('owner' => SQL_TABLE_PREFIX . 'container_acl'), array('account_id'))
             ->join(array(
@@ -929,10 +972,13 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         
         Tinebase_Backend_Sql_Abstract::traitGroup($select);
         
-        $stmt = $this->_db->query($select);
-        $containersData = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
+        
+        $containers = new Tinebase_Record_RecordSet('Tinebase_Model_Container', $stmt->fetchAll(Zend_Db::FETCH_ASSOC), TRUE);
         
-        return $containersData;
+        $this->saveInClassCache(__FUNCTION__, $classCacheId, $containers);
+        
+        return $containers;
     }
     
     /**
@@ -1066,23 +1112,6 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
     }
     
     /**
-     * reset class cache
-     * 
-     * @param string $key
-     * @return Tinebase_Container
-     */
-    public function resetClassCache($key = null)
-    {
-        foreach ($this->_classCache as $cacheKey => $cacheValue) {
-            if ($key === null || $key === $cacheKey) {
-                $this->_classCache[$cacheKey] = array();
-            }
-        }
-        
-        return $this;
-    }
-    
-    /**
      * set container color, if the user has the required right
      *
      * @param   int|Tinebase_Model_Container $_containerId
@@ -1115,7 +1144,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
      * @param   array|string                        $_grant
      * @return  boolean
      */
-    public function hasGrant($_accountId, $_containerId, $_grant) 
+    public function hasGrant($_accountId, $_containerId, $_grant)
     {
         $accountId = Tinebase_Model_User::convertUserIdToInt($_accountId);
         
@@ -1130,36 +1159,32 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__
             . ' account: ' . $accountId . ' / containerId: ' . $containerId . ' / grant:' . implode('/', (array)$_grant));
         
-        // always bring values in the same order for $classCacheId 
-        if (is_array($_grant)) {
-            sort($_grant);
-        }
-        
-        $classCacheId = convertCacheId($accountId . $containerId . implode('', (array)$_grant));
+        $classCacheId = convertCacheId($accountId . $containerId);
         
-        if (isset($this->_classCache[__FUNCTION__][$classCacheId]) || array_key_exists($classCacheId, $this->_classCache[__FUNCTION__])) {
-            return $this->_classCache[__FUNCTION__][$classCacheId];
+        try {
+            $allGrants = $this->loadFromClassCache(__FUNCTION__, $classCacheId);
+        } catch (Tinebase_Exception_NotFound $tenf) {
+            // NOTE: some tests ask for already deleted container ;-)
+            $select = $this->_getSelect(array(), true)
+                ->distinct()
+                ->where("{$this->_db->quoteIdentifier('container.id')} = ?", $containerId)
+                ->join(array(
+                    /* table  */ 'container_acl' => SQL_TABLE_PREFIX . 'container_acl'), 
+                    /* on     */ "{$this->_db->quoteIdentifier('container_acl.container_id')} = {$this->_db->quoteIdentifier('container.id')}",
+                    /* select */ array('container_acl.account_grant')
+                );
+                
+            $this->addGrantsSql($select, $accountId, '*');
+            
+            $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
+            
+            $allGrants = $stmt->fetchAll(Zend_Db::FETCH_COLUMN);
+            $this->saveInClassCache(__FUNCTION__, $classCacheId, $allGrants);
         }
         
-        // NOTE: some tests ask for already deleted container ;-)
-        $select = $this->_getSelect(self::IDCOL, true)
-            ->where("{$this->_db->quoteIdentifier('container.id')} = ?", $containerId)
-            ->join(array(
-                /* table  */ 'container_acl' => SQL_TABLE_PREFIX . 'container_acl'), 
-                /* on     */ "{$this->_db->quoteIdentifier('container_acl.container_id')} = {$this->_db->quoteIdentifier('container.id')}",
-                /* select */ array()
-            );
-        
-        $this->addGrantsSql($select, $accountId, $_grant);
+        $matchingGrants = array_intersect((array)$_grant, $allGrants);
         
-        $stmt = $this->_db->query($select);
-        
-        $grants = $stmt->fetchAll(Zend_Db::FETCH_COLUMN);
-        $result = ! empty($grants);
-        
-        $this->_classCache[__FUNCTION__][$classCacheId] = $result;
-        
-        return $result;
+        return !!count($matchingGrants);
     }
     
     /**
@@ -1182,10 +1207,10 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         
         Tinebase_Backend_Sql_Abstract::traitGroup($select);
         
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
 
         $grantsData = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
-
+        
         foreach($grantsData as $grantData) {
             $givenGrants = explode(',', $grantData['account_grants']);
             foreach($givenGrants as $grant) {
@@ -1247,12 +1272,13 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
             
             Tinebase_Backend_Sql_Abstract::traitGroup($select);
             
-            $stmt = $this->_db->query($select);
+            $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
             $rows = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
             $grants = $this->_getGrantsFromArray($rows, $accountId, $_grantModel);
             
             $cache->save($grants, $cacheKey, array('container'), self::ACL_CACHE_TIMEOUT);
         }
+        
         return $grants;
     }
     
@@ -1311,7 +1337,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         }
         
         if (empty($containerIds)) {
-            return;
+            return array();
         }
         
         $accountId = $_accountId instanceof Tinebase_Record_Abstract
@@ -1331,15 +1357,10 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         
         Tinebase_Backend_Sql_Abstract::traitGroup($select);
         
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $rows = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
         
-        if (empty($rows)) {
-            return;
-        }
-        
         $containers = array();
-        
         // add results to container ids and get grants array
         foreach ($rows as $row) {
             // NOTE id is non-ambiguous
@@ -1663,7 +1684,7 @@ class Tinebase_Container extends Tinebase_Backend_Sql_Abstract
         
         $select = $this->_getSelect(array('id', 'content_seq'), TRUE);
         $select->where($this->_db->quoteInto($this->_db->quoteIdentifier('id') . ' IN (?)', (array) $containerIds));
-        $stmt = $this->_db->query($select);
+        $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
         $result = $stmt->fetchAll();
         foreach ($result as $key => $value) {
             $result[$value['id']] = $value['content_seq'];