From bdd139266bbd71b828394a1500551254fc42a819 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sat, 3 Dec 2005 04:45:44 +0000 Subject: --- framework/Web/UI/TAssetManager.php | 221 +++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 framework/Web/UI/TAssetManager.php (limited to 'framework/Web/UI/TAssetManager.php') diff --git a/framework/Web/UI/TAssetManager.php b/framework/Web/UI/TAssetManager.php new file mode 100644 index 00000000..0f96ae90 --- /dev/null +++ b/framework/Web/UI/TAssetManager.php @@ -0,0 +1,221 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ $Date: $ + * @package System.Web.UI + */ + +/** + * TAssetManager class + * + * TAssetManager provides a scheme to allow web clients visiting + * private files that are normally web-inaccessible. + * + * TAssetManager will copy the file to be published into a web-accessible + * directory. The default base directory for storing the file is "assets", which + * should be under the application directory. This can be changed by setting + * the {@link setBasePath BasePath} property together with the + * {@link setBaseUrl BaseUrl} property that refers to the URL for accessing the base path. + * + * By default, TAssetManager will not publish a file or directory if it already + * exists in the publishing directory and has an older modification time. + * If the application mode is set as 'Performance', the modification time check + * will be skipped. You can explicitly require a modification time check + * with the function {@link publishFilePath}. This is usually + * very useful during development. + * + * TAssetManager may be configured in application configuration file within + * page service element as follows, + * + * where {@link getBasePath BasePath} and {@link getBaseUrl BaseUrl} are + * configurable properties of TAssetManager. Make sure that BasePath is a namespace + * pointing to a valid directory writable by the Web server process. + * + * @author Qiang Xue + * @version $Revision: $ $Date: $ + * @package System.Web.UI + * @since 3.0 + */ +class TAssetManager extends TComponent implements IModule +{ + /** + * Default web accessible base path for storing private files + */ + const DEFAULT_BASEPATH='assets'; + /** + * @var string base web accessible path for storing private files + */ + private $_basePath=null; + /** + * @var string base URL for accessing the publishing directory. + */ + private $_baseUrl=null; + /** + * @var string module ID + */ + private $_id='asset'; + /** + * @var boolean whether to use timestamp checking to ensure files are published with up-to-date versions. + */ + private $_checkTimestamp=false; + /** + * @var TApplication application instance + */ + private $_application; + /** + * @var array published assets + */ + private $_published=array(); + + /** + * 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; + if($this->_basePath===null) + $this->_basePath=dirname($application->getRequest()->getPhysicalApplicationPath()).'/'.self::DEFAULT_BASEPATH; + if(!is_writable($this->_basePath) || !is_dir($this->_basePath)) + throw new TConfigurationException('assetmanager_basepath_invalid',$this->_basePath); + if($this->_baseUrl===null) + $this->_baseUrl=dirname($application->getRequest()->getApplicationPath()).'/'.self::DEFAULT_BASEPATH; + $application->getService()->setAssetManager($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; + } + + /** + * @return string the root directory storing published asset files + */ + public function getBasePath() + { + return $this->_basePath; + } + + /** + * Sets the root directory storing published asset files. + * The directory must be in namespace format. + * @param string the root directory storing published asset files + * @throws TInvalidOperationException if the service is initialized already + */ + public function setBasePath($value) + { + if($this->_initialized) + throw new TInvalidOperationException('assetmanager_basepath_unchangeable'); + else + { + $this->_basePath=Prado::getPathOfAlias($value); + if($this->_basePath===null || !is_dir($this->_basePath) || !is_writable($this->_basePath)) + throw new TInvalidDataValueException('assetmanage_basepath_invalid',$value); + } + } + + /** + * @return string the base url that the published asset files can be accessed + */ + public function getBaseUrl() + { + return $this->_baseUrl; + } + + /** + * @param string the base url that the published asset files can be accessed + * @throws TInvalidOperationException if the service is initialized already + */ + public function setBaseUrl($value) + { + if($this->_initialized) + throw new TInvalidOperationException('assetmanager_baseurl_unchangeable'); + else + $this->_baseUrl=$value; + } + + /** + * Publishes a file or a directory (recursively). + * This method will copy the content in a directory (recursively) to + * a web accessible directory and returns the URL for the directory. + * @param string the path to be published + * @param boolean whether to use file modify time to ensure every published file is latest + * @return string an absolute URL to the published directory + */ + public function publishFilePath($path,$checkTimestamp=false) + { + if(isset($this->_published[$path])) + return $this->_published[$path]; + else if(($fullpath=realpath($path))===false) + return ''; + else if(is_file($fullpath)) + { + $dir=md5(dirname($fullpath)); + $file=$this->_basePath.'/'.$dir.'/'.basename($fullpath); + if(!is_file($file) || $checkTimestamp || $this->_application->getMode()!=='Performance') + { + if(!is_dir($this->_basePath.'/'.$dir)) + @mkdir($this->_basePath.'/'.$dir); + if(!is_file($file) || @filemtime($file)<@filemtime($fullpath)) + @copy($fullpath,$file); + } + $this->_published[$path]=$this->_baseUrl.'/'.$dir.'/'.basename($fullpath); + return $this->_published[$path]; + } + else + { + $dir=md5($fullpath); + if(!is_dir($this->_basePath.'/'.$dir) || $checkTimestamp || $this->_application->getMode()!=='Performance') + $this->copyDirectory($fullpath,$this->_basePath.'/'.$dir); + $this->_published[$path]=$this->_baseUrl.'/'.$dir; + return $this->_published[$path]; + } + } + + /** + * Copies a directory recursively as another. + * If the destination directory does not exist, it will be created. + * File modification time is used to ensure the copied files are latest. + * @param string the source directory + * @param string the destination directory + */ + protected function copyDirectory($src,$dst) + { + if(!is_dir($dst)) + @mkdir($dst); + $folder=@opendir($src); + while($file=@readdir($folder)) + { + if($file==='.' || $file==='..') + continue; + else if(is_file($src.'/'.$file)) + { + if(@filemtime($dst.'/'.$file)<@filemtime($src.'/'.$file)) + @copy($src.'/'.$file,$dst.'/'.$file); + } + else + $this->copyDirectory($src.'/'.$file,$dst.'/'.$file); + } + closedir($folder); + } +} + +?> \ No newline at end of file -- cgit v1.2.3