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