summaryrefslogtreecommitdiff
path: root/framework/Web
diff options
context:
space:
mode:
authorxue <>2005-11-20 23:48:11 +0000
committerxue <>2005-11-20 23:48:11 +0000
commit796029932b87e46d317262ab9562a5c091027dfc (patch)
tree8a1d0638448999ae05e2fbc98c8478b48ea919e0 /framework/Web
parent2a4097f1c50e820fde0f3a769463c1858985b7fb (diff)
Diffstat (limited to 'framework/Web')
-rw-r--r--framework/Web/Services/TPageService.php4
-rw-r--r--framework/Web/UI/TTemplateManager.php630
-rw-r--r--framework/Web/UI/TThemeManager.php338
3 files changed, 2 insertions, 970 deletions
diff --git a/framework/Web/Services/TPageService.php b/framework/Web/Services/TPageService.php
index df239088..048bead3 100644
--- a/framework/Web/Services/TPageService.php
+++ b/framework/Web/Services/TPageService.php
@@ -11,8 +11,8 @@
*/
Prado::using('System.Web.UI.TPage');
-Prado::using('System.Web.UI.TTemplateManager');
-Prado::using('System.Web.UI.TThemeManager');
+Prado::using('System.Web.TTemplateManager');
+Prado::using('System.Web.TThemeManager');
Prado::using('System.Web.TAssetManager');
/**
diff --git a/framework/Web/UI/TTemplateManager.php b/framework/Web/UI/TTemplateManager.php
deleted file mode 100644
index 6b9ccfc0..00000000
--- a/framework/Web/UI/TTemplateManager.php
+++ /dev/null
@@ -1,630 +0,0 @@
-<?php
-/**
- * TTemplateManager and TTemplate class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- */
-
-/**
- * TTemplateManager class
- *
- * TTemplateManager manages the loading and parsing of control templates.
- *
- * Given a class name, TTemplateManager tries to locate the corresponding template
- * file under the directory containing the class file. The name of the template file
- * is the class name with the extension '.tpl'.
- *
- * By default, TTemplateManager is registered with {@link TPageService} as the
- * template manager module that can be accessed via {@link TPageService::getTemplateManager()}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- * @since 3.0
- */
-class TTemplateManager extends TComponent implements IModule
-{
- /**
- * Template file extension
- */
- const TEMPLATE_FILE_EXT='.tpl';
- /**
- * Prefix of the cache variable name for storing parsed templates
- */
- const TEMPLATE_CACHE_PREFIX='prado:template:';
- /**
- * @var TApplication application instance
- */
- private $_application;
- /**
- * @var string module ID
- */
- private $_id;
-
- /**
- * Initializes the module.
- * This method is required by IModule and is invoked by application.
- * It starts output buffer if it is enabled.
- * @param TApplication application
- * @param TXmlElement module configuration
- */
- public function init($application,$config)
- {
- $this->_application=$application;
- $application->getService()->setTemplateManager($this);
- }
-
- /**
- * @return string id of this module
- */
- public function getID()
- {
- return $this->_id;
- }
-
- /**
- * @param string id of this module
- */
- public function setID($value)
- {
- $this->_id=$value;
- }
-
- /**
- * Loads the template corresponding to the specified class name.
- * @return ITemplate template for the class name, null if template doesn't exist.
- */
- public function getTemplateByClassName($className)
- {
- $class=new ReflectionClass($className);
- $tplFile=dirname($class->getFileName()).'/'.$className.self::TEMPLATE_FILE_EXT;
- return $this->getTemplateByFileName($tplFile);
- }
-
- /**
- * Loads the template from the specified file.
- * @return ITemplate template parsed from the specified file, null if the file doesn't exist.
- */
- public function getTemplateByFileName($fileName)
- {
- if(($fileName=realpath($fileName))!==false && is_file($fileName))
- {
- if(($cache=$this->_application->getCache())===null)
- return new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName);
- else
- {
- $array=$cache->get(self::TEMPLATE_CACHE_PREFIX.$fileName);
- if(is_array($array))
- {
- list($template,$timestamp)=$array;
- if(filemtime($fileName)<$timestamp)
- return $template;
- }
- $template=new TTemplate(file_get_contents($fileName),dirname($fileName),$fileName);
- $cache->set(self::TEMPLATE_CACHE_PREFIX.$fileName,array($template,time()));
- return $template;
- }
- }
- else
- return null;
- }
-}
-
-/**
- * TTemplate implements PRADO template parsing logic.
- * A TTemplate object represents a parsed PRADO control template.
- * It can instantiate the template as child controls of a specified control.
- * The template format is like HTML, with the following special tags introduced,
- * - component tags: a component tag represents the configuration of a component.
- * The tag name is in the format of com:ComponentType, where ComponentType is the component
- * class name. Component tags must be well-formed. Attributes of the component tag
- * are treated as either property initial values, event handler attachment, or regular
- * tag attributes.
- * - property tags: property tags are used to set large block of attribute values.
- * The property tag name is in the format of prop:AttributeName, where AttributeName
- * can be a property name, an event name or a regular tag attribute name.
- * - directive: directive specifies the property values for the template owner.
- * It is in the format of &lt;% property name-value pairs %&gt;
- * - expressions: expressions are shorthand of {@link TExpression} and {@link TStatements}
- * controls. They are in the formate of &lt;= PHP expression &gt; and &lt; PHP statements &gt;
- * - comments: There are two kinds of comments, regular HTML comments and special template comments.
- * The former is in the format of &lt;!-- comments --&gt;, which will be treated as text strings.
- * The latter is in the format of &lt;%* comments %&gt;, which will be stripped out.
- *
- * Tags other than the above are not required to be well-formed.
- *
- * A TTemplate object represents a parsed PRADO template. To instantiate the template
- * for a particular control, call {@link instantiateIn($control)}, which
- * will create and intialize all components specified in the template and
- * set their parent as the control.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- * @since 3.0
- */
-class TTemplate extends TComponent implements ITemplate
-{
- /**
- * '<!.*?!>' - template comments
- * '<!--.*?-->' - HTML comments
- * '<\/?com:([\w\.]+)((?:\s*[\w\.]+=\'.*?\'|\s*[\w\.]+=".*?"|\s*[\w\.]+=<%.*?%>)*)\s*\/?>' - component tags
- * '<\/?prop:([\w\.]+)\s*>' - property tags
- * '<%@\s*(\w+)((?:\s*[\w\.]+=\'.*?\'|\s*[\w\.]+=".*?")*)\s*%>' - directives
- * '<%=?(.*?)%>' - expressions
- */
- const REGEX_RULES='/<!.*?!>|<!--.*?-->|<\/?com:([\w\.]+)((?:\s*[\w\.]+=\'.*?\'|\s*[\w\.]+=".*?"|\s*[\w\.]+=<%.*?%>)*)\s*\/?>|<\/?prop:([\w\.]+)\s*>|<%@\s*((?:\s*[\w\.]+=\'.*?\'|\s*[\w\.]+=".*?")*)\s*%>|<%=?(.*?)%>/msS';
-
- /**
- * @var array list of component tags and strings
- */
- private $_tpl=array();
- /**
- * @var array list of directive settings
- */
- private $_directive=array();
- /**
- * @var string context path
- */
- private $_contextPath;
- /**
- * @var string template file path (if available)
- */
- private $_tplFile=null;
-
- /**
- * Constructor.
- * The template will be parsed after construction.
- * @param string the template string
- * @param string the template context directory
- * @param string the template file, null if no file
- */
- public function __construct($template,$contextPath,$tplFile=null)
- {
- $this->_contextPath=$contextPath;
- $this->_tplFile=$tplFile;
- $this->parse($template);
- }
-
- /**
- * @return array name-value pairs declared in the directive
- */
- public function getDirective()
- {
- return $this->_directive;
- }
-
- /**
- * @return array the parsed template
- */
- public function &getItems()
- {
- return $this->_tpl;
- }
-
- /**
- * Instantiates the template.
- * Content in the template will be instantiated as components and text strings
- * and passed to the specified parent control.
- * @param TControl the parent control
- * @throws TTemplateRuntimeException if an error is encountered during the instantiation.
- */
- public function instantiateIn($tplControl)
- {
- $page=$tplControl->getPage();
- $assetManager=$page->getService()->getAssetManager();
- $controls=array();
- foreach($this->_tpl as $key=>$object)
- {
- if(isset($object[2])) // component
- {
- if(strpos($object[1],'.')===false)
- {
- if(class_exists($object[1],false))
- $component=new $object[1];
- else
- {
- include_once($object[1].Prado::CLASS_FILE_EXT);
- if(class_exists($object[1],false))
- $component=new $object[1];
- else
- throw new TTemplateRuntimeException('template_component_unknown',$object[1]);
- }
- }
- else
- $component=Prado::createComponent($object[1]);
- if($component instanceof TControl)
- {
- $controls[$key]=$component;
- $component->setTemplateControl($tplControl);
- if(isset($object[2]['id']))
- $tplControl->registerObject($object[2]['id'],$component);
- if(isset($object[2]['skinid']))
- {
- $component->setSkinID($object[2]['skinid']);
- unset($object[2]['skinid']);
- }
- $component->applyStyleSheetSkin($page);
- // apply attributes
- foreach($object[2] as $name=>$value)
- {
- if($component->hasEvent($name)) // is an event
- {
- if(is_string($value))
- {
- if(strpos($value,'.')===false)
- $component->attachEventHandler($name,array($component,'TemplateControl.'.$value));
- else
- $component->attachEventHandler($name,array($component,$value));
- }
- else
- throw new TTemplateRuntimeException('template_event_invalid',get_class($component),$name);
- }
- else if(strpos($name,'.')===false) // is simple property or custom attribute
- {
- if($component->hasProperty($name))
- {
- if($component->canSetProperty($name))
- {
- $setter='set'.$name;
- if(is_string($value))
- $component->$setter($value);
- else if($value[0]===0)
- $component->bindProperty($name,$value[1]);
- else if($value[0]===1)
- $component->$setter($component->evaluateExpression($value[1]));
- else // url
- {
- $url=$assetManager->publishFilePath($this->_contextPath.'/'.$value[1]);
- $component->$setter($url);
- }
- }
- else
- throw new TTemplateRuntimeException('template_property_readonly',get_class($component),$name);
- }
- else if($component->getAllowCustomAttributes())
- {
- if(is_array($value))
- {
- if($value[0]===1)
- $value=$component->evaluateExpression($value[1]);
- else if($value[0]===2)
- $value=$assetManager->publishFilePath($this->_contextPath.'/'.$value[1]);
- else
- throw new TTemplateRuntimeException('template_attribute_unbindable',get_class($component),$name);
- }
- $component->getAttributes()->add($name,$value);
- }
- else
- throw new TTemplateRuntimeException('template_property_undefined',get_class($component),$name);
- }
- else // complex property
- {
- if(is_string($value))
- $component->setSubProperty($name,$value);
- else if($value[0]===0)
- $component->bindProperty($name,$value[1]);
- else if($value[0]===1)
- $component->setSubProperty($component->evaluateExpression($value[1]));
- else
- {
- $url=$assetManager->publishFilePath($this->_contextPath.'/'.$value[1]);
- $component->$setter($url);
- }
- }
- }
- $parent=isset($controls[$object[0]])?$controls[$object[0]]:$tplControl;
- $component->createdOnTemplate($parent);
- }
- else if($component instanceof TComponent)
- {
- if(isset($object[2]['id']))
- {
- $tplControl->registerObject($object[2]['id'],$component);
- if(!$component->hasProperty('id'))
- unset($object[2]['id']);
- }
- foreach($object[2] as $name=>$value)
- {
- if($component->hasProperty($name))
- {
- if($component->canSetProperty($name))
- {
- $setter='set'.$name;
- if(is_string($value))
- $component->$setter($value);
- else if($value[0]===1)
- $component->$setter($component->evaluateExpression($value[1]));
- else if($value[0]===2)
- {
- $url=$assetManager->publishFilePath($this->_contextPath.'/'.$value[1]);
- $component->$setter($url);
- }
- else
- throw new TTemplateRuntimeException('template_property_unbindable',get_class($component),$name);
- }
- else
- throw new TTemplateRuntimeException('template_property_readonly',get_class($component),$name);
- }
- else
- throw new TTemplateRuntimeException('template_property_undefined',get_class($component),$name);
- }
- $parent=isset($controls[$object[0]])?$controls[$object[0]]:$tplControl;
- $parent->addParsedObject($component);
- }
- else
- throw new TTemplateRuntimeException('template_component_required',$object[1]);
- }
- else // string
- {
- if(isset($controls[$object[0]]))
- $controls[$object[0]]->addParsedObject($object[1]);
- else
- $tplControl->addParsedObject($object[1]);
- }
- }
- }
-
- /**
- * Parses a template string.
- *
- * This template parser recognizes five types of data:
- * regular string, well-formed component tags, well-formed property tags, directives, and expressions.
- *
- * The parsing result is returned as an array. Each array element can be of three types:
- * - a string, 0: container index; 1: string content;
- * - a component tag, 0: container index; 1: component type; 2: attributes (name=>value pairs)
- * If a directive is found in the template, it will be parsed and can be
- * retrieved via {@link getDirective}, which returns an array consisting of
- * name-value pairs in the directive.
- *
- * Note, attribute names are treated as case-insensitive and will be turned into lower cases.
- * Component and directive types are case-sensitive.
- * Container index is the index to the array element that stores the container object.
- * If an object has no container, its container index is -1.
- *
- * @param string the template string
- * @throws TTemplateParsingException if a parsing error is encountered
- */
- protected function parse($input)
- {
- $tpl=&$this->_tpl;
- $n=preg_match_all(self::REGEX_RULES,$input,$matches,PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
- $expectPropEnd=false;
- $textStart=0;
- $stack=array();
- $container=-1;
- $c=0;
- for($i=0;$i<$n;++$i)
- {
- $match=&$matches[$i];
- $str=$match[0][0];
- $matchStart=$match[0][1];
- $matchEnd=$matchStart+strlen($str)-1;
- if(strpos($str,'<com:')===0) // opening component tag
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- $type=$match[1][0];
- $attributes=$this->parseAttributes($match[2][0]);
- $tpl[$c++]=array($container,$type,$attributes);
- if($str[strlen($str)-2]!=='/') // open tag
- {
- array_push($stack,$type);
- $container=$c-1;
- }
- }
- else if(strpos($str,'</com:')===0) // closing component tag
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- $type=$match[1][0];
-
- if(empty($stack))
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_closingtag_unexpected',"Line $line","</com:$type>");
- else
- throw new TTemplateParsingException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","</com:$type>");
- }
-
- $name=array_pop($stack);
- if($name!==$type)
- {
- if($name[0]==='@')
- $tag='</prop:'.substr($name,1).'>';
- else
- $tag='</com:'.$name.'>';
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_closingtag_expected',"Line $line",$tag);
- else
- throw new TTemplateParsingException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag);
- }
- $container=$tpl[$container][0];
- }
- else if(strpos($str,'<%@')===0) // directive
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- if(isset($tpl[0]))
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_directive_nonunique',"Line $line");
- else
- throw new TTemplateParsingException('template_directive_nonunique',"{$this->_tplFile} (Line $line)");
- }
- $this->_directive=$this->parseAttributes($match[4][0]);
- }
- else if(strpos($str,'<%')===0) // expression
- {
- if($expectPropEnd)
- continue;
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- if($str[2]==='=')
- $tpl[$c++]=array($container,'TExpression',array('Expression'=>$match[5][0]));
- else
- $tpl[$c++]=array($container,'TStatements',array('Statements'=>$match[5][0]));
- }
- else if(strpos($str,'<prop:')===0) // opening property
- {
- $prop=strtolower($match[3][0]);
- array_push($stack,'@'.$prop);
- if(!$expectPropEnd)
- {
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- $expectPropEnd=true;
- }
- }
- else if(strpos($str,'</prop:')===0) // closing property
- {
- $prop=strtolower($match[3][0]);
- if(empty($stack))
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_closingtag_unexpected',"Line $line","</prop:$prop>");
- else
- throw new TTemplateParsingException('template_closingtag_unexpected',"{$this->_tplFile} (Line $line)","</prop:$prop>");
- }
- $name=array_pop($stack);
- if($name!=='@'.$prop)
- {
- if($name[0]==='@')
- $tag='</prop:'.substr($name,1).'>';
- else
- $tag='</com:'.$name.'>';
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_closingtag_expected',"Line $line",$tag);
- else
- throw new TTemplateParsingException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag);
- }
- if(($last=count($stack))<1 || $stack[$last-1][0]!=='@')
- {
- if($matchStart>$textStart && $container>=0)
- {
- $value=substr($input,$textStart,$matchStart-$textStart);
- if(preg_match('/^<%.*?%>$/msS',$value))
- {
- if($value[2]==='#') // databind
- $tpl[$container][2][$prop]=array(0,substr($value,3,strlen($value)-5));
- else if($value[2]==='=') // a dynamic initialization
- $tpl[$container][2][$prop]=array(1,substr($value,3,strlen($value)-5));
- else
- $tpl[$container][2][$prop]=$value;
- }
- else
- $tpl[$container][2][$prop]=$value;
- $textStart=$matchEnd+1;
- }
- $expectPropEnd=false;
- }
- }
- else if(strpos($str,'<!--')===0) // HTML comments
- {
- $state=0;
- }
- else if(strpos($str,'<!')===0) // template comments
- {
- if($expectPropEnd)
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_comments_forbidden',"Line $line");
- else
- throw new TTemplateParsingException('template_comments_forbidden',"{$this->_tplFile} (Line $line)");
- }
- if($matchStart>$textStart)
- $tpl[$c++]=array($container,substr($input,$textStart,$matchStart-$textStart));
- $textStart=$matchEnd+1;
- }
- else
- {
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_matching_unexpected',"Line $line",$match);
- else
- throw new TTemplateParsingException('template_matching_unexpected',"{$this->_tplFile} (Line $line)",$match);
- }
- }
- if(!empty($stack))
- {
- $name=array_pop($stack);
- if($name[0]==='@')
- $tag='</prop:'.substr($name,1).'>';
- else
- $tag='</com:'.$name.'>';
- $line=count(explode("\n",substr($input,0,$matchEnd+1)));
- if($this->_tplFile===null)
- throw new TTemplateParsingException('template_closingtag_expected',"Line $line",$tag);
- else
- throw new TTemplateParsingException('template_closingtag_expected',"{$this->_tplFile} (Line $line)",$tag);
- }
- if($textStart<strlen($input))
- $tpl[$c++]=array($container,substr($input,$textStart));
- return $tpl;
- }
-
- /**
- * Parses the attributes of a tag from a string.
- * @param string the string to be parsed.
- * @return array attribute values indexed by names.
- */
- protected function parseAttributes($str)
- {
- if($str==='')
- return array();
- $pattern='/([\w\.]+)=(\'.*?\'|".*?"|<%.*?%>)/msS';
- $attributes=array();
- $n=preg_match_all($pattern,$str,$matches,PREG_SET_ORDER);
- for($i=0;$i<$n;++$i)
- {
- $name=strtolower($matches[$i][1]);
- $value=$matches[$i][2];
- if($value[0]==='\'' || $value[0]==='"')
- {
- $value=substr($value,1,strlen($value)-2);
- if(!preg_match('/(<%#.*?%>|<%=.*?%>|<%~.*?%>)/msS',$value))
- {
- $attributes[$name]=$value;
- continue;
- }
- }
- if($value[0]==='<')
- {
- if($value[2]==='#') // databind
- $attributes[$name]=array(0,substr($value,3,strlen($value)-5));
- else if($value[2]==='=') // a dynamic initialization
- $attributes[$name]=array(1,substr($value,3,strlen($value)-5));
- else if($value[2]==='~') // a URL
- $attributes[$name]=array(2,trim(substr($value,3,strlen($value)-5)));
- else
- $attributes[$name]=substr($value,2,strlen($value)-4);
- }
- }
- return $attributes;
- }
-}
-
-?> \ No newline at end of file
diff --git a/framework/Web/UI/TThemeManager.php b/framework/Web/UI/TThemeManager.php
deleted file mode 100644
index 5d7319e8..00000000
--- a/framework/Web/UI/TThemeManager.php
+++ /dev/null
@@ -1,338 +0,0 @@
-<?php
-/**
- * TThemeManager class
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- */
-
-/**
- * TThemeManager class
- *
- * TThemeManager manages the themes used in a Prado application.
- *
- * Themes are stored under the directory specified by the
- * {@link setBasePath BasePath} property. The themes can be accessed
- * via URL {@link setBaseUrl BaseUrl}. Each theme is represented by a subdirectory
- * and all the files under that directory. The name of a theme is the name
- * of the corresponding subdirectory.
- * By default, the base path of all themes is a directory named "themes"
- * under the directory containing the application entry script.
- * To get a theme (normally you do not need to), call {@link getTheme}.
- *
- * TThemeManager may be configured within page service tag in application
- * configuration file as follows,
- * <module id="themes" type="System.Web.UI.TThemeManager"
- * BasePath="Application.themes" BaseUrl="/themes" />
- * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl}
- * and {@link getBufferOutput BufferOutput} are configurable properties of THttpResponse.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- * @since 3.0
- */
-class TThemeManager extends TComponent implements IModule
-{
- /**
- * default themes base path
- */
- const DEFAULT_BASEPATH='themes';
- /**
- * @var string module ID
- */
- private $_id;
- /**
- * @var boolean whether this module has been initialized
- */
- private $_initialized=false;
- /**
- * @var string the directory containing all themes
- */
- private $_basePath=null;
- /**
- * @var string the base URL for all themes
- */
- private $_baseUrl=null;
- /**
- * @var TApplication application
- */
- private $_application;
-
- /**
- * Initializes the module.
- * This method is required by IModule and is invoked by application.
- * @param TApplication application
- * @param TXmlElement module configuration
- */
- public function init($application,$config)
- {
- $this->_application=$application;
- $this->_initialized=true;
- $application->getService()->setThemeManager($this);
- }
-
- /**
- * @return string id of this module
- */
- public function getID()
- {
- return $this->_id;
- }
-
- /**
- * @param string id of this module
- */
- public function setID($value)
- {
- $this->_id=$value;
- }
-
- /**
- * @param string name of the theme to be retrieved
- * @return TTheme the theme retrieved
- */
- public function getTheme($name)
- {
- $themePath=$this->getBasePath().'/'.$name;
- $themeUrl=$this->getBaseUrl().'/'.$name;
- return new TTheme($this->_application,$themePath,$themeUrl);
-
- }
-
- /**
- * @return string the base path for all themes. It is returned as an absolute path.
- * @throws TConfigurationException if base path is not set and "themes" directory does not exist.
- */
- public function getBasePath()
- {
- if($this->_basePath===null)
- {
- $this->_basePath=dirname($this->_application->getRequest()->getPhysicalApplicationPath()).'/'.self::DEFAULT_BASEPATH;
- if(($basePath=realpath($this->_basePath))===false || !is_dir($basePath))
- throw new TConfigurationException('thememanager_basepath_invalid',$this->_basePath);
- $this->_basePath=$basePath;
- }
- return $this->_basePath;
- }
-
- /**
- * @param string the base path for all themes. It must be in the format of a namespace.
- * @throws TInvalidDataValueException if the base path is not a proper namespace.
- */
- public function setBasePath($value)
- {
- if($this->_initialized)
- throw new TInvalidOperationException('thememanager_basepath_unchangeable');
- else
- {
- $this->_basePath=Prado::getPathOfAlias($value);
- if($this->_basePath===null || !is_dir($this->_basePath))
- throw new TInvalidDataValueException('thememanager_basepath_invalid',$value);
- $this->_basePath=$value;
- }
- }
-
- /**
- * @return string the base URL for all themes.
- * @throws TConfigurationException If base URL is not set and a correct one cannot be determined by Prado.
- */
- public function getBaseUrl()
- {
- if($this->_baseUrl===null)
- {
- $appPath=dirname($this->_application->getRequest()->getPhysicalApplicationPath());
- $basePath=$this->getBasePath();
- if(strpos($basePath,$appPath)===false)
- throw new TConfigurationException('thememanager_baseurl_required');
- $appUrl=dirname($this->_application->getRequest()->getApplicationPath());
- $this->_baseUrl=$appUrl.'/'.strtr(substr($basePath,strlen($appPath)),'\\','/');
- }
- return $this->_baseUrl;
- }
-
- /**
- * @param string the base URL for all themes.
- */
- public function setBaseUrl($value)
- {
- $this->_baseUrl=rtrim($value,'/');
- }
-}
-
-/**
- * TTheme class
- *
- * TTheme represents a particular theme. It is merely a collection of skins
- * that are applicable to the corresponding controls.
- *
- * Each theme is stored as a directory and files under that directory.
- * The theme name is the directory name. When TTheme is created, the files
- * whose name has the extension ".skin" are parsed and saved as controls skins.
- *
- * A skin is essentially a list of initial property values that are to be applied
- * to a control when the skin is applied.
- * Each type of control can have multiple skins identified by the SkinID.
- * If a skin does not have SkinID, it is the default skin that will be applied
- * to controls that do not specify particular SkinID.
- *
- * Whenever possible, TTheme will try to make use of available cache to save
- * the parsing time.
- *
- * To apply a theme to a particular control, call {@link applySkin}.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI
- * @since 3.0
- */
-class TTheme extends TComponent
-{
- /**
- * prefix for cache variable name used to store parsed themes
- */
- const THEME_CACHE_PREFIX='prado:theme:';
- /**
- * Extension name of skin files
- */
- const SKIN_FILE_EXT='.skin';
- /**
- * @var string theme path
- */
- private $_themePath;
- /**
- * @var string theme url
- */
- private $_themeUrl;
- /**
- * @var array list of skins for the theme
- */
- private $_skins=null;
-
- /**
- * Constructor.
- * @param TApplication application instance
- * @param string theme path
- * @param string theme URL
- * @throws TConfigurationException if theme path does not exist or any parsing error of the skin files
- */
- public function __construct($application,$themePath,$themeUrl)
- {
- $this->_themeUrl=$themeUrl;
- if(($cache=$application->getCache())!==null)
- {
- $array=$cache->get(self::THEME_CACHE_PREFIX.$themePath);
- if(is_array($array))
- {
- list($skins,$timestamp)=$array;
- $cacheValid=true;
- if($application->getMode()!=='Performance')
- {
- if(($dir=opendir($themePath))===false)
- throw new TIOException('theme_path_inexistent',$themePath);
- while(($file=readdir($dir))!==false)
- {
- if(basename($file,self::SKIN_FILE_EXT)!==$file && filemtime($themePath.'/'.$file)>$timestamp)
- {
- $cacheValid=false;
- break;
- }
- }
- closedir($dir);
- }
- if($cacheValid)
- $this->_skins=$skins;
- }
- }
- if($this->_skins===null)
- {
- if(($dir=opendir($themePath))===false)
- throw new TIOException('theme_path_inexistent',$themePath);
- while(($file=readdir($dir))!==false)
- {
- if(basename($file,self::SKIN_FILE_EXT)!==$file)
- {
- $template=new TTemplate(file_get_contents($themePath.'/'.$file),$themePath,$themePath.'/'.$file);
- foreach($template->getItems() as $skin)
- {
- if($skin[0]!==-1)
- throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath));
- else if(!isset($skin[2])) // a text string, ignored
- continue;
- $type=$skin[1];
- $id=isset($skin[2]['skinid'])?$skin[2]['skinid']:0;
- unset($skin[2]['skinid']);
- if(isset($this->_skins[$type][$id]))
- throw new TConfigurationException('theme_skinid_duplicated',$type,$id,dirname($themePath));
- foreach($skin[2] as $name=>$value)
- {
- if(is_array($value) && $value[0]===0)
- throw new TConfigurationException('theme_databind_forbidden',dirname($themePath),$type,$id);
- }
- $this->_skins[$type][$id]=$skin[2];
- }
- }
- }
- closedir($dir);
- if($cache!==null)
- $cache->set(self::THEME_CACHE_PREFIX.$themePath,array($this->_skins,time()));
- }
- }
-
- /**
- * Applies the theme to a particular control.
- * The control's class name and SkinID value will be used to
- * identify which skin to be applied. If the control's SkinID is empty,
- * the default skin will be applied.
- * @param TControl the control to be applied with a skin
- * @return boolean if a skin is successfully applied
- * @throws TConfigurationException if any error happened during the skin application
- */
- public function applySkin($control)
- {
- $type=get_class($control);
- if(($id=$control->getSkinID())==='')
- $id=0;
- if(isset($this->_skins[$type][$id]))
- {
- foreach($this->_skins[$type][$id] as $name=>$value)
- {
- if(is_array($value))
- {
- if($value[0]===1)
- $value=$this->evaluateExpression($value[1]);
- else if($value[0]===2)
- $value=$this->_themeUrl.'/'.$value[1];
- }
- if(strpos($name,'.')===false) // is simple property or custom attribute
- {
- if($control->hasProperty($name))
- {
- if($control->canSetProperty($name))
- {
- $setter='set'.$name;
- $control->$setter($value);
- }
- else
- throw new TConfigurationException('theme_property_readonly',$type,$name);
- }
- else if($control->getAllowCustomAttributes())
- $control->getAttributes()->add($name,$value);
- else
- throw new TConfigurationException('theme_property_undefined',$type,$name);
- }
- else // complex property
- $control->setSubProperty($name,$value);
- }
- return true;
- }
- else
- return false;
- }
-}
-
-?> \ No newline at end of file