eZ Publish  [4.0]
eztemplatesetfunction.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZTemplateSetFunction class
00004 //
00005 // Created on: <05-Mar-2002 13:55:25 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 eZTemplateSetFunction eztemplatesetfunction.php
00033   \ingroup eZTemplateFunctions
00034   \brief Sets template variables code using function 'set'
00035 
00036   Allows for setting template variables from templates using
00037   a template function. This is mainly used for optimizations.
00038 
00039   The let function will define new variables and initialize them with
00040   a value while set only sets values to existing variables.
00041   The let function is also scoped with children which means that the
00042   variables are unset when the children are processed.
00043 
00044 \code
00045 // Example template code
00046 {let object=$item1 some_text='abc' integer=1}
00047   {set object=$item2 some_text='def'}
00048 
00049 {/let}
00050 
00051 {set name=NewNamespace place='/etc/test.tpl'}
00052 
00053 \endcode
00054 */
00055 
00056 class eZTemplateSetFunction
00057 {
00058     const SCOPE_RELATIVE = 1;
00059     const SCOPE_ROOT = 2;
00060     const SCOPE_GLOBAL = 3;
00061 
00062     /*!
00063      Initializes the function with the function names $setName and $letName.
00064     */
00065     function eZTemplateSetFunction( $setName = 'set', $letName = 'let', $defaultName = 'default' )
00066     {
00067         $this->SetName = $setName;
00068         $this->LetName = $letName;
00069         $this->DefaultName = $defaultName;
00070     }
00071 
00072     /*!
00073      Returns an array of the function names, required for eZTemplate::registerFunctions.
00074     */
00075     function functionList()
00076     {
00077         return array( $this->SetName, $this->LetName, $this->DefaultName );
00078     }
00079 
00080     function functionTemplateStatistics( $functionName, &$node, $tpl, $resourceData, $namespace, &$stats )
00081     {
00082         $newNamespace = $namespace;
00083         $parameters = eZTemplateNodeTool::extractFunctionNodeParameters( $node );
00084         if ( $functionName == $this->SetName or
00085              $functionName == $this->LetName or
00086              $functionName == $this->DefaultName )
00087         {
00088             if ( isset( $parameters['-name'] ) )
00089             {
00090                 $nameData = $parameters['-name'];
00091                 $nameDataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
00092                                                                                $nameData, false,
00093                                                                                $resourceData );
00094                 if ( $nameDataInspection['is-constant'] and
00095                      !$nameDataInspection['has-operators'] and
00096                      !$nameDataInspection['has-attributes'] )
00097                 {
00098                     $parameterNamespace = $nameDataInspection['new-data'][0][1];
00099                     $newNamespace = $tpl->mergeNamespace( $namespace, $parameterNamespace );
00100                 }
00101             }
00102         }
00103         if ( $functionName == $this->SetName )
00104         {
00105             foreach ( array_keys( $parameters ) as $name )
00106             {
00107                 if ( $name == '-name' )
00108                     continue;
00109                 $parameter =& $parameters[$name];
00110                 eZTemplateCompiler::setVariableStatistics( $stats, $newNamespace, $name, array( 'is_modified' => true ) );
00111                 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $parameter, false, $resourceData, $namespace, $stats );
00112             }
00113         }
00114         else if ( $functionName == $this->LetName )
00115         {
00116             foreach ( array_keys( $parameters ) as $name )
00117             {
00118                 if ( $name == '-name' )
00119                     continue;
00120                 $parameter =& $parameters[$name];
00121                 eZTemplateCompiler::setVariableStatistics( $stats, $newNamespace, $name, array( 'is_created' => true,
00122                                                                                              'is_removed' => true ) );
00123                 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $parameter, false, $resourceData, $namespace, $stats );
00124             }
00125         }
00126         else if ( $functionName == $this->DefaultName )
00127         {
00128             foreach ( array_keys( $parameters ) as $name )
00129             {
00130                 if ( $name == '-name' )
00131                     continue;
00132                 $parameter =& $parameters[$name];
00133                 eZTemplateCompiler::setVariableStatistics( $stats, $newNamespace, $name, array( ) );
00134                 eZTemplateCompiler::calculateVariableNodeStatistics( $tpl, $parameter, false, $resourceData, $namespace, $stats );
00135             }
00136         }
00137         if ( $functionName == $this->LetName or
00138              $functionName == $this->DefaultName )
00139         {
00140             $functionChildren = eZTemplateNodeTool::extractFunctionNodeChildren( $node );
00141             if ( is_array( $functionChildren ) )
00142             {
00143                 eZTemplateCompiler::calculateVariableStatisticsChildren( $tpl, $functionChildren, $resourceData, $newNamespace, $stats );
00144             }
00145         }
00146     }
00147 
00148 
00149     function functionTemplateHints()
00150     {
00151         return array( $this->LetName => array( 'parameters' => true,
00152                                                'static' => false,
00153                                                'tree-transformation' => true,
00154                                                'transform-children' => true,
00155                                                'transform-parameters' => true ),
00156                       $this->SetName => array( 'parameters' => true,
00157                                                'static' => false,
00158                                                'tree-transformation' => true,
00159                                                'transform-children' => true,
00160                                                'transform-parameters' => true ),
00161                       $this->DefaultName => array( 'parameters' => true,
00162                                                    'static' => false,
00163                                                    'tree-transformation' => true,
00164                                                    'transform-children' => true,
00165                                                    'transform-parameters' => true ) );
00166     }
00167 
00168     function templateNodeTransformation( $functionName, &$node,
00169                                          $tpl, $parameters, $privateData )
00170     {
00171         switch( $functionName )
00172         {
00173             case $this->SetName:
00174             case $this->DefaultName:
00175             case $this->LetName:
00176             {
00177                 $scope = eZTemplate::NAMESPACE_SCOPE_RELATIVE;
00178                 if ( isset( $parameters['-scope'] ) )
00179                 {
00180                     if ( !eZTemplateNodeTool::isStaticElement( $parameters['-scope'] ) )
00181                         return false;
00182                     $scopeText = eZTemplateNodeTool::elementStaticValue( $parameters['-scope'] );
00183                     if ( $scopeText == 'relative' )
00184                         $scope = eZTemplate::NAMESPACE_SCOPE_RELATIVE;
00185                     else if ( $scopeText == 'root' )
00186                         $scope = eZTemplate::NAMESPACE_SCOPE_LOCAL;
00187                     else if ( $scopeText == 'global' )
00188                         $scope = eZTemplate::NAMESPACE_SCOPE_GLOBAL;
00189                 }
00190 
00191                 $parameters = eZTemplateNodeTool::extractFunctionNodeParameters( $node );
00192                 $namespaceValue = false;
00193                 if ( isset( $parameters['-name'] ) )
00194                 {
00195                     if ( !eZTemplateNodeTool::isStaticElement( $parameters['-name'] ) )
00196                     {
00197                         return false;
00198                     }
00199 
00200                     $namespaceValue = eZTemplateNodeTool::elementStaticValue( $parameters['-name'] );
00201                 }
00202 
00203                 $variableList = array();
00204                 $setVarNodes = array();
00205                 foreach ( array_keys( $parameters ) as $parameterName )
00206                 {
00207                     if ( $parameterName == '-name' or $parameterName == '-scope'  )
00208                     {
00209                         continue;
00210                     }
00211 
00212                     $parameterData =& $parameters[$parameterName];
00213 
00214                     $setVarNodes[] = eZTemplateNodeTool::createVariableNode(
00215                             false, $parameterData, eZTemplateNodeTool::extractFunctionNodePlacement( $node ),
00216                             array(), array( $namespaceValue, $scope, $parameterName ),
00217                             ( $functionName == $this->SetName ), ( $functionName != $this->DefaultName ),
00218                             false, ( $functionName == $this->DefaultName ) );
00219 
00220                     if ( $functionName == $this->LetName or $functionName == $this->DefaultName )
00221                     {
00222                         $variableList[] = $parameterName;
00223                     }
00224                 }
00225 
00226                 if ( ( $functionName == $this->LetName or $functionName == $this->DefaultName ) and
00227                      $namespaceValue )
00228                 {
00229                     $setVarNodes[] = eZTemplateNodeTool::createNamespaceChangeNode( $namespaceValue );
00230                 }
00231 
00232                 if ( $functionName == $this->LetName or $functionName == $this->DefaultName )
00233                 {
00234                     $childNodes = eZTemplateNodeTool::extractFunctionNodeChildren( $node );
00235                     if ( !is_array( $childNodes ) )
00236                     {
00237                         $childNodes = array();
00238                     }
00239                 }
00240                 else
00241                 {
00242                     $childNodes = array();
00243                 }
00244 
00245                 $unsetVarNodes = array();
00246 
00247                 if ( ( $functionName == $this->LetName or $functionName == $this->DefaultName ) and
00248                      $namespaceValue )
00249                 {
00250                     $unsetVarNodes[] = eZTemplateNodeTool::createNamespaceRestoreNode();
00251                 }
00252 
00253                 if ( $functionName == $this->LetName or $functionName == $this->DefaultName )
00254                 {
00255                     foreach( $variableList as $parameterName )
00256                     {
00257                         $unsetVarNodes[] = eZTemplateNodeTool::createVariableUnsetNode( array( $namespaceValue,
00258                                                                                                eZTemplate::NAMESPACE_SCOPE_RELATIVE,
00259                                                                                                $parameterName ),
00260                                                                                         array( 'remember_set' => $functionName == $this->DefaultName ) );
00261                     }
00262                 }
00263 
00264                 return array_merge( $setVarNodes, $childNodes, $unsetVarNodes );
00265             } break;
00266         }
00267 
00268     }
00269 
00270     function templateHookProcess( $functionName, $functionHookName, $functionHook,
00271                                   $tpl, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace )
00272     {
00273     }
00274 
00275     function defineVariables( $tpl, $functionParameters, $functionPlacement, $name, $rootNamespace, &$currentNamespace )
00276     {
00277         $oldCurrentNamespace = $currentNamespace;
00278         $definedVariables = array();
00279         foreach ( array_keys( $functionParameters ) as $key )
00280         {
00281             $item =& $functionParameters[$key];
00282             switch ( $key )
00283             {
00284                 case '-name':
00285                     break;
00286 
00287                 default:
00288                 {
00289                     if ( !$tpl->hasVariable( $key, $name ) )
00290                     {
00291                         $itemValue = $tpl->elementValue( $item, $rootNamespace, $currentNamespace, $functionPlacement );
00292                         $tpl->setVariableRef( $key, $itemValue, $name );
00293                         $definedVariables[] = $key;
00294                     }
00295                     else
00296                     {
00297                         $varname = $key;
00298                         if ( $name != '' )
00299                             $varname = "$name:$varname";
00300                         $tpl->warning( $this->SetName, "Variable '$varname' already exists, cannot define" );
00301                     }
00302                 } break;
00303             }
00304         }
00305         $currentNamespace = $name;
00306         return array( $definedVariables,
00307                       $oldCurrentNamespace );
00308     }
00309 
00310     function createDefaultVariables( $tpl, $functionParameters, $functionPlacement, $name, $rootNamespace, &$currentNamespace )
00311     {
00312         $oldCurrentNamespace = $currentNamespace;
00313         $definedVariables = array();
00314         foreach ( array_keys( $functionParameters ) as $key )
00315         {
00316             $item =& $functionParameters[$key];
00317             switch ( $key )
00318             {
00319                 case '-name':
00320                     break;
00321 
00322                 default:
00323                 {
00324                     if ( !$tpl->hasVariable( $key, $name ) )
00325                     {
00326                         $itemValue = $tpl->elementValue( $item, $rootNamespace, $currentNamespace, $functionPlacement );
00327                         $tpl->setVariableRef( $key, $itemValue, $name );
00328                         $definedVariables[] = $key;
00329                     }
00330                 } break;
00331             }
00332         }
00333         $currentNamespace = $name;
00334         return array( $definedVariables,
00335                       $oldCurrentNamespace );
00336     }
00337 
00338     function cleanupVariables( $tpl, $rootNamespace, &$currentNamespace, $setData )
00339     {
00340         $definedVariables = $setData[0];
00341         foreach ( $definedVariables as $variable )
00342         {
00343             $tpl->unsetVariable( $variable, $currentNamespace );
00344         }
00345         $currentNamespace = $setData[1];
00346     }
00347 
00348     /*!
00349      Loads the file specified in the parameter 'uri' with namespace 'name'.
00350     */
00351     function process( $tpl, &$textElements, $functionName, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace )
00352     {
00353         if ( $functionName != $this->SetName and
00354              $functionName != $this->LetName and
00355              $functionName != $this->DefaultName )
00356             return null;
00357 
00358         $children = $functionChildren;
00359         $parameters = $functionParameters;
00360 
00361         $scope = eZTemplateSetFunction::SCOPE_RELATIVE;
00362         if ( isset( $parameters['-scope'] ) )
00363         {
00364             $scopeText = $tpl->elementValue( $parameters['-scope'], $rootNamespace, $currentNamespace, $functionPlacement );
00365             if ( $scopeText == 'relative' )
00366                 $scope = eZTemplateSetFunction::SCOPE_RELATIVE;
00367             else if ( $scopeText == 'root' )
00368                 $scope = eZTemplateSetFunction::SCOPE_ROOT;
00369             else if ( $scopeText == 'global' )
00370                 $scope = eZTemplateSetFunction::SCOPE_GLOBAL;
00371             else
00372                 $tpl->warning( $functionName, "Scope value '$scopeText' is not valid, use either 'relative', 'root' or 'global'" );
00373         }
00374 
00375         $name = null;
00376         if ( isset( $parameters['-name'] ) )
00377             $name = $tpl->elementValue( $parameters['-name'], $rootNamespace, $currentNamespace, $functionPlacement );
00378         if ( $name === null )
00379         {
00380             if ( $scope == eZTemplateSetFunction::SCOPE_RELATIVE )
00381                 $name = $currentNamespace;
00382             else if ( $scope == eZTemplateSetFunction::SCOPE_ROOT )
00383                 $name = $rootNamespace;
00384             else
00385                 $name = '';
00386         }
00387         else
00388         {
00389             if ( $scope == eZTemplateSetFunction::SCOPE_RELATIVE and
00390                  $currentNamespace != '' )
00391                 $name = "$currentNamespace:$name";
00392             else if ( $scope == eZTemplateSetFunction::SCOPE_ROOT and
00393                       $rootNamespace != '' )
00394                 $name = "$rootNamespace:$name";
00395         }
00396 
00397         $definedVariables = array();
00398         if ( $functionName == $this->SetName )
00399         {
00400             foreach ( array_keys( $functionParameters ) as $key )
00401             {
00402                 $item =& $functionParameters[$key];
00403                 switch ( $key )
00404                 {
00405                     case '-name':
00406                     case '-scope':
00407                         break;
00408 
00409                     default:
00410                     {
00411                         if ( $tpl->hasVariable( $key, $name ) )
00412                         {
00413                             unset( $itemValue );
00414                             $itemValue = $tpl->elementValue( $item, $rootNamespace, $currentNamespace, $functionPlacement );
00415                             $tpl->setVariableRef( $key, $itemValue, $name );
00416                         }
00417                         else
00418                         {
00419                             $varname = $key;
00420                             if ( $name != '' )
00421                                 $varname = "$name:$varname";
00422                             $tpl->warning( $functionName, "Variable '$varname' doesn't exist, cannot set" );
00423                         }
00424                     } break;
00425                 }
00426             }
00427         }
00428         else if ( $functionName == $this->DefaultName )
00429         {
00430             $definedVariables = eZTemplateSetFunction::createDefaultVariables( $tpl, $functionParameters, $functionPlacement, $name, $rootNamespace, $currentNamespace );
00431         }
00432         else
00433         {
00434             $definedVariables = eZTemplateSetFunction::defineVariables( $tpl, $functionParameters, $functionPlacement, $name, $rootNamespace, $currentNamespace );
00435         }
00436         if ( $functionName == $this->LetName or
00437              $functionName == $this->DefaultName )
00438         {
00439             if ( is_array( $functionChildren ) )
00440             {
00441                 foreach ( array_keys( $functionChildren ) as $childKey )
00442                 {
00443                     $child =& $functionChildren[$childKey];
00444                     $tpl->processNode( $child, $textElements, $rootNamespace, $name );
00445                 }
00446             }
00447             eZTemplateSetFunction::cleanupVariables( $tpl, $rootNamespace, $currentNamespace, $definedVariables );
00448         }
00449     }
00450 
00451     /*!
00452      Returns false, telling the template parser that this is a single tag.
00453     */
00454     function hasChildren()
00455     {
00456         return array( $this->SetName => false,
00457                       $this->LetName => true,
00458                       $this->DefaultName => true );
00459     }
00460 
00461     /// The name of the set function
00462     public $SetName;
00463     public $LetName;
00464     public $DefaultName;
00465 }
00466 
00467 ?>