eZ Publish  [4.0]
eztemplateswitchfunction.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // Definition of eZTemplateSwitchFunction class
00004 //
00005 // Created on: <06-Mar-2002 08:07:54 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 eZTemplateSwitchFunction eztemplateswitchfunction.php
00033   \ingroup eZTemplateFunctions
00034   \brief Handles conditional output in templates using function "switch"
00035 
00036   This allows for writing switch/case sentences (similar to if/else if/else)
00037   which you normally find in programming languages. With this you can display
00038   text depending on a certain template variable.
00039 
00040 \code
00041 // Example template code
00042 {* Matches $a against $b or $c *}
00043 {switch match=$a}
00044 {case match=$b}
00045 Matched $b
00046 {/case}
00047 {case match=$c}
00048 Matched $c
00049 {/case}
00050 {/switch}
00051 
00052 \endcode
00053 
00054 TODO: Add support for custom operations when matching
00055 {case process=$match|gt(5)}
00056 Matched $c
00057 {/case}
00058 
00059 
00060 */
00061 
00062 class eZTemplateSwitchFunction
00063 {
00064     /*!
00065      Initializes the function with the name $name, default is "switch".
00066     */
00067     function eZTemplateSwitchFunction()
00068     {
00069         $this->SwitchName = 'switch';
00070     }
00071 
00072     /*!
00073      Returns an array of the function names, required for eZTemplate::registerFunctions.
00074     */
00075     function functionList()
00076     {
00077         return array( $this->SwitchName );
00078     }
00079 
00080     function functionTemplateHints()
00081     {
00082         return array( $this->SwitchName => array( 'parameters' => true,
00083                                                   'static' => false,
00084                                                   'transform-children' => false,
00085                                                   'tree-transformation' => true,
00086                                                   'transform-parameters' => true ) );
00087     }
00088 
00089     /*!
00090      Returns the attribute list which is case.
00091     */
00092     function attributeList()
00093     {
00094         return array( "case" => true );
00095     }
00096 
00097     function templateNodeCaseTransformation( $tpl, &$newNodes, &$caseNodes, &$caseCounter, &$node, $privateData )
00098     {
00099         if ( $node[2] == 'case' )
00100         {
00101             if ( is_array( $node[3] ) && count( $node[3] ) )
00102             {
00103                 if ( isset( $node[3]['match'] ) )
00104                 {
00105                     $match = $node[3]['match'];
00106                     $match = eZTemplateCompiler::processElementTransformationList( $tpl, $node, $match, $privateData );
00107 
00108                     $dynamicCase = false;
00109                     if ( eZTemplateNodeTool::isStaticElement( $match ) )
00110                     {
00111                         $matchValue = eZTemplateNodeTool::elementStaticValue( $match );
00112                         $caseText = eZPHPCreator::variableText( $matchValue, 0, 0, false );
00113                     }
00114                     else
00115                     {
00116                         $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $match, false, array(), 'case' . $caseCounter );
00117                         $caseText = "\$case" . $caseCounter;
00118                         ++$caseCounter;
00119                         $dynamicCase = true;
00120                     }
00121 
00122                     $caseNodes[] = eZTemplateNodeTool::createCodePieceNode( "    case $caseText:\n    {" );
00123                     if ( $dynamicCase )
00124                         $caseNodes[] = eZTemplateNodeTool::createCodePieceNode( "        unset( $caseText );" );
00125                 }
00126                 else if ( isset( $node[3]['in'] ) )
00127                 {
00128                     return false;
00129                 }
00130             }
00131             else
00132             {
00133                 $caseNodes[] = eZTemplateNodeTool::createCodePieceNode( "    default:\n    {" );
00134             }
00135 
00136             $children = eZTemplateNodeTool::extractFunctionNodeChildren( $node );
00137             if ( $children === false )
00138             {
00139                 $children = array();
00140             }
00141             else
00142             {
00143                 $children = eZTemplateCompiler::processNodeTransformationNodes( $tpl, $node, $children, $privateData );
00144             }
00145 
00146             $caseNodes[] = eZTemplateNodeTool::createSpacingIncreaseNode( 8 );
00147 
00148             $caseNodes = array_merge( $caseNodes, $children );
00149             $caseNodes[] = eZTemplateNodeTool::createSpacingDecreaseNode( 8 );
00150 
00151             $caseNodes[] = eZTemplateNodeTool::createCodePieceNode( "    } break;" );
00152         }
00153     }
00154 
00155 
00156     function templateNodeTransformation( $functionName, &$node,
00157                                          $tpl, $parameters, $privateData )
00158     {
00159         $newNodes = array();
00160         $namespaceValue = false;
00161         $varName = 'match';
00162 
00163         if ( !isset( $parameters['match'] ) )
00164         {
00165             return false;
00166         }
00167 
00168         if ( isset( $parameters['name'] ) )
00169         {
00170             $nameData = $parameters['name'];
00171             if ( !eZTemplateNodeTool::isStaticElement( $nameData ) )
00172                 return false;
00173             $namespaceValue = eZTemplateNodeTool::elementStaticValue( $nameData );
00174         }
00175 
00176         if ( isset( $parameters['var'] ) )
00177         {
00178             $varData = $parameters['var'];
00179             if ( !eZTemplateNodeTool::isStaticElement( $varData ) )
00180                 return false;
00181             $varName = eZTemplateNodeTool::elementStaticValue( $varData );
00182         }
00183 
00184         $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['match'], false, array(),
00185                                                               array( $namespaceValue, eZTemplate::NAMESPACE_SCOPE_RELATIVE, $varName ) );
00186         $newNodes[] = eZTemplateNodeTool::createVariableNode( false, $parameters['match'],
00187                                                               eZTemplateNodeTool::extractFunctionNodePlacement( $node ),
00188                                                               array( 'variable-name' => 'match',
00189                                                                      'text-result' => true ), 'match' );
00190 //                                                                       'text-result' => false ) );
00191         if ( isset( $parameters['name'] ) )
00192         {
00193             $newNodes[] = eZTemplateNodeTool::createNamespaceChangeNode( $parameters['name'] );
00194         }
00195 
00196         $tmpNodes = array();
00197         $children = eZTemplateNodeTool::extractFunctionNodeChildren( $node );
00198         $caseNodes = array();
00199         $caseCounter = 1;
00200         if ( is_array( $children ) )
00201         {
00202             foreach ( $children as $child )
00203             {
00204                 $childType = $child[0];
00205                 if ( $childType == eZTemplate::NODE_FUNCTION )
00206                 {
00207                     if ( $this->templateNodeCaseTransformation( $tpl, $tmpNodes, $caseNodes, $caseCounter, $child, $privateData ) === false )
00208                     {
00209                         return false;
00210                     }
00211                 }
00212             }
00213         }
00214         $newNodes = array_merge( $newNodes, $tmpNodes );
00215         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "switch ( \$match )\n{" );
00216         $newNodes = array_merge( $newNodes, $caseNodes );
00217 
00218         $newNodes[] = eZTemplateNodeTool::createCodePieceNode( "}" );
00219         $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( 'match' );
00220         if ( isset( $parameters['name'] ) )
00221         {
00222             $newNodes[] = eZTemplateNodeTool::createNamespaceRestoreNode();
00223         }
00224         $newNodes[] = eZTemplateNodeTool::createVariableUnsetNode( array( $namespaceValue, eZTemplate::NAMESPACE_SCOPE_RELATIVE, 'match' ) );
00225 
00226         return $newNodes;
00227     }
00228 
00229     /*!
00230      Processes the function with all it's children.
00231     */
00232     function process( $tpl, &$textElements, $functionName, $functionChildren, $functionParameters, $functionPlacement, $rootNamespace, $currentNamespace )
00233     {
00234         $children = $functionChildren;
00235         $params = $functionParameters;
00236         $name = "";
00237         if ( isset( $params["name"] ) )
00238             $name = $tpl->elementValue( $params["name"], $rootNamespace, $currentNamespace, $functionPlacement );
00239         $varName = false;
00240         if ( isset( $params["var"] ) )
00241             $varName = $tpl->elementValue( $params["var"], $rootNamespace, $currentNamespace, $functionPlacement );
00242         if ( $currentNamespace != "" )
00243         {
00244             if ( $name != "" )
00245                 $name = "$currentNamespace:$name";
00246             else
00247                 $name = $currentNamespace;
00248         }
00249         if ( isset( $params["match"] ) )
00250             $match = $tpl->elementValue( $params["match"], $rootNamespace, $currentNamespace, $functionPlacement );
00251         else
00252         {
00253             $tpl->missingParameter( $this->SwitchName, "match" );
00254             return false;
00255         }
00256 
00257         $items = array();
00258         $in_items = array();
00259         $def = null;
00260         $case = null;
00261         if ( is_array( $children ) )
00262         {
00263             foreach( $children as $child )
00264             {
00265                 $childType = $child[0];
00266                 if ( $childType == eZTemplate::NODE_FUNCTION )
00267                 {
00268                     switch ( $child[2] )
00269                     {
00270                         case "case":
00271                         {
00272                             $child_params = $child[3];
00273                             if ( isset( $child_params["match"] ) )
00274                             {
00275                                 $child_match = $child_params["match"];
00276                                 $child_match = $tpl->elementValue( $child_match, $rootNamespace, $currentNamespace, $functionPlacement );
00277                                 if ( !isset( $items[$child_match] ) )
00278                                 {
00279                                     $items[$child_match] = $child;
00280                                     if ( is_null( $case ) and
00281                                          $match == $child_match )
00282                                     {
00283                                         $case = $child;
00284                                     }
00285                                 }
00286                                 else
00287                                 {
00288                                     $tpl->warning( $this->SwitchName, "Match value $child_match already set, skipping", $functionPlacement );
00289                                 }
00290                             }
00291                             else if ( isset( $child_params["in"] ) )
00292                             {
00293                                 $key_name = null;
00294                                 if ( isset( $child_params["key"] ) )
00295                                 {
00296                                     $child_key = $child_params["key"];
00297                                     $key_name = $tpl->elementValue( $child_key, $rootNamespace, $currentNamespace, $functionPlacement );
00298                                 }
00299                                 $child_in = $child_params["in"];
00300                                 $child_in = $tpl->elementValue( $child_in, $rootNamespace, $currentNamespace, $functionPlacement );
00301                                 if ( !is_array( $child_in ) )
00302                                     break;
00303                                 if ( is_null( $case ) )
00304                                 {
00305                                     if ( is_null( $key_name ) )
00306                                     {
00307                                         if ( in_array( $match, $child_in ) )
00308                                         {
00309                                             $case = $child;
00310                                         }
00311                                     }
00312                                     else
00313                                     {
00314                                         foreach( $child_in as $child_in_element )
00315                                         {
00316                                             if ( !is_array( $key_name ) )
00317                                                 $key_name_array = array( $key_name );
00318                                             else
00319                                                 $key_name_array = $key_name;
00320                                             $child_value = $tpl->variableAttribute( $child_in_element, $key_name );
00321                                             if ( $child_value == $match )
00322                                             {
00323                                                 $case = $child;
00324                                                 break;
00325                                             }
00326                                         }
00327                                     }
00328                                 }
00329                             }
00330                             else
00331                             {
00332                                 $def = $child;
00333                             }
00334                         } break;
00335                         default:
00336                         {
00337                             $tpl->warning( $this->SwitchName, "Only case functions are allowed as children, found \""
00338                                            . $child[2] . "\"", $functionPlacement );
00339                         } break;
00340                     }
00341                 }
00342                 else if ( $childType == eZTemplate::NODE_TEXT )
00343                 {
00344                     // Ignore text.
00345                 }
00346                 else
00347                 {
00348                     $tpl->warning( $this->SwitchName, "Only functions are allowed as children, found \""
00349                                    . $childType . "\"", $functionPlacement );
00350                 }
00351             }
00352         }
00353 
00354         if ( is_null( $case ) )
00355         {
00356             $case = $def;
00357         }
00358 
00359         if ( $case !== null )
00360         {
00361             if ( $varName !== false )
00362                 $tpl->setVariable( $varName, $match, $name );
00363             else
00364                 $tpl->setVariable( "match", $match, $name );
00365             $case_children = $case[1];
00366             if ( $case_children )
00367             {
00368                 foreach( $case_children as $case_child )
00369                 {
00370                     $tpl->processNode( $case_child, $textElements, $rootNamespace, $name );
00371                 }
00372             }
00373         }
00374         else
00375             $tpl->warning( $this->SwitchName, "No case match and no default case", $functionPlacement );
00376         return;
00377     }
00378 
00379     /*!
00380      Returns true.
00381     */
00382     function hasChildren()
00383     {
00384         return true;
00385     }
00386 
00387     /// The name of the switch function
00388     public $SwitchName;
00389 }
00390 
00391 ?>