eZ Publish  [4.0]
eztemplateiffunction.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZTemplateIfFunction class
00004 //
00005 // Created on: <07-Feb-2005 16:31:03 vs>
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 eZTemplateIfFunction eztemplateiffunction.php
00033   \ingroup eZTemplateFunctions
00034   \brief Conditional execution in templates
00035 
00036   This class allows to execute on of two or more code pieces depending
00037   on a condition.
00038 
00039   Syntax:
00040 \code
00041   {if <condition>}
00042   [{elseif <condition>}]
00043   [{else}]
00044   {/if}
00045 \endcode
00046 
00047   Example:
00048 \code
00049   {if eq( $var, true() )}
00050     Hello world
00051   {else}
00052     No world here, move along.
00053   {/if}
00054 \endcode
00055 */
00056 
00057 class eZTemplateIfFunction
00058 {
00059     const FUNCTION_NAME = 'if';
00060 
00061     /*!
00062      * Returns an array of the function names, required for eZTemplate::registerFunctions.
00063      */
00064     function &functionList()
00065     {
00066         //eZDebug::writeDebug( "if::functionList()" );
00067         $functionList = array( eZTemplateIfFunction::FUNCTION_NAME );
00068         return $functionList;
00069     }
00070 
00071     /*!
00072      * Returns the attribute list which is 'delimiter', 'elseif' and 'else'.
00073      * key:   parameter name
00074      * value: can have children
00075      */
00076     function attributeList()
00077     {
00078         return array( 'elseif'    => false,
00079                       'else'      => false );
00080     }
00081 
00082 
00083     /*!
00084      * Returns the array with hits for the template compiler.
00085      */
00086     function functionTemplateHints()
00087     {
00088         return array( eZTemplateIfFunction::FUNCTION_NAME => array( 'parameters' => true,
00089                                                              'static' => false,
00090                                                              'transform-parameters' => true,
00091                                                              'tree-transformation' => true ) );
00092     }
00093 
00094     /*!
00095      * Compiles the function and its children into PHP code.
00096      */
00097     function templateNodeTransformation( $functionName, &$node,
00098                                          $tpl, $parameters, $privateData )
00099     {
00100         $tpl->ElseifCounter++;
00101         $newNodes       = array();
00102         $nodesToPrepend = array();
00103         $nodesToAppend  = array();
00104         $nodePlacement  = eZTemplateNodeTool::extractFunctionNodePlacement( $node );
00105         $uniqid        =  md5( $nodePlacement[2] ) . "_" . $tpl->ElseifCounter;
00106         $children       = eZTemplateNodeTool::extractFunctionNodeChildren( $node );
00107 
00108 
00109         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "// if begins" );
00110         $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['condition'], $nodePlacement, array( 'treat-value-as-non-object' => true ), 'if_cond' );
00111         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "if ( \$if_cond )\n{" );
00112         $newNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode();
00113 
00114         if ( is_array( $children ) )
00115         {
00116             foreach ( array_keys( $children ) as $childKey )
00117             {
00118                 $child =& $children[$childKey];
00119 
00120                 if ( $child[0] == eZTemplate::NODE_FUNCTION )
00121                 {
00122                     $childFunctionName =& $child[2];
00123                     $childChildren     = eZTemplateNodeTool::extractFunctionNodeChildren( $child );
00124                     $childFunctionArgs =& $child[3];
00125 
00126                     if ( $childFunctionName == 'elseif' )
00127                     {
00128                         $compiledElseifCondition = eZTemplateCompiler::processElementTransformationList( $tpl, $child, $childFunctionArgs['condition'], $privateData );
00129                         $nodesToPrepend[] = eZTemplateNodeTool::createVariableNode( false, $compiledElseifCondition,
00130                                                                                     $nodePlacement,
00131                                                                                     array( 'text-result' => true ),
00132                                                                                     "elseif_cond_$uniqid" );
00133                         $newNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode();
00134                         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}\nelseif ( \$elseif_cond_$uniqid )\n{" );
00135                         $newNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode();
00136                         $nodesToAppend[] = eZTemplateNodeTool::createVariableUnsetNode( "elseif_cond_$uniqid" );
00137                         // increment unique elseif counter
00138                         $uniqid        =  md5( $nodePlacement[2] ) . "_" . ++$tpl->ElseifCounter;
00139                     }
00140                     elseif ( $childFunctionName == 'else' )
00141                     {
00142                         $newNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode();
00143                         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}\nelse\n{" );
00144                         $newNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode();
00145                     }
00146                     elseif ( $childFunctionName == 'break' )
00147                         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "break;\n" );
00148                     elseif ( $childFunctionName == 'continue' )
00149                         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "continue;\n" );
00150                     elseif ( $childFunctionName == 'skip' )
00151                         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "\$skipDelimiter = true;\ncontinue;\n" );
00152 
00153                     // let other functions (ones not listed in the conditions above) be transformed
00154                     if ( in_array( $childFunctionName, array( 'elseif', 'else', 'break', 'continue', 'skip' ) ) )
00155                          continue;
00156                 }
00157                 $newNodes[] = $child;
00158             }
00159         }
00160 
00161         $newNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode();
00162         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}" );
00163         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "unset( \$if_cond );" );
00164         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "// if ends\n" );
00165 
00166         $newNodes = array_merge( $nodesToPrepend, $newNodes, $nodesToAppend );
00167 
00168         return $newNodes;
00169     }
00170 
00171     /*!
00172      * Actually executes the function and its children (in processed mode).
00173      */
00174     function process( $tpl, &$textElements, $functionName, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace )
00175     {
00176         if ( count( $functionParameters ) == 0 || !count( $functionParameters['condition'] ) )
00177         {
00178             eZDebug::writeError( "Not enough arguments passed to 'if' function." );
00179             return;
00180         }
00181 
00182         $ifValue = $tpl->elementValue( $functionParameters['condition'], $rootNamespace, $currentNamespace, $functionPlacement );
00183 
00184         $show        = $ifValue; // whether to show the child being currently processing
00185         $showWasTrue = $show;    // true if $show has been assigned 'true' value at least once in the current {if}...{/if} block.
00186         $foundElse   = false;    // true if 'else' has been met once in the current {if}...{/if} block.
00187 
00188         if ( !is_array( $functionChildren ) )
00189         {
00190             return;
00191         }
00192         foreach ( $functionChildren as $key => $child )
00193         {
00194             $childType = $child[0];
00195 
00196             // parse 'elseif', 'else' functions
00197             if ( $childType == eZTemplate::NODE_FUNCTION )
00198             {
00199                 $childFunctionName      =& $child[2];
00200                 $childFunctionArgs      =& $child[3];
00201                 $childFunctionPlacement =& $child[4];
00202 
00203                 if ( $childFunctionName == 'else' )
00204                 {
00205                     if ( $foundElse  )
00206                     {
00207                         eZDebug::writeError( "Duplicated 'else'" );
00208                         $show = false;
00209                         continue;
00210                     }
00211 
00212                     $show = !$showWasTrue;
00213                     $foundElse = true;
00214                     continue;
00215                 }
00216                 elseif ( $childFunctionName == 'elseif' )
00217                 {
00218                     if ( $foundElse  )
00219                     {
00220                         eZDebug::writeError( "There should be no more 'elseif' after 'else'" );
00221                         $show = false;
00222                         continue;
00223                     }
00224 
00225                     if ( !isset( $childFunctionArgs['condition'] ) || !count( $childFunctionArgs['condition'] ) ) // no arguments passes to 'elseif' (should not happen)
00226                         $elseifValue = false;
00227                     else
00228                         $elseifValue = $tpl->elementValue( $childFunctionArgs['condition'], $rootNamespace, $currentNamespace, $functionPlacement );
00229 
00230                     if ( !$showWasTrue && $elseifValue )
00231                         $show = $showWasTrue = true;
00232                     else
00233                         $show = false;
00234                     continue;
00235                 }
00236                 elseif ( $childFunctionName == 'break' )
00237                 {
00238                     if ( !$show )
00239                             continue;
00240                     return array( 'breakFunctionFound' => 1 );
00241                 }
00242                 elseif ( $childFunctionName == 'continue' )
00243                 {
00244                     if ( !$show )
00245                             continue;
00246                     return array( 'continueFunctionFound' => 1 );
00247                 }
00248                 elseif ( $childFunctionName == 'skip' )
00249                 {
00250                     if ( !$show )
00251                             continue;
00252                     return array( 'skipFunctionFound' => 1 );
00253                 }
00254             }
00255 
00256             if ( $show )
00257             {
00258                 $rslt = $tpl->processNode( $child, $textElements, $rootNamespace, $currentNamespace );
00259 
00260                 // handle 'break', 'continue' and 'skip'
00261                 if ( is_array( $rslt ) && ( array_key_exists( 'breakFunctionFound', $rslt ) ||
00262                                             array_key_exists( 'continueFunctionFound', $rslt )  ||
00263                                             array_key_exists( 'skipFunctionFound', $rslt ) ) )
00264                 {
00265                     return $rslt;
00266                 }
00267             }
00268         }
00269     }
00270 
00271     /*!
00272      * Returns true, telling the template parser that the function can have children.
00273      */
00274     function hasChildren()
00275     {
00276         return true;
00277     }
00278 }
00279 
00280 ?>