Exponential 6.0.13 Exponential Enterprise Open Source CMS - PHP Class Reference

eztemplatecompiler.php
Go to the documentation of this file.
1 <?php
47 class eZTemplateCompiler
48 {
49 const CODE_DATE = 1074699607;
50
55 static function TemplatePrefix()
56 {
57 $templatePrefix = '';
58 $ini = eZINI::instance();
59 if ( $ini->variable( 'TemplateSettings', 'TemplateCompression' ) == 'enabled' )
60 {
61 $templatePrefix = 'compress.zlib://';
62 }
63 return $templatePrefix;
64 }
82 static function setSettings( $settingsMap )
83 {
84 $existingMap = array();
85 if ( isset( $GLOBALS['eZTemplateCompilerSettings'] ) )
86 {
87 $existingMap = $GLOBALS['eZTemplateCompilerSettings'];
88 }
89 $GLOBALS['eZTemplateCompilerSettings'] = array_merge( $existingMap, $settingsMap );
90 }
91
97 static function isCompilationEnabled()
98 {
99 if ( isset( $GLOBALS['eZSiteBasics'] ) )
100 {
101 $siteBasics = $GLOBALS['eZSiteBasics'];
102 if ( isset( $siteBasics['no-cache-adviced'] ) and
103 $siteBasics['no-cache-adviced'] )
104 {
105 return false;
106 }
107 }
108
109 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['compile'] ) and
110 $GLOBALS['eZTemplateCompilerSettings']['compile'] !== null )
111 {
112 return $GLOBALS['eZTemplateCompilerSettings']['compile'];
113 }
114
115 $ini = eZINI::instance();
116 $compilationEnabled = $ini->variable( 'TemplateSettings', 'TemplateCompile' ) == 'enabled';
117 return $compilationEnabled;
118 }
119
124 static function isCommentsEnabled()
125 {
126 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['comments'] ) and
127 $GLOBALS['eZTemplateCompilerSettings']['comments'] !== null )
128 {
129 return $GLOBALS['eZTemplateCompilerSettings']['comments'];
130 }
131
132 $ini = eZINI::instance();
133 $commentsEnabled = $ini->variable( 'TemplateSettings', 'CompileComments' ) == 'enabled';
134 return $commentsEnabled;
135 }
136
147 static function isDevelopmentModeEnabled()
148 {
149 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['development_mode'] ) and
150 $GLOBALS['eZTemplateCompilerSettings']['development_mode'] !== null )
151 {
152 return $GLOBALS['eZTemplateCompilerSettings']['development_mode'];
153 }
154
155 $ini = eZINI::instance();
156 $developmentModeEnabled = $ini->variable( 'TemplateSettings', 'DevelopmentMode' ) == 'enabled';
157 return $developmentModeEnabled;
158 }
159
164 static function isAccumulatorsEnabled()
165 {
166 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['accumulators'] ) and
167 $GLOBALS['eZTemplateCompilerSettings']['accumulators'] !== null )
168 {
169 return $GLOBALS['eZTemplateCompilerSettings']['accumulators'];
170 }
171
172 $ini = eZINI::instance();
173 $enabled = $ini->variable( 'TemplateSettings', 'CompileAccumulators' ) == 'enabled';
174 return $enabled;
175 }
176
181 static function isTimingPointsEnabled()
182 {
183 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['timingpoints'] ) and
184 $GLOBALS['eZTemplateCompilerSettings']['timingpoints'] !== null )
185 {
186 return $GLOBALS['eZTemplateCompilerSettings']['timingpoints'];
187 }
188
189 $ini = eZINI::instance();
190 $enabled = $ini->variable( 'TemplateSettings', 'CompileTimingPoints' ) == 'enabled';
191 return $enabled;
192 }
193
198 static function isFallbackResourceCodeEnabled()
199 {
200 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'] ) and
201 $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'] !== null )
202 {
203 return $GLOBALS['eZTemplateCompilerSettings']['fallbackresource'];
204 }
205
206 $ini = eZINI::instance();
207 $enabled = $ini->variable( 'TemplateSettings', 'CompileResourceFallback' ) == 'enabled';
208 return $enabled;
209 }
210
215 static function isNodePlacementEnabled()
216 {
217 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'] ) and
218 $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'] !== null )
219 {
220 return $GLOBALS['eZTemplateCompilerSettings']['nodeplacement'];
221 }
222
223 $ini = eZINI::instance();
224 $nodePlacementEnabled = $ini->variable( 'TemplateSettings', 'CompileNodePlacements' ) == 'enabled';
225 return $nodePlacementEnabled;
226 }
227
232 static function isExecutionEnabled()
233 {
234 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['execution'] ) and
235 $GLOBALS['eZTemplateCompilerSettings']['execution'] !== null )
236 {
237 return $GLOBALS['eZTemplateCompilerSettings']['execution'];
238 }
239
240 $ini = eZINI::instance();
241 $execution = $ini->variable( 'TemplateSettings', 'CompileExecution' ) == 'enabled';
242 return $execution;
243 }
244
249 static function alwaysGenerate()
250 {
251 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['generate'] ) and
252 $GLOBALS['eZTemplateCompilerSettings']['generate'] !== null )
253 {
254 return $GLOBALS['eZTemplateCompilerSettings']['generate'];
255 }
256
257 $ini = eZINI::instance();
258 $alwaysGenerate = $ini->variable( 'TemplateSettings', 'CompileAlwaysGenerate' ) == 'enabled';
259 return $alwaysGenerate;
260 }
261
266 static function isTreeEnabled( $treeName )
267 {
268 $ini = eZINI::instance();
269 $treeList = $ini->variable( 'TemplateSettings', 'CompileIncludeNodeTree' );
270 return in_array( $treeName, $treeList );
271 }
272
277 static function compilationDirectory()
278 {
279 if ( isset( $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'] ) and
280 $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'] !== null )
281 {
282 return $GLOBALS['eZTemplateCompilerSettings']['compilation-directory'];
283 }
284
285 $compilationDirectory =& $GLOBALS['eZTemplateCompilerDirectory'];
286 if ( !isset( $compilationDirectory ) )
287 {
288 $ini = eZINI::instance();
289 $shareTemplates = $ini->hasVariable( 'TemplateSettings', 'ShareCompiledTemplates' ) ?
290 $ini->variable( 'TemplateSettings', 'ShareCompiledTemplates' ) == 'enabled' :
291 false;
292 if ( $shareTemplates &&
293 $ini->hasVariable( 'TemplateSettings', 'SharedCompiledTemplatesDir' ) &&
294 trim( $ini->variable( 'TemplateSettings', 'SharedCompiledTemplatesDir' ) ) != '' )
295 {
296 $compilationDirectory = eZDir::path( array( $ini->variable( 'TemplateSettings', 'SharedCompiledTemplatesDir' ) ) );
297 }
298 else
299 {
300 $compilationDirectory = eZDir::path( array( eZSys::cacheDirectory(), 'template/compiled' ) );
301 }
302 }
303 return $compilationDirectory;
304 }
305
310 static function compilationFilename( $key, $resourceData )
311 {
312 $internalCharset = eZTextCodec::internalCharset();
313 $templateFilepath = $resourceData['template-filename'];
314 $extraName = '';
315 if ( preg_match( "#^.+/(.*)\.tpl$#", $templateFilepath, $matches ) )
316 $extraName = $matches[1] . '-';
317 else if ( preg_match( "#^(.*)\.tpl$#", $templateFilepath, $matches ) )
318 $extraName = $matches[1] . '-';
319 $accessText = false;
320 if ( isset( $GLOBALS['eZCurrentAccess']['name'] ) )
321 $accessText = '-' . $GLOBALS['eZCurrentAccess']['name'];
322 $locale = eZLocale::instance();
323 $language = $locale->localeFullCode();
324 $http = eZHTTPTool::instance();
325 $useFullUrlText = $http->UseFullUrl ? 'full' : 'relative';
326
327 $pageLayoutVariable = "";
328 if ( isset( $GLOBALS['eZCustomPageLayout'] ) )
329 $pageLayoutVariable = $GLOBALS['eZCustomPageLayout'];
330
331 $ini = eZINI::instance();
332
333 $shareTemplates = $ini->hasVariable( 'TemplateSettings', 'ShareCompiledTemplates' ) ?
334 $ini->variable( 'TemplateSettings', 'ShareCompiledTemplates' ) == 'enabled' :
335 false;
336
337 if ( $shareTemplates )
338 $cacheFileKey = $key . '-' . $language;
339 else
340 $cacheFileKey = $key . '-' . $internalCharset . '-' . $language . '-' . $useFullUrlText . $accessText . "-" . $pageLayoutVariable . '-' . eZSys::indexFile();
341
342 $cacheFileName = $extraName . md5( $cacheFileKey ) . '.php';
343 return $cacheFileName;
344 }
345
352 static function hasCompiledTemplate( $key, $timestamp, &$resourceData )
353 {
354 if ( !eZTemplateCompiler::isCompilationEnabled() )
355 return false;
356 if ( eZTemplateCompiler::alwaysGenerate() )
357 return false;
358
359 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData );
360
361 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), $cacheFileName, eZTemplateCompiler::TemplatePrefix() );
362 $canRestore = $php->canRestore( $timestamp );
363 $uri = false;
364 if ( $canRestore )
365 eZDebugSetting::writeDebug( 'eztemplate-compile', "Cache hit for uri '$uri' with key '$key'", 'eZTemplateCompiler::hasCompiledTemplate' );
366 else
367 eZDebugSetting::writeDebug( 'eztemplate-compile', "Cache miss for uri '$uri' with key '$key'", 'eZTemplateCompiler::hasCompiledTemplate' );
368 return $canRestore;
369 }
370
387 static function executeCompilation( $tpl, &$textElements, $key, &$resourceData,
388 $rootNamespace, $currentNamespace )
389 {
390 if ( !eZTemplateCompiler::isCompilationEnabled() )
391 return false;
392 if ( !eZTemplateCompiler::isExecutionEnabled() )
393 return false;
394 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData );
395 $resourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled();
396
397 $directory = eZTemplateCompiler::compilationDirectory();
398 $phpScript = eZDir::path( array( $directory, $cacheFileName ) );
399 if ( file_exists( $phpScript ) )
400 {
401 $text = false;
402 $helperStatus = eZTemplateCompiler::executeCompilationHelper( $phpScript, $text,
403 $tpl, $key, $resourceData,
404 $rootNamespace, $currentNamespace );
405 if ( $helperStatus )
406 {
407 $textElements[] = $text;
408 return true;
409 }
410 else
411 {
412 eZDebug::writeError(
413 "Failed executing compiled template '$phpScript',"
414 . " if this file is valid, then the error is probably"
415 . " related to APC usage, try restarting the webserver",
416 __METHOD__
417 );
418 throw new eZTemplateFailedExecutingCompiledTemplate(
419 "Failed executing a compiled template, see error.log for details"
420 );
421 }
422 }
423 else
424 eZDebug::writeError( "Unknown compiled template '$phpScript'", __METHOD__ );
425 return false;
426 }
427
435 static function executeCompilationHelper( $phpScript, &$text,
436 $tpl, $key, &$resourceData,
437 $rootNamespace, $currentNamespace )
438 {
439 $vars =& $tpl->Variables;
440
441 /* We use $setArray to detect if execution failed, and not $text,
442 * because an empty template does not return any $text and this is not
443 * an error. */
444 $setArray = null;
445 $namespaceStack = array();
446
447 $tpl->createLocalVariablesList();
448 include( eZTemplateCompiler::TemplatePrefix() . $phpScript );
449 $tpl->unsetLocalVariables();
450 $tpl->destroyLocalVariablesList();
451
452 if ( $setArray !== null )
453 {
454 return true;
455 }
456 return false;
457 }
458
465 static function compileTemplate( $tpl, $key, &$resourceData )
466 {
467 if ( !eZTemplateCompiler::isCompilationEnabled() )
468 return false;
469
470 $resourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled();
471
472 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $resourceData );
473 $resourceData['uniqid'] = md5( $resourceData['template-filename']. uniqid( "ezp". getmypid(), true ) );
474
475 // Time limit #1:
476 // We reset the time limit to 30 seconds to ensure that templates
477 // have enough time to compile
478 // However if time limit is unlimited (0) we leave it be
479 // Time limit will also be reset after subtemplates are compiled
480 $maxExecutionTime = ini_get( 'max_execution_time' );
481 if ( $maxExecutionTime != 0 && $maxExecutionTime < 30 )
482 {
483 @set_time_limit( 30 );
484 }
485
486 $rootNode =& $resourceData['root-node'];
487 if ( !$rootNode )
488 return false;
489
490 $GLOBALS['eZTemplateCompilerResourceCache'][$resourceData['template-filename']] =& $resourceData;
491
492 $useComments = eZTemplateCompiler::isCommentsEnabled();
493
494 if ( !$resourceData['test-compile'] )
495 {
496 eZTemplateCompiler::createCommonCompileTemplate();
497 }
498
499 /* Check if we need to disable the generation of spacing for the compiled templates */
500 $ini = eZINI::instance();
501 $spacing = 'disabled';
502 if ( $ini->variable( 'TemplateSettings', 'UseFormatting' ) == 'enabled' )
503 {
504 $spacing = 'enabled';
505 }
506
507 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), $cacheFileName,
508 eZTemplateCompiler::TemplatePrefix(), array( 'spacing' => $spacing ) );
509 $php->addComment( 'URI: ' . $resourceData['uri'] );
510 $php->addComment( 'Filename: ' . $resourceData['template-filename'] );
511 $php->addComment( 'Timestamp: ' . $resourceData['time-stamp'] . ' (' . date( 'D M j G:i:s T Y', $resourceData['time-stamp'] ) . ')' );
512
513 $php->addCodePiece("\$oldSetArray_{$resourceData['uniqid']} = isset( \$setArray ) ? \$setArray : array();\n".
514 "\$setArray = array();\n");
515 // Code to decrement include level of the templates
516 $php->addCodePiece( "\$tpl->Level++;\n" );
517 $php->addCodePiece( "if ( \$tpl->Level > $tpl->MaxLevel )\n".
518 "{\n".
519 "\$text = \$tpl->MaxLevelWarning;".
520 "\$tpl->Level--;\n".
521 "return;\n".
522 "}\n" );
523 if ( $resourceData['locales'] && count( $resourceData['locales'] ) )
524 {
525 $php->addComment( 'Locales: ' . join( ', ', $resourceData['locales'] ) );
526
527 $php->addCodePiece(
528 '$locales = array( "'. join( '", "', $resourceData['locales'] ) . "\" );\n".
529 '$oldLocale_'. $resourceData['uniqid']. ' = setlocale( LC_CTYPE, null );'. "\n".
530 '$currentLocale_'. $resourceData['uniqid']. ' = setlocale( LC_CTYPE, $locales );'. "\n"
531 );
532 }
533 // $php->addCodePiece( "print( \"" . $resourceData['template-filename'] . " ($cacheFileName)<br/>\n\" );" );
534 if ( $useComments )
535 {
536 $templateFilename = $resourceData['template-filename'];
537 if ( file_exists( $templateFilename ) )
538 {
539 $fd = fopen( $templateFilename, 'rb' );
540 if ( $fd )
541 {
542 $templateText = fread( $fd, filesize( $templateFilename ) );
543 $php->addComment( "Original code:\n" . $templateText );
544 fclose( $fd );
545 }
546 }
547 }
548 $php->addVariable( 'eZTemplateCompilerCodeDate', eZTemplateCompiler::CODE_DATE );
549 $php->addCodePiece( "if ( !defined( 'EZ_TEMPLATE_COMPILER_COMMON_CODE' ) )\n" );
550 $php->addInclude( eZTemplateCompiler::compilationDirectory() . '/common.php', eZPHPCreator::INCLUDE_ONCE_STATEMENT, array( 'spacing' => 4 ) );
551 $php->addSpace();
552
553 if ( eZTemplateCompiler::isAccumulatorsEnabled() )
554 {
555 $php->addCodePiece( "eZDebug::accumulatorStart( 'template_compiled_execution', 'template_total', 'Template compiled execution', true );\n" );
556 }
557 if ( eZTemplateCompiler::isTimingPointsEnabled() )
558 {
559 $php->addCodePiece( "eZDebug::addTimingPoint( 'Script start $cacheFileName' );\n" );
560 }
561
562 // $php->addCodePiece( "if ( !isset( \$vars ) )\n \$vars =& \$tpl->Variables;\n" );
563 // $php->addSpace();
564
565 $parameters = array();
566 $textName = eZTemplateCompiler::currentTextName( $parameters );
567
568 // $php->addCodePiece( "if ( !isset( \$$textName ) )\n \$$textName = '';\n" );
569 // $php->addSpace();
570
571 $transformedTree = array();
572 eZTemplateCompiler::processNodeTransformation( $useComments, $php, $tpl, $rootNode, $resourceData, $transformedTree );
573
574 if ( $ini->variable( 'TemplateSettings', 'TemplateOptimization' ) == 'enabled' )
575 {
576 /* Retrieve class information for the attribute lookup table */
577 if ( isset( $resourceData['handler']->Keys ) and isset( $resourceData['handler']->Keys['class'] ) ) {
578 $resourceData['class-info'] = eZTemplateOptimizer::fetchClassDeclaration( $resourceData['handler']->Keys['class'] );
579 }
580 /* Run the optimizations */
581 eZTemplateOptimizer::optimize( $useComments, $php, $tpl, $transformedTree, $resourceData );
582 }
583
584 $staticTree = array();
585 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, $transformedTree, $resourceData, $staticTree );
586
587 $combinedTree = array();
588 eZTemplateCompiler::processNodeCombining( $useComments, $php, $tpl, $staticTree, $resourceData, $combinedTree );
589
590 $finalTree = $combinedTree;
591 if ( !eZTemplateCompiler::isNodePlacementEnabled() )
592 eZTemplateCompiler::processRemoveNodePlacement( $finalTree );
593
594 eZTemplateCompiler::generatePHPCode( $useComments, $php, $tpl, $finalTree, $resourceData );
595
596 if ( eZTemplateCompiler::isTreeEnabled( 'final' ) )
597 $php->addVariable( 'finalTree', $finalTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) );
598 if ( eZTemplateCompiler::isTreeEnabled( 'combined' ) )
599 $php->addVariable( 'combinedTree', $combinedTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) );
600 if ( eZTemplateCompiler::isTreeEnabled( 'static' ) )
601 $php->addVariable( 'staticTree', $staticTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) );
602 if ( eZTemplateCompiler::isTreeEnabled( 'transformed' ) )
603 $php->addVariable( 'transformedTree', $transformedTree, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) );
604 if ( eZTemplateCompiler::isTreeEnabled( 'original' ) )
605 $php->addVariable( 'originalTree', $rootNode, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'full-tree' => true ) );
606
607 if ( eZTemplateCompiler::isTimingPointsEnabled() )
608 $php->addCodePiece( "eZDebug::addTimingPoint( 'Script end $cacheFileName' );\n" );
609 if ( eZTemplateCompiler::isAccumulatorsEnabled() )
610 $php->addCodePiece( "eZDebug::accumulatorStop( 'template_compiled_execution', true );\n" );
611
612 if ( $resourceData['locales'] && count( $resourceData['locales'] ) )
613 {
614 $php->addCodePiece(
615 'setlocale( LC_CTYPE, $oldLocale_'. $resourceData['uniqid']. ' );'. "\n"
616 );
617 }
618 $php->addCodePiece('$setArray = $oldSetArray_'. $resourceData['uniqid']. ";\n");
619
620 // Code to decrement include level of the templates
621 $php->addCodePiece("\$tpl->Level--;\n" );
622
623 /*
624 // dump names of all defined PHP variables
625 $php->addCodePiece( "echo \"defined vars in $resourceData[uri]:<br/><pre>\\n\";\n" );
626 $php->addCodePiece( 'foreach ( array_keys( get_defined_vars() ) as $var_name ) echo "- $var_name\n";' );
627 // dump tpl vars
628 $php->addCodePiece( 'echo "\n-----------------------------------------------------------\nvars: ";' );
629 $php->addCodePiece( 'var_dump( $vars );' );
630 $php->addCodePiece( 'echo "</pre><hr/>\n";' );
631 */
632
633 if ( !$resourceData['test-compile'] )
634 {
635 $php->store( true );
636 }
637
638 return true;
639 }
640
647 static function processNodeCombining( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode )
648 {
649 $nodeType = $node[0];
650 if ( $nodeType == eZTemplate::NODE_ROOT )
651 {
652 $children = $node[1];
653 $newNode[0] = $nodeType;
654 $newNode[1] = false;
655 if ( $children )
656 {
657 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, $children, $resourceData, $newNode );
658 }
659 }
660 else
661 $tpl->error( 'processNodeCombining', "Unknown root type $nodeType, should be " . eZTemplate::NODE_ROOT );
662 }
663
668 static function processNodeCombiningChildren( $useComments, $php, $tpl, &$nodeChildren, &$resourceData, &$parentNode )
669 {
670 $newNodeChildren = array();
671 $lastNode = false;
672 foreach ( $nodeChildren as $node )
673 {
674 $newNode = false;
675 if ( !isset( $node[0] ) )
676 continue;
677 $nodeType = $node[0];
678 if ( $nodeType == eZTemplate::NODE_ROOT )
679 {
680 $children = $node[1];
681 $newNode = array( $nodeType,
682 false );
683 if ( $children )
684 {
685 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl, $children, $resourceData, $newNode );
686 }
687 }
688 else if ( $nodeType == eZTemplate::NODE_TEXT )
689 {
690 $text = $node[2];
691 $placement = $node[3];
692
693 $newNode = array( $nodeType,
694 false,
695 $text,
696 $placement );
697 eZTemplateCompiler::combineStaticNodes( $tpl, $resourceData, $lastNode, $newNode );
698 }
699 else if ( $nodeType == eZTemplate::NODE_VARIABLE )
700 {
701 $variableCustom = $node[1];
702 $variableData = $node[2];
703 $variablePlacement = $node[3];
704 $variableParameters = false;
705 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
706 $variableData, $variablePlacement,
707 $resourceData );
708 $newNode = $node;
709 $newNode[1] = $variableCustom;
710 unset( $dataInspection );
711 eZTemplateCompiler::combineStaticNodes( $tpl, $resourceData, $lastNode, $newNode );
712 }
713 else if ( $nodeType == eZTemplate::NODE_FUNCTION )
714 {
715 $functionChildren = $node[1];
716 $functionName = $node[2];
717 $functionParameters = $node[3];
718 $functionPlacement = $node[4];
719
720 $newNode = array( $nodeType,
721 false,
722 $functionName,
723 $functionParameters,
724 $functionPlacement );
725 if ( isset( $node[5] ) )
726 $newNode[5] = $node[5];
727
728 if ( is_array( $functionChildren ) )
729 {
730 eZTemplateCompiler::processNodeCombiningChildren( $useComments, $php, $tpl,
731 $functionChildren, $resourceData, $newNode );
732 }
733
734 }
735 else
736 $newNode = $node;
737 if ( $lastNode != false )
738 {
739 $newNodeChildren[] = $lastNode;
740 $lastNode = false;
741 }
742 if ( $newNode != false )
743 $lastNode = $newNode;
744 }
745 if ( $lastNode != false )
746 {
747 $newNodeChildren[] = $lastNode;
748 $lastNode = false;
749 }
750 $parentNode[1] = $newNodeChildren;
751 }
752
760 static function combineStaticNodes( $tpl, &$resourceData, &$lastNode, &$newNode )
761 {
762 if ( $lastNode == false or
763 $newNode == false )
764 return false;
765 $lastNodeType = $lastNode[0];
766 $newNodeType = $newNode[0];
767 if ( !in_array( $lastNodeType, array( eZTemplate::NODE_TEXT,
768 eZTemplate::NODE_VARIABLE ) ) or
769 !in_array( $newNodeType, array( eZTemplate::NODE_TEXT,
770 eZTemplate::NODE_VARIABLE ) ) )
771 return false;
772 if ( $lastNodeType == eZTemplate::NODE_VARIABLE )
773 {
774 if ( is_array( $lastNode[1] ) )
775 return false;
776 $lastDataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
777 $lastNode[2], $lastNode[3],
778 $resourceData );
779 if ( !$lastDataInspection['is-constant'] or
780 $lastDataInspection['is-variable'] or
781 $lastDataInspection['has-attributes'] or
782 $lastDataInspection['has-operators'] )
783 return false;
784 if ( isset( $lastNode[4] ) and
785 isset( $lastNode[4]['text-result'] ) and
786 !$lastNode[4]['text-result'] )
787 return false;
788 }
789 if ( $newNodeType == eZTemplate::NODE_VARIABLE )
790 {
791 if ( is_array( $newNode[1] ) )
792 return false;
793 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
794 $newNode[2], $newNode[3],
795 $resourceData );
796 if ( !$newDataInspection['is-constant'] or
797 $newDataInspection['is-variable'] or
798 $newDataInspection['has-attributes'] or
799 $newDataInspection['has-operators'] )
800 return false;
801 if ( isset( $newNode[4] ) and
802 isset( $newNode[4]['text-result'] ) and
803 !$newNode[4]['text-result'] )
804 return false;
805 if ( isset( $newNode[1] ) and
806 $newNode[1] !== false )
807 return false;
808 }
809 $textElements = array();
810 $lastNodeData = eZTemplateCompiler::staticNodeData( $lastNode );
811 $newNodeData = eZTemplateCompiler::staticNodeData( $newNode );
812 $tpl->appendElementText( $textElements, $lastNodeData, false, false );
813 $tpl->appendElementText( $textElements, $newNodeData, false, false );
814 $newData = implode( '', $textElements );
815 // Create a normalized placement structure with two sub-arrays [start, end]
816 $newPlacement = array(
817 0 => array(null, null, null),
818 1 => array(null, null, null)
819 );
820
821 // Prefer lastNode placement if valid
822 if ( isset($lastNode[3]) && is_array($lastNode[3]) ) {
823 $newPlacement = $lastNode[3];
824 }
825
826 // If lastNode didn't provide usable placement, try newNode
827 if ( (!isset($newPlacement[1]) || !is_array($newPlacement[1])) && isset($newNode[3]) && is_array($newNode[3]) ) {
828 $newPlacement = $newNode[3];
829 }
830
831 // Ensure both start(0) and end(1) arrays exist and have keys 0..2
832 if ( !isset($newPlacement[0]) || !is_array($newPlacement[0]) ) {
833 $newPlacement[0] = array(null, null, null);
834 } else {
835 $newPlacement[0][0] = $newPlacement[0][0] ?? null;
836 $newPlacement[0][1] = $newPlacement[0][1] ?? null;
837 $newPlacement[0][2] = $newPlacement[0][2] ?? null;
838 }
839
840 if ( !isset($newPlacement[1]) || !is_array($newPlacement[1]) ) {
841 $newPlacement[1] = array(null, null, null);
842 } else {
843 $newPlacement[1][0] = $newPlacement[1][0] ?? null;
844 $newPlacement[1][1] = $newPlacement[1][1] ?? null;
845 $newPlacement[1][2] = $newPlacement[1][2] ?? null;
846 }
847
848 // Merge end values from $newNode if they exist (non-destructive)
849 if ( isset($newNode[3]) && is_array($newNode[3]) && isset($newNode[3][1]) && is_array($newNode[3][1]) ) {
850 $newPlacement[1][0] = $newNode[3][1][0] ?? $newPlacement[1][0];
851 $newPlacement[1][1] = $newNode[3][1][1] ?? $newPlacement[1][1];
852 $newPlacement[1][2] = $newNode[3][1][2] ?? $newPlacement[1][2];
853 }
854 /* --- End: safer placement merge --- */
855 $lastNode = false;
856 $newNode = array( eZTemplate::NODE_TEXT,
857 false,
858 $newData,
859 $newPlacement );
860 }
861
868 static function staticNodeData( $node )
869 {
870 $nodeType = $node[0];
871 if ( $nodeType == eZTemplate::NODE_TEXT )
872 {
873 return $node[2];
874 }
875 else if ( $nodeType == eZTemplate::NODE_VARIABLE )
876 {
877 $data = $node[2];
878 if ( is_array( $data ) and
879 count( $data ) > 0 )
880 {
881 $dataType = $data[0][0];
882 if ( $dataType == eZTemplate::TYPE_STRING or
883 $dataType == eZTemplate::TYPE_NUMERIC or
884 $dataType == eZTemplate::TYPE_IDENTIFIER or
885 $dataType == eZTemplate::TYPE_ARRAY or
886 $dataType == eZTemplate::TYPE_BOOLEAN )
887 {
888 return $data[0][1];
889 }
890 }
891 }
892 return null;
893 }
894
899 static function processStaticOptimizations( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode )
900 {
901 $nodeType = $node[0];
902 if ( $nodeType == eZTemplate::NODE_ROOT )
903 {
904 $children = $node[1];
905 $newNode[0] = $nodeType;
906 $newNode[1] = false;
907 if ( $children )
908 {
909 $newNode[1] = array();
910 foreach ( $children as $child )
911 {
912 $newChild = array();
913 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl, $child, $resourceData, $newChild );
914 $newNode[1][] = $newChild;
915 }
916 }
917 }
918 else if ( $nodeType == eZTemplate::NODE_TEXT )
919 {
920 $text = $node[2];
921 if( isset( $node[3] ) )
922 $placement = $node[3];
923 else
924 $placement = array( array(), array(), null);
925
926 $newNode[0] = $nodeType;
927 $newNode[1] = false;
928 $newNode[2] = $text;
929 $newNode[3] = $placement;
930 }
931 else if ( $nodeType == eZTemplate::NODE_VARIABLE )
932 {
933 $variableCustom = $node[1];
934 $variableData = $node[2];
935 $variablePlacement = $node[3];
936 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
937 $variableData, $variablePlacement,
938 $resourceData );
939 if ( isset( $dataInspection['new-data'] ) )
940 {
941 $variableData = $dataInspection['new-data'];
942 }
943 $newNode = $node;
944 $newNode[1] = $variableCustom;
945 $newNode[2] = $variableData;
946 unset( $dataInspection );
947 }
948 else if ( $nodeType == eZTemplate::NODE_FUNCTION )
949 {
950 $functionChildren = $node[1];
951 $functionName = $node[2];
952 $functionParameters = $node[3];
953 $functionPlacement = $node[4];
954
955 $newFunctionChildren = array();
956 if ( is_array( $functionChildren ) )
957 {
958 foreach ( $functionChildren as $functionChild )
959 {
960 $newChild = array();
961 eZTemplateCompiler::processStaticOptimizations( $useComments, $php, $tpl,
962 $functionChild, $resourceData, $newChild );
963 $newFunctionChildren[] = $newChild;
964 }
965 $functionChildren = $newFunctionChildren;
966 }
967
968 $newFunctionParameters = array();
969 if ( $functionParameters )
970 {
971 foreach ( $functionParameters as $functionParameterName => $functionParameterData )
972 {
973 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
974 $functionParameterData, false,
975 $resourceData );
976 if ( isset( $dataInspection['new-data'] ) )
977 {
978 $functionParameterData = $dataInspection['new-data'];
979 }
980 $newFunctionParameters[$functionParameterName] = $functionParameterData;
981 }
982 $functionParameters = $newFunctionParameters;
983 }
984
985 $newNode[0] = $nodeType;
986 $newNode[1] = $functionChildren;
987 $newNode[2] = $functionName;
988 $newNode[3] = $functionParameters;
989 $newNode[4] = $functionPlacement;
990 if ( isset( $node[5] ) )
991 $newNode[5] = $node[5];
992 }
993 else
994 $newNode = $node;
995 }
996
1002 static function processNodeTransformation( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode )
1003 {
1004 $newNode = eZTemplateCompiler::processNodeTransformationRoot( $useComments, $php, $tpl, $node, $resourceData );
1005 }
1006
1012 static function processNodeTransformationNodes( $tpl, &$node, &$nodes, &$privateData )
1013 {
1014 $useComments = $privateData['use-comments'];
1015 $php =& $privateData['php-creator'];
1016 $resourceData =& $privateData['resource-data'];
1017 return eZTemplateCompiler::processNodeTransformationChildren( $useComments, $php, $tpl, $node, $nodes, $resourceData );
1018 }
1019
1024 static function processNodeTransformationChildren( $useComments, $php, $tpl, &$node, &$children, &$resourceData )
1025 {
1026 if ( $children )
1027 {
1028 $newChildren = array();
1029 foreach ( $children as $childNode )
1030 {
1031 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData );
1032 if ( !$newChildNode )
1033 $newChildren[] = $childNode;
1034 else
1035 $newChildren = array_merge( $newChildren, $newChildNode );
1036 }
1037 if ( count( $newChildren ) > 0 )
1038 return $newChildren;
1039 }
1040 return $children;
1041 }
1042
1047 static function processNodeTransformationRoot( $useComments, $php, $tpl, &$node, &$resourceData )
1048 {
1049 $nodeType = $node[0];
1050 if ( $nodeType == eZTemplate::NODE_ROOT )
1051 {
1052 $children = $node[1];
1053 $newNode = array( $nodeType,
1054 false );
1055 if ( $children )
1056 {
1057 $newChildren = array();
1058 foreach ( $children as $childNode )
1059 {
1060 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData );
1061 if ( !$newChildNode )
1062 $newChildren[] = $childNode;
1063 else
1064 $newChildren = array_merge( $newChildren, $newChildNode );
1065 }
1066 if ( count( $newChildren ) > 0 )
1067 $newNode[1] = $newChildren;
1068 }
1069 return $newNode;
1070 }
1071 else
1072 $tpl->error( 'processNodeTransformation', "Unknown root type $nodeType, should be " . eZTemplate::NODE_ROOT );
1073 return false;
1074 }
1075
1081 static function processNodeTransformationChild( $useComments, $php, $tpl, &$node, &$resourceData )
1082 {
1083 $nodeType = $node[0];
1084 if ( $nodeType == eZTemplate::NODE_FUNCTION )
1085 {
1086 $nodeCopy = $node;
1087 $functionChildren = $node[1];
1088 $functionName = $node[2];
1089 $functionParameters = $node[3];
1090 $functionPlacement = $node[4];
1091 if ( !isset( $tpl->Functions[$functionName] ) )
1092 return false;
1093
1094 if ( is_array( $tpl->Functions[$functionName] ) )
1095 {
1096 $tpl->loadAndRegisterFunctions( $tpl->Functions[$functionName] );
1097 }
1098 $functionObject =& $tpl->Functions[$functionName];
1099 if ( is_object( $functionObject ) )
1100 {
1101 $hasTransformationSupport = false;
1102 $transformChildren = true;
1103 $transformParameters = false;
1104 if ( method_exists( $functionObject, 'functionTemplateHints' ) )
1105 {
1106 $hints = $functionObject->functionTemplateHints();
1107 if ( isset( $hints[$functionName] ) and
1108 isset( $hints[$functionName]['tree-transformation'] ) and
1109 $hints[$functionName]['tree-transformation'] )
1110 $hasTransformationSupport = true;
1111 if ( isset( $hints[$functionName] ) and
1112 isset( $hints[$functionName]['transform-children'] ) )
1113 $transformChildren = $hints[$functionName]['transform-children'];
1114 if ( isset( $hints[$functionName] ) and
1115 isset( $hints[$functionName]['transform-parameters'] ) )
1116 $transformParameters = $hints[$functionName]['transform-parameters'];
1117 }
1118 if ( $hasTransformationSupport and
1119 method_exists( $functionObject, 'templateNodeTransformation' ) )
1120 {
1121 if ( $transformChildren and
1122 $functionChildren )
1123 {
1124 $newChildren = array();
1125 foreach ( $functionChildren as $childNode )
1126 {
1127 $newChildNode = eZTemplateCompiler::processNodeTransformationChild( $useComments, $php, $tpl, $childNode, $resourceData );
1128 if ( !$newChildNode )
1129 $newChildren[] = $childNode;
1130 else if ( !is_array( $newChildNode ) )
1131 $newChildren[] = $newChildNode;
1132 else
1133 $newChildren = array_merge( $newChildren, $newChildNode );
1134 }
1135 if ( count( $newChildren ) > 0 )
1136 $node[1] = $newChildren;
1137 }
1138
1139 if ( $transformParameters and
1140 $functionParameters )
1141 {
1142 $newParameters = array();
1143 foreach ( $functionParameters as $parameterName => $parameterElementList )
1144 {
1145 $elementTree = $parameterElementList;
1146 $elementList = $elementTree;
1147 $newParamNode = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node,
1148 $elementTree, $elementList, $resourceData );
1149 if ( !$newParamNode || !is_array( $newParamNode ) )
1150 $newParameters[$parameterName] = $parameterElementList;
1151 else
1152 $newParameters[$parameterName] = $newParamNode;
1153 }
1154 if ( count( $newParameters ) > 0 )
1155 {
1156 $node[3] = $newParameters;
1157 $functionParameters = $newParameters;
1158 }
1159 }
1160
1161 $privateData = array( 'use-comments' => $useComments,
1162 'php-creator' => $php,
1163 'resource-data' => &$resourceData );
1164 $newNodes = $functionObject->templateNodeTransformation( $functionName, $node,
1165 $tpl, $functionParameters, $privateData );
1166 unset( $privateData );
1167 if ( !$newNodes )
1168 {
1169 $node = $nodeCopy;
1170 $node[1] = $functionChildren;
1171 return false;
1172 return $node;
1173 }
1174 return $newNodes;
1175 }
1176 }
1177 else if ( $resourceData['test-compile'] )
1178 {
1179 $tpl->warning( '', "Function '$functionName' is not registered.", $functionPlacement );
1180 }
1181
1182 return false;
1183 }
1184 else if ( $nodeType == eZTemplate::NODE_VARIABLE )
1185 {
1186 $elementTree = $node[2];
1187 $elementList = $elementTree;
1188
1189 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node,
1190 $elementTree, $elementList, $resourceData );
1191 if ( $newParameterElements )
1192 {
1193 $newNode = $node;
1194 $newNode[2] = $newParameterElements;
1195 $newNodes = array( $newNode );
1196 return $newNodes;
1197 }
1198 }
1199 else if ( $nodeType == eZTemplate::NODE_ROOT )
1200 {
1201 return eZTemplateCompiler::processNodeTransformationRoot( $useComments, $php, $tpl, $node, $resourceData );
1202 }
1203 else
1204 return false;
1205 }
1206
1211 static function processElementTransformationList( $tpl, &$node, $elements, &$privateData )
1212 {
1213 $useComments = $privateData['use-comments'];
1214 $php =& $privateData['php-creator'];
1215 $resourceData =& $privateData['resource-data'];
1216 $elementTree = $elements;
1217 $newElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node,
1218 $elementTree, $elements, $resourceData );
1219 if ( $newElements )
1220 return $newElements;
1221 return $elements;
1222 }
1223
1229 static function processElementTransformationChild( $useComments, $php, $tpl, &$node,
1230 $elementTree, $elementList, &$resourceData )
1231 {
1232 $count = is_countable( $elementList ) ? count( $elementList ) : 0;
1233 $lastElement = null;
1234 $newElementList = array();
1235 for ( $i = 0; $i < $count; ++$i )
1236 {
1237 $element =& $elementList[$i];
1238 $elementType = $element[0];
1239 if ( $elementType == eZTemplate::TYPE_OPERATOR )
1240 {
1241 $operatorName = $element[1][0];
1242 $operatorParameters = array_slice( $element[1], 1 );
1243 if ( !isset( $tpl->Operators[$operatorName] ) )
1244 return false;
1245
1246 if ( is_array( $tpl->Operators[$operatorName] ) )
1247 {
1248 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] );
1249 }
1250 $operatorObject =& $tpl->Operators[$operatorName];
1251 if ( is_object( $operatorObject ) )
1252 {
1253 $hasTransformationSupport = false;
1254 $transformParameters = false;
1255 $inputAsParameter = false;
1256 $knownType = 'static';
1257 if ( method_exists( $operatorObject, 'operatorTemplateHints' ) )
1258 {
1259 $hints = $operatorObject->operatorTemplateHints();
1260 if ( isset( $hints[$operatorName] ) and
1261 isset( $hints[$operatorName]['element-transformation'] ) and
1262 $hints[$operatorName]['element-transformation'] )
1263 {
1264 $hasTransformationSupport = true;
1265 }
1266
1267 if ( $hasTransformationSupport and
1268 isset( $hints[$operatorName]['element-transformation-func'] ) )
1269 {
1270 $transformationMethod = $hints[$operatorName]['element-transformation-func'];
1271 }
1272 else
1273 {
1274 $transformationMethod = 'templateElementTransformation';
1275 }
1276
1277 if ( isset( $hints[$operatorName] ) and
1278 isset( $hints[$operatorName]['transform-parameters'] ) )
1279 {
1280 $transformParameters = $hints[$operatorName]['transform-parameters'];
1281 }
1282
1283 if ( isset( $hints[$operatorName] ) and
1284 isset( $hints[$operatorName]['input-as-parameter'] ) )
1285 {
1286 $inputAsParameter = $hints[$operatorName]['input-as-parameter'];
1287 }
1288
1289 if ( isset( $hints[$operatorName]['output'] ) and !$hints[$operatorName]['output'] )
1290 {
1291 $knownType = 'null';
1292 }
1293 else if ( isset( $hints[$operatorName]['output-type'] ) )
1294 {
1295 $knownType = $hints[$operatorName]['output-type'];
1296 }
1297 }
1298 if ( $hasTransformationSupport and
1299 method_exists( $operatorObject, $transformationMethod ) )
1300 {
1301 $resetNewElementList = false;
1302 if ( $transformParameters )
1303 {
1304 $newParameters = array();
1305 if ( $inputAsParameter )
1306 {
1307 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node,
1308 $elementTree, $newElementList, $resourceData );
1309 if ( count( $newParameterElements ) > 0 or
1310 $inputAsParameter === 'always' )
1311 {
1312 $newParameters[] = $newParameterElements;
1313 $resetNewElementList = true;
1314 }
1315 }
1316
1317 foreach ( $operatorParameters as $operatorParameter )
1318 {
1319 $newParameterElements = eZTemplateCompiler::processElementTransformationChild( $useComments, $php, $tpl, $node,
1320 $elementTree, $operatorParameter, $resourceData );
1321 if ( !$newParameterElements )
1322 $newParameters[] = $operatorParameter;
1323 else
1324 $newParameters[] = $newParameterElements;
1325 }
1326 $operatorParameters = $newParameters;
1327 }
1328
1329 $newElements = $operatorObject->$transformationMethod( $operatorName, $node, $tpl, $resourceData,
1330 $element, $lastElement, $elementList, $elementTree,
1331 $operatorParameters );
1332 if ( is_array( $newElements ) )
1333 {
1334 if ( $resetNewElementList )
1335 {
1336 $newElementList = $newElements;
1337 }
1338 else
1339 {
1340 $newElementList = array_merge( $newElementList, $newElements );
1341 }
1342 }
1343 else
1344 {
1345 $newElementList[] = $element;
1346 }
1347 }
1348 else
1349 {
1350 $newElementList[] = $element;
1351 }
1352 }
1353 else if ( $resourceData['test-compile'] )
1354 {
1355 $tpl->warning( '', "Operator '$operatorName' is not registered." );
1356 }
1357 }
1358 else
1359 {
1360 $newElementList[] = $element;
1361 }
1362 $lastElement = $element;
1363 }
1364 return $newElementList;
1365 }
1366
1370 static function processRemoveNodePlacement( &$node )
1371 {
1372 $nodeType = $node[0];
1373 if ( $nodeType == eZTemplate::NODE_ROOT )
1374 {
1375 $nodeChildren =& $node[1];
1376 for ( $i = 0; $i < count( $nodeChildren ); ++$i )
1377 {
1378 $nodeChild =& $nodeChildren[$i];
1379 eZTemplateCompiler::processRemoveNodePlacement( $nodeChild );
1380 }
1381 }
1382 else if ( $nodeType == eZTemplate::NODE_TEXT )
1383 {
1384 $node[3] = false;
1385 }
1386 else if ( $nodeType == eZTemplate::NODE_VARIABLE )
1387 {
1388 $node[3] = false;
1389 }
1390 else if ( $nodeType == eZTemplate::NODE_FUNCTION )
1391 {
1392 $node[4] = false;
1393 $nodeChildren =& $node[1];
1394 if ( $nodeChildren )
1395 {
1396 for ( $i = 0; $i < count( $nodeChildren ); ++$i )
1397 {
1398 $nodeChild =& $nodeChildren[$i];
1399 eZTemplateCompiler::processRemoveNodePlacement( $nodeChild );
1400 }
1401 }
1402 }
1403 else if ( $nodeType == eZTemplate::NODE_OPERATOR )
1404 {
1405 }
1406 }
1407
1417 static function inspectVariableData( $tpl, $variableData, $variablePlacement, &$resourceData )
1418 {
1419 $dataInspection = array( 'is-constant' => false,
1420 'is-variable' => false,
1421 'has-operators' => false,
1422 'has-attributes' => false );
1423 if ( !is_array( $variableData ) )
1424 return $dataInspection;
1425 $newVariableData = array();
1426 // Static optimizations, the following items are done:
1427 // - Recognize static data
1428 // - Extract static data, if possible, from operators
1429 // - Remove parameters and input which not be used.
1430 foreach ( $variableData as $variableItem )
1431 {
1432 $variableItemType = $variableItem[0];
1433 $variableItemData = $variableItem[1];
1434 $variableItemPlacement = $variableItem[2];
1435 if ( $variableItemType == eZTemplate::TYPE_STRING or
1436 $variableItemType == eZTemplate::TYPE_IDENTIFIER )
1437 {
1438 $dataInspection['is-constant'] = true;
1439 $dataInspection['is-variable'] = false;
1440 $newVariableData[] = $variableItem;
1441 }
1442 else if ( $variableItemType == eZTemplate::TYPE_NUMERIC )
1443 {
1444 $dataInspection['is-constant'] = true;
1445 $dataInspection['is-variable'] = false;
1446 $newVariableData[] = $variableItem;
1447 }
1448 else if ( $variableItemType == eZTemplate::TYPE_BOOLEAN )
1449 {
1450 $dataInspection['is-constant'] = true;
1451 $dataInspection['is-variable'] = false;
1452 $newVariableData[] = $variableItem;
1453 }
1454 else if ( $variableItemType == eZTemplate::TYPE_DYNAMIC_ARRAY )
1455 {
1456 $dataInspection['is-constant'] = false;
1457 $dataInspection['is-variable'] = true;
1458 $newVariableData[] = $variableItem;
1459 }
1460 else if ( $variableItemType == eZTemplate::TYPE_ARRAY )
1461 {
1462 $dataInspection['is-constant'] = true;
1463 $dataInspection['is-variable'] = false;
1464 $newVariableData[] = $variableItem;
1465 }
1466 else if ( $variableItemType == eZTemplate::TYPE_VARIABLE )
1467 {
1468 $dataInspection['is-constant'] = false;
1469 $dataInspection['is-variable'] = true;
1470 $newVariableData[] = $variableItem;
1471 }
1472 else if ( $variableItemType == eZTemplate::TYPE_ATTRIBUTE )
1473 {
1474 $dataInspection['has-attributes'] = true;
1475 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
1476 $variableItemData, $variableItemPlacement,
1477 $resourceData );
1478 if ( isset( $newDataInspection['new-data'] ) )
1479 {
1480 $variableItemData = $newDataInspection['new-data'];
1481 }
1482 $variableItem[1] = $variableItemData;
1483 unset( $newDataInspection );
1484 $newVariableData[] = $variableItem;
1485 }
1486 else if ( $variableItemType == eZTemplate::TYPE_OPERATOR )
1487 {
1488 $dataInspection['has-operators'] = true;
1489 $operatorName = $variableItemData[0];
1490 $operatorHint = eZTemplateCompiler::operatorHint( $tpl, $operatorName );
1491 $newVariableItem = $variableItem;
1492 if ( $operatorHint and
1493 isset( $operatorHint['input'] ) and
1494 isset( $operatorHint['output'] ) and
1495 isset( $operatorHint['parameters'] ) )
1496 {
1497 if ( !$operatorHint['input'] and
1498 $operatorHint['output'] )
1499 $newVariableData = array();
1500 if ( !isset( $operatorHint) or !$operatorHint['parameters'] )
1501 $newVariableItem[1] = array( $operatorName );
1502 if ( isset ( $operatorHint['static'] ) and
1503 $operatorHint['static'] )
1504 {
1505 $operatorStaticData = eZTemplateCompiler::operatorStaticData( $tpl, $operatorName );
1506 $newVariableItem = eZTemplateCompiler::createStaticVariableData( $tpl, $operatorStaticData, $variableItemPlacement );
1507 $dataInspection['is-constant'] = true;
1508 $dataInspection['is-variable'] = false;
1509 $dataInspection['has-operators'] = false;
1510 }
1511 }
1512 if ( $newVariableItem[0] == eZTemplate::TYPE_OPERATOR )
1513 {
1514 $tmpVariableItem = $newVariableItem[1];
1515 $newVariableItem[1] = array( $operatorName );
1516 for ( $i = 1; $i < count( $tmpVariableItem ); ++$i )
1517 {
1518 $operatorParameter = $tmpVariableItem[$i];
1519 $newDataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
1520 $operatorParameter, false,
1521 $resourceData );
1522 if ( isset( $newDataInspection['new-data'] ) )
1523 {
1524 $operatorParameter = $newDataInspection['new-data'];
1525 }
1526 $newVariableItem[1][] = $operatorParameter;
1527 }
1528 }
1529 $newVariableData[] = $newVariableItem;
1530 }
1531 else if ( $variableItemType == eZTemplate::TYPE_VOID )
1532 {
1533 $tpl->warning( 'TemplateCompiler', "Void datatype should not be used, ignoring it" );
1534 }
1535 else if ( $variableItemType > eZTemplate::TYPE_INTERNAL and
1536 $variableItemType < eZTemplate::TYPE_INTERNAL_STOP )
1537 {
1538 $newVariableData[] = $variableItem;
1539 }
1540 else
1541 {
1542 $tpl->warning( 'TemplateCompiler', "Unknown data type $variableItemType, ignoring it" );
1543 }
1544 }
1545 $dataInspection['new-data'] = $newVariableData;
1546 return $dataInspection;
1547 }
1548
1553 static function operatorHint( $tpl, $operatorName )
1554 {
1555 if ( isset( $tpl->Operators[$operatorName] ) and
1556 is_array( $tpl->Operators[$operatorName] ) )
1557 {
1558 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] );
1559 }
1560 $operatorObject =& $tpl->Operators[$operatorName];
1561 $operatorHint = false;
1562 if ( is_object( $operatorObject ) )
1563 {
1564 if ( method_exists( $operatorObject, 'operatorTemplateHints' ) )
1565 {
1566 $operatorHintArray = $operatorObject->operatorTemplateHints();
1567 if ( isset( $operatorHintArray[$operatorName] ) )
1568 {
1569 $operatorHint = $operatorHintArray[$operatorName];
1570 }
1571 }
1572 }
1573 else if ( $tpl->testCompile() )
1574 {
1575 $tpl->warning( '', "Operator '$operatorName' is not registered." );
1576 }
1577
1578 return $operatorHint;
1579 }
1580
1587 static function operatorStaticData( $tpl, $operatorName )
1588 {
1589 if ( is_array( $tpl->Operators[$operatorName] ) )
1590 {
1591 $tpl->loadAndRegisterOperators( $tpl->Operators[$operatorName] );
1592 }
1593 $operatorObject =& $tpl->Operators[$operatorName];
1594 $operatorData = null;
1595 if ( is_object( $operatorObject ) )
1596 {
1597 if ( method_exists( $operatorObject, 'operatorCompiledStaticData' ) )
1598 {
1599 $operatorData = $operatorObject->operatorCompiledStaticData( $operatorName );
1600 }
1601 }
1602 else if ( $tpl->testCompile() )
1603 {
1604 $tpl->warning( '', "Operator '$operatorName' is not registered." );
1605 }
1606
1607 return $operatorData;
1608 }
1609
1616 static function createStaticVariableData( $tpl, $staticData, $variableItemPlacement )
1617 {
1618 if ( is_string( $staticData ) )
1619 return array( eZTemplate::TYPE_STRING,
1620 $staticData,
1621 $variableItemPlacement );
1622 else if ( is_bool( $staticData ) )
1623 return array( eZTemplate::TYPE_BOOLEAN,
1624 $staticData,
1625 $variableItemPlacement );
1626 else if ( is_bool( $staticData ) or is_numeric( $staticData ) )
1627 return array( eZTemplate::TYPE_NUMERIC,
1628 $staticData,
1629 $variableItemPlacement );
1630 else if ( is_array( $staticData ) )
1631 return array( eZTemplate::TYPE_ARRAY,
1632 $staticData,
1633 $variableItemPlacement );
1634 else
1635 return array( eZTemplate::TYPE_STRING,
1636 "$staticData",
1637 $variableItemPlacement );
1638 }
1639
1646 static function fetchTemplatePiece( $placementData )
1647 {
1648 if ( !isset( $placementData[0] ) or
1649 !isset( $placementData[1] ) or
1650 !isset( $placementData[2] ) )
1651 return null;
1652 $file = $placementData[2];
1653 $startPosition = $placementData[0][2];
1654 $endPosition = $placementData[1][2];
1655 $length = $endPosition - $startPosition;
1656 if ( file_exists( $file ) )
1657 {
1658 if ( $length > 0 )
1659 {
1660 $fd = fopen( $file, 'rb' );
1661 fseek( $fd, $startPosition );
1662 $text = fread( $fd, $length );
1663 fclose( $fd );
1664 return $text;
1665 }
1666 else
1667 {
1668 return '';
1669 }
1670 }
1671 return null;
1672 }
1673
1678 static function createCommonCompileTemplate()
1679 {
1680 $php = new eZPHPCreator( eZTemplateCompiler::compilationDirectory(), 'common.php' );
1681 if ( $php->exists() )
1682 return;
1683
1684 $php->addComment( "This file contains functions which are common to all compiled templates.\n\n" .
1685 'NOTE: This file is autogenerated and should not be modified, any changes will be lost!' );
1686 $php->addSpace();
1687 $php->addDefine( 'EZ_TEMPLATE_COMPILER_COMMON_CODE', true );
1688 $php->addSpace();
1689
1690 $namespaceStack = array();
1691 $php->addCodePiece( "if ( !isset( \$namespaceStack ) )\n" );
1692 $php->addVariable( 'namespaceStack', $namespaceStack, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'spacing' => 4 ) );
1693 $php->addSpace();
1694
1695 $lbracket = '{';
1696 $rbracket = '}';
1697 $initText = "if ( !function_exists( 'compiledfetchvariable' ) )
1698 $lbracket
1699 function compiledFetchVariable( \$vars, \$namespace, \$name )
1700 $lbracket
1701 \$exists = ( array_key_exists( \$namespace, \$vars ) and
1702 array_key_exists( \$name, \$vars[\$namespace] ) );
1703 if ( \$exists )
1704 $lbracket
1705 return \$vars[\$namespace][\$name];
1706 $rbracket
1707 return null;
1708 $rbracket
1709 $rbracket
1710 if ( !function_exists( 'compiledfetchtext' ) )
1711 $lbracket
1712 function compiledFetchText( \$tpl, \$rootNamespace, \$currentNamespace, \$namespace, \$var )
1713 $lbracket
1714 \$text = '';
1715 \$tpl->appendElement( \$text, \$var, \$rootNamespace, \$currentNamespace );
1716 return \$text;
1717 $rbracket
1718 $rbracket
1719 if ( !function_exists( 'compiledAcquireResource' ) )
1720 $lbracket
1721 function compiledAcquireResource( \$phpScript, \$key, &\$originalText,
1722 \$tpl, \$rootNamespace, \$currentNamespace )
1723 {
1724 include( '" . eZTemplateCompiler::TemplatePrefix() . "' . \$phpScript );
1725 if ( isset( \$text ) )
1726 {
1727 \$originalText .= \$text;
1728 return true;
1729 }
1730 return false;
1731 }
1732 $rbracket
1733 if ( !function_exists( 'compiledfetchattribute' ) )
1734 $lbracket
1735 function compiledFetchAttribute( \$value, \$attributeValue )
1736 $lbracket
1737 if ( is_object( \$value ) )
1738 $lbracket
1739 if ( method_exists( \$value, \"attribute\" ) and
1740 method_exists( \$value, \"hasAttribute\" ) )
1741 $lbracket
1742 if ( \$value->hasAttribute( \$attributeValue ) )
1743 $lbracket
1744 return \$value->attribute( \$attributeValue );
1745 $rbracket
1746 $rbracket
1747 $rbracket
1748 else if ( is_array( \$value ) )
1749 $lbracket
1750 if ( isset( \$value[\$attributeValue] ) )
1751 $lbracket
1752 return \$value[\$attributeValue];
1753 $rbracket
1754 $rbracket
1755 return null;
1756 $rbracket
1757 $rbracket
1758 ";
1759 $php->addCodePiece( $initText );
1760 $php->store( true );
1761 }
1762
1767 static function currentTextName( $parameters )
1768 {
1769 $textData = array( 'variable' => 'text',
1770 'counter' => 0 );
1771 if ( isset( $parameters['text-data'] ) )
1772 $textData = $parameters['text-data'];
1773 $name = $textData['variable'];
1774 if ( $textData['counter'] > 0 )
1775 $name .= $textData['counter'];
1776 return $name;
1777 }
1778
1779 static function boundVariableName( $variableID, $parameters )
1780 {
1781 $bindMap =& $parameters['variable-bind']['map'][$variableID];
1782 if ( isset( $bindMap ) )
1783 $bindMap = array();
1784 }
1785
1791 static function generatePHPCode( $useComments, $php, $tpl, &$node, &$resourceData )
1792 {
1793 $parameters = array();
1794 $currentParameters = array( 'spacing' => 0 );
1795 $nodeType = $node[0];
1796 if ( $nodeType == eZTemplate::NODE_ROOT )
1797 {
1798 $children = $node[1];
1799 if ( $children )
1800 {
1801 eZTemplateCompiler::generatePHPCodeChildren( $useComments, $php, $tpl, $children, $resourceData, $parameters, $currentParameters );
1802 }
1803 }
1804 else
1805 $tpl->error( 'generatePHPCode', "Unknown root type $nodeType, should be " . eZTemplate::NODE_ROOT );
1806 $php->addSpace();
1807 }
1808
1813 static function generatePHPCodeChildren( $useComments, $php, $tpl, &$nodeChildren, &$resourceData, &$parameters, $currentParameters )
1814 {
1815 foreach ( $nodeChildren as $node )
1816 {
1817 $newNode = false;
1818 $nodeType = $node[0];
1819 if ( $nodeType > eZTemplate::NODE_USER_CUSTOM )
1820 {
1821 // Do custom nodes
1822 }
1823 else if ( $nodeType > eZTemplate::NODE_INTERNAL )
1824 {
1825 // Do custom internal nodes
1826 if ( $nodeType == eZTemplate::NODE_INTERNAL_CODE_PIECE )
1827 {
1828 $codePiece = $node[1];
1829 $spacing = $currentParameters['spacing'];
1830 if ( isset( $node[2]['spacing'] ) )
1831 $spacing += $node[2]['spacing'];
1832 $php->addCodePiece( $codePiece, array( 'spacing' => $spacing ) );
1833 }
1834 else if ( $nodeType == eZTemplate::NODE_INTERNAL_WARNING )
1835 {
1836 $warningText = $php->thisVariableText( $node[1], 23, 0, false );
1837 $warningLabel = false;
1838 $warningLabelText = '';
1839 if ( isset( $node[2] ) )
1840 $warningLabelText = $php->thisVariableText( $node[2], 0, 0, false );
1841 $spacing = $currentParameters['spacing'];
1842 if ( isset( $node[3]['spacing'] ) )
1843 $spacing += $node[3]['spacing'];
1844 $placementText = 'false';
1845 if ( isset( $node[4] ) )
1846 $placementText = $php->thisVariableText( $node[4], 0, 0, false );
1847 $php->addCodePiece( "\$tpl->warning( " . $warningLabelText . ", " . $warningText . ", " . $placementText . " );", array( 'spacing' => $spacing ) );
1848 }
1849 else if ( $nodeType == eZTemplate::NODE_INTERNAL_ERROR )
1850 {
1851 $errorText = $php->thisVariableText( $node[1], 21, 0, false );
1852 $errorLabel = false;
1853 $errorLabelText = '';
1854 if ( isset( $node[2] ) )
1855 $errorLabelText = $php->thisVariableText( $node[2], 0, 0, false );
1856 $spacing = $currentParameters['spacing'];
1857 if ( isset( $node[3]['spacing'] ) )
1858 $spacing += $node[3]['spacing'];
1859 $placementText = 'false';
1860 if ( isset( $node[4] ) )
1861 $placementText = $php->thisVariableText( $node[4], 0, 0, false );
1862 $php->addCodePiece( "\$tpl->error( " . $errorLabelText . ", " . $errorText . ", " . $placementText . " );", array( 'spacing' => $spacing ) );
1863 }
1864 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_READ )
1865 {
1866 $variableName = $node[1];
1867 $spacing = $currentParameters['spacing'];
1868 if ( isset( $node[2]['spacing'] ) )
1869 $spacing += $node[2]['spacing'];
1870 $textName = eZTemplateCompiler::currentTextName( $parameters );
1871 $assignmentType = $node[3];
1872 $assignmentText = $php->variableNameText( $variableName, $assignmentType, $node[2] );
1873 $php->addCodePiece( "$assignmentText\$$textName;", array( 'spacing' => $spacing ) );
1874 }
1875 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_ASSIGN )
1876 {
1877 $variableName = $node[1];
1878 $spacing = $currentParameters['spacing'];
1879 if ( isset( $node[2]['spacing'] ) )
1880 $spacing += $node[2]['spacing'];
1881 $textName = eZTemplateCompiler::currentTextName( $parameters );
1882 $assignmentType = $node[3];
1883 $assignmentText = $php->variableNameText( $textName, $assignmentType, $node[2] );
1884 $php->addCodePiece( "$assignmentText\$$variableName;", array( 'spacing' => $spacing ) );
1885 }
1886 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_INCREASE )
1887 {
1888 $spacing = $currentParameters['spacing'];
1889 if ( isset( $node[1]['spacing'] ) )
1890 $spacing += $node[1]['spacing'];
1891 $textName = eZTemplateCompiler::currentTextName( $parameters );
1892 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$textStack ) )\n" .
1893 " \$textStack = array();\n" .
1894 "\$textStack[] = \$$textName;\n" .
1895 "\$$textName = '';", array( 'spacing' => $spacing ) );
1896 }
1897 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_DECREASE )
1898 {
1899 $spacing = $currentParameters['spacing'];
1900 if ( isset( $node[1]['spacing'] ) )
1901 $spacing += $node[1]['spacing'];
1902 $textName = eZTemplateCompiler::currentTextName( $parameters );
1903 $php->addCodePiece( "\$$textName = array_pop( \$textStack );", array( 'spacing' => $spacing ) );
1904 }
1905 else if ( $nodeType == eZTemplate::NODE_INTERNAL_OUTPUT_SPACING_INCREASE )
1906 {
1907 $spacing = $node[1];
1908 $currentParameters['spacing'] += $spacing;
1909 continue;
1910 }
1911 else if ( $nodeType == eZTemplate::NODE_INTERNAL_SPACING_DECREASE )
1912 {
1913 $spacing = $node[1];
1914 $currentParameters['spacing'] -= $spacing;
1915 continue;
1916 }
1917 else if ( $nodeType == eZTemplate::NODE_INTERNAL_VARIABLE_SET )
1918 {
1919 $variableName = $node[1];
1920 $variableValue = $node[2];
1921 $spacing = $currentParameters['spacing'];
1922 if ( isset( $node[3]['spacing'] ) )
1923 $spacing += $node[3]['spacing'];
1924 $php->addVariable( $variableName, $variableValue, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'spacing' => $spacing ) );
1925 }
1926 else if ( $nodeType == eZTemplate::NODE_INTERNAL_VARIABLE_UNSET )
1927 {
1928 $variableName = $node[1];
1929 $spacing = $currentParameters['spacing'];
1930 if ( isset( $node[2]['spacing'] ) )
1931 $spacing += $node[2]['spacing'];
1932
1933 if ( is_array( $variableName ) )
1934 {
1935 $namespace = $variableName[0];
1936 $namespaceScope = $variableName[1];
1937 $variableName = $variableName[2];
1938 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true );
1939 if ( !is_string( $namespaceText ) )
1940 $namespaceText = "\$namespace";
1941 $variableNameText = $php->thisVariableText( $variableName, 0, 0, false );
1942 if ( isset( $node[2]['remember_set'] ) and $node[2]['remember_set'] )
1943 {
1944 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( isset( \$setArray[$namespaceText][$variableNameText] ) )\n".
1945 "{\n" );
1946 $spacing += 4;
1947 }
1948 if ( isset( $node[2]['local-variable'] ) )
1949 {
1950 $php->addCodePiece( "\$tpl->unsetLocalVariable( $variableNameText, $namespaceText );\n",
1951 array( 'spacing' => $spacing ) );
1952 }
1953 else
1954 {
1955 $php->addCodePiece( "unset( \$vars[$namespaceText][$variableNameText] );",
1956 array( 'spacing' => $spacing ) );
1957 }
1958
1959 if ( isset( $node[2]['remember_set'] ) and $node[2]['remember_set'] )
1960 {
1961 $php->addCodePiece( "\n}\n" );
1962 $spacing -= 4;
1963 }
1964 }
1965 else
1966 {
1967 $php->addVariableUnset( $variableName, array( 'spacing' => $spacing ) );
1968 }
1969 }
1970 else if ( ( $nodeType == eZTemplate::NODE_INTERNAL_RESOURCE_ACQUISITION ) ||
1971 ( $nodeType == eZTemplate::NODE_OPTIMIZED_RESOURCE_ACQUISITION ) )
1972 {
1973 $resource = $node[1];
1974 $resourceObject = $tpl->resourceHandler( $resource );
1975 if ( !$resourceObject )
1976 continue;
1977
1978 $spacing = $currentParameters['spacing'];
1979 if ( isset( $node[7]['spacing'] ) )
1980 $spacing += $node[7]['spacing'];
1981 $newRootNamespace = $node[8];
1982 $resourceVariableName = $node[9];
1983 $resourceFilename = isset( $node[10] ) ? $node[10] : false;
1984
1985 /* We can only use fallback code if we know upfront which
1986 * template is included; it does not work if we are using
1987 * something from the ezobjectforwarder which makes the
1988 * uriMap an array */
1989 $useFallbackCode = true;
1990 $uriMap = $node[2];
1991 if ( is_string( $uriMap ) )
1992 {
1993 $uriMap = array( $uriMap );
1994 }
1995 else
1996 {
1997 $useFallbackCode = false;
1998 }
1999
2000 $resourceMap = array();
2001 $hasCompiledCode = false;
2002 if ( is_array( $uriMap ) )
2003 {
2004 foreach ( $uriMap as $uriKey => $originalURI )
2005 {
2006 $uri = $originalURI;
2007 if ( $resource )
2008 $uri = $resource . ':' . $uri;
2009 unset( $tmpResourceData );
2010 $tmpResourceData = $tpl->resourceData( $resourceObject, $uri, $node[1], $originalURI );
2011 $uriText = $php->thisVariableText( $uri, 0, 0, false );
2012
2013 $resourceCanCache = true;
2014 if ( !$resourceObject->servesStaticData() )
2015 $resourceCanCache = false;
2016 if ( !$tpl->isCachingAllowed() )
2017 $resourceCanCache = false;
2018
2019 $tmpResourceData['text'] = null;
2020 $tmpResourceData['root-node'] = null;
2021 $tmpResourceData['compiled-template'] = false;
2022 $tmpResourceData['time-stamp'] = null;
2023 $tmpResourceData['key-data'] = null;
2024 $tmpResourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled();
2025 $subSpacing = 0;
2026 $hasResourceData = false;
2027
2028 $savedLocale = setlocale( LC_CTYPE, null );
2029 if ( isset( $GLOBALS['eZTemplateCompilerResourceCache'][$tmpResourceData['template-filename']] ) )
2030 {
2031 $tmpFileName = $tmpResourceData['template-filename'];
2032 unset( $tmpResourceData );
2033 $tmpResourceData = $GLOBALS['eZTemplateCompilerResourceCache'][$tmpFileName];
2034 $tmpResourceData['compiled-template'] = true;
2035 $tmpResourceData['use-comments'] = eZTemplateCompiler::isCommentsEnabled();
2036 $hasResourceData = true;
2037 $hasCompiledCode = true;
2038 }
2039 else if ( $useFallbackCode )
2040 {
2041 // If we can use fallback code we don't need to compile the templates in advance
2042 // Simply fake that it has been compiled by setting some variables
2043 // Note: Yes this is a hack, but rewriting this code is not an easy task
2044 if ( $resourceObject->handleResource( $tpl, $tmpResourceData, $node[4], $node[5] ) )
2045 {
2046 $tmpResourceData['compiled-template'] = true;
2047 $hasResourceData = true;
2048 $hasCompiledCode = true;
2049 }
2050 }
2051 else
2052 {
2053 if ( $resourceObject->handleResource( $tpl, $tmpResourceData, $node[4], $node[5] ) )
2054 {
2055 if ( !$tmpResourceData['compiled-template'] and
2056 $tmpResourceData['root-node'] === null )
2057 {
2058 $root =& $tmpResourceData['root-node'];
2059 $root = array( eZTemplate::NODE_ROOT, false );
2060 $templateText =& $tmpResourceData["text"];
2061 $keyData = $tmpResourceData['key-data'];
2062 $rootNamespace = '';
2063 $tpl->parse( $templateText, $root, $rootNamespace, $tmpResourceData );
2064 $hasResourceData = false;
2065 }
2066
2067 /* We always DO need to execute this part if we
2068 * don't have any fallback code. If we can
2069 * generate the fallback code we make the
2070 * included template compile on demand */
2071 if ( !$tmpResourceData['compiled-template'] and
2072 $resourceCanCache and
2073 $tpl->canCompileTemplate( $tmpResourceData, $node[5] ) and
2074 !$useFallbackCode )
2075 {
2076 $generateStatus = $tpl->compileTemplate( $tmpResourceData, $node[5] );
2077
2078 // Time limit #2:
2079 /* We reset the time limit to 60 seconds to
2080 * ensure that remaining template has
2081 * enough time to compile. However if time
2082 * limit is unlimited (0) we leave it be */
2083 $maxExecutionTime = ini_get( 'max_execution_time' );
2084 if ( $maxExecutionTime != 0 && $maxExecutionTime < 60 )
2085 {
2086 @set_time_limit( 60 );
2087 }
2088
2089 if ( $generateStatus )
2090 $tmpResourceData['compiled-template'] = true;
2091 }
2092 }
2093 $GLOBALS['eZTemplateCompilerResourceCache'][$tmpResourceData['template-filename']] =& $tmpResourceData;
2094 }
2095 setlocale( LC_CTYPE, $savedLocale );
2096 $textName = eZTemplateCompiler::currentTextName( $parameters );
2097 if ( $tmpResourceData['compiled-template'] )
2098 {
2099 $hasCompiledCode = true;
2100 // if ( !eZTemplateCompiler::isFallbackResourceCodeEnabled() )
2101 // $useFallbackCode = false;
2102 $keyData = $tmpResourceData['key-data'];
2103 $templatePath = $tmpResourceData['template-name'];
2104 $key = $resourceObject->cacheKey( $keyData, $tmpResourceData, $templatePath, $node[5] );
2105 $cacheFileName = eZTemplateCompiler::compilationFilename( $key, $tmpResourceData );
2106
2107 $directory = eZTemplateCompiler::compilationDirectory();
2108 $phpScript = eZDir::path( array( $directory, $cacheFileName ) );
2109 $phpScriptText = $php->thisVariableText( $phpScript, 0, 0, false );
2110 $resourceMap[$uriKey] = array( 'key' => $uriKey,
2111 'uri' => $uri,
2112 'phpscript' => $phpScript );
2113 }
2114 }
2115 }
2116
2117 if ( $useComments )
2118 {
2119 $variablePlacement = $node[6];
2120 if ( $variablePlacement )
2121 {
2122 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement );
2123 $php->addComment( "Resource Acquisition:", true, true, array( 'spacing' => $spacing ) );
2124 $php->addComment( $originalText, true, true, array( 'spacing' => $spacing ) );
2125 }
2126 }
2127
2128 if ( $hasCompiledCode )
2129 {
2130 if ( $resourceVariableName )
2131 {
2132 $phpScriptText = '$phpScript';
2133 $phpScriptArray = array();
2134
2135 foreach ( $resourceMap as $resourceMapItem )
2136 {
2137 $phpScriptArray[$resourceMapItem['key']] = $resourceMapItem['phpscript'];
2138 }
2139
2140 if ( !$resourceFilename ) /* Not optimized version */
2141 {
2142 $php->addVariable( "phpScriptArray", $phpScriptArray, eZPHPCreator::VARIABLE_ASSIGNMENT, array( 'spacing' => $spacing ) );
2143 $resourceVariableNameText = "\$$resourceVariableName";
2144 $php->addCodePiece( "\$phpScript = isset( \$phpScriptArray[$resourceVariableNameText] ) ? \$phpScriptArray[$resourceVariableNameText] : false;\n", array( 'spacing' => $spacing ) );
2145 }
2146 else /* Optimised version */
2147 {
2148 $php->addVariable( "phpScript", $phpScriptArray[$node[10]], eZPHPCreator::VARIABLE_ASSIGNMENT, array('spacing' => $spacing ) );
2149 }
2150
2151 // The default is to only check if it exists
2152 $modificationCheckText = "file_exists( $phpScriptText )";
2153 if ( eZTemplateCompiler::isDevelopmentModeEnabled() )
2154 {
2155 $modificationCheckText = "file_exists( $phpScriptText ) && filemtime( $phpScriptText ) > filemtime( $uriText )";
2156 }
2157 $php->addCodePiece( "\$resourceFound = false;\nif " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( $phpScriptText !== false and $modificationCheckText )\n{\n", array( 'spacing' => $spacing ) );
2158 }
2159 else
2160 {
2161 $php->addCodePiece( "\$resourceFound = false;\n", array( 'spacing' => $spacing ) );
2162 $phpScript = $resourceMap[0]['phpscript'];
2163 $phpScriptText = $php->thisVariableText( $phpScript, 0, 0, false );
2164 // Not sure where this should come from
2165 // if ( $resourceIndex > 0 )
2166 // $php->addCodePiece( "else " );
2167 // The default is to only check if it exists
2168 $modificationCheckText = "file_exists( $phpScriptText )";
2169 if ( eZTemplateCompiler::isDevelopmentModeEnabled() )
2170 {
2171 $modificationCheckText = "file_exists( $phpScriptText ) && filemtime( $phpScriptText ) > filemtime( $uriText )";
2172 }
2173 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( $modificationCheckText )\n{\n", array( 'spacing' => $spacing ) );
2174
2175 }
2176
2177 /* Generate code to do a namespace switch and includes the template */
2178 $code = "\$resourceFound = true;\n\$namespaceStack[] = array( \$rootNamespace, \$currentNamespace );\n";
2179 if ( $newRootNamespace )
2180 {
2181 $newRootNamespaceText = $php->thisVariableText( $newRootNamespace, 0, 0, false );
2182 $code .= "\$currentNamespace = \$rootNamespace = !\$currentNamespace ? $newRootNamespaceText : ( \$currentNamespace . ':' . $newRootNamespaceText );\n";
2183 }
2184 else
2185 {
2186 $code .= "\$rootNamespace = \$currentNamespace;\n";
2187 }
2188
2189 $code .=
2190 "\$tpl->createLocalVariablesList();\n" .
2191 "\$tpl->appendTemplateFetch( $uriText );\n" . // Make sure the template file is recorded, like in loadURIRoot
2192 "include( '" . eZTemplateCompiler::TemplatePrefix() . "' . $phpScriptText );\n" .
2193 "\$tpl->unsetLocalVariables();\n" .
2194 "\$tpl->destroyLocalVariablesList();\n" .
2195 "list( \$rootNamespace, \$currentNamespace ) = array_pop( \$namespaceStack );\n";
2196
2197 $php->addCodePiece( $code, array( 'spacing' => $spacing + 4 ) );
2198 if ( $useFallbackCode )
2199 $php->addCodePiece( "}\nelse\n{\n \$resourceFound = true;\n", array( 'spacing' => $spacing ) );
2200 else
2201 $php->addCodePiece( "}\n", array( 'spacing' => $spacing ) );
2202 $subSpacing = 4;
2203 }
2204 else
2205 {
2206 /* Yes, this is a hack, but it is required because
2207 * sometimes the generated nodes after this one emit an
2208 * else statement while there is no accompanied if */
2209 $php->addCodePiece( "\nif " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "(false)\n{\n}\n" );
2210 }
2211
2212 /* The fallback code will be added if we need to process an
2213 * URI, this will also compile a template then. We need to
2214 * do the namespace switch manually here otherwise the
2215 * processed template will be run on the node from which
2216 * the template was included from. */
2217 if ( $useFallbackCode )
2218 {
2219 $code = "\$resourceFound = true;\n\$namespaceStack[] = array( \$rootNamespace, \$currentNamespace );\n";
2220 if ( $newRootNamespace )
2221 {
2222 $newRootNamespaceText = $php->thisVariableText( $newRootNamespace, 0, 0, false );
2223 $code .= "\$currentNamespace = \$rootNamespace = !\$currentNamespace ? $newRootNamespaceText : ( \$currentNamespace . ':' . $newRootNamespaceText );\n";
2224 }
2225 else
2226 {
2227 $code .= "\$rootNamespace = \$currentNamespace;\n";
2228 }
2229 $php->addCodePiece( $code );
2230
2231 $php->addCodePiece( "\$textElements = array();\n\$extraParameters = array();\n\$tpl->processURI( $uriText, true, \$extraParameters, \$textElements, \$rootNamespace, \$currentNamespace );\n\$$textName .= implode( '', \$textElements );\n", array( 'spacing' => $spacing + $subSpacing ) );
2232 $php->addCodePiece( "list( \$rootNamespace, \$currentNamespace ) = array_pop( \$namespaceStack );\n" );
2233 }
2234
2235 if ( $hasCompiledCode and $useFallbackCode )
2236 {
2237 $php->addCodePiece( "}\n", array( 'spacing' => $spacing ) );
2238 }
2239 }
2240 else if ( $nodeType == eZTemplate::NODE_INTERNAL_NAMESPACE_CHANGE )
2241 {
2242 $variableData = $node[1];
2243 $spacing = $currentParameters['spacing'];
2244 if ( isset( $node[2]['spacing'] ) )
2245 $spacing += $node[2]['spacing'];
2246 $php->addCodePiece( "\$namespaceStack[] = \$currentNamespace;\n", array( 'spacing' => $spacing ) );
2247 $php->addCodePiece( '$currentNamespace .= ( $currentNamespace ? ":" : "" ) . \''. $variableData[0][1] . '\';' . "\n", array( 'spacing' => $spacing ) );
2248 }
2249 else if ( $nodeType == eZTemplate::NODE_INTERNAL_NAMESPACE_RESTORE )
2250 {
2251 $spacing = $currentParameters['spacing'];
2252 if ( isset( $node[1]['spacing'] ) )
2253 $spacing += $node[1]['spacing'];
2254 $php->addCodePiece( "\$currentNamespace = array_pop( \$namespaceStack );\n", array( 'spacing' => $spacing ) );
2255 }
2256 else if ( $nodeType == eZTemplate::NODE_OPTIMIZED_INIT )
2257 {
2258 $code = <<<END
2259 \$node = ( array_key_exists( \$rootNamespace, \$vars ) and array_key_exists( "node", \$vars[\$rootNamespace] ) ) ? \$vars[\$rootNamespace]["node"] : null;
2260 if ( is_object( \$node ) )
2261 \$object = \$node->attribute( 'object' );
2262 if ( isset( \$object ) && is_object( \$object ) )
2263 \$nod_{$resourceData['uniqid']} = \$object->attribute( 'data_map' );
2264 else
2265 \$nod_{$resourceData['uniqid']} = false;
2266 unset( \$node, \$object );
2267
2268 END;
2269 $php->addCodePiece($code);
2270 // Tell the rest of the system that we have create the nod_* variable
2271 $resourceData['node-object-cached'] = true;
2272 }
2273 else
2274 eZDebug::writeWarning( "Unknown internal template node type $nodeType, ignoring node for code generation",
2275 'eZTemplateCompiler:generatePHPCodeChildren' );
2276 }
2277 else if ( $nodeType == eZTemplate::NODE_ROOT )
2278 {
2279 $children = $node[1];
2280 if ( $children )
2281 {
2282 $newCurrentParameters = $currentParameters;
2283 $newCurrentParameters['spacing'] += 4;
2284 eZTemplateCompiler::generatePHPCodeChildren( $useComments, $php, $tpl, $children, $resourceData, $parameters, $newCurrentParameters );
2285 }
2286 continue;
2287 }
2288 else if ( $nodeType == eZTemplate::NODE_TEXT )
2289 {
2290 $text = $node[2];
2291 if ( $text != '' )
2292 {
2293 $variablePlacement = $node[3];
2294 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement );
2295 if ( $useComments )
2296 {
2297 $php->addComment( "Text start:", true, true, array( 'spacing' => $currentParameters['spacing'] ) );
2298 $php->addComment( $originalText, true, true, array( 'spacing' => $currentParameters['spacing'] ) );
2299 $php->addComment( "Text end:", true, true, array( 'spacing' => $currentParameters['spacing'] ) );
2300 }
2301 $php->addVariable( eZTemplateCompiler::currentTextName( $parameters ),
2302 $text, eZPHPCreator::VARIABLE_APPEND_TEXT,
2303 array( 'spacing' => $currentParameters['spacing'] ) );
2304 }
2305 continue;
2306 }
2307 else if ( $nodeType == eZTemplate::NODE_VARIABLE )
2308 {
2309 $variableAssignmentName = $node[1];
2310 $variableData = $node[2];
2311 $variablePlacement = $node[3];
2312
2313 $variableParameters = array();
2314 if ( isset( $node[4] ) and
2315 $node[4] )
2316 $variableParameters = $node[4];
2317 $variableOnlyExisting = isset( $node[5] ) ? $node[5] : false;
2318 $variableOverWrite = isset( $node[6] ) ? $node[6] : false;
2319 $rememberSet = isset( $node[7] ) ? $node[7] : false;
2320
2321 $spacing = $currentParameters['spacing'];
2322 if ( isset( $variableParameters['spacing'] ) )
2323 $spacing += $variableParameters['spacing'];
2324 $variableParameters = array_merge( array( 'variable-name' => 'var',
2325 'text-result' => true ),
2326 $variableParameters );
2327 $dataInspection = eZTemplateCompiler::inspectVariableData( $tpl,
2328 $variableData, $variablePlacement,
2329 $resourceData );
2330 $newNode = $node;
2331 $newNode[1] = false;
2332
2333 $treatVariableDataAsNonObject = isset( $variableParameters['treat-value-as-non-object'] ) && $variableParameters['treat-value-as-non-object'];
2334
2335 if ( $useComments )
2336 {
2337 $php->addComment( "Variable data: " .
2338 "Is constant: " . ( $dataInspection['is-constant'] ? 'Yes' : 'No' ) .
2339 " Is variable: " . ( $dataInspection['is-variable'] ? 'Yes' : 'No' ) .
2340 " Has attributes: " . ( $dataInspection['has-attributes'] ? 'Yes' : 'No' ) .
2341 " Has operators: " . ( $dataInspection['has-operators'] ? 'Yes' : 'No' ),
2342 true, true, array( 'spacing' => $spacing )
2343 );
2344 $originalText = eZTemplateCompiler::fetchTemplatePiece( $variablePlacement );
2345 $php->addComment( '{' . $originalText . '}', true, true, array( 'spacing' => $spacing ) );
2346 }
2347 $generatedVariableName = $variableParameters['variable-name'];
2348 $assignVariable = false;
2349 if ( $variableAssignmentName !== false )
2350 {
2351 if ( is_array( $variableAssignmentName ) )
2352 {
2353 $variableParameters['text-result'] = false;
2354 $assignVariable = true;
2355 }
2356 else
2357 {
2358 $generatedVariableName = $variableAssignmentName;
2359 $variableParameters['text-result'] = false;
2360 }
2361 }
2362
2363 $isStaticElement = false;
2364 $nodeElements = $node[2];
2365 $knownTypes = array();
2366 if ( eZTemplateNodeTool::isConstantElement( $nodeElements ) and
2367 !$variableParameters['text-result'] )
2368 {
2369 $variableText = $php->thisVariableText( eZTemplateNodeTool::elementConstantValue( $nodeElements ), 0, 0, false );
2370 $isStaticElement = true;
2371 }
2372 else if ( eZTemplateNodeTool::isPHPVariableElement( $nodeElements ) and
2373 !$variableParameters['text-result'] )
2374 {
2375 $variableText = '$' . eZTemplateNodeTool::elementConstantValue( $nodeElements );
2376 $isStaticElement = true;
2377 }
2378 else
2379 {
2380 $variableText = "\$$generatedVariableName";
2381 eZTemplateCompiler::generateVariableCode( $php, $tpl, $node, $knownTypes, $dataInspection,
2382 array( 'spacing' => $spacing,
2383 'variable' => $generatedVariableName,
2384 'treat-value-as-non-object' => $treatVariableDataAsNonObject,
2385 'counter' => 0 ),
2386 $resourceData );
2387 }
2388
2389 if ( $variableParameters['text-result'] )
2390 {
2391 $textName = eZTemplateCompiler::currentTextName( $parameters );
2392 if ( count( $knownTypes ) == 0 or in_array( 'objectproxy', $knownTypes ) )
2393 {
2394 $php->addCodePiece( "\$$textName .= ( is_object( \$$generatedVariableName ) ? compiledFetchText( \$tpl, \$rootNamespace, \$currentNamespace, false, \$$generatedVariableName ) : \$$generatedVariableName );" . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "\n" .
2395 "unset( \$$generatedVariableName );\n", array( 'spacing' => $spacing ) );
2396 }
2397 else
2398 {
2399 $php->addCodePiece( "\$$textName .= \$$generatedVariableName;\n" .
2400 "unset( \$$generatedVariableName );\n", array( 'spacing' => $spacing ) );
2401 }
2402 }
2403 else if ( $assignVariable )
2404 {
2405 $namespace = $variableAssignmentName[0];
2406 $namespaceScope = $variableAssignmentName[1];
2407 $variableName = $variableAssignmentName[2];
2408 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true );
2409 if ( !is_string( $namespaceText ) )
2410 $namespaceText = "\$namespace";
2411 $variableNameText = $php->thisVariableText( $variableName, 0, 0, false );
2412 $unsetVariableText = false;
2413 if ( $variableOnlyExisting )
2414 {
2415 if ( !$isStaticElement )
2416 $unsetVariableText = "\n unset( $variableText );";
2417 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( array_key_exists( $namespaceText, \$vars ) && array_key_exists( $variableNameText, \$vars[$namespaceText] ) )\n".
2418 "{\n".
2419 " \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n".
2420 "}",
2421 array( 'spacing' => $spacing ) );
2422 }
2423 else if ( $variableOverWrite )
2424 {
2425 if ( !$isStaticElement )
2426 $unsetVariableText = "\nunset( $variableText );";
2427 if ( isset( $variableParameters['local-variable'] ) )
2428 {
2429 $php->addCodePiece( "if ( \$tpl->hasVariable( $variableNameText, $namespaceText ) )\n{\n" ); // if the variable already exists
2430 $php->addCodePiece( " \$tpl->warning( '" . eZTemplateDefFunction::DEF_FUNCTION_NAME . "', \"Variable '$variableName' is already defined.\", " . $php->thisVariableText( $variablePlacement ) . " );\n" );
2431 $php->addCodePiece( " \$tpl->setVariable( $variableNameText, $variableText, $namespaceText );\n}\nelse\n{\n" );
2432 $php->addCodePiece( " \$tpl->setLocalVariable( $variableNameText, $variableText, $namespaceText );\n}\n" ,
2433 array( 'spacing' => $spacing ) );
2434 }
2435 else
2436 {
2437 $php->addCodePiece( "\$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText",
2438 array( 'spacing' => $spacing ) );
2439 }
2440
2441 }
2442 else if ( $rememberSet )
2443 {
2444 if ( !$isStaticElement )
2445 $unsetVariableText = "\n unset( $variableText );";
2446 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$vars[$namespaceText][$variableNameText] ) )\n".
2447 "{\n".
2448 " \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n".
2449 " \$setArray[$namespaceText][$variableNameText] = true;\n".
2450 "}\n",
2451 array( 'spacing' => $spacing ) );
2452 }
2453 else
2454 {
2455 if ( !$isStaticElement )
2456 $unsetVariableText = "\n unset( $variableText );";
2457 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( !isset( \$vars[$namespaceText][$variableNameText] ) )\n{\n \$vars[$namespaceText][$variableNameText] = $variableText;$unsetVariableText\n}",
2458 array( 'spacing' => $spacing ) );
2459 }
2460 }
2461 else if ( $variableAssignmentName !== false and $isStaticElement )
2462 {
2463 $php->addCodePiece( "\$$generatedVariableName = $variableText;", array( 'spacing' => $spacing ) );
2464 }
2465 else if ( $variableAssignmentName !== false and !$isStaticElement and !$treatVariableDataAsNonObject )
2466 {
2467 // Normal assignment from an expression, no need to anything extra
2468 }
2469 unset( $dataInspection );
2470 }
2471 else if ( $nodeType == eZTemplate::NODE_FUNCTION )
2472 {
2473 $functionChildren = $node[1];
2474 $functionName = $node[2];
2475 $functionParameters = $node[3];
2476 $functionPlacement = $node[4];
2477
2478 $newNode = array( $nodeType,
2479 false,
2480 $functionName,
2481 $functionParameters,
2482 $functionPlacement );
2483
2484 $parameterText = 'No parameters';
2485 if ( $functionParameters )
2486 {
2487 $parameterText = "Parameters: ". implode( ', ', array_keys( $functionParameters ) );
2488 }
2489 if ( $useComments )
2490 {
2491 $php->addComment( "Function: $functionName, $parameterText", true, true, array( 'spacing' => $currentParameters['spacing'] ) );
2492 $originalText = eZTemplateCompiler::fetchTemplatePiece( $functionPlacement );
2493 $php->addComment( '{' . $originalText . '}', true, true, array( 'spacing' => $currentParameters['spacing'] ) );
2494 }
2495 if ( isset( $node[5] ) )
2496 {
2497 $functionHook = $node[5];
2498 $functionHookCustomFunction = $functionHook['function'];
2499 if ( $functionHookCustomFunction )
2500 {
2501 $functionHookCustomFunction = array_merge( array( 'add-function-name' => false,
2502 'add-hook-name' => false,
2503 'add-template-handler' => true,
2504 'add-function-hook-data' => false,
2505 'add-function-parameters' => true,
2506 'add-function-placement' => false,
2507 'add-calculated-namespace' => false,
2508 'add-namespace' => true,
2509 'add-input' => false,
2510 'return-value' => false ),
2511 $functionHookCustomFunction );
2512 if ( !isset( $parameters['hook-result-variable-counter'][$functionName] ) )
2513 $parameters['hook-result-variable-counter'][$functionName] = 0;
2514 if ( $functionHookCustomFunction['return-value'] )
2515 $parameters['hook-result-variable-counter'][$functionName]++;
2516 $hookResultName = $functionName . 'Result' . $parameters['hook-result-variable-counter'][$functionName];
2517 if ( $functionHookCustomFunction['add-input'] )
2518 $parameters['hook-result-variable-counter'][$functionName]--;
2519 $functionHookCustomFunctionName = $functionHookCustomFunction['name'];
2520 $codeText = '';
2521 if ( $functionHookCustomFunction['return-value'] )
2522 $codeText = "\$$hookResultName = ";
2523 if ( $functionHookCustomFunction['static'] )
2524 {
2525 $hookClassName = $functionHookCustomFunction['class-name'];
2526 $codeText .= "$hookClassName::$functionHookCustomFunctionName( ";
2527 }
2528 else
2529 $codeText .= "\$functionObject->$functionHookCustomFunctionName( ";
2530 $codeTextLength = strlen( $codeText );
2531
2532 $functionNameText = $php->thisVariableText( $functionName, 0, 0, false );
2533 $functionChildrenText = $php->thisVariableText( $functionChildren, $codeTextLength, 0, false );
2534
2535 $inputFunctionParameters = $functionParameters;
2536 if ( $functionHookCustomFunction['add-calculated-namespace'] )
2537 unset( $inputFunctionParameters['name'] );
2538 $functionParametersText = $php->thisVariableText( $inputFunctionParameters, $codeTextLength, 0, false );
2539
2540 $functionPlacementText = $php->thisVariableText( $functionPlacement, $codeTextLength, 0, false );
2541 $functionHookText = $php->thisVariableText( $functionHook, $codeTextLength, 0, false );
2542
2543 $functionHookName = $functionHook['name'];
2544 $functionHookNameText = $php->thisVariableText( $functionHookName, 0, 0, false );
2545
2546 $codeParameters = array();
2547 if ( $functionHookCustomFunction['add-function-name'] )
2548 $codeParameters[] = $functionNameText;
2549 if ( $functionHookCustomFunction['add-hook-name'] )
2550 $codeParameters[] = $functionHookNameText;
2551 if ( $functionHookCustomFunction['add-function-hook-data'] )
2552 $codeParameters[] = $functionHookText;
2553 if ( $functionHookCustomFunction['add-template-handler'] )
2554 $codeParameters[] = "\$tpl";
2555 if ( $functionHookCustomFunction['add-function-parameters'] )
2556 $codeParameters[] = $functionParametersText;
2557 if ( $functionHookCustomFunction['add-function-placement'] )
2558 $codeParameters[] = $functionPlacementText;
2559 if ( $functionHookCustomFunction['add-calculated-namespace'] )
2560 {
2561 $name = '';
2562 if ( isset( $functionParameters['name'] ) )
2563 {
2564 $nameParameter = $functionParameters['name'];
2565 $nameInspection = eZTemplateCompiler::inspectVariableData( $tpl,
2566 $nameParameter, $functionPlacement,
2567 $resourceData );
2568 if ( $nameInspection['is-constant'] and
2569 !$nameInspection['is-variable'] and
2570 !$nameInspection['has-attributes'] and
2571 !$nameInspection['has-operators'] )
2572 {
2573 $nameData = $nameParameter[0][1];
2574 $nameText = $php->thisVariableText( $nameData, 0, 0, false );
2575 $php->addCodePiece( "if ( \$currentNamespace != '' )
2576 \$name = \$currentNamespace . ':' . $nameText;
2577 else
2578 \$name = $nameText;\n", array( 'spacing' => $currentParameters['spacing'] ) );
2579 $codeParameters[] = "\$name";
2580 }
2581 else
2582 {
2583 $persistence = array();
2584 $knownTypes = array();
2585 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $nameParameter, $knownTypes, $nameInspection,
2586 $persistence,
2587 array( 'variable' => 'name',
2588 'counter' => 0 ),
2589 $resourceData );
2590 $php->addCodePiece( "if " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( \$currentNamespace != '' )
2591 {
2592 if ( \$name != '' )
2593 \$name = \"\$currentNamespace:\$name\";
2594 else
2595 \$name = \$currentNamespace;
2596 }\n", array( 'spacing' => $currentParameters['spacing'] ) );
2597 $codeParameters[] = "\$name";
2598 }
2599 }
2600 else
2601 {
2602 $codeParameters[] = "\$currentNamespace";
2603 }
2604 }
2605 if ( $functionHookCustomFunction['add-namespace'] )
2606 $codeParameters[] = "\$rootNamespace, \$currentNamespace";
2607 if ( $functionHookCustomFunction['add-input'] )
2608 $codeParameters[] = "\$$hookResultName";
2609 $codeText .= implode( ",\n" . str_repeat( ' ', $codeTextLength ),
2610 $codeParameters );
2611 $codeText .= " );\n";
2612 if ( $functionHookCustomFunction['static'] )
2613 {
2614 $hookFile = $functionHookCustomFunction['php-file'];
2615 $hookFileText = $php->thisVariableText( $hookFile, 0, 0, false );
2616 $php->addCodePiece( "include_once( $hookFileText );\n", array( 'spacing' => $currentParameters['spacing'] ) );
2617 }
2618 else
2619 $php->addCodePiece( "\$functionObject = \$tpl->fetchFunctionObject( $functionNameText );\n", array( 'spacing' => $currentParameters['spacing'] ) );
2620 $php->addCodePiece( $codeText, array( 'spacing' => $currentParameters['spacing'] ) );
2621 }
2622 else
2623 {
2624 $functionNameText = $php->thisVariableText( $functionName, 0, 0, false );
2625 $functionChildrenText = $php->thisVariableText( $functionChildren, 52, 0, false );
2626 $functionParametersText = $php->thisVariableText( $functionParameters, 52, 0, false );
2627 $functionPlacementText = $php->thisVariableText( $functionPlacement, 52, 0, false );
2628
2629 $functionHookText = $php->thisVariableText( $functionHook, 52, 0, false );
2630 $functionHookName = $functionHook['name'];
2631 $functionHookNameText = $php->thisVariableText( $functionHookName, 0, 0, false );
2632 $functionHookParameters = $functionHook['parameters'];
2633 $php->addCodePiece( "\$functionObject = \$tpl->fetchFunctionObject( $functionNameText );
2634 \$hookResult = \$functionObject->templateHookProcess( $functionNameText, $functionHookNameText,
2635 $functionHookText,
2636 \$tpl,
2637 $functionParametersText,
2638 $functionPlacementText,
2639 \$rootNamespace, \$currentNamespace );
2640 ", array( 'spacing' => $currentParameters['spacing'] ) );
2641 }
2642 }
2643 else
2644 {
2645 $textName = eZTemplateCompiler::currentTextName( $parameters );
2646 $functionNameText = $php->thisVariableText( $functionName, 0, 0, false );
2647 $functionChildrenText = $php->thisVariableText( $functionChildren, 22, 0, false );
2648 $functionParametersText = $php->thisVariableText( $functionParameters, 22, 0, false );
2649 $functionPlacementText = $php->thisVariableText( $functionPlacement, 22, 0, false );
2650 $php->addCodePiece( "\$textElements = array();
2651 \$tpl->processFunction( $functionNameText, \$textElements,
2652 $functionChildrenText,
2653 $functionParametersText,
2654 $functionPlacementText,
2655 \$rootNamespace, \$currentNamespace );
2656 \$$textName .= implode( '', \$textElements );\n", array( 'spacing' => $currentParameters['spacing'] ) );
2657 }
2658 }
2659 $php->addSpace();
2660 }
2661 }
2662
2668 static function generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, $parameters = array(), $skipSimpleAssignment = false )
2669 {
2670 if ( $namespace != '' )
2671 {
2672 if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_GLOBAL )
2673 {
2674 $php->addVariable( 'namespace', $namespace, eZPHPCreator::VARIABLE_ASSIGNMENT, $parameters );
2675 }
2676 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_LOCAL )
2677 {
2678 $php->addCodePiece( "\$namespace = \$rootNamespace;
2679 if ( \$namespace == '' )
2680 \$namespace = \"$namespace\";
2681 else
2682 \$namespace .= ':$namespace';
2683 ", $parameters );
2684 }
2685 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_RELATIVE )
2686 {
2687 $php->addCodePiece( "\$namespace = \$currentNamespace;
2688 if ( \$namespace == '' )
2689 \$namespace = \"$namespace\";
2690 else
2691 \$namespace .= ':$namespace';
2692 ", $parameters );
2693 }
2694 }
2695 else
2696 {
2697 if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_GLOBAL )
2698 {
2699 if ( $skipSimpleAssignment )
2700 return "''";
2701 $php->addVariable( 'namespace', '', eZPHPCreator::VARIABLE_ASSIGNMENT, $parameters );
2702 }
2703 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_LOCAL )
2704 {
2705 if ( $skipSimpleAssignment )
2706 return "\$rootNamespace";
2707 $php->addCodePiece( "\$namespace = \$rootNamespace;\n", $parameters );
2708 }
2709 else if ( $namespaceScope == eZTemplate::NAMESPACE_SCOPE_RELATIVE )
2710 {
2711 if ( $skipSimpleAssignment )
2712 return "\$currentNamespace";
2713 $php->addCodePiece( "\$namespace = \$currentNamespace;\n", $parameters );
2714 }
2715 }
2716 return true;
2717 }
2718
2723 static function generateVariableCode( $php, $tpl, $node, &$knownTypes, $dataInspection, $parameters, &$resourceData )
2724 {
2725 $variableData = $node[2];
2726 $persistence = array();
2727 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $variableData, $knownTypes, $dataInspection, $persistence, $parameters, $resourceData );
2728 }
2729
2736 static function generateVariableDataCode( $php, $tpl, $variableData, &$knownTypes, $dataInspection, &$persistence, $parameters, &$resourceData )
2737 {
2738 $staticTypeMap = array( eZTemplate::TYPE_STRING => 'string',
2739 eZTemplate::TYPE_NUMERIC => 'numeric',
2740 eZTemplate::TYPE_IDENTIFIER => 'string',
2741 eZTemplate::TYPE_ARRAY => 'array',
2742 eZTemplate::TYPE_BOOLEAN => 'boolean' );
2743
2744 $variableAssignmentName = $parameters['variable'];
2745 $variableAssignmentCounter = $parameters['counter'];
2746 $spacing = 0;
2747 $optimizeNode = false;
2748 if ( isset( $parameters['spacing'] ) )
2749 $spacing = $parameters['spacing'];
2750 if ( $variableAssignmentCounter > 0 )
2751 $variableAssignmentName .= $variableAssignmentCounter;
2752
2753 // We need to unset the assignment variable before any elements are processed
2754 // This ensures that we don't work on existing variables
2755 $php->addCodePiece( "unset( \$$variableAssignmentName );\n", array( 'spacing' => $spacing ) );
2756
2757 if ( is_array( $variableData ) )
2758 {
2759 foreach ( $variableData as $index => $variableDataItem )
2760 {
2761 $variableDataType = $variableDataItem[0];
2762 if ( $variableDataType == eZTemplate::TYPE_STRING or
2763 $variableDataType == eZTemplate::TYPE_NUMERIC or
2764 $variableDataType == eZTemplate::TYPE_IDENTIFIER or
2765 $variableDataType == eZTemplate::TYPE_ARRAY or
2766 $variableDataType == eZTemplate::TYPE_BOOLEAN )
2767 {
2768 $knownTypes = array_unique( array_merge( $knownTypes, array( $staticTypeMap[$variableDataType] ) ) );
2769 $dataValue = $variableDataItem[1];
2770 $dataText = $php->thisVariableText( $dataValue, 0, 0, false );
2771 $php->addCodePiece( "\$$variableAssignmentName = $dataText;\n", array( 'spacing' => $spacing ) );
2772 }
2773 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_NODE )
2774 {
2775 $optimizeNode = true;
2776 if ( !isset( $resourceData['node-object-cached'] ) )
2777 $tpl->error( "eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ), "Attribute node-object-cached of variable \$resourceData was not found but variable node eZTemplate::TYPE_OPTIMIZED_NODE is still present. This should not happen" );
2778 $php->addCodePiece("\$$variableAssignmentName = \$nod_{$resourceData['uniqid']};\n");
2779
2780 // If optimized node is not set, use unoptimized code.
2781 $php->addCodePiece( "if ( !\$$variableAssignmentName )\n{\n" );
2782 }
2783 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_ARRAY_LOOKUP )
2784 {
2785 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" );
2786
2787 // This code is used a lot so we create a variable for it
2788 $phpVar = "\$$variableAssignmentName";
2789 $indexName = "'{$variableDataItem[1][0][1]}'";
2790
2791 // Add sanity checking
2792 $code .= ( "if ( !isset( {$phpVar}[{$indexName}] ) )\n" .
2793 "{\n" .
2794 " \$tpl->error( 'eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ) . "', \"PHP variable \\$phpVar"."[{$indexName}] does not exist, cannot fetch the value.\" );\n" .
2795 " $phpVar = null;\n" .
2796 "}\n" .
2797 "else\n " );
2798
2799 // Add the actual code
2800 $code .= "$phpVar = {$phpVar}[{$indexName}];\n";
2801
2802 $php->addCodePiece( $code );
2803 }
2804 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_ATTRIBUTE_LOOKUP )
2805 {
2806 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" );
2807 $code .= <<<END
2808 if ( !is_object( \${$variableAssignmentName} ) )
2809 {
2810 \${$variableAssignmentName} = null;
2811 }
2812 else if ( \${$variableAssignmentName}->hasAttribute( "{$variableDataItem[1][0][1]}" ) )
2813 {
2814 \${$variableAssignmentName} = \${$variableAssignmentName}->attribute( "{$variableDataItem[1][0][1]}" );
2815 }
2816
2817 END;
2818 $php->addCodePiece($code);
2819 }
2820 else if ( $variableDataType == eZTemplate::TYPE_OPTIMIZED_CONTENT_CALL )
2821 {
2822 // Line number comment
2823 $code = ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/\n" ) : "" );
2824
2825 // This code is used a lot so we create a variable for it
2826 $phpVar = "\$$variableAssignmentName";
2827
2828 // Add sanity checking
2829 $code .= ( "if ( !is_object( $phpVar ) )\n" .
2830 "{\n" .
2831 " \$tpl->error( 'eZTemplateCompiler" . ( $resourceData['use-comments'] ? ( ":" . __LINE__ ) : "" ) . "', \"PHP variable \\$phpVar is not an object, cannot fetch content()\" );\n" .
2832 " $phpVar = null;\n" .
2833 "}\n" .
2834 "else\n" .
2835 "{\n" );
2836
2837 // Add the actual code
2838 $code .= " {$phpVar}Tmp = {$phpVar}->content();\n" .
2839 " unset( $phpVar );\n" .
2840 " $phpVar = {$phpVar}Tmp;\n" .
2841 " unset( {$phpVar}Tmp );\n}\n";
2842
2843 $php->addCodePiece( $code );
2844 }
2845 else if ( $variableDataType == eZTemplate::TYPE_PHP_VARIABLE )
2846 {
2847 $knownTypes = array();
2848 $phpVariableName = $variableDataItem[1];
2849 $php->addCodePiece( "\$$variableAssignmentName = \$$phpVariableName;\n", array( 'spacing' => $spacing ) );
2850 }
2851 else if ( $variableDataType == eZTemplate::TYPE_VARIABLE )
2852 {
2853 $knownTypes = array();
2854 $namespace = $variableDataItem[1][0];
2855 $namespaceScope = $variableDataItem[1][1];
2856 $variableName = $variableDataItem[1][2];
2857 $namespaceText = eZTemplateCompiler::generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, array( 'spacing' => $spacing ), true );
2858 if ( !is_string( $namespaceText ) )
2859 $namespaceText = "\$namespace";
2860 $variableNameText = $php->thisVariableText( $variableName, 0, 0, false );
2861 $code = "unset( \$$variableAssignmentName );\n";
2862 $code .= "\$$variableAssignmentName = ( array_key_exists( $namespaceText, \$vars ) and array_key_exists( $variableNameText, \$vars[$namespaceText] ) ) ? \$vars[$namespaceText][$variableNameText] : null;\n";
2863 $php->addCodePiece( $code,
2864 array( 'spacing' => $spacing ) );
2865 }
2866 else if ( $variableDataType == eZTemplate::TYPE_ATTRIBUTE )
2867 {
2868 $knownTypes = array();
2869 $newParameters = $parameters;
2870 $newParameters['counter'] += 1;
2871 $tmpVariableAssignmentName = $newParameters['variable'];
2872 $tmpVariableAssignmentCounter = $newParameters['counter'];
2873 if ( $tmpVariableAssignmentCounter > 0 )
2874 $tmpVariableAssignmentName .= $tmpVariableAssignmentCounter;
2875 if ( eZTemplateNodeTool::isConstantElement( $variableDataItem[1] ) )
2876 {
2877 $attributeStaticValue = eZTemplateNodeTool::elementConstantValue( $variableDataItem[1] );
2878 $attributeText = $php->thisVariableText( $attributeStaticValue, 0, 0, false );
2879 }
2880 else
2881 {
2882 $newParameters['counter'] += 1;
2883 $tmpKnownTypes = array();
2884 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $variableDataItem[1], $tmpKnownTypes, $dataInspection,
2885 $persistence, $newParameters, $resourceData );
2886 $newVariableAssignmentName = $newParameters['variable'];
2887 $newVariableAssignmentCounter = $newParameters['counter'];
2888 if ( $newVariableAssignmentCounter > 0 )
2889 $newVariableAssignmentName .= $newVariableAssignmentCounter;
2890 $attributeText = "\$$newVariableAssignmentName";
2891 }
2892 $php->addCodePiece( "\$$tmpVariableAssignmentName = compiledFetchAttribute( \$$variableAssignmentName, $attributeText );\n" .
2893 "unset( \$$variableAssignmentName );\n" .
2894 "\$$variableAssignmentName = \$$tmpVariableAssignmentName;\n",
2895 array( 'spacing' => $spacing ) );
2896
2897 // End if optimized node object is null/false. See also eZTemplateOptimizer::optimizeVariable()
2898 if ( $optimizeNode &&
2899 $index == 3 )
2900 {
2901 $php->addCodePiece( "}\n" );
2902 }
2903 }
2904 else if ( $variableDataType == eZTemplate::TYPE_OPERATOR )
2905 {
2906 $knownTypes = array();
2907 $operatorParameters = $variableDataItem[1];
2908 $operatorName = $operatorParameters[0];
2909 $operatorParameters = array_splice( $operatorParameters, 1 );
2910 $operatorNameText = $php->thisVariableText( $operatorName, 0, 0, false );
2911 $operatorParametersText = $php->thisVariableText( $operatorParameters, 23, 0, false );
2912
2913 $operatorHint = eZTemplateCompiler::operatorHint( $tpl, $operatorName );
2914 if ( isset( $operatorHint['output'] ) and $operatorHint['output'] )
2915 {
2916 if ( isset( $operatorHint['output-type'] ) )
2917 {
2918 $knownType = $operatorHint['output-type'];
2919 if ( is_array( $knownType ) )
2920 $knownTypes = array_merge( $knownTypes, $knownType );
2921 else
2922 $knownTypes[] = $knownType;
2923 $knownTypes = array_unique( $knownTypes );
2924 }
2925 else
2926 $knownTypes[] = 'static';
2927 }
2928
2929 $php->addCodePiece( "if (! isset( \$$variableAssignmentName ) ) \$$variableAssignmentName = NULL;\n", array ( 'spacing' => $spacing ) );
2930 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$variableAssignmentName ) and method_exists( \$$variableAssignmentName, 'templateValue' ) )\n" .
2931 " \$$variableAssignmentName = \$$variableAssignmentName" . "->templateValue();\n" );
2932 $php->addCodePiece( "\$" . $variableAssignmentName . "Data = array( 'value' => \$$variableAssignmentName );
2933 \$tpl->processOperator( $operatorNameText,
2934 $operatorParametersText,
2935 \$rootNamespace, \$currentNamespace, \$" . $variableAssignmentName . "Data, false, false );
2936 \$$variableAssignmentName = \$" . $variableAssignmentName . "Data['value'];
2937 unset( \$" . $variableAssignmentName . "Data );\n",
2938 array( 'spacing' => $spacing ) );
2939 }
2940 else if ( $variableDataType == eZTemplate::TYPE_VOID )
2941 {
2942 }
2943 else if ( $variableDataType == eZTemplate::TYPE_DYNAMIC_ARRAY )
2944 {
2945 $knownTypes = array_unique( array_merge( $knownTypes, array( 'array' ) ) );
2946 $code = '%output% = array( ';
2947
2948 $matchMap = array( '%input%', '%output%' );
2949 $replaceMap = array( '$' . $variableAssignmentName, '$' . $variableAssignmentName );
2950 $unsetList = array();
2951 $counter = 1;
2952 $paramCount = 0;
2953
2954 $values = $variableDataItem[2];
2955 $newParameters = $parameters;
2956 foreach ( $values as $key => $value )
2957 {
2958 if ( $paramCount != 0 )
2959 {
2960 $code .= ', ';
2961 }
2962 ++$paramCount;
2963 $code .= '\'' . $key . '\' => ';
2964 if( eZTemplateNodeTool::isConstantElement( $value ) )
2965 {
2966 $code .= eZPHPCreator::variableText( eZTemplateNodeTool::elementConstantValue( $value ), 0, 0, false );
2967 continue;
2968 }
2969 $code .= '%' . $counter . '%';
2970 $newParameters['counter'] += 1;
2971 $newVariableAssignmentName = $newParameters['variable'];
2972 $newVariableAssignmentCounter = $newParameters['counter'];
2973 if ( $newVariableAssignmentCounter > 0 )
2974 $newVariableAssignmentName .= $newVariableAssignmentCounter;
2975 $matchMap[] = '%' . $counter . '%';
2976 $replaceMap[] = '$' . $newVariableAssignmentName;
2977 $unsetList[] = $newVariableAssignmentName;
2978 $tmpKnownTypes = array();
2979 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $value, $tmpKnownTypes, $dataInspection,
2980 $persistence, $newParameters, $resourceData );
2981 ++$counter;
2982 }
2983
2984 $code .= ' );';
2985 $code = str_replace( $matchMap, $replaceMap, $code );
2986 $php->addCodePiece( $code, array( 'spacing' => $spacing ) );
2987 $php->addVariableUnsetList( $unsetList, array( 'spacing' => $spacing ) );
2988 }
2989 else if ( $variableDataType == eZTemplate::TYPE_INTERNAL_CODE_PIECE )
2990 {
2991 $code = $variableDataItem[1];
2992 $values = false;
2993 $matchMap = array( '%input%', '%output%' );
2994 $replaceMap = array( '$' . $variableAssignmentName, '$' . $variableAssignmentName );
2995 $unsetList = array();
2996 $counter = 1;
2997 if ( isset( $variableDataItem[3] ) && is_array( $variableDataItem[3] ) )
2998 {
2999 $newParameters = $parameters;
3000 $values = $variableDataItem[3];
3001 foreach ( $values as $value )
3002 {
3003 $newParameters['counter'] += 1;
3004 $newVariableAssignmentName = $newParameters['variable'];
3005 $newVariableAssignmentCounter = $newParameters['counter'];
3006 if ( $newVariableAssignmentCounter > 0 )
3007 $newVariableAssignmentName .= $newVariableAssignmentCounter;
3008 if ( eZTemplateNodeTool::isConstantElement( $value ) )
3009 {
3010 $staticValue = eZTemplateNodeTool::elementConstantValue( $value );
3011 $staticValueText = $php->thisVariableText( $staticValue, 0, 0, false );
3012 if ( preg_match( "/%code$counter%/", $code ) )
3013 {
3014 $matchMap[] = '%code' . $counter . '%';
3015 $replaceMap[] = '';
3016 }
3017 $matchMap[] = '%' . $counter . '%';
3018 $replaceMap[] = $staticValueText;
3019 }
3020 else
3021 {
3022 $matchMap[] = '%' . $counter . '%';
3023 $replaceMap[] = '$' . $newVariableAssignmentName;
3024 $unsetList[] = $newVariableAssignmentName;
3025 if ( preg_match( "/%code$counter%/", $code ) )
3026 {
3027 $tmpPHP = new eZPHPCreator( '', '', eZTemplateCompiler::TemplatePrefix() );
3028 $tmpKnownTypes = array();
3029 eZTemplateCompiler::generateVariableDataCode( $tmpPHP, $tpl, $value, $tmpKnownTypes, $dataInspection,
3030 $persistence, $newParameters, $resourceData );
3031 $newCode = $tmpPHP->fetch( false );
3032 if ( count( $tmpKnownTypes ) == 0 or in_array( 'objectproxy', $tmpKnownTypes ) )
3033 {
3034 $newCode .= ( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$newVariableAssignmentName ) and method_exists( \$$newVariableAssignmentName, 'templateValue' ) )\n" .
3035 " \$$newVariableAssignmentName = \$$newVariableAssignmentName" . "->templateValue();\n" );
3036 }
3037 $matchMap[] = '%code' . $counter . '%';
3038 $replaceMap[] = $newCode;
3039 }
3040 else
3041 {
3042 $tmpKnownTypes = array();
3043 eZTemplateCompiler::generateVariableDataCode( $php, $tpl, $value, $tmpKnownTypes, $dataInspection,
3044 $persistence, $newParameters, $resourceData );
3045 if ( !$parameters['treat-value-as-non-object'] and ( count( $tmpKnownTypes ) == 0 or in_array( 'objectproxy', $tmpKnownTypes ) ) )
3046 {
3047 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$newVariableAssignmentName ) and method_exists( \$$newVariableAssignmentName, 'templateValue' ) )\n" .
3048 " \$$newVariableAssignmentName = \$$newVariableAssignmentName" . "->templateValue();\n",
3049 array( 'spacing' => $spacing ) );
3050 }
3051 }
3052 }
3053 ++$counter;
3054 }
3055 }
3056 if ( isset( $variableDataItem[4] ) && ( $variableDataItem[4] !== false ) )
3057 {
3058 $values = $variableDataItem[4];
3059
3060 for ( $i = 0; $i < $values; $i++ )
3061 {
3062 $newParameters['counter'] += 1;
3063 $newVariableAssignmentName = $newParameters['variable'];
3064 $newVariableAssignmentCounter = $newParameters['counter'];
3065 if ( $newVariableAssignmentCounter > 0 )
3066 $newVariableAssignmentName .= $newVariableAssignmentCounter;
3067 $matchMap[] = '%tmp' . ( $i + 1 ) . '%';
3068 $replaceMap[] = '$' . $newVariableAssignmentName;
3069 $unsetList[] = $newVariableAssignmentName;
3070 }
3071 }
3072 if ( isset( $variableDataItem[5] ) and $variableDataItem[5] )
3073 {
3074 if ( is_array( $variableDataItem[5] ) )
3075 $knownTypes = array_unique( array_merge( $knownTypes, $variableDataItem[5] ) );
3076 else if ( is_string( $variableDataItem[5] ) )
3077 $knownTypes = array_unique( array_merge( $knownTypes, array( $variableDataItem[5] ) ) );
3078 else
3079 $knownTypes = array_unique( array_merge( $knownTypes, array( 'static' ) ) );
3080 }
3081 $code = str_replace( $matchMap, $replaceMap, $code );
3082 $php->addCodePiece( $code, array( 'spacing' => $spacing ) );
3083 $php->addVariableUnsetList( $unsetList, array( 'spacing' => $spacing ) );
3084 }
3085 }
3086 }
3087 // After the entire expression line is done we try to extract the actual value if proxies are used
3088 $php->addCodePiece( "if (! isset( \$$variableAssignmentName ) ) \$$variableAssignmentName = NULL;\n" );
3089 $php->addCodePiece( "while " . ( $resourceData['use-comments'] ? ( "/*TC:" . __LINE__ . "*/" ) : "" ) . "( is_object( \$$variableAssignmentName ) and method_exists( \$$variableAssignmentName, 'templateValue' ) )\n" .
3090 " \$$variableAssignmentName = \$$variableAssignmentName" . "->templateValue();\n" );
3091 }
3092 }
3093
3094 ?>
eZDebugSetting\writeDebug
static writeDebug( $conditionName, $string, $label="")
Definition: ezdebugsetting.php:127
eZDebug\writeError
static writeError( $string, $label="", $backgroundClass="")
Definition: ezdebug.php:545
eZDir\path
static path( $names, $includeEndSeparator=false, $type=self::SEPARATOR_UNIX)
Definition: ezdir.php:237
eZHTTPTool\instance
static instance()
Definition: ezhttptool.php:189
eZLocale\instance
static instance( $localeString=false)
Definition: ezlocale.php:1536
eZPHPCreator
eZPHPCreator provides a simple interface for creating and executing PHP code.
eZSys\indexFile
static indexFile( $withAccessPath=true)
Definition: ezsys.php:618
eZSys\cacheDirectory
static cacheDirectory()
Definition: ezsys.php:527
eZTemplateCompiler
Creates compiled PHP code from templates to speed up template usage.
Definition: eztemplatecompiler.php:48
eZTemplateCompiler\compileTemplate
static compileTemplate( $tpl, $key, &$resourceData)
Definition: eztemplatecompiler.php:465
eZTemplateCompiler\processNodeCombining
static processNodeCombining( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode)
Definition: eztemplatecompiler.php:647
eZTemplateCompiler\currentTextName
static currentTextName( $parameters)
Definition: eztemplatecompiler.php:1767
eZTemplateCompiler\processElementTransformationChild
static processElementTransformationChild( $useComments, $php, $tpl, &$node, $elementTree, $elementList, &$resourceData)
Definition: eztemplatecompiler.php:1229
eZTemplateCompiler\processElementTransformationList
static processElementTransformationList( $tpl, &$node, $elements, &$privateData)
Definition: eztemplatecompiler.php:1211
eZTemplateCompiler\isDevelopmentModeEnabled
static isDevelopmentModeEnabled()
Definition: eztemplatecompiler.php:147
eZTemplateCompiler\compilationFilename
static compilationFilename( $key, $resourceData)
Definition: eztemplatecompiler.php:310
eZTemplateCompiler\isFallbackResourceCodeEnabled
static isFallbackResourceCodeEnabled()
Definition: eztemplatecompiler.php:198
eZTemplateCompiler\createCommonCompileTemplate
static createCommonCompileTemplate()
Definition: eztemplatecompiler.php:1678
eZTemplateCompiler\staticNodeData
static staticNodeData( $node)
Definition: eztemplatecompiler.php:868
eZTemplateCompiler\executeCompilationHelper
static executeCompilationHelper( $phpScript, &$text, $tpl, $key, &$resourceData, $rootNamespace, $currentNamespace)
Definition: eztemplatecompiler.php:435
eZTemplateCompiler\alwaysGenerate
static alwaysGenerate()
Definition: eztemplatecompiler.php:249
eZTemplateCompiler\boundVariableName
static boundVariableName( $variableID, $parameters)
Definition: eztemplatecompiler.php:1779
eZTemplateCompiler\executeCompilation
static executeCompilation( $tpl, &$textElements, $key, &$resourceData, $rootNamespace, $currentNamespace)
Definition: eztemplatecompiler.php:387
eZTemplateCompiler\combineStaticNodes
static combineStaticNodes( $tpl, &$resourceData, &$lastNode, &$newNode)
Definition: eztemplatecompiler.php:760
eZTemplateCompiler\processStaticOptimizations
static processStaticOptimizations( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode)
Definition: eztemplatecompiler.php:899
eZTemplateCompiler\CODE_DATE
const CODE_DATE
Definition: eztemplatecompiler.php:49
eZTemplateCompiler\processNodeTransformationNodes
static processNodeTransformationNodes( $tpl, &$node, &$nodes, &$privateData)
Definition: eztemplatecompiler.php:1012
eZTemplateCompiler\processNodeCombiningChildren
static processNodeCombiningChildren( $useComments, $php, $tpl, &$nodeChildren, &$resourceData, &$parentNode)
Definition: eztemplatecompiler.php:668
eZTemplateCompiler\processNodeTransformationChild
static processNodeTransformationChild( $useComments, $php, $tpl, &$node, &$resourceData)
Definition: eztemplatecompiler.php:1081
eZTemplateCompiler\compilationDirectory
static compilationDirectory()
Definition: eztemplatecompiler.php:277
eZTemplateCompiler\TemplatePrefix
static TemplatePrefix()
Definition: eztemplatecompiler.php:55
eZTemplateCompiler\isNodePlacementEnabled
static isNodePlacementEnabled()
Definition: eztemplatecompiler.php:215
eZTemplateCompiler\processRemoveNodePlacement
static processRemoveNodePlacement(&$node)
Definition: eztemplatecompiler.php:1370
eZTemplateCompiler\isTreeEnabled
static isTreeEnabled( $treeName)
Definition: eztemplatecompiler.php:266
eZTemplateCompiler\isCompilationEnabled
static isCompilationEnabled()
Definition: eztemplatecompiler.php:97
eZTemplateCompiler\inspectVariableData
static inspectVariableData( $tpl, $variableData, $variablePlacement, &$resourceData)
Definition: eztemplatecompiler.php:1417
eZTemplateCompiler\processNodeTransformation
static processNodeTransformation( $useComments, $php, $tpl, &$node, &$resourceData, &$newNode)
Definition: eztemplatecompiler.php:1002
eZTemplateCompiler\isCommentsEnabled
static isCommentsEnabled()
Definition: eztemplatecompiler.php:124
eZTemplateCompiler\isTimingPointsEnabled
static isTimingPointsEnabled()
Definition: eztemplatecompiler.php:181
eZTemplateCompiler\createStaticVariableData
static createStaticVariableData( $tpl, $staticData, $variableItemPlacement)
Definition: eztemplatecompiler.php:1616
eZTemplateCompiler\generateMergeNamespaceCode
static generateMergeNamespaceCode( $php, $tpl, $namespace, $namespaceScope, $parameters=array(), $skipSimpleAssignment=false)
Definition: eztemplatecompiler.php:2668
eZTemplateCompiler\setSettings
static setSettings( $settingsMap)
Definition: eztemplatecompiler.php:82
eZTemplateCompiler\generatePHPCodeChildren
static generatePHPCodeChildren( $useComments, $php, $tpl, &$nodeChildren, &$resourceData, &$parameters, $currentParameters)
Definition: eztemplatecompiler.php:1813
eZTemplateCompiler\isExecutionEnabled
static isExecutionEnabled()
Definition: eztemplatecompiler.php:232
eZTemplateCompiler\processNodeTransformationChildren
static processNodeTransformationChildren( $useComments, $php, $tpl, &$node, &$children, &$resourceData)
Definition: eztemplatecompiler.php:1024
eZTemplateCompiler\operatorHint
static operatorHint( $tpl, $operatorName)
Definition: eztemplatecompiler.php:1553
eZTemplateCompiler\generateVariableDataCode
static generateVariableDataCode( $php, $tpl, $variableData, &$knownTypes, $dataInspection, &$persistence, $parameters, &$resourceData)
Definition: eztemplatecompiler.php:2736
eZTemplateCompiler\hasCompiledTemplate
static hasCompiledTemplate( $key, $timestamp, &$resourceData)
Definition: eztemplatecompiler.php:352
eZTemplateCompiler\operatorStaticData
static operatorStaticData( $tpl, $operatorName)
Definition: eztemplatecompiler.php:1587
eZTemplateCompiler\isAccumulatorsEnabled
static isAccumulatorsEnabled()
Definition: eztemplatecompiler.php:164
eZTemplateCompiler\fetchTemplatePiece
static fetchTemplatePiece( $placementData)
Definition: eztemplatecompiler.php:1646
eZTemplateCompiler\processNodeTransformationRoot
static processNodeTransformationRoot( $useComments, $php, $tpl, &$node, &$resourceData)
Definition: eztemplatecompiler.php:1047
eZTemplateCompiler\generatePHPCode
static generatePHPCode( $useComments, $php, $tpl, &$node, &$resourceData)
Definition: eztemplatecompiler.php:1791
eZTemplateFailedExecutingCompiledTemplate
Definition: failedexecutingcompiledtemplate.php:17
eZTemplateNodeTool\elementConstantValue
static elementConstantValue( $elements)
Definition: eztemplatenodetool.php:197
eZTemplateNodeTool\isConstantElement
static isConstantElement( $elements)
Definition: eztemplatenodetool.php:233
eZTemplateOptimizer\optimize
static optimize( $useComments, &$php, $tpl, &$tree, &$resourceData)
Definition: eztemplateoptimizer.php:141
eZTemplateOptimizer\fetchClassDeclaration
static fetchClassDeclaration( $classID)
Definition: eztemplateoptimizer.php:192
eZTemplate\NODE_INTERNAL_WARNING
const NODE_INTERNAL_WARNING
Definition: eztemplate.php:226
eZTemplate\NODE_INTERNAL_VARIABLE_UNSET
const NODE_INTERNAL_VARIABLE_UNSET
Definition: eztemplate.php:221
eZTemplate\TYPE_OPERATOR
const TYPE_OPERATOR
Definition: eztemplate.php:252
eZTemplate\NODE_INTERNAL_RESOURCE_ACQUISITION
const NODE_INTERNAL_RESOURCE_ACQUISITION
Definition: eztemplate.php:229
eZTemplate\TYPE_DYNAMIC_ARRAY
const TYPE_DYNAMIC_ARRAY
Definition: eztemplate.php:255
eZTemplate\TYPE_VARIABLE
const TYPE_VARIABLE
Definition: eztemplate.php:250
eZTemplate\NODE_USER_CUSTOM
const NODE_USER_CUSTOM
Definition: eztemplate.php:243
eZTemplate\NODE_INTERNAL_SPACING_DECREASE
const NODE_INTERNAL_SPACING_DECREASE
Definition: eztemplate.php:238
eZTemplate\NODE_INTERNAL_CODE_PIECE
const NODE_INTERNAL_CODE_PIECE
Definition: eztemplate.php:218
eZTemplate\TYPE_OPTIMIZED_ARRAY_LOOKUP
const TYPE_OPTIMIZED_ARRAY_LOOKUP
Definition: eztemplate.php:262
eZTemplate\TYPE_INTERNAL_STOP
const TYPE_INTERNAL_STOP
Definition: eztemplate.php:266
eZTemplate\NODE_INTERNAL_OUTPUT_ASSIGN
const NODE_INTERNAL_OUTPUT_ASSIGN
Definition: eztemplate.php:232
eZTemplate\NODE_INTERNAL_VARIABLE_SET
const NODE_INTERNAL_VARIABLE_SET
Definition: eztemplate.php:220
eZTemplate\TYPE_OPTIMIZED_CONTENT_CALL
const TYPE_OPTIMIZED_CONTENT_CALL
Definition: eztemplate.php:263
eZTemplate\TYPE_PHP_VARIABLE
const TYPE_PHP_VARIABLE
Definition: eztemplate.php:259
eZTemplate\NODE_TEXT
const NODE_TEXT
Definition: eztemplate.php:211
eZTemplate\NODE_INTERNAL
const NODE_INTERNAL
Definition: eztemplate.php:217
eZTemplate\NODE_INTERNAL_NAMESPACE_CHANGE
const NODE_INTERNAL_NAMESPACE_CHANGE
Definition: eztemplate.php:223
eZTemplate\NODE_OPTIMIZED_RESOURCE_ACQUISITION
const NODE_OPTIMIZED_RESOURCE_ACQUISITION
Definition: eztemplate.php:230
eZTemplate\TYPE_ARRAY
const TYPE_ARRAY
Definition: eztemplate.php:254
eZTemplate\TYPE_BOOLEAN
const TYPE_BOOLEAN
Definition: eztemplate.php:253
eZTemplate\NODE_ROOT
const NODE_ROOT
Definition: eztemplate.php:210
eZTemplate\TYPE_INTERNAL
const TYPE_INTERNAL
Definition: eztemplate.php:257
eZTemplate\TYPE_OPTIMIZED_NODE
const TYPE_OPTIMIZED_NODE
Definition: eztemplate.php:261
eZTemplate\NODE_VARIABLE
const NODE_VARIABLE
Definition: eztemplate.php:212
eZTemplate\NODE_OPERATOR
const NODE_OPERATOR
Definition: eztemplate.php:214
eZTemplate\NODE_INTERNAL_OUTPUT_READ
const NODE_INTERNAL_OUTPUT_READ
Definition: eztemplate.php:233
eZTemplate\TYPE_ATTRIBUTE
const TYPE_ATTRIBUTE
Definition: eztemplate.php:251
eZTemplate\TYPE_VOID
const TYPE_VOID
Definition: eztemplate.php:246
eZTemplate\TYPE_IDENTIFIER
const TYPE_IDENTIFIER
Definition: eztemplate.php:249
eZTemplate\NODE_INTERNAL_ERROR
const NODE_INTERNAL_ERROR
Definition: eztemplate.php:227
eZTemplate\NODE_FUNCTION
const NODE_FUNCTION
Definition: eztemplate.php:213
eZTemplate\TYPE_NUMERIC
const TYPE_NUMERIC
Definition: eztemplate.php:248
eZTemplate\TYPE_STRING
const TYPE_STRING
Definition: eztemplate.php:247
eZTemplate\NODE_INTERNAL_OUTPUT_DECREASE
const NODE_INTERNAL_OUTPUT_DECREASE
Definition: eztemplate.php:235
eZTemplate\NODE_INTERNAL_OUTPUT_INCREASE
const NODE_INTERNAL_OUTPUT_INCREASE
Definition: eztemplate.php:234
eZTemplate\NODE_INTERNAL_OUTPUT_SPACING_INCREASE
const NODE_INTERNAL_OUTPUT_SPACING_INCREASE
Definition: eztemplate.php:237
eZTemplate\TYPE_OPTIMIZED_ATTRIBUTE_LOOKUP
const TYPE_OPTIMIZED_ATTRIBUTE_LOOKUP
Definition: eztemplate.php:264
eZTextCodec\internalCharset
static internalCharset()
Definition: eztextcodec.php:546
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.