|
eZ Publish
[4.0]
|
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.0.x 00010 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 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 ezcontentcachemanager.php 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 //include_once( 'kernel/classes/ezcontentobject.php' ); 00048 //include_once( 'lib/ezutils/classes/ezini.php' ); 00049 require_once( 'access.php' ); 00050 00051 class eZContentCacheManager 00052 { 00053 // Clear cache types 00054 const CLEAR_NO_CACHE = 0; 00055 const CLEAR_NODE_CACHE = 1; 00056 const CLEAR_PARENT_CACHE = 2; 00057 const CLEAR_RELATING_CACHE = 4; 00058 const CLEAR_KEYWORD_CACHE = 8; 00059 const CLEAR_SIBLINGS_CACHE = 16; 00060 const CLEAR_ALL_CACHE = 31; 00061 const CLEAR_DEFAULT = 15; // CLEAR_NODE_CACHE and CLEAR_PARENT_CACHE and CLEAR_RELATING_CACHE and CLEAR_KEYWORD_CACHE 00062 00063 /*! 00064 \static 00065 Appends parent nodes ids of \a $object to \a $nodeIDList array. 00066 \param $versionNum The version of the object to use or \c true for current version 00067 \param[out] $nodeIDList Array with node IDs 00068 */ 00069 static function appendParentNodeIDs( $object, $versionNum, &$nodeIDList ) 00070 { 00071 foreach ( $object->parentNodes( $versionNum ) as $parentNode ) 00072 { 00073 if ( is_object ( $parentNode ) ) 00074 { 00075 $nodeIDList[] = $parentNode->attribute( 'node_id' ); 00076 } 00077 } 00078 } 00079 00080 /*! 00081 \static 00082 Appends nodes ids from \a $nodeList list to \a $nodeIDList 00083 \param[out] $nodeIDList Array with node IDs 00084 */ 00085 static function appendNodeIDs( $nodeList, &$nodeIDList ) 00086 { 00087 foreach ( $nodeList as $node ) 00088 { 00089 $nodeIDList[] = $node->attribute( 'node_id' ); 00090 } 00091 } 00092 00093 /*! 00094 \static 00095 Goes through all content nodes in \a $nodeList and extracts the \c 'path_string'. 00096 \return An array with \c 'path_string' information. 00097 */ 00098 static function fetchNodePathString( $nodeList ) 00099 { 00100 $pathList = array(); 00101 foreach ( $nodeList as $node ) 00102 { 00103 $pathList[] = $node->attribute( 'path_string' ); 00104 } 00105 return $pathList; 00106 } 00107 00108 /*! 00109 \static 00110 Find all content objects that relates \a $object and appends 00111 their node IDs to \a $nodeIDList. 00112 \param[out] $nodeIDList Array with node IDs 00113 */ 00114 static function appendRelatingNodeIDs( $object, &$nodeIDList ) 00115 { 00116 $viewCacheIni = eZINI::instance( 'viewcache.ini' ); 00117 if ( $viewCacheIni->hasVariable( 'ViewCacheSettings', 'ClearRelationTypes' ) ) 00118 { 00119 $relTypes = $viewCacheIni->variable( 'ViewCacheSettings', 'ClearRelationTypes' ); 00120 00121 if ( !count( $relTypes ) ) 00122 return; 00123 00124 $relatedObjects = array(); 00125 00126 $relationsMask = 0; 00127 if ( in_array( 'object', $relTypes ) ) 00128 $relationsMask |= eZContentObject::RELATION_COMMON | eZContentObject::RELATION_EMBED; 00129 00130 if ( in_array( 'common', $relTypes ) ) 00131 $relationsMask |= eZContentObject::RELATION_COMMON; 00132 00133 if ( in_array( 'embedded', $relTypes ) ) 00134 $relationsMask |= eZContentObject::RELATION_EMBED; 00135 00136 if ( in_array( 'linked', $relTypes ) ) 00137 $relationsMask |= eZContentObject::RELATION_LINK; 00138 00139 if ( in_array( 'attribute', $relTypes ) ) 00140 $relationsMask |= eZContentObject::RELATION_ATTRIBUTE; 00141 00142 if ( $relationsMask ) 00143 { 00144 $objects = $object->relatedContentObjectList( false, false, false, false, 00145 array( 'AllRelations' => $relationsMask ) ); 00146 $previousVersionObjects = array(); 00147 $previousVersion = $object->previousVersion(); 00148 if ( $previousVersion ) 00149 { 00150 $previousVersionObjects = $object->relatedContentObjectList( $previousVersion, false, false, false, 00151 array( 'AllRelations' => $relationsMask ) ); 00152 } 00153 $relatedObjects = array_merge( $relatedObjects, $objects, $previousVersionObjects ); 00154 } 00155 00156 $relationsMask = 0; 00157 if ( in_array( 'reverse_object', $relTypes ) ) 00158 $relationsMask |= eZContentObject::RELATION_COMMON | eZContentObject::RELATION_EMBED; 00159 00160 if ( in_array( 'reverse_common', $relTypes ) ) 00161 $relationsMask |= eZContentObject::RELATION_COMMON; 00162 00163 if ( in_array( 'reverse_embedded', $relTypes ) ) 00164 $relationsMask |= eZContentObject::RELATION_EMBED; 00165 00166 if ( in_array( 'reverse_linked', $relTypes ) ) 00167 $relationsMask |= eZContentObject::RELATION_LINK; 00168 00169 if ( in_array( 'reverse_attribute', $relTypes ) ) 00170 $relationsMask |= eZContentObject::RELATION_ATTRIBUTE; 00171 00172 if ( $relationsMask ) 00173 { 00174 $objects = $object->reverseRelatedObjectList( false, false, false, 00175 array( 'AllRelations' => $relationsMask ) ); 00176 $previousVersionObjects = array(); 00177 $previousVersion = $object->previousVersion(); 00178 if ( $previousVersion ) 00179 { 00180 $previousVersionObjects = $object->relatedContentObjectList( $previousVersion, false, false, false, 00181 array( 'AllRelations' => $relationsMask ) ); 00182 } 00183 $relatedObjects = array_merge( $relatedObjects, $objects, $previousVersionObjects ); 00184 } 00185 } 00186 else 00187 { 00188 $normalRelated = $object->relatedContentObjectArray(); 00189 $reversedRelated = $object->contentObjectListRelatingThis(); 00190 00191 $relatedObjects = array_merge( $normalRelated, $reversedRelated ); 00192 } 00193 00194 foreach ( $relatedObjects as $relatedObject ) 00195 { 00196 $assignedNodes = $relatedObject->assignedNodes( false ); 00197 foreach ( $assignedNodes as $assignedNode ) 00198 { 00199 $nodeIDList[] = $assignedNode['node_id']; 00200 } 00201 } 00202 $nodeIDList = array_unique( $nodeIDList ); 00203 } 00204 00205 /*! 00206 \static 00207 Appends node ids of objects with the same keyword(s) as \a $object to \a $nodeIDList array. 00208 \param $versionNum The version of the object to use or \c true for current version 00209 \param[out] $nodeIDList Array with node IDs 00210 */ 00211 static function appendKeywordNodeIDs( $object, $versionNum, &$nodeIDList ) 00212 { 00213 if ( $versionNum === true ) 00214 $versionNum = false; 00215 $keywordArray = array(); 00216 $attributes = $object->contentObjectAttributes( true, $versionNum ); 00217 foreach ( array_keys( $attributes ) as $key ) // Looking for ezkeyword attributes 00218 { 00219 if ( $attributes[$key] instanceof eZContentObjectAttribute and 00220 $attributes[$key]->attribute( 'data_type_string' ) == 'ezkeyword' ) // Found one 00221 { 00222 $keywordObject = $attributes[$key]->content(); 00223 if ( $keywordObject instanceof eZKeyword ) 00224 { 00225 foreach ( $keywordObject->attribute( 'keywords' ) as $keyword ) 00226 { 00227 $keywordArray[] = $keyword; 00228 } 00229 } 00230 } 00231 } 00232 00233 // Find all nodes that have the given keywords 00234 if ( count( $keywordArray ) > 0 ) 00235 { 00236 //include_once( 'lib/ezdb/classes/ezdb.php' ); 00237 $db = eZDB::instance(); 00238 foreach( $keywordArray as $k => $keyword ) 00239 { 00240 $keywordArray[$k] = "'" . $db->escapeString( $keyword ) . "'"; 00241 } 00242 $keywordString = implode( ', ', $keywordArray ); 00243 $rows = $db->arrayQuery( "SELECT DISTINCT ezcontentobject_tree.node_id 00244 FROM 00245 ezcontentobject_tree, 00246 ezcontentobject_attribute, 00247 ezkeyword_attribute_link, 00248 ezkeyword 00249 WHERE 00250 ezcontentobject_tree.contentobject_id = ezcontentobject_attribute.contentobject_id AND 00251 ezcontentobject_attribute.id = ezkeyword_attribute_link.objectattribute_id AND 00252 ezkeyword_attribute_link.keyword_id = ezkeyword.id AND 00253 ezkeyword.keyword IN ( $keywordString )" ); 00254 00255 foreach ( $rows as $row ) 00256 { 00257 $nodeIDList[] = $row['node_id']; 00258 } 00259 } 00260 } 00261 00262 /* 00263 \static 00264 For each node in \a $nodeList finds its sibling nodes and adds its ids to 00265 the \a $nodeIDList 00266 */ 00267 static function appendSiblingsNodeIDs( &$nodeList, &$nodeIDList ) 00268 { 00269 $params = array( 'Depth' => 1, 00270 'AsObject' => false ); 00271 foreach ( $nodeList as $node ) 00272 { 00273 $siblingNodeList = eZContentObjectTreeNode::subTreeByNodeID( $params, $node->attribute( 'parent_node_id' ) ); 00274 if ( count( $siblingNodeList ) > 0 ) 00275 { 00276 foreach ( array_keys( $siblingNodeList ) as $siblingKey ) 00277 { 00278 $nodeIDList[] = $siblingNodeList[$siblingKey]['node_id']; 00279 } 00280 } 00281 } 00282 } 00283 00284 /* 00285 \static 00286 Reads 'viewcache.ini' file and determines relation between 00287 \a $classID and another class. 00288 00289 \return An associative array with information on the class, containsL: 00290 - dependent_class_identifier - The class identifier of objects that depend on this class 00291 - additional_objects - Array of additional arbitrary object ids to clear 00292 - max_parents - The maxium number of parent nodes to check, or \c 0 for no limit 00293 - clear_cache_type - Bitfield of clear types, see nodeListForObject() for more details 00294 - object_filter - Array with object IDs, if there are entries only these objects should be checked. 00295 */ 00296 static function dependencyInfo( $classID, $ignoreINISettings = false ) 00297 { 00298 $ini = eZINI::instance( 'viewcache.ini' ); 00299 $info = false; 00300 00301 if ( $ignoreINISettings || $ini->variable( 'ViewCacheSettings', 'SmartCacheClear' ) == 'enabled' ) 00302 { 00303 if ( $ini->hasGroup( $classID ) ) 00304 { 00305 $info = array(); 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 //Check if clear_cache_type on class type is none before we begin 00469 if ( $dependentClassInfo['clear_cache_type'] === self::CLEAR_NO_CACHE ) 00470 { 00471 $clearCacheType = $dependentClassInfo['clear_cache_type']; 00472 // when recursing we will never have to handle this object again for other cache types 00473 // because types of caches to clear will always be set to none 00474 $handledObjectList[$contentObjectID] = self::CLEAR_ALL_CACHE; 00475 } 00476 00477 if ( $clearCacheType & self::CLEAR_NODE_CACHE ) 00478 { 00479 eZContentCacheManager::appendNodeIDs( $assignedNodes, $nodeList ); 00480 } 00481 00482 if ( $clearCacheType & self::CLEAR_PARENT_CACHE ) 00483 { 00484 eZContentCacheManager::appendParentNodeIDs( $contentObject, $versionNum, $nodeList ); 00485 } 00486 00487 if ( $clearCacheType & self::CLEAR_RELATING_CACHE ) 00488 { 00489 eZContentCacheManager::appendRelatingNodeIDs( $contentObject, $nodeList ); 00490 } 00491 00492 if ( $clearCacheType & self::CLEAR_KEYWORD_CACHE ) 00493 { 00494 eZContentCacheManager::appendKeywordNodeIDs( $contentObject, $versionNum, $nodeList ); 00495 } 00496 00497 if ( $clearCacheType & self::CLEAR_SIBLINGS_CACHE ) 00498 { 00499 eZContentCacheManager::appendSiblingsNodeIDs( $assignedNodes, $nodeList ); 00500 } 00501 00502 if ( $dependentClassInfo['clear_cache_type'] & self::CLEAR_SIBLINGS_CACHE ) 00503 { 00504 if ( !( $clearCacheType & self::CLEAR_SIBLINGS_CACHE ) ) 00505 { 00506 eZContentCacheManager::appendSiblingsNodeIDs( $assignedNodes, $nodeList ); 00507 $handledObjectList[$contentObjectID] |= self::CLEAR_SIBLINGS_CACHE; 00508 } 00509 00510 // drop 'siblings' bit and process parent nodes. 00511 // since 'sibling' mode is affected to the current object 00512 $dependentClassInfo['clear_cache_type'] &= ~self::CLEAR_SIBLINGS_CACHE; 00513 } 00514 00515 if ( isset( $dependentClassInfo['additional_objects'] ) ) 00516 { 00517 foreach( $dependentClassInfo['additional_objects'] as $objectID ) 00518 { 00519 // skip if cache type is already handled for this object 00520 if ( isset( $handledObjectList[$objectID] ) && $handledObjectList[$objectID] & self::CLEAR_NODE_CACHE ) 00521 { 00522 continue; 00523 } 00524 00525 $object = eZContentObject::fetch( $objectID ); 00526 if ( $object ) 00527 { 00528 //eZDebug::writeDebug( 'adding additional object ' . $objectID, 'eZContentCacheManager::nodeListForObject() for object ' . $contentObjectID ); 00529 eZContentCacheManager::nodeListForObject( $object, true, self::CLEAR_NODE_CACHE, $nodeList, $handledObjectList ); 00530 } 00531 } 00532 } 00533 00534 if ( isset( $dependentClassInfo['dependent_class_identifier'] ) ) 00535 { 00536 $maxParents = $dependentClassInfo['max_parents']; 00537 $dependentClassIdentifiers = $dependentClassInfo['dependent_class_identifier']; 00538 $smartClearType = $dependentClassInfo['clear_cache_type']; 00539 00540 // getting 'path_string's for all locations. 00541 $nodePathList = eZContentCacheManager::fetchNodePathString( $assignedNodes ); 00542 00543 foreach ( $nodePathList as $nodePath ) 00544 { 00545 $step = 0; 00546 00547 // getting class identifier and node ID for each node in the $nodePath, up to $maxParents 00548 $nodeInfoList = eZContentObjectTreeNode::fetchClassIdentifierListByPathString( $nodePath, false, $maxParents ); 00549 00550 // for each node in $nodeInfoList determine if this node belongs to $dependentClassIdentifiers. If 00551 // so then clear cache for this node. 00552 foreach ( $nodeInfoList as $item ) 00553 { 00554 if ( in_array( $item['class_identifier'], $dependentClassIdentifiers ) ) 00555 { 00556 $object = eZContentObject::fetchByNodeID( $item['node_id'] ); 00557 if ( !$object instanceof eZContentObject ) 00558 { 00559 continue; 00560 } 00561 $objectID = $object->attribute( 'id' ); 00562 00563 if ( isset( $handledObjectList[$objectID] ) ) 00564 { 00565 // remove cache types that were already handled 00566 $smartClearType &= ~$handledObjectList[$objectID]; 00567 00568 // if there are no cache types remaining, then skip 00569 if ( $smartClearType == self::CLEAR_NO_CACHE ) 00570 { 00571 continue; 00572 } 00573 } 00574 00575 if ( count( $dependentClassInfo['object_filter'] ) > 0 ) 00576 { 00577 if ( in_array( $objectID, $dependentClassInfo['object_filter'] ) ) 00578 { 00579 //eZDebug::writeDebug( 'adding parent ' . $objectID, 'eZContentCacheManager::nodeListForObject() for object ' . $contentObjectID ); 00580 eZContentCacheManager::nodeListForObject( $object, true, $smartClearType, $nodeList, $handledObjectList ); 00581 } 00582 } 00583 else 00584 { 00585 //eZDebug::writeDebug( 'adding parent ' . $objectID, 'eZContentCacheManager::nodeListForObject() for object ' . $contentObjectID ); 00586 eZContentCacheManager::nodeListForObject( $object, true, $smartClearType, $nodeList, $handledObjectList ); 00587 } 00588 } 00589 } 00590 } 00591 } 00592 00593 //self::writeDebugBits( $handledObjectList, self::CLEAR_SIBLINGS_CACHE ); 00594 } 00595 00596 /*! 00597 \static 00598 Figures out all nodes that are affected by the change of object \a $objectID. 00599 This involves finding all nodes, parent nodes and nodes of objects 00600 that relate this object. 00601 The 'viewcache.ini' file is also checked to see if some special content classes 00602 has dependencies to the current object, if this is true extra nodes might be 00603 included. 00604 00605 \param $versionNum The version of the object to use or \c true for current version 00606 \param $additionalNodeList An array with node IDs to add to clear list, 00607 or \c false for no additional nodes. 00608 \return An array with node IDs that must have their viewcaches cleared. 00609 */ 00610 static function nodeList( $objectID, $versionNum ) 00611 { 00612 $nodeList = array(); 00613 00614 $object = eZContentObject::fetch( $objectID ); 00615 if ( !$object ) 00616 { 00617 return false; 00618 } 00619 00620 eZContentCacheManager::nodeListForObject( $object, $versionNum, self::CLEAR_DEFAULT, $nodeList, $handledObjectList ); 00621 00622 return $nodeList; 00623 } 00624 00625 /*! 00626 \static 00627 Depreciated. Use 'clearObjectViewCache' instead 00628 */ 00629 static function clearViewCache( $objectID, $versionNum = true , $additionalNodeList = false ) 00630 { 00631 eZDebug::writeWarning( "'clearViewCache' function was depreciated. Use 'clearObjectViewCache' instead", 'eZContentCacheManager::clearViewCache' ); 00632 eZContentCacheManager::clearObjectViewCache( $objectID, $versionNum, $additionalNodeList ); 00633 } 00634 00635 /*! 00636 \static 00637 Clears view caches of nodes, parent nodes and relating nodes 00638 of content objects with id \a $objectID. 00639 It will use 'viewcache.ini' to determine additional nodes. 00640 00641 \param $versionNum The version of the object to use or \c true for current version 00642 \param $additionalNodeList An array with node IDs to add to clear list, 00643 or \c false for no additional nodes. 00644 */ 00645 static function clearObjectViewCache( $objectID, $versionNum = true, $additionalNodeList = false ) 00646 { 00647 eZDebug::accumulatorStart( 'node_cleanup_list', '', 'Node cleanup list' ); 00648 00649 $nodeList = eZContentCacheManager::nodeList( $objectID, $versionNum ); 00650 00651 if ( $nodeList === false and !is_array( $additionalNodeList ) ) 00652 return false; 00653 00654 if ( $nodeList === false ) 00655 { 00656 $nodeList = array(); 00657 } 00658 00659 if ( is_array( $additionalNodeList ) ) 00660 { 00661 array_splice( $nodeList, count( $nodeList ), 0, $additionalNodeList ); 00662 } 00663 00664 if ( count( $nodeList ) == 0 ) 00665 { 00666 return false; 00667 } 00668 00669 $nodeList = array_unique( $nodeList ); 00670 00671 eZDebug::accumulatorStop( 'node_cleanup_list' ); 00672 00673 eZDebugSetting::writeDebug( 'kernel-content-edit', count( $nodeList ), "count in nodeList" ); 00674 00675 $ini = eZINI::instance(); 00676 if ( $ini->variable( 'ContentSettings', 'StaticCache' ) == 'enabled' ) 00677 { 00678 //include_once( 'kernel/classes/ezstaticcache.php' ); 00679 //include_once( 'kernel/classes/ezcontentobjecttreenode.php' ); 00680 $staticCache = new eZStaticCache(); 00681 $staticCache->generateAlwaysUpdatedCache(); 00682 $staticCache->generateNodeListCache( $nodeList ); 00683 } 00684 00685 //include_once( 'kernel/classes/ezcontentcache.php' ); 00686 00687 eZDebug::accumulatorStart( 'node_cleanup', '', 'Node cleanup' ); 00688 00689 eZContentObject::expireComplexViewModeCache(); 00690 $cleanupValue = eZContentCache::calculateCleanupValue( count( $nodeList ) ); 00691 00692 if ( eZContentCache::inCleanupThresholdRange( $cleanupValue ) ) 00693 eZContentCache::cleanup( $nodeList ); 00694 else 00695 eZContentObject::expireAllViewCache(); 00696 00697 eZDebug::accumulatorStop( 'node_cleanup' ); 00698 return true; 00699 } 00700 00701 /*! 00702 \static 00703 Clears view cache for specified object. 00704 Checks 'ViewCaching' ini setting to determine whether cache is enabled or not. 00705 */ 00706 static function clearObjectViewCacheIfNeeded( $objectID, $versionNum = true, $additionalNodeList = false ) 00707 { 00708 $ini = eZINI::instance(); 00709 if ( $ini->variable( 'ContentSettings', 'ViewCaching' ) === 'enabled' ) 00710 eZContentCacheManager::clearObjectViewCache( $objectID, $versionNum, $additionalNodeList ); 00711 } 00712 00713 /*! 00714 \static 00715 Clears template-block cache and template-block with subtree_expiry parameter caches for specified object. 00716 Checks 'TemplateCache' ini setting to determine whether cache is enabled or not. 00717 If $objectID is \c false all template block caches will be cleared. 00718 */ 00719 static function clearTemplateBlockCacheIfNeeded( $objectID ) 00720 { 00721 $ini = eZINI::instance(); 00722 if ( $ini->variable( 'TemplateSettings', 'TemplateCache' ) === 'enabled' ) 00723 eZContentCacheManager::clearTemplateBlockCache( $objectID ); 00724 } 00725 00726 /*! 00727 \static 00728 Clears template-block cache and template-block with subtree_expiry parameter caches for specified object 00729 without checking 'TemplateCache' ini setting. If $objectID is \c false all template block caches will be cleared. 00730 */ 00731 static function clearTemplateBlockCache( $objectID ) 00732 { 00733 // ordinary template block cache 00734 eZContentObject::expireTemplateBlockCache(); 00735 00736 // subtree template block cache 00737 $nodeList = false; 00738 $object = false; 00739 if ( $objectID ) 00740 $object = eZContentObject::fetch( $objectID ); 00741 if ( $object ) 00742 $nodeList = $object->assignedNodes(); 00743 00744 //include_once( 'kernel/classes/ezsubtreecache.php' ); 00745 eZSubtreeCache::cleanup( $nodeList ); 00746 } 00747 00748 /*! 00749 \static 00750 Generates the related viewcaches (PreGeneration) for the content object. 00751 It will only do this if [ContentSettings]/PreViewCache in site.ini is enabled. 00752 00753 \param $objectID The ID of the content object to generate caches for. 00754 */ 00755 static function generateObjectViewCache( $objectID ) 00756 { 00757 // Generate the view cache 00758 $ini = eZINI::instance(); 00759 $object = eZContentObject::fetch( $objectID ); 00760 $user = eZUser::currentUser(); 00761 00762 //include_once( 'kernel/classes/eznodeviewfunctions.php' ); 00763 eZDebug::accumulatorStart( 'generate_cache', '', 'Generating view cache' ); 00764 if ( $ini->variable( 'ContentSettings', 'PreViewCache' ) == 'enabled' ) 00765 { 00766 $preCacheSiteaccessArray = $ini->variable( 'ContentSettings', 'PreCacheSiteaccessArray' ); 00767 00768 $currentSiteAccess = $GLOBALS['eZCurrentAccess']['name']; 00769 00770 // This is the default view parameters for content/view 00771 $viewParameters = array( 'offset' => 0, 00772 'year' => false, 00773 'month' => false, 00774 'day' => false, 00775 'namefilter' => false ); 00776 if ( is_array( $preCacheSiteaccessArray ) && count( $preCacheSiteaccessArray ) > 0 ) 00777 { 00778 foreach ( $preCacheSiteaccessArray as $changeToSiteAccess ) 00779 { 00780 $GLOBALS['eZCurrentAccess']['name'] = $changeToSiteAccess; 00781 00782 if ( $GLOBALS['eZCurrentAccess']['type'] == EZ_ACCESS_TYPE_URI ) 00783 { 00784 eZSys::clearAccessPath(); 00785 eZSys::addAccessPath( $changeToSiteAccess ); 00786 } 00787 00788 require_once( 'kernel/common/template.php' ); 00789 $tpl = templateInit(); 00790 $res = eZTemplateDesignResource::instance(); 00791 00792 // Get the sitedesign and cached view preferences for this siteaccess 00793 $siteini = eZINI::instance( 'site.ini', 'settings', null, null, false ); 00794 $siteini->prependOverrideDir( "siteaccess/$changeToSiteAccess", false, 'siteaccess' ); 00795 $siteini->loadCache(); 00796 $designSetting = $siteini->variable( "DesignSettings", "SiteDesign" ); 00797 $cachedViewPreferences = $siteini->variable( 'ContentSettings', 'CachedViewPreferences' ); 00798 $res->setDesignSetting( $designSetting, 'site' ); 00799 00800 $res->setOverrideAccess( $changeToSiteAccess ); 00801 00802 $language = false; // Needs to be specified if you want to generate the cache for a specific language 00803 $viewMode = 'full'; 00804 00805 $assignedNodes = $object->assignedNodes(); 00806 foreach ( $assignedNodes as $node ) 00807 { 00808 // We want to generate the cache for the specified user 00809 $previewCacheUsers = $ini->variable( 'ContentSettings', 'PreviewCacheUsers' ); 00810 foreach ( $previewCacheUsers as $previewCacheUserID ) 00811 { 00812 // If the text is 'anon' we need to fetch the Anonymous user ID. 00813 if ( $previewCacheUserID === 'anonymous' ) 00814 { 00815 $previewCacheUserID = $siteini->variable( "UserSettings", "AnonymousUserID" ); 00816 $previewCacheUser = eZUser::fetch( $previewCacheUserID ); 00817 } 00818 else if ( $previewCacheUserID === 'current' ) 00819 { 00820 $previewCacheUser = $user; 00821 } 00822 else 00823 { 00824 $previewCacheUser = eZUser::fetch( $previewCacheUserID ); 00825 } 00826 if ( !$previewCacheUser ) 00827 continue; 00828 00829 // Before we generate the view cache we must change the currently logged in user to $previewCacheUser 00830 // If not the templates might read in wrong personalized data (preferences etc.) 00831 $previewCacheUser->setCurrentlyLoggedInUser( $previewCacheUser, $previewCacheUser->attribute( 'contentobject_id' ) ); 00832 00833 // Cache the current node 00834 $cacheFileArray = eZNodeviewfunctions::generateViewCacheFile( $previewCacheUser, $node->attribute( 'node_id' ), 0, false, $language, $viewMode, $viewParameters, $cachedViewPreferences ); 00835 $tmpRes = eZNodeviewfunctions::generateNodeView( $tpl, $node, $node->attribute( 'object' ), $language, $viewMode, 0, $cacheFileArray['cache_dir'], $cacheFileArray['cache_path'], true, $viewParameters ); 00836 00837 // Cache the parent node 00838 $parentNode = $node->attribute( 'parent' ); 00839 $objectID = $parentNode->attribute( 'contentobject_id' ); 00840 // if parent objectID is null or is 0 we should not create cache. 00841 if ( $objectID ) 00842 { 00843 $cacheFileArray = eZNodeviewfunctions::generateViewCacheFile( $previewCacheUser, $parentNode->attribute( 'node_id' ), 0, false, $language, $viewMode, $viewParameters, $cachedViewPreferences ); 00844 $tmpRes = eZNodeviewfunctions::generateNodeView( $tpl, $parentNode, $parentNode->attribute( 'object' ), $language, $viewMode, 0, $cacheFileArray['cache_dir'], $cacheFileArray['cache_path'], true, $viewParameters ); 00845 } 00846 } 00847 } 00848 } 00849 // Restore the old user as the current one 00850 $user->setCurrentlyLoggedInUser( $user, $user->attribute( 'contentobject_id' ) ); 00851 00852 $GLOBALS['eZCurrentAccess']['name'] = $currentSiteAccess; 00853 $res->setDesignSetting( $currentSiteAccess, 'site' ); 00854 $res->setOverrideAccess( false ); 00855 00856 if ( $GLOBALS['eZCurrentAccess']['type'] == EZ_ACCESS_TYPE_URI ) 00857 { 00858 eZSys::clearAccessPath(); 00859 eZSys::addAccessPath( $currentSiteAccess ); 00860 } 00861 } 00862 } 00863 00864 if ( $ini->variable( 'ContentSettings', 'StaticCache' ) == 'enabled' ) 00865 { 00866 //include_once( 'kernel/classes/ezstaticcache.php' ); 00867 00868 $nodes = array(); 00869 $ini = eZINI::instance(); 00870 $staticCache = new eZStaticCache(); 00871 $useURLAlias =& $GLOBALS['eZContentObjectTreeNodeUseURLAlias']; 00872 $pathPrefix = $ini->variable( 'SiteAccessSettings', 'PathPrefix' ); 00873 00874 if ( !isset( $useURLAlias ) ) 00875 { 00876 $useURLAlias = $ini->variable( 'URLTranslator', 'Translation' ) == 'enabled'; 00877 } 00878 00879 eZContentCacheManager::nodeListForObject( $object, true, self::CLEAR_DEFAULT, $nodes, $handledObjectList ); 00880 00881 // If no nodes returns it means that ClearCacheMethod = self::CLEAR_NO_CACHE 00882 if ( count( $nodes ) ) 00883 { 00884 foreach ( $nodes as $nodeID ) 00885 { 00886 if ( $useURLAlias ) 00887 { 00888 $oNode = eZContentObjectTreeNode::fetch( $nodeID, false, true ); 00889 if ( !isset( $oNode ) ) 00890 continue; 00891 00892 $urlAlias = $oNode->urlAlias(); 00893 if ( $pathPrefix != '' ) 00894 { 00895 $tempAlias = substr( $pathPrefix, strlen( $pathPrefix ) -1 ) == '/' 00896 ? $urlAlias . '/' 00897 : $urlAlias; 00898 if ( strncmp( $tempAlias, $pathPrefix, strlen( $tempAlias) ) == 0 ) 00899 $urlAlias = substr( $tempAlias, strlen( $pathPrefix ) ); 00900 } 00901 } 00902 else 00903 { 00904 $urlAlias = 'content/view/full/' . $nodeID; 00905 } 00906 $staticCache->cacheURL( '/' . $urlAlias, $nodeID ); 00907 } 00908 $staticCache->generateAlwaysUpdatedCache(); 00909 } 00910 } 00911 eZDebug::accumulatorStop( 'generate_cache' ); 00912 } 00913 00914 /*! 00915 \static 00916 Clears content cache if needed by \a $sectionID 00917 */ 00918 static function clearContentCacheIfNeededBySectionID( $sectionID ) 00919 { 00920 // fetch all objects of this section 00921 $objectList = eZContentObject::fetchList( false, array( 'section_id' => "$sectionID" ) ); 00922 // Clear cache 00923 foreach ( $objectList as $object ) 00924 { 00925 eZContentCacheManager::clearContentCacheIfNeeded( $object['id'] ); 00926 } 00927 return true; 00928 } 00929 00930 /*! 00931 \static 00932 Clears content cache for specified object: view cache, template-block cache, template-block with subtree_expiry parameter cache. 00933 Checks appropriate ini settings to determine whether caches are enabled or not. 00934 */ 00935 static function clearContentCacheIfNeeded( $objectID, $versionNum = true, $additionalNodeList = false ) 00936 { 00937 eZDebug::accumulatorStart( 'check_cache', '', 'Check cache' ); 00938 00939 eZContentCacheManager::clearObjectViewCacheIfNeeded( $objectID, $versionNum, $additionalNodeList ); 00940 eZContentCacheManager::clearTemplateBlockCacheIfNeeded( $objectID ); 00941 00942 // Clear cached path strings of content SSL zones. 00943 //include_once( 'kernel/classes/ezsslzone.php' ); 00944 eZSSLZone::clearCacheIfNeeded(); 00945 00946 eZDebug::accumulatorStop( 'check_cache' ); 00947 return true; 00948 } 00949 00950 /*! 00951 \static 00952 Clears content cache for specified object: view cache, template-block cache, template-block with subtree_expiry parameter cache 00953 without checking of ini settings. 00954 */ 00955 static function clearContentCache( $objectID, $versionNum = true, $additionalNodeList = false ) 00956 { 00957 eZDebug::accumulatorStart( 'check_cache', '', 'Check cache' ); 00958 00959 eZContentCacheManager::clearObjectViewCache( $objectID, $versionNum, $additionalNodeList ); 00960 eZContentCacheManager::clearTemplateBlockCache( $objectID ); 00961 00962 // Clear cached path strings of content SSL zones. 00963 //include_once( 'kernel/classes/ezsslzone.php' ); 00964 eZSSLZone::clearCache(); 00965 00966 eZDebug::accumulatorStop( 'check_cache' ); 00967 return true; 00968 } 00969 00970 /*! 00971 \static 00972 Clears all content cache: view cache, template-block cache, template-block with subtree_expiry parameter cache. 00973 */ 00974 static function clearAllContentCache( $ignoreINISettings = false ) 00975 { 00976 if ( !$ignoreINISettings ) 00977 { 00978 $ini = eZINI::instance(); 00979 $viewCacheEnabled = ( $ini->variable( 'ContentSettings', 'ViewCaching' ) === 'enabled' ); 00980 $templateCacheEnabled = ( $ini->variable( 'TemplateSettings', 'TemplateCache' ) === 'enabled' ); 00981 } 00982 else 00983 { 00984 $viewCacheEnabled = true; 00985 $templateCacheEnabled = true; 00986 } 00987 00988 if ( $viewCacheEnabled || $templateCacheEnabled ) 00989 { 00990 // view cache and/or ordinary template block cache 00991 eZContentObject::expireAllCache(); 00992 00993 // subtree template block caches 00994 if ( $templateCacheEnabled ) 00995 { 00996 //include_once( 'kernel/classes/ezsubtreecache.php' ); 00997 eZSubtreeCache::cleanupAll(); 00998 } 00999 } 01000 } 01001 } 01002 01003 ?>