Fixed bug #10439: Data array used in ws-grid should be cached
authormbresch <mbresch@743128fe-103e-dd11-99c4-001b210b3e58>
Tue, 18 Jan 2011 13:15:31 +0000 (13:15 +0000)
committermbresch <mbresch@743128fe-103e-dd11-99c4-001b210b3e58>
Tue, 18 Jan 2011 13:15:31 +0000 (13:15 +0000)
git-svn-id: https://svn.typo3.org/TYPO3v4/CoreProjects/workspaces/workspaces/trunk@3861 743128fe-103e-dd11-99c4-001b210b3e58

typo3/sysext/workspaces/ChangeLog
typo3/sysext/workspaces/Classes/ExtDirect/Server.php
typo3/sysext/workspaces/Classes/Service/GridData.php
typo3/sysext/workspaces/Classes/Service/Tcemain.php
typo3/sysext/workspaces/ext_localconf.php
typo3/sysext/workspaces/ext_tables.sql

index 6326b61..ec08e0a 100644 (file)
@@ -1,3 +1,7 @@
+2011-01-18  Marco Bresch <typo3@starfinanz.de>
+
+       * Fixed bug #10439: Data array used in ws-grid should be cached
+
 2011-01-18  Tolleiv Nietsch <typo3@tolleiv.de>
 
        * Fixed bug #12347: Incorrect registration of status report
index 30b3079..3afe36a 100644 (file)
@@ -45,7 +45,7 @@ class tx_Workspaces_ExtDirect_Server extends tx_Workspaces_ExtDirect_AbstractHan
                $versions = $wslibObj->selectVersionsInWorkspace($this->getCurrentWorkspace(), 0, -99, $pageId, $parameter->depth);
 
                $workspacesService = t3lib_div::makeInstance('tx_Workspaces_Service_GridData');
-               $data = $workspacesService->generateGridListFromVersions($versions, $parameter);
+               $data = $workspacesService->generateGridListFromVersions($versions, $parameter, $this->getCurrentWorkspace());
                return $data;
        }
 
