| [ Index ] |
|
Code source de PRADO 3.0.6 |
1 <?php 2 /** 3 * TThemeManager class 4 * 5 * @author Qiang Xue <qiang.xue@gmail.com> 6 * @link http://www.pradosoft.com/ 7 * @copyright Copyright © 2005 PradoSoft 8 * @license http://www.pradosoft.com/license/ 9 * @version $Id: TThemeManager.php 1536 2006-12-01 19:51:21Z xue $ 10 * @package System.Web.UI 11 */ 12 13 Prado::using('System.Web.Services.TPageService'); 14 15 /** 16 * TThemeManager class 17 * 18 * TThemeManager manages the themes used in a Prado application. 19 * 20 * Themes are stored under the directory specified by the 21 * {@link setBasePath BasePath} property. The themes can be accessed 22 * via URL {@link setBaseUrl BaseUrl}. Each theme is represented by a subdirectory 23 * and all the files under that directory. The name of a theme is the name 24 * of the corresponding subdirectory. 25 * By default, the base path of all themes is a directory named "themes" 26 * under the directory containing the application entry script. 27 * To get a theme (normally you do not need to), call {@link getTheme}. 28 * 29 * TThemeManager may be configured within page service tag in application 30 * configuration file as follows, 31 * <module id="themes" class="System.Web.UI.TThemeManager" 32 * BasePath="Application.themes" BaseUrl="/themes" /> 33 * where {@link getCacheExpire CacheExpire}, {@link getCacheControl CacheControl} 34 * and {@link getBufferOutput BufferOutput} are configurable properties of THttpResponse. 35 * 36 * @author Qiang Xue <qiang.xue@gmail.com> 37 * @version $Id: TThemeManager.php 1536 2006-12-01 19:51:21Z xue $ 38 * @package System.Web.UI 39 * @since 3.0 40 */ 41 class TThemeManager extends TModule 42 { 43 /** 44 * default themes base path 45 */ 46 const DEFAULT_BASEPATH='themes'; 47 /** 48 * @var boolean whether this module has been initialized 49 */ 50 private $_initialized=false; 51 /** 52 * @var string the directory containing all themes 53 */ 54 private $_basePath=null; 55 /** 56 * @var string the base URL for all themes 57 */ 58 private $_baseUrl=null; 59 60 /** 61 * Initializes the module. 62 * This method is required by IModule and is invoked by application. 63 * @param TXmlElement module configuration 64 */ 65 public function init($config) 66 { 67 $this->_initialized=true; 68 $service=$this->getService(); 69 if($service instanceof TPageService) 70 $service->setThemeManager($this); 71 else 72 throw new TConfigurationException('thememanager_service_unavailable'); 73 } 74 75 /** 76 * @param string name of the theme to be retrieved 77 * @return TTheme the theme retrieved 78 */ 79 public function getTheme($name) 80 { 81 $themePath=$this->getBasePath().'/'.$name; 82 $themeUrl=rtrim($this->getBaseUrl(),'/').'/'.$name; 83 return new TTheme($themePath,$themeUrl); 84 85 } 86 87 /** 88 * @return array list of available theme names 89 */ 90 public function getAvailableThemes() 91 { 92 $themes=array(); 93 $basePath=$this->getBasePath(); 94 $folder=@opendir($basePath); 95 while($file=@readdir($folder)) 96 { 97 if($file!=='.' && $file!=='..' && $file!=='.svn' && is_dir($basePath.'/'.$file)) 98 $themes[]=$file; 99 } 100 closedir($folder); 101 return $themes; 102 } 103 104 /** 105 * @return string the base path for all themes. It is returned as an absolute path. 106 * @throws TConfigurationException if base path is not set and "themes" directory does not exist. 107 */ 108 public function getBasePath() 109 { 110 if($this->_basePath===null) 111 { 112 $this->_basePath=dirname($this->getRequest()->getApplicationFilePath()).'/'.self::DEFAULT_BASEPATH; 113 if(($basePath=realpath($this->_basePath))===false || !is_dir($basePath)) 114 throw new TConfigurationException('thememanager_basepath_invalid2',$this->_basePath); 115 $this->_basePath=$basePath; 116 } 117 return $this->_basePath; 118 } 119 120 /** 121 * @param string the base path for all themes. It must be in the format of a namespace. 122 * @throws TInvalidDataValueException if the base path is not a proper namespace. 123 */ 124 public function setBasePath($value) 125 { 126 if($this->_initialized) 127 throw new TInvalidOperationException('thememanager_basepath_unchangeable'); 128 else 129 { 130 $this->_basePath=Prado::getPathOfNamespace($value); 131 if($this->_basePath===null || !is_dir($this->_basePath)) 132 throw new TInvalidDataValueException('thememanager_basepath_invalid',$value); 133 } 134 } 135 136 /** 137 * @return string the base URL for all themes. 138 * @throws TConfigurationException If base URL is not set and a correct one cannot be determined by Prado. 139 */ 140 public function getBaseUrl() 141 { 142 if($this->_baseUrl===null) 143 { 144 $appPath=dirname($this->getRequest()->getApplicationFilePath()); 145 $basePath=$this->getBasePath(); 146 if(strpos($basePath,$appPath)===false) 147 throw new TConfigurationException('thememanager_baseurl_required'); 148 $appUrl=rtrim(dirname($this->getRequest()->getApplicationUrl()),'/\\'); 149 $this->_baseUrl=$appUrl.strtr(substr($basePath,strlen($appPath)),'\\','/'); 150 } 151 return $this->_baseUrl; 152 } 153 154 /** 155 * @param string the base URL for all themes. 156 */ 157 public function setBaseUrl($value) 158 { 159 $this->_baseUrl=rtrim($value,'/'); 160 } 161 } 162 163 /** 164 * TTheme class 165 * 166 * TTheme represents a particular theme. It is merely a collection of skins 167 * that are applicable to the corresponding controls. 168 * 169 * Each theme is stored as a directory and files under that directory. 170 * The theme name is the directory name. When TTheme is created, the files 171 * whose name has the extension ".skin" are parsed and saved as controls skins. 172 * 173 * A skin is essentially a list of initial property values that are to be applied 174 * to a control when the skin is applied. 175 * Each type of control can have multiple skins identified by the SkinID. 176 * If a skin does not have SkinID, it is the default skin that will be applied 177 * to controls that do not specify particular SkinID. 178 * 179 * Whenever possible, TTheme will try to make use of available cache to save 180 * the parsing time. 181 * 182 * To apply a theme to a particular control, call {@link applySkin}. 183 * 184 * @author Qiang Xue <qiang.xue@gmail.com> 185 * @version $Id: TThemeManager.php 1536 2006-12-01 19:51:21Z xue $ 186 * @package System.Web.UI 187 * @since 3.0 188 */ 189 class TTheme extends TApplicationComponent implements ITheme 190 { 191 /** 192 * prefix for cache variable name used to store parsed themes 193 */ 194 const THEME_CACHE_PREFIX='prado:theme:'; 195 /** 196 * Extension name of skin files 197 */ 198 const SKIN_FILE_EXT='.skin'; 199 /** 200 * @var string theme path 201 */ 202 private $_themePath; 203 /** 204 * @var string theme url 205 */ 206 private $_themeUrl; 207 /** 208 * @var array list of skins for the theme 209 */ 210 private $_skins=null; 211 /** 212 * @var string theme name 213 */ 214 private $_name=''; 215 /** 216 * @var array list of css files 217 */ 218 private $_cssFiles=array(); 219 /** 220 * @var array list of js files 221 */ 222 private $_jsFiles=array(); 223 224 /** 225 * Constructor. 226 * @param string theme path 227 * @param string theme URL 228 * @throws TConfigurationException if theme path does not exist or any parsing error of the skin files 229 */ 230 public function __construct($themePath,$themeUrl) 231 { 232 $this->_themeUrl=$themeUrl; 233 $this->_themePath=realpath($themePath); 234 $this->_name=basename($themePath); 235 $cacheValid=false; 236 // TODO: the following needs to be cleaned up (Qiang) 237 if(($cache=$this->getApplication()->getCache())!==null) 238 { 239 $array=$cache->get(self::THEME_CACHE_PREFIX.$themePath); 240 if(is_array($array)) 241 { 242 list($skins,$cssFiles,$jsFiles,$timestamp)=$array; 243 if($this->getApplication()->getMode()!==TApplicationMode::Performance) 244 { 245 if(($dir=opendir($themePath))===false) 246 throw new TIOException('theme_path_inexistent',$themePath); 247 $cacheValid=true; 248 while(($file=readdir($dir))!==false) 249 { 250 if($file==='.' || $file==='..') 251 continue; 252 else if(basename($file,'.css')!==$file) 253 $this->_cssFiles[]=$themeUrl.'/'.$file; 254 else if(basename($file,'.js')!==$file) 255 $this->_jsFiles[]=$themeUrl.'/'.$file; 256 else if(basename($file,self::SKIN_FILE_EXT)!==$file && filemtime($themePath.'/'.$file)>$timestamp) 257 { 258 $cacheValid=false; 259 break; 260 } 261 } 262 closedir($dir); 263 if($cacheValid) 264 $this->_skins=$skins; 265 } 266 else 267 { 268 $cacheValid=true; 269 $this->_cssFiles=$cssFiles; 270 $this->_jsFiles=$jsFiles; 271 $this->_skins=$skins; 272 } 273 } 274 } 275 if(!$cacheValid) 276 { 277 $this->_cssFiles=array(); 278 $this->_jsFiles=array(); 279 $this->_skins=array(); 280 if(($dir=opendir($themePath))===false) 281 throw new TIOException('theme_path_inexistent',$themePath); 282 while(($file=readdir($dir))!==false) 283 { 284 if($file==='.' || $file==='..') 285 continue; 286 else if(basename($file,'.css')!==$file) 287 $this->_cssFiles[]=$themeUrl.'/'.$file; 288 else if(basename($file,'.js')!==$file) 289 $this->_jsFiles[]=$themeUrl.'/'.$file; 290 else if(basename($file,self::SKIN_FILE_EXT)!==$file) 291 { 292 $template=new TTemplate(file_get_contents($themePath.'/'.$file),$themePath,$themePath.'/'.$file); 293 foreach($template->getItems() as $skin) 294 { 295 if(!isset($skin[2])) // a text string, ignored 296 continue; 297 else if($skin[0]!==-1) 298 throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath)); 299 $type=$skin[1]; 300 $id=isset($skin[2]['skinid'])?$skin[2]['skinid']:0; 301 unset($skin[2]['skinid']); 302 if(isset($this->_skins[$type][$id])) 303 throw new TConfigurationException('theme_skinid_duplicated',$type,$id,dirname($themePath)); 304 /* 305 foreach($skin[2] as $name=>$value) 306 { 307 if(is_array($value) && ($value[0]===TTemplate::CONFIG_DATABIND || $value[0]===TTemplate::CONFIG_PARAMETER)) 308 throw new TConfigurationException('theme_databind_forbidden',dirname($themePath),$type,$id); 309 } 310 */ 311 $this->_skins[$type][$id]=$skin[2]; 312 } 313 } 314 } 315 closedir($dir); 316 sort($this->_cssFiles); 317 sort($this->_jsFiles); 318 if($cache!==null) 319 $cache->set(self::THEME_CACHE_PREFIX.$themePath,array($this->_skins,$this->_cssFiles,$this->_jsFiles,time())); 320 } 321 } 322 323 /** 324 * @return string theme name 325 */ 326 public function getName() 327 { 328 return $this->_name; 329 } 330 331 /** 332 * @return string the URL to the theme folder (without ending slash) 333 */ 334 public function getBaseUrl() 335 { 336 return $this->_themeUrl; 337 } 338 339 /** 340 * @return string the file path to the theme folder 341 */ 342 public function getBasePath() 343 { 344 return $this->_themePath; 345 } 346 347 /** 348 * Applies the theme to a particular control. 349 * The control's class name and SkinID value will be used to 350 * identify which skin to be applied. If the control's SkinID is empty, 351 * the default skin will be applied. 352 * @param TControl the control to be applied with a skin 353 * @return boolean if a skin is successfully applied 354 * @throws TConfigurationException if any error happened during the skin application 355 */ 356 public function applySkin($control) 357 { 358 $type=get_class($control); 359 if(($id=$control->getSkinID())==='') 360 $id=0; 361 if(isset($this->_skins[$type][$id])) 362 { 363 foreach($this->_skins[$type][$id] as $name=>$value) 364 { 365 Prado::trace("Applying skin $name to $type",'System.Web.UI.TThemeManager'); 366 if(is_array($value)) 367 { 368 switch($value[0]) 369 { 370 case TTemplate::CONFIG_EXPRESSION: 371 $value=$this->evaluateExpression($value[1]); 372 break; 373 case TTemplate::CONFIG_ASSET: 374 $value=$this->_themeUrl.'/'.ltrim($value[1],'/'); 375 break; 376 case TTemplate::CONFIG_DATABIND: 377 $control->bindProperty($name,$value[1]); 378 break; 379 case TTemplate::CONFIG_PARAMETER: 380 $control->setSubProperty($name,$this->getApplication()->getParameters()->itemAt($value[1])); 381 break; 382 case TTemplate::CONFIG_TEMPLATE: 383 $control->setSubProperty($name,$value[1]); 384 break; 385 case TTemplate::CONFIG_LOCALIZATION: 386 $control->setSubProperty($name,Prado::localize($value[1])); 387 break; 388 default: 389 throw new TConfigurationException('theme_tag_unexpected',$name,$value[0]); 390 break; 391 } 392 } 393 if(!is_array($value)) 394 { 395 if(strpos($name,'.')===false) // is simple property or custom attribute 396 { 397 if($control->hasProperty($name)) 398 { 399 if($control->canSetProperty($name)) 400 { 401 $setter='set'.$name; 402 $control->$setter($value); 403 } 404 else 405 throw new TConfigurationException('theme_property_readonly',$type,$name); 406 } 407 else 408 throw new TConfigurationException('theme_property_undefined',$type,$name); 409 } 410 else // complex property 411 $control->setSubProperty($name,$value); 412 } 413 } 414 return true; 415 } 416 else 417 return false; 418 } 419 420 /** 421 * @return array list of CSS files (URL) in the theme 422 */ 423 public function getStyleSheetFiles() 424 { 425 return $this->_cssFiles; 426 } 427 428 /** 429 * @return array list of Javascript files (URL) in the theme 430 */ 431 public function getJavaScriptFiles() 432 { 433 return $this->_jsFiles; 434 } 435 } 436 437 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Sun Feb 25 21:07:04 2007 | par Balluche grâce à PHPXref 0.7 |