PageRenderTime 49ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/includes/Opl/Opt/Class.php

https://bitbucket.org/kandsten/hitta.sverok.se
PHP | 1229 lines | 704 code | 93 blank | 432 comment | 64 complexity | c45a11d723e738dd58a21d5cfd6cc226 MD5 | raw file
Possible License(s): GPL-3.0, MIT
  1. <?php
  2. /*
  3. * OPEN POWER LIBS <http://www.invenzzia.org>
  4. *
  5. * This file is subject to the new BSD license that is bundled
  6. * with this package in the file LICENSE. It is also available through
  7. * WWW at this URL: <http://www.invenzzia.org/license/new-bsd>
  8. *
  9. * Copyright (c) Invenzzia Group <http://www.invenzzia.org>
  10. * and other contributors. See website for details.
  11. *
  12. * $Id: Class.php 272 2009-12-23 08:42:26Z zyxist $
  13. */
  14. /*
  15. * Interface definitions
  16. */
  17. interface Opt_Component_Interface
  18. {
  19. public function __construct($name = '');
  20. public function setView(Opt_View $view);
  21. public function setDatasource($data);
  22. public function set($name, $value);
  23. public function get($name);
  24. public function defined($name);
  25. public function display($attributes = array());
  26. public function processEvent($name);
  27. public function manageAttributes($tagName, Array $attributes);
  28. } // end Opt_Component_Interface;
  29. interface Opt_Block_Interface
  30. {
  31. public function setView(Opt_View $view);
  32. public function onOpen(Array $attributes);
  33. public function onClose();
  34. public function onSingle(Array $attributes);
  35. } // end Opt_Block_Interface;
  36. interface Opt_Caching_Interface
  37. {
  38. public function templateCacheStart(Opt_View $view);
  39. public function templateCacheStop(Opt_View $view);
  40. } // end Opt_Caching_Interface;
  41. interface Opt_Output_Interface
  42. {
  43. public function getName();
  44. public function render(Opt_View $view);
  45. } // end Opt_Output_Interface;
  46. interface Opt_Generator_Interface
  47. {
  48. public function generate($what);
  49. } // end Opt_Generator_Interface;
  50. /*
  51. * Class definitions
  52. */
  53. class Opt_Class extends Opl_Class
  54. {
  55. // Constants
  56. const CM_DEFAULT = 0;
  57. const CM_REBUILD = 1;
  58. const CM_PERFORMANCE = 2;
  59. const ACCESS_LOCAL = 0;
  60. const ACCESS_GLOBAL = 1;
  61. const CHOOSE_MODE = 0;
  62. const XML_MODE = 1;
  63. const QUIRKS_MODE = 2;
  64. const OPT_INSTRUCTION = 1;
  65. const OPT_NAMESPACE = 2;
  66. const OPT_FORMAT = 3;
  67. const OPT_COMPONENT = 4;
  68. const OPT_BLOCK = 5;
  69. const PHP_FUNCTION = 6;
  70. const PHP_CLASS = 7;
  71. const XML_ENTITY = 8;
  72. const VERSION = '2.0.4';
  73. const ERR_STANDARD = 6135; // E_ALL^E_NOTICE
  74. // Directory configuration
  75. public $sourceDir = NULL;
  76. public $compileDir = NULL;
  77. public $cacheDir = NULL;
  78. // Template configuration
  79. public $compileId = NULL;
  80. // Front-end configuration
  81. public $compileMode = self::CM_DEFAULT;
  82. public $charset = 'utf-8';
  83. public $contentType = 0;
  84. public $gzipCompression = true;
  85. public $headerBuffering = false;
  86. public $contentNegotiation = false;
  87. public $errorReporting = self::ERR_STANDARD;
  88. public $stdStream = 'file';
  89. public $debugConsole = false;
  90. public $allowRelativePaths = false;
  91. // Function configuration
  92. public $moneyFormat;
  93. public $numberDecimals;
  94. public $numberDecPoint;
  95. public $numberThousandSep;
  96. // Compiler configuration
  97. public $mode = self::XML_MODE;
  98. public $unicodeNames = false;
  99. public $htmlAttributes = false;
  100. public $printComments = false;
  101. public $prologRequired = true;
  102. public $stripWhitespaces = true;
  103. public $singleRootNode = true;
  104. public $basicOOP = true;
  105. public $advancedOOP = true;
  106. public $backticks = null;
  107. public $translate = null;
  108. public $strictCallbacks = true;
  109. public $htmlEntities = true;
  110. public $escape = true;
  111. public $variableAccess = self::ACCESS_LOCAL;
  112. public $defaultFormat = 'Array';
  113. // Data
  114. protected $_tf = NULL; // translation interface
  115. // Add-ons
  116. protected $_cache;
  117. protected $_instructions = array('Opt_Instruction_Section', 'Opt_Instruction_Tree',
  118. 'Opt_Instruction_Grid', 'Opt_Instruction_Selector', 'Opt_Instruction_Repeat',
  119. 'Opt_Instruction_Snippet', 'Opt_Instruction_Extend',
  120. 'Opt_Instruction_For', 'Opt_Instruction_Foreach', 'Opt_Instruction_If',
  121. 'Opt_Instruction_Put', 'Opt_Instruction_Capture', 'Opt_Instruction_Attribute',
  122. 'Opt_Instruction_Tag', 'Opt_Instruction_Root', 'Opt_Instruction_Prolog',
  123. 'Opt_Instruction_Dtd', 'Opt_Instruction_Literal', 'Opt_Instruction_Include',
  124. 'Opt_Instruction_Dynamic', 'Opt_Instruction_Component', 'Opt_Instruction_Block');
  125. protected $_functions = array(
  126. 'money' => 'Opt_Function::money', 'number' => 'Opt_Function::number', 'spacify' => 'Opt_Function::spacify',
  127. 'firstof' => 'Opt_Function::firstof', 'indent' => 'Opt_Function::indent', 'strip' => 'Opt_Function::strip',
  128. 'stripTags' => 'Opt_Function::stripTags', 'upper' => 'Opt_Function::upper', 'lower' => 'Opt_Function::lower',
  129. 'capitalize' => 'Opt_Function::capitalize', 'countWords' => 'str_word_count', 'countChars' => 'strlen',
  130. 'replace' => '#3,1,2#str_replace', 'repeat' => 'str_repeat', 'nl2br' => 'Opt_Function::nl2br', 'date' => 'date',
  131. 'regexReplace' => '#3,1,2#preg_replace', 'truncate' => 'Opt_Function::truncate', 'wordWrap' => 'Opt_Function::wordwrap',
  132. 'contains' => 'Opt_Function::contains', 'count' => 'sizeof', 'sum' => 'Opt_Function::sum', 'average' => 'Opt_Function::average',
  133. 'absolute' => 'Opt_Function::absolute', 'stddev' => 'Opt_Function::stddev', 'range' => 'Opt_Function::range',
  134. 'isUrl' => 'Opt_Function::isUrl', 'isImage' => 'Opt_Function::isImage', 'stddev' => 'Opt_Function::stddev',
  135. 'entity' => 'Opt_Function::entity', 'scalar' => 'is_scalar', 'containsKey' => 'Opt_Function::containsKey',
  136. 'cycle' => 'Opt_Function::cycle'
  137. );
  138. protected $_classes = array();
  139. protected $_components = array();
  140. protected $_blocks = array();
  141. protected $_namespaces = array(1 => 'opt', 'com', 'parse');
  142. protected $_formats = array(
  143. 'Array' => 'Opt_Format_Array',
  144. 'SingleArray' => 'Opt_Format_SingleArray',
  145. 'StaticGenerator' => 'Opt_Format_StaticGenerator',
  146. 'RuntimeGenerator' => 'Opt_Format_RuntimeGenerator',
  147. 'Objective' => 'Opt_Format_Objective');
  148. protected $_entities = array('lb' => '{', 'rb' => '}');
  149. protected $_buffers = array();
  150. // Status
  151. protected $_init = false;
  152. // Other
  153. protected $_compiler;
  154. /*
  155. * Template parsing
  156. */
  157. /**
  158. * Returns the compiler object and optionally loads the necessary classes. Unless
  159. * you develop instructions or reimplement various core features you do not have
  160. * to use this method.
  161. *
  162. * @return Opt_Compiler_Class The compiler
  163. */
  164. public function getCompiler()
  165. {
  166. if(!is_object($this->_compiler))
  167. {
  168. $this->_compiler = new Opt_Compiler_Class($this);
  169. }
  170. return $this->_compiler;
  171. } // end getCompiler();
  172. /*
  173. * Extensions and configuration
  174. */
  175. /**
  176. * Performs the main initialization of OPT. If the optional argument `$config` is
  177. * specified, it is transparently sent to Opt_Class::loadConfig(). Before using this
  178. * method, we are obligated to configure the library and load the necessary extensions.
  179. *
  180. * @param mixed $config = null The optional configuration to be loaded
  181. */
  182. public function setup($config = null)
  183. {
  184. if(is_array($config))
  185. {
  186. $this->loadConfig($config);
  187. }
  188. if(!is_null($this->pluginDir))
  189. {
  190. $this->loadPlugins();
  191. }
  192. if(Opl_Registry::exists('opl_translate'))
  193. {
  194. $this->setTranslationInterface(Opl_Registry::get('opl_translate'));
  195. }
  196. if(Opl_Registry::getState('opl_debug_console') || $this->debugConsole)
  197. {
  198. $this->debugConsole = true;
  199. Opt_Support::initDebugConsole($this);
  200. }
  201. // Check paths etc.
  202. if(is_string($this->sourceDir))
  203. {
  204. $this->sourceDir = array('file' => $this->sourceDir);
  205. }
  206. foreach($this->sourceDir as &$path)
  207. {
  208. $this->_securePath($path);
  209. }
  210. $this->_securePath($this->compileDir);
  211. $this->_init = true;
  212. } // end setup();
  213. /**
  214. * Registers a new add-on in OPT identified by `$type`. The type is identified
  215. * by the appropriate Opt_Class constant. The semantics of the next arguments
  216. * depends on the registered add-on.
  217. *
  218. * Note that you may register several add-ons at the same time by passing an
  219. * array as the second argument.
  220. *
  221. * @param int $type The type of registered item(s).
  222. * @param mixed $item The item or a list of items to be registered
  223. * @param mixed $addon = null Used in several types of add-ons
  224. * @return void
  225. */
  226. public function register($type, $item, $addon = null)
  227. {
  228. if($this->_init)
  229. {
  230. throw new Opt_Initialization_Exception($this->_init, 'register an item');
  231. }
  232. $map = array(1 => '_instructions', '_namespaces', '_formats', '_components', '_blocks', '_functions', '_classes', '_entities');
  233. $whereto = $map[$type];
  234. // Massive registration
  235. if(is_array($item))
  236. {
  237. $this->$whereto = array_merge($this->$whereto, $item);
  238. return;
  239. }
  240. switch($type)
  241. {
  242. case self::OPT_FORMAT:
  243. if($addon === null)
  244. {
  245. $addon = 'Opt_Format_'.$item;
  246. }
  247. $a = &$this->$whereto;
  248. $a[$item] = $addon;
  249. break;
  250. case self::OPT_INSTRUCTION:
  251. if($addon === null)
  252. {
  253. $addon = 'Opt_Instruction_'.$item;
  254. }
  255. $a = &$this->$whereto;
  256. $a[$item] = $addon;
  257. break;
  258. case self::OPT_NAMESPACE:
  259. $a = &$this->$whereto;
  260. $a[] = $item;
  261. break;
  262. default:
  263. if($addon === null)
  264. {
  265. throw new BadMethodCallException('Missing argument 3 for Opt_Class::register()');
  266. }
  267. $a = &$this->$whereto;
  268. $a[$item] = $addon;
  269. }
  270. } // end register();
  271. /**
  272. * Registers a new translation interface to be used in templates. The translation
  273. * interface must implement Opl_Translation_Interface. If the specified parameter
  274. * is not a valid translation interface, the method unregisters the already set one
  275. * and returns false.
  276. *
  277. * @param Opl_Translation_Interface $tf The translation interface or "null".
  278. * @return boolean True, if the translation interface was properly set.
  279. */
  280. public function setTranslationInterface($tf)
  281. {
  282. if(!$tf instanceof Opl_Translation_Interface)
  283. {
  284. $this->_tf = null;
  285. return false;
  286. }
  287. $this->_tf = $tf;
  288. return true;
  289. } // end setTranslationInterface();
  290. /**
  291. * Returns the current translation interface assigned to OPT.
  292. *
  293. * @return Opl_Translation_Interface The translation interface.
  294. */
  295. public function getTranslationInterface()
  296. {
  297. return $this->_tf;
  298. } // end getTranslationInterface();
  299. /**
  300. * Sets the global caching system to use in all the views.
  301. *
  302. * @param Opt_Caching_Interface $cache=null The caching interface
  303. */
  304. public function setCache(Opt_Caching_Interface $cache = null)
  305. {
  306. $this->_cache = $cache;
  307. } // end setCache();
  308. /**
  309. * Returns the current global caching system.
  310. *
  311. * @return Opt_Caching_Interface
  312. */
  313. public function getCache()
  314. {
  315. return $this->_cache;
  316. } // end getCache();
  317. /**
  318. * An implementation of advisory output buffering which allows us
  319. * to tell us, whether another part of the script opened the requested
  320. * buffer.
  321. *
  322. * @param String $buffer The buffer name
  323. * @param Boolean $state The new buffer state: true to open, false to close.
  324. */
  325. public function setBufferState($buffer, $state)
  326. {
  327. if($state)
  328. {
  329. if(!isset($this->_buffers[$buffer]))
  330. {
  331. $this->_buffers[$buffer] = 1;
  332. }
  333. else
  334. {
  335. $this->_buffers[$buffer]++;
  336. }
  337. }
  338. else
  339. {
  340. if(isset($this->_buffers[$buffer]) && $this->_buffers[$buffer] > 0)
  341. {
  342. $this->_buffers[$buffer]--;
  343. }
  344. }
  345. } // end setBufferState();
  346. /**
  347. * Returns the state of the specified output buffer.
  348. *
  349. * @param String $buffer Buffer name
  350. * @return Boolean
  351. */
  352. public function getBufferState($buffer)
  353. {
  354. if(!isset($this->_buffers[$buffer]))
  355. {
  356. return false;
  357. }
  358. return ($this->_buffers[$buffer] > 0);
  359. } // end getBufferState();
  360. /*
  361. * Internal use
  362. */
  363. /**
  364. * Allows the read access to some of the internal structures for the
  365. * template compiler.
  366. *
  367. * @internal
  368. * @param string $name The structure to be returned.
  369. * @return array The returned structure.
  370. */
  371. public function _getList($name)
  372. {
  373. static $list;
  374. if(is_null($list))
  375. {
  376. $list = array('_instructions', '_namespaces', '_formats', '_components', '_blocks', '_functions', '_classes', '_tf', '_entities');
  377. }
  378. if(in_array($name, $list))
  379. {
  380. return $this->$name;
  381. }
  382. return NULL;
  383. } // end _getList();
  384. /**
  385. * The helper function for the plugin subsystem. It returns the
  386. * PHP code that loads the specified plugin.
  387. *
  388. * @internal
  389. * @param String $directory The plugin directory
  390. * @param SplFileInfo $file The loaded file
  391. * @return String
  392. */
  393. protected function _pluginLoader($directory, SplFileInfo $file)
  394. {
  395. $ns = explode('.', $file->getFilename());
  396. switch($ns[0])
  397. {
  398. case 'instruction':
  399. return 'Opl_Loader::mapAbsolute(\'Opt_Instruction_'.$ns[1].'\', \''.$directory.$file->getFilename().'\'); $this->register(Opt_Class::OPT_INSTRUCTION, \''.$ns[1].'\'); ';
  400. case 'format':
  401. return 'Opl_Loader::mapAbsolute(\'Opt_Format_'.$ns[1].'\', \''.$directory.$file->getFilename().'\'); $this->register(Opt_Class::OPT_FORMAT, \''.$ns[1].'\'); ';
  402. default:
  403. return ' require(\''.$directory.$file->getFilename().'\'); ';
  404. }
  405. } // end _pluginLoader();
  406. /**
  407. * Parses the stream in the template path name and returns
  408. * the real path.
  409. *
  410. * @internal
  411. * @param String $name Template filename
  412. * @return String
  413. */
  414. public function _stream($name)
  415. {
  416. if(strpos($name, ':') !== FALSE)
  417. {
  418. // We get the stream ID from the given filename.
  419. $data = explode(':', $name);
  420. if(!isset($this->sourceDir[$data[0]]))
  421. {
  422. throw new Opt_ObjectNotExists_Exception('resource', $data[0]);
  423. }
  424. if(!$this->allowRelativePaths && strpos($data[1], '../') !== false)
  425. {
  426. throw new Opt_NotSupported_Exception('relative paths', $data[1]);
  427. }
  428. return $this->sourceDir[$data[0]].$data[1];
  429. }
  430. // Here, the standard stream is used.
  431. if(!isset($this->sourceDir[$this->stdStream]))
  432. {
  433. throw new Opt_ObjectNotExists_Exception('resource', $this->stdStream);
  434. }
  435. if(!$this->allowRelativePaths && strpos($name, '../') !== false)
  436. {
  437. throw new Opt_NotSupported_Exception('relative paths', $name);
  438. }
  439. return $this->sourceDir[$this->stdStream].$name;
  440. } // end _stream();
  441. /**
  442. * Loads the template source code. Returns the template body or
  443. * the array with two (false) values in case of problems.
  444. *
  445. * @internal
  446. * @param String $filename The template filename
  447. * @param Boolean $exception Do we inform about the problems with exception?
  448. * @return String|Array
  449. */
  450. public function _getSource($filename, $exception = true)
  451. {
  452. $item = $this->_stream($filename);
  453. if(!file_exists($item))
  454. {
  455. if(!$exception)
  456. {
  457. return array(false, false);
  458. }
  459. throw new Opt_TemplateNotFound_Exception($item);
  460. }
  461. return file_get_contents($item);
  462. } // end _getSource();
  463. /**
  464. * The class constructor - registers the main object in the
  465. * OPL registry.
  466. */
  467. public function __construct()
  468. {
  469. Opl_Registry::register('opt', $this);
  470. } // end __construct();
  471. /**
  472. * The destructor. Clears the output buffers and optionally
  473. * displays the debug console.
  474. */
  475. public function __destruct()
  476. {
  477. if(ob_get_level() > 0)
  478. {
  479. while(@ob_end_flush());
  480. }
  481. if($this->debugConsole)
  482. {
  483. try
  484. {
  485. Opt_Support::updateTimers();
  486. Opl_Debug_Console::display();
  487. }
  488. catch(Opl_Exception $e)
  489. {
  490. die('<div style="background: #f77777;">Opt_Class destructor exception: '.$e->getMessage().'</div>');
  491. }
  492. }
  493. } // end __destruct();
  494. } // end Opt_Class;
  495. /**
  496. * The main view class.
  497. */
  498. class Opt_View
  499. {
  500. const VAR_LOCAL = false;
  501. const VAR_GLOBAL = true;
  502. private $_tpl;
  503. private $_template;
  504. private $_formatInfo = array();
  505. private $_inheritance = array();
  506. private $_cplInheritance = array();
  507. private $_data = array();
  508. private $_tf;
  509. private $_processingTime = null;
  510. private $_branch = null;
  511. private $_cache = null;
  512. private $_mode;
  513. private $_outputBuffer = array();
  514. static private $_vars = array();
  515. static private $_capture = array();
  516. static private $_global = array();
  517. static private $_globalFormatInfo = array();
  518. /**
  519. * Creates a new view object. The optional argument, $template
  520. * may specify the template to be associated with this view.
  521. * Please note that if you do not specify the template here,
  522. * you have to do this manually later using Opt_View::setTemplate()
  523. * method.
  524. *
  525. * @param string $template The template file.
  526. */
  527. public function __construct($template = '')
  528. {
  529. $this->_tpl = Opl_Registry::get('opt');
  530. $this->_template = $template;
  531. $this->_mode = $this->_tpl->mode;
  532. $this->_cache = $this->_tpl->getCache();
  533. } // end __construct();
  534. /**
  535. * Associates a template file to the view.
  536. *
  537. * @param string $file The template file.
  538. */
  539. public function setTemplate($file)
  540. {
  541. $this->_template = $file;
  542. } // end setTemplate();
  543. /**
  544. * Returns a template associated with this view.
  545. *
  546. * @return string The template filename.
  547. */
  548. public function getTemplate()
  549. {
  550. return $this->_template;
  551. } // end getTemplate();
  552. /**
  553. * Sets the template mode (XML, Quirks, etc...)
  554. *
  555. * @param Int $mode The new mode
  556. */
  557. public function setMode($mode)
  558. {
  559. $this->_mode = $mode;
  560. } // end setMode();
  561. /**
  562. * Gets the current template mode.
  563. *
  564. * @return Int
  565. */
  566. public function getMode()
  567. {
  568. return $this->_mode;
  569. } // end getMode();
  570. /**
  571. * Sets a template inheritance branch that will be used
  572. * in this view. If you want to disable branching, set
  573. * the argument to NULL.
  574. *
  575. * @param string $branch The branch name.
  576. */
  577. public function setBranch($branch)
  578. {
  579. $this->_branch = $branch;
  580. } // end setBranch();
  581. /**
  582. * Returns a branch used in the template inheritance.
  583. *
  584. * @return string The branch name.
  585. */
  586. public function getBranch()
  587. {
  588. return $this->_branch;
  589. } // end getBranch();
  590. /**
  591. * Returns the view processing time for the debug purposes.
  592. * The processing time is calculated only if the debug mode
  593. * is enabled.
  594. *
  595. * @return float The processing time.
  596. */
  597. public function getTime()
  598. {
  599. return $this->_processingTime;
  600. } // end getTime();
  601. /*
  602. * Data management
  603. */
  604. /**
  605. * Creates a new local template variable.
  606. *
  607. * @param string $name The variable name.
  608. * @param mixed $value The variable value.
  609. */
  610. public function __set($name, $value)
  611. {
  612. $this->_data[$name] = $value;
  613. } // end __set();
  614. /**
  615. * Creates a new local template variable.
  616. *
  617. * @param string $name The variable name.
  618. * @param mixed $value The variable value.
  619. */
  620. public function assign($name, $value)
  621. {
  622. $this->_data[$name] = $value;
  623. } // end assign();
  624. /**
  625. * Creates a group of local template variables
  626. * using an associative array, where the keys are
  627. * the variable names.
  628. *
  629. * @param array $vars A list of variables.
  630. */
  631. public function assignGroup($values)
  632. {
  633. $this->_data = array_merge($this->_data, $values);
  634. } // end assignGroup();
  635. /**
  636. * Creates a new local template variable with
  637. * the value assigned by reference.
  638. *
  639. * @param string $name The variable name.
  640. * @param mixed &$value The variable value.
  641. */
  642. public function assignRef($name, &$value)
  643. {
  644. $this->_data[$name] = &$value;
  645. } // end assignRef();
  646. /**
  647. * Returns the value of a template variable or
  648. * null, if the variable does not exist.
  649. *
  650. * @param string $name The variable name.
  651. * @return mixed The variable value or NULL.
  652. */
  653. public function get($name)
  654. {
  655. if(!isset($this->_data[$name]))
  656. {
  657. return null;
  658. }
  659. return $this->_data[$name];
  660. } // end read();
  661. /**
  662. * Returns the value of a local template variable or
  663. * null, if the variable does not exist.
  664. *
  665. * @param string $name The variable name.
  666. * @return mixed The variable value or NULL.
  667. */
  668. public function __get($name)
  669. {
  670. if(!isset($this->_data[$name]))
  671. {
  672. return null;
  673. }
  674. return $this->_data[$name];
  675. } // end __get();
  676. /**
  677. * Returns TRUE, if the local template variable with the
  678. * specified name is defined.
  679. *
  680. * @param string $name The variable name.
  681. * @return boolean True, if the variable is defined.
  682. */
  683. public function defined($name)
  684. {
  685. return isset($this->_data[$name]);
  686. } // end defined();
  687. /**
  688. * Returns TRUE, if the local template variable with the
  689. * specified name is defined.
  690. *
  691. * @param string $name The variable name.
  692. * @return boolean True, if the variable is defined.
  693. */
  694. public function __isset($name)
  695. {
  696. return isset($this->_data[$name]);
  697. } // end __isset();
  698. /**
  699. * Removes a local template variable with the specified name.
  700. *
  701. * @param string $name The variable name.
  702. * @return boolean True, if the variable has been removed.
  703. */
  704. public function remove($name)
  705. {
  706. if(isset($this->_data[$name]))
  707. {
  708. unset($this->_data[$name]);
  709. if(isset($this->_formatInfo[$name]))
  710. {
  711. unset($this->_formatInfo[$name]);
  712. }
  713. return true;
  714. }
  715. return false;
  716. } // end remove();
  717. /**
  718. * Removes a local template variable with the specified name.
  719. *
  720. * @param string $name The variable name.
  721. * @return boolean True, if the variable has been removed.
  722. */
  723. public function __unset($name)
  724. {
  725. return $this->remove($name);
  726. } // end __unset();
  727. /**
  728. * Creates a new global template variable.
  729. *
  730. * @static
  731. * @param string $name The variable name.
  732. * @param mixed $value The variable value.
  733. */
  734. static public function assignGlobal($name, $value)
  735. {
  736. self::$_global[$name] = $value;
  737. } // end assignGlobal();
  738. /**
  739. * Creates a group of global template variables
  740. * using an associative array, where the keys are
  741. * the variable names.
  742. *
  743. * @static
  744. * @param array $vars A list of variables.
  745. */
  746. static public function assignGroupGlobal($values)
  747. {
  748. self::$_global = array_merge(self::$_global, $values);
  749. } // end assignGroupGlobal();
  750. /**
  751. * Creates a new global template variable with
  752. * the value assigned by reference.
  753. *
  754. * @static
  755. * @param string $name The variable name.
  756. * @param mixed &$value The variable value.
  757. */
  758. static public function assignRefGlobal($name, &$value)
  759. {
  760. self::$_global[$name] = &$value;
  761. } // end assignRefGlobal();
  762. /**
  763. * Returns TRUE, if the global template variable with the
  764. * specified name is defined.
  765. *
  766. * @static
  767. * @param string $name The variable name.
  768. * @return boolean True, if the variable is defined.
  769. */
  770. static public function definedGlobal($name)
  771. {
  772. return isset(self::$_global[$name]);
  773. } // end definedGlobal();
  774. /**
  775. * Returns the value of a global template variable or
  776. * null, if the variable does not exist.
  777. *
  778. * @static
  779. * @param string $name The variable name.
  780. * @return mixed The variable value or NULL.
  781. */
  782. static public function getGlobal($name)
  783. {
  784. if(!isset(self::$_global[$name]))
  785. {
  786. return null;
  787. }
  788. return self::$_global[$name];
  789. } // end getGlobal();
  790. /**
  791. * Removes a global template variable with the specified name.
  792. *
  793. * @static
  794. * @param string $name The variable name.
  795. * @return boolean True, if the variable has been removed.
  796. */
  797. static public function removeGlobal($name)
  798. {
  799. if(isset(self::$_global[$name]))
  800. {
  801. unset(self::$_global[$name]);
  802. return true;
  803. }
  804. return false;
  805. } // end removeGlobal();
  806. /**
  807. * Clears all the possible static private buffers.
  808. */
  809. static public function clear()
  810. {
  811. self::$_vars = array();
  812. self::$_capture = array();
  813. self::$_global = array();
  814. self::$_globalFormatInfo = array();
  815. } // end clear();
  816. /**
  817. * Returns the value of the internal template variable or
  818. * NULL if it does not exist.
  819. *
  820. * @param string $name The internal variable name.
  821. * @return mixed The variable value or NULL.
  822. */
  823. public function getTemplateVar($name)
  824. {
  825. if(!isset(self::$_vars[$name]))
  826. {
  827. return null;
  828. }
  829. return self::$_vars[$name];
  830. } // end getTemplateVar();
  831. /**
  832. * Sets the specified data format for the identifier that may
  833. * identify a template variable or some other things. The details
  834. * are explained in the OPT user manual.
  835. *
  836. * @param string $item The item name
  837. * @param string $format The format to be used for the specified item.
  838. */
  839. public function setFormat($item, $format)
  840. {
  841. $this->_formatInfo[$item] = $format;
  842. } // end setFormat();
  843. /**
  844. * Sets the specified data format for the identifier that may
  845. * identify a global template variable or some other things. The details
  846. * are explained in the OPT user manual.
  847. *
  848. * @static
  849. * @param string $item The item name
  850. * @param string $format The format to be used for the specified item.
  851. * @param boolean $global Does it register the item in the "global." group?
  852. */
  853. static public function setFormatGlobal($item, $format, $global = true)
  854. {
  855. if($global)
  856. {
  857. self::$_globalFormatInfo['global.'.$item] = $format;
  858. }
  859. else
  860. {
  861. self::$_globalFormatInfo[$item] = $format;
  862. }
  863. } // end setFormatGlobal();
  864. /**
  865. * Sets the caching interface that should be used with this view.
  866. *
  867. * @param Opt_Caching_Interface $iface The caching interface
  868. */
  869. public function setCache(Opt_Caching_Interface $iface = null)
  870. {
  871. $this->_cache = $iface;
  872. } // end setCache();
  873. /**
  874. * Returns the caching interface used with this view
  875. *
  876. * @return Opt_Caching_Interface
  877. */
  878. public function getCache()
  879. {
  880. return $this->_cache;
  881. } // end getCache();
  882. /**
  883. * A method for caching systems that tells, whether there is some
  884. * dynamic content available in the captured part.
  885. *
  886. * @return Boolean
  887. */
  888. public function hasDynamicContent()
  889. {
  890. return sizeof($this->_outputBuffer) > 0;
  891. } // end hasDynamicContent();
  892. /**
  893. * Returns the static parts of the cached template, if the opt:dynamic
  894. * is used. Please note that the returned array does not contain the
  895. * last buffer, which must be closed and retrieved manually with
  896. * ob_get_flush().
  897. *
  898. * @return Array
  899. */
  900. public function getOutputBuffers()
  901. {
  902. return $this->_outputBuffer;
  903. } // end getBuffers();
  904. /*
  905. * Dynamic inheritance
  906. */
  907. /**
  908. * Creates a dynamic template inheritance between the templates in the view.
  909. * There are two possible uses of the method. If you specify only the one
  910. * argument, the method will extend the main view template with the specified
  911. * template.
  912. *
  913. * The two arguments can be used to extend other templates in the inheritance
  914. * chain. In this case the first argument specifies the template that is going
  915. * to extend something, and the second one - the extended template.
  916. *
  917. * @param string $source The extending template or the extended template in case of one-argument call.
  918. * @param string $destination The extended template.
  919. */
  920. public function inherit($source, $destination = null)
  921. {
  922. if(is_null($destination))
  923. {
  924. $this->_inheritance[$this->_template] = str_replace(array('/', ':', '\\'), '__', $source);
  925. $this->_cplInheritance[$this->_template] = $source;
  926. return;
  927. }
  928. $this->_inheritance[$source] = str_replace(array('/', ':', '\\'), '__',$destination);
  929. $this->_cplInheritance[$source] = $destination;
  930. } // end inherit();
  931. /*
  932. * Internal use
  933. */
  934. /**
  935. * Executes, and optionally compiles the template represented by the view.
  936. * Returns true, if the template was found and successfully executed.
  937. *
  938. * @param Opt_Output_Interface $output The output interface.
  939. * @param Boolean $exception Should the exceptions be thrown if the template does not exist?
  940. * @return Boolean
  941. */
  942. public function _parse(Opt_Output_Interface $output, $exception = true)
  943. {
  944. if($this->_tpl->debugConsole)
  945. {
  946. $time = microtime(true);
  947. }
  948. $cached = false;
  949. if(!is_null($this->_cache))
  950. {
  951. $result = $this->_cache->templateCacheStart($this);
  952. if($result !== false)
  953. {
  954. // For dynamic cache...
  955. if(is_string($result))
  956. {
  957. include($result);
  958. }
  959. return true;
  960. }
  961. $cached = true;
  962. }
  963. $this->_tf = $this->_tpl->getTranslationInterface();
  964. if($this->_tpl->compileMode != Opt_Class::CM_PERFORMANCE)
  965. {
  966. list($compileName, $compileTime) = $this->_preprocess($exception);
  967. if(is_null($compileName))
  968. {
  969. return false;
  970. }
  971. }
  972. else
  973. {
  974. $compileName = $this->_convert($this->_template);
  975. $compileTime = null;
  976. if(!$exception && !file_exists($compileName))
  977. {
  978. return false;
  979. }
  980. }
  981. $old = error_reporting($this->_tpl->errorReporting);
  982. require($this->_tpl->compileDir.$compileName);
  983. error_reporting($old);
  984. // The counter stops, if the time counting has been enabled for the debug console purposes
  985. if(!is_null($this->_cache))
  986. {
  987. $this->_cache->templateCacheStop($this);
  988. }
  989. if(isset($time))
  990. {
  991. Opt_Support::addView($this->_template, $output->getName(), $this->_processingTime = microtime(true) - $time, $cached);
  992. }
  993. return true;
  994. } // end _parse();
  995. /**
  996. * The method checks whether the template exists and if it was modified by
  997. * the template designer. In the second case, it loads and runs the template
  998. * compiler to produce a new version. Returns an array with the template data:
  999. * - Compiled template name
  1000. * - Compilation time
  1001. * They are needed by the template execution system or template inheritance. In
  1002. * case of problems, the array contains two NULL values.
  1003. *
  1004. * @internal
  1005. * @param Boolean $exception Do we inform about unexisting template with exceptions?
  1006. * @return Array
  1007. */
  1008. protected function _preprocess($exception = true)
  1009. {
  1010. $item = $this->_tpl->_stream($this->_template);
  1011. $compiled = $this->_convert($this->_template);
  1012. $compileTime = @filemtime($this->_tpl->compileDir.$compiled);
  1013. $result = NULL;
  1014. // Here the "rebuild" compilation mode is processed
  1015. if($this->_tpl->compileMode == Opt_Class::CM_REBUILD)
  1016. {
  1017. if(!file_exists($item))
  1018. {
  1019. if(!$exception)
  1020. {
  1021. return array(NULL, NULL);
  1022. }
  1023. throw new Opt_TemplateNotFound_Exception($item);
  1024. }
  1025. $result = file_get_contents($item);
  1026. }
  1027. else
  1028. {
  1029. // Otherwise, we perform a modification test.
  1030. $rootTime = @filemtime($item);
  1031. if($rootTime === false)
  1032. {
  1033. if(!$exception)
  1034. {
  1035. return array(NULL, NULL);
  1036. }
  1037. throw new Opt_TemplateNotFound_Exception($item);
  1038. }
  1039. if($compileTime === false || $compileTime < $rootTime)
  1040. {
  1041. $result = file_get_contents($item);
  1042. }
  1043. }
  1044. if(is_null($result))
  1045. {
  1046. return array($compiled, $compileTime);
  1047. }
  1048. $compiler = $this->_tpl->getCompiler();
  1049. $compiler->setInheritance($this->_cplInheritance);
  1050. $compiler->setFormatList(array_merge($this->_formatInfo, self::$_globalFormatInfo));
  1051. $compiler->set('branch', $this->_branch);
  1052. $compiler->compile($result, $this->_template, $compiled, $this->_mode);
  1053. return array($compiled, $compileTime);
  1054. } // end _preprocess();
  1055. /**
  1056. * This method is used by the template with the template inheritance. It
  1057. * allows to check, whether one of the templates on the dependency list
  1058. * has been modified. The method takes the compilation time of the compiled
  1059. * template and the list of the source template names that it depends on.
  1060. *
  1061. * Returns true, if one if the templates is newer than the compilation time.
  1062. *
  1063. * @param Int $compileTime Compiled template creation time.
  1064. * @param Array $templates The list of dependencies
  1065. * @return Boolean
  1066. */
  1067. protected function _massPreprocess($compileTime, $templates)
  1068. {
  1069. switch($this->_tpl->compileMode)
  1070. {
  1071. case Opt_Class::CM_PERFORMANCE:
  1072. case Opt_Class::CM_REBUILD:
  1073. return false; // We return false even here, because the compilation has already been done in _parse()
  1074. case Opt_Class::CM_DEFAULT:
  1075. $cnt = sizeof($templates);
  1076. // $templates = array();
  1077. // TODO: Check whether the object as array key works :P
  1078. for($i = 0; $i < $cnt; $i++)
  1079. {
  1080. $templates[$i] = $this->_tpl->_stream($templates[$i]);
  1081. $time = @filemtime($templates[$i]);
  1082. if(is_null($time))
  1083. {
  1084. throw new Opt_TemplateNotFound_Exception($templates[$i]);
  1085. }
  1086. if($time >= $compileTime)
  1087. {
  1088. return true;
  1089. }
  1090. }
  1091. return false;
  1092. }
  1093. } // end _massPreprocess();
  1094. /**
  1095. * Converts the source template file name to the compiled
  1096. * template file name.
  1097. *
  1098. * @internal
  1099. * @param String $filename The source file name
  1100. * @return String
  1101. */
  1102. public function _convert($filename)
  1103. {
  1104. $list = array();
  1105. if(sizeof($this->_inheritance) > 0)
  1106. {
  1107. $list = $this->_inheritance;
  1108. sort($list);
  1109. }
  1110. $list[] = str_replace(array('/', ':', '\\'), '__', $filename);
  1111. if(!is_null($this->_tpl->compileId))
  1112. {
  1113. return $this->_tpl->compileId.'_'.implode('/', $list).'.php';
  1114. }
  1115. return implode('/', $list).'.php';
  1116. } // end _convert();
  1117. /**
  1118. * Compiles the specified template and returns the current
  1119. * time.
  1120. *
  1121. * @internal
  1122. * @param String $filename The file name.
  1123. * @return Integer
  1124. */
  1125. public function _compile($filename)
  1126. {
  1127. $compiled = $this->_convert($filename);
  1128. $compiler = $this->_tpl->getCompiler();
  1129. $compiler->setInheritance($this->_cplInheritance);
  1130. $compiler->setFormatList(array_merge($this->_formatInfo, self::$_globalFormatInfo));
  1131. $compiler->set('branch', $this->_branch);
  1132. $compiler->compile($this->_tpl->_getSource($filename), $filename, $compiled, $this->_mode);
  1133. return time();
  1134. } // end _compile();
  1135. } // end Opt_View;