PageRenderTime 24ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/htdocs/yii/1.1.5/framework/web/CAssetManager.php

http://github.com/pmjones/php-framework-benchmarks
PHP | 257 lines | 115 code | 14 blank | 128 comment | 27 complexity | a6708994fd53d49533c1b126fa84af99 MD5 | raw file
Possible License(s): LGPL-3.0, Apache-2.0, BSD-3-Clause, ISC, AGPL-3.0, LGPL-2.1
  1. <?php
  2. /**
  3. * CAssetManager class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright Copyright &copy; 2008-2010 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * CAssetManager is a Web application component that manages private files (called assets) and makes them accessible by Web clients.
  12. *
  13. * It achieves this goal by copying assets to a Web-accessible directory
  14. * and returns the corresponding URL for accessing them.
  15. *
  16. * To publish an asset, simply call {@link publish()}.
  17. *
  18. * The Web-accessible directory holding the published files is specified
  19. * by {@link setBasePath basePath}, which defaults to the "assets" directory
  20. * under the directory containing the application entry script file.
  21. * The property {@link setBaseUrl baseUrl} refers to the URL for accessing
  22. * the {@link setBasePath basePath}.
  23. *
  24. * @author Qiang Xue <qiang.xue@gmail.com>
  25. * @version $Id: CAssetManager.php 2599 2010-11-01 23:19:19Z qiang.xue $
  26. * @package system.web
  27. * @since 1.0
  28. */
  29. class CAssetManager extends CApplicationComponent
  30. {
  31. /**
  32. * Default web accessible base path for storing private files
  33. */
  34. const DEFAULT_BASEPATH='assets';
  35. /**
  36. * @var boolean whether to use symbolic link to publish asset files. Defaults to false, meaning
  37. * asset files are copied to public folders. Using symbolic links has the benefit that the published
  38. * assets will always be consistent with the source assets. This is especially useful during development.
  39. *
  40. * However, there are special requirements for hosting environments in order to use symbolic links.
  41. * In particular, symbolic links are supported only on Linux/Unix, and Windows Vista/2008 or greater.
  42. * The latter requires PHP 5.3 or greater.
  43. *
  44. * Moreover, some Web servers need to be properly configured so that the linked assets are accessible
  45. * to Web users. For example, for Apache Web server, the following configuration directive should be added
  46. * for the Web folder:
  47. * <pre>
  48. * Options FollowSymLinks
  49. * </pre>
  50. *
  51. * @since 1.1.5
  52. */
  53. public $linkAssets=false;
  54. /**
  55. * @var string base web accessible path for storing private files
  56. */
  57. private $_basePath;
  58. /**
  59. * @var string base URL for accessing the publishing directory.
  60. */
  61. private $_baseUrl;
  62. /**
  63. * @var array published assets
  64. */
  65. private $_published=array();
  66. /**
  67. * @return string the root directory storing the published asset files. Defaults to 'WebRoot/assets'.
  68. */
  69. public function getBasePath()
  70. {
  71. if($this->_basePath===null)
  72. {
  73. $request=Yii::app()->getRequest();
  74. $this->setBasePath(dirname($request->getScriptFile()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH);
  75. }
  76. return $this->_basePath;
  77. }
  78. /**
  79. * Sets the root directory storing published asset files.
  80. * @param string $value the root directory storing published asset files
  81. * @throws CException if the base path is invalid
  82. */
  83. public function setBasePath($value)
  84. {
  85. if(($basePath=realpath($value))!==false && is_dir($basePath) && is_writable($basePath))
  86. $this->_basePath=$basePath;
  87. else
  88. throw new CException(Yii::t('yii','CAssetManager.basePath "{path}" is invalid. Please make sure the directory exists and is writable by the Web server process.',
  89. array('{path}'=>$value)));
  90. }
  91. /**
  92. * @return string the base url that the published asset files can be accessed.
  93. * Note, the ending slashes are stripped off. Defaults to '/AppBaseUrl/assets'.
  94. */
  95. public function getBaseUrl()
  96. {
  97. if($this->_baseUrl===null)
  98. {
  99. $request=Yii::app()->getRequest();
  100. $this->setBaseUrl($request->getBaseUrl().'/'.self::DEFAULT_BASEPATH);
  101. }
  102. return $this->_baseUrl;
  103. }
  104. /**
  105. * @param string $value the base url that the published asset files can be accessed
  106. */
  107. public function setBaseUrl($value)
  108. {
  109. $this->_baseUrl=rtrim($value,'/');
  110. }
  111. /**
  112. * Publishes a file or a directory.
  113. * This method will copy the specified asset to a web accessible directory
  114. * and return the URL for accessing the published asset.
  115. * <ul>
  116. * <li>If the asset is a file, its file modification time will be checked
  117. * to avoid unnecessary file copying;</li>
  118. * <li>If the asset is a directory, all files and subdirectories under it will
  119. * be published recursively. Note, in this case the method only checks the
  120. * existence of the target directory to avoid repetitive copying.</li>
  121. * </ul>
  122. * @param string $path the asset (file or directory) to be published
  123. * @param boolean $hashByName whether the published directory should be named as the hashed basename.
  124. * If false, the name will be the hashed dirname of the path being published.
  125. * Defaults to false. Set true if the path being published is shared among
  126. * different extensions.
  127. * @param integer $level level of recursive copying when the asset is a directory.
  128. * Level -1 means publishing all subdirectories and files;
  129. * Level 0 means publishing only the files DIRECTLY under the directory;
  130. * level N means copying those directories that are within N levels.
  131. * @param boolean $forceCopy whether we should copy the asset file or directory even if it is already published before.
  132. * This parameter is set true mainly during development stage when the original
  133. * assets are being constantly changed. The consequence is that the performance
  134. * is degraded, which is not a concern during development, however.
  135. * This parameter has been available since version 1.1.2.
  136. * @return string an absolute URL to the published asset
  137. * @throws CException if the asset to be published does not exist.
  138. */
  139. public function publish($path,$hashByName=false,$level=-1,$forceCopy=false)
  140. {
  141. if(isset($this->_published[$path]))
  142. return $this->_published[$path];
  143. else if(($src=realpath($path))!==false)
  144. {
  145. if(is_file($src))
  146. {
  147. $dir=$this->hash($hashByName ? basename($src) : dirname($src));
  148. $fileName=basename($src);
  149. $dstDir=$this->getBasePath().DIRECTORY_SEPARATOR.$dir;
  150. $dstFile=$dstDir.DIRECTORY_SEPARATOR.$fileName;
  151. if($this->linkAssets)
  152. {
  153. if(!is_file($dstFile))
  154. symlink($src,$dstFile);
  155. }
  156. else if(@filemtime($dstFile)<@filemtime($src) || $forceCopy)
  157. {
  158. if(!is_dir($dstDir))
  159. {
  160. mkdir($dstDir);
  161. @chmod($dstDir,0777);
  162. }
  163. copy($src,$dstFile);
  164. }
  165. return $this->_published[$path]=$this->getBaseUrl()."/$dir/$fileName";
  166. }
  167. else if(is_dir($src))
  168. {
  169. $dir=$this->hash($hashByName ? basename($src) : $src);
  170. $dstDir=$this->getBasePath().DIRECTORY_SEPARATOR.$dir;
  171. if($this->linkAssets)
  172. {
  173. if(!is_dir($dstDir))
  174. symlink($src,$dstDir);
  175. }
  176. else if(!is_dir($dstDir) || $forceCopy)
  177. CFileHelper::copyDirectory($src,$dstDir,array('exclude'=>array('.svn'),'level'=>$level));
  178. return $this->_published[$path]=$this->getBaseUrl().'/'.$dir;
  179. }
  180. }
  181. throw new CException(Yii::t('yii','The asset "{asset}" to be published does not exist.',
  182. array('{asset}'=>$path)));
  183. }
  184. /**
  185. * Returns the published path of a file path.
  186. * This method does not perform any publishing. It merely tells you
  187. * if the file or directory is published, where it will go.
  188. * @param string $path directory or file path being published
  189. * @param boolean $hashByName whether the published directory should be named as the hashed basename.
  190. * If false, the name will be the hashed dirname of the path being published.
  191. * Defaults to false. Set true if the path being published is shared among
  192. * different extensions.
  193. * @return string the published file path. False if the file or directory does not exist
  194. */
  195. public function getPublishedPath($path,$hashByName=false)
  196. {
  197. if(($path=realpath($path))!==false)
  198. {
  199. $base=$this->getBasePath().DIRECTORY_SEPARATOR;
  200. if(is_file($path))
  201. return $base . $this->hash($hashByName ? basename($path) : dirname($path)) . DIRECTORY_SEPARATOR . basename($path);
  202. else
  203. return $base . $this->hash($hashByName ? basename($path) : $path);
  204. }
  205. else
  206. return false;
  207. }
  208. /**
  209. * Returns the URL of a published file path.
  210. * This method does not perform any publishing. It merely tells you
  211. * if the file path is published, what the URL will be to access it.
  212. * @param string $path directory or file path being published
  213. * @param boolean $hashByName whether the published directory should be named as the hashed basename.
  214. * If false, the name will be the hashed dirname of the path being published.
  215. * Defaults to false. Set true if the path being published is shared among
  216. * different extensions.
  217. * @return string the published URL for the file or directory. False if the file or directory does not exist.
  218. */
  219. public function getPublishedUrl($path,$hashByName=false)
  220. {
  221. if(isset($this->_published[$path]))
  222. return $this->_published[$path];
  223. if(($path=realpath($path))!==false)
  224. {
  225. if(is_file($path))
  226. return $this->getBaseUrl().'/'.$this->hash($hashByName ? basename($path) : dirname($path)).'/'.basename($path);
  227. else
  228. return $this->getBaseUrl().'/'.$this->hash($hashByName ? basename($path) : $path);
  229. }
  230. else
  231. return false;
  232. }
  233. /**
  234. * Generate a CRC32 hash for the directory path. Collisions are higher
  235. * than MD5 but generates a much smaller hash string.
  236. * @param string $path string to be hashed.
  237. * @return string hashed string.
  238. */
  239. protected function hash($path)
  240. {
  241. return sprintf('%x',crc32($path.Yii::getVersion()));
  242. }
  243. }