]>
git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - config/nagiosql/pear/HTML/Template/ITX.php
3 * Integrated Template - IT
7 * Copyright (c) 1997-2007 Ulf Wendel, Pierre-Alain Joye,
10 * This source file is subject to the New BSD license, That is bundled
11 * with this package in the file LICENSE, and is available through
12 * the world-wide-web at
13 * http://www.opensource.org/licenses/bsd-license.php
14 * If you did not receive a copy of the new BSDlicense and are unable
15 * to obtain it through the world-wide-web, please send a note to
16 * pajoye@php.net so we can mail you a copy immediately.
18 * Author: Ulf Wendel <ulf.wendel@phpdoc.de>
19 * Pierre-Alain Joye <pajoye@php.net>
20 * David Soria Parra <dsp@php.net>
23 * @package HTML_Template_IT
24 * @author Ulf Wendel <uw@netuse.de>
25 * @license BSD http://www.opensource.org/licenses/bsd-license.php
26 * @version CVS: $Id: ITX.php,v 1.19 2008/11/14 23:57:17 kguest Exp $
27 * @link http://pear.php.net/packages/HTML_Template_IT
31 require_once 'HTML/Template/IT.php';
32 require_once 'HTML/Template/IT_Error.php';
35 * Integrated Template Extension - ITX
37 * With this class you get the full power of the phplib template class.
38 * You may have one file with blocks in it but you have as well one main file
39 * and multiple files one for each block. This is quite usefull when you have
40 * user configurable websites. Using blocks not in the main template allows
41 * you to modify some parts of your layout easily.
43 * Note that you can replace an existing block and add new blocks at runtime.
44 * Adding new blocks means changing a variable placeholder to a block.
47 * @package HTML_Template_IT
48 * @author Ulf Wendel <uw@netuse.de>
49 * @license BSD http://www.opensource.org/licenses/bsd-license.php
50 * @link http://pear.php.net/packages/HTML_Template_IT
53 class HTML_Template_ITX
extends HTML_Template_IT
56 * Array with all warnings.
59 * @see $printWarning, $haltOnWarning, warning()
67 * @see $haltOnWarning, $warn, warning()
69 var $printWarning = false;
72 * Call die() on warning?
75 * @see $warn, $printWarning, warning()
77 var $haltOnWarning = false;
80 * RegExp used to test for a valid blockname.
84 var $checkblocknameRegExp = '';
87 * Functionnameprefix used when searching function calls in the template.
91 var $functionPrefix = 'func_';
94 * Functionname RegExp.
98 var $functionnameRegExp = '[_a-zA-Z]+[A-Za-z_0-9]*';
101 * RegExp used to grep function calls in the template.
103 * The variable gets set by the constructor.
107 * @see HTML_Template_IT()
109 var $functionRegExp = '';
112 * List of functions found in the template.
117 var $functions = array();
120 * List of callback functions specified by the user.
125 var $callback = array();
128 * Builds some complex regexps and calls the constructor
129 * of the parent class.
131 * Make sure that you call this constructor if you derive your own
132 * template class from this one.
134 * @param string $root Root node?
137 * @see HTML_Template_IT()
139 function HTML_Template_ITX($root = '')
142 $this->checkblocknameRegExp
= '@' . $this->blocknameRegExp
. '@';
144 $this->functionRegExp
= '@' . $this->functionPrefix
. '(' .
145 $this->functionnameRegExp
. ')\s*\(@sm';
147 $this->HTML_Template_IT($root);
148 } // end func constructor
151 * Clears all datafields of the object and rebuild the internal blocklist
153 * LoadTemplatefile() and setTemplate() automatically call this function
154 * when a new template is given. Don't use this function
155 * unless you know what you're doing.
163 $this->buildFunctionlist();
164 $this->findBlocks($this->template
);
166 // we don't need it any more
167 $this->template
= '';
168 $this->buildBlockvariablelist();
173 * Replaces an existing block with new content.
175 * This function will replace a block of the template and all blocks
176 * contained in the replaced block and add a new block insted, means
177 * you can dynamically change your template.
179 * Note that changing the template structure violates one of the IT[X]
180 * development goals. I've tried to write a simple to use template engine
181 * supporting blocks. In contrast to other systems IT[X] analyses the way
182 * you've nested blocks and knows which block belongs into another block.
183 * The nesting information helps to make the API short and simple. Replacing
184 * blocks does not only mean that IT[X] has to update the nesting
185 * information (relatively time consumpting task) but you have to make sure
186 * that you do not get confused due to the template change itself.
188 * @param string $block Blockname
189 * @param string $template Blockcontent
190 * @param boolean $keep_content true if the new block inherits the content
195 * @see replaceBlockfile(), addBlock(), addBlockfile()
198 function replaceBlock($block, $template, $keep_content = false)
200 if (!isset($this->blocklist
[$block])) {
201 return new IT_Error("The block "."'$block'".
202 " does not exist in the template and thus it can't be replaced.",
206 if ($template == '') {
207 return new IT_Error('No block content given.', __FILE__
, __LINE__
);
211 $blockdata = $this->blockdata
[$block];
214 // remove all kinds of links to the block / data of the block
215 $this->removeBlockData($block);
217 $template = "<!-- BEGIN $block -->" . $template . "<!-- END $block -->";
218 $parents = $this->blockparents
[$block];
220 $this->findBlocks($template);
221 $this->blockparents
[$block] = $parents;
223 // KLUDGE: rebuild the list for all block - could be done faster
224 $this->buildBlockvariablelist();
227 $this->blockdata
[$block] = $blockdata;
230 // old TODO - I'm not sure if we need this
234 } // end func replaceBlock
237 * Replaces an existing block with new content from a file.
239 * @param string $block Blockname
240 * @param string $filename Name of the file that contains the blockcontent
241 * @param boolean $keep_content true if the new block inherits the content of
244 * @brother replaceBlock()
248 function replaceBlockfile($block, $filename, $keep_content = false)
250 return $this->replaceBlock($block, $this->getFile($filename), $keep_content);
251 } // end func replaceBlockfile
254 * Adds a block to the template changing a variable placeholder
255 * to a block placeholder.
257 * Add means "replace a variable placeholder by a new block".
258 * This is different to PHPLibs templates. The function loads a
259 * block, creates a handle for it and assigns it to a certain
260 * variable placeholder. To to the same with PHPLibs templates you would
261 * call set_file() to create the handle and parse() to assign the
262 * parsed block to a variable. By this PHPLibs templates assume
263 * that you tend to assign a block to more than one one placeholder.
264 * To assign a parsed block to more than only the placeholder you specify
265 * in this function you have to use a combination of getBlock()
268 * As no updates to cached data is necessary addBlock() and addBlockfile()
269 * are rather "cheap" meaning quick operations.
271 * The block content must not start with <!-- BEGIN blockname -->
272 * and end with <!-- END blockname --> this would cause overhead and
275 * @param string $placeholder Name of the variable placeholder, the name
276 * must be unique within the template.
277 * @param string $blockname Name of the block to be added
278 * @param string $template Content of the block
282 * @see addBlockfile()
285 function addBlock($placeholder, $blockname, $template)
287 // Don't trust any user even if it's a programmer or yourself...
288 if ($placeholder == '') {
289 return new IT_Error('No variable placeholder given.',
291 } elseif ($blockname == '' ||
292 !preg_match($this->checkblocknameRegExp
, $blockname)
294 return new IT_Error("No or invalid blockname '$blockname' given.",
296 } elseif ($template == '') {
297 return new IT_Error('No block content given.', __FILE__
, __LINE__
);
298 } elseif (isset($this->blocklist
[$blockname])) {
299 return new IT_Error('The block already exists.',
303 // find out where to insert the new block
304 $parents = $this->findPlaceholderBlocks($placeholder);
305 if (count($parents) == 0) {
307 return new IT_Error("The variable placeholder".
308 " '$placeholder' was not found in the template.",
311 } elseif (count($parents) > 1) {
314 while (list($k, $parent) = each($parents)) {
317 $msg = substr($parent, -2);
319 return new IT_Error("The variable placeholder "."'$placeholder'".
320 " must be unique, found in multiple blocks '$msg'.",
324 $template = "<!-- BEGIN $blockname -->"
326 . "<!-- END $blockname -->";
327 $this->findBlocks($template);
328 if ($this->flagBlocktrouble
) {
329 return false; // findBlocks() already throws an exception
332 $this->blockinner
[$parents[0]][] = $blockname;
334 $escblockname = '__' . $blockname . '__';
336 $this->blocklist
[$parents[0]] = preg_replace(
337 '@' . $this->openingDelimiter
. $placeholder .
338 $this->closingDelimiter
. '@',
339 $this->openingDelimiter
. $escblockname . $this->closingDelimiter
,
340 $this->blocklist
[$parents[0]]);
342 $this->deleteFromBlockvariablelist($parents[0], $placeholder);
343 $this->updateBlockvariablelist($blockname);
346 } // end func addBlock
349 * Adds a block taken from a file to the template changing a variable
350 * placeholder to a block placeholder.
352 * @param string $placeholder Name of the variable placeholder to be converted
353 * @param string $blockname Name of the block to be added
354 * @param string $filename File that contains the block
356 * @brother addBlock()
360 function addBlockfile($placeholder, $blockname, $filename)
362 return $this->addBlock($placeholder, $blockname, $this->getFile($filename));
363 } // end func addBlockfile
366 * Returns the name of the (first) block that contains
367 * the specified placeholder.
369 * @param string $placeholder Name of the placeholder you're searching
370 * @param string $block Name of the block to scan. If left out (default)
371 * all blocks are scanned.
373 * @return string Name of the (first) block that contains
374 * the specified placeholder.
375 * If the placeholder was not found or an error occured
376 * an empty string is returned.
380 function placeholderExists($placeholder, $block = '')
382 if ($placeholder == '') {
383 new IT_Error('No placeholder name given.', __FILE__
, __LINE__
);
387 if ($block != '' && !isset($this->blocklist
[$block])) {
388 new IT_Error("Unknown block '$block'.", __FILE__
, __LINE__
);
392 // name of the block where the given placeholder was found
396 if (is_array($variables = $this->blockvariables
[$block])) {
397 // search the value in the list of blockvariables
399 while (list($k, $variable) = each($variables)) {
400 if ($k == $placeholder) {
408 // search all blocks and return the name of the first block that
409 // contains the placeholder
410 reset($this->blockvariables
);
411 while (list($blockname, $variables) = each($this->blockvariables
)) {
412 if (is_array($variables) && isset($variables[$placeholder])) {
420 } // end func placeholderExists
423 * Checks the list of function calls in the template and
424 * calls their callback function.
429 function performCallback()
431 reset($this->functions
);
432 while (list($func_id, $function) = each($this->functions
)) {
433 if (isset($this->callback
[$function['name']])) {
434 if ($this->callback
[$function['name']]['expandParameters']) {
435 $callFunction = 'call_user_func_array';
437 $callFunction = 'call_user_func';
440 if ($this->callback
[$function['name']]['object'] != '') {
441 $call = $callFunction(
443 &$GLOBALS[$this->callback
[$function['name']]['object']],
444 $this->callback
[$function['name']]['function']),
448 $call = $callFunction(
449 $this->callback
[$function['name']]['function'],
452 $this->variableCache
['__function' . $func_id . '__'] = $call;
456 } // end func performCallback
459 * Returns a list of all function calls in the current template.
464 function getFunctioncalls()
466 return $this->functions
;
467 } // end func getFunctioncalls
470 * Replaces a function call with the given replacement.
472 * @param int $functionID Function ID
473 * @param string $replacement Replacement
479 function setFunctioncontent($functionID, $replacement)
481 $this->variableCache
['__function' . $functionID . '__'] = $replacement;
482 } // end func setFunctioncontent
485 * Sets a callback function.
487 * IT[X] templates (note the X) can contain simple function calls.
488 * "function call" means that the editor of the template can add
489 * special placeholder to the template like 'func_h1("embedded in h1")'.
490 * IT[X] will grab this function calls and allow you to define a callback
493 * This is an absolutely evil feature. If your application makes heavy
494 * use of such callbacks and you're even implementing if-then etc. on
495 * the level of a template engine you're reiventing the wheel... - that's
496 * actually how PHP came into life. Anyway, sometimes it's handy.
498 * Consider also using XML/XSLT or native PHP. And please do not push
499 * IT[X] any further into this direction of adding logics to the template
502 * For those of you ready for the X in IT[X]:
506 * function h_one($args) {
507 * return sprintf('<h1>%s</h1>', $args[0]);
511 * $itx = new HTML_Template_ITX(...);
513 * $itx->setCallbackFunction('h1', 'h_one');
514 * $itx->performCallback();
518 * func_h1('H1 Headline');
520 * @param string $tplfunction Function name in the template
521 * @param string $callbackfunction Name of the callback function
522 * @param string $callbackobject Name of the callback object
523 * @param boolean $expandCallbackParameters If the callback is called with
524 * a list of parameters or with an
525 * array holding the parameters
527 * @return boolean False on failure.
530 * @deprecated The $callbackobject parameter is depricated since
531 * version 1.2 and might be dropped in further versions.
533 function setCallbackFunction($tplfunction, $callbackfunction,
534 $callbackobject = '',
535 $expandCallbackParameters = false)
537 if ($tplfunction == '' ||
$callbackfunction == '') {
538 return new IT_Error("No template function "."('$tplfunction')".
539 " and/or no callback function ('$callback') given.",
542 $this->callback
[$tplfunction] = array(
543 'function' => $callbackfunction,
544 'object' => $callbackobject,
545 'expandParameters' => (boolean
)
546 $expandCallbackParameters);
549 } // end func setCallbackFunction
552 * Sets the Callback function lookup table
554 * @param array $functions function table
555 * array[templatefunction] =
557 * "function" => userfunction,
558 * "object" => userobject
564 function setCallbackFuntiontable($functions)
566 $this->callback
= $functions;
567 } // end func setCallbackFunctiontable
570 * Recursively removes all data assiciated with a block, including
573 * @param string $block block to be removed
578 function removeBlockData($block)
580 if (isset($this->blockinner
[$block])) {
581 foreach ($this->blockinner
[$block] as $k => $inner) {
582 $this->removeBlockData($inner);
585 unset($this->blockinner
[$block]);
588 unset($this->blocklist
[$block]);
589 unset($this->blockdata
[$block]);
590 unset($this->blockvariables
[$block]);
591 unset($this->touchedBlocks
[$block]);
593 } // end func removeBlockinner
596 * Returns a list of blocknames in the template.
598 * @return array [blockname => blockname]
602 function getBlocklist()
604 $blocklist = array();
605 foreach ($this->blocklist
as $block => $content) {
606 $blocklist[$block] = $block;
610 } // end func getBlocklist
613 * Checks wheter a block exists.
615 * @param string $blockname Blockname
619 * @see getBlocklist()
621 function blockExists($blockname)
623 return isset($this->blocklist
[$blockname]);
624 } // end func blockExists
627 * Returns a list of variables of a block.
629 * @param string $block Blockname
631 * @return array [varname => varname]
633 * @see BlockvariableExists()
635 function getBlockvariables($block)
637 if (!isset($this->blockvariables
[$block])) {
641 $variables = array();
642 foreach ($this->blockvariables
[$block] as $variable => $v) {
643 $variables[$variable] = $variable;
647 } // end func getBlockvariables
650 * Checks wheter a block variable exists.
652 * @param string $block Blockname
653 * @param string $variable Variablename
657 * @see getBlockvariables()
659 function BlockvariableExists($block, $variable)
661 return isset($this->blockvariables
[$block][$variable]);
662 } // end func BlockvariableExists
665 * Builds a functionlist from the template.
670 function buildFunctionlist()
672 $this->functions
= array();
674 $template = $this->template
;
678 while (preg_match($this->functionRegExp
, $template, $regs)) {
680 $pos = strpos($template, $regs[0]);
682 $template = substr($template, $pos +
strlen($regs[0]));
684 $head = $this->getValue($template, ')');
687 $search = $regs[0] . $head . ')';
689 $replace = $this->openingDelimiter
.
690 '__function' . $num . '__' .
691 $this->closingDelimiter
;
693 $this->template
= str_replace($search, $replace, $this->template
);
694 $template = str_replace($search, $replace, $template);
696 while ($head != '' && $args2 = $this->getValue($head, ',')) {
697 $arg2 = trim($args2);
699 $args[] = ('"' == $arg2{0} ||
"'" == $arg2{0}) ?
700 substr($arg2, 1, -1) : $arg2;
702 if ($arg2 == $head) {
705 $head = substr($head, strlen($arg2) +
1);
708 $this->functions
[$num++
] = array('name' => $regs[1],
712 } // end func buildFunctionlist
715 * Truncates the given code from the first occurence of
716 * $delimiter but ignores $delimiter enclosed by " or '.
718 * @param string $code The code which should be parsed
719 * @param string $delimiter The delimiter char
723 * @see buildFunctionList()
725 function getValue($code, $delimiter)
731 if (!is_array($delimiter)) {
732 $delimiter = array($delimiter => true);
735 $len = strlen($code);
739 if (isset($delimiter[$code[0]])) {
742 for ($i = 0; $i < $len; ++
$i) {
745 if (($char == '"' ||
$char == "'") &&
746 ($char == $enclosed_by ||
'' == $enclosed_by) &&
747 (0 == $i ||
($i > 0 && '\\' != $code[$i - 1]))) {
750 $enclosed_by = $char;
754 $enclosed = !$enclosed;
758 if (!$enclosed && isset($delimiter[$char])) {
764 return substr($code, 0, $i);
765 } // end func getValue
768 * Deletes one or many variables from the block variable list.
770 * @param string $block Blockname
771 * @param mixed $variables Name of one variable or array of variables
772 * (array (name => true ) ) to be stripped.
777 function deleteFromBlockvariablelist($block, $variables)
779 if (!is_array($variables)) {
780 $variables = array($variables => true);
783 reset($this->blockvariables
[$block]);
784 while (list($varname, $val) = each($this->blockvariables
[$block])) {
785 if (isset($variables[$varname])) {
786 unset($this->blockvariables
[$block][$varname]);
789 } // end deleteFromBlockvariablelist
792 * Updates the variable list of a block.
794 * @param string $block Blockname
799 function updateBlockvariablelist($block)
801 preg_match_all($this->variablesRegExp
,
802 $this->blocklist
[$block], $regs);
804 if (count($regs[1]) != 0) {
805 foreach ($regs[1] as $k => $var) {
806 $this->blockvariables
[$block][$var] = true;
809 $this->blockvariables
[$block] = array();
812 // check if any inner blocks were found
813 if (isset($this->blockinner
[$block]) &&
814 is_array($this->blockinner
[$block]) &&
815 count($this->blockinner
[$block]) > 0) {
817 * loop through inner blocks, registering the variable
818 * placeholders in each
820 foreach ($this->blockinner
[$block] as $childBlock) {
821 $this->updateBlockvariablelist($childBlock);
824 } // end func updateBlockvariablelist
827 * Returns an array of blocknames where the given variable
828 * placeholder is used.
830 * @param string $variable Variable placeholder
832 * @return array $parents parents[0..n] = blockname
835 function findPlaceholderBlocks($variable)
838 reset($this->blocklist
);
839 while (list($blockname, $content) = each($this->blocklist
)) {
840 reset($this->blockvariables
[$blockname]);
842 while (list($varname, $val) = each($this->blockvariables
[$blockname])) {
843 if ($variable == $varname) {
844 $parents[] = $blockname;
850 } // end func findPlaceholderBlocks
853 * Handles warnings, saves them to $warn and prints them or
854 * calls die() depending on the flags
856 * @param string $message Warning
857 * @param string $file File where the warning occured
858 * @param int $line Linenumber where the warning occured
860 * @see $warn, $printWarning, $haltOnWarning
864 function warning($message, $file = '', $line = 0)
866 $message = sprintf('HTML_Template_ITX Warning: %s [File: %s, Line: %d]',
871 $this->warn
[] = $message;
873 if ($this->printWarning
) {
877 if ($this->haltOnWarning
) {
880 } // end func warning
882 } // end class HTML_Template_ITX