Overview

Packages

  • application
    • commands
    • components
      • actions
      • filters
      • leftWidget
      • permissions
      • sortableWidget
      • util
      • webupdater
      • x2flow
        • actions
        • triggers
      • X2GridView
      • X2Settings
    • controllers
    • models
      • embedded
    • modules
      • accounts
        • controllers
        • models
      • actions
        • controllers
        • models
      • calendar
        • controllers
        • models
      • charts
        • models
      • contacts
        • controllers
        • models
      • docs
        • components
        • controllers
        • models
      • groups
        • controllers
        • models
      • marketing
        • components
        • controllers
        • models
      • media
        • controllers
        • models
      • mobile
        • components
      • opportunities
        • controllers
        • models
      • products
        • controllers
        • models
      • quotes
        • controllers
        • models
      • services
        • controllers
        • models
      • template
        • models
      • users
        • controllers
        • models
      • workflow
        • controllers
        • models
      • x2Leads
        • controllers
        • models
  • Net
  • None
  • PHP
  • system
    • base
    • caching
      • dependencies
    • collections
    • console
    • db
      • ar
      • schema
        • cubrid
        • mssql
        • mysql
        • oci
        • pgsql
        • sqlite
    • i18n
      • gettext
    • logging
    • test
    • utils
    • validators
    • web
      • actions
      • auth
      • filters
      • form
      • helpers
      • renderers
      • services
      • widgets
        • captcha
        • pagers
  • Text
    • Highlighter
  • zii
    • behaviors
    • widgets
      • grid
      • jui

Classes

  • ActionFormModelBase
  • CActiveDataProvider
  • CalendarEventFormModel
  • CallFormModel
  • CArrayDataProvider
  • CAssetManager
  • CBaseController
  • CBaseUrlRule
  • CCacheHttpSession
  • CClientScript
  • CController
  • CCookieCollection
  • CDataProvider
  • CDataProviderIterator
  • CDbHttpSession
  • CExtController
  • CFormModel
  • CHttpCookie
  • CHttpRequest
  • CHttpSession
  • CHttpSessionIterator
  • COutputEvent
  • CPagination
  • CreatePageFormModel
  • CSort
  • CSqlDataProvider
  • CTheme
  • CThemeManager
  • CUploadedFile
  • CUrlManager
  • CUrlRule
  • CWebApplication
  • CWebModule
  • CWidgetFactory
  • EditMobileFormsFormModel
  • EventCommentPublisherFormModel
  • EventFormModel
  • EventPublisherFormModel
  • FileSystemObjectDataProvider
  • MassActionFormModel
  • MobilePagination
  • NoteFormModel
  • NotificationsController
  • TimeFormModel
  • UploadLogoFormModel
  • X2FormModel
  • X2HttpRequest

