|
TYPO3 API
SVNRelease
|
00001 <?php 00002 /*************************************************************** 00003 * Copyright notice 00004 * 00005 * (c) 2010-2011 Workspaces Team (http://forge.typo3.org/projects/show/typo3v4-workspaces) 00006 * All rights reserved 00007 * 00008 * This script is part of the TYPO3 project. The TYPO3 project is 00009 * free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * The GNU General Public License can be found at 00015 * http://www.gnu.org/copyleft/gpl.html. 00016 * A copy is found in the textfile GPL.txt and important notices to the license 00017 * from the author is found in LICENSE.txt distributed with these scripts. 00018 * 00019 * 00020 * This script is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 * GNU General Public License for more details. 00024 * 00025 * This copyright notice MUST APPEAR in all copies of the script! 00026 ***************************************************************/ 00027 00028 /** 00029 * @author Workspaces Team (http://forge.typo3.org/projects/show/typo3v4-workspaces) 00030 * @package Workspaces 00031 * @subpackage Service 00032 */ 00033 class tx_Workspaces_Service_GridData { 00034 protected $currentWorkspace = NULL; 00035 protected $dataArray = array(); 00036 protected $sort = ''; 00037 protected $sortDir = ''; 00038 protected $workspacesCache = NULL; 00039 00040 /** 00041 * Generates grid list array from given versions. 00042 * 00043 * @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" 00044 * @param object $parameter 00045 * @return array 00046 * @throws InvalidArgumentException 00047 */ 00048 public function generateGridListFromVersions($versions, $parameter, $currentWorkspace) { 00049 00050 // Read the given parameters from grid. If the parameter is not set use default values. 00051 $filterTxt = isset($parameter->filterTxt) ? $parameter->filterTxt : ''; 00052 $start = isset($parameter->start) ? intval($parameter->start) : 0; 00053 $limit = isset($parameter->limit) ? intval($parameter->limit) : 10; 00054 $this->sort = isset($parameter->sort) ? $parameter->sort : 't3ver_oid'; 00055 $this->sortDir = isset($parameter->dir) ? $parameter->dir : 'ASC'; 00056 00057 if (is_int($currentWorkspace)) { 00058 $this->currentWorkspace = $currentWorkspace; 00059 } else { 00060 throw new InvalidArgumentException('No such workspace defined'); 00061 } 00062 00063 $data = array(); 00064 $data['data'] = array(); 00065 00066 $this->generateDataArray($versions, $filterTxt); 00067 00068 $data['total'] = count($this->dataArray); 00069 $data['data'] = $this->getDataArray($start, $limit); 00070 00071 return $data; 00072 } 00073 00074 /** 00075 * Generates grid list array from given versions. 00076 * 00077 * @param array $versions 00078 * @param string $filterTxt 00079 * @return void 00080 */ 00081 protected function generateDataArray(array $versions, $filterTxt) { 00082 /** @var $stagesObj Tx_Workspaces_Service_Stages */ 00083 $stagesObj = t3lib_div::makeInstance('Tx_Workspaces_Service_Stages'); 00084 00085 /** @var $workspacesObj Tx_Workspaces_Service_Workspaces */ 00086 $workspacesObj = t3lib_div::makeInstance('Tx_Workspaces_Service_Workspaces'); 00087 $availableWorkspaces = $workspacesObj->getAvailableWorkspaces(); 00088 00089 $workspaceAccess = $GLOBALS['BE_USER']->checkWorkspace($GLOBALS['BE_USER']->workspace); 00090 $swapStage = ($workspaceAccess['publish_access'] & 1) ? Tx_Workspaces_Service_Stages::STAGE_PUBLISH_ID : 0; 00091 $swapAccess = $GLOBALS['BE_USER']->workspacePublishAccess($GLOBALS['BE_USER']->workspace) && 00092 $GLOBALS['BE_USER']->workspaceSwapAccess(); 00093 00094 $this->initializeWorkspacesCachingFramework(); 00095 00096 // check for dataArray in cache 00097 if ($this->getDataArrayFromCache($versions, $filterTxt) == FALSE) { 00098 $stagesObj = t3lib_div::makeInstance('Tx_Workspaces_Service_Stages'); 00099 00100 foreach ($versions as $table => $records) { 00101 $versionArray = array('table' => $table); 00102 00103 foreach ($records as $record) { 00104 00105 $origRecord = t3lib_BEFunc::getRecord($table, $record['t3ver_oid']); 00106 $versionRecord = t3lib_BEFunc::getRecord($table, $record['uid']); 00107 00108 if (isset($GLOBALS['TCA'][$table]['columns']['hidden'])) { 00109 $recordState = $this->workspaceState($versionRecord['t3ver_state'], $origRecord['hidden'], $versionRecord['hidden']); 00110 } else { 00111 $recordState = $this->workspaceState($versionRecord['t3ver_state']); 00112 } 00113 $isDeletedPage = ($table == 'pages' && $recordState == 'deleted'); 00114 $viewUrl = tx_Workspaces_Service_Workspaces::viewSingleRecord($table, $record['t3ver_oid'], $origRecord); 00115 00116 $pctChange = $this->calculateChangePercentage($table, $origRecord, $versionRecord); 00117 $versionArray['uid'] = $record['uid']; 00118 $versionArray['workspace'] = $versionRecord['t3ver_id']; 00119 $versionArray['label_Workspace'] = htmlspecialchars($versionRecord[$GLOBALS['TCA'][$table]['ctrl']['label']]); 00120 $versionArray['label_Live'] = htmlspecialchars($origRecord[$GLOBALS['TCA'][$table]['ctrl']['label']]); 00121 $versionArray['label_Stage'] = htmlspecialchars($stagesObj->getStageTitle($versionRecord['t3ver_stage'])); 00122 $versionArray['change'] = $pctChange; 00123 $versionArray['path_Live'] = htmlspecialchars(t3lib_BEfunc::getRecordPath($record['livepid'], '', 999)); 00124 $versionArray['path_Workspace'] = htmlspecialchars(t3lib_BEfunc::getRecordPath($record['wspid'], '', 999)); 00125 $versionArray['workspace_Title'] = htmlspecialchars(tx_Workspaces_Service_Workspaces::getWorkspaceTitle($versionRecord['t3ver_wsid'])); 00126 00127 $versionArray['workspace_Tstamp'] = $versionRecord['tstamp']; 00128 $versionArray['workspace_Formated_Tstamp'] = t3lib_BEfunc::datetime($versionRecord['tstamp']); 00129 $versionArray['t3ver_oid'] = $record['t3ver_oid']; 00130 $versionArray['livepid'] = $record['livepid']; 00131 $versionArray['stage'] = $versionRecord['t3ver_stage']; 00132 $versionArray['icon_Live'] = t3lib_iconWorks::mapRecordTypeToSpriteIconClass($table, $origRecord); 00133 $versionArray['icon_Workspace'] = t3lib_iconWorks::mapRecordTypeToSpriteIconClass($table, $versionRecord); 00134 00135 $versionArray['allowedAction_nextStage'] = $stagesObj->isNextStageAllowedForUser($versionRecord['t3ver_stage']); 00136 $versionArray['allowedAction_prevStage'] = $stagesObj->isPrevStageAllowedForUser($versionRecord['t3ver_stage']); 00137 00138 if ($swapAccess && $swapStage != 0 && $versionRecord['t3ver_stage'] == $swapStage) { 00139 $versionArray['allowedAction_swap'] = $stagesObj->isNextStageAllowedForUser($swapStage); 00140 } else if ($swapAccess && $swapStage == 0) { 00141 $versionArray['allowedAction_swap'] = TRUE; 00142 } else { 00143 $versionArray['allowedAction_swap'] = FALSE; 00144 } 00145 $versionArray['allowedAction_delete'] = TRUE; 00146 // preview and editing of a deleted page won't work ;) 00147 $versionArray['allowedAction_view'] = !$isDeletedPage && $viewUrl; 00148 $versionArray['allowedAction_edit'] = !$isDeletedPage; 00149 $versionArray['allowedAction_editVersionedPage'] = !$isDeletedPage; 00150 00151 $versionArray['state_Workspace'] = $recordState; 00152 00153 if ($filterTxt == '' || $this->isFilterTextInVisibleColumns($filterTxt, $versionArray)) { 00154 $this->dataArray[] = $versionArray; 00155 } 00156 } 00157 } 00158 $this->sortDataArray(); 00159 00160 $this->setDataArrayIntoCache($versions, $filterTxt); 00161 } 00162 $this->sortDataArray(); 00163 } 00164 00165 /** 00166 * Gets the data array by considering the page to be shown in the grid view. 00167 * 00168 * @param integer $start 00169 * @param integer $limit 00170 * @return array 00171 */ 00172 protected function getDataArray($start, $limit) { 00173 $dataArrayPart = array(); 00174 $end = $start + $limit < count($this->dataArray) ? $start + $limit : count($this->dataArray); 00175 00176 for ($i = $start; $i < $end; $i++) { 00177 $dataArrayPart[] = $this->dataArray[$i]; 00178 } 00179 00180 return $dataArrayPart; 00181 } 00182 00183 00184 /** 00185 * Initialize the workspace cache 00186 * 00187 * @return void 00188 */ 00189 protected function initializeWorkspacesCachingFramework() { 00190 if (TYPO3_UseCachingFramework === TRUE) { 00191 try { 00192 $GLOBALS['typo3CacheFactory']->create( 00193 'workspaces_cache', 00194 't3lib_cache_frontend_StringFrontend', 00195 $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['backend'], 00196 $GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations']['sys_workspace_cache']['options']); 00197 } catch (t3lib_cache_exception_DuplicateIdentifier $e) { 00198 // do nothing, a workspace cache already exists 00199 } 00200 00201 $this->workspacesCache = $GLOBALS['typo3CacheManager']->getCache('workspaces_cache'); 00202 } 00203 } 00204 00205 00206 /** 00207 * Put the generated dataArray into the workspace cache. 00208 * 00209 * @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" 00210 * @param string $filterTxt The given filter text from the grid. 00211 */ 00212 protected function setDataArrayIntoCache (array $versions, $filterTxt) { 00213 if (TYPO3_UseCachingFramework === TRUE) { 00214 $hash = $this->calculateHash($versions, $filterTxt); 00215 $content = serialize($this->dataArray); 00216 00217 $this->workspacesCache->set($hash, $content, array($this->currentWorkspace)); 00218 } 00219 } 00220 00221 00222 /** 00223 * Checks if a cache entry is given for given versions and filter text and tries to load the data array from cache. 00224 * 00225 * @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" 00226 * @param string $filterTxt The given filter text from the grid. 00227 */ 00228 protected function getDataArrayFromCache (array $versions, $filterTxt) { 00229 $cacheEntry = FALSE; 00230 00231 if (TYPO3_UseCachingFramework === TRUE) { 00232 $hash = $this->calculateHash($versions, $filterTxt); 00233 00234 $content = $this->workspacesCache->get($hash); 00235 00236 if ($content != FALSE) { 00237 $this->dataArray = unserialize($content); 00238 $cacheEntry = TRUE; 00239 } 00240 } 00241 00242 return $cacheEntry; 00243 } 00244 00245 /** 00246 * 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. 00247 * 00248 * @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" 00249 * @param string $filterTxt The given filter text from the grid. 00250 */ 00251 protected function calculateHash (array $versions, $filterTxt) { 00252 $hashArray = array( 00253 $GLOBALS['BE_USER']->workspace, 00254 $GLOBALS['BE_USER']->user['uid'], 00255 $versions, 00256 $filterTxt, 00257 $this->sort, 00258 $this->sortDir, 00259 $this->currentWorkspace); 00260 $hash = md5(serialize($hashArray)); 00261 00262 return $hash; 00263 } 00264 00265 00266 /** 00267 * Performs sorting on the data array accordant to the 00268 * selected column in the grid view to be used for sorting. 00269 * 00270 * @return void 00271 */ 00272 protected function sortDataArray() { 00273 switch ($this->sort) { 00274 case 'uid'; 00275 case 'change'; 00276 case 'workspace_Tstamp'; 00277 case 't3ver_oid'; 00278 case 'liveid'; 00279 case 'livepid': 00280 usort($this->dataArray, array($this, 'intSort')); 00281 break; 00282 case 'label_Workspace'; 00283 case 'label_Live'; 00284 case 'label_Stage'; 00285 case 'workspace_Title'; 00286 case 'path_Live': 00287 // case 'path_Workspace': This is the first sorting attribute 00288 usort($this->dataArray, array($this, 'stringSort')); 00289 break; 00290 } 00291 } 00292 00293 /** 00294 * Implements individual sorting for columns based on integer comparison. 00295 * 00296 * @param array $a 00297 * @param array $b 00298 * @return integer 00299 */ 00300 protected function intSort(array $a, array $b) { 00301 // Als erstes nach dem Pfad sortieren 00302 $path_cmp = strcasecmp($a['path_Workspace'], $b['path_Workspace']); 00303 00304 if ($path_cmp < 0) { 00305 return $path_cmp; 00306 } elseif ($path_cmp == 0) { 00307 if ($a[$this->sort] == $b[$this->sort]) { 00308 return 0; 00309 } 00310 if ($this->sortDir == 'ASC') { 00311 return ($a[$this->sort] < $b[$this->sort]) ? -1 : 1; 00312 } elseif ($this->sortDir == 'DESC') { 00313 return ($a[$this->sort] > $b[$this->sort]) ? -1 : 1; 00314 } 00315 } elseif ($path_cmp > 0) { 00316 return $path_cmp; 00317 } 00318 return 0; //ToDo: Throw Exception 00319 } 00320 00321 /** 00322 * Implements individual sorting for columns based on string comparison. 00323 * 00324 * @param $a 00325 * @param $b 00326 * @return int 00327 */ 00328 protected function stringSort($a, $b) { 00329 $path_cmp = strcasecmp($a['path_Workspace'], $b['path_Workspace']); 00330 00331 if ($path_cmp < 0) { 00332 return $path_cmp; 00333 } elseif ($path_cmp == 0) { 00334 if ($a[$this->sort] == $b[$this->sort]) { 00335 return 0; 00336 } 00337 if ($this->sortDir == 'ASC') { 00338 return (strcasecmp($a[$this->sort], $b[$this->sort])); 00339 } elseif ($this->sortDir == 'DESC') { 00340 return (strcasecmp($a[$this->sort], $b[$this->sort]) * (-1)); 00341 } 00342 } elseif ($path_cmp > 0) { 00343 return $path_cmp; 00344 } 00345 return 0; //ToDo: Throw Exception 00346 } 00347 00348 /** 00349 * Determines whether the text used to filter the results is part of 00350 * a column that is visible in the grid view. 00351 * 00352 * @param string $filterText 00353 * @param array $versionArray 00354 * @return boolean 00355 */ 00356 protected function isFilterTextInVisibleColumns($filterText, array $versionArray) { 00357 if (is_array($GLOBALS['BE_USER']->uc['moduleData']['Workspaces']['columns'])) { 00358 foreach ($GLOBALS['BE_USER']->uc['moduleData']['Workspaces']['columns'] as $column => $value) { 00359 if (isset($value['hidden']) && isset($column) && isset($versionArray[$column])) { 00360 if ($value['hidden'] == 0) { 00361 switch ($column) { 00362 case 'workspace_Tstamp': 00363 if (stripos($versionArray['workspace_Formated_Tstamp'], $filterText) !== FALSE) { 00364 return TRUE; 00365 } 00366 break; 00367 case 'change': 00368 if (stripos(strval($versionArray[$column]), str_replace('%', '', $filterText)) !== FALSE) { 00369 return TRUE; 00370 } 00371 break; 00372 default: 00373 if (stripos(strval($versionArray[$column]), $filterText) !== FALSE) { 00374 return TRUE; 00375 } 00376 } 00377 } 00378 } 00379 } 00380 } 00381 return FALSE; 00382 } 00383 00384 /** 00385 * Calculates the percentage of changes between two records. 00386 * 00387 * @param string $table 00388 * @param array $diffRecordOne 00389 * @param array $diffRecordTwo 00390 * @return integer 00391 */ 00392 public function calculateChangePercentage($table, array $diffRecordOne, array $diffRecordTwo) { 00393 global $TCA; 00394 00395 // Initialize: 00396 $changePercentage = 0; 00397 $changePercentageArray = array(); 00398 00399 // Check that records are arrays: 00400 if (is_array($diffRecordOne) && is_array($diffRecordTwo)) { 00401 00402 // Load full table description 00403 t3lib_div::loadTCA($table); 00404 00405 $similarityPercentage = 0; 00406 00407 // Traversing the first record and process all fields which are editable: 00408 foreach ($diffRecordOne as $fieldName => $fieldValue) { 00409 if ($TCA[$table]['columns'][$fieldName] && $TCA[$table]['columns'][$fieldName]['config']['type'] != 'passthrough' && !t3lib_div::inList('t3ver_label', $fieldName)) { 00410 00411 if (strcmp(trim($diffRecordOne[$fieldName]), trim($diffRecordTwo[$fieldName])) 00412 && $TCA[$table]['columns'][$fieldName]['config']['type'] == 'group' 00413 && $TCA[$table]['columns'][$fieldName]['config']['internal_type'] == 'file' 00414 ) { 00415 00416 // Initialize: 00417 $uploadFolder = $TCA[$table]['columns'][$fieldName]['config']['uploadfolder']; 00418 $files1 = array_flip(t3lib_div::trimExplode(',', $diffRecordOne[$fieldName], 1)); 00419 $files2 = array_flip(t3lib_div::trimExplode(',', $diffRecordTwo[$fieldName], 1)); 00420 00421 // Traverse filenames and read their md5 sum: 00422 foreach ($files1 as $filename => $tmp) { 00423 $files1[$filename] = @is_file(PATH_site . $uploadFolder . '/' . $filename) ? md5(t3lib_div::getUrl(PATH_site . $uploadFolder . '/' . $filename)) : $filename; 00424 } 00425 foreach ($files2 as $filename => $tmp) { 00426 $files2[$filename] = @is_file(PATH_site . $uploadFolder . '/' . $filename) ? md5(t3lib_div::getUrl(PATH_site . $uploadFolder . '/' . $filename)) : $filename; 00427 } 00428 00429 // Implode MD5 sums and set flag: 00430 $diffRecordOne[$fieldName] = implode(' ', $files1); 00431 $diffRecordTwo[$fieldName] = implode(' ', $files2); 00432 } 00433 00434 // If there is a change of value: 00435 if (strcmp(trim($diffRecordOne[$fieldName]), trim($diffRecordTwo[$fieldName]))) { 00436 // Get the best visual presentation of the value to calculate differences: 00437 $val1 = t3lib_BEfunc::getProcessedValue($table, $fieldName, $diffRecordOne[$fieldName], 0, 1); 00438 $val2 = t3lib_BEfunc::getProcessedValue($table, $fieldName, $diffRecordTwo[$fieldName], 0, 1); 00439 00440 similar_text($val1, $val2, $similarityPercentage); 00441 $changePercentageArray[] = $similarityPercentage > 0 ? abs($similarityPercentage - 100) : 0; 00442 } 00443 } 00444 } 00445 00446 // Calculate final change percentage: 00447 if (is_array($changePercentageArray)) { 00448 $sumPctChange = 0; 00449 foreach ($changePercentageArray as $singlePctChange) { 00450 $sumPctChange += $singlePctChange; 00451 } 00452 count($changePercentageArray) > 0 ? $changePercentage = round($sumPctChange / count($changePercentageArray)) : $changePercentage = 0; 00453 } 00454 00455 } 00456 return $changePercentage; 00457 } 00458 00459 /** 00460 * Gets the state of a given state value. 00461 * 00462 * @param integer stateId of offline record 00463 * @param boolean hidden flag of online record 00464 * @param boolean hidden flag of offline record 00465 * @return string 00466 */ 00467 protected function workspaceState($stateId, $hiddenOnline = FALSE, $hiddenOffline = FALSE) { 00468 switch ($stateId) { 00469 case -1: 00470 $state = 'new'; 00471 break; 00472 case 1: 00473 case 2: 00474 $state = 'deleted'; 00475 break; 00476 case 4: 00477 $state = 'moved'; 00478 break; 00479 default: 00480 $state = 'modified'; 00481 } 00482 00483 if ($hiddenOnline == 0 && $hiddenOffline == 1) { 00484 $state = 'hidden'; 00485 } elseif ($hiddenOnline == 1 && $hiddenOffline == 0) { 00486 $state = 'unhidden'; 00487 } 00488 00489 return $state; 00490 } 00491 } 00492 00493 00494 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/workspaces/Classes/Service/GridData.php'])) { 00495 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/workspaces/Classes/Service/GridData.php']); 00496 } 00497 ?>
1.8.0