Location: PHPKode > projects > Open Power Template > lib/Opt/Class.php
<?php
/*
 *  OPEN POWER LIBS <http://www.invenzzia.org>
 *
 * This file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE. It is also available through
 * WWW at this URL: <http://www.invenzzia.org/license/new-bsd>
 *
 * Copyright (c) Invenzzia Group <http://www.invenzzia.org>
 * and other contributors. See website for details.
 *
 */

	/*
	 * Interface definitions
	 */
	interface Opt_Component_Interface
	{
		public function __construct($name = '');
		public function setView(Opt_View $view);
		public function setDatasource($data);

		public function set($name, $value);
		public function get($name);
		public function defined($name);

		public function display($attributes = array());
		public function processEvent($name);
		public function manageAttributes($tagName, Array $attributes);
	} // end Opt_Component_Interface;
	
	interface Opt_Block_Interface
	{
		public function setView(Opt_View $view);
		public function onOpen(Array $attributes);
		public function onClose();
		public function onSingle(Array $attributes);
	} // end Opt_Block_Interface;
	
	interface Opt_Caching_Interface
	{
		public function templateCacheStart(Opt_View $view);
		public function templateCacheStop(Opt_View $view);
	} // end Opt_Caching_Interface;
	
	interface Opt_Output_Interface
	{
		public function getName();
		public function render(Opt_View $view);
	} // end Opt_Output_Interface;

	interface Opt_Generator_Interface
	{
		public function generate($what);
	} // end Opt_Generator_Interface;
	
	/*
	 * Class definitions
	 */

	class Opt_Class extends Opl_Class
	{
		// Constants
		const CM_DEFAULT = 0;
		const CM_REBUILD = 1;
		const CM_PERFORMANCE = 2;
		
		const ACCESS_LOCAL = 0;
		const ACCESS_GLOBAL = 1;
		
		const CHOOSE_MODE = 0;
		const XML_MODE = 1;
		const QUIRKS_MODE = 2;

		const OPT_INSTRUCTION = 1;
		const OPT_NAMESPACE = 2;
		const OPT_FORMAT = 3;
		const OPT_COMPONENT = 4;
		const OPT_BLOCK = 5;
		const PHP_FUNCTION = 6;
		const PHP_CLASS = 7;
		const XML_ENTITY = 8;
	
		const VERSION = '2.0.6';
		const ERR_STANDARD = 6135; // E_ALL^E_NOTICE
	
		// Directory configuration
		public $sourceDir = NULL;
		public $compileDir = NULL;
		public $cacheDir = NULL;

		// Template configuration
		public $compileId = NULL;

		// Front-end configuration
		public $compileMode = self::CM_DEFAULT;
		public $charset = 'utf-8';
		public $contentType = 0;
		public $gzipCompression = true;
		public $headerBuffering = false;
		public $contentNegotiation = false;
		public $errorReporting = self::ERR_STANDARD;
		public $stdStream = 'file';
		public $debugConsole = false;
		public $allowRelativePaths = false;

		// Function configuration
		public $moneyFormat;
		public $numberDecimals;
		public $numberDecPoint;
		public $numberThousandSep;
		public $pluralForms = array(
			'%d == 1' => 0,
			'%d' => 1
		);

		// Compiler configuration
		public $mode = self::XML_MODE;
		public $unicodeNames = false;
		public $htmlAttributes = false;
		public $printComments = false;
		public $prologRequired = true;
		public $stripWhitespaces = true;
		public $singleRootNode = true;
		public $basicOOP = true;
		public $advancedOOP = true;
		public $backticks = null;
		public $translate = null;
		public $strictCallbacks = true;
		public $htmlEntities = true;
		public $escape = true;
		public $variableAccess = self::ACCESS_LOCAL;
		public $defaultFormat = 'Array';

		// Data
		protected $_tf = NULL;	// translation interface
		
		// Add-ons
		protected $_cache;

		protected $_instructions = array('Opt_Instruction_Section', 'Opt_Instruction_Tree',
			'Opt_Instruction_Grid', 'Opt_Instruction_Selector', 'Opt_Instruction_Repeat',
			'Opt_Instruction_Snippet', 'Opt_Instruction_Extend',
			'Opt_Instruction_For', 'Opt_Instruction_Foreach', 'Opt_Instruction_If',
			'Opt_Instruction_Put', 'Opt_Instruction_Capture', 'Opt_Instruction_Attribute',
			'Opt_Instruction_Tag', 'Opt_Instruction_Root', 'Opt_Instruction_Prolog',
			'Opt_Instruction_Dtd', 'Opt_Instruction_Literal', 'Opt_Instruction_Include',
			'Opt_Instruction_Dynamic', 'Opt_Instruction_Component', 'Opt_Instruction_Block');
		protected $_functions = array(
			'money' => 'Opt_Function::money', 'number' => 'Opt_Function::number', 'spacify' => 'Opt_Function::spacify',
			'firstof' => 'Opt_Function::firstof', 'indent' => 'Opt_Function::indent', 'strip' => 'Opt_Function::strip',
			'stripTags' => 'Opt_Function::stripTags', 'upper' => 'Opt_Function::upper', 'lower' => 'Opt_Function::lower',
			'capitalize' => 'Opt_Function::capitalize', 'countWords' => 'str_word_count', 'countChars' => 'strlen',
			'replace' => '#3,1,2#str_replace', 'repeat' => 'str_repeat', 'nl2br' => 'Opt_Function::nl2br', 'date' => 'date',
			'regexReplace' => '#3,1,2#preg_replace', 'truncate' => 'Opt_Function::truncate', 'wordWrap' => 'Opt_Function::wordwrap',
			'contains' => 'Opt_Function::contains', 'count' => 'sizeof', 'sum' => 'Opt_Function::sum', 'average' => 'Opt_Function::average',
			'absolute' => 'Opt_Function::absolute', 'stddev' => 'Opt_Function::stddev', 'range' => 'Opt_Function::range',
			'isUrl' => 'Opt_Function::isUrl', 'isImage' => 'Opt_Function::isImage', 'stddev' => 'Opt_Function::stddev',
			'entity' => 'Opt_Function::entity', 'scalar' => 'is_scalar', 'containsKey' => 'Opt_Function::containsKey',
			'cycle' => 'Opt_Function::cycle', 'autoLink' => 'Opt_Function::autoLink', 'pluralize' => 'Opt_Function::pluralize',
			'countSubstring' => 'Opt_Function::countSubstring', 'pad' => 'Opt_Function::pad', 'autoLink' => 'Opt_Function::autoLink',
			'position' => 'strpos'
		);
		protected $_classes = array();
		protected $_components = array();
		protected $_blocks = array();
		protected $_namespaces = array(1 => 'opt', 'com', 'parse');
		protected $_formats = array(
			'Array' => 'Opt_Format_Array',
			'SingleArray' => 'Opt_Format_SingleArray',
			'StaticGenerator' => 'Opt_Format_StaticGenerator',
			'RuntimeGenerator' => 'Opt_Format_RuntimeGenerator',
			'Objective' => 'Opt_Format_Objective',
			'SplDatastructure' => 'Opt_Format_SplDatastructure');
		protected $_entities = array('lb' => '{', 'rb' => '}');
		protected $_buffers = array();

		// Status
		protected $_init = false;

		// Other
		protected $_compiler;
		
		/*
		 * Template parsing
		 */

		/**
		 * Returns the compiler object and optionally loads the necessary classes. Unless
		 * you develop instructions or reimplement various core features you do not have
		 * to use this method.
		 *
		 * @return Opt_Compiler_Class The compiler
		 */
		public function getCompiler()
		{
			if(!is_object($this->_compiler))
			{
				$this->_compiler = new Opt_Compiler_Class($this);
			}
			return $this->_compiler;
		} // end getCompiler();

		/*
		 * Extensions and configuration
		 */

		/**
		 * Performs the main initialization of OPT. If the optional argument `$config` is
		 * specified, it is transparently sent to Opt_Class::loadConfig(). Before using this
		 * method, we are obligated to configure the library and load the necessary extensions.
		 *
		 * @param mixed $config = null The optional configuration to be loaded
		 */
		public function setup($config = null)
		{
			if(is_array($config))
			{
				$this->loadConfig($config);
			}
			if(!is_null($this->pluginDir))
			{
				$this->loadPlugins();
			}

			if(Opl_Registry::exists('opl_translate'))
			{
				$this->setTranslationInterface(Opl_Registry::get('opl_translate'));
			}
			if(Opl_Registry::getState('opl_debug_console') || $this->debugConsole)
			{
				$this->debugConsole = true;				
				Opt_Support::initDebugConsole($this);
			}
			
			// Check paths etc.
			if(is_string($this->sourceDir))
			{
				$this->sourceDir = array('file' => $this->sourceDir);
			}
			foreach($this->sourceDir as &$path)
			{
				$this->_securePath($path);
			}
			$this->_securePath($this->compileDir);
			$this->_init = true;
		} // end setup();

		/**
		 * Registers a new add-on in OPT identified by `$type`. The type is identified
		 * by the appropriate Opt_Class constant. The semantics of the next arguments
		 * depends on the registered add-on.
		 *
		 * Note that you may register several add-ons at the same time by passing an
		 * array as the second argument.
		 *
		 * @param int $type The type of registered item(s).
		 * @param mixed $item The item or a list of items to be registered
		 * @param mixed $addon = null Used in several types of add-ons
		 * @return void
		 */
		public function register($type, $item, $addon = null)
		{
			if($this->_init)
			{
				throw new Opt_Initialization_Exception($this->_init, 'register an item');
			}
			
			$map = array(1 => '_instructions', '_namespaces', '_formats', '_components', '_blocks', '_functions', '_classes', '_entities');
			$whereto = $map[$type];
			// Massive registration
			if(is_array($item))
			{
				$this->$whereto = array_merge($this->$whereto, $item);
				return;
			}
			switch($type)
			{
				case self::OPT_FORMAT:
					if($addon === null)
					{
						$addon = 'Opt_Format_'.$item;
					}
					$a = &$this->$whereto;
					$a[$item] = $addon;
					break;
				case self::OPT_INSTRUCTION:
					if($addon === null)
					{
						$addon = 'Opt_Instruction_'.$item;
					}
					$a = &$this->$whereto;
					$a[$item] = $addon;
					break;
				case self::OPT_NAMESPACE:
					$a = &$this->$whereto;
					$a[] = $item;
					break;
				default:
					if($addon === null)
					{
						throw new BadMethodCallException('Missing argument 3 for Opt_Class::register()');
					}
					$a = &$this->$whereto;
					$a[$item] = $addon;
			}
		} // end register();

		/**
		 * Registers a new translation interface to be used in templates. The translation
		 * interface must implement Opl_Translation_Interface. If the specified parameter
		 * is not a valid translation interface, the method unregisters the already set one
		 * and returns false.
		 *
		 * @param Opl_Translation_Interface $tf  The translation interface or "null".
		 * @return boolean True, if the translation interface was properly set.
		 */
		public function setTranslationInterface($tf)
		{
			if(!$tf instanceof Opl_Translation_Interface)
			{
				$this->_tf = null;
				return false;
			}
			$this->_tf = $tf;
			return true;
		} // end setTranslationInterface();

		/**
		 * Returns the current translation interface assigned to OPT.
		 *
		 * @return Opl_Translation_Interface The translation interface.
		 */
		public function getTranslationInterface()
		{
			return $this->_tf;
		} // end getTranslationInterface();

		/**
		 * Sets the global caching system to use in all the views.
		 *
		 * @param Opt_Caching_Interface $cache=null The caching interface
		 */
		public function setCache(Opt_Caching_Interface $cache = null)
		{
			$this->_cache = $cache;
		} // end setCache();

		/**
		 * Returns the current global caching system.
		 *
		 * @return Opt_Caching_Interface
		 */
		public function getCache()
		{
			return $this->_cache;
		} // end getCache();

		/**
		 * An implementation of advisory output buffering which allows us
		 * to tell us, whether another part of the script opened the requested
		 * buffer.
		 *
		 * @param string $buffer The buffer name
		 * @param boolean $state The new buffer state: true to open, false to close.
		 */
		public function setBufferState($buffer, $state)
		{
			if($state)
			{
				if(!isset($this->_buffers[$buffer]))
				{
					$this->_buffers[$buffer] = 1;
				}
				else
				{
					$this->_buffers[$buffer]++;
				}
			}
			else
			{
				if(isset($this->_buffers[$buffer]) && $this->_buffers[$buffer] > 0)
				{
					$this->_buffers[$buffer]--;
				}
			}
		} // end setBufferState();

		/**
		 * Returns the state of the specified output buffer.
		 *
		 * @param String $buffer Buffer name
		 * @return Boolean
		 */
		public function getBufferState($buffer)
		{
			if(!isset($this->_buffers[$buffer]))
			{
				return false;
			}
			return ($this->_buffers[$buffer] > 0);
		} // end getBufferState();

		/*
		 * Internal use
		 */

		/**
		 * Allows the read access to some of the internal structures for the
		 * template compiler.
		 *
		 * @internal
		 * @param string $name The structure to be returned.
		 * @return array The returned structure.
		 */
		public function _getList($name)
		{
			static $list;
			if(is_null($list))
			{
				$list = array('_instructions', '_namespaces', '_formats', '_components', '_blocks', '_functions', '_classes', '_tf', '_entities');
			}
			if(in_array($name, $list))
			{
				return $this->$name;
			}
			return NULL;
		} // end _getList();

		/**
		 * The helper function for the plugin subsystem. It returns the
		 * PHP code that loads the specified plugin.
		 *
		 * @internal
		 * @param String $directory The plugin directory
		 * @param SplFileInfo $file The loaded file
		 * @return String
		 */
		protected function _pluginLoader($directory, SplFileInfo $file)
		{
			$ns = explode('.', $file->getFilename());
			if(end($ns) == 'php')
			{
				switch($ns[0])
				{
					case 'instruction':
						return 'Opl_Loader::mapAbsolute(\'Opt_Instruction_'.$ns[1].'\', \''.$directory.$file->getFilename().'\'); $this->register(Opt_Class::OPT_INSTRUCTION, \''.$ns[1].'\'); ';
					case 'format':
						return 'Opl_Loader::mapAbsolute(\'Opt_Format_'.$ns[1].'\', \''.$directory.$file->getFilename().'\'); $this->register(Opt_Class::OPT_FORMAT, \''.$ns[1].'\'); ';
					default:
						return ' require(\''.$directory.$file->getFilename().'\'); ';
				}
			}
		} // end _pluginLoader();

		/**
		 * Parses the stream in the template path name and returns
		 * the real path.
		 *
		 * @internal
		 * @param String $name Template filename
		 * @return String
		 */
		public function _stream($name)
		{
			if(strpos($name, ':') !== FALSE)
			{
				// We get the stream ID from the given filename.
				$data = explode(':', $name);
				if(!isset($this->sourceDir[$data[0]]))
				{
					throw new Opt_ObjectNotExists_Exception('resource', $data[0]);
				}
				if(!$this->allowRelativePaths && strpos($data[1], '../') !== false)
				{
					throw new Opt_NotSupported_Exception('relative paths', $data[1]);
				}
				return $this->sourceDir[$data[0]].$data[1];
			}
			// Here, the standard stream is used.
			if(!isset($this->sourceDir[$this->stdStream]))
			{
				throw new Opt_ObjectNotExists_Exception('resource', $this->stdStream);
			}
			if(!$this->allowRelativePaths && strpos($name, '../') !== false)
			{
				throw new Opt_NotSupported_Exception('relative paths', $name);
			}
			return $this->sourceDir[$this->stdStream].$name;
		} // end _stream();

		/**
		 * Loads the template source code. Returns the template body or
		 * the array with two (false) values in case of problems.
		 *
		 * @internal
		 * @param String $filename The template filename
		 * @param Boolean $exception Do we inform about the problems with exception?
		 * @return String|Array
		 */
		public function _getSource($filename, $exception = true)
		{
			$item = $this->_stream($filename);
			if(!file_exists($item))
			{
				if(!$exception)
				{
					return array(false, false);
				}
				throw new Opt_TemplateNotFound_Exception($item);
			}
			return file_get_contents($item);
		} // end _getSource();

		/**
		 * The class constructor - registers the main object in the
		 * OPL registry.
		 */
		public function __construct()
		{
			Opl_Registry::register('opt', $this);
		} // end __construct();

		/**
		 * The destructor. Clears the output buffers and optionally
		 * displays the debug console.
		 */
		public function __destruct()
		{
			if($this->debugConsole)
			{
				try
				{
					Opt_Support::updateTimers();
					Opl_Debug_Console::display();
				}
				catch(Opl_Exception $e)
				{
					die('<div style="background: #f77777;">Opt_Class destructor exception: '.$e->getMessage().'</div>');
				}
			}
		} // end __destruct();
	} // end Opt_Class;

	/**
	 * The main view class.
	 */
	class Opt_View
	{
		const VAR_LOCAL = false;
		const VAR_GLOBAL = true;

		/**
		 * A reference to the main class object.
		 * @var Opt_Class
		 */
		private $_tpl;

		/**
		 * The template name
		 * @var string
		 */
		private $_template;

		/**
		 * Data format information storage
		 * @var array
		 */
		private $_formatInfo = array();

		/**
		 * Template inheritance storage for the inflectors
		 * @var array
		 */
		private $_inheritance = array();

		/**
		 * Template inheritance storage for the compiler.
		 * @var array
		 */
		private $_cplInheritance = array();

		/**
		 * View data
		 * @var array
		 */
		private $_data = array();

		/**
		 * Translation interface
		 * @var Opl_Translation_Interface
		 */
		private $_tf;

		/**
		 * The information for the debugger: processing time
		 * @var integer
		 */
		private $_processingTime = null;

		/**
		 * The branch name for the template inheritance.
		 * @var string
		 */
		private $_branch = null;

		/**
		 * The caching system used in the view.
		 * @var Opt_Caching_Interface
		 */
		private $_cache = null;

		/**
		 * The compiler mode (XML/HTML or quirks).
		 * @var integer
		 */
		private $_mode;

		/**
		 * Part of the caching system to integrate with opt:dynamic instruction.
		 * @var array
		 */
		private $_outputBuffer = array();

		/**
		 * The template variable storage
		 * @static
		 * @var array
		 */
		static private $_vars = array();

		/**
		 * The list of the captured content.
		 * @static
		 * @var array
		 */
		static private $_capture = array();

		/**
		 * The global template data
		 * @static
		 * @var array
		 */
		static private $_global = array();

		/**
		 * The global data format information
		 * @static
		 * @var array
		 */
		static private $_globalFormatInfo = array();

		/**
		 * Creates a new view object. The optional argument, $template
		 * may specify the template to be associated with this view.
		 * Please note that if you do not specify the template here,
		 * you have to do this manually later using Opt_View::setTemplate()
		 * method.
		 *
		 * @param string $template The template file.
		 */
		public function __construct($template = '')
		{
			$this->_tpl = Opl_Registry::get('opt');
			$this->_template = $template;
			$this->_mode = $this->_tpl->mode;
			$this->_cache = $this->_tpl->getCache();
		} // end __construct();

		/**
		 * Associates a template file to the view.
		 *
		 * @param string $file The template file.
		 */
		public function setTemplate($file)
		{
			$this->_template = $file;
		} // end setTemplate();

		/**
		 * Returns a template associated with this view.
		 *
		 * @return string The template filename.
		 */
		public function getTemplate()
		{
			return $this->_template;
		} // end getTemplate();

		/**
		 * Sets the template mode (XML, Quirks, etc...)
		 *
		 * @param Int $mode The new mode
		 */
		public function setMode($mode)
		{
			$this->_mode = $mode;
		} // end setMode();

		/**
		 * Gets the current template mode.
		 *
		 * @return Int
		 */
		public function getMode()
		{
			return $this->_mode;
		} // end getMode();

		/**
		 * Sets a template inheritance branch that will be used
		 * in this view. If you want to disable branching, set
		 * the argument to NULL.
		 *
		 * @param string $branch The branch name.
		 */
		public function setBranch($branch)
		{
			$this->_branch = $branch;
		} // end setBranch();

		/**
		 * Returns a branch used in the template inheritance.
		 *
		 * @return string The branch name.
		 */
		public function getBranch()
		{
			return $this->_branch;
		} // end getBranch();

		/**
		 * Returns the view processing time for the debug purposes.
		 * The processing time is calculated only if the debug mode
		 * is enabled.
		 *
		 * @return float The processing time.
		 */
		public function getTime()
		{
			return $this->_processingTime;
		} // end getTime();

		/*
		 * Data management
		 */

		/**
		 * Creates a new local template variable.
		 *
		 * @param string $name The variable name.
		 * @param mixed $value The variable value.
		 */
		public function __set($name, $value)
		{
			$this->_data[$name] = $value;
		} // end __set();

		/**
		 * Creates a new local template variable.
		 *
		 * @param string $name The variable name.
		 * @param mixed $value The variable value.
		 */
		public function assign($name, $value)
		{
			$this->_data[$name] = $value;
		} // end assign();

		/**
		 * Creates a group of local template variables
		 * using an associative array, where the keys are
		 * the variable names.
		 *
		 * @param array $vars A list of variables.
		 */
		public function assignGroup($values)
		{
			$this->_data = array_merge($this->_data, $values);
		} // end assignGroup();

		/**
		 * Creates a new local template variable with
		 * the value assigned by reference.
		 *
		 * @param string $name The variable name.
		 * @param mixed &$value The variable value.
		 */
		public function assignRef($name, &$value)
		{
			$this->_data[$name] = &$value;
		} // end assignRef();

		/**
		 * Returns the value of a template variable or
		 * null, if the variable does not exist.
		 *
		 * @param string $name The variable name.
		 * @return mixed The variable value or NULL.
		 */
		public function get($name)
		{
			if(!isset($this->_data[$name]))
			{
				return null;
			}
			return $this->_data[$name];
		} // end read();

		/**
		 * Returns the value of a local template variable or
		 * null, if the variable does not exist.
		 *
		 * @param string $name The variable name.
		 * @return mixed The variable value or NULL.
		 */
		public function &__get($name)
		{
			if(!isset($this->_data[$name]))
			{
				// For returning by reference...
				$empty = null;
				return $empty;
			}
			return $this->_data[$name];
		} // end __get();

		/**
		 * Returns TRUE, if the local template variable with the
		 * specified name is defined.
		 *
		 * @param string $name The variable name.
		 * @return boolean True, if the variable is defined.
		 */
		public function defined($name)
		{
			return isset($this->_data[$name]);
		} // end defined();

		/**
		 * Returns TRUE, if the local template variable with the
		 * specified name is defined.
		 *
		 * @param string $name The variable name.
		 * @return boolean True, if the variable is defined.
		 */
		public function __isset($name)
		{
			return isset($this->_data[$name]);
		} // end __isset();

		/**
		 * Removes a local template variable with the specified name.
		 *
		 * @param string $name The variable name.
		 * @return boolean True, if the variable has been removed.
		 */
		public function remove($name)
		{
			if(isset($this->_data[$name]))
			{
				unset($this->_data[$name]);
				if(isset($this->_formatInfo[$name]))
				{
					unset($this->_formatInfo[$name]);
				}
				return true;
			}
			return false;
		} // end remove();

		/**
		 * Removes a local template variable with the specified name.
		 *
		 * @param string $name The variable name.
		 * @return boolean True, if the variable has been removed.
		 */
		public function __unset($name)
		{
			return $this->remove($name);
		} // end __unset();

		/**
		 * Creates a new global template variable.
		 *
		 * @static
		 * @param string $name The variable name.
		 * @param mixed $value The variable value.
		 */
		static public function assignGlobal($name, $value)
		{
			self::$_global[$name] = $value;
		} // end assignGlobal();

		/**
		 * Creates a group of global template variables
		 * using an associative array, where the keys are
		 * the variable names.
		 *
		 * @static
		 * @param array $vars A list of variables.
		 */
		static public function assignGroupGlobal($values)
		{
			self::$_global = array_merge(self::$_global, $values);
		} // end assignGroupGlobal();

		/**
		 * Creates a new global template variable with
		 * the value assigned by reference.
		 *
		 * @static
		 * @param string $name The variable name.
		 * @param mixed &$value The variable value.
		 */
		static public function assignRefGlobal($name, &$value)
		{
			self::$_global[$name] = &$value;
		} // end assignRefGlobal();

		/**
		 * Returns TRUE, if the global template variable with the
		 * specified name is defined.
		 *
		 * @static
		 * @param string $name The variable name.
		 * @return boolean True, if the variable is defined.
		 */
		static public function definedGlobal($name)
		{
			return isset(self::$_global[$name]);
		} // end definedGlobal();

		/**
		 * Returns the value of a global template variable or
		 * null, if the variable does not exist.
		 *
		 * @static
		 * @param string $name The variable name.
		 * @return mixed The variable value or NULL.
		 */
		static public function getGlobal($name)
		{
			if(!isset(self::$_global[$name]))
			{
				return null;
			}
			return self::$_global[$name];
		} // end getGlobal();

		/**
		 * Removes a global template variable with the specified name.
		 *
		 * @static
		 * @param string $name The variable name.
		 * @return boolean True, if the variable has been removed.
		 */
		static public function removeGlobal($name)
		{
			if(isset(self::$_global[$name]))
			{
				unset(self::$_global[$name]);
				return true;
			}
			return false;
		} // end removeGlobal();

		/**
		 * Clears all the possible static private buffers.
		 */
		static public function clear()
		{
			self::$_vars = array();
			self::$_capture = array();
			self::$_global = array();
			self::$_globalFormatInfo = array();
		} // end clear();

		/**
		 * Returns the value of the internal template variable or
		 * NULL if it does not exist.
		 *
		 * @param string $name The internal variable name.
		 * @return mixed The variable value or NULL.
		 */
		public function getTemplateVar($name)
		{
			if(!isset(self::$_vars[$name]))
			{
				return null;
			}
			return self::$_vars[$name];
		} // end getTemplateVar();

		/**
		 * Sets the specified data format for the identifier that may
		 * identify a template variable or some other things. The details
		 * are explained in the OPT user manual.
		 *
		 * @param string $item The item name
		 * @param string $format The format to be used for the specified item.
		 */
		public function setFormat($item, $format)
		{
			$this->_formatInfo[$item] = $format;
		} // end setFormat();
		
		/**
		 * Sets the specified data format for the identifier that may
		 * identify a global template variable or some other things. The details
		 * are explained in the OPT user manual.
		 *
		 * @static
		 * @param string $item The item name
		 * @param string $format The format to be used for the specified item.
		 * @param boolean $global Does it register the item in the "global." group?
		 */
		static public function setFormatGlobal($item, $format, $global = true)
		{
			if($global)
			{
				self::$_globalFormatInfo['global.'.$item] = $format;
			}
			else
			{
				self::$_globalFormatInfo[$item] = $format;
			}
		} // end setFormatGlobal();

		/**
		 * Sets the caching interface that should be used with this view.
		 *
		 * @param Opt_Caching_Interface $iface The caching interface
		 */
		public function setCache(Opt_Caching_Interface $iface = null)
		{
			$this->_cache = $iface;
		} // end setCache();

		/**
		 * Returns the caching interface used with this view
		 *
		 * @return Opt_Caching_Interface
		 */
		public function getCache()
		{
			return $this->_cache;
		} // end getCache();

		/**
		 * A method for caching systems that tells, whether there is some
		 * dynamic content available in the captured part.
		 *
		 * @return Boolean
		 */
		public function hasDynamicContent()
		{
			return sizeof($this->_outputBuffer) > 0;
		} // end hasDynamicContent();

		/**
		 * Returns the static parts of the cached template, if the opt:dynamic
		 * is used. Please note that the returned array does not contain the
		 * last buffer, which must be closed and retrieved manually with
		 * ob_get_flush().
		 *
		 * @return Array
		 */
		public function getOutputBuffers()
		{
			return $this->_outputBuffer;
		} // end getBuffers();
		
		/*
		 * Dynamic inheritance
		 */

		/**
		 * Creates a dynamic template inheritance between the templates in the view.
		 * There are two possible uses of the method. If you specify only the one
		 * argument, the method will extend the main view template with the specified
		 * template.
		 *
		 * The two arguments can be used to extend other templates in the inheritance
		 * chain. In this case the first argument specifies the template that is going
		 * to extend something, and the second one - the extended template.
		 *
		 * @param string $source The extending template or the extended template in case of one-argument call.
		 * @param string $destination The extended template.
		 */
		public function inherit($source, $destination = null)
		{
			if($destination === null)
			{
				$this->_inheritance[$this->_template] = str_replace(array('/', ':', '\\'), '__', $source);
				$this->_cplInheritance[$this->_template] = $source;
				return;
			}
			$this->_inheritance[$source] = str_replace(array('/', ':', '\\'), '__',$destination);
			$this->_cplInheritance[$source] = $destination;
		} // end inherit();
		
		/*
		 * Internal use
		 */

		/**
		 * Executes, and optionally compiles the template represented by the view.
		 * Returns true, if the template was found and successfully executed.
		 *
		 * @param Opt_Output_Interface $output The output interface.
		 * @param Boolean $exception Should the exceptions be thrown if the template does not exist?
		 * @return Boolean
		 */
		public function _parse(Opt_Output_Interface $output, $exception = true)
		{
			if($this->_tpl->debugConsole)
			{
				$time = microtime(true);
			}
			$cached = false;
			if($this->_cache !== null)
			{
				$result = $this->_cache->templateCacheStart($this);
				if($result !== false)
				{
					// For dynamic cache...
					if(is_string($result))
					{
						include($result);
					}
					return true;
				}
				$cached = true;
			}
			$this->_tf = $this->_tpl->getTranslationInterface();
			if($this->_tpl->compileMode != Opt_Class::CM_PERFORMANCE)
			{
				list($compileName, $compileTime) = $this->_preprocess($exception);	
				if(is_null($compileName))
				{
					return false;
				}
			}
			else
			{
				$compileName = $this->_convert($this->_template);
				$compileTime = null;
				if(!$exception && !file_exists($compileName))
				{
					return false;
				}
			}
			
			$old = error_reporting($this->_tpl->errorReporting);
			require($this->_tpl->compileDir.$compileName);
			error_reporting($old);

			// The counter stops, if the time counting has been enabled for the debug console purposes
			if($this->_cache !== null)
			{
				$this->_cache->templateCacheStop($this);
			}
			if(isset($time))
			{
				Opt_Support::addView($this->_template, $output->getName(), $this->_processingTime = microtime(true) - $time, $cached);
			}
			return true;
		} // end _parse();

		/**
		 * The method checks whether the template exists and if it was modified by
		 * the template designer. In the second case, it loads and runs the template
		 * compiler to produce a new version. Returns an array with the template data:
		 *  - Compiled template name
		 *  - Compilation time
		 * They are needed by the template execution system or template inheritance. In
		 * case of problems, the array contains two NULL values.
		 *
		 * @internal
		 * @param Boolean $exception Do we inform about unexisting template with exceptions?
		 * @return Array
		 */
		protected function _preprocess($exception = true)
		{
			$item = $this->_tpl->_stream($this->_template);
			$compiled = $this->_convert($this->_template);
			$compileTime = @filemtime($this->_tpl->compileDir.$compiled);
			$result = NULL;
			
			// Here the "rebuild" compilation mode is processed
			if($this->_tpl->compileMode == Opt_Class::CM_REBUILD)
			{
				if(!file_exists($item))
				{
					if(!$exception)
					{
						return array(NULL, NULL);
					}
					throw new Opt_TemplateNotFound_Exception($item);
				}
				$result = file_get_contents($item);
			}
			else
			{				
				// Otherwise, we perform a modification test.
				$rootTime = @filemtime($item);
				if($rootTime === false)
				{
					if(!$exception)
					{
						return array(NULL, NULL);
					}
					throw new Opt_TemplateNotFound_Exception($item);
				}
				if($compileTime === false || $compileTime < $rootTime)
				{
					$result = file_get_contents($item);
				}
			}

			if($result === null)
			{
				return array($compiled, $compileTime);
			}

			$compiler = $this->_tpl->getCompiler();
			$compiler->setInheritance($this->_cplInheritance);
			$compiler->setFormatList(array_merge($this->_formatInfo, self::$_globalFormatInfo));
			$compiler->set('branch', $this->_branch);
			$compiler->compile($result, $this->_template, $compiled, $this->_mode);
			return array($compiled, $compileTime);
		} // end _preprocess();

		/**
		 * This method is used by the template with the template inheritance. It
		 * allows to check, whether one of the templates on the dependency list
		 * has been modified. The method takes the compilation time of the compiled
		 * template and the list of the source template names that it depends on.
		 *
		 * Returns true, if one if the templates is newer than the compilation time.
		 *
		 * @param Int $compileTime Compiled template creation time.
		 * @param Array $templates The list of dependencies
		 * @return Boolean
		 */
		protected function _massPreprocess($compileTime, $templates)
		{
			// We do not check CM_REBUILD, because the compilation has already been done in _parse()
			if($this->_tpl->compileMode == Opt_Class::CM_DEFAULT)
			{
				$cnt = sizeof($templates);
					
				// TODO: Check whether the object as array key works :P
				for($i = 0; $i < $cnt; $i++)
				{
					$templates[$i] = $this->_tpl->_stream($templates[$i]);
					$time = @filemtime($templates[$i]);
					if($time === null)
					{
						throw new Opt_TemplateNotFound_Exception($templates[$i]);
					}
					if($time >= $compileTime)
					{
						return true;
					}
				}
			}
			return false;
		} // end _massPreprocess();

		/**
		 * Converts the source template file name to the compiled
		 * template file name.
		 *
		 * @internal
		 * @param String $filename The source file name
		 * @return String
		 */
		public function _convert($filename)
		{
			$list = array();
			if(sizeof($this->_inheritance) > 0)
			{
				$list = $this->_inheritance;
				sort($list);
			}
			$list[] = str_replace(array('/', ':', '\\'), '__', $filename);
			if($this->_tpl->compileId !== null)
			{
				return $this->_tpl->compileId.'_'.implode('/', $list).'.php';
			}
			return implode('/', $list).'.php';
		} // end _convert();

		/**
		 * Compiles the specified template and returns the current
		 * time.
		 *
		 * @internal
		 * @param String $filename The file name.
		 * @return Integer
		 */
		public function _compile($filename)
		{
			$compiled = $this->_convert($filename);
			$compiler = $this->_tpl->getCompiler();
			$compiler->setInheritance($this->_cplInheritance);
			$compiler->setFormatList(array_merge($this->_formatInfo, self::$_globalFormatInfo));
			$compiler->set('branch', $this->_branch);
			$compiler->compile($this->_tpl->_getSource($filename), $filename, $compiled, $this->_mode);
			return time();
		} // end _compile();
	} // end Opt_View;
Return current item: Open Power Template