|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZTemplateDesignResource class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package kernel 00009 */ 00010 00011 /*! 00012 \class eZTemplatedesignresource eztemplatedesignresource.php 00013 \brief Handles template file loading with override support 00014 00015 */ 00016 00017 class eZTemplateDesignResource extends eZTemplateFileResource 00018 { 00019 const DESIGN_BASE_CACHE_NAME = 'designbase_'; 00020 00021 /** 00022 * Contains in memory cache of override array used by {@link eZTemplateDesignResource::overrideArray()} 00023 * 00024 * @static 00025 * @protected 00026 * @var $overrideArrayCache null|array 00027 */ 00028 protected static $overrideArrayCache = null; 00029 00030 /*! 00031 Initializes with a default resource name "design". 00032 */ 00033 function eZTemplateDesignResource( $name = "design" ) 00034 { 00035 $this->eZTemplateFileResource( $name, true ); 00036 $this->Keys = array(); 00037 $this->KeyStack = array(); 00038 } 00039 00040 function templateNodeTransformation( $functionName, &$node, 00041 $tpl, &$resourceData, $parameters, $namespaceValue ) 00042 { 00043 if ( $this->Name != 'design' and $this->Name != 'standard' ) 00044 return false; 00045 00046 $file = $resourceData['template-name']; 00047 $matchFileArray = eZTemplateDesignResource::overrideArray( $this->OverrideSiteAccess ); 00048 $matchList = array(); 00049 foreach ( $matchFileArray as $matchFile ) 00050 { 00051 if ( !isset( $matchFile['template'] ) ) 00052 continue; 00053 if ( $matchFile['template'] == ('/' . $file) ) 00054 { 00055 $matchList[] = $matchFile; 00056 } 00057 } 00058 00059 $resourceName = $resourceData['resource']; 00060 $resourceNameText = eZPHPCreator::variableText( $resourceName ); 00061 00062 $designKeysName = 'dKeys'; 00063 if ( $resourceName == 'standard' ) 00064 $designKeysName = 'rKeys'; 00065 00066 $newNodes = array(); 00067 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if " . ( $resourceData['use-comments'] ? ( "/*TDR:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$$designKeysName ) )\n" . 00068 "{\n" . 00069 " \$resH = \$tpl->resourceHandler( $resourceNameText );\n" . 00070 " \$$designKeysName = \$resH->keys();" . 00071 "\n" . 00072 "}\n" ); 00073 foreach ( $matchList as $match ) 00074 { 00075 $basedir = $match['base_dir']; 00076 $template = $match['template']; 00077 $file = $basedir . $template; 00078 $spacing = 0; 00079 $addFileResource = true; 00080 if ( isset( $match['custom_match'] ) ) 00081 { 00082 $spacing = 4; 00083 $customMatchList = $match['custom_match']; 00084 $matchCount = 0; 00085 foreach ( $customMatchList as $customMatch ) 00086 { 00087 $matchConditionCount = count( $customMatch['conditions'] ); 00088 $code = ''; 00089 if ( $matchCount > 0 ) 00090 { 00091 $code = "else " . ( $resourceData['use-comments'] ? ( "/*TDR:" . __LINE__ . "*/" ) : "" ) . ""; 00092 } 00093 if ( $matchConditionCount > 0 ) 00094 { 00095 if ( $matchCount > 0 ) 00096 $code .= " "; 00097 $code .= "if " . ( $resourceData['use-comments'] ? ( "/*TDR:" . __LINE__ . "*/" ) : "" ) . "( "; 00098 } 00099 $ifLength = strlen( $code ); 00100 $conditionCount = 0; 00101 if ( is_array( $customMatch['conditions'] ) ) 00102 { 00103 foreach ( $customMatch['conditions'] as $conditionName => $conditionValue ) 00104 { 00105 if ( $conditionCount > 0 ) 00106 $code .= " and\n" . str_repeat( ' ', $ifLength ); 00107 $conditionNameText = eZPHPCreator::variableText( $conditionName, 0 ); 00108 $conditionValueText = eZPHPCreator::variableText( $conditionValue, 0 ); 00109 00110 $code .= "isset( \$" . $designKeysName . "[$conditionNameText] ) and "; 00111 if ( $conditionName == 'url_alias' ) 00112 { 00113 $code .= "(strpos( \$" . $designKeysName . "[$conditionNameText], $conditionValueText ) === 0 )"; 00114 } 00115 else 00116 { 00117 $code .= "( is_array( \$" . $designKeysName . "[$conditionNameText] ) ? " . 00118 "in_array( $conditionValueText, \$" . $designKeysName . "[$conditionNameText] ) : " . 00119 "\$" . $designKeysName . "[$conditionNameText] == $conditionValueText )"; 00120 } 00121 ++$conditionCount; 00122 } 00123 } 00124 if ( $matchConditionCount > 0 ) 00125 { 00126 $code .= " )\n"; 00127 } 00128 if ( $matchConditionCount > 0 or $matchCount > 0 ) 00129 { 00130 $code .= "{"; 00131 } 00132 $matchFile = $customMatch['match_file']; 00133 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( $code ); 00134 $newNodes[] = eZTemplateNodeTool::createResourceAcquisitionNode( '', 00135 $matchFile, $matchFile, 00136 eZTemplate::RESOURCE_FETCH, false, 00137 $node[4], array( 'spacing' => $spacing ), 00138 $namespaceValue ); 00139 if ( $matchConditionCount > 0 or $matchCount > 0 ) 00140 { 00141 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}" ); 00142 } 00143 ++$matchCount; 00144 if ( $matchConditionCount == 0 ) 00145 { 00146 $addFileResource = false; 00147 break; 00148 } 00149 } 00150 if ( $addFileResource ) 00151 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "else" . ( $resourceData['use-comments'] ? ( "/*TDR:" . __LINE__ . "*/" ) : "" ) . "\n{" ); 00152 } 00153 if ( $addFileResource ) 00154 { 00155 $newNodes[] = eZTemplateNodeTool::createResourceAcquisitionNode( '', 00156 $file, $file, 00157 eZTemplate::RESOURCE_FETCH, false, 00158 $node[4], array( 'spacing' => $spacing ), 00159 $namespaceValue ); 00160 } 00161 if ( isset( $match['custom_match'] ) and $addFileResource ) 00162 $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}" ); 00163 } 00164 00165 return $newNodes; 00166 } 00167 00168 /*! 00169 \static 00170 \return the sitedesign for the design type \a $type, currently \c standard and \c site is allowed. 00171 If no sitedesign is set it will fetch it from site.ini. 00172 */ 00173 static function designSetting( $type = 'standard' ) 00174 { 00175 if ( $type != 'standard' and 00176 $type != 'site' ) 00177 { 00178 eZDebug::writeWarning( "Cannot retrieve designsetting for type '$type'", __METHOD__ ); 00179 return null; 00180 } 00181 if ( $type == 'site' ) 00182 { 00183 if ( !empty( $GLOBALS['eZSiteBasics']['site-design-override'] ) ) 00184 { 00185 return $GLOBALS['eZSiteBasics']['site-design-override']; 00186 } 00187 } 00188 if ( isset( $GLOBALS['eZTemplateDesignSetting'][$type] ) ) 00189 { 00190 return $GLOBALS['eZTemplateDesignSetting'][$type]; 00191 } 00192 $ini = eZINI::instance(); 00193 if ( $type == 'standard' ) 00194 { 00195 $GLOBALS['eZTemplateDesignSetting'][$type] = $ini->variable( "DesignSettings", "StandardDesign" ); 00196 } 00197 else if ( $type == 'site' ) 00198 { 00199 $GLOBALS['eZTemplateDesignSetting'][$type] = $ini->variable( "DesignSettings", "SiteDesign" ); 00200 } 00201 return $GLOBALS['eZTemplateDesignSetting'][$type]; 00202 } 00203 00204 /*! 00205 Sets the sitedesign for the design type \a $type, currently \c standard and \c site is allowed. 00206 The design is set to \a $designSetting. 00207 */ 00208 function setDesignSetting( $designSetting, $type = 'standard' ) 00209 { 00210 if ( $type != 'standard' and 00211 $type != 'site' ) 00212 { 00213 eZDebug::writeWarning( "Cannot set designsetting '$designSetting' for type '$type'", __METHOD__ ); 00214 return; 00215 } 00216 if ( !isset( $GLOBALS['eZTemplateDesignSetting'] ) ) 00217 { 00218 $GLOBALS['eZTemplateDesignSetting'] = array(); 00219 } 00220 $GLOBALS['eZTemplateDesignSetting'][$type] = $designSetting; 00221 } 00222 00223 /*! 00224 \static 00225 00226 */ 00227 static function fileMatch( $bases, $element, $path, &$triedFiles ) 00228 { 00229 $bases = array_unique( $bases ); 00230 foreach ( $bases as $base ) 00231 { 00232 $resource = $element != '' ? "$base/$element" : $base; 00233 $possibleMatchFile = $resource . '/' . $path; 00234 00235 $triedFiles[] = $possibleMatchFile; 00236 00237 if ( file_exists( $possibleMatchFile ) ) 00238 { 00239 return array( 'resource' => $resource, 00240 'path' => $possibleMatchFile ); 00241 } 00242 } 00243 00244 return false; 00245 } 00246 00247 /*! 00248 Loads the template file if it exists, also sets the modification timestamp. 00249 Returns true if the file exists. 00250 */ 00251 function handleResource( $tpl, &$resourceData, $method, &$extraParameters ) 00252 { 00253 $path = $resourceData['template-name']; 00254 00255 $matchKeys = $this->Keys; 00256 if ( isset( $GLOBALS['eZDesignKeys'] ) ) 00257 { 00258 $matchKeys = array_merge( $matchKeys, $GLOBALS['eZDesignKeys'] ); 00259 unset( $GLOBALS['eZDesignKeys'] ); 00260 $this->Keys = $matchKeys; 00261 } 00262 if ( is_array( $extraParameters ) and 00263 isset( $extraParameters['ezdesign:keys'] ) ) 00264 { 00265 $this->mergeKeys( $matchKeys, $extraParameters['ezdesign:keys'] ); 00266 } 00267 $this->KeyStack[] = $this->Keys; 00268 $this->Keys = $matchKeys; 00269 00270 eZDebug::accumulatorStart( 'override_cache', 'Override', 'Cache load' ); 00271 00272 if( !isset( $GLOBALS['eZOverrideTemplateCacheMap'] ) ) 00273 { 00274 $overrideCacheFile = $this->createOverrideCache(); 00275 00276 if ( $overrideCacheFile ) 00277 { 00278 include_once( $overrideCacheFile ); 00279 } 00280 } 00281 00282 if ( isset( $GLOBALS['eZOverrideTemplateCacheMap'] ) ) 00283 { 00284 if( isset( $GLOBALS['eZOverrideTemplateCacheMap'][md5( '/' . $path )] ) ) 00285 { 00286 $cacheMap = $GLOBALS['eZOverrideTemplateCacheMap'][md5( '/' . $path )]; 00287 if ( !is_string( $cacheMap ) and trim( $cacheMap['code'] ) ) 00288 { 00289 eval( "\$matchFile = " . $cacheMap['code'] . ";" ); 00290 } 00291 else 00292 { 00293 $matchFile = $cacheMap; 00294 } 00295 $match['file'] = $matchFile; 00296 } 00297 } 00298 else 00299 { 00300 $template = "/" . $path; 00301 $matchFileArray = eZTemplateDesignResource::overrideArray( $this->OverrideSiteAccess ); 00302 00303 $matchFile = $matchFileArray[$template]; 00304 00305 if ( isset( $matchFile['custom_match'] ) ) 00306 { 00307 $matchFound = false; 00308 foreach ( $matchFile['custom_match'] as $customMatch ) 00309 { 00310 $matchOverride = true; 00311 if ( count( $customMatch['conditions'] ) > 0 ) 00312 { 00313 foreach ( array_keys( $customMatch['conditions'] ) as $conditionKey ) 00314 { 00315 // Create special substring match for subtree override 00316 if ( $conditionKey == 'url_alias' ) 00317 { 00318 if ( strpos( $matchKeys['url_alias'], $customMatch['conditions'][$conditionKey] ) === 0 ) 00319 { 00320 } 00321 else 00322 { 00323 $matchOverride = false; 00324 } 00325 } 00326 else if ( isset( $matchKeys[$conditionKey] ) and 00327 isset( $customMatch['conditions'][$conditionKey] ) ) 00328 { 00329 if ( is_array( $matchKeys[$conditionKey] ) ) 00330 { 00331 if ( !in_array( $customMatch['conditions'][$conditionKey], $matchKeys[$conditionKey] ) ) 00332 { 00333 $matchOverride = false; 00334 } 00335 } 00336 else if ( $matchKeys[$conditionKey] != $customMatch['conditions'][$conditionKey] ) 00337 { 00338 $matchOverride = false; 00339 } 00340 } 00341 else 00342 { 00343 $matchOverride = false; 00344 } 00345 } 00346 if ( $matchOverride == true ) 00347 { 00348 $match['file'] = $customMatch['match_file']; 00349 $matchFound = true; 00350 break; 00351 } 00352 else 00353 { 00354 } 00355 } 00356 else 00357 { 00358 // Default match without conditions 00359 $match['file'] = $customMatch['match_file']; 00360 $matchFound = true; 00361 } 00362 } 00363 if ( !$matchFound ) 00364 $match['file'] = $matchFile['base_dir'] . $matchFile['template']; 00365 } 00366 else 00367 { 00368 $match['file'] = $matchFile['base_dir'] . $matchFile['template']; 00369 } 00370 } 00371 eZDebug::accumulatorStop( 'override_cache' ); 00372 if ( isset( $match ) ) 00373 { 00374 $file = $match["file"]; 00375 00376 $matchedKeys = array(); 00377 $usedKeys = array(); 00378 foreach ( $matchKeys as $matchKeyName => $matchKeyValue ) 00379 { 00380 $usedKeys[$matchKeyName] = $matchKeyValue; 00381 } 00382 $extraParameters['ezdesign:used_keys'] = $usedKeys; 00383 $extraParameters['ezdesign:matched_keys'] = $matchedKeys; 00384 $tpl->setVariable( 'used', $usedKeys, 'DesignKeys' ); 00385 $tpl->setVariable( 'matched', $matchedKeys, 'DesignKeys' ); 00386 $resourceData['template-filename'] = $file; 00387 $result = eZTemplateFileResource::handleResourceData( $tpl, $this, $resourceData, $method, $extraParameters ); 00388 } 00389 else 00390 { 00391 $result = false; 00392 } 00393 $this->Keys = array_pop( $this->KeyStack ); 00394 return $result; 00395 } 00396 00397 /*! 00398 Generates the cache for the template override matching. 00399 */ 00400 function createOverrideCache() 00401 { 00402 if ( isset( $GLOBALS['eZSiteBasics'] ) ) 00403 { 00404 if ( isset( $GLOBALS['eZSiteBasics']['no-cache-adviced'] ) and 00405 $GLOBALS['eZSiteBasics']['no-cache-adviced'] ) 00406 return false; 00407 } 00408 global $eZTemplateOverrideCacheNoPermission; 00409 if ( $eZTemplateOverrideCacheNoPermission == "nocache" ) 00410 { 00411 return false; 00412 } 00413 00414 $ini = eZINI::instance( 'site.ini' ); 00415 $useOverrideCache = true; 00416 if ( $ini->hasVariable( 'OverrideSettings', 'Cache' ) ) 00417 $useOverrideCache = $ini->variable( 'OverrideSettings', 'Cache' ) == 'enabled'; 00418 00419 $standardBase = eZTemplateDesignResource::designSetting( 'standard' ); 00420 $siteBase = eZTemplateDesignResource::designSetting( 'site' ); 00421 00422 $overrideKeys = $this->overrideKeys(); 00423 00424 $overrideKey = md5( implode( ',', $overrideKeys ) . $siteBase . $standardBase ); 00425 $cacheDir = eZSys::cacheDirectory(); 00426 00427 $overrideCacheFile = $cacheDir.'/override/override_'.$overrideKey.'.php'; 00428 00429 // Build matching cache only of it does not already exists, 00430 // or override file has been updated 00431 if ( !$useOverrideCache or 00432 !file_exists( $overrideCacheFile ) ) 00433 { 00434 $matchFileArray = eZTemplateDesignResource::overrideArray( $this->OverrideSiteAccess ); 00435 00436 // Generate PHP compiled cache file. 00437 $phpCache = new eZPHPCreator( "$cacheDir/override", "override_$overrideKey.php" ); 00438 00439 $phpCode = "\$GLOBALS['eZOverrideTemplateCacheMap'] = array (\n"; 00440 $numMatchFiles = count ( $matchFileArray ); 00441 $countMatchFiles = 0; 00442 // $phpCode .= "switch ( \$matchFile )\n{\n "; 00443 foreach ( array_keys( $matchFileArray ) as $matchKey ) 00444 { 00445 $countMatchFiles++; 00446 $phpCode .= '\'' . md5( $matchKey ) . '\' => '; 00447 if ( isset( $matchFileArray[$matchKey]['custom_match'] ) ) 00448 { 00449 $baseDir = isset( $matchFileArray[$matchKey]['base_dir'] ) ? $matchFileArray[$matchKey]['base_dir'] : ''; 00450 $defaultMatchFile = $baseDir . $matchKey; 00451 // Custom override matching 00452 // $phpCode .= " case \"$matchKey\":\n {\n"; 00453 00454 $matchConditionArray = array(); 00455 foreach ( $matchFileArray[$matchKey]['custom_match'] as $customMatch ) 00456 { 00457 $matchCondition = ""; 00458 $condCount = 0; 00459 if ( is_array( $customMatch['conditions'] ) ) 00460 { 00461 foreach ( array_keys( $customMatch['conditions'] ) as $conditionKey ) 00462 { 00463 if ( $condCount > 0 ) 00464 $matchCondition .= " and "; 00465 00466 // Have a special substring match for subtree matching 00467 00468 $matchCondition .= "( isset( \$matchKeys[\\'$conditionKey\\'] ) and "; 00469 if ( $conditionKey == 'url_alias' ) 00470 { 00471 $matchCondition .= 00472 "( strpos( \$matchKeys[\\'url_alias\\'], \\'" . $customMatch['conditions']['url_alias'] . "\\' ) === 0 ) )"; 00473 } 00474 else 00475 { 00476 $matchCondition .= 00477 "( is_array( \$matchKeys[\\'$conditionKey\\'] ) ? " . 00478 "in_array( \\'" . $customMatch['conditions'][$conditionKey] . "\\', \$matchKeys[\\'$conditionKey\\'] ) : " . 00479 "\$matchKeys[\\'$conditionKey\\'] == \\'" . $customMatch['conditions'][$conditionKey] . "\\') )"; 00480 } 00481 00482 $condCount++; 00483 } 00484 } 00485 00486 // Only create custom match if conditions are defined 00487 if ( $matchCondition != "" ) 00488 { 00489 // $phpCode .= " if ( $matchCondition )\n {\n"; 00490 // $phpCode .= " return '" . $customMatch['match_file'] . "';\n }\n"; 00491 if ( $condCount > 1 ) 00492 $matchConditionArray[] = array( 'condition' => '(' . $matchCondition . ')', 00493 'matchFile' => $customMatch['match_file'] ); 00494 else 00495 $matchConditionArray[] = array( 'condition' => $matchCondition, 00496 'matchFile' => $customMatch['match_file'] ); 00497 } 00498 else 00499 { 00500 // No override conditions defined. Override default match file 00501 $defaultMatchFile = $customMatch['match_file']; 00502 } 00503 } 00504 00505 $phpCode .= "array ( 'eval' => 1, 'code' => "; 00506 00507 $phpCode .= "'"; 00508 00509 foreach ( array_keys( $matchConditionArray ) as $key ) 00510 { 00511 $phpCode .= '(' . $matchConditionArray[$key]['condition'] . ' ? ' . "\\'" . $matchConditionArray[$key]['matchFile'] . "\\'" . ' : '; 00512 } 00513 00514 $phpCode .= "\\'" . $defaultMatchFile . "\\'"; 00515 00516 for ( $condCount = 0; $condCount < count( $matchConditionArray ); $condCount++) 00517 { 00518 $phpCode .= ')'; 00519 } 00520 00521 $phpCode .= "' )"; 00522 } 00523 else 00524 { 00525 $phpCode .= "'". $matchFileArray[$matchKey]['base_dir'] . $matchKey . "'"; 00526 } 00527 00528 if ( $countMatchFiles < $numMatchFiles ) 00529 { 00530 $phpCode .= ",\n"; 00531 } 00532 else 00533 { 00534 $phpCode .= ");\n"; 00535 } 00536 } 00537 00538 $phpCache->addCodePiece( $phpCode ); 00539 if ( $useOverrideCache and 00540 $phpCache->store() ) 00541 { 00542 00543 } 00544 else 00545 { 00546 if ( $useOverrideCache ) 00547 { 00548 eZDebug::writeError( "Could not write template override cache file, check permissions in $cacheDir/override/.\nRunning eZ Publish without this cache will have a performance impact.", __METHOD__ ); 00549 } 00550 $eZTemplateOverrideCacheNoPermission = 'nocache'; 00551 $overrideCacheFile = false; 00552 } 00553 } 00554 00555 return $overrideCacheFile; 00556 } 00557 00558 /*! 00559 \static 00560 \return an array with keys that define the current override. 00561 */ 00562 function overrideKeys( $siteAccess = false ) 00563 { 00564 // print( "<br>" . xdebug_call_function() . "<br>" ); 00565 $keys = array(); 00566 $designStartPath = eZTemplateDesignResource::designStartPath(); 00567 $keys[] = $designStartPath; 00568 00569 // fetch the override array from a specific siteacces 00570 if ( $siteAccess ) 00571 { 00572 // Get the design resources 00573 $ini = eZSiteAccess::getIni( $siteAccess, 'site.ini' ); 00574 00575 $overrideINI = eZINI::instance( 'override.ini', 'settings', null, null, true ); 00576 00577 // overwrite overrideDirs from siteIni instance 00578 $overrideINI->setOverrideDirs( $ini->overrideDirs( false ) ); 00579 $overrideINI->load(); 00580 00581 $standardBase = $ini->variable( "DesignSettings", "StandardDesign" ); 00582 $keys[] = "siteaccess/$siteAccess"; 00583 $keys[] = $standardBase; 00584 $siteBase = $ini->variable( "DesignSettings", "SiteDesign" ); 00585 $keys[] = $siteBase; 00586 } 00587 else 00588 { 00589 $ini = eZINI::instance(); 00590 if ( $this->OverrideSiteAccess != false ) 00591 { 00592 $overrideINI = eZSiteAccess::getIni( $siteAccess, 'override.ini' ); 00593 $keys[] = "siteaccess/$this->OverrideSiteAccess"; 00594 } 00595 else 00596 { 00597 $overrideINI = eZINI::instance( 'override.ini' ); 00598 $siteAccess = $GLOBALS['eZCurrentAccess']['name']; 00599 $keys[] = "siteaccess/$siteAccess"; 00600 } 00601 00602 $standardBase = eZTemplateDesignResource::designSetting( 'standard' ); 00603 $keys[] = $standardBase; 00604 $siteBase = eZTemplateDesignResource::designSetting( 'site' ); 00605 $keys[] = $siteBase; 00606 } 00607 00608 00609 $additionalSiteDesignList = $ini->variable( "DesignSettings", "AdditionalSiteDesignList" ); 00610 $keys = array_merge( $keys, $additionalSiteDesignList ); 00611 00612 // Add extension paths 00613 $extensionDirectory = eZExtension::baseDirectory(); 00614 00615 $designINI = eZINI::instance( 'design.ini' ); 00616 $extensions = $designINI->variable( 'ExtensionSettings', 'DesignExtensions' ); 00617 00618 return array_merge( $keys, $extensions ); 00619 } 00620 00621 /*! 00622 \static 00623 */ 00624 static function serializeOverrides( $siteAccess = false, 00625 $matchKeys = array() ) 00626 { 00627 } 00628 00629 /*! 00630 \static 00631 \return An array containing the names of the design extensions that are 00632 currently active 00633 */ 00634 static function designExtensions() 00635 { 00636 $designINI = eZINI::instance( 'design.ini' ); 00637 $extensions = $designINI->variable( 'ExtensionSettings', 'DesignExtensions' ); 00638 return array_reverse( $extensions ); 00639 } 00640 00641 /*! 00642 \static 00643 \return Gives all knows bases for available sitedesign folders. 00644 */ 00645 static function allDesignBases( $siteAccess = false ) 00646 { 00647 // in memory caching 00648 if ( $siteAccess ) 00649 { 00650 if ( isset( $GLOBALS['eZTemplateDesignResourceSiteAccessBases'] ) ) 00651 { 00652 if ( isset( $GLOBALS['eZTemplateDesignResourceSiteAccessBases'][$siteAccess] ) ) 00653 { 00654 return $GLOBALS['eZTemplateDesignResourceSiteAccessBases'][$siteAccess]; 00655 } 00656 } 00657 else 00658 { 00659 $GLOBALS['eZTemplateDesignResourceSiteAccessBases'] = array(); 00660 } 00661 } 00662 else 00663 { 00664 if ( isset( $GLOBALS['eZTemplateDesignResourceBases'] ) ) 00665 { 00666 return $GLOBALS['eZTemplateDesignResourceBases']; 00667 } 00668 } 00669 00670 $designLocationCache = false; 00671 $ini = eZINI::instance( 'site.ini' ); 00672 if( $ini->variable( 'DesignSettings', 'DesignLocationCache' ) == 'enabled' ) 00673 $designLocationCache = true; 00674 00675 /* 00676 * We disable design cache in case of DB clustering 00677 * because it will add 2 SQL queries per HTTP request 00678 */ 00679 $ini = eZINI::instance( 'file.ini' ); 00680 if( $ini->variable( 'ClusteringSettings', 'FileHandler' ) == 'eZDBFileHandler') 00681 $designLocationCache = false; 00682 00683 if( $designLocationCache ) 00684 { 00685 $siteAccessName = $GLOBALS['eZCurrentAccess']['name']; 00686 00687 $cachePath = eZSys::cacheDirectory() 00688 . '/' 00689 . self::DESIGN_BASE_CACHE_NAME 00690 . md5( $siteAccessName ) 00691 . '.php'; 00692 00693 $clusterFileHandler = eZClusterFileHandler::instance( $cachePath ); 00694 00695 if( $clusterFileHandler->fileExists( $cachePath ) ) 00696 { 00697 $designBaseList = unserialize( $clusterFileHandler->fetchContents() ); 00698 00699 self::savesMemoryCache( $designBaseList, $siteAccess ); 00700 } 00701 else 00702 { 00703 // find design locations 00704 $designBaseList = self::findDesignBase( $ini, $siteAccess ); 00705 00706 // stores it on the disk 00707 $clusterFileHandler->fileStoreContents( $cachePath, 00708 serialize( $designBaseList ), 00709 'designbases', 00710 'php' ); 00711 00712 self::savesMemoryCache( $designBaseList, $siteAccess ); 00713 } 00714 } 00715 else 00716 { 00717 // find design locations 00718 $designBaseList = self::findDesignBase( $ini, $siteAccess ); 00719 00720 self::savesMemoryCache( $designBaseList, $siteAccess ); 00721 } 00722 00723 return $designBaseList; 00724 } 00725 00726 /** 00727 * Find the location on design bases on the disk 00728 * 00729 * @param $ini an eZINI object 00730 * @param $siteAccess Wether to use siteaccesses or not 00731 * @return array The list of design bases 00732 */ 00733 private static function findDesignBase( eZINI $ini, $siteAccess = false ) 00734 { 00735 if( $siteAccess ) 00736 { 00737 $ini = eZSiteAccess::getIni( $siteAccess, 'site.ini' ); 00738 00739 $standardDesign = $ini->variable( 'DesignSettings', 'StandardDesign' ); 00740 $siteDesign = $ini->variable( 'DesignSettings', 'SiteDesign' ); 00741 00742 } 00743 else 00744 { 00745 $ini = eZINI::instance(); 00746 $standardDesign = eZTemplateDesignResource::designSetting( 'standard' ); 00747 $siteDesign = eZTemplateDesignResource::designSetting( 'site' ); 00748 } 00749 00750 $siteDesignList = $ini->variable( 'DesignSettings', 'AdditionalSiteDesignList' ); 00751 00752 array_unshift( $siteDesignList, $siteDesign ); 00753 $siteDesignList[] = $standardDesign; 00754 $siteDesignList = array_unique( $siteDesignList ); 00755 00756 $designBaseList = array(); 00757 $extensionDirectory = eZExtension::baseDirectory(); 00758 $designStartPath = eZTemplateDesignResource::designStartPath(); 00759 $extensions = eZTemplateDesignResource::designExtensions(); 00760 00761 foreach ( $siteDesignList as $design ) 00762 { 00763 foreach ( $extensions as $extension ) 00764 { 00765 $path = "$extensionDirectory/$extension/$designStartPath/$design"; 00766 if ( file_exists( $path ) ) 00767 { 00768 $designBaseList[] = $path; 00769 } 00770 } 00771 00772 $path = "$designStartPath/$design"; 00773 if ( file_exists( $path ) ) 00774 { 00775 $designBaseList[] = $path; 00776 } 00777 } 00778 00779 return $designBaseList; 00780 } 00781 00782 /** 00783 * Stores design base list in memory for the current request 00784 * 00785 * @param $designBaseList An array with the design bases 00786 * @param $siteAccess Whether to use siteaccess or not 00787 * @return void 00788 */ 00789 private static function savesMemoryCache( array $designBaseList, $siteAccess = false ) 00790 { 00791 // store design base list in memory for the current request 00792 if ( $siteAccess ) 00793 $GLOBALS['eZTemplateDesignResourceSiteAccessBases'][$siteAccess] = $designBaseList; 00794 else 00795 $GLOBALS['eZTemplateDesignResourceBases'] = $designBaseList; 00796 } 00797 00798 /*! 00799 \static 00800 \return The start path of the design directory, by default it will return \c 'design' 00801 To change the directory use setDesignStartPath(). 00802 */ 00803 static function designStartPath() 00804 { 00805 $designStartPath = false; 00806 if ( isset( $GLOBALS['eZTemplateDesignResourceStartPath'] ) ) 00807 { 00808 $designStartPath = $GLOBALS['eZTemplateDesignResourceStartPath']; 00809 } 00810 if ( !$designStartPath ) 00811 $designStartPath = 'design'; 00812 return $designStartPath; 00813 } 00814 00815 /*! 00816 \static 00817 Changes the design start path which is used to find design files. 00818 \param $path Must be a string defining the path or \c false to use default start path. 00819 \sa designStartPath(); 00820 */ 00821 static function setDesignStartPath( $path ) 00822 { 00823 $GLOBALS['eZTemplateDesignResourceStartPath'] = $path; 00824 } 00825 00826 /** 00827 * Get an array of all the current templates and overrides for them. 00828 * The current siteaccess is used if none is specified. 00829 * 00830 * @static 00831 * @return array 00832 */ 00833 static function overrideArray( $siteAccess = false ) 00834 { 00835 00836 if ( $siteAccess === false and self::$overrideArrayCache !== null ) 00837 { 00838 return self::$overrideArrayCache; 00839 } 00840 00841 $bases = eZTemplateDesignResource::allDesignBases( $siteAccess ); 00842 00843 // fetch the override array from a specific siteacces 00844 if ( $siteAccess ) 00845 { 00846 $overrideINI = eZSiteAccess::getIni( $siteAccess, 'override.ini' ); 00847 } 00848 else 00849 { 00850 $overrideINI = eZINI::instance( 'override.ini' ); 00851 } 00852 00853 $designStartPath = eZTemplateDesignResource::designStartPath(); 00854 00855 // Generate match cache for all templates 00856 00857 // Build arrays of available files, start with standard design and end with most prefered design 00858 $matchFileArray = array(); 00859 00860 $reverseBases = array_reverse( $bases ); 00861 00862 foreach ( $reverseBases as $base ) 00863 { 00864 $templateResource = $base . '/templates'; 00865 $sourceFileArray = eZDir::recursiveFindRelative( $templateResource, "", "tpl" ); 00866 foreach ( $sourceFileArray as $source ) 00867 { 00868 $matchFileArray[$source]['base_dir'] = $templateResource; 00869 $matchFileArray[$source]['template'] = $source; 00870 } 00871 } 00872 00873 // Load override templates 00874 $overrideSettingGroups = $overrideINI->groups(); 00875 if ( isset( $GLOBALS['eZDesignOverrides'] ) ) 00876 { 00877 $overrideSettingGroups = array_merge( $overrideSettingGroups, $GLOBALS['eZDesignOverrides'] ); 00878 } 00879 00880 foreach ( $overrideSettingGroups as $overrideName => $overrideSetting ) 00881 { 00882 $overrideSource = "/" . $overrideSetting['Source']; 00883 $overrideMatchFile = $overrideSetting['MatchFile']; 00884 00885 // Find the matching file in the available resources 00886 $triedFiles = array(); 00887 $fileInfo = eZTemplateDesignResource::fileMatch( $bases, 'override/templates', $overrideMatchFile, $triedFiles ); 00888 00889 $resourceInUse = is_array( $fileInfo ) ? $fileInfo['resource'] : false; 00890 $overrideMatchFilePath = is_array( $fileInfo ) ? $fileInfo['path'] : false; 00891 00892 // if the override template is not found 00893 // then we probably shouldn't use it 00894 // there should be added a check around the following code 00895 // if ( $overrideMatchFilePath ) 00896 // { 00897 $customMatchArray = array(); 00898 $customMatchArray['conditions'] = isset( $overrideSetting['Match'] ) ? $overrideSetting['Match'] : null; 00899 $customMatchArray['match_file'] = $overrideMatchFilePath; 00900 $customMatchArray['override_name'] = $overrideName; 00901 00902 $matchFileArray[$overrideSource]['custom_match'][] = $customMatchArray; 00903 // } 00904 00905 // if overriding a non-existing template 00906 // then we use the override template as main template 00907 // this code should probably be removed 00908 // because we should not allow an override if the main template is missing 00909 if ( $resourceInUse && !isset( $matchFileArray[$overrideSource]['base_dir'] ) ) 00910 { 00911 $matchFileArray[$overrideSource]['base_dir'] = $resourceInUse; 00912 $matchFileArray[$overrideSource]['template'] = $overrideSource; 00913 } 00914 00915 if ( ! $overrideMatchFilePath ) 00916 { 00917 eZDebug::writeError( "Custom match file: path '$overrideMatchFile' not found in any resource. Check the template settings in settings/override.ini", __METHOD__ ); 00918 eZDebug::writeError( implode( ', ', $triedFiles ), __METHOD__ . ' tried files' ); 00919 } 00920 00921 } 00922 00923 if ( $siteAccess === false ) 00924 { 00925 self::$overrideArrayCache = $matchFileArray; 00926 } 00927 00928 return $matchFileArray; 00929 } 00930 00931 /** 00932 * Clear in memory override array cache 00933 * 00934 * @static 00935 * @since 4.2 00936 */ 00937 static public function clearInMemoryOverrideArray( ) 00938 { 00939 self::$overrideArrayCache = null; 00940 unset( $GLOBALS['eZOverrideTemplateCacheMap'] ); 00941 } 00942 00943 /** 00944 * Clear in memory cache (design settings and override cache) 00945 * 00946 * @static 00947 * @since 4.4 00948 */ 00949 static public function clearInMemoryCache( ) 00950 { 00951 $GLOBALS['eZTemplateDesignSetting'] = array(); 00952 self::clearInMemoryOverrideArray(); 00953 } 00954 00955 /*! 00956 Sets the override keys to \a $keys, if some of the keys already exists they are overriden 00957 by the new keys. 00958 \sa clearKeys 00959 */ 00960 function setKeys( $keys ) 00961 { 00962 $this->mergeKeys( $this->Keys, $keys ); 00963 } 00964 00965 /*! 00966 Removes the given key 00967 */ 00968 function removeKey( $key ) 00969 { 00970 if ( isset( $this->Keys[$key] ) ) 00971 unset( $this->Keys[$key] ); 00972 } 00973 00974 /*! 00975 \private 00976 Merges keys set in \a $keys with the array in \a $originalKeys. 00977 */ 00978 function mergeKeys( &$originalKeys, $keys ) 00979 { 00980 foreach ( $keys as $key ) 00981 { 00982 if ( count( $key ) >= 2 ) 00983 $originalKeys[$key[0]] = $key[1]; 00984 } 00985 } 00986 00987 /*! 00988 Removes all override keys. 00989 \sa setKeys 00990 */ 00991 function clearKeys() 00992 { 00993 $this->Keys = array(); 00994 } 00995 00996 /*! 00997 \return the match keys. 00998 \sa setKeys 00999 */ 01000 function keys() 01001 { 01002 if ( isset( $GLOBALS['eZDesignKeys'] ) ) 01003 { 01004 return array_merge( $this->Keys, $GLOBALS['eZDesignKeys'] ); 01005 } 01006 return $this->Keys; 01007 } 01008 01009 /*! 01010 \static 01011 */ 01012 static function addGlobalOverride( $name, $source, $match, $subdir, $matches ) 01013 { 01014 if ( !isset( $GLOBALS['eZDesignOverrides'] ) ) 01015 $GLOBALS['eZDesignOverrides'] = array(); 01016 $GLOBALS['eZDesignOverrides'][$name] = array( 'Source' => $source, 01017 'MatchFile' => $match, 01018 'Subdir' => $subdir, 01019 'Match' => $matches ); 01020 } 01021 01022 /** 01023 * Returns a shared instance of the eZTemplateDesignResource class. 01024 * 01025 * @return eZTemplateDesignResource 01026 */ 01027 static function instance() 01028 { 01029 if ( !isset( $GLOBALS['eZTemplateDesignResourceInstance'] ) ) 01030 { 01031 $GLOBALS['eZTemplateDesignResourceInstance'] = new eZTemplateDesignResource(); 01032 } 01033 return $GLOBALS['eZTemplateDesignResourceInstance']; 01034 } 01035 01036 /*! 01037 Sets the siteaccess which are to be used for loading the override settings. 01038 */ 01039 function setOverrideAccess( $siteAccess ) 01040 { 01041 $this->OverrideSiteAccess = $siteAccess; 01042 } 01043 01044 public $Keys; 01045 public $OverrideSiteAccess = false; 01046 } 01047 01048 ?>