ILIAS  Release_4_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
ITX.php
Go to the documentation of this file.
1 <?php
2 //
3 // +----------------------------------------------------------------------+
4 // | Copyright (c) 1997-2005 Ulf Wendel, Pierre-Alain Joye |
5 // +----------------------------------------------------------------------+
6 // | This source file is subject to the New BSD license, That is bundled |
7 // | with this package in the file LICENSE, and is available through |
8 // | the world-wide-web at |
9 // | http://www.opensource.org/licenses/bsd-license.php |
10 // | If you did not receive a copy of the new BSD license and are unable |
11 // | to obtain it through the world-wide-web, please send a note to |
12 // | pajoye@php.net so we can mail you a copy immediately. |
13 // +----------------------------------------------------------------------+
14 // | Author: Ulf Wendel <ulf.wendel@phpdoc.de> |
15 // | Pierre-Alain Joye <pajoye@php.net> |
16 // +----------------------------------------------------------------------+
17 //
18 // $Id: ITX.php,v 1.16 2006/08/17 15:47:22 dsp Exp $
19 //
20 
21 require_once 'HTML/Template/IT.php';
22 require_once 'HTML/Template/IT_Error.php';
23 
42 {
49  var $warn = array();
50 
57  var $printWarning = false;
58 
65  var $haltOnWarning = false;
66 
72 
77  var $functionPrefix = 'func_';
78 
83  var $functionnameRegExp = '[_a-zA-Z]+[A-Za-z_0-9]*';
84 
93  var $functionRegExp = '';
94 
100  var $functions = array();
101 
107  var $callback = array();
108 
118  function HTML_Template_ITX($root = '')
119  {
120 
121  $this->checkblocknameRegExp = '@' . $this->blocknameRegExp . '@';
122  $this->functionRegExp = '@' . $this->functionPrefix . '(' .
123  $this->functionnameRegExp . ')\s*\(@sm';
124 
125  $this->HTML_Template_IT($root);
126  } // end func constructor
127 
128  function init()
129  {
130  $this->free();
131  $this->buildFunctionlist();
132  $this->findBlocks($this->template);
133  // we don't need it any more
134  $this->template = '';
135  $this->buildBlockvariablelist();
136 
137  } // end func init
138 
164  function replaceBlock($block, $template, $keep_content = false)
165  {
166  if (!isset($this->blocklist[$block])) {
167  return new IT_Error(
168  "The block "."'$block'".
169  " does not exist in the template and thus it can't be replaced.",
170  __FILE__, __LINE__
171  );
172  }
173 
174  if ($template == '') {
175  return new IT_Error('No block content given.', __FILE__, __LINE__);
176  }
177 
178  if ($keep_content) {
179  $blockdata = $this->blockdata[$block];
180  }
181 
182  // remove all kinds of links to the block / data of the block
183  $this->removeBlockData($block);
184 
185  $template = "<!-- BEGIN $block -->" . $template . "<!-- END $block -->";
186  $parents = $this->blockparents[$block];
187  $this->findBlocks($template);
188  $this->blockparents[$block] = $parents;
189 
190  // KLUDGE: rebuild the list for all block - could be done faster
191  $this->buildBlockvariablelist();
192 
193  if ($keep_content) {
194  $this->blockdata[$block] = $blockdata;
195  }
196 
197  // old TODO - I'm not sure if we need this
198  // update caches
199 
200  return true;
201  } // end func replaceBlock
202 
212  function replaceBlockfile($block, $filename, $keep_content = false)
213  {
214  return $this->replaceBlock($block, $this->getFile($filename), $keep_content);
215  } // end func replaceBlockfile
216 
248  function addBlock($placeholder, $blockname, $template)
249  {
250  // Don't trust any user even if it's a programmer or yourself...
251  if ($placeholder == '') {
252  return new IT_Error('No variable placeholder given.',
253  __FILE__, __LINE__
254  );
255  } elseif ($blockname == '' ||
256  !preg_match($this->checkblocknameRegExp, $blockname)
257  ) {
258  return new IT_Error("No or invalid blockname '$blockname' given.",
259  __FILE__, __LINE__
260  );
261  } elseif ($template == '') {
262  return new IT_Error('No block content given.', __FILE__, __LINE__);
263  } elseif (isset($this->blocklist[$blockname])) {
264  return new IT_Error('The block already exists.',
265  __FILE__, __LINE__
266  );
267  }
268 
269  // find out where to insert the new block
270  $parents = $this->findPlaceholderBlocks($placeholder);
271  if (count($parents) == 0) {
272 
273  return new IT_Error(
274  "The variable placeholder".
275  " '$placeholder' was not found in the template.",
276  __FILE__, __LINE__
277  );
278 
279  } elseif (count($parents) > 1) {
280 
281  reset($parents);
282  while (list($k, $parent) = each($parents)) {
283  $msg .= "$parent, ";
284  }
285  $msg = substr($parent, -2);
286 
287  return new IT_Error("The variable placeholder "."'$placeholder'".
288  " must be unique, found in multiple blocks '$msg'.",
289  __FILE__, __LINE__
290  );
291  }
292 
293  $template = "<!-- BEGIN $blockname -->" . $template . "<!-- END $blockname -->";
294  $this->findBlocks($template);
295  if ($this->flagBlocktrouble) {
296  return false; // findBlocks() already throws an exception
297  }
298  $this->blockinner[$parents[0]][] = $blockname;
299  $this->blocklist[$parents[0]] = preg_replace(
300  '@' . $this->openingDelimiter . $placeholder .
301  $this->closingDelimiter . '@',
302 
303  $this->openingDelimiter . '__' . $blockname . '__' .
304  $this->closingDelimiter,
305 
306  $this->blocklist[$parents[0]]
307  );
308 
309  $this->deleteFromBlockvariablelist($parents[0], $placeholder);
310  $this->updateBlockvariablelist($blockname);
311 
312  return true;
313  } // end func addBlock
314 
325  function addBlockfile($placeholder, $blockname, $filename)
326  {
327  return $this->addBlock($placeholder, $blockname, $this->getFile($filename));
328  } // end func addBlockfile
329 
344  function placeholderExists($placeholder, $block = '')
345  {
346  if ($placeholder == '') {
347  new IT_Error('No placeholder name given.', __FILE__, __LINE__);
348  return '';
349  }
350 
351  if ($block != '' && !isset($this->blocklist[$block])) {
352  new IT_Error("Unknown block '$block'.", __FILE__, __LINE__);
353  return '';
354  }
355 
356  // name of the block where the given placeholder was found
357  $found = '';
358 
359  if ($block != '') {
360  if (is_array($variables = $this->blockvariables[$block])) {
361  // search the value in the list of blockvariables
362  reset($variables);
363  while (list($k, $variable) = each($variables)) {
364  if ($k == $placeholder) {
365  $found = $block;
366  break;
367  }
368  }
369  }
370  } else {
371 
372  // search all blocks and return the name of the first block that
373  // contains the placeholder
374  reset($this->blockvariables);
375  while (list($blockname, $variables) = each($this->blockvariables)){
376  if (is_array($variables) && isset($variables[$placeholder])) {
377  $found = $blockname;
378  break;
379  }
380  }
381  }
382 
383  return $found;
384  } // end func placeholderExists
385 
392  function performCallback()
393  {
394  reset($this->functions);
395  while (list($func_id, $function) = each($this->functions)) {
396  if (isset($this->callback[$function['name']])) {
397  if ($this->callback[$function['name']]['expandParameters']) {
398  $callFunction = 'call_user_func_array';
399  } else {
400  $callFunction = 'call_user_func';
401  }
402 
403  if ($this->callback[$function['name']]['object'] != '') {
404  $call =
405  $callFunction(
406  array(
407  &$GLOBALS[$this->callback[$function['name']]['object']],
408  $this->callback[$function['name']]['function']),
409  $function['args']
410  );
411 
412  } else {
413  $call =
414  $callFunction(
415  $this->callback[$function['name']]['function'],
416  $function['args']
417  );
418  }
419  $this->variableCache['__function' . $func_id . '__'] = $call;
420  }
421  }
422 
423  } // end func performCallback
424 
431  function getFunctioncalls()
432  {
433  return $this->functions;
434  } // end func getFunctioncalls
435 
443  function setFunctioncontent($functionID, $replacement)
444  {
445  $this->variableCache['__function' . $functionID . '__'] = $replacement;
446  } // end func setFunctioncontent
447 
495  function
496  setCallbackFunction($tplfunction, $callbackfunction, $callbackobject = '', $expandCallbackParameters=false)
497  {
498  if ($tplfunction == '' || $callbackfunction == '') {
499  return new IT_Error(
500  "No template function "."('$tplfunction')".
501  " and/or no callback function ('$callback') given.",
502  __FILE__, __LINE__
503  );
504  }
505  $this->callback[$tplfunction] = array(
506  'function' => $callbackfunction,
507  'object' => $callbackobject,
508  'expandParameters' => (boolean) $expandCallbackParameters
509  );
510 
511  return true;
512  } // end func setCallbackFunction
513 
526  {
527  $this->callback = $functions;
528  } // end func setCallbackFunctiontable
529 
536  function removeBlockData($block)
537  {
538  if (isset($this->blockinner[$block])) {
539  foreach ($this->blockinner[$block] as $k => $inner) {
540  $this->removeBlockData($inner);
541  }
542 
543  unset($this->blockinner[$block]);
544  }
545 
546  unset($this->blocklist[$block]);
547  unset($this->blockdata[$block]);
548  unset($this->blockvariables[$block]);
549  unset($this->touchedBlocks[$block]);
550 
551  } // end func removeBlockinner
552 
560  function getBlocklist()
561  {
562  $blocklist = array();
563  foreach ($this->blocklist as $block => $content) {
564  $blocklist[$block] = $block;
565  }
566 
567  return $blocklist;
568  } // end func getBlocklist
569 
578  function blockExists($blockname)
579  {
580  return isset($this->blocklist[$blockname]);
581  } // end func blockExists
582 
591  function getBlockvariables($block)
592  {
593  if (!isset($this->blockvariables[$block])) {
594  return array();
595  }
596 
597  $variables = array();
598  foreach ($this->blockvariables[$block] as $variable => $v) {
599  $variables[$variable] = $variable;
600  }
601 
602  return $variables;
603  } // end func getBlockvariables
604 
614  function BlockvariableExists($block, $variable)
615  {
616  return isset($this->blockvariables[$block][$variable]);
617  } // end func BlockvariableExists
618 
623  function buildFunctionlist()
624  {
625  $this->functions = array();
626 
628  $num = 0;
629 
630  while (preg_match($this->functionRegExp, $template, $regs)) {
631 
632  $pos = strpos($template, $regs[0]);
633  $template = substr($template, $pos + strlen($regs[0]));
634 
635  $head = $this->getValue($template, ')');
636  $args = array();
637 
638  $search = $regs[0] . $head . ')';
639 
640  $replace = $this->openingDelimiter .
641  '__function' . $num . '__' .
643 
644  $this->template = str_replace($search, $replace, $this->template);
645  $template = str_replace($search, $replace, $template);
646 
647  while ($head != '' && $args2 = $this->getValue($head, ',')) {
648  $arg2 = trim($args2);
649  $args[] = ('"' == $arg2{0} || "'" == $arg2{0}) ?
650  substr($arg2, 1, -1) : $arg2;
651  if ($arg2 == $head) {
652  break;
653  }
654  $head = substr($head, strlen($arg2) + 1);
655  }
656 
657  $this->functions[$num++] = array(
658  'name' => $regs[1],
659  'args' => $args
660  );
661  }
662 
663  } // end func buildFunctionlist
664 
675  function getValue($code, $delimiter) {
676  if ($code == '') {
677  return '';
678  }
679 
680  if (!is_array($delimiter)) {
681  $delimiter = array( $delimiter => true );
682  }
683 
684  $len = strlen($code);
685  $enclosed = false;
686  $enclosed_by = '';
687 
688  if (isset($delimiter[$code[0]])) {
689  $i = 1;
690  } else {
691  for ($i = 0; $i < $len; ++$i) {
692  $char = $code[$i];
693 
694  if (
695  ($char == '"' || $char == "'") &&
696  ($char == $enclosed_by || '' == $enclosed_by) &&
697  (0 == $i || ($i > 0 && '\\' != $code[$i - 1]))
698  ) {
699 
700  if (!$enclosed) {
701  $enclosed_by = $char;
702  } else {
703  $enclosed_by = "";
704  }
705  $enclosed = !$enclosed;
706 
707  }
708 
709  if (!$enclosed && isset($delimiter[$char])) {
710  break;
711  }
712  }
713  }
714 
715  return substr($code, 0, $i);
716  } // end func getValue
717 
726  function deleteFromBlockvariablelist($block, $variables)
727  {
728  if (!is_array($variables)) {
729  $variables = array($variables => true);
730  }
731 
732  reset($this->blockvariables[$block]);
733  while (list($varname, $val) = each($this->blockvariables[$block])) {
734  if (isset($variables[$varname])) {
735  unset($this->blockvariables[$block][$varname]);
736  }
737  }
738  } // end deleteFromBlockvariablelist
739 
746  function updateBlockvariablelist($block)
747  {
748  preg_match_all( $this->variablesRegExp,
749  $this->blocklist[$block], $regs
750  );
751 
752  if (count($regs[1]) != 0) {
753  foreach ($regs[1] as $k => $var) {
754  $this->blockvariables[$block][$var] = true;
755  }
756  } else {
757  $this->blockvariables[$block] = array();
758  }
759 
760  // check if any inner blocks were found
761  if (isset($this->blockinner[$block]) &&
762  is_array($this->blockinner[$block]) &&
763  count($this->blockinner[$block]) > 0
764  ) {
765  /*
766  * loop through inner blocks, registering the variable
767  * placeholders in each
768  */
769  foreach ($this->blockinner[$block] as $childBlock) {
770  $this->updateBlockvariablelist($childBlock);
771  }
772  }
773  } // end func updateBlockvariablelist
774 
783  function findPlaceholderBlocks($variable)
784  {
785  $parents = array();
786  reset($this->blocklist);
787  while (list($blockname, $content) = each($this->blocklist)) {
788  reset($this->blockvariables[$blockname]);
789  while (
790  list($varname, $val) = each($this->blockvariables[$blockname]))
791  {
792  if ($variable == $varname) {
793  $parents[] = $blockname;
794  }
795  }
796  }
797 
798  return $parents;
799  } // end func findPlaceholderBlocks
800 
811  function warning($message, $file = '', $line = 0)
812  {
813  $message = sprintf(
814  'HTML_Template_ITX Warning: %s [File: %s, Line: %d]',
815  $message,
816  $file,
817  $line
818  );
819 
820  $this->warn[] = $message;
821 
822  if ($this->printWarning) {
823  print $message;
824  }
825 
826  if ($this->haltOnWarning) {
827  die($message);
828  }
829  } // end func warning
830 
831 } // end class HTML_Template_ITX
832 ?>