|
eZ Publish
[4.1]
|
00001 <?php 00002 // 00003 // Definition of eZContentCacheManager class 00004 // 00005 // Created on: <23-Sep-2004 12:52:38 jb> 00006 // 00007 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00008 // SOFTWARE NAME: eZ Publish 00009 // SOFTWARE RELEASE: 4.1.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2009 eZ Systems AS 00011 // SOFTWARE LICENSE: GNU General Public License v2.0 00012 // NOTICE: > 00013 // This program is free software; you can redistribute it and/or 00014 // modify it under the terms of version 2.0 of the GNU General 00015 // Public License as published by the Free Software Foundation. 00016 // 00017 // This program is distributed in the hope that it will be useful, 00018 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 // GNU General Public License for more details. 00021 // 00022 // You should have received a copy of version 2.0 of the GNU General 00023 // Public License along with this program; if not, write to the Free 00024 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00025 // MA 02110-1301, USA. 00026 // 00027 // 00028 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ## 00029 // 00030 00031 /*! \file 00032 */ 00033 00034 /*! 00035 \class eZContentCacheManager ezcontentcachemanager.php 00036 \brief Figures out relations between objects, nodes and classes for cache management 00037 00038 This class works together with eZContentCache to manage the cache files 00039 for content viewing. This class takes care of finding out the relationship 00040 and then passes a list of nodes to eZContentCache which does the actual 00041 clearing. 00042 00043 The manager uses special rules in 'viewcache.ini' to figure relationships. 00044 \sa eZContentCache 00045 */ 00046 00047 require_once( 'access.php' ); 00048 00049 class eZContentCacheManager 00050 { 00051 // Clear cache types 00052 const CLEAR_NO_CACHE = 0; 00053 const CLEAR_NODE_CACHE = 1; 00054 const CLEAR_PARENT_CACHE = 2; 00055 const CLEAR_RELATING_CACHE = 4; 00056 const CLEAR_KEYWORD_CACHE = 8; 00057 const CLEAR_SIBLINGS_CACHE = 16; 00058 const CLEAR_ALL_CACHE = 31; 00059 const CLEAR_DEFAULT = 15; // CLEAR_NODE_CACHE and CLEAR_PARENT_CACHE and CLEAR_RELATING_CACHE and CLEAR_KEYWORD_CACHE 00060 00061 /*! 00062 \static 00063 Appends parent nodes ids of \a $object to \a $nodeIDList array. 00064 \param $versionNum The version of the object to use or \c true for current version 00065 \param[out] $nodeIDList Array with node IDs 00066 */ 00067 static function appendParentNodeIDs( $object, $versionNum, &$nodeIDList ) 00068 { 00069 foreach ( $object->parentNodeIDArray() as $parentNodeID ) 00070 { 00071 $nodeIDList[] = $parentNodeID; 00072 } 00073 } 00074 00075 /*! 00076 \static 00077 Appends nodes ids from \a $nodeList list to \a $nodeIDList 00078 \param[out] $nodeIDList Array with node IDs 00079 */ 00080 static function appendNodeIDs( $nodeList, &$nodeIDList ) 00081 { 00082 foreach ( $nodeList as $node ) 00083 { 00084 $nodeIDList[] = $node->attribute( 'node_id' ); 00085 } 00086 } 00087 00088 /*! 00089 \static 00090 Goes through all content nodes in \a $nodeList and extracts the \c 'path_string'. 00091 \return An array with \c 'path_string' information. 00092 */ 00093 static function fetchNodePathString( $nodeList ) 00094 { 00095 $pathList = array(); 00096 foreach ( $nodeList as $node ) 00097 { 00098 $pathList[] = $node->attribute( 'path_string' ); 00099 } 00100 return $pathList; 00101 } 00102 00103 /*! 00104 \static 00105 Find all content objects that relates \a $object and appends 00106 their node IDs to \a $nodeIDList. 00107 \param[out] $nodeIDList Array with node IDs 00108 */ 00109 static function appendRelatingNodeIDs( $object, &$nodeIDList ) 00110 { 00111 $viewCacheIni = eZINI::instance( 'viewcache.ini' ); 00112 if ( $viewCacheIni->hasVariable( 'ViewCacheSettings', 'ClearRelationTypes' ) ) 00113 { 00114 $relTypes = $viewCacheIni->variable( 'ViewCacheSettings', 'ClearRelationTypes' ); 00115 00116 if ( !count( $relTypes ) ) 00117 return; 00118 00119 $relatedObjects = array(); 00120 00121 $relationsMask = 0; 00122 if ( in_array( 'object', $relTypes ) ) 00123 $relationsMask |= eZContentObject::RELATION_COMMON | eZContentObject::RELATION_EMBED; 00124 00125 if ( in_array( 'common', $relTypes ) ) 00126 $relationsMask |= eZContentObject::RELATION_COMMON; 00127 00128 if ( in_array( 'embedded', $relTypes ) ) 00129 $relationsMask |= eZContentObject::RELATION_EMBED; 00130 00131 if ( in_array( 'linked', $relTypes ) ) 00132 $relationsMask |= eZContentObject::RELATION_LINK; 00133 00134 if ( in_array( 'attribute', $relTypes ) ) 00135 $relationsMask |= eZContentObject::RELATION_ATTRIBUTE; 00136 00137 if ( $relationsMask ) 00138 { 00139 $objects = $object->relatedContentObjectList( false, false, false, false, 00140 array( 'AllRelations' => $relationsMask ) ); 00141 $previousVersionObjects = array(); 00142 $previousVersion = $object->previousVersion(); 00143 if ( $previousVersion ) 00144 { 00145 $previousVersionObjects = $object->relatedContentObjectList( $previousVersion, false, false, false, 00146 array( 'AllRelations' => $relationsMask ) ); 00147 } 00148 $relatedObjects = array_merge( $relatedObjects, $objects, $previousVersionObjects ); 00149 } 00150 00151 $relationsMask = 0; 00152 if ( in_array( 'reverse_object', $relTypes ) ) 00153 $relationsMask |= eZContentObject::RELATION_COMMON | eZContentObject::RELATION_EMBED; 00154 00155 if ( in_array( 'reverse_common', $relTypes ) ) 00156 $relationsMask |= eZContentObject::RELATION_COMMON; 00157 00158 if ( in_array( 'reverse_embedded', $relTypes ) ) 00159 $relationsMask |= eZContentObject::RELATION_EMBED; 00160 00161 if ( in_array( 'reverse_linked', $relTypes ) ) 00162 $relationsMask |= eZContentObject::RELATION_LINK; 00163 00164 if ( in_array( 'reverse_attribute', $relTypes ) ) 00165 $relationsMask |= eZContentObject::RELATION_ATTRIBUTE; 00166 00167 if ( $relationsMask ) 00168 { 00169 $objects = $object->reverseRelatedObjectList( false, false, false, 00170 array( 'AllRelations' => $relationsMask ) ); 00171 $previousVersionObjects = array(); 00172 $previousVersion = $object->previousVersion(); 00173 if ( $previousVersion ) 00174 { 00175 $previousVersionObjects = $object->relatedContentObjectList( $previousVersion, false, false, false, 00176 array( 'AllRelations' => $relationsMask ) ); 00177 } 00178 $relatedObjects = array_merge( $relatedObjects, $objects, $previousVersionObjects ); 00179 } 00180 } 00181 else 00182 { 00183 $normalRelated = $object->relatedContentObjectArray(); 00184 $reversedRelated = $object->contentObjectListRelatingThis(); 00185 00186 $relatedObjects = array_merge( $normalRelated, $reversedRelated ); 00187 } 00188 00189 foreach ( $relatedObjects as $relatedObject ) 00190 { 00191 $assignedNodes = $relatedObject->assignedNodes( false ); 00192 foreach ( $assignedNodes as $assignedNode ) 00193 { 00194 $nodeIDList[] = $assignedNode['node_id']; 00195 } 00196 } 00197 $nodeIDList = array_unique( $nodeIDList ); 00198 } 00199 00200 /*! 00201 \static 00202 Appends node ids of objects with the same keyword(s) as \a $object to \a $nodeIDList array. 00203 \param $versionNum The version of the object to use or \c true for current version 00204 \param[out] $nodeIDList Array with node IDs 00205 */ 00206 static function appendKeywordNodeIDs( $object, $versionNum, &$nodeIDList, $limit = null ) 00207 { 00208 if ( $limit === 0 ) 00209 return; 00210 if ( $versionNum === true ) 00211 $versionNum = false; 00212 $keywordArray = array(); 00213 $attributes = $object->contentObjectAttributes( true, $versionNum ); 00214 foreach ( array_keys( $attributes ) as $key ) // Looking for ezkeyword attributes 00215 { 00216 if ( $attributes[$key] instanceof eZContentObjectAttribute and 00217 $attributes[$key]->attribute( 'data_type_string' ) == 'ezkeyword' ) // Found one 00218 { 00219 $keywordObject = $attributes[$key]->content(); 00220 if ( $keywordObject instanceof eZKeyword ) 00221 { 00222 foreach ( $keywordObject->attribute( 'keywords' ) as $keyword ) 00223 { 00224 $keywordArray[] = $keyword; 00225 } 00226 } 00227 } 00228 } 00229 00230 // Find all nodes that have the given keywords 00231 if ( count( $keywordArray ) > 0 ) 00232 { 00233 $db = eZDB::instance(); 00234 foreach( $keywordArray as $k => $keyword ) 00235 { 00236 $keywordArray[$k] = "'" . $db->escapeString( $keyword ) . "'"; 00237 } 00238 $keywordString = implode( ', ', $keywordArray ); 00239 $params = $limit ? array( 'offset' => 0, 'limit' => $limit ) : array(); 00240 $rows = $db->arrayQuery( "SELECT DISTINCT ezcontentobject_tree.node_id 00241 FROM 00242 ezcontentobject_tree, 00243 ezcontentobject_attribute, 00244 ezkeyword_attribute_link, 00245 ezkeyword 00246 WHERE 00247 ezcontentobject_tree.contentobject_id = ezcontentobject_attribute.contentobject_id AND 00248 ezcontentobject_attribute.id = ezkeyword_attribute_link.objectattribute_id AND 00249 ezkeyword_attribute_link.keyword_id = ezkeyword.id AND 00250 ezkeyword.keyword IN ( $keywordString )", 00251 $params ); 00252 00253 foreach ( $rows as $row ) 00254 { 00255 $nodeIDList[] = $row['node_id']; 00256 } 00257 } 00258 } 00259 00260 /* 00261 \static 00262 For each node in \a $nodeList finds its sibling nodes and adds its ids to 00263 the \a $nodeIDList 00264 */ 00265 static function appendSiblingsNodeIDs( &$nodeList, &$nodeIDList ) 00266 { 00267 $params = array( 'Depth' => 1, 00268 'AsObject' => false ); 00269 foreach ( $nodeList as $node ) 00270 { 00271 $siblingNodeList = eZContentObjectTreeNode::subTreeByNodeID( $params, $node->attribute( 'parent_node_id' ) ); 00272 if ( count( $siblingNodeList ) > 0 ) 00273 { 00274 foreach ( array_keys( $siblingNodeList ) as $siblingKey ) 00275 { 00276 $nodeIDList[] = $siblingNodeList[$siblingKey]['node_id']; 00277 } 00278 } 00279 } 00280 } 00281 00282 /* 00283 \static 00284 Reads 'viewcache.ini' file and determines relation between 00285 \a $classID and another class. 00286 00287 \return An associative array with information on the class, containsL: 00288 - dependent_class_identifier - The class identifier of objects that depend on this class 00289 - additional_objects - Array of additional arbitrary object ids to clear 00290 - max_parents - The maxium number of parent nodes to check, or \c 0 for no limit 00291 - clear_cache_type - Bitfield of clear types, see nodeListForObject() for more details 00292 - object_filter - Array with object IDs, if there are entries only these objects should be checked. 00293 */ 00294 static function dependencyInfo( $classID, $ignoreINISettings = false ) 00295 { 00296 $ini = eZINI::instance( 'viewcache.ini' ); 00297 $info = false; 00298 00299 if ( $ignoreINISettings || $ini->variable( 'ViewCacheSettings', 'SmartCacheClear' ) !== 'disabled' ) 00300 { 00301 if ( $ini->hasGroup( $classID ) ) 00302 { 00303 $info = array(); 00304 $info['clear_cache_exclusive'] = $ini->variable( 'ViewCacheSettings', 'SmartCacheClear' ) === 'exclusive'; 00305 00306 if ( $ini->hasVariable( $classID, 'DependentClassIdentifier' ) ) 00307 $info['dependent_class_identifier'] = $ini->variable( $classID, 'DependentClassIdentifier' ); 00308 00309 if ( $ini->hasVariable( $classID, 'MaxParents' ) ) 00310 $info['max_parents'] = $ini->variable( $classID, 'MaxParents' ); 00311 else 00312 $info['max_parents'] = 0; 00313 00314 if ( $ini->hasVariable( $classID, 'AdditionalObjectIDs' ) ) 00315 $info['additional_objects'] = $ini->variable( $classID, 'AdditionalObjectIDs' ); 00316 00317 $info['clear_cache_type'] = 0; 00318 if ( $ini->hasVariable( $classID, 'ClearCacheMethod' ) ) 00319 { 00320 $type = $ini->variable( $classID, 'ClearCacheMethod' ); 00321 00322 if ( is_array( $type ) ) 00323 { 00324 if ( in_array( 'none', $type ) ) 00325 { 00326 $info['clear_cache_type'] = self::CLEAR_NO_CACHE; 00327 } 00328 elseif ( in_array( 'all', $type ) ) 00329 { 00330 $info['clear_cache_type'] = self::CLEAR_ALL_CACHE; 00331 } 00332 else 00333 { 00334 if ( in_array( 'object', $type ) ) 00335 $info['clear_cache_type'] |= self::CLEAR_NODE_CACHE; 00336 00337 if ( in_array( 'parent', $type ) ) 00338 $info['clear_cache_type'] |= self::CLEAR_PARENT_CACHE; 00339 00340 if ( in_array( 'relating', $type ) ) 00341 $info['clear_cache_type'] |= self::CLEAR_RELATING_CACHE; 00342 00343 if ( in_array( 'keyword', $type ) ) 00344 $info['clear_cache_type'] |= self::CLEAR_KEYWORD_CACHE; 00345 00346 if ( in_array( 'siblings', $type ) ) 00347 $info['clear_cache_type'] |= self::CLEAR_SIBLINGS_CACHE; 00348 } 00349 } 00350 else 00351 { 00352 // deprecated 00353 if ( $type == 'clear_all_caches' ) 00354 { 00355 $info['clear_cache_type'] = self::CLEAR_ALL_CACHE; 00356 } 00357 else 00358 { 00359 if ( $type == 'clear_object_caches_only' || 00360 $type == 'clear_object_and_parent_nodes_caches' || 00361 $type == 'clear_object_and_relating_objects_caches' ) 00362 { 00363 $info['clear_cache_type'] |= self::CLEAR_NODE_CACHE; 00364 } 00365 00366 if ( $type == 'clear_object_and_parent_nodes_caches' || 00367 $type == 'clear_parent_nodes_caches_only' || 00368 $type == 'clear_parent_nodes_and_relating_caches' ) 00369 { 00370 $info['clear_cache_type'] |= self::CLEAR_PARENT_CACHE; 00371 } 00372 00373 if ( $type == 'clear_object_and_relating_objects_caches' || 00374 $type == 'clear_parent_nodes_and_relating_caches' || 00375 $type == 'clear_relating_caches_only' ) 00376 { 00377 $info['clear_cache_type'] |= self::CLEAR_RELATING_CACHE; 00378 } 00379 00380 if ( $type == 'clear_keyword_caches_only' ) 00381 { 00382 $info['clear_cache_type'] |= self::CLEAR_KEYWORD_CACHE; 00383 } 00384 } 00385 } 00386 } 00387 else 00388 { 00389 $info['clear_cache_type'] = self::CLEAR_DEFAULT; 00390 } 00391 00392 $info['object_filter'] = array(); 00393 if ( $ini->hasVariable( $classID, 'ObjectFilter' ) ) 00394 { 00395 $info['object_filter'] = $ini->variable( $classID, 'ObjectFilter' ); 00396 } 00397 } 00398 } 00399 00400 return $info; 00401 } 00402 00403 /* 00404 Can be used to debug the \a $handledObjectList parameter of nodeListForObject() 00405 */ 00406 static function writeDebugBits( $handledObjectList, $highestBit ) 00407 { 00408 $bitPadLength = (int)( pow( $highestBit, 0.5 ) + 1 ); 00409 //$bitPadLength = strlen( decbin( $highestBit ) ); 00410 00411 $objectIDList = array_keys( $handledObjectList ); 00412 $maxObjectID = max( $objectIDList ); 00413 $padLength = strlen( $maxObjectID ) + 2; 00414 00415 $msg = ''; 00416 foreach ( $handledObjectList as $objectID => $clearCacheType ) 00417 { 00418 $bitString = decbin( $clearCacheType ); 00419 $msg .= str_pad( $objectID, $padLength, ' ', STR_PAD_RIGHT ) . str_pad( $bitString, $bitPadLength, '0', STR_PAD_LEFT ); 00420 $msg .= "\r\n"; 00421 } 00422 00423 eZDebug::writeDebug( $msg, 'eZContentCacheManager::writeDebugBits()' ); 00424 } 00425 00426 /*! 00427 \static 00428 Use \a $clearCacheType to include different kind of nodes( parent, relating, etc ). 00429 If \a $versionNum is true, then current version will be used. 00430 00431 \param $contentObject Current content object that is checked. 00432 \param $versionNum The version of the object to use or \c true for current version 00433 \param $clearCacheType Bit field which controls the the extra nodes to include, 00434 use bitwise or with one of these defines: 00435 - self::CLEAR_NODE_CACHE - Clear the nodes of the object 00436 - self::CLEAR_PARENT_CACHE - Clear the parent nodes of the object 00437 - self::CLEAR_RELATING_CACHE - Clear nodes of objects that relate this object 00438 - self::CLEAR_KEYWORD_CACHE - Clear nodes of objects that have the same keyword as this object 00439 - self::CLEAR_SIBLINGS_CACHE - Clear caches for siblings of the node. 00440 - self::CLEAR_ALL_CACHE - Enables all of the above 00441 - self::CLEAR_NO_CACHE - Do not clear cache for current object. 00442 \param[out] $nodeList An array with node IDs that are affected by the current object change. 00443 \param[out] $handledObjectList An associative array with object IDs and the cache types that were handled for these objects already. 00444 Used to avoid infinite recursion. 00445 00446 \note This function is recursive. 00447 */ 00448 static function nodeListForObject( $contentObject, $versionNum, $clearCacheType, &$nodeList, &$handledObjectList ) 00449 { 00450 $contentObjectID = $contentObject->attribute( 'id' ); 00451 00452 if ( isset( $handledObjectList[$contentObjectID] ) ) 00453 { 00454 $handledObjectList[$contentObjectID] |= $clearCacheType; 00455 } 00456 else 00457 { 00458 $handledObjectList[$contentObjectID] = $clearCacheType; 00459 } 00460 //self::writeDebugBits( $handledObjectList, self::CLEAR_SIBLINGS_CACHE ); 00461 00462 $assignedNodes = $contentObject->assignedNodes(); 00463 00464 // determine if $contentObject has dependent objects for which cache should be cleared too. 00465 $objectClassIdentifier = $contentObject->attribute( 'class_identifier' ); 00466 $dependentClassInfo = eZContentCacheManager::dependencyInfo( $objectClassIdentifier ); 00467 00468 if ( $dependentClassInfo['clear_cache_type'] === self::CLEAR_NO_CACHE ) 00469 { 00470 // BC: Allow smart cache clear setting to specify no caching setting 00471 $clearCacheType = self::CLEAR_NO_CACHE; 00472 } 00473 else if ( $dependentClassInfo['clear_cache_exclusive'] === true ) 00474 { 00475 // use class specific smart cache rules exclusivly 00476 $clearCacheType = $dependentClassInfo['clear_cache_type']; 00477 } 00478 00479 if ( $clearCacheType === self::CLEAR_NO_CACHE ) 00480 { 00481 // when recursing we will never have to handle this object again for other cache types 00482 // because types of caches to clear will always be set to none 00483 $handledObjectList[$contentObjectID] = self::CLEAR_ALL_CACHE; 00484 } 00485 00486 if ( $clearCacheType & self::CLEAR_NODE_CACHE ) 00487 { 00488 eZContentCacheManager::appendNodeIDs( $assignedNodes, $nodeList ); 00489 } 00490 00491 if ( $clearCacheType & self::CLEAR_PARENT_CACHE ) 00492 { 00493 eZContentCacheManager::appendParentNodeIDs( $contentObject, $versionNum, $nodeList ); 00494 } 00495 00496 if ( $clearCacheType & self::CLEAR_RELATING_CACHE ) 00497 { 00498 eZContentCacheManager::appendRelatingNodeIDs( $contentObject, $nodeList ); 00499 } 00500 00501 if ( $clearCacheType & self::CLEAR_KEYWORD_CACHE ) 00502 { 00503 $keywordClearLimit = null; 00504 $viewcacheini = eZINI::instance( 'viewcache.ini' ); 00505 if ( is_numeric( $viewcacheini->variable( 'ViewCacheSettings', 'KeywordNodesCacheClearLimit' ) ) ) 00506 $keywordClearLimit = (int) $viewcacheini->variable( 'ViewCacheSettings', 'KeywordNodesCacheClearLimit' ); 00507 00508 eZContentCacheManager::appendKeywordNodeIDs( $contentObject, $versionNum, $nodeList, $keywordClearLimit ); 00509 } 00510 00511 if ( $clearCacheType & self::CLEAR_SIBLINGS_CACHE ) 00512 { 00513 eZContentCacheManager::appendSiblingsNodeIDs( $assignedNodes, $nodeList ); 00514 } 00515 00516 if ( $dependentClassInfo['clear_cache_type'] & self::CLEAR_SIBLINGS_CACHE ) 00517 { 00518 if ( !( $clearCacheType & self::CLEAR_SIBLINGS_CACHE ) ) 00519 { 00520 eZContentCacheManager::appendSiblingsNodeIDs( $assignedNodes, $nodeList ); 00521 $handledObjectList[$contentObjectID] |= self::CLEAR_SIBLINGS_CACHE; 00522 } 00523 00524 // drop 'siblings' bit and process parent nodes. 00525 // since 'sibling' mode is affected to the current object 00526 $dependentClassInfo['clear_cache_type'] &= ~self::CLEAR_SIBLINGS_CACHE; 00527 } 00528 00529 if ( isset( $dependentClassInfo['additional_objects'] ) ) 00530 { 00531 foreach( $dependentClassInfo['additional_objects'] as $objectID ) 00532 { 00533 // skip if cache type is already handled for this object 00534 if ( isset( $handledObjectList[$objectID] ) && $handledObjectList[$objectID] & self::CLEAR_NODE_CACHE ) 00535 { 00536 continue; 00537 } 00538 00539 $object = eZContentObject::fetch( $objectID ); 00540 if ( $object ) 00541 { 00542 //eZDebug::writeDebug( 'adding additional object ' . $objectID, 'eZContentCacheManager::nodeListForObject() for object ' . $contentObjectID ); 00543 eZContentCacheManager::nodeListForObject( $object, true, self::CLEAR_NODE_CACHE, $nodeList, $handledObjectList ); 00544 } 00545 } 00546 } 00547 00548 if ( isset( $dependentClassInfo['dependent_class_identifier'] ) ) 00549 { 00550 $maxParents = $dependentClassInfo['max_parents']; 00551 $dependentClassIdentifiers = $dependentClassInfo['dependent_class_identifier']; 00552 $smartClearType = $dependentClassInfo['clear_cache_type']; 00553 00554 // getting 'path_string's for all locations. 00555 $nodePathList = eZContentCacheManager::fetchNodePathString( $assignedNodes ); 00556 00557 foreach ( $nodePathList as $nodePath ) 00558 { 00559 $step = 0; 00560 00561 // getting class identifier and node ID for each node in the $nodePath, up to $maxParents 00562 $nodeInfoList = eZContentObjectTreeNode::fetchClassIdentifierListByPathString( $nodePath, false, $maxParents ); 00563 00564 // for each node in $nodeInfoList determine if this node belongs to $dependentClassIdentifiers. If 00565 // so then clear cache for this node. 00566 foreach ( $nodeInfoList as $item ) 00567 { 00568 if ( in_array( $item['class_identifier'], $dependentClassIdentifiers ) ) 00569 { 00570 $object = eZContentObject::fetchByNodeID( $item['node_id'] ); 00571 if ( !$object instanceof eZContentObject ) 00572 { 00573 continue; 00574 } 00575 $objectID = $object->attribute( 'id' ); 00576 00577 if ( isset( $handledObjectList[$objectID] ) ) 00578 { 00579 // remove cache types that were already handled 00580 $smartClearType &= ~$handledObjectList[$objectID]; 00581 00582 // if there are no cache types remaining, then skip 00583 if ( $smartClearType == self::CLEAR_NO_CACHE ) 00584 { 00585 continue; 00586 } 00587 } 00588 00589 if ( count( $dependentClassInfo['object_filter'] ) > 0 ) 00590 { 00591 if ( in_array( $objectID, $dependentClassInfo['object_filter'] ) ) 00592 { 00593 //eZDebug::writeDebug( 'adding parent ' . $objectID, 'eZContentCacheManager::nodeListForObject() for object ' . $contentObjectID ); 00594 eZContentCacheManager::nodeListForObject( $object, true, $smartClearType, $nodeList, $handledObjectList ); 00595 } 00596 } 00597 else 00598 { 00599 //eZDebug::writeDebug( 'adding parent ' . $objectID, 'eZContentCacheManager::nodeListForObject() for object ' . $contentObjectID ); 00600 eZContentCacheManager::nodeListForObject( $object, true, $smartClearType, $nodeList, $handledObjectList ); 00601 } 00602 } 00603 } 00604 } 00605 } 00606 00607 //self::writeDebugBits( $handledObjectList, self::CLEAR_SIBLINGS_CACHE ); 00608 } 00609 00610 /*! 00611 \static 00612 Figures out all nodes that are affected by the change of object \a $objectID. 00613 This involves finding all nodes, parent nodes and nodes of objects 00614 that relate this object. 00615 The 'viewcache.ini' file is also checked to see if some special content classes 00616 has dependencies to the current object, if this is true extra nodes might be 00617 included. 00618 00619 \param $versionNum The version of the object to use or \c true for current version 00620 \param $additionalNodeList An array with node IDs to add to clear list, 00621 or \c false for no additional nodes. 00622 \return An array with node IDs that must have their viewcaches cleared. 00623 */ 00624 static function nodeList( $objectID, $versionNum ) 00625 { 00626 $nodeList = array(); 00627 00628 $object = eZContentObject::fetch( $objectID ); 00629 if ( !$object ) 00630 { 00631 return false; 00632 } 00633 00634 eZContentCacheManager::nodeListForObject( $object, $versionNum, self::CLEAR_DEFAULT, $nodeList, $handledObjectList ); 00635 00636 return $nodeList; 00637 } 00638 00639 /*! 00640 \static 00641 Depreciated. Use 'clearObjectViewCache' instead 00642 */ 00643 static function clearViewCache( $objectID, $versionNum = true , $additionalNodeList = false ) 00644 { 00645 eZDebug::writeWarning( "'clearViewCache' function was depreciated. Use 'clearObjectViewCache' instead", 'eZContentCacheManager::clearViewCache' ); 00646 eZContentCacheManager::clearObjectViewCache( $objectID, $versionNum, $additionalNodeList ); 00647 } 00648 00649 /*! 00650 \static 00651 Clears view caches of nodes, parent nodes and relating nodes 00652 of content objects with id \a $objectID. 00653 It will use 'viewcache.ini' to determine additional nodes. 00654 00655 \param $versionNum The version of the object to use or \c true for current version 00656 \param $additionalNodeList An array with node IDs to add to clear list, 00657 or \c false for no additional nodes. 00658 */ 00659 static function clearObjectViewCache( $objectID, $versionNum = true, $additionalNodeList = false ) 00660 { 00661 eZDebug::accumulatorStart( 'node_cleanup_list', '', 'Node cleanup list' ); 00662 00663 $nodeList = eZContentCacheManager::nodeList( $objectID, $versionNum ); 00664 00665 if ( $nodeList === false and !is_array( $additionalNodeList ) ) 00666 return false; 00667 00668 if ( $nodeList === false ) 00669 { 00670 $nodeList = array(); 00671 } 00672 00673 if ( is_array( $additionalNodeList ) ) 00674 { 00675 array_splice( $nodeList, count( $nodeList ), 0, $additionalNodeList ); 00676 } 00677 00678 if ( count( $nodeList ) == 0 ) 00679 { 00680 return false; 00681 } 00682 00683 $nodeList = array_unique( $nodeList ); 00684 00685 eZDebug::accumulatorStop( 'node_cleanup_list' ); 00686 00687 eZDebugSetting::writeDebug( 'kernel-content-edit', count( $nodeList ), "count in nodeList" ); 00688 00689 $ini = eZINI::instance(); 00690 if ( $ini->variable( 'ContentSettings', 'StaticCache' ) == 'enabled' ) 00691 { 00692 $staticCache = new eZStaticCache(); 00693 $staticCache->generateAlwaysUpdatedCache(); 00694 $staticCache->generateNodeListCache( $nodeList ); 00695 } 00696 00697 eZDebug::accumulatorStart( 'node_cleanup', '', 'Node cleanup' ); 00698 00699 eZContentObject::expireComplexViewModeCache(); 00700 $cleanupValue = eZContentCache::calculateCleanupValue( count( $nodeList ) ); 00701 00702 if ( eZContentCache::inCleanupThresholdRange( $cleanupValue ) ) 00703 eZContentCache::cleanup( $nodeList ); 00704 else 00705 eZContentObject::expireAllViewCache(); 00706 00707 eZDebug::accumulatorStop( 'node_cleanup' ); 00708 return true; 00709 } 00710 00711 /*! 00712 \static 00713 Clears view cache for specified object. 00714 Checks 'ViewCaching' ini setting to determine whether cache is enabled or not. 00715 */ 00716 static function clearObjectViewCacheIfNeeded( $objectID, $versionNum = true, $additionalNodeList = false ) 00717 { 00718 $ini = eZINI::instance(); 00719 if ( $ini->variable( 'ContentSettings', 'ViewCaching' ) === 'enabled' ) 00720 eZContentCacheManager::clearObjectViewCache( $objectID, $versionNum, $additionalNodeList ); 00721 } 00722 00723 /*! 00724 \static 00725 Clears template-block cache and template-block with subtree_expiry parameter caches for specified object. 00726 Checks 'TemplateCache' ini setting to determine whether cache is enabled or not. 00727 If $objectID is \c false all template block caches will be cleared. 00728 */ 00729 static function clearTemplateBlockCacheIfNeeded( $objectID ) 00730 { 00731 $ini = eZINI::instance(); 00732 if ( $ini->variable( 'TemplateSettings', 'TemplateCache' ) === 'enabled' ) 00733 eZContentCacheManager::clearTemplateBlockCache( $objectID ); 00734 } 00735 00736 /*! 00737 \static 00738 Clears template-block cache and template-block with subtree_expiry parameter caches for specified object 00739 without checking 'TemplateCache' ini setting. If $objectID is \c false all template block caches will be cleared. 00740 */ 00741 static function clearTemplateBlockCache( $objectID ) 00742 { 00743 // ordinary template block cache 00744 eZContentObject::expireTemplateBlockCache(); 00745 00746 // subtree template block cache 00747 $nodeList = false; 00748 $object = false; 00749 if ( $objectID ) 00750 $object = eZContentObject::fetch( $objectID ); 00751 if ( $object ) 00752 $nodeList = $object->assignedNodes(); 00753 00754 eZSubtreeCache::cleanup( $nodeList ); 00755 } 00756 00757 /*! 00758 \static 00759 Generates the related viewcaches (PreGeneration) for the content object. 00760 It will only do this if [ContentSettings]/PreViewCache in site.ini is enabled. 00761 00762 \param $objectID The ID of the content object to generate caches for. 00763 */ 00764 static function generateObjectViewCache( $objectID ) 00765 { 00766 // Generate the view cache 00767 $ini = eZINI::instance(); 00768 $object = eZContentObject::fetch( $objectID ); 00769 $user = eZUser::currentUser(); 00770 00771 eZDebug::accumulatorStart( 'generate_cache', '', 'Generating view cache' ); 00772 if ( $ini->variable( 'ContentSettings', 'PreViewCache' ) == 'enabled' ) 00773 { 00774 $preCacheSiteaccessArray = $ini->variable( 'ContentSettings', 'PreCacheSiteaccessArray' ); 00775 00776 $currentSiteAccess = $GLOBALS['eZCurrentAccess']['name']; 00777 00778 // This is the default view parameters for content/view 00779 $viewParameters = array( 'offset' => 0, 00780 'year' => false, 00781 'month' => false, 00782 'day' => false, 00783 'namefilter' => false ); 00784 if ( is_array( $preCacheSiteaccessArray ) && count( $preCacheSiteaccessArray ) > 0 ) 00785 { 00786 foreach ( $preCacheSiteaccessArray as $changeToSiteAccess ) 00787 { 00788 $GLOBALS['eZCurrentAccess']['name'] = $changeToSiteAccess; 00789 00790 if ( $GLOBALS['eZCurrentAccess']['type'] == EZ_ACCESS_TYPE_URI ) 00791 { 00792 eZSys::clearAccessPath(); 00793 eZSys::addAccessPath( $changeToSiteAccess ); 00794 } 00795 00796 require_once( 'kernel/common/template.php' ); 00797 $tpl = templateInit(); 00798 $res = eZTemplateDesignResource::instance(); 00799 00800 // Get the sitedesign and cached view preferences for this siteaccess 00801 $siteini = eZINI::instance( 'site.ini', 'settings', null, null, false ); 00802 $siteini->prependOverrideDir( "siteaccess/$changeToSiteAccess", false, 'siteaccess' ); 00803 $siteini->loadCache(); 00804 $designSetting = $siteini->variable( "DesignSettings", "SiteDesign" ); 00805 $cachedViewPreferences = $siteini->variable( 'ContentSettings', 'CachedViewPreferences' ); 00806 $res->setDesignSetting( $designSetting, 'site' ); 00807 00808 $res->setOverrideAccess( $changeToSiteAccess ); 00809 00810 $language = false; // Needs to be specified if you want to generate the cache for a specific language 00811 $viewMode = 'full'; 00812 00813 $assignedNodes = $object->assignedNodes(); 00814 foreach ( $assignedNodes as $node ) 00815 { 00816 // We want to generate the cache for the specified user 00817 $previewCacheUsers = $ini->variable( 'ContentSettings', 'PreviewCacheUsers' ); 00818 foreach ( $previewCacheUsers as $previewCacheUserID ) 00819 { 00820 // If the text is 'anon' we need to fetch the Anonymous user ID. 00821 if ( $previewCacheUserID === 'anonymous' ) 00822 { 00823 $previewCacheUserID = $siteini->variable( "UserSettings", "AnonymousUserID" ); 00824 $previewCacheUser = eZUser::fetch( $previewCacheUserID ); 00825 } 00826 else if ( $previewCacheUserID === 'current' ) 00827 { 00828 $previewCacheUser = $user; 00829 } 00830 else 00831 { 00832 $previewCacheUser = eZUser::fetch( $previewCacheUserID ); 00833 } 00834 if ( !$previewCacheUser ) 00835 continue; 00836 00837 // Before we generate the view cache we must change the currently logged in user to $previewCacheUser 00838 // If not the templates might read in wrong personalized data (preferences etc.) 00839 $previewCacheUser->setCurrentlyLoggedInUser( $previewCacheUser, $previewCacheUser->attribute( 'contentobject_id' ) ); 00840 00841 // Cache the current node 00842 $cacheFileArray = eZNodeviewfunctions::generateViewCacheFile( $previewCacheUser, $node->attribute( 'node_id' ), 0, false, $language, $viewMode, $viewParameters, $cachedViewPreferences ); 00843 $tmpRes = eZNodeviewfunctions::generateNodeView( $tpl, $node, $node->attribute( 'object' ), $language, $viewMode, 0, $cacheFileArray['cache_dir'], $cacheFileArray['cache_path'], true, $viewParameters ); 00844 00845 // Cache the parent node 00846 $parentNode = $node->attribute( 'parent' ); 00847 $objectID = $parentNode->attribute( 'contentobject_id' ); 00848 // if parent objectID is null or is 0 we should not create cache. 00849 if ( $objectID ) 00850 { 00851 $cacheFileArray = eZNodeviewfunctions::generateViewCacheFile( $previewCacheUser, $parentNode->attribute( 'node_id' ), 0, false, $language, $viewMode, $viewParameters, $cachedViewPreferences ); 00852 $tmpRes = eZNodeviewfunctions::generateNodeView( $tpl, $parentNode, $parentNode->attribute( 'object' ), $language, $viewMode, 0, $cacheFileArray['cache_dir'], $cacheFileArray['cache_path'], true, $viewParameters ); 00853 } 00854 } 00855 } 00856 } 00857 // Restore the old user as the current one 00858 $user->setCurrentlyLoggedInUser( $user, $user->attribute( 'contentobject_id' ) ); 00859 00860 $GLOBALS['eZCurrentAccess']['name'] = $currentSiteAccess; 00861 $res->setDesignSetting( $currentSiteAccess, 'site' ); 00862 $res->setOverrideAccess( false ); 00863 00864 if ( $GLOBALS['eZCurrentAccess']['type'] == EZ_ACCESS_TYPE_URI ) 00865 { 00866 eZSys::clearAccessPath(); 00867 eZSys::addAccessPath( $currentSiteAccess ); 00868 } 00869 } 00870 } 00871 00872 if ( $ini->variable( 'ContentSettings', 'StaticCache' ) == 'enabled' ) 00873 { 00874 $nodes = array(); 00875 $ini = eZINI::instance(); 00876 $staticCache = new eZStaticCache(); 00877 $useURLAlias =& $GLOBALS['eZContentObjectTreeNodeUseURLAlias']; 00878 $pathPrefix = $ini->variable( 'SiteAccessSettings', 'PathPrefix' ); 00879 00880 if ( !isset( $useURLAlias ) ) 00881 { 00882 $useURLAlias = $ini->variable( 'URLTranslator', 'Translation' ) == 'enabled'; 00883 } 00884 00885 eZContentCacheManager::nodeListForObject( $object, true, self::CLEAR_DEFAULT, $nodes, $handledObjectList ); 00886 00887 // If no nodes returns it means that ClearCacheMethod = self::CLEAR_NO_CACHE 00888 if ( count( $nodes ) ) 00889 { 00890 foreach ( $nodes as $nodeID ) 00891 { 00892 if ( $useURLAlias ) 00893 { 00894 $oNode = eZContentObjectTreeNode::fetch( $nodeID, false, true ); 00895 if ( !isset( $oNode ) ) 00896 continue; 00897 00898 $urlAlias = $oNode->urlAlias(); 00899 if ( $pathPrefix != '' ) 00900 { 00901 $tempAlias = substr( $pathPrefix, strlen( $pathPrefix ) -1 ) == '/' 00902 ? $urlAlias . '/' 00903 : $urlAlias; 00904 if ( strncmp( $tempAlias, $pathPrefix, strlen( $tempAlias) ) == 0 ) 00905 $urlAlias = substr( $tempAlias, strlen( $pathPrefix ) ); 00906 } 00907 } 00908 else 00909 { 00910 $urlAlias = 'content/view/full/' . $nodeID; 00911 } 00912 $staticCache->cacheURL( '/' . $urlAlias, $nodeID ); 00913 } 00914 $staticCache->generateAlwaysUpdatedCache(); 00915 } 00916 } 00917 eZDebug::accumulatorStop( 'generate_cache' ); 00918 } 00919 00920 /*! 00921 \static 00922 Clears content cache if needed by \a $sectionID 00923 */ 00924 static function clearContentCacheIfNeededBySectionID( $sectionID ) 00925 { 00926 // fetch all objects of this section 00927 $objectList = eZContentObject::fetchList( false, array( 'section_id' => "$sectionID" ) ); 00928 // Clear cache 00929 foreach ( $objectList as $object ) 00930 { 00931 eZContentCacheManager::clearContentCacheIfNeeded( $object['id'] ); 00932 } 00933 return true; 00934 } 00935 00936 /*! 00937 \static 00938 Clears content cache for specified object: view cache, template-block cache, template-block with subtree_expiry parameter cache. 00939 Checks appropriate ini settings to determine whether caches are enabled or not. 00940 */ 00941 static function clearContentCacheIfNeeded( $objectID, $versionNum = true, $additionalNodeList = false ) 00942 { 00943 eZDebug::accumulatorStart( 'check_cache', '', 'Check cache' ); 00944 00945 eZContentCacheManager::clearObjectViewCacheIfNeeded( $objectID, $versionNum, $additionalNodeList ); 00946 eZContentCacheManager::clearTemplateBlockCacheIfNeeded( $objectID ); 00947 00948 // Clear cached path strings of content SSL zones. 00949 eZSSLZone::clearCacheIfNeeded(); 00950 00951 eZDebug::accumulatorStop( 'check_cache' ); 00952 return true; 00953 } 00954 00955 /*! 00956 \static 00957 Clears content cache for specified object: view cache, template-block cache, template-block with subtree_expiry parameter cache 00958 without checking of ini settings. 00959 */ 00960 static function clearContentCache( $objectID, $versionNum = true, $additionalNodeList = false ) 00961 { 00962 eZDebug::accumulatorStart( 'check_cache', '', 'Check cache' ); 00963 00964 eZContentCacheManager::clearObjectViewCache( $objectID, $versionNum, $additionalNodeList ); 00965 eZContentCacheManager::clearTemplateBlockCache( $objectID ); 00966 00967 // Clear cached path strings of content SSL zones. 00968 eZSSLZone::clearCache(); 00969 00970 eZDebug::accumulatorStop( 'check_cache' ); 00971 return true; 00972 } 00973 00974 /*! 00975 \static 00976 Clears all content cache: view cache, template-block cache, template-block with subtree_expiry parameter cache. 00977 */ 00978 static function clearAllContentCache( $ignoreINISettings = false ) 00979 { 00980 if ( !$ignoreINISettings ) 00981 { 00982 $ini = eZINI::instance(); 00983 $viewCacheEnabled = ( $ini->variable( 'ContentSettings', 'ViewCaching' ) === 'enabled' ); 00984 $templateCacheEnabled = ( $ini->variable( 'TemplateSettings', 'TemplateCache' ) === 'enabled' ); 00985 } 00986 else 00987 { 00988 $viewCacheEnabled = true; 00989 $templateCacheEnabled = true; 00990 } 00991 00992 if ( $viewCacheEnabled || $templateCacheEnabled ) 00993 { 00994 // view cache and/or ordinary template block cache 00995 eZContentObject::expireAllCache(); 00996 00997 // subtree template block caches 00998 if ( $templateCacheEnabled ) 00999 { 01000 eZSubtreeCache::cleanupAll(); 01001 } 01002 } 01003 } 01004 } 01005 01006 ?>