index b3b7643..6415226 100644 (file)
  * @subpackage Service
  */
 class tx_Workspaces_Service_GridData {
+       protected $currentWorkspace = NULL;
        protected $dataArray = array();
        protected $sort = '';
        protected $sortDir = '';
+       protected $workspacesCache = NULL;
 
        /**
         * Generates grid list array from given versions.
@@ -41,8 +43,9 @@ class tx_Workspaces_Service_GridData {
         * @param array $versions All records uids etc. First key is table name, second key incremental integer. Records are associative arrays with uid, t3ver_oid and t3ver_swapmode fields. The pid of the online record is found as "livepid" the pid of the offline record is found in "wspid"
         * @param object $parameter
         * @return array
+        * @throws InvalidArgumentException
         */
-       public function generateGridListFromVersions($versions, $parameter) {
+       public function generateGridListFromVersions($versions, $parameter, $currentWorkspace) {
 
                        // Read the given parameters from grid. If the parameter is not set use default values.
                $filterTxt = isset($parameter->filterTxt) ? $parameter->filterTxt : '';
@@ -50,6 +53,12 @@ class tx_Workspaces_Service_GridData {
                $limit = isset($parameter->limit) ? intval($parameter->limit) : 10;
                $this->sort = isset($parameter->sort) ? $parameter->sort : 't3ver_oid';
                $this->sortDir = isset($parameter->dir) ? $parameter->dir : 'ASC';
+               
+               if (is_int($currentWorkspace)) {
+                       $this->currentWorkspace = $currentWorkspace;
+               } else {
+                       throw new InvalidArgumentException('No such workspace defined');
+               }
 
                $data = array();
                $data['data'] = array();
@@ -77,17 +86,20 @@ class tx_Workspaces_Service_GridData {
                $workspacesObj = t3lib_div::makeInstance('Tx_Workspaces_Service_Workspaces');
                $availableWorkspaces = $workspacesObj->getAvailableWorkspaces();
 
-               foreach ($versions as $table => $records) {
-                       $versionArray = array('table' => $table);
-
-                       foreach ($records as $record) {
-
-                               $origRecord = t3lib_BEFunc::getRecord($table, $record['t3ver_oid']);
-                               $versionRecord = t3lib_BEFunc::getRecord($table, $record['uid']);
-
-                               // check the given version is from an available workspace
-                               if (array_key_exists($versionRecord['t3ver_wsid'], $availableWorkspaces)) {
-                                       
+               $this->initializeWorkspacesCachingFramework();
+
+               // check for dataArray in cache
+               if ($this->getDataArrayFromCache($versions, $filterTxt) == FALSE) {
+                       $stagesObj = t3lib_div::makeInstance('Tx_Workspaces_Service_Stages');
+       
+                       foreach ($versions as $table => $records) {
+                               $versionArray = array('table' => $table);
+       
+                               foreach ($records as $record) {
+       
+                                       $origRecord = t3lib_BEFunc::getRecord($table, $record['t3ver_oid']);
+                                       $versionRecord = t3lib_BEFunc::getRecord($table, $record['uid']);
+       
                                        if (isset($GLOBALS['TCA'][$table]['columns']['hidden'])) {
                                                $recordState = $this->workspaceState($versionRecord['t3ver_state'], $origRecord['hidden'], $versionRecord['hidden']);
                                        } else {
@@ -131,6 +143,9 @@ class tx_Workspaces_Service_GridData {
                                        }
                                }
                        }
+                       $this->sortDataArray();
+                       
+                       $this->setDataArrayIntoCache($versions, $filterTxt);
                }
                $this->sortDataArray();
        }
@@ -153,6 +168,89 @@ class tx_Workspaces_Service_GridData {
                return $dataArrayPart;
        }
 
+
+       /**
+        * Initialize the workspace cache
+        * 
+        * @return void
+        */
+       protected function initializeWorkspacesCachingFramework() {
+               if (TYPO3_UseCachingFramework) {
+                       try {
+                               $GLOBALS['typo3CacheFactory']->create(
+                                       'workspaces_cache',
+                                       't3lib_cache_frontend_StringFrontend',
+                                       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['backend'],
+                                       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['options']);
+                       } catch (t3lib_cache_exception_DuplicateIdentifier $e) {
+                               // do nothing, a workspace cache already exists
+                       }
+       
+                       $this->workspacesCache = $GLOBALS['typo3CacheManager']->getCache('workspaces_cache');
+               }
+       }
+
+
+       /**
+        * Put the generated dataArray into the workspace cache.
+        * 
+        * @param array $versions All records uids etc. First key is table name, second key incremental integer. Records are associative arrays with uid, t3ver_oid and t3ver_swapmode fields. The pid of the online record is found as "livepid" the pid of the offline record is found in "wspid"
+        * @param string $filterTxt The given filter text from the grid.
+        */
+       protected function setDataArrayIntoCache (array $versions, $filterTxt) {
+               if (TYPO3_UseCachingFramework) {
+                       $hash = $this->calculateHash($versions, $filterTxt);
+                       $content = serialize($this->dataArray);
+                       
+                       $this->workspacesCache->set($hash, $content, array($this->currentWorkspace));
+               }
+       }
+       
+       
+       /**
+        * Checks if a cache entry is given for given versions and filter text and tries to load the data array from cache.
+        * 
+        * @param array $versions All records uids etc. First key is table name, second key incremental integer. Records are associative arrays with uid, t3ver_oid and t3ver_swapmode fields. The pid of the online record is found as "livepid" the pid of the offline record is found in "wspid"
+        * @param string $filterTxt The given filter text from the grid.
+        */
+       protected function getDataArrayFromCache (array $versions, $filterTxt) {
+               $cacheEntry = FALSE;
+               
+               if (TYPO3_UseCachingFramework) {
+                       $hash = $this->calculateHash($versions, $filterTxt);
+                       
+                       $content = $this->workspacesCache->get($hash);
+                       
+                       if ($content != FALSE) {
+                               $this->dataArray = unserialize($content);
+                               $cacheEntry = TRUE;
+                       }
+               }
+               
+               return $cacheEntry;
+       }
+       
+       /**
+        * Calculate the hash value of the used workspace, the user id, the versions array, the filter text, the sorting attribute, the workspace selected in grid and the sorting direction.
+        * 
+        * @param array $versions All records uids etc. First key is table name, second key incremental integer. Records are associative arrays with uid, t3ver_oid and t3ver_swapmode fields. The pid of the online record is found as "livepid" the pid of the offline record is found in "wspid"
+        * @param string $filterTxt The given filter text from the grid.
+        */
+       protected function calculateHash (array $versions, $filterTxt) {
+               $hashArray = array(
+                       $GLOBALS['BE_USER']->workspace,
+                       $GLOBALS['BE_USER']->user['uid'],
+                       $versions,
+                       $filterTxt,
+                       $this->sort,
+                       $this->sortDir,
+                       $this->currentWorkspace);
+               $hash = md5(serialize($hashArray));
+               
+               return $hash;
+       }
+
+
        /**
         * Performs sorting on the data array accordant to the
         * selected column in the grid view to be used for sorting.
index 3c75e44..b21376c 100644 (file)
@@ -56,6 +56,19 @@ class tx_Workspaces_Service_Tcemain {
        }
 
        /**
+        * hook that is called AFTER all commands of the commandmap was 
+        * executed
+        *
+        * @param t3lib_TCEmain $tcemainObj reference to the main tcemain object
+        * @return      void
+        */
+       public function processCmdmap_afterFinish(t3lib_TCEmain $tcemainObj) {
+               if (TYPO3_UseCachingFramework) {
+                       $this->flushWorkspaceCacheEntriesByWorkspaceId($tcemainObj->BE_USER->workspace);
+               }
+       }
+
+       /**
         * In case a sys_workspace_stage record is deleted we do a hard reset
         * for all existing records in that stage to avoid that any of these end up
         * as orphan records.
@@ -129,6 +142,30 @@ class tx_Workspaces_Service_Tcemain {
                return $tceMain;
        }
 
+       /**
+        * Flushes the workspace cache for current workspace and for the virtual "all workspaces" too.
+        * 
+        * @param integer $workspaceId The workspace to be flushed in cache
+        * @return void
+        */
+       protected function flushWorkspaceCacheEntriesByWorkspaceId($workspaceId) {
+               if (TYPO3_UseCachingFramework) {
+                       try {
+                               $GLOBALS['typo3CacheFactory']->create(
+                                       'workspaces_cache',
+                                       't3lib_cache_frontend_StringFrontend',
+                                       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['backend'],
+                                       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['options']);
+                       } catch (t3lib_cache_exception_DuplicateIdentifier $e) {
+                               // do nothing, a workspace cache already exists
+                       }
+       
+                       $workspacesCache = $GLOBALS['typo3CacheManager']->getCache('workspaces_cache');
+       
+                       $workspacesCache->flushByTag($workspaceId);
+                       $workspacesCache->flushByTag(tx_Workspaces_Service_Workspaces::SELECT_ALL_WORKSPACES);
+               }
+       }
 }
 
 
index 805d63d..88b1207 100644 (file)
@@ -20,4 +20,15 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tcemain.php']['proc
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_befunc.php']['viewOnClickClass']['workspaces'] = 'EXT:workspaces/Classes/Service/Tcemain.php:tx_Workspaces_Service_Befunc';
 $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_fe.php']['hook_eofe']['workspaces'] = 'EXT:workspaces/Classes/Service/Fehooks.php:tx_Workspaces_Service_Fehooks->hook_eofe';
 
+if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['useCachingFramework']) {
+               // Initialize the caching framework. The caching framework is asking it self if it is initialized already before initializing.
+       t3lib_cache::initializeCachingFramework();
+       
+       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['backend'] = 't3lib_cache_backend_DbBackend';
+       $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['options'] = array(
+               'cacheTable' => 'sys_workspace_cache',
+               'tagsTable' => 'sys_workspace_cache_tags'
+       );
+}
+
 ?>
\ No newline at end of file
index 60be2f6..b68b0db 100644 (file)
@@ -48,3 +48,30 @@ CREATE TABLE sys_workspace_stage (
        PRIMARY KEY (uid),
        KEY parent (pid)
 );
+
+
+#
+# Table structure for table 'sys_workspace_cache'
+#
+CREATE TABLE sys_workspace_cache (
+    id int(11) unsigned NOT NULL auto_increment,
+    identifier varchar(32) DEFAULT '' NOT NULL,
+    content mediumblob NOT NULL,
+    crdate int(11) DEFAULT '0' NOT NULL,
+    lifetime int(11) DEFAULT '0' NOT NULL,    
+      PRIMARY KEY (id),
+      KEY cache_id (identifier)
+) ENGINE=InnoDB;
+
+
+#
+# Table structure for table 'sys_workspace_cache_tags'
+#
+CREATE TABLE sys_workspace_cache_tags (
+  id int(11) unsigned NOT NULL auto_increment,
+  identifier varchar(128) DEFAULT '' NOT NULL,
+  tag varchar(128) DEFAULT '' NOT NULL,
+  PRIMARY KEY (id),
+  KEY cache_id (identifier),
+  KEY cache_tag (tag)
+) ENGINE=InnoDB;