|
eZ Publish
[4.0]
|
00001 <?php 00002 // 00003 // Definition of eZTemplateCacheBlock class 00004 // 00005 // Created on: <27-Mar-2007 11:20:14 amos> 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 /*! 00032 \class eZTemplateCacheBlock eztemplatecacheblock.php 00033 \brief Cache block 00034 00035 */ 00036 00037 class eZTemplateCacheBlock 00038 { 00039 /*! 00040 Helper function for retrieving a cache-block entry which can be used by any custom code. 00041 00042 \param $keys Array or string which is used for key. To ensure uniqueness prefix or add an entry which is unique to your code. 00043 \param $subtreeExpiry The subtree expiry value, use null to disable or a string. See subtreeCacheSubDir for more details. 00044 \param $ttl Amount of seconds the cache should live, use null, 0 or -1 to disable TTL. 00045 \param $useGlobalExpiry Boolean which controls if the global content expiry value should be used or not. 00046 00047 Returns an array with the file handler objects as the first entry and the content data as the second. 00048 If the content could not be retrieved the content contains the object eZClusterFileFailure. 00049 00050 00051 Example of usage: 00052 \code 00053 list($handler, $data) = eZTemplateCacheBlock::retrieve( array( 'my_cool_key', $id, ), $nodeID, 60 ); // lives 60 seconds 00054 if ( !$data instanceof eZClusterFileFailure ) 00055 { 00056 echo $data; 00057 } 00058 else 00059 { 00060 // ... generate the data 00061 $data = '...'; 00062 $handler->storeCache( array( 'scope' => 'template-block', 00063 'binarydata' => $data ) ); 00064 } 00065 \endcode 00066 00067 Note: Because of the cluster code the storeCache() call must occur to ensure stability. 00068 00069 */ 00070 static function retrieve( $keys, $subtreeExpiry, $ttl, $useGlobalExpiry = true ) 00071 { 00072 $nodeID = $subtreeExpiry ? eZTemplateCacheBlock::decodeNodeID( $subtreeExpiry ) : false; 00073 $cachePath = eZTemplateCacheBlock::cachePath( eZTemplateCacheBlock::keyString( $keys ), $nodeID ); 00074 return eZTemplateCacheBlock::handle( $cachePath, $nodeID, $ttl, $useGlobalExpiry ); 00075 } 00076 00077 /*! 00078 \static 00079 Helper function for the compiled code, similar to retrieve() but requires the $cachePath to be calculated up front. 00080 */ 00081 static function handle( $cachePath, $nodeID, $ttl, $useGlobalExpiry = true ) 00082 { 00083 $globalExpiryTime = -1; 00084 eZExpiryHandler::registerShutdownFunction(); 00085 if ( $useGlobalExpiry ) 00086 { 00087 $globalExpiryTime = eZExpiryHandler::getTimestamp( 'template-block-cache', -1 ); 00088 } 00089 00090 require_once( 'kernel/classes/ezclusterfilehandler.php' ); 00091 $cacheHandler = eZClusterFileHandler::instance( $cachePath ); 00092 00093 $subtreeExpiry = -1; 00094 // Perform an extra check if the DB handler is in use, 00095 // get the modified_subnode value from the specified node ($nodeID) 00096 // and use it as an extra expiry value. 00097 if ( $cacheHandler instanceof eZDBFileHandler ) 00098 { 00099 $subtreeExpiry = eZTemplateCacheBlock::getSubtreeModification( $nodeID ); 00100 } 00101 $globalExpiryTime = max( eZExpiryHandler::getTimestamp( 'global-template-block-cache', -1 ), // This expiry value is the true global expiry for cache-blocks 00102 $globalExpiryTime, 00103 $subtreeExpiry ); 00104 00105 if ( $ttl == 0 ) 00106 $ttl = -1; 00107 return array( &$cacheHandler, 00108 $cacheHandler->processCache( array( 'eZTemplateCacheBlock', 'retrieveContent' ), null, 00109 $ttl, $globalExpiryTime ) ); 00110 } 00111 00112 /*! 00113 Figures out the modification time for the subtree by looking up the database using $nodeID. 00114 If $nodeID is set to false no lookup is done and it will return -1. 00115 */ 00116 static function getSubtreeModification( $nodeID ) 00117 { 00118 if ( $nodeID === false ) 00119 return -1; 00120 $nodeID = (int)$nodeID; 00121 $sql = "SELECT modified_subnode FROM ezcontentobject_tree WHERE node_id=$nodeID"; 00122 //include_once( 'lib/ezdb/classes/ezdb.php' ); 00123 $db = eZDB::instance(); 00124 $rows = $db->arrayQuery( $sql ); 00125 if ( count( $rows ) > 0 ) 00126 return $rows[0]['modified_subnode']; 00127 return -1; 00128 } 00129 00130 /*! 00131 \static 00132 Calculates the key entry for the function placement array $functionPlacement and returns it. 00133 00134 \note This function is placed in this class to reduce the need to load the class eZTemplateCacheFunction 00135 when the templates are compiled. This reduces memory usage. 00136 */ 00137 static function placementString( $functionPlacement ) 00138 { 00139 $placementString = $functionPlacement[0][0] . "_"; 00140 $placementString .= $functionPlacement[0][1] . "_"; 00141 $placementString .= $functionPlacement[1][0] . "_"; 00142 $placementString .= $functionPlacement[1][1] . "_"; 00143 $placementString .= $functionPlacement[2]; 00144 return $placementString; 00145 } 00146 00147 /*! 00148 \static 00149 Calculates the key string from the key values $keys. 00150 00151 Note: Arrays are traversed recursively. 00152 */ 00153 static function keyString( $keys ) 00154 { 00155 return serialize( $keys ); 00156 } 00157 00158 /*! 00159 \static 00160 Calculates the cache path based on the key string $keyString and $nodeID. 00161 00162 See subtreeCacheSubDir() for more details on the $nodeID parameter. 00163 */ 00164 static function cachePath( $keyString, $nodeID = false ) 00165 { 00166 //include_once( 'lib/ezutils/classes/ezsys.php' ); 00167 $filename = eZSys::ezcrc32( $keyString ) . ".cache"; 00168 00169 $phpDir = eZTemplateCacheBlock::templateBlockCacheDir(); 00170 if ( is_numeric( $nodeID ) ) 00171 { 00172 $phpDir .= eZTemplateCacheBlock::calculateSubtreeCacheDir( $nodeID, $filename ); 00173 } 00174 else 00175 { 00176 $phpDir .= $filename[0] . '/' . $filename[1] . '/' . $filename[2]; 00177 } 00178 00179 $phpPath = $phpDir . '/' . $filename; 00180 return $phpPath; 00181 } 00182 00183 /*! 00184 \static 00185 Returns base directory where template block caches are stored. 00186 */ 00187 static function templateBlockCacheDir() 00188 { 00189 $cacheDir = eZSys::cacheDirectory() . '/template-block/' ; 00190 return $cacheDir; 00191 } 00192 00193 /*! 00194 \static 00195 Figures out the node ID for the $subtreeExpiryParameter. 00196 00197 The parameter $subtreeExpiryParameter is expiry value is usually taken from the template operator and can be one of: 00198 - A numerical value which represents the node ID (the fastest approach) 00199 - A string containing 'content/view/full/xxx' where xx is the node ID number, the number will be extracted. 00200 - A string containing a nice url which will be decoded into a node ID using the database (slowest approach). 00201 */ 00202 static function decodeNodeID( $subtreeExpiryParameter ) 00203 { 00204 $nodeID = false; 00205 if ( !is_numeric( $subtreeExpiryParameter ) ) 00206 { 00207 $nodePathString = ''; 00208 00209 // clean up $subtreeExpiryParameter 00210 $subtreeExpiryParameter = trim( $subtreeExpiryParameter, '/' ); 00211 00212 $nodeID = false; 00213 $subtree = $subtreeExpiryParameter; 00214 00215 if ( $subtree == '' ) 00216 { 00217 // 'subtree_expiry' is empty => use root node. 00218 $nodeID = 2; 00219 } 00220 else 00221 { 00222 $nonAliasPath = 'content/view/full/'; 00223 00224 if ( strpos( $subtree, $nonAliasPath ) === 0 ) 00225 { 00226 // 'subtree_expiry' is like 'content/view/full/2' 00227 $nodeID = (int)substr( $subtree, strlen( $nonAliasPath ) ); 00228 } 00229 else 00230 { 00231 // 'subtree_expiry' is url_alias 00232 $nodeID = eZURLAliasML::fetchNodeIDByPath( $subtree ); 00233 if ( !$nodeID ) 00234 { 00235 eZDebug::writeError( "Could not find path_string '$subtree' for 'subtree_expiry' node.", 'eZTemplateCacheBlock::subtreeExpiryCacheDir()' ); 00236 } 00237 else 00238 { 00239 $nodeID = (int)$nodeID; 00240 } 00241 } 00242 } 00243 } 00244 else 00245 { 00246 $nodeID = (int)$subtreeExpiryParameter; 00247 } 00248 return $nodeID; 00249 } 00250 00251 /*! 00252 \static 00253 Returns path of the directory where 'subtree_expiry' caches are stored. 00254 00255 See decodeNodeID() for details on the $subtreeExpiryParameter parameter. 00256 */ 00257 static function calculateSubtreeCacheDir( $nodeID, $cacheFilename ) 00258 { 00259 $cacheDir = eZTemplateCacheBlock::subtreeCacheSubDirForNode( $nodeID ); 00260 $cacheDir .= '/' . $cacheFilename[0] . '/' . $cacheFilename[1] . '/' . $cacheFilename[2]; 00261 00262 return $cacheDir; 00263 } 00264 00265 /*! 00266 \static 00267 Returns path of the directory where 'subtree_expiry' caches are stored. 00268 00269 See decodeNodeID() for details on the $subtreeExpiryParameter parameter. 00270 00271 \note If you know the node ID you can use calculateSubtreeCacheDir() instead. 00272 */ 00273 static function subtreeCacheSubDir( $subtreeExpiryParameter, $cacheFilename ) 00274 { 00275 $nodeID = eZTemplateCacheBlock::decodeNodeID( $subtreeExpiryParameter ); 00276 return eZTemplateCacheBlock::calculateSubtreeCacheDir( $nodeID, $cacheFilename ); 00277 } 00278 00279 /*! 00280 \static 00281 Builds and returns path from $nodeID, e.g. if $nodeID = 23 then path = subtree/2/3 00282 */ 00283 static function subtreeCacheSubDirForNode( $nodeID ) 00284 { 00285 $cacheDir = eZTemplateCacheBlock::subtreeCacheBaseSubDir(); 00286 00287 if ( is_numeric( $nodeID ) ) 00288 { 00289 $nodeID = (string)$nodeID; 00290 $length = strlen( $nodeID ); 00291 $pos = 0; 00292 while ( $pos < $length ) 00293 { 00294 $cacheDir .= '/' . $nodeID[$pos]; 00295 ++$pos; 00296 } 00297 } 00298 else 00299 { 00300 eZDebug::writeWarning( "Unable to determine cacheDir for nodeID = $nodeID", 'eZtemplateCacheFunction::subtreeCacheSubDirForNode' ); 00301 } 00302 00303 $cacheDir .= '/cache'; 00304 return $cacheDir; 00305 } 00306 00307 /*! 00308 \static 00309 Returns base directory where 'subtree_expiry' caches are stored. 00310 */ 00311 static function subtreeCacheBaseSubDir() 00312 { 00313 return 'subtree'; 00314 } 00315 00316 /*! 00317 \static 00318 Callback function to get the contents of the specified filename. 00319 00320 \param $fname Name of file 00321 \param $mtime Modified time of file. 00322 */ 00323 static function retrieveContent( $fname, $mtime ) 00324 { 00325 return file_get_contents( $fname ); 00326 } 00327 } 00328 00329 ?>