PageRenderTime 65ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/libraries/pattemplate/patTemplate.php

https://github.com/adothompson/ucsc-identity-joomla
PHP | 2670 lines | 1405 code | 287 blank | 978 comment | 278 complexity | b7f657d1cb556f2fd76919e77d257ee9 MD5 | raw file
Possible License(s): 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 10381 2008-06-01 03:35:53Z pasamio $
  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. if(!isset($this->_vars[$template]['rows']))
  605. return null;
  606. $cnt = count( $this->_vars[$template]['rows'] );
  607. for( $i = 0; $i < $cnt; $i++ )
  608. {
  609. if( !isset( $this->_vars[$template]['rows'][$i][$varname] ) )
  610. continue;
  611. array_push( $value, $this->_vars[$template]['rows'][$i][$varname] );
  612. }
  613. if( !empty( $value ) )
  614. return $value;
  615. return null;
  616. }
  617. /**
  618. * clear the value of a variable
  619. *
  620. * @access public
  621. * @param string name of the template
  622. * @param string name of the variable
  623. * @return boolean
  624. * @see clearVars(), clearTemplate()
  625. */
  626. function clearVar( $template, $varname )
  627. {
  628. $template = strtolower( $template );
  629. $varname = strtoupper( $varname );
  630. if (isset( $this->_vars[$template]['scalar'][$varname] )) {
  631. unset ($this->_vars[$template]['scalar'][$varname]);
  632. return true;
  633. }
  634. $result = false;
  635. $cnt = count( $this->_vars[$template]['rows'] );
  636. for ($i = 0; $i < $cnt; $i++) {
  637. if (!isset($this->_vars[$template]['rows'][$i][$varname])) {
  638. continue;
  639. }
  640. unset($this->_vars[$template]['rows'][$i][$varname]);
  641. $result = true;
  642. }
  643. return $result;
  644. }
  645. /**
  646. * Adds several variables to a template
  647. *
  648. * Each Template can have an unlimited amount of its own variables
  649. * $variables has to be an assotiative array containing variable/value pairs
  650. *
  651. * @param string $template name of the template
  652. * @param array $variables assotiative array of the variables
  653. * @param string $prefix prefix for all variable names
  654. * @access public
  655. * @see addVar(), addRows(), addGlobalVar(), addGlobalVars()
  656. */
  657. function addVars( $template, $variables, $prefix = '' )
  658. {
  659. $template = strtolower( $template );
  660. $prefix = strtoupper( $prefix );
  661. $variables = array_change_key_case( $variables, CASE_UPPER );
  662. foreach ($variables as $varname => $value) {
  663. $varname = $prefix.$varname;
  664. if (!is_array($value)) {
  665. if (!is_scalar($value)) {
  666. continue;
  667. }
  668. $this->_vars[$template]['scalar'][$varname] = $value;
  669. continue;
  670. }
  671. $cnt = count( $value );
  672. for( $i = 0; $i < $cnt; $i++ ) {
  673. if( !isset( $this->_vars[$template]['rows'][$i] ) )
  674. $this->_vars[$template]['rows'][$i] = array();
  675. $this->_vars[$template]['rows'][$i][$varname] = $value[$i];
  676. }
  677. }
  678. }
  679. /**
  680. * Clear all variables in a template
  681. *
  682. * This clears only variables, but does
  683. *
  684. * @access public
  685. * @param string $template name of the template
  686. * @return boolean
  687. * @see clearVar(), clearTemplate()
  688. */
  689. function clearVars( $template )
  690. {
  691. $template = strtolower($template);
  692. $this->_vars[$template] = array(
  693. 'scalar' => array(),
  694. 'rows' => array()
  695. );
  696. return true;
  697. }
  698. /**
  699. * Adds several rows of variables to a template
  700. *
  701. * Each Template can have an unlimited amount of its own variables
  702. * Can be used to add a database result as variables to a template
  703. *
  704. * @param string $template name of the template
  705. * @param array $rows array containing assotiative arrays with variable/value pairs
  706. * @param string $prefix prefix for all variable names
  707. * @access public
  708. * @see addVar(), addVars(), addGlobalVar(), addGlobalVars()
  709. */
  710. function addRows( $template, $rows, $prefix = '' )
  711. {
  712. $template = strtolower( $template );
  713. $prefix = strtoupper( $prefix );
  714. $cnt = count( $rows );
  715. for( $i = 0; $i < $cnt; $i++ )
  716. {
  717. if( !isset( $this->_vars[$template]['rows'][$i] ) )
  718. $this->_vars[$template]['rows'][$i] = array();
  719. $rows[$i] = array_change_key_case( $rows[$i], CASE_UPPER );
  720. foreach( $rows[$i] as $varname => $value )
  721. {
  722. $this->_vars[$template]['rows'][$i][$prefix.$varname] = $value;
  723. }
  724. }
  725. }
  726. /**
  727. * Adds an object to a template
  728. *
  729. * All properties of the object will be available as template variables.
  730. *
  731. * @access public
  732. * @param string name of the template
  733. * @param object|array object or array of objects
  734. * @param string prefix for all variable names
  735. * @param boolean ignore private properties (starting with _)
  736. * @see addVar(), addRows(), addGlobalVar(), addGlobalVars()
  737. */
  738. function addObject( $template, $object, $prefix = '', $ignorePrivate = false )
  739. {
  740. if( is_array( $object ) ) {
  741. $rows = array();
  742. foreach($object as $o) {
  743. array_push( $rows, $this->getObjectVars($o, $ignorePrivate) );
  744. }
  745. return $this->addRows( $template, $rows, $prefix );
  746. } elseif (is_object($object)) {
  747. return $this->addVars( $template, $this->getObjectVars($object, $ignorePrivate), $prefix );
  748. }
  749. return false;
  750. }
  751. /**
  752. * get the vars from an object
  753. *
  754. * @access private
  755. * @param object
  756. * @param boolean ignore private properties (starting with _)
  757. * @return array
  758. */
  759. function getObjectVars($obj, $ignorePrivate = false)
  760. {
  761. if (method_exists($obj, 'getVars')) {
  762. return $obj->getVars();
  763. }
  764. $vars = get_object_vars($obj);
  765. if ($ignorePrivate === false) {
  766. return $vars;
  767. }
  768. foreach ($vars as $var => $value) {
  769. if ($var{0} == '_') {
  770. unset($vars[$var]);
  771. }
  772. }
  773. return $vars;
  774. }
  775. /**
  776. * Adds a global variable
  777. *
  778. * Global variables are valid in all templates of this object.
  779. * A global variable has to be scalar, it will be converted to a string.
  780. *
  781. * @access public
  782. * @param string $varname name of the global variable
  783. * @param string $value value of the variable
  784. * @return boolean true on success
  785. * @see addGlobalVars(), addVar(), addVars(), addRows()
  786. */
  787. function addGlobalVar( $varname, $value )
  788. {
  789. $this->_globals[strtoupper( $varname )] = ( string )$value;
  790. return true;
  791. }
  792. /**
  793. * Clears a global variable
  794. *
  795. * @access public
  796. * @param string $varname name of the global variable
  797. * @return boolean true on success
  798. * @see clearVar(), clearVars(), clearGlobalVars()
  799. */
  800. function clearGlobalVar( $varname )
  801. {
  802. $varname = strtoupper( $varname );
  803. if (!isset($this->_globals[$varname])) {
  804. return false;
  805. }
  806. unset($this->_globals[$varname]);
  807. return true;
  808. }
  809. /**
  810. * Clears all global variables
  811. *
  812. * @access public
  813. * @return boolean true on success
  814. * @see clearVar(), clearVars(), clearGlobalVar()
  815. */
  816. function clearGlobalVars()
  817. {
  818. $this->_globals = array();
  819. return true;
  820. }
  821. /**
  822. * Adds several global variables
  823. *
  824. * Global variables are valid in all templates of this object.
  825. *
  826. * $variables is an associative array, containing name/value pairs of the variables.
  827. *
  828. * @access public
  829. * @param array $variables array containing the variables
  830. * @param string $prefix prefix for variable names
  831. * @return boolean true on success
  832. * @see addGlobalVar(), addVar(), addVars(), addRows()
  833. */
  834. function addGlobalVars( $variables, $prefix = '' )
  835. {
  836. $variables = array_change_key_case( $variables, CASE_UPPER );
  837. $prefix = strtoupper( $prefix );
  838. foreach( $variables as $varname => $value )
  839. {
  840. $this->_globals[$prefix.$varname] = ( string )$value;
  841. }
  842. return true;
  843. }
  844. /**
  845. * get all global variables
  846. *
  847. * @access public
  848. * @return array global variables
  849. */
  850. function getGlobalVars()
  851. {
  852. return $this->_globals;
  853. }
  854. /**
  855. * checks wether a template exists
  856. *
  857. * @access public
  858. * @param string name of the template
  859. * @return boolean true, if the template exists, false otherwise
  860. */
  861. function exists( $name )
  862. {
  863. return in_array( strtolower( $name ), $this->_templateList );
  864. }
  865. /**
  866. * enable a template cache
  867. *
  868. * A template cache will improve performace, as the templates
  869. * do not have to be read on each request.
  870. *
  871. * @access public
  872. * @param string name of the template cache
  873. * @param array parameters for the template cache
  874. * @return boolean true on success, patError otherwise
  875. */
  876. function useTemplateCache( $cache, $params = array() )
  877. {
  878. if( !is_object( $cache ) )
  879. {
  880. $cache = &$this->loadModule( 'TemplateCache', $cache, $params );
  881. }
  882. if( patErrorManager::isError( $cache ) )
  883. return $cache;
  884. $this->_tmplCache = &$cache;
  885. return true;
  886. }
  887. /**
  888. * enable an output filter
  889. *
  890. * Output filters are used to modify the template
  891. * result before it is sent to the browser.
  892. *
  893. * They are applied, when displayParsedTemplate() is called.
  894. *
  895. * @access public
  896. * @param string name of the output filter
  897. * @param array parameters for the output filter
  898. * @return boolean true on success, patError otherwise
  899. */
  900. function applyOutputFilter( $filter, $params = array(), $template = null )
  901. {
  902. if (!is_object($filter)) {
  903. $filter = &$this->loadModule( 'OutputFilter', $filter, $params );
  904. }
  905. if (patErrorManager::isError($filter)) {
  906. return $filter;
  907. }
  908. if ($template === null) {
  909. $this->_outputFilters[] = &$filter;
  910. return true;
  911. }
  912. $template = strtolower($template);
  913. if (!$this->exists($template)) {
  914. return patErrorManager::raiseWarning(PATTEMPLATE_WARNING_NO_TEMPLATE, 'The selected template does not exist');
  915. }
  916. $this->_templates[$template]['attributes']['outputfilter'] = &$filter;
  917. return true;
  918. }
  919. /**
  920. * enable an input filter
  921. *
  922. * input filters are used to modify the template
  923. * stream before it is split into smaller templates-
  924. *
  925. * @access public
  926. * @param string name of the input filter
  927. * @param array parameters for the input filter
  928. * @return boolean true on success, patError otherwise
  929. */
  930. function applyInputFilter( $filter, $params = array() )
  931. {
  932. if( !is_object( $filter ) )
  933. {
  934. $filter = &$this->loadModule( 'InputFilter', $filter, $params );
  935. }
  936. if( patErrorManager::isError( $filter ) )
  937. return $filter;
  938. $this->_inputFilters[] = &$filter;
  939. return true;
  940. }
  941. /**
  942. * open a file and parse for patTemplate tags
  943. *
  944. * @access public
  945. * @param name of the file
  946. * @return true, if the template could be parsed
  947. * @deprecated Use patTemplate::readTemplatesFromInput() instead, as the method name is misleading
  948. * @see readTemplatesFromInput()
  949. */
  950. function readTemplatesFromFile( $filename )
  951. {
  952. return $this->readTemplatesFromInput( $filename, 'File' );
  953. }
  954. /**
  955. * open any input and parse for patTemplate tags
  956. *
  957. * @access public
  958. * @param string name of the input (filename, shm segment, etc.)
  959. * @param string driver that is used as reader, you may also pass a Reader object
  960. * @param array additional options that will only be used for this template
  961. * @param string name of the template that should be used as a container, should not be used by public
  962. * calls.
  963. * @return boolean true, if the template could be parsed, false otherwise
  964. */
  965. function readTemplatesFromInput( $input, $reader = 'File', $options = null, $parseInto = null )
  966. {
  967. if ((string)$input === '') {
  968. return patErrorManager::raiseError(PATTEMPLATE_ERROR_NO_INPUT, 'No input to read has been passed.');
  969. }
  970. if (is_array($options)) {
  971. $options = array_merge( $this->_options, $options );
  972. } else {
  973. $options = $this->_options;
  974. }
  975. if (!is_null($parseInto)) {
  976. $parseInto = strtolower( $parseInto );
  977. }
  978. $templates = false;
  979. if ($this->_tmplCache !== null) {
  980. /**
  981. * get the unique cache key
  982. */
  983. $key = $this->_tmplCache->getKey($input, $options);
  984. $templates = $this->_loadTemplatesFromCache( $input, $reader, $options, $key );
  985. /**
  986. * check for error returned from cache
  987. */
  988. if (patErrorManager::isError($templates)) {
  989. return $templates;
  990. }
  991. }
  992. /**
  993. * templates have not been loaded from cache
  994. */
  995. if ($templates === false) {
  996. if (!is_object( $reader)) {
  997. $reader = &$this->loadModule('Reader', $reader);
  998. if (patErrorManager::isError($reader)) {
  999. return $reader;
  1000. }
  1001. }
  1002. if ($reader->isInUse()) {
  1003. $reader = &$this->loadModule( 'Reader', $reader->getName(), array(), true);
  1004. if( patErrorManager::isError( $reader ) ) {
  1005. return $reader;
  1006. }
  1007. }
  1008. $reader->setOptions($options);
  1009. /**
  1010. * set the root attributes
  1011. */
  1012. if( !is_null( $parseInto ) )
  1013. {
  1014. $attributes = $this->getAttributes( $parseInto );
  1015. if( !patErrorManager::isError( $attributes ) )
  1016. {
  1017. $reader->setRootAttributes( $attributes );
  1018. }
  1019. }
  1020. $templates = $reader->readTemplates( $input );
  1021. /**
  1022. * check for error returned from reader
  1023. */
  1024. if( patErrorManager::isError( $templates ) )
  1025. return $templates;
  1026. /**
  1027. * store the
  1028. */
  1029. if( $this->_tmplCache !== null )
  1030. {
  1031. $this->_tmplCache->write( $key, $templates );
  1032. }
  1033. }
  1034. /**
  1035. * traverse all templates
  1036. */
  1037. foreach( $templates as $name => $spec )
  1038. {
  1039. /**
  1040. * root template
  1041. */
  1042. if( $name == '__ptroot' )
  1043. {
  1044. if( $parseInto === false )
  1045. {
  1046. continue;
  1047. }
  1048. if( !in_array( $parseInto, $this->_templateList ) )
  1049. continue;
  1050. $spec['loaded'] = true;
  1051. $spec['attributes'] = $this->_templates[$parseInto]['attributes'];
  1052. $name = $parseInto;
  1053. }
  1054. else
  1055. {
  1056. /**
  1057. * store the name
  1058. */
  1059. array_push( $this->_templateList, $name );
  1060. }
  1061. /**
  1062. * if this is the first template that has been loaded
  1063. * set it as the root template
  1064. */
  1065. if( $this->_root === null && is_null( $parseInto ) && isset( $spec['isRoot'] ) && $spec['isRoot'] == true )
  1066. {
  1067. $this->_root = $name;
  1068. }
  1069. /**
  1070. * set some default values
  1071. */
  1072. $spec['iteration'] = 0;
  1073. $spec['lastMode'] = 'w';
  1074. $spec['result'] = '';
  1075. $spec['modifyVars'] = array();
  1076. $spec['copyVars'] = array();
  1077. $spec['defaultVars'] = array();
  1078. /**
  1079. * store the template
  1080. */
  1081. $this->_templates[$name] = $spec;
  1082. $this->prepareTemplate( $name );
  1083. /**
  1084. * store the default values of the variables
  1085. */
  1086. foreach( $spec['varspecs'] as $varname => $varspec )
  1087. {
  1088. if (isset($varspec['modifier'])) {
  1089. $this->_templates[$name]['modifyVars'][$varname] = $varspec['modifier'];
  1090. }
  1091. if( isset( $varspec['copyfrom'] ) )
  1092. {
  1093. $this->_templates[$name]['copyVars'][$varname] = $varspec['copyfrom'];
  1094. }
  1095. if( !isset( $varspec['default'] ) )
  1096. continue;
  1097. $this->_templates[$name]['defaultVars'][$varname] = $varspec['default'];
  1098. if( !is_null( $this->getVar( $name, $varname ) ) )
  1099. continue;
  1100. $this->addVar( $name, $varname, $varspec['default'] );
  1101. }
  1102. unset($this->_templates[$name]['varspecs']);
  1103. /**
  1104. * autoload the template
  1105. *
  1106. * Some error management is needed here...
  1107. */
  1108. if( isset( $this->_templates[$name]['attributes']['src'] ) && $this->_templates[$name]['attributes']['autoload'] == 'on' )
  1109. {
  1110. if( $this->_templates[$name]['loaded'] !== true )
  1111. {
  1112. if( $this->_templates[$name]['attributes']['parse'] == 'on' )
  1113. {
  1114. $this->readTemplatesFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], $options, $name );
  1115. }
  1116. else
  1117. {
  1118. $this->loadTemplateFromInput( $this->_templates[$name]['attributes']['src'], $this->_templates[$name]['attributes']['reader'], null, $name );
  1119. }
  1120. $this->_templates[$name]['loaded'] = true;
  1121. }
  1122. }
  1123. }
  1124. return true;
  1125. }
  1126. /**
  1127. * load from template cache
  1128. *
  1129. * @access private
  1130. * @param string name of the input (filename, shm segment, etc.)
  1131. * @param string driver that is used as reader, you may also pass a Reader object
  1132. * @param array options for the reader
  1133. * @param string cache key
  1134. * @return array|boolean either an array containing the templates, or false
  1135. */
  1136. function _loadTemplatesFromCache( $input, &$reader, $options, $key )
  1137. {
  1138. if( is_object( $reader ) )
  1139. $statName = $reader->getName();
  1140. else
  1141. $statName = $reader;
  1142. $stat = &$this->loadModule( 'Stat', $statName );
  1143. $stat->setOptions( $options );
  1144. /**
  1145. * get modification time
  1146. */
  1147. $modTime = $stat->getModificationTime( $input );
  1148. $templates = $this->_tmplCache->load( $key, $modTime );
  1149. return $templates;
  1150. }
  1151. /**
  1152. * open any input and load content into template
  1153. *
  1154. * @access public
  1155. * @param string name of the input (filename, shm segment, etc.)
  1156. * @param string driver that is used as reader
  1157. * @param string name of the template that should be used as a container,
  1158. * @return boolean true, if the template could be parsed, false otherwise
  1159. */
  1160. function loadTemplateFromInput( $input, $reader = 'File', $options = null, $parseInto = false )
  1161. {
  1162. if( is_array( $options ) )
  1163. $options = array_merge( $this->_options, $options );
  1164. else
  1165. $options = $this->_options;
  1166. if( !is_null( $parseInto ) )
  1167. $parseInto = strtolower( $parseInto );
  1168. $reader = &$this->loadModule( 'Reader', $reader );
  1169. if( patErrorManager::isError( $reader ) )
  1170. {
  1171. return $reader;
  1172. }
  1173. $reader->setOptions($options);
  1174. $result = $reader->loadTemplate( $input );
  1175. if( patErrorManager::isError( $result ) )
  1176. {
  1177. return $result;
  1178. }
  1179. $this->_templates[$parseInto]['content'] .= $result;
  1180. $this->_templates[$parseInto]['loaded'] = true;
  1181. return true;
  1182. }
  1183. /**
  1184. * load a template that had autoload="off"
  1185. *
  1186. * This is needed, if you change the source of a template and want to
  1187. * load it, after changing the attribute.
  1188. *
  1189. * @access public
  1190. * @param string template name
  1191. * @return boolean true, if template could be loaded
  1192. */
  1193. function loadTemplate( $template )
  1194. {
  1195. $template = strtolower( $template );
  1196. if( !isset( $this->_templates[$template] ) )
  1197. {
  1198. return patErrorManager::raiseWarning(
  1199. PATTEMPLATE_WARNING_NO_TEMPLATE,
  1200. "Template '$template' does not exist."
  1201. );
  1202. }
  1203. if( $this->_templates[$template]['loaded'] === true )
  1204. return true;
  1205. if( $this->_templates[$template]['attributes']['parse'] == 'on' )
  1206. {
  1207. return $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1208. }
  1209. else
  1210. {
  1211. return $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1212. }
  1213. }
  1214. /**
  1215. * loads a patTemplate module
  1216. *
  1217. * Modules are located in the patTemplate folder and include:
  1218. * - Readers
  1219. * - Caches
  1220. * - Variable Modifiers
  1221. * - Filters
  1222. * - Functions
  1223. * - Stats
  1224. *
  1225. * @access public
  1226. * @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
  1227. * @param string moduleName
  1228. * @param array parameters for the module
  1229. * @return object
  1230. */
  1231. function &loadModule( $moduleType, $moduleName, $params = array(), $new = false )
  1232. {
  1233. if( !isset( $this->_modules[$moduleType] ) )
  1234. $this->_modules[$moduleType] = array();
  1235. $sig = md5( $moduleName . serialize( $params ) );
  1236. if( isset( $this->_modules[$moduleType][$sig] ) && $new === false ) {
  1237. return $this->_modules[$moduleType][$sig];
  1238. }
  1239. if( !class_exists( 'patTemplate_Module' ) )
  1240. {
  1241. $file = sprintf( "%s/Module.php", $this->getIncludePath() );
  1242. if( !file_exists( $file ) or !include_once $file )
  1243. return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, 'Could not load module base class.' );
  1244. }
  1245. $baseClass = 'patTemplate_' . $moduleType;
  1246. if( !class_exists( $baseClass ) )
  1247. {
  1248. $baseFile = sprintf( "%s/%s.php", $this->getIncludePath(), $moduleType );
  1249. if( !file_exists( $baseFile ) or !include_once $baseFile )
  1250. return patErrorManager::raiseError( PATTEMPLATE_ERROR_BASECLASS_NOT_FOUND, "Could not load base class for $moduleType ($baseFile)." );
  1251. }
  1252. $moduleClass = 'patTemplate_' . $moduleType . '_' .$moduleName;
  1253. if( !class_exists( $moduleClass ) )
  1254. {
  1255. if( isset( $this->_moduleDirs[$moduleType] ) )
  1256. $dirs = $this->_moduleDirs[$moduleType];
  1257. else
  1258. $dirs = array();
  1259. array_push( $dirs, $this->getIncludePath() .'/'. $moduleType );
  1260. $found = false;
  1261. foreach( $dirs as $dir )
  1262. {
  1263. $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
  1264. if ( file_exists( $moduleFile ) and include_once $moduleFile) {
  1265. $found = true;
  1266. break;
  1267. }
  1268. }
  1269. if( !$found ) {
  1270. return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Could not load module $moduleClass ($moduleFile)." );
  1271. }
  1272. }
  1273. if( !class_exists( $moduleClass ) )
  1274. {
  1275. return patErrorManager::raiseError( PATTEMPLATE_ERROR_MODULE_NOT_FOUND, "Module file $moduleFile does not contain class $moduleClass." );
  1276. }
  1277. $this->_modules[$moduleType][$sig] = &new $moduleClass;
  1278. if( method_exists( $this->_modules[$moduleType][$sig], 'setTemplateReference' ) )
  1279. {
  1280. $this->_modules[$moduleType][$sig]->setTemplateReference( $this );
  1281. }
  1282. $this->_modules[$moduleType][$sig]->setParams( $params );
  1283. return $this->_modules[$moduleType][$sig];
  1284. }
  1285. /**
  1286. * checks whether a module exists.
  1287. *
  1288. * Modules are located in the patTemplate folder and include:
  1289. * - Readers
  1290. * - Caches
  1291. * - Variable Modifiers
  1292. * - Filters
  1293. * - Functions
  1294. * - Stats
  1295. *
  1296. * @access public
  1297. * @param string moduleType (Reader|TemplateCache|Modifier|OutputFilter|InputFilter)
  1298. * @param string moduleName
  1299. * @return boolean
  1300. */
  1301. function moduleExists( $moduleType, $moduleName )
  1302. {
  1303. // !!!JOOMLA VARIATION!!!
  1304. // cache checks on files
  1305. static $paths;
  1306. if (!$paths)
  1307. {
  1308. $paths = array();
  1309. }
  1310. if (isset($this->_moduleDirs[$moduleType])) {
  1311. $dirs = $this->_moduleDirs[$moduleType];
  1312. } else {
  1313. $dirs = array();
  1314. }
  1315. array_push($dirs, $this->getIncludePath() .'/'. $moduleType);
  1316. foreach ($dirs as $dir) {
  1317. $moduleFile = sprintf( "%s/%s.php", $dir, str_replace( '_', '/', $moduleName ) );
  1318. if (!isset( $paths[$moduleFile] ))
  1319. {
  1320. if (!file_exists($moduleFile)) {
  1321. $paths[$moduleFile] = false;
  1322. }
  1323. else if (!is_readable($moduleFile)) {
  1324. $paths[$moduleFile] = false;
  1325. }
  1326. else
  1327. {
  1328. $paths[$moduleFile] = true;
  1329. }
  1330. }
  1331. if (!$paths[$moduleFile]) {
  1332. continue;
  1333. }
  1334. return true;
  1335. }
  1336. return false;
  1337. }
  1338. /**
  1339. * parses a template
  1340. *
  1341. * Parses a template and stores the parsed content.
  1342. * mode can be "w" for write (delete already parsed content) or "a" for append (appends the
  1343. * new parsed content to the already parsed content)
  1344. *
  1345. * @access public
  1346. * @param string name of the template
  1347. * @param string mode for the parsing
  1348. */
  1349. function parseTemplate( $template, $mode = 'w' )
  1350. {
  1351. $template = strtolower($template);
  1352. if (!isset($this->_templates[$template])) {
  1353. return patErrorManager::raiseWarning(
  1354. PATTEMPLATE_WARNING_NO_TEMPLATE,
  1355. "Template '$template' does not exist."
  1356. );
  1357. }
  1358. /**
  1359. * template is not visible
  1360. */
  1361. if ($this->_templates[$template]['attributes']['visibility'] == 'hidden') {
  1362. $this->_templates[$template]['result'] = '';
  1363. $this->_templates[$template]['parsed'] = true;
  1364. return true;
  1365. }
  1366. /**
  1367. * check, if the template has been loaded
  1368. * and load it if necessary.
  1369. */
  1370. if ($this->_templates[$template]['loaded'] !== true) {
  1371. if ($this->_templates[$template]['attributes']['parse'] == 'on') {
  1372. $result = $this->readTemplatesFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1373. } else {
  1374. $result = $this->loadTemplateFromInput( $this->_templates[$template]['attributes']['src'], $this->_templates[$template]['attributes']['reader'], null, $template );
  1375. }
  1376. if (patErrorManager::isError($result)) {
  1377. return $result;
  1378. }
  1379. }
  1380. /**
  1381. * check for autoclear
  1382. */
  1383. if(
  1384. isset( $this->_templates[$template]['attributes']['autoclear'] ) &&
  1385. $this->_templates[$template]['attributes']['autoclear'] == 'yes' &&
  1386. $mode === 'w' &&
  1387. $this->_templates[$template]['lastMode'] != 'a'
  1388. ) {
  1389. $this->_templates[$template]['parsed'] = false;
  1390. }
  1391. /**
  1392. * template has been parsed and mode is not 'append'
  1393. */
  1394. if ($this->_templates[$template]['parsed'] === true && $mode === 'w') {
  1395. return true;
  1396. }
  1397. $this->_templates[$template]['lastMode'] = $mode;
  1398. $this->_initTemplate( $template );
  1399. if (!isset($this->_vars[$template]['rows'])) {
  1400. $this->_vars[$template]['rows'] = array();
  1401. }
  1402. $loop = count( $this->_vars[$template]['rows'] );
  1403. /**
  1404. * loop at least one times
  1405. */
  1406. if ($loop < 1) {
  1407. $loop = 1;
  1408. }
  1409. if (isset($this->_templates[$template]['attributes']['maxloop'])) {
  1410. $loop = ceil( $loop / $this->_templates[$template]['attributes']['maxloop'] ) * $this->_templates[$template]['attributes']['maxloop'];
  1411. }
  1412. $this->_templates[$template]['loop'] = max( $this->_templates[$template]['attributes']['loop'], $loop );
  1413. $start = 0;
  1414. if (isset($this->_templates[$template]['attributes']['limit'])) {
  1415. $p = strpos( $this->_templates[$template]['attributes']['limit'], ',' );
  1416. if ($p === false) {
  1417. $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $this->_templates[$template]['attributes']['limit'] );
  1418. $start = 0;
  1419. } else {
  1420. $start = substr( $this->_templates[$template]['attributes']['limit'], 0, $p );
  1421. $end = substr( $this->_templates[$template]['attributes']['limit'], $p+1 )+$start;
  1422. $this->_templates[$template]['loop'] = min( $this->_templates[$template]['loop'], $end );
  1423. }
  1424. }
  1425. /**
  1426. * template should be cleared before parsing
  1427. */
  1428. if ($mode == 'w') {
  1429. $this->_templates[$template]['result'] = '';
  1430. $this->_templates[$template]['iteration'] = $start;
  1431. }
  1432. $loopCount = 0;
  1433. for ($i = $start; $i < $this->_templates[$template]['loop']; $i++) {
  1434. $finished = false;
  1435. unset( $this->_templates[$template]['vars'] );
  1436. /**
  1437. * fetch the variables
  1438. */
  1439. $this->_fetchVariables( $template );
  1440. /**
  1441. * fetch the template
  1442. */
  1443. $result = $this->_fetchTemplate($template);
  1444. if ($result === false) {
  1445. $this->_templates[$template]['iteration']++;
  1446. continue;
  1447. }
  1448. /**
  1449. * parse
  1450. */
  1451. $this->_parseVariables( $template );
  1452. $result = $this->_parseDependencies( $template );
  1453. if (patErrorManager::isError($result)) {
  1454. return $result;
  1455. }
  1456. /**
  1457. * store result
  1458. */
  1459. $this->_templates[$template]['result'] .= $this->_templates[$template]['work'];
  1460. $this->_templates[$template]['iteration']++;
  1461. ++$loopCount;
  1462. /**
  1463. * check for maximum loops
  1464. */
  1465. if (isset($this->_templates[$template]['attributes']['maxloop'])) {
  1466. if ($loopCount == $this->_templates[$template]['attributes']['maxloop'] && $i < ($loop-1)) {
  1467. $loopCount = 0;
  1468. $finished = true;
  1469. $this->_templates[$template]['parsed'] = true;
  1470. $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a' );
  1471. $this->_templates[$template]['parsed'] = false;
  1472. $this->_templates[$template]['result'] = '';
  1473. }
  1474. }
  1475. }
  1476. if (!$finished && isset($this->_templates[$template]['attributes']['maxloop'])) {
  1477. $this->_templates[$template]['parsed'] = true;
  1478. $this->parseTemplate( $this->_templates[$template]['attributes']['parent'], 'a', false );
  1479. $this->_templates[$template]['parsed'] = false;
  1480. $this->_templates[$template]['result'] = '';
  1481. $this->_templates[$this->_templates[$template]['attributes']['parent']]['work'] = '';
  1482. }
  1483. $this->_parseGlobals($template);
  1484. $this->_handleUnusedVars($template);
  1485. $this->_templates[$template]['parsed'] = true;
  1486. if (isset($this->_templates[$template]['attributes']['autoclear']) && $this->_templates[$template]['attributes']['autoclear'] == 'yes') {
  1487. $this->_vars[$template] = array(
  1488. 'scalar' => array(),
  1489. 'rows' => array()
  1490. );
  1491. }
  1492. if (isset($this->_templates[$template]['attributes']['outputfilter'])) {
  1493. if (is_object($this->_templates[$template]['attributes']['outputfilter'])) {
  1494. $filter = &$this->_templates[$template]['attributes']['outputfilter'];
  1495. } else {
  1496. $filter = &$this->loadModule('OutputFilter', $this->_templates[$template]['attributes']['outputfilter']);
  1497. }
  1498. if (patErrorManager::isError($filter)) {
  1499. return $filter;
  1500. }
  1501. $this->_templates[$template]['result'] = $filter->apply($this->_templates[$template]['result']);
  1502. }
  1503. return true;
  1504. }
  1505. /**
  1506. * Initialize a template
  1507. *
  1508. * This method checks the variable specifications and
  1509. * copys variables from other templates.
  1510. *
  1511. * @access private
  1512. * @param string name of the template
  1513. * @return boolean true on success
  1514. */
  1515. function _initTemplate( $template )
  1516. {
  1517. foreach( $this->_templates[$template]['copyVars'] as $dest => $src )
  1518. {
  1519. /**
  1520. * copy from the same template
  1521. */
  1522. if( !is_array( $src ) )
  1523. {
  1524. $srcTemplate = $template;
  1525. $srcVar = $src;
  1526. }
  1527. else
  1528. {
  1529. $srcTemplate = $src[0];
  1530. $srcVar = $src[1];
  1531. }
  1532. $copied = false;
  1533. /**
  1534. * copy from another template
  1535. */
  1536. if( isset( $this->_vars[$srcTemplate] ) )
  1537. {
  1538. if( isset( $this->_vars[$srcTemplate]['scalar'][$srcVar] ) )
  1539. {
  1540. $this->_vars[$template]['scalar'][$dest] = $this->_vars[$srcTemplate]['scalar'][$srcVar];
  1541. continue;
  1542. }
  1543. $rows = count( $this->_vars[$srcTemplate]['rows'] );
  1544. for( $i = 0; $i < $rows; $i++ )
  1545. {
  1546. if( !isset( $this->_vars[$srcTemplate]['rows'][$i][$srcVar] ) )
  1547. continue;
  1548. if( !isset( $this->_vars[$template]['rows'][$i] ) )
  1549. $this->_vars[$template]['rows'][$i] = array();
  1550. $this->_vars[$template]['rows'][$i][$dest] = $this->_vars[$srcTemplate]['rows'][$i][$srcVar];
  1551. $copied = true;
  1552. }
  1553. }
  1554. if( !$copied && isset( $this->_globals[$srcVar] ))
  1555. {
  1556. $this->_vars[$template]['scalar'][$dest] = $this->_globals[$srcVar];
  1557. }
  1558. }
  1559. return true;
  1560. }
  1561. /**
  1562. * parse all variables in a template
  1563. *
  1564. * @access private
  1565. * @param string
  1566. */
  1567. function _parseVariables( $template )
  1568. {
  1569. /**
  1570. * modify variables before parsing
  1571. */
  1572. $this->_applyModifers($template, $this->_templates[$template]['vars']);
  1573. foreach( $this->_templates[$template]['vars'] as $key => $value )
  1574. {
  1575. if( is_array( $value ) )
  1576. {
  1577. if( count( $this->_templates[$template]['currentDependencies'] ) == 1 )
  1578. {
  1579. $child = $this->_templates[$template]['currentDependencies'][0];
  1580. }
  1581. else
  1582. {
  1583. if( isset( $this->_templates[$template]['attributes']['child'] ) )
  1584. $child = $this->_templates[$template]['attributes']['child'];
  1585. else
  1586. continue;
  1587. }
  1588. $this->setAttribute( $child, 'autoclear', 'yes' );
  1589. $this->addVar( $child, $key, $value );
  1590. continue;
  1591. }
  1592. $var = $this->_startTag.$key.$this->_endTag;
  1593. $this->_templates[$template]['work'] = str_replace( $var, $value, $this->_templates[$template]['work'] );
  1594. }
  1595. return true;
  1596. }
  1597. /**
  1598. * parse global variables in the template
  1599. *
  1600. * @access private
  1601. * @param string name of the template
  1602. * @return boolean
  1603. */
  1604. function _parseGlobals($template)
  1605. {
  1606. $globalVars = $this->_globals;
  1607. $this->_applyModifers($template, $globalVars);
  1608. foreach( $globalVars as $key => $value )
  1609. {
  1610. if( is_array( $value ) )
  1611. {
  1612. continue;
  1613. }
  1614. $var = $this->_startTag.$key.$this->_endTag;
  1615. $this->_templates[$template]['result'] = str_replace( $var, $value, $this->_templates[$template]['result'] );
  1616. }
  1617. return true;
  1618. }
  1619. /**
  1620. * apply variable modifiers
  1621. *
  1622. * The variables will be passed by reference.
  1623. *
  1624. * @access private
  1625. * @param string name of the template (use modifiers from this template)
  1626. * @param array variables to which the modifiers should be applied
  1627. * @return boolean
  1628. */
  1629. function _applyModifers($template, &$vars)
  1630. {
  1631. foreach ($this->_templates[$template]['modifyVars'] as $varname => $modifier) {
  1632. if (!isset($vars[$varname])) {
  1633. continue;
  1634. }
  1635. if (($modifier['type'] === 'php' || $modifier['type'] === 'auto' ) && is_callable($modifier['mod'])) {
  1636. $vars[$varname] = call_user_func($modifier['mod'], $vars[$varname]);
  1637. continue;
  1638. }
  1639. if ($modifier['type'] === 'php') {
  1640. continue;
  1641. }
  1642. $mod = &$this->loadModule( 'Modifier', ucfirst( $modifier['mod'] ) );
  1643. $vars[$varname] = $mod->modify( $vars[$varname], $modifier['params'] );
  1644. }
  1645. // apply the default modifier
  1646. if (isset($this->_templates[$template]['attributes']['defaultmodifier'])) {
  1647. $defaultModifier = $this->_templates[$template]['attributes']['defaultmodifier'];
  1648. if (is_callable($defaultModifier)) {
  1649. $type = 'php';
  1650. } else {
  1651. $type = 'custom';
  1652. $defaultModifier = &$this->loadModule('Modifier', ucfirst($defaultModifier));
  1653. }
  1654. foreach (array_keys($vars) as $varname) {
  1655. if (isset($this->_templates[$template]['modifyVars'][$varname])) {
  1656. continue;
  1657. }
  1658. if ($type === 'php') {
  1659. $vars[$varname] = call_user_func($defaultModifier, $vars[$varname]);
  1660. } else {
  1661. $vars[$varname] = $defaultModifier->modify($vars[$varname], array());
  1662. }
  1663. }
  1664. }
  1665. return true;
  1666. }
  1667. /**
  1668. * parse all dependencies in a template
  1669. *
  1670. * @access private
  1671. * @param string
  1672. */
  1673. function _parseDependencies($template)
  1674. {
  1675. $countDep = count( $this->_templates[$template]['currentDependencies'] );
  1676. for ($i = 0; $i < $countDep; $i++) {
  1677. $depTemplate = $this->_templates[$template]['currentDependencies'][$i];
  1678. if ($depTemplate == $template) {
  1679. return patErrorManager::raiseError(PATTEMPLATE_ERROR_RECURSION, 'You have an error in your template "' . $template . '", which leads to recursion');
  1680. }
  1681. $this->parseTemplate($depTemplate);
  1682. $var = $this->_startTag.'TMPL:'.strtoupper( $depTemplate) .$this->_endTag;
  1683. $this->_templates[$template]['work'] = str_replace( $var, $this->_templates[$depTemplate]['result'], $this->_templates[$template]['work'] );
  1684. }
  1685. return true;
  1686. }
  1687. /**
  1688. * fetch plain template
  1689. *
  1690. * The template content will be stored in the template
  1691. * configuration so it can be used by other
  1692. * methods.
  1693. *
  1694. * @access private
  1695. * @param string template name
  1696. * @return boolean
  1697. */
  1698. function _fetchTemplate( $template )
  1699. {
  1700. switch( $this->_templates[$template]['attributes']['type'] )
  1701. {
  1702. /**
  1703. * condition template
  1704. */
  1705. case 'condition':
  1706. $value = $this->_getConditionValue($template, $this->_templates[$template]['attributes']['conditionvar']);
  1707. if ($value === false) {
  1708. $this->_templates[$template]['work'] = '';
  1709. $this->_templates[$template]['currentDependencies'] = array();
  1710. } else {
  1711. $this->_templates[$template]['work'] = $this->_templates[$template]['subtemplates'][$value]['data'];
  1712. $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['subtemplates'][$value]['dependencies'];
  1713. }
  1714. break;
  1715. /**
  1716. * condition template
  1717. */
  1718. case 'simplecondition':
  1719. foreach( $this->_templates[$template]['attributes']['requiredvars'] as $var )
  1720. {
  1721. // different template scope
  1722. if( $var[0] !== $template ) {
  1723. $this->_fetchVariables($var[0]);
  1724. }
  1725. $value = null;
  1726. // fetch the local variable
  1727. if( isset( $this->_templates[$var[0]]['vars'][$var[1]] )
  1728. && strlen( $this->_templates[$var[0]]['vars'][$var[1]] ) > 0 ) {
  1729. $value = $this->_templates[$var[0]]['vars'][$var[1]];
  1730. }
  1731. if (isset($this->_templates[$template]['attributes']['useglobals'])) {
  1732. if(isset($this->_globals[$var[1]]) && strlen($this->_globals[$var[1]]) > 1) {
  1733. $value = $this->_globals[$var[1]];
  1734. }
  1735. }
  1736. if ($value !== null) {
  1737. if ($var[2] === null) {
  1738. continue;
  1739. } else {
  1740. // Joomla! addition 23-June-2005
  1741. // value wrapped in ## uses regex for comparison
  1742. $condition = $var[2];
  1743. if (substr( $condition, 0, 1 ) == '#' && substr( $condition, -1, 1 ) == '#' ) {
  1744. if (preg_match( $condition, $value )) {
  1745. continue;
  1746. }
  1747. } else if ($condition == $value) {
  1748. continue;
  1749. }
  1750. /* Pat Original
  1751. if ($var[2] == $value) {
  1752. continue;
  1753. }
  1754. */
  1755. }
  1756. }
  1757. $this->_templates[$template]['work'] = '';
  1758. $this->_templates[$template]['currentDependencies'] = array();
  1759. break 2;
  1760. }
  1761. $this->_templates[$template]['work'] = $this->_templates[$template]['content'];
  1762. $this->_templates[$template]['currentDependencies'] = $this->_templates[$template]['dependencies'];
  1763. break;
  1764. /**
  1765. * modulo template
  1766. */
  1767. case 'modulo':
  1768. // check for empty templa…

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