eZ Publish  [4.0]
ezcontentcachemanager.php
Go to the documentation of this file.
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 ?>