<?php /** * TTemplateControl class file. * * @author Qiang Xue <qiang.xue@gmail.com> * @link http://www.pradosoft.com/ * @copyright Copyright © 2005 PradoSoft * @license http://www.pradosoft.com/license/ * @version $Revision: $ $Date: $ * @package System.Web.UI */ /** * TTemplateControl class. * TTemplateControl is the base class for all controls that use templates. * By default, a control template is assumed to be in a file under the same * directory with the control class file. They have the same file name and * different extension name. For template file, the extension name is ".tpl". * * @author Qiang Xue <qiang.xue@gmail.com> * @version $Revision: $ $Date: $ * @package System.Web.UI * @since 3.0 */ class TTemplateControl extends TControl implements INamingContainer { /** * template file extension. */ const EXT_TEMPLATE='.tpl'; /** * @var ITemplate the parsed template structure shared by the same control class */ protected static $_template=array(); /** * @var ITemplate the parsed template structure specific for this control instance */ protected $_localTemplate=null; /** * @var TTemplateControl the master control if any */ private $_master=null; /** * @var string master control class name */ private $_masterClass=''; /** * @var array list of TContent controls */ private $_contents=array(); /** * @var array list of TContentPlaceHolder controls */ private $_placeholders=array(); /** * Constructor. * Loads template for the control class if not loaded. * Applies template directive if any. */ public function __construct() { if(($tpl=$this->getTemplate(true))!==null) { foreach($tpl->getDirective() as $name=>$value) $this->setSubProperty($name,$value); } } /** * @param boolean whether to attempt loading template if it is not loaded yet * @return ITemplate|null the parsed template, null if none */ public function getTemplate($load=false) { if($this->_localTemplate===null) { $class=get_class($this); $tpl=isset(self::$_template[$class])?self::$_template[$class]:null; return ($tpl===null && $load)?$this->loadTemplate():$tpl; } else return $this->_localTemplate; } /** * Sets the parsed template. * Note, the template will be applied to the whole control class. * This method should only be used by framework and control developers. * @param ITemplate the parsed template */ public function setTemplate($value) { $this->_localTemplate=$value; } /** * Loads and parses the control template * @return ITemplate the parsed template structure */ protected function loadTemplate() { Prado::trace("Loading template ".get_class($this),'System.Web.UI.TTemplateControl'); $template=$this->getService()->getTemplateManager()->getTemplateByClassName(get_class($this)); self::$_template[get_class($this)]=$template; return $template; } /** * Creates child controls. * This method is overriden to load and instantiate control template. * This method should only be used by framework and control developers. */ protected function createChildControls() { if($tpl=$this->getTemplate()) $tpl->instantiateIn($this); } /** * Registers a content control. * @param TContent */ public function registerContent(TContent $object) { $this->_contents[$object->getID()]=$object; } /** * @return string master class name (in namespace form) */ public function getMasterClass() { return $this->_masterClass; } /** * @param string master control class name (in namespace form) */ public function setMasterClass($value) { $this->_masterClass=$value; } /** * @return TTemplateControl|null master control associated with this control, null if none */ public function getMaster() { return $this->_master; } /** * Registers a content placeholder to this template control. * This method should only be used by framework and control developers. * @param string ID of the placeholder * @param TControl control that directly enloses the placeholder * @param integer the index in the control list of the parent control that the placeholder is at */ public function registerContentPlaceHolder($id,$parent,$loc) { $this->_placeholders[$id]=array($parent,$loc); } /** * Injects all content controls (and their children) to the corresponding content placeholders. * This method should only be used by framework and control developers. * @param string ID of the content control * @param TContent the content to be injected */ public function injectContent($id,$content) { if(isset($this->_placeholders[$id])) { list($parent,$loc)=$this->_placeholders[$id]; $parent->getControls()->insert($loc,$content); } } /** * Performs the OnInit step for the control and all its child controls. * This method overrides the parent implementation * by ensuring child controls are created first, * and if master class is set, master will be applied. * Only framework developers should use this method. * @param TControl the naming container control */ protected function initRecursive($namingContainer=null) { $this->ensureChildControls(); if($this->_masterClass!=='') { $master=Prado::createComponent($this->_masterClass); if(!($master instanceof TTemplateControl)) throw new TInvalidDataValueException('tplcontrol_required',get_class($master)); $this->_master=$master; $this->getControls()->clear(); $this->getControls()->add($master); $master->ensureChildControls(); foreach($this->_contents as $id=>$content) $master->injectContent($id,$content); } parent::initRecursive($namingContainer); } } ?>