PageRenderTime 56ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/includes/patTemplate/patTemplate.php

https://bitbucket.org/dgough/annamaria-daneswood-25102012
PHP | 2705 lines | 1426 code | 292 blank | 987 comment | 275 complexity | ebc942aece73ba3dea10a23e77542987 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. <?PHP
  2. /**
  3. * patTemplate
  4. *
  5. * $Id: patTemplate.php 1544 2005-12-23 07:01:01Z eddieajau $
  6. *
  7. * powerful templating engine
  8. *
  9. * @version 3.1.0
  10. * @package patTemplate
  11. * @author Stephan Schmidt <schst@php.net>
  12. * @license LGPL
  13. * @link http://www.php-tools.net
  14. */
  15. // ** Following line Joomla! specific **
  16. require_once( dirname( __FILE__ ) . '/patErrorManager.php' );
  17. /**
  18. * template already exists
  19. */
  20. define( 'PATTEMPLATE_ERROR_TEMPLATE_EXISTS', 5010 );
  21. /**
  22. * template does not exist
  23. */
  24. define ( 'PATTEMPLATE_WARNING_NO_TEMPLATE', 5011 );
  25. /**
  26. * unknown type
  27. */
  28. define ( 'PATTEMPLATE_WARNING_UNKNOWN_TYPE', 5012 );
  29. /**
  30. * base class for module could not be found
  31. */
  32. define( 'PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND', 5050 );
  33. /**
  34. * module could not be found
  35. */
  36. define( 'PATTEMPLATE_ERROR_MODULE_NOT_FOUND', 5051 );
  37. /**
  38. * array expected
  39. */
  40. define( 'PATTEMPLATE_ERROR_EXPECTED_ARRAY', 5052 );
  41. /**
  42. * No input
  43. */
  44. define( 'PATTEMPLATE_ERROR_NO_INPUT', 6000 );
  45. /**
  46. * Recursion
  47. */
  48. define( 'PATTEMPLATE_ERROR_RECURSION', 6010 );
  49. /**
  50. * patTemplate
  51. *
  52. * powerful templating engine
  53. *
  54. * @version 3.1.0
  55. * @package patTemplate
  56. * @author Stephan Schmidt <schst@php.net>
  57. * @license LGPL
  58. * @link http://www.php-tools.net
  59. */
  60. class patTemplate
  61. {
  62. /**
  63. * standard system vars that identify pat tools
  64. * @var array
  65. */
  66. var $_systemVars = array(
  67. 'appName' => 'patTemplate',
  68. 'appVersion' => '3.1.0',
  69. 'author' => array(
  70. 'Stephan Schmidt <schst@php.net>'
  71. )
  72. );
  73. /**
  74. * default attributes for new templates
  75. * @access private
  76. * @var array
  77. */
  78. var $_defaultAttributes = array(
  79. 'type' => 'standard',
  80. 'visibility' => 'visible',
  81. 'loop' => 1,
  82. 'unusedvars' => 'strip',
  83. 'whitespace' => 'keep',
  84. 'autoclear' => 'off',
  85. 'autoload' => 'on'
  86. );
  87. /**
  88. * options for patTemplate
  89. *
  90. * Currently the following options are implemented:
  91. * - maintainBc defines, whether patTemplate should be backwards compatible.
  92. * This means, that you may use 'default' and 'empty' for subtemplates.
  93. *
  94. * @access private
  95. * @var array
  96. */
  97. var $_options = array(
  98. 'startTag' => '{',
  99. 'endTag' => '}',
  100. 'root' => array('__default' => '.'),
  101. 'namespace' => 'patTemplate',
  102. 'maintainBc' => true,
  103. 'defaultFunction' => false
  104. );
  105. /**
  106. * start tag
  107. *
  108. * @access private
  109. * @var string
  110. */
  111. var $_startTag = '{';
  112. /**
  113. * end tag
  114. *
  115. * @access private
  116. * @var string
  117. */
  118. var $_endTag = '}';
  119. /**
  120. * loaded modules
  121. *
  122. * Modules are:
  123. * - Readers
  124. * - Caches
  125. * - Variable modifiers
  126. * - Filters
  127. *
  128. * @access private
  129. * @var array
  130. */
  131. var $_modules = array();
  132. /**
  133. * directories, where modules can be stored
  134. * @access private
  135. * @var array
  136. */
  137. var $_moduleDirs = array();
  138. /**
  139. * stores all template names
  140. * @access private
  141. * @var array
  142. */
  143. var $_templateList = array();
  144. /**
  145. * stores all template data
  146. * @access private
  147. * @var array
  148. */
  149. var $_templates = array();
  150. /**
  151. * stores all global variables
  152. * @access private
  153. * @var array
  154. */
  155. var $_globals = array();
  156. /**
  157. * stores all local variables
  158. * @access private
  159. * @var array
  160. */
  161. var $_vars = array();
  162. /**
  163. * stores the name of the first template that has been
  164. * found
  165. *
  166. * @access private
  167. * @var string
  168. */
  169. var $_root;
  170. /**
  171. * output filters that should be used
  172. *
  173. * @access private
  174. * @var array
  175. */
  176. var $_outputFilters = array();
  177. /**
  178. * input filters that should be used
  179. *
  180. * @access private
  181. * @var array
  182. */
  183. var $_inputFilters = array();
  184. /**
  185. * template cache, that should be used
  186. *
  187. * @access private
  188. * @var array
  189. */
  190. var $_tmplCache = null;
  191. /**
  192. * placeholders, that have been discovered
  193. *
  194. * @access private
  195. * @var array
  196. */
  197. var $_discoveredPlaceholders = array();
  198. /**
  199. * Create a new patTemplate instance.
  200. *
  201. * The constructor accepts the type of the templates as sole parameter.
  202. * You may choose one of:
  203. * - html (default)
  204. * - tex
  205. *
  206. * The type influences the tags you are using in your templates.
  207. *
  208. * @access public
  209. * @param string type (either html or tex)
  210. */
  211. function patTemplate( $type = 'html' )
  212. {
  213. if( !defined( 'PATTEMPLATE_INCLUDE_PATH' ) ) {
  214. define( 'PATTEMPLATE_INCLUDE_PATH', dirname( __FILE__ ) . '/patTemplate' );
  215. }
  216. $this->setType( $type );
  217. }
  218. /**
  219. * sets an option
  220. *
  221. * Currently, the following options are supported
  222. * - maintainBc (true|false)
  223. * - namespace (string)
  224. *
  225. * @access public
  226. * @param string option to set
  227. * @param string value of the option
  228. */
  229. function setOption($option, $value)
  230. {
  231. $this->_options[$option] = $value;
  232. }
  233. /**
  234. * gets an option
  235. *
  236. * @access public
  237. * @param string option to get
  238. * @return mixed value of the option
  239. */
  240. function getOption( $option )
  241. {
  242. if (!isset($this->_options[$option])) {
  243. return null;
  244. }
  245. return $this->_options[$option];
  246. }
  247. /**
  248. * sets name of directory where templates are stored
  249. *
  250. * @access public
  251. * @param string dir where templates are stored
  252. * @deprecated please use patTemplate::setRoot() instead
  253. */
  254. function setBasedir($basedir)
  255. {
  256. $this->setRoot($basedir);
  257. }
  258. /**
  259. * sets root base for the template
  260. *
  261. * The parameter depends on the reader you are using.
  262. *
  263. * @access public
  264. * @param string root base of the templates
  265. */
  266. function setRoot($root, $reader = '__default')
  267. {
  268. $this->_options['root'][$reader] = $root;
  269. }
  270. /**
  271. * gets name of root base for the templates
  272. *
  273. * @access public
  274. * @return mixed root base
  275. */
  276. function getRoot($reader = '__default')
  277. {
  278. return $this->_options['root'][$reader];
  279. }
  280. /**
  281. * sets namespace of patTemplate tags
  282. *
  283. * If you want to use more than one namespace, you may set this to
  284. * an array. All tags in these namespaces will be treated as patTemplate
  285. * tags.
  286. *
  287. * @access public
  288. * @param string|array namespace(s)
  289. */
  290. function setNamespace($ns)
  291. {
  292. $this->_options['namespace'] = $ns;
  293. }
  294. /**
  295. * gets namespace of patTemplate tags
  296. *
  297. * @access public
  298. * @return string|array namespace(s)
  299. */
  300. function getNamespace()
  301. {
  302. return $this->_options['namespace'];
  303. }
  304. /**
  305. * set default attribute
  306. *
  307. * @access public
  308. * @param string attribute name
  309. * @param mixed attribute value
  310. */
  311. function setDefaultAttribute( $name, $value )
  312. {
  313. $this->_defaultAttributes[$name] = $value;
  314. }
  315. /**
  316. * set default attributes
  317. *
  318. * @access public
  319. * @param array attributes
  320. */
  321. function setDefaultAttributes( $attributes )
  322. {
  323. $this->_defaultAttributes = array_merge( $this->_defaultAttributes, $attributes );
  324. }
  325. /**
  326. * get default attributes
  327. *
  328. * @access public
  329. * @return return default attributes
  330. */
  331. function getDefaultAttributes()
  332. {
  333. return $this->_defaultAttributes;
  334. }
  335. /**
  336. * set the type for the templates
  337. *
  338. * @access public
  339. * @param string type (html or tex)
  340. * @return boolean true on success
  341. */
  342. function setType( $type )
  343. {
  344. switch( strtolower( $type ) )
  345. {
  346. case "tex":
  347. $this->setTags( '<{', '}>' );
  348. break;
  349. case "html":
  350. $this->setTags( '{', '}' );
  351. break;
  352. default:
  353. return patErrorManager::raiseWarning(
  354. PATTEMPLATE_WARNING_UNKNOWN_TYPE,
  355. "Unknown type '$type'. Please use 'html' or 'tex'."
  356. );
  357. }
  358. return true;
  359. }
  360. /**
  361. * set the start and end tag for variables
  362. *
  363. * @access public
  364. * @param string start tag
  365. * @param string end tag
  366. * @return boolean true on success
  367. */
  368. function setTags( $startTag, $endTag )
  369. {
  370. $this->_options['startTag'] = $startTag;
  371. $this->_options['endTag'] = $endTag;
  372. $this->_startTag = $startTag;
  373. $this->_endTag = $endTag;
  374. return true;
  375. }
  376. /**
  377. * get start tag for variables
  378. *
  379. * @access public
  380. * @return string start tag
  381. */
  382. function getStartTag()
  383. {
  384. return $this->_options['startTag'];
  385. }
  386. /**
  387. * get end tag for variables
  388. *
  389. * @access public
  390. * @return string end tag
  391. */
  392. function getEndTag()
  393. {
  394. return $this->_options['endTag'];
  395. }
  396. /**
  397. * add a directory where patTemplate should search for
  398. * modules.
  399. *
  400. * You may either pass a string or an array of directories.
  401. *
  402. * patTemplate will be searching for a module in the same
  403. * order you added them. If the module cannot be found in
  404. * the custom folders, it will look in
  405. * patTemplate/$moduleType.
  406. *
  407. * @access public
  408. * @param string module type
  409. * @param string|array directory or directories to search.
  410. */
  411. function addModuleDir( $moduleType, $dir )
  412. {
  413. if( !isset( $this->_moduleDirs[$moduleType] ) )
  414. $this->_moduleDirs[$moduleType] = array();
  415. if( is_array( $dir ) )
  416. $this->_moduleDirs[$moduleType] = array_merge( $this->_moduleDirs[$moduleType], $dir );
  417. else
  418. array_push( $this->_moduleDirs[$moduleType], $dir );
  419. }
  420. /**
  421. * Sets an attribute of a template
  422. *
  423. * supported attributes: visibilty, loop, parse, unusedvars
  424. *
  425. * @param string $template name of the template
  426. * @param string $attribute name of the attribute
  427. * @param mixed $value value of the attribute
  428. * @access public
  429. * @see setAttributes(),getAttribute(), clearAttribute()
  430. */
  431. function setAttribute( $template, $attribute, $value )
  432. {
  433. $template = strtolower( $template );
  434. if( !isset( $this->_templates[$template] ) )
  435. {
  436. return patErrorManager::raiseWarning(
  437. PATTEMPLATE_WARNING_NO_TEMPLATE,
  438. "Template '$template' does not exist."
  439. );
  440. }
  441. $attribute = strtolower( $attribute );
  442. $this->_templates[$template]['attributes'][$attribute] = $value;
  443. return true;
  444. }
  445. /**
  446. * Sets several attribute of a template
  447. *
  448. * $attributes has to be a assotiative arrays containing attribute/value pairs
  449. * supported attributes: visibilty, loop, parse, unusedvars
  450. *
  451. * @param string $template name of the template
  452. * @param array $attributes attribute/value pairs
  453. * @access public
  454. * @see setAttribute(), getAttribute(), clearAttribute()
  455. */
  456. function setAttributes( $template, $attributes )
  457. {
  458. if( !is_array( $attributes ) )
  459. {
  460. return patErrorManager::raiseError( PATTEMPLATE_ERROR_EXPECTED_ARRAY, 'patTemplate::setAttributes: Expected array as second parameter, '.gettype( $attributes ).' given' );
  461. }
  462. $template = strtolower( $template );
  463. $attributes = array_change_key_case( $attributes );
  464. if( !isset( $this->_templates[$template] ) )
  465. {
  466. return patErrorManager::raiseWarning(
  467. PATTEMPLATE_WARNING_NO_TEMPLATE,
  468. "Template '$template' does not exist."
  469. );
  470. }
  471. $this->_templates[$template]['attributes'] = array_merge( $this->_templates[$template]['attributes'], $attributes );
  472. return true;
  473. }
  474. /**
  475. * Get all attributes of a template
  476. *
  477. * @param string name of the template
  478. * @return array attributes
  479. * @access public
  480. */
  481. function getAttributes( $template )
  482. {
  483. $template = strtolower( $template );
  484. if( !isset( $this->_templates[$template] ) )
  485. {
  486. return patErrorManager::raiseWarning(
  487. PATTEMPLATE_WARNING_NO_TEMPLATE,
  488. "Template '$template' does not exist."
  489. );
  490. }
  491. return $this->_templates[$template]['attributes'];
  492. }
  493. /**
  494. * Gets an attribute of a template
  495. *
  496. * supported attributes: visibilty, loop, parse, unusedvars
  497. *
  498. * @param string $template name of the template
  499. * @param string $attribute name of the attribute
  500. * @return mixed value of the attribute
  501. * @access public
  502. * @see setAttribute(), setAttributes(), clearAttribute()
  503. */
  504. function getAttribute( $template, $attribute )
  505. {
  506. $template = strtolower( $template );
  507. $attribute = strtolower( $attribute );
  508. if( !isset( $this->_templates[$template] ) )
  509. {
  510. return patErrorManager::raiseWarning(
  511. PATTEMPLATE_WARNING_NO_TEMPLATE,
  512. "Template '$template' does not exist."
  513. );
  514. }
  515. return $this->_templates[$template]['attributes'][$attribute];
  516. }
  517. /**
  518. * Clears an attribute of a template
  519. *
  520. * supported attributes: visibilty, loop, parse, unusedvars
  521. *
  522. * @param string $template name of the template
  523. * @param string $attribute name of the attribute
  524. * @access public
  525. * @see setAttribute(), setAttributes(), getAttribute()
  526. */
  527. function clearAttribute( $template, $attribute )
  528. {
  529. $template = strtolower( $template );
  530. $attribute = strtolower( $attribute );
  531. if( !isset( $this->_templates[$template] ) )
  532. {
  533. return patErrorManager::raiseWarning(
  534. PATTEMPLATE_WARNING_NO_TEMPLATE,
  535. "Template '$template' does not exist."
  536. );
  537. }
  538. $this->_templates[$template]['attributes'][$attribute] = '';;
  539. return true;
  540. }
  541. /**
  542. * Prepare a template
  543. *
  544. * This can be used if you want to add variables to
  545. * a template, that has not been loaded yet.
  546. *
  547. * @access public
  548. * @param string template name
  549. */
  550. function prepareTemplate( $name )
  551. {
  552. $name = strtolower( $name );
  553. if( !isset( $this->_vars[$name] ) )
  554. {
  555. $this->_vars[$name] = array(
  556. 'scalar' => array(),
  557. 'rows' => array()
  558. );
  559. }
  560. }
  561. /**
  562. * add a variable to a template
  563. *
  564. * A variable may also be an indexed array, but _not_
  565. * an associative array!
  566. *
  567. * @access public
  568. * @param string $template name of the template
  569. * @param string $varname name of the variable
  570. * @param mixed $value value of the variable
  571. */
  572. function addVar( $template, $varname, $value )
  573. {
  574. $template = strtolower( $template );
  575. $varname = strtoupper( $varname );
  576. if( !is_array( $value ) ) {
  577. $this->_vars[$template]['scalar'][$varname] = $value;
  578. return true;
  579. }
  580. $cnt = count( $value );
  581. for ($i = 0; $i < $cnt; $i++) {
  582. if (!isset( $this->_vars[$template]['rows'][$i] )) {
  583. $this->_vars[$template]['rows'][$i] = array();
  584. }
  585. $this->_vars[$template]['rows'][$i][$varname] = $value[$i];
  586. }
  587. return true;
  588. }
  589. /**
  590. * get the value of a variable
  591. *
  592. * @access public
  593. * @param string name of the template
  594. * @param string name of the variable
  595. * @return string value of the variable, null if the variable is not set
  596. */
  597. function getVar( $template, $varname )
  598. {
  599. $template = strtolower( $template );
  600. $varname = strtoupper( $varname );
  601. if( isset( $this->_vars[$template]['scalar'][$varname] ) )
  602. return $this->_vars[$template]['scalar'][$varname];
  603. $value = array();
  604. $cnt = count( $this->_vars[$template]['rows'] );
  605. for( $i = 0; $i < $cnt; $i++ )
  606. {
  607. if( !isset( $this->_vars[$template]['rows'][$i][$varname] ) )
  608. continue;
  609. array_push( $value, $this->_vars[$template]['rows'][$i][$varname] );
  610. }
  611. if( !empty( $value ) )
  612. return $value;
  613. return null;
  614. }
  615. /**
  616. * clear the value of a variable
  617. *
  618. * @access public
  619. * @param string name of the template
  620. * @param string name of the variable
  621. * @return boolean
  622. * @see clearVars(), clearTemplate()
  623. */
  624. function clearVar( $template, $varname )
  625. {
  626. $template = strtolower( $template );
  627. $varname = strtoupper( $varname );
  628. if (isset( $this->_vars[$template]['scalar'][$varname] )) {
  629. unset ($this->_vars[$template]['scalar'][$varname]);
  630. return true;
  631. }
  632. $result = false;
  633. $cnt = count( $this->_vars[$template]['rows'] );
  634. for ($i = 0; $i < $cnt; $i++) {
  635. if (!isset($this->_vars[$template]['rows'][$i][$varname])) {
  636. continue;
  637. }
  638. unset($this->_vars[$template]['rows'][$i][$varname]);
  639. $result = true;
  640. }
  641. return $result;
  642. }
  643. /**
  644. * Adds several variables to a template
  645. *
  646. * Each Template can have an unlimited amount of its own variables
  647. * $variables has to be an assotiative array containing variable/value pairs
  648. *
  649. * @param string $template name of the template
  650. * @param array $variables assotiative array of the variables
  651. * @param string $prefix prefix for all variable names
  652. * @access public
  653. * @see addVar(), addRows(), addGlobalVar(), addGlobalVars()
  654. */
  655. function addVars( $template, $variables, $prefix = '' )
  656. {
  657. $template = strtolower( $template );
  658. $prefix = strtoupper( $prefix );
  659. $variables = array_change_key_case( $variables, CASE_UPPER );
  660. foreach ($variables as $varname => $value) {
  661. $varname = $prefix.$varname;
  662. if (!is_array($value)) {
  663. if (!is_scalar($value)) {
  664. continue;
  665. }
  666. $this->_vars[$template]['scalar'][$varname] = $value;
  667. continue;
  668. }
  669. $cnt = count( $value );
  670. for( $i = 0; $i < $cnt; $i++ ) {
  671. if( !isset( $this->_vars[$template]['rows'][$i] ) )
  672. $this->_vars[$template]['rows'][$i] = array();
  673. $this->_vars[$template]['rows'][$i][$varname] = $value[$i];
  674. }
  675. }
  676. }
  677. /**
  678. * Clear all variables in a template
  679. *
  680. * This clears only variables, but does
  681. *
  682. * @access public
  683. * @param string $template name of the template
  684. * @return boolean
  685. * @see clearVar(), clearTemplate()
  686. */
  687. function clearVars( $template )
  688. {
  689. $template = strtolower($template);
  690. $this->_vars[$template] = array(
  691. 'scalar' => array(),
  692. 'rows' => array()
  693. );
  694. return true;
  695. }
  696. /**
  697. * Adds several rows of variables to a template
  698. *
  699. * Each Template can have an unlimited amount of its own variables
  700. * Can be used to add a database result as variables to a template
  701. *
  702. * @param string $template name of the template
  703. * @param array $rows array containing assotiative arrays with variable/value pairs
  704. * @param string $prefix prefix for all variable names
  705. * @access public
  706. * @see addVar(), addVars(), addGlobalVar(), addGlobalVars()
  707. */
  708. function addRows( $template, $rows, $prefix = '' )
  709. {
  710. $template = strtolower( $template );
  711. $prefix = strtoupper( $prefix );
  712. $cnt = count( $rows );
  713. for( $i = 0; $i < $cnt; $i++ )
  714. {
  715. if( !isset( $this->_vars[$template]['rows'][$i] ) )
  716. $this->_vars[$template]['rows'][$i] = array();
  717. $rows[$i] = array_change_key_case( $rows[$i], CASE_UPPER );
  718. foreach( $rows[$i] as $varname => $value )
  719. {
  720. $this->_vars[$template]['rows'][$i][$prefix.$varname] = $value;
  721. }
  722. }
  723. }
  724. /**
  725. * Adds an object to a template
  726. *
  727. * All properties of the object will be available as template variables.
  728. *
  729. * @access public
  730. * @param string name of the template
  731. * @param object|array object or array of objects
  732. * @param string prefix for all variable names
  733. * @param boolean ignore private properties (starting with _)
  734. * @see addVar(), addRows(), addGlobalVar(), addGlobalVars()
  735. */
  736. function addObject( $template, $object, $prefix = '', $ignorePrivate = false )
  737. {
  738. if( is_array( $object ) ) {
  739. $rows = array();
  740. foreach($object as $o) {
  741. array_push( $rows, $this->getObjectVars($o, $ignorePrivate) );
  742. }
  743. return $this->addRows( $template, $rows, $prefix );
  744. } elseif (is_object($object)) {
  745. return $this->addVars( $template, $this->getObjectVars($object, $ignorePrivate), $prefix );
  746. }
  747. return false;
  748. }
  749. /**
  750. * get the vars from an object
  751. *
  752. * @access private
  753. * @param object
  754. * @param boolean ignore private properties (starting with _)
  755. * @return array
  756. */
  757. function getObjectVars($obj, $ignorePrivate = false)
  758. {
  759. if (method_exists($obj, 'getVars')) {
  760. return $obj->getVars();
  761. }
  762. $vars = get_object_vars($obj);
  763. if ($ignorePrivate === false) {
  764. return $vars;
  765. }
  766. foreach ($vars as $var => $value) {
  767. if ($var{0} == '_') {
  768. unset($vars[$var]);
  769. }
  770. }
  771. return $vars;
  772. }
  773. /**
  774. * Adds a global variable
  775. *
  776. * Global variables are valid in all templates of this object.
  777. * A global variable has to be scalar, it will be converted to a string.
  778. *
  779. * @access public
  780. * @param string $varname name of the global variable
  781. * @param string $value value of the variable
  782. * @return boolean true on success
  783. * @see addGlobalVars(), addVar(), addVars(), addRows()
  784. */
  785. function addGlobalVar( $varname, $value )
  786. {
  787. $this->_globals[strtoupper( $varname )] = ( string )$value;
  788. return true;
  789. }
  790. /**
  791. * Clears a global variable
  792. *
  793. * @access public
  794. * @param string $varname name of the global variable
  795. * @return boolean true on success
  796. * @see clearVar(), clearVars(), clearGlobalVars()
  797. */
  798. function clearGlobalVar( $varname )
  799. {
  800. $varname = strtoupper( $varname );
  801. if (!isset($this->_globals[$varname])) {
  802. return false;
  803. }
  804. unset($this->_globals[$varname]);
  805. return true;
  806. }
  807. /**
  808. * Clears all global variables
  809. *
  810. * @access public
  811. * @return boolean true on success
  812. * @see clearVar(), clearVars(), clearGlobalVar()
  813. */
  814. function clearGlobalVars()
  815. {
  816. $this->_globals = array();
  817. return true;
  818. }
  819. /**
  820. * Adds several global variables
  821. *
  822. * Global variables are valid in all templates of this object.
  823. *
  824. * $variables is an associative array, containing name/value pairs of the variables.
  825. *
  826. * @access public
  827. * @param array $variables array containing the variables
  828. * @param string $prefix prefix for variable names
  829. * @return boolean true on success
  830. * @see addGlobalVar(), addVar(), addVars(), addRows()
  831. */
  832. function addGlobalVars( $variables, $prefix = '' )
  833. {
  834. $variables = array_change_key_case( $variables, CASE_UPPER );
  835. $prefix = strtoupper( $prefix );
  836. foreach( $variables as $varname => $value )
  837. {
  838. $this->_globals[$prefix.$varname] = ( string )$value;
  839. }
  840. return true;
  841. }
  842. /**
  843. * get all global variables
  844. *
  845. * @access public
  846. * @return array global variables
  847. */
  848. function getGlobalVars()
  849. {
  850. return $this->_globals;
  851. }
  852. /**
  853. * checks wether a template exists
  854. *
  855. * @access public
  856. * @param string name of the template
  857. * @return boolean true, if the template exists, false otherwise
  858. */
  859. function exists( $name )
  860. {
  861. return in_array( strtolower( $name ), $this->_templateList );
  862. }
  863. /**
  864. * enable a template cache
  865. *
  866. * A template cache will improve performace, as the templates
  867. * do not have to be read on each request.
  868. *
  869. * @access public
  870. * @param string name of the template cache
  871. * @param array parameters for the template cache
  872. * @return boolean true on success, patError otherwise
  873. */
  874. function useTemplateCache( $cache, $params = array() )
  875. {
  876. if( !is_object( $cache ) )
  877. {
  878. $cache = &$this->loadModule( 'TemplateCache', $cache, $params );
  879. }
  880. if( patErrorManager::isError( $cache ) )
  881. return $cache;
  882. $this->_tmplCache = &$cache;
  883. return true;
  884. }
  885. /**
  886. * enable an output filter
  887. *
  888. * Output filters are used to modify the template
  889. * result before it is sent to the browser.
  890. *
  891. * They are applied, when displayParsedTemplate() is called.
  892. *
  893. * @access public
  894. * @param string name of the output filter
  895. * @param array parameters for the output filter
  896. * @return boolean true on success, patError otherwise
  897. */
  898. function applyOutputFilter( $filter, $params = array(), $template = null )
  899. {
  900. if (!is_object($filter)) {
  901. $filter = &$this->loadModule( 'OutputFilter', $filter, $params );
  902. }
  903. if (patErrorManager::isError($filter)) {
  904. return $filter;
  905. }
  906. if ($template === null) {
  907. $this->_outputFilters[] = &$filter;
  908. return true;
  909. }
  910. $template = strtolower($template);
  911. if (!$this->exists($template)) {
  912. return patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'The selected template does not exist');
  913. }
  914. $this->_templates[$template]['attributes']['outputfilter'] = &$filter;
  915. return true;
  916. }
  917. /**
  918. * enable an input filter
  919. *
  920. * input filters are used to modify the template
  921. * stream before it is split into smaller templates-
  922. *
  923. * @access public
  924. * @param string name of the input filter
  925. * @param array parameters for the input filter
  926. * @return boolean true on success, patError otherwise
  927. */
  928. function applyInputFilter( $filter, $params = array() )
  929. {
  930. if( !is_object( $filter ) )
  931. {
  932. $filter = &$this->loadModule( 'InputFilter', $filter, $params );
  933. }
  934. if( patErrorManager::isError( $filter ) )
  935. return $filter;
  936. $this->_inputFilters[] = &$filter;
  937. return true;
  938. }
  939. /**
  940. * open a file and parse for patTemplate tags
  941. *
  942. * @access public
  943. * @param name of the file
  944. * @return true, if the template could be parsed
  945. * @deprecated Use patTemplate::readTemplatesFromInput() instead, as the method name is misleading
  946. * @see readTemplatesFromInput()
  947. */
  948. function readTemplatesFromFile( $filename )
  949. {
  950. return $this->readTemplatesFromInput( $filename, 'File' );
  951. }
  952. /**
  953. * open any input and parse for patTemplate tags
  954. *
  955. * @access public
  956. * @param string name of the input (filename, shm segment, etc.)
  957. * @param string driver that is used as reader, you may also pass a Reader object
  958. * @param array additional options that will only be used for this template
  959. * @param string name of the template that should be used as a container, should not be used by public
  960. * calls.
  961. * @return boolean true, if the template could be parsed, false otherwise
  962. */
  963. function readTemplatesFromInput( $input, $reader = 'File', $options = null, $parseInto = null )
  964. {
  965. if ((string)$input === '') {
  966. return patErrorManager::raiseError(PATTEMPLATE_ERROR_NO_INPUT, 'No input to read has been passed.');
  967. }
  968. if (is_array($options)) {
  969. $options = array_merge( $this->_options, $options );
  970. } else {
  971. $options = $this->_options;
  972. }
  973. if (!is_null($parseInto)) {
  974. $parseInto = strtolower( $parseInto );
  975. }
  976. $templates = false;
  977. if ($this->_tmplCache !== null) {
  978. /**
  979. * get the unique cache key
  980. */
  981. $key = $this->_tmplCache->getKey($input, $options);
  982. $templates = $this->_loadTemplatesFromCache( $input, $reader, $options, $key );
  983. /**
  984. * check for error returned from cache
  985. */
  986. if (patErrorManager::isError($templates)) {
  987. return $templates;
  988. }
  989. }
  990. /**
  991. * templates have not been loaded from cache
  992. */
  993. if ($templates === false) {
  994. if (!is_object( $reader)) {
  995. $reader = &$this->loadModule('Reader', $reader);
  996. if (patErrorManager::isError($reader)) {
  997. return $reader;
  998. }
  999. }
  1000. if ($reader->isInUse()) {
  1001. $reader = &$this->loadModule( 'Reader', $reader->getName(), array(), true);
  1002. if( patErrorManager::isError( $reader ) ) {
  1003. return $reader;
  1004. }
  1005. }
  1006. $reader->setOptions($options);
  1007. /**
  1008. * set the root attributes
  1009. */
  1010. if( !is_null( $parseInto ) )
  1011. {
  1012. $attributes = $this->getAttributes( $parseInto );
  1013. if( !patErrorManager::isError( $attributes ) )
  1014. {
  1015. $reader->setRootAttributes( $attributes );
  1016. }
  1017. }
  1018. $templates = $reader->readTemplates( $input );
  1019. /**
  1020. * check for error returned from reader
  1021. */
  1022. if( patErrorManager::isError( $templates ) )
  1023. return $templates;
  1024. /**
  1025. * store the
  1026. */
  1027. if( $this->_tmplCache !== null )
  1028. {
  1029. $this->_tmplCache->write( $key, $templates );
  1030. }
  1031. }
  1032. /**
  1033. * traverse all templates
  1034. */
  1035. foreach( $templates as $name => $spec )
  1036. {
  1037. /**
  1038. * root template
  1039. */
  1040. if( $name == '__ptroot' )
  1041. {
  1042. if( $parseInto === false )
  1043. {
  1044. continue;
  1045. }
  1046. if( !in_array( $parseInto, $this->_templateList ) )
  1047. continue;
  1048. $spec['loaded'] = true;
  1049. $spec['attributes'] = $this->_templates[$parseInto]['attributes'];
  1050. $name = $parseInto;
  1051. }
  1052. else
  1053. {
  1054. /**
  1055. * store the name
  1056. */
  1057. array_push( $this->_templateList, $name );
  1058. }
  1059. /**
  1060. * if this is the first template that has been loaded
  1061. * set it as the root template
  1062. */
  1063. if( $this->_root === null && is_null( $parseInto ) && isset( $spec['isRoot'] ) && $spec['isRoot'] == true )
  1064. {
  1065. $this->_root = $name;
  1066. }
  1067. /**
  1068. * set some default values
  1069. */
  1070. $spec['iteration'] = 0;
  1071. $spec['lastMode'] = 'w';
  1072. $spec['result'] = '';
  1073. $spec['modifyVars'] = array();
  1074. $spec['copyVars'] = array();
  1075. $spec['defaultVars'] = array();
  1076. /**
  1077. * store the template
  1078. */
  1079. $this->_templates[$name] = $spec;
  1080. $this->prepareTemplate( $name );
  1081. /**
  1082. * store the default values of the variables
  1083. */
  1084. foreach( $spec['varspecs'] as $varname => $varspec )
  1085. {
  1086. if (isset($varspec['modifier'])) {
  1087. $this->_templates[$name]['modifyVars'][$varname] = $varspec['modifier'];
  1088. }
  1089. if( isset( $varspec['copyfrom'] ) )
  1090. {
  1091. $this->_templates[$name]['copyVars'][$varname] = $varspec['copyfrom'];
  1092. }
  1093. if( !isset( $varspec['default'] ) )
  1094. continue;
  1095. $this->_templates[$name]['defaultVars'][$varname] = $varspec['default'];
  1096. if( !is_null( $this->getVar( $name, $varname ) ) )
  1097. continue;
  1098. $this->addVar( $name, $varname, $varspec['default'] );
  1099. }
  1100. unset($this->_templates[$name]['varspecs']);
  1101. /**
  1102. * autoload the template
  1103. *
  1104. * Some error management is needed here...
  1105. */
  1106. if( isset( $this->_templates[$name]['attributes']['src'] ) && $this->_templates[$name]['attributes']['autoload'] == 'on' )
  1107. {
  1108. if( $this->_templates[$name]['loaded'] !== true )
  1109. {
  1110. if( $this->_templates[$name]['attributes']['parse'] == 'on' )
  1111. {
  1112. $this->readTemplatesFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], $options, $name );
  1113. }
  1114. else
  1115. {
  1116. $this->loadTemplateFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], null, $name );
  1117. }
  1118. $this->_templates[$name]['loaded'] = true;
  1119. }
  1120. }
  1121. }
  1122. return true;
  1123. }
  1124. /**
  1125. * load from template cache
  1126. *
  1127. * @access private
  1128. * @param string name of the input (filename, shm segment, etc.)
  1129. * @param string driver that is used as reader, you may also pass a Reader object
  1130. * @param array options for the reader
  1131. * @param string cache key
  1132. * @return array|boolean either an array containing the templates, or false
  1133. */
  1134. function _loadTemplatesFromCache( $input, &$reader, $options, $key )
  1135. {
  1136. if( is_object( $reader ) )
  1137. $statName = $reader->getName();
  1138. else
  1139. $statName = $reader;
  1140. $stat = &$this->loadModule( 'Stat', $statName );
  1141. $stat->setOptions( $options );
  1142. /**
  1143. * get modification time
  1144. */
  1145. $modTime = $stat->getModificationTime( $input );
  1146. $templates = $this->_tmplCache->load( $key, $modTime );
  1147. return $templates;
  1148. }
  1149. /**
  1150. * open any input and load content into template
  1151. *
  1152. * @access public
  1153. * @param string name of the input (filename, shm segment, etc.)
  1154. * @param string driver that is used as reader
  1155. * @param string name of the template that should be used as a container,
  1156. * @return boolean true, if the template could be parsed, false otherwise
  1157. */
  1158. function loadTemplateFromInput( $input, $reader = 'File', $options = null, $parseInto = false )
  1159. {
  1160. if( is_array( $options ) )
  1161. $options = array_merge( $this->_options, $options );
  1162. else
  1163. $options = $this->_options;
  1164. if( !is_null( $parseInto ) )
  1165. $parseInto = strtolower( $parseInto );
  1166. $reader = &$this->loadModule( 'Reader', $reader );
  1167. if( patErrorManager::isError( $reader ) )
  1168. {
  1169. return $reader;
  1170. }
  1171. $reader->setOptions($options);
  1172. $result = $reader->loadTemplate( $input );
  1173. if( patErrorManager::isError( $result ) )
  1174. {
  1175. return $result;
  1176. }
  1177. $this->_templates[$parseInto]['content'] .= $result;
  1178. $this->_templates[$parseInto]['loaded'] = true;
  1179. return true;
  1180. }
  1181. /**
  1182. * load a template that had autoload="off"
  1183. *
  1184. * This is needed, if you change the source of a template and want to
  1185. * load it, after changing the attribute.
  1186. *
  1187. * @access public
  1188. * @param string template name
  1189. * @return boolean true, if template could be loaded
  1190. */
  1191. function loadTemplate( $template )
  1192. {
  1193. $template = strtolower( $template );
  1194. if( !isset( $this->_templates[$template] ) )
  1195. {
  1196. return patErrorManager::raiseWarning(
  1197. PATTEMPLATE_WARNING_NO_TEMPLATE,
  1198. "Template '$template' does not exist."
  1199. );
  1200. }
  1201. if( $this->_templates[$template]['loaded'] === true )
  1202. return true;
  1203. if( $this->_templates[$template]['attributes']['parse'] == 'on' )
  1204. {
  1205. return $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1206. }
  1207. else
  1208. {
  1209. return $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1210. }
  1211. }
  1212. /**
  1213. * loads a patTemplate module
  1214. *
  1215. * Modules are located in the patTemplate folder and include:
  1216. * - Readers
  1217. * - Caches
  1218. * - Variable Modifiers
  1219. * - Filters
  1220. * - Functions
  1221. * - Stats
  1222. *
  1223. * @access public
  1224. * @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
  1225. * @param string moduleName
  1226. * @param array parameters for the module
  1227. * @return object
  1228. */
  1229. function &loadModule( $moduleType, $moduleName, $params = array(), $new = false )
  1230. {
  1231. if( !isset( $this->_modules[$moduleType] ) )
  1232. $this->_modules[$moduleType] = array();
  1233. $sig = md5( $moduleName . serialize( $params ) );
  1234. if( isset( $this->_modules[$moduleType][$sig] ) && $new === false ) {
  1235. return $this->_modules[$moduleType][$sig];
  1236. }
  1237. if( !class_exists( 'patTemplate_Module' ) )
  1238. {
  1239. $file = sprintf( "%s/Module.php", $this->getIncludePath() );
  1240. if( !@include_once $file )
  1241. return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, 'Could not load module base class.' );
  1242. }
  1243. $baseClass = 'patTemplate_' . $moduleType;
  1244. if( !class_exists( $baseClass ) )
  1245. {
  1246. $baseFile = sprintf( "%s/%s.php", $this->getIncludePath(), $moduleType );
  1247. if( !@include_once $baseFile )
  1248. return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, "Could not load base class for $moduleType ($baseFile)." );
  1249. }
  1250. $moduleClass = 'patTemplate_' . $moduleType . '_' .$moduleName;
  1251. if( !class_exists( $moduleClass ) )
  1252. {
  1253. if( isset( $this->_moduleDirs[$moduleType] ) )
  1254. $dirs = $this->_moduleDirs[$moduleType];
  1255. else
  1256. $dirs = array();
  1257. array_push( $dirs, $this->getIncludePath() .'/'. $moduleType );
  1258. $found = false;
  1259. foreach( $dirs as $dir )
  1260. {
  1261. $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
  1262. if (@include_once $moduleFile) {
  1263. $found = true;
  1264. break;
  1265. }
  1266. }
  1267. if( !$found ) {
  1268. return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Could not load module $moduleClass ($moduleFile)." );
  1269. }
  1270. }
  1271. if( !class_exists( $moduleClass ) )
  1272. {
  1273. return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Module file $moduleFile does not contain class $moduleClass." );
  1274. }
  1275. $this->_modules[$moduleType][$sig] = &new $moduleClass;
  1276. if( method_exists( $this->_modules[$moduleType][$sig], 'setTemplateReference' ) )
  1277. {
  1278. $this->_modules[$moduleType][$sig]->setTemplateReference( $this );
  1279. }
  1280. $this->_modules[$moduleType][$sig]->setParams( $params );
  1281. return $this->_modules[$moduleType][$sig];
  1282. }
  1283. /**
  1284. * checks whether a module exists.
  1285. *
  1286. * Modules are located in the patTemplate folder and include:
  1287. * - Readers
  1288. * - Caches
  1289. * - Variable Modifiers
  1290. * - Filters
  1291. * - Functions
  1292. * - Stats
  1293. *
  1294. * @access public
  1295. * @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
  1296. * @param string moduleName
  1297. * @return boolean
  1298. */
  1299. function moduleExists( $moduleType, $moduleName )
  1300. {
  1301. if (isset($this->_moduleDirs[$moduleType])) {
  1302. $dirs = $this->_moduleDirs[$moduleType];
  1303. } else {
  1304. $dirs = array();
  1305. }
  1306. array_push($dirs, $this->getIncludePath() .'/'. $moduleType);
  1307. foreach ($dirs as $dir) {
  1308. $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
  1309. if (!file_exists($moduleFile)) {
  1310. continue;
  1311. }
  1312. if (!is_readable($moduleFile)) {
  1313. continue;
  1314. }
  1315. return true;
  1316. }
  1317. return false;
  1318. }
  1319. /**
  1320. * parses a template
  1321. *
  1322. * Parses a template and stores the parsed content.
  1323. * mode can be "w" for write (delete already parsed content) or "a" for append (appends the
  1324. * new parsed content to the already parsed content)
  1325. *
  1326. * @access public
  1327. * @param string name of the template
  1328. * @param string mode for the parsing
  1329. */
  1330. function parseTemplate( $template, $mode = 'w' )
  1331. {
  1332. $template = strtolower($template);
  1333. if (!isset($this->_templates[$template])) {
  1334. return patErrorManager::raiseWarning(
  1335. PATTEMPLATE_WARNING_NO_TEMPLATE,
  1336. "Template '$template' does not exist."
  1337. );
  1338. }
  1339. /**
  1340. * template is not visible
  1341. */
  1342. if ($this->_templates[$template]['attributes']['visibility'] == 'hidden') {
  1343. $this->_templates[$template]['result'] = '';
  1344. $this->_templates[$template]['parsed'] = true;
  1345. return true;
  1346. }
  1347. /**
  1348. * check, if the template has been loaded
  1349. * and load it if necessary.
  1350. */
  1351. if ($this->_templates[$template]['loaded'] !== true) {
  1352. if ($this->_templates[$template]['attributes']['parse'] == 'on') {
  1353. $result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1354. } else {
  1355. $result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1356. }
  1357. if (patErrorManager::isError($result)) {
  1358. return $result;
  1359. }
  1360. }
  1361. /**
  1362. * check for autoclear
  1363. */
  1364. if(
  1365. isset( $this->_templates[$template]['attributes']['autoclear'] ) &&
  1366. $this->_templates[$template]['attributes']['autoclear'] == 'yes' &&
  1367. $mode === 'w' &&
  1368. $this->_templates[$template]['lastMode'] != 'a'
  1369. ) {
  1370. $this->_templates[$template]['parsed'] = false;
  1371. }
  1372. /**
  1373. * template has been parsed and mode is not 'append'
  1374. */
  1375. if ($this->_templates[$template]['parsed'] === true && $mode === 'w') {
  1376. return true;
  1377. }
  1378. $this->_templates[$template]['lastMode'] = $mode;
  1379. $this->_initTemplate( $template );
  1380. if (!isset($this->_vars[$template]['rows'])) {
  1381. $this->_vars[$template]['rows'] = array();
  1382. }
  1383. $loop = count( $this->_vars[$template]['rows'] );
  1384. /**
  1385. * loop at least one times
  1386. */
  1387. if ($loop < 1) {
  1388. $loop = 1;
  1389. }
  1390. if (isset($this->_templates[$template]['attributes']['maxloop'])) {
  1391. $loop = ceil( $loop / $this->_templates[$template]['attributes']['maxloop'] ) * $this->_templates[$template]['attributes']['maxloop'];
  1392. }
  1393. $this->_templates[$template]['loop'] = max( $this->_templates[$template]['attributes']['loop'], $loop );
  1394. $start = 0;
  1395. if (isset($this->_templates[$template]['attributes']['limit'])) {
  1396. $p = strpos( $this->_templates[$template]['attributes']['limit'], ',' );
  1397. if ($p === false) {
  1398. $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $this->_templates[$template]['attributes']['limit'] );
  1399. $start = 0;
  1400. } else {
  1401. $start = substr( $this->_templates[$template]['attributes']['limit'], 0, $p );
  1402. $end = substr( $this->_templates[$template]['attributes']['limit'], $p+1 )+$start;
  1403. $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $end );
  1404. }
  1405. }
  1406. /**
  1407. * template should be cleared before parsing
  1408. */
  1409. if ($mode == 'w') {
  1410. $this->_templates[$template]['result'] = '';
  1411. $this->_templates[$template]['iteration'] = $start;
  1412. }
  1413. $loopCount = 0;
  1414. for ($i = $start; $i < $this->_templates[$template]['loop']; $i++) {
  1415. $finished = false;
  1416. unset( $this->_templates[$template]['vars'] );
  1417. /**
  1418. * fetch the variables
  1419. */
  1420. $this->_fetchVariables( $template );
  1421. /**
  1422. * fetch the template
  1423. */
  1424. $result = $this->_fetchTemplate($template);
  1425. if ($result === false) {
  1426. $this->_templates[$template]['iteration']++;
  1427. continue;
  1428. }
  1429. /**
  1430. * parse
  1431. */
  1432. $this->_parseVariables( $template );
  1433. $result = $this->_parseDependencies( $template );
  1434. if (patErrorManager::isError($result)) {
  1435. return $result;
  1436. }
  1437. /**
  1438. * store result
  1439. */
  1440. $this->_templates[$template]['result'] .= $this->_templates[$template]['work'];
  1441. $this->_templates[$template]['iteration']++;
  1442. ++$loopCount;
  1443. /**
  1444. * check for maximum loops
  1445. */
  1446. if (isset($this->_templates[$template]['attributes']['maxloop'])) {
  1447. if ($loopCount == $this->_templates[$template]['attributes']['maxloop'] && $i < ($loop-1)) {
  1448. $loopCount = 0;
  1449. $finished = true;
  1450. $this->_templates[$template]['parsed'] = true;
  1451. $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a' );
  1452. $this->_templates[$template]['parsed'] = false;
  1453. $this->_templates[$template]['result'] = '';
  1454. }
  1455. }
  1456. }
  1457. if (!$finished && isset($this->_templates[$template]['attributes']['maxloop'])) {
  1458. $this->_templates[$template]['parsed'] = true;
  1459. $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a', false );
  1460. $this->_templates[$template]['parsed'] = false;
  1461. $this->_templates[$template]['result'] = '';
  1462. $this->_templates[$this->_templates[$template]['attributes']['parent']]['work'] = '';
  1463. }
  1464. $this->_parseGlobals($template);
  1465. $this->_handleUnusedVars($template);
  1466. $this->_templates[$template]['parsed'] = true;
  1467. if (isset($this->_templates[$template]['attributes']['autoclear']) && $this->_templates[$template]['attributes']['autoclear'] == 'yes') {
  1468. $this->_vars[$template] = array(
  1469. 'scalar' => array(),
  1470. 'rows' => array()
  1471. );
  1472. }
  1473. if (isset($this->_templates[$template]['attributes']['outputfilter'])) {
  1474. if (is_object($this->_templates[$template]['attributes']['outputfilter'])) {
  1475. $filter = &$this->_templates[$template]['attributes']['outputfilter'];
  1476. } else {
  1477. $filter = &$this->loadModule('OutputFilter', $this->_templates[$template]['attributes']['outputfilter']);
  1478. }
  1479. if (patErrorManager::isError($filter)) {
  1480. return $filter;
  1481. }
  1482. $this->_templates[$template]['result'] = $filter->apply($this->_templates[$template]['result']);
  1483. }
  1484. return true;
  1485. }
  1486. /**
  1487. * Initialize a template
  1488. *
  1489. * This method checks the variable specifications and
  1490. * copys variables from other templates.
  1491. *
  1492. * @access private
  1493. * @param string name of the template
  1494. * @return boolean true on success
  1495. */
  1496. function _initTemplate( $template )
  1497. {
  1498. foreach( $this->_templates[$template]['copyVars'] as $dest => $src )
  1499. {
  1500. /**
  1501. * copy from the same template
  1502. */
  1503. if( !is_array( $src ) )
  1504. {
  1505. $srcTemplate = $template;
  1506. $srcVar = $src;
  1507. }
  1508. else
  1509. {
  1510. $srcTemplate = $src[0];
  1511. $srcVar = $src[1];
  1512. }
  1513. $copied = false;
  1514. /**
  1515. * copy from another template
  1516. */
  1517. if( isset( $this->_vars[$srcTemplate] ) )
  1518. {
  1519. if( isset( $this->_vars[$srcTemplate]['scalar'][$srcVar] ) )
  1520. {
  1521. $this->_vars[$template]['scalar'][$dest] = $this->_vars[$srcTemplate]['scalar'][$srcVar];
  1522. continue;
  1523. }
  1524. $rows = count( $this->_vars[$srcTemplate]['rows'] );
  1525. for( $i = 0; $i < $rows; $i++ )
  1526. {
  1527. if( !isset( $this->_vars[$srcTemplate]['rows'][$i][$srcVar] ) )
  1528. continue;
  1529. if( !isset( $this->_vars[$template]['rows'][$i] ) )
  1530. $this->_vars[$template]['rows'][$i] = array();
  1531. $this->_vars[$template]['rows'][$i][$dest] = $this->_vars[$srcTemplate]['rows'][$i][$srcVar];
  1532. $copied = true;
  1533. }
  1534. }
  1535. if( !$copied && isset( $this->_globals[$srcVar] ))
  1536. {
  1537. $this->_vars[$template]['scalar'][$dest] = $this->_globals[$srcVar];
  1538. }
  1539. }
  1540. return true;
  1541. }
  1542. /**
  1543. * parse all variables in a template
  1544. *
  1545. * @access private
  1546. * @param string
  1547. */
  1548. function _parseVariables( $template )
  1549. {
  1550. /**
  1551. * modify variables before parsing
  1552. */
  1553. $this->_applyModifers($template, $this->_templates[$template]['vars']);
  1554. foreach( $this->_templates[$template]['vars'] as $key => $value )
  1555. {
  1556. if( is_array( $value ) )
  1557. {
  1558. if( count( $this->_templates[$template]['currentDependencies'] ) == 1 )
  1559. {
  1560. $child = $this->_templates[$template]['currentDependencies'][0];
  1561. }
  1562. else
  1563. {
  1564. if( isset( $this->_templates[$template]['attributes']['child'] ) )
  1565. $child = $this->_templates[$template]['attributes']['child'];
  1566. else
  1567. continue;
  1568. }
  1569. $this->setAttribute( $child, 'autoclear', 'yes' );
  1570. $this->addVar( $child, $key, $value );
  1571. continue;
  1572. }
  1573. $var = $this->_startTag.$key.$this->_endTag;
  1574. $this->_templates[$template]['work'] = str_replace( $var, $value, $this->_templates[$template]['work'] );
  1575. }
  1576. return true;
  1577. }
  1578. /**
  1579. * parse global variables in the template
  1580. *
  1581. * @access private
  1582. * @param string name of the template
  1583. * @return boolean
  1584. */
  1585. function _parseGlobals($template)
  1586. {
  1587. $globalVars = $this->_globals;
  1588. $this->_applyModifers($template, $globalVars);
  1589. foreach( $globalVars as $key => $value )
  1590. {
  1591. if( is_array( $value ) )
  1592. {
  1593. continue;
  1594. }
  1595. $var = $this->_startTag.$key.$this->_endTag;
  1596. $this->_templates[$template]['result'] = str_replace( $var, $value, $this->_templates[$template]['result'] );
  1597. }
  1598. return true;
  1599. }
  1600. /**
  1601. * apply variable modifiers
  1602. *
  1603. * The variables will be passed by reference.
  1604. *
  1605. * @access private
  1606. * @param string name of the template (use modifiers from this template)
  1607. * @param array variables to which the modifiers should be applied
  1608. * @return boolean
  1609. */
  1610. function _applyModifers($template, &$vars)
  1611. {
  1612. foreach ($this->_templates[$template]['modifyVars'] as $varname => $modifier) {
  1613. if (!isset($vars[$varname])) {
  1614. continue;
  1615. }
  1616. if (($modifier['type'] === 'php' || $modifier['type'] === 'auto' ) && is_callable($modifier['mod'])) {
  1617. $vars[$varname] = call_user_func($modifier['mod'], $vars[$varname]);
  1618. continue;
  1619. }
  1620. if ($modifier['type'] === 'php') {
  1621. continue;
  1622. }
  1623. $mod = &$this->loadModule( 'Modifier', ucfirst( $modifier['mod'] ) );
  1624. $vars[$varname] = $mod->modify( $vars[$varname], $modifier['params'] );
  1625. }
  1626. // apply the default modifier
  1627. if (isset($this->_templates[$template]['attributes']['defaultmodifier'])) {
  1628. $defaultModifier = $this->_templates[$template]['attributes']['defaultmodifier'];
  1629. if (is_callable($defaultModifier)) {
  1630. $type = 'php';
  1631. } else {
  1632. $type = 'custom';
  1633. $defaultModifier = &$this->loadModule('Modifier', ucfirst($defaultModifier));
  1634. }
  1635. foreach (array_keys($vars) as $varname) {
  1636. if (isset($this->_templates[$template]['modifyVars'][$varname])) {
  1637. continue;
  1638. }
  1639. if ($type === 'php') {
  1640. $vars[$varname] = call_user_func($defaultModifier, $vars[$varname]);
  1641. } else {
  1642. $vars[$varname] = $defaultModifier->modify($vars[$varname], array());
  1643. }
  1644. }
  1645. }
  1646. return true;
  1647. }
  1648. /**
  1649. * parse all dependencies in a template
  1650. *
  1651. * @access private
  1652. * @param string
  1653. */
  1654. function _parseDependencies($template)
  1655. {
  1656. $countDep = count( $this->_templates[$template]['currentDependencies'] );
  1657. for ($i = 0; $i < $countDep; $i++) {
  1658. $depTemplate = $this->_templates[$template]['currentDependencies'][$i];
  1659. if ($depTemplate == $template) {
  1660. return patErrorManager::raiseError(PATTEMPLATE_ERROR_RECURSION, 'You have an error in your template "' . $template . '", which leads to recursion');
  1661. }
  1662. $this->parseTemplate($depTemplate);
  1663. $var = $this->_startTag.'TMPL:'.strtoupper( $depTemplate) .$this->_endTag;
  1664. $this->_templates[$template]['work'] = str_replace( $var, $this->_templates[$depTemplate]['result'], $this->_templates[$template]['work'] );
  1665. }
  1666. return true;
  1667. }
  1668. /**
  1669. * fetch plain template
  1670. *
  1671. * The template content will be stored in the template
  1672. * configuration so it can be used by other
  1673. * methods.
  1674. *
  1675. * @access private
  1676. * @param string template name
  1677. * @return boolean
  1678. */
  1679. function _fetchTemplate( $template )
  1680. {
  1681. switch( $this->_templates[$template]['attributes']['type'] )
  1682. {
  1683. /**
  1684. * condition template
  1685. */
  1686. case 'condition':
  1687. $value = $this->_getConditionValue($template, $this->_templates[$template]['attributes']['conditionvar']);
  1688. if ($value === false) {
  1689. $this->_templates[$template]['work'] = '';
  1690. $this->_templates[$template]['currentDependencies'] = array();
  1691. } else {
  1692. $this->_templates[$template]['work'] = $this->_templates[$template]['subtemplates'][$value]['data'];
  1693. $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
  1694. }
  1695. break;
  1696. /**
  1697. * condition template
  1698. */
  1699. case 'simplecondition':
  1700. foreach( $this->_templates[$template]['attributes']['requiredvars'] as $var )
  1701. {
  1702. // different template scope
  1703. if( $var[0] !== $template ) {
  1704. $this->_fetchVariables($var[0]);
  1705. }
  1706. $value = null;
  1707. // fetch the local variable
  1708. if( isset( $this->_templates[$var[0]]['vars'][$var[1]] )
  1709. && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 ) {
  1710. $value = $this->_templates[$var[0]]['vars'][$var[1]];
  1711. }
  1712. if (isset($this->_templates[$template]['attributes']['useglobals'])) {
  1713. if(isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1) {
  1714. $value = $this->_globals[$var[1]];
  1715. }
  1716. }
  1717. if ($value !== null) {
  1718. if ($var[2] === null) {
  1719. continue;
  1720. } else {
  1721. // Joomla! addition 23-June-2005
  1722. // value wrapped in ## uses regex for comparison
  1723. $condition = $var[2];
  1724. if (substr( $condition, 0, 1 ) == '#' && substr( $condition, -1, 1 ) == '#' ) {
  1725. if (preg_match( $condition, $value )) {
  1726. continue;
  1727. }
  1728. } else if ($condition == $value) {
  1729. continue;
  1730. }
  1731. /* Pat Original
  1732. if ($var[2] == $value) {
  1733. continue;
  1734. }
  1735. */
  1736. }
  1737. }
  1738. $this->_templates[$template]['work'] = '';
  1739. $this->_templates[$template]['currentDependencies'] = array();
  1740. break 2;
  1741. }
  1742. $this->_templates[$template]['work'] = $this->_templates[$template]['content'];
  1743. $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['dependencies'];
  1744. break;
  1745. /**
  1746. * modulo template
  1747. */
  1748. case 'modulo':
  1749. // check for empty template
  1750. if ($this->_hasVariables($template)) {
  1751. $value = (string)($this->_templates[$template]['iteration'] + 1 ) % $this->_templates[$template]['attributes']['modulo'];
  1752. } else {
  1753. $value = '__empty';
  1754. }
  1755. $value = $this->_getConditionValue($template, $value, false);
  1756. if ($value === false) {
  1757. $this->_temp

Large files files are truncated, but you can click here to view the full file