Interfaces

  • IDataProvider
  • IWidgetFactory
  • Overview
  • Package
  • Class
  • Tree
  1: <?php
  2: /**
  3:  * CAssetManager class file.
  4:  *
  5:  * @author Qiang Xue <qiang.xue@gmail.com>
  6:  * @link http://www.yiiframework.com/
  7:  * @copyright 2008-2013 Yii Software LLC
  8:  * @license http://www.yiiframework.com/license/
  9:  */
 10: 
 11: 
 12: /**
 13:  * CAssetManager is a Web application component that manages private files (called assets) and makes them accessible by Web clients.
 14:  *
 15:  * It achieves this goal by copying assets to a Web-accessible directory
 16:  * and returns the corresponding URL for accessing them.
 17:  *
 18:  * To publish an asset, simply call {@link publish()}.
 19:  *
 20:  * The Web-accessible directory holding the published files is specified
 21:  * by {@link setBasePath basePath}, which defaults to the "assets" directory
 22:  * under the directory containing the application entry script file.
 23:  * The property {@link setBaseUrl baseUrl} refers to the URL for accessing
 24:  * the {@link setBasePath basePath}.
 25:  *
 26:  * @property string $basePath The root directory storing the published asset files. Defaults to 'WebRoot/assets'.
 27:  * @property string $baseUrl The base url that the published asset files can be accessed.
 28:  * Note, the ending slashes are stripped off. Defaults to '/AppBaseUrl/assets'.
 29:  *
 30:  * @author Qiang Xue <qiang.xue@gmail.com>
 31:  * @package system.web
 32:  * @since 1.0
 33:  */
 34: class CAssetManager extends CApplicationComponent
 35: {
 36:     /**
 37:      * Default web accessible base path for storing private files
 38:      */
 39:     const DEFAULT_BASEPATH='assets';
 40:     /**
 41:      * @var boolean whether to use symbolic link to publish asset files. Defaults to false, meaning
 42:      * asset files are copied to public folders. Using symbolic links has the benefit that the published
 43:      * assets will always be consistent with the source assets. This is especially useful during development.
 44:      *
 45:      * However, there are special requirements for hosting environments in order to use symbolic links.
 46:      * In particular, symbolic links are supported only on Linux/Unix, and Windows Vista/2008 or greater.
 47:      * The latter requires PHP 5.3 or greater.
 48:      *
 49:      * Moreover, some Web servers need to be properly configured so that the linked assets are accessible
 50:      * to Web users. For example, for Apache Web server, the following configuration directive should be added
 51:      * for the Web folder:
 52:      * <pre>
 53:      * Options FollowSymLinks
 54:      * </pre>
 55:      *
 56:      * Note that this property cannot be true when {@link $forceCopy} property has true value too. Otherwise
 57:      * an exception would be thrown. Using both properties at the same time is illogical because both of them
 58:      * are solving similar tasks but in a different ways. Please refer to the {@link $forceCopy} documentation
 59:      * for more details.
 60:      *
 61:      * @since 1.1.5
 62:      */
 63:     public $linkAssets=false;
 64:     /**
 65:      * @var array list of directories and files which should be excluded from the publishing process.
 66:      * Defaults to exclude '.svn' and '.gitignore' files only. This option has no effect if {@link linkAssets} is enabled.
 67:      * @since 1.1.6
 68:      **/
 69:     public $excludeFiles=array('.svn','.gitignore');
 70:     /**
 71:      * @var integer the permission to be set for newly generated asset files.
 72:      * This value will be used by PHP chmod function.
 73:      * Defaults to 0666, meaning the file is read-writable by all users.
 74:      * @since 1.1.8
 75:      */
 76:     public $newFileMode=0666;
 77:     /**
 78:      * @var integer the permission to be set for newly generated asset directories.
 79:      * This value will be used by PHP chmod function.
 80:      * Defaults to 0777, meaning the directory can be read, written and executed by all users.
 81:      * @since 1.1.8
 82:      */
 83:     public $newDirMode=0777;
 84:     /**
 85:      * @var boolean whether we should copy the asset files and directories even if they already published before.
 86:      * This property is used only during development stage. The main use case of this property is when you need
 87:      * to force the original assets always copied by changing only one value without searching needed {@link publish}
 88:      * method calls across the application codebase. Also it is useful in operating systems which does not fully
 89:      * support symbolic links (therefore it is not possible to use {@link $linkAssets}) or we don't want to use them.
 90:      * This property sets the default value of the $forceCopy parameter in {@link publish} method. Default value
 91:      * of this property is false meaning that the assets will be published only in case they don't exist in webroot
 92:      * assets directory.
 93:      *
 94:      * Note that this property cannot be true when {@link $linkAssets} property has true value too. Otherwise
 95:      * an exception would be thrown. Using both properties at the same time is illogical because both of them
 96:      * are solving similar tasks but in a different ways. Please refer to the {@link $linkAssets} documentation
 97:      * for more details.
 98:      *
 99:      * @since 1.1.11
100:      */
101:     public $forceCopy=false;
102:     /**
103:      * @var string base web accessible path for storing private files
104:      */
105:     private $_basePath;
106:     /**
107:      * @var string base URL for accessing the publishing directory.
108:      */
109:     private $_baseUrl;
110:     /**
111:      * @var array published assets
112:      */
113:     private $_published=array();
114: 
115:     /**
116:      * @return string the root directory storing the published asset files. Defaults to 'WebRoot/assets'.
117:      */
118:     public function getBasePath()
119:     {
120:         if($this->_basePath===null)
121:         {
122:             $request=Yii::app()->getRequest();
123:             $this->setBasePath(dirname($request->getScriptFile()).DIRECTORY_SEPARATOR.self::DEFAULT_BASEPATH);
124:         }
125:         return $this->_basePath;
126:     }
127: 
128:     /**
129:      * Sets the root directory storing published asset files.
130:      * @param string $value the root directory storing published asset files
131:      * @throws CException if the base path is invalid
132:      */
133:     public function setBasePath($value)
134:     {
135:         if(($basePath=realpath($value))!==false && is_dir($basePath) && is_writable($basePath))
136:             $this->_basePath=$basePath;
137:         else
138:             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.',
139:                 array('{path}'=>$value)));
140:     }
141: 
142:     /**
143:      * @return string the base url that the published asset files can be accessed.
144:      * Note, the ending slashes are stripped off. Defaults to '/AppBaseUrl/assets'.
145:      */
146:     public function getBaseUrl()
147:     {
148:         if($this->_baseUrl===null)
149:         {
150:             $request=Yii::app()->getRequest();
151:             $this->setBaseUrl($request->getBaseUrl().'/'.self::DEFAULT_BASEPATH);
152:         }
153:         return $this->_baseUrl;
154:     }
155: 
156:     /**
157:      * @param string $value the base url that the published asset files can be accessed
158:      */
159:     public function setBaseUrl($value)
160:     {
161:         $this->_baseUrl=rtrim($value,'/');
162:     }
163: 
164:     /**
165:      * Publishes a file or a directory.
166:      * This method will copy the specified asset to a web accessible directory
167:      * and return the URL for accessing the published asset.
168:      * <ul>
169:      * <li>If the asset is a file, its file modification time will be checked
170:      * to avoid unnecessary file copying;</li>
171:      * <li>If the asset is a directory, all files and subdirectories under it will
172:      * be published recursively. Note, in case $forceCopy is false the method only checks the
173:      * existence of the target directory to avoid repetitive copying.</li>
174:      * </ul>
175:      *
176:      * Note: On rare scenario, a race condition can develop that will lead to a
177:      * one-time-manifestation of a non-critical problem in the creation of the directory
178:      * that holds the published assets. This problem can be avoided altogether by 'requesting'
179:      * in advance all the resources that are supposed to trigger a 'publish()' call, and doing
180:      * that in the application deployment phase, before system goes live. See more in the following
181:      * discussion: http://code.google.com/p/yii/issues/detail?id=2579
182:      *
183:      * @param string $path the asset (file or directory) to be published
184:      * @param boolean $hashByName whether the published directory should be named as the hashed basename.
185:      * If false, the name will be the hash taken from dirname of the path being published and path mtime.
186:      * Defaults to false. Set true if the path being published is shared among
187:      * different extensions.
188:      * @param integer $level level of recursive copying when the asset is a directory.
189:      * Level -1 means publishing all subdirectories and files;
190:      * Level 0 means publishing only the files DIRECTLY under the directory;
191:      * level N means copying those directories that are within N levels.
192:      * @param boolean $forceCopy whether we should copy the asset file or directory even if it is already
193:      * published before. In case of publishing a directory old files will not be removed.
194:      * This parameter is set true mainly during development stage when the original
195:      * assets are being constantly changed. The consequence is that the performance is degraded,
196:      * which is not a concern during development, however. Default value of this parameter is null meaning
197:      * that it's value is controlled by {@link $forceCopy} class property. This parameter has been available
198:      * since version 1.1.2. Default value has been changed since 1.1.11.
199:      * Note that this parameter cannot be true when {@link $linkAssets} property has true value too. Otherwise
200:      * an exception would be thrown. Using this parameter with {@link $linkAssets} property at the same time
201:      * is illogical because both of them are solving similar tasks but in a different ways. Please refer
202:      * to the {@link $linkAssets} documentation for more details.
203:      * @return string an absolute URL to the published asset
204:      * @throws CException if the asset to be published does not exist.
205:      */
206:     public function publish($path,$hashByName=false,$level=-1,$forceCopy=null)
207:     {
208:         if($forceCopy===null)
209:             $forceCopy=$this->forceCopy;
210:         if($forceCopy && $this->linkAssets)
211:             throw new CException(Yii::t('yii','The "forceCopy" and "linkAssets" cannot be both true.'));
212:         if(isset($this->_published[$path]))
213:             return $this->_published[$path];
214:         elseif(is_string($path) && ($src=realpath($path))!==false)
215:         {
216:             $dir=$this->generatePath($src,$hashByName);
217:             $dstDir=$this->getBasePath().DIRECTORY_SEPARATOR.$dir;
218:             if(is_file($src))
219:             {
220:                 $fileName=basename($src);
221:                 $dstFile=$dstDir.DIRECTORY_SEPARATOR.$fileName;
222: 
223:                 if(!is_dir($dstDir))
224:                 {
225:                     mkdir($dstDir,$this->newDirMode,true);
226:                     @chmod($dstDir,$this->newDirMode);
227:                 }
228: 
229:                 if($this->linkAssets && !is_file($dstFile)) symlink($src,$dstFile);
230:                 elseif(@filemtime($dstFile)<@filemtime($src))
231:                 {
232:                     copy($src,$dstFile);
233:                     @chmod($dstFile,$this->newFileMode);
234:                 }
235: 
236:                 return $this->_published[$path]=$this->getBaseUrl()."/$dir/$fileName";
237:             }
238:             elseif(is_dir($src))
239:             {
240:                 if($this->linkAssets && !is_dir($dstDir))
241:                 {
242:                     symlink($src,$dstDir);
243:                 }
244:                 elseif(!is_dir($dstDir) || $forceCopy)
245:                 {
246:                     CFileHelper::copyDirectory($src,$dstDir,array(
247:                         'exclude'=>$this->excludeFiles,
248:                         'level'=>$level,
249:                         'newDirMode'=>$this->newDirMode,
250:                         'newFileMode'=>$this->newFileMode,
251:                     ));
252:                 }
253: 
254:                 return $this->_published[$path]=$this->getBaseUrl().'/'.$dir;
255:             }
256:         }
257:         throw new CException(Yii::t('yii','The asset "{asset}" to be published does not exist.',
258:             array('{asset}'=>$path)));
259:     }
260: 
261:     /**
262:      * Returns the published path of a file path.
263:      * This method does not perform any publishing. It merely tells you
264:      * if the file or directory is published, where it will go.
265:      * @param string $path directory or file path being published
266:      * @param boolean $hashByName whether the published directory should be named as the hashed basename.
267:      * If false, the name will be the hash taken from dirname of the path being published and path mtime.
268:      * Defaults to false. Set true if the path being published is shared among
269:      * different extensions.
270:      * @return string the published file path. False if the file or directory does not exist
271:      */
272:     public function getPublishedPath($path,$hashByName=false)
273:     {
274:         if(is_string($path) && ($path=realpath($path))!==false)
275:         {
276:             $base=$this->getBasePath().DIRECTORY_SEPARATOR.$this->generatePath($path,$hashByName);
277:             return is_file($path) ? $base.DIRECTORY_SEPARATOR.basename($path) : $base ;
278:         }
279:         else
280:             return false;
281:     }
282: 
283:     /**
284:      * Returns the URL of a published file path.
285:      * This method does not perform any publishing. It merely tells you
286:      * if the file path is published, what the URL will be to access it.
287:      * @param string $path directory or file path being published
288:      * @param boolean $hashByName whether the published directory should be named as the hashed basename.
289:      * If false, the name will be the hash taken from dirname of the path being published and path mtime.
290:      * Defaults to false. Set true if the path being published is shared among
291:      * different extensions.
292:      * @return string the published URL for the file or directory. False if the file or directory does not exist.
293:      */
294:     public function getPublishedUrl($path,$hashByName=false)
295:     {
296:         if(isset($this->_published[$path]))
297:             return $this->_published[$path];
298:         if(is_string($path) && ($path=realpath($path))!==false)
299:         {
300:             $base=$this->getBaseUrl().'/'.$this->generatePath($path,$hashByName);
301:             return is_file($path) ? $base.'/'.basename($path) : $base;
302:         }
303:         else
304:             return false;
305:     }
306: 
307:     /**
308:      * Generate a CRC32 hash for the directory path. Collisions are higher
309:      * than MD5 but generates a much smaller hash string.
310:      * @param string $path string to be hashed.
311:      * @return string hashed string.
312:      */
313:     protected function hash($path)
314:     {
315:         return sprintf('%x',crc32($path.Yii::getVersion()));
316:     }
317: 
318:     /**
319:      * Generates path segments relative to basePath.
320:      * @param string $file for which public path will be created.
321:      * @param bool $hashByName whether the published directory should be named as the hashed basename.
322:      * @return string path segments without basePath.
323:      * @since 1.1.13
324:      */
325:     protected function generatePath($file,$hashByName=false)
326:     {
327:         if (is_file($file))
328:             $pathForHashing=$hashByName ? dirname($file) : dirname($file).filemtime($file);
329:         else
330:             $pathForHashing=$hashByName ? $file : $file.filemtime($file);
331: 
332:         return $this->hash($pathForHashing);
333:     }
334: }
335: 
API documentation generated by ApiGen 2.8.0