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