Browse Source

draft of script/asset management is done.

tags/2.0.0-beta
Qiang Xue 12 years ago
parent
commit
8f9cfa2c30
  1. 50
      framework/helpers/base/FileHelper.php
  2. 40
      framework/web/AssetBundle.php
  3. 107
      framework/web/AssetManager.php

50
framework/helpers/base/FileHelper.php

@ -86,11 +86,14 @@ class FileHelper
{
if (function_exists('finfo_open')) {
$info = finfo_open(FILEINFO_MIME_TYPE, $magicFile);
if ($info && ($result = finfo_file($info, $file)) !== false) {
if ($info) {
$result = finfo_file($info, $file);
finfo_close($info);
if ($result !== false) {
return $result;
}
}
}
return $checkExtension ? self::getMimeTypeByExtension($file) : null;
}
@ -122,4 +125,49 @@ class FileHelper
}
/**
* Copies a whole directory as another one.
* The files and sub-directories will also be copied over.
* @param string $src the source directory
* @param string $dst the destination directory
* @param array $options options for directory copy. Valid options are:
*
* - dirMode: integer, the permission to be set for newly copied directories. Defaults to 0777.
* - fileMode: integer, the permission to be set for newly copied files. Defaults to the current environment setting.
* - filter: callback, a PHP callback that is called for every sub-directory and file to
* determine if it should be copied. The signature of the callback should be:
*
* ~~~
* // $path is the file/directory path to be copied
* function ($path) {
* // return a boolean indicating if $path should be copied
* }
* ~~~
*/
public static function copyDirectory($src, $dst, $options = array())
{
if (!is_dir($dst)) {
mkdir($dst, isset($options['dirMode']) ? $options['dirMode'] : 0777, true);
}
$handle = opendir($src);
while (($file = readdir($handle)) !== false) {
if ($file === '.' || $file === '..') {
continue;
}
$srcPath = $src . DIRECTORY_SEPARATOR . $file;
if (!isset($options['filter']) || call_user_func($options['filter'], $srcPath)) {
$dstPath = $dst . DIRECTORY_SEPARATOR . $file;
if (is_file($srcPath)) {
copy($srcPath, $dstPath);
if (isset($options['fileMode'])) {
chmod($dstPath, $options['fileMode']);
}
} else {
static::copyDirectory($srcPath, $dstPath, $options);
}
}
}
closedir($handle);
}
}

40
framework/web/AssetBundle.php

@ -11,27 +11,6 @@ use Yii;
use yii\base\Object;
/**
* Each asset bundle should be declared with the following structure:
*
* ~~~
* array(
* 'basePath' => '...',
* 'baseUrl' => '...', // if missing, the bundle will be published to the "www/assets" folder
* 'js' => array(
* 'js/main.js',
* 'js/menu.js',
* 'js/base.js' => self::POS_HEAD,
* 'css' => array(
* 'css/main.css',
* 'css/menu.css',
* ),
* 'depends' => array(
* 'jquery',
* 'yii',
* 'yii/treeview',
* ),
* )
* ~~~
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
@ -61,9 +40,26 @@ class AssetBundle extends Object
*
* Note that you should not use backward slashes "\" to specify JavaScript files.
*
* A JavaScript file can be associated with the options: // todo
* Each JavaScript file may be associated with options. In this case, the array key
* should be the JavaScript file path, while the corresponding array value should
* be the option array. The options will be passed to [[ViewContent::registerJsFile()]].
*/
public $js = array();
/**
* @var array list of CSS files that this bundle contains. Each CSS file can
* be specified in one of the three formats:
*
* - a relative path: a path relative to [[basePath]] if [[basePath]] is set,
* or a URL relative to [[baseUrl]] if [[basePath]] is not set;
* - an absolute URL;
* - a path alias that can be resolved into a relative path or an absolute URL.
*
* Note that you should not use backward slashes "\" to specify CSS files.
*
* Each CSS file may be associated with options. In this case, the array key
* should be the CSS file path, while the corresponding array value should
* be the option array. The options will be passed to [[ViewContent::registerCssFile()]].
*/
public $css = array();
/**
* @var array list of the bundle names that this bundle depends on

107
framework/web/AssetManager.php

@ -11,6 +11,7 @@ use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\helpers\FileHelper;
/**
*
@ -58,24 +59,22 @@ class AssetManager extends Component
**/
public $excludeFiles = array('.svn', '.gitignore');
/**
* @var integer the permission to be set for newly generated asset files.
* This value will be used by PHP chmod function.
* Defaults to 0666, meaning the file is read-writable by all users.
* @since 1.1.8
* @var integer the permission to be set for newly published asset files.
* This value will be used by PHP chmod() function.
* If not set, the permission will be determined by the current environment.
*/
public $newFileMode = 0666;
public $fileMode;
/**
* @var integer the permission to be set for newly generated asset directories.
* This value will be used by PHP chmod function.
* This value will be used by PHP chmod() function.
* Defaults to 0777, meaning the directory can be read, written and executed by all users.
* @since 1.1.8
*/
public $newDirMode = 0777;
public $dirMode = 0777;
/**
* @var array published assets
* Initializes the component.
* @throws InvalidConfigException if [[basePath]] is invalid
*/
private $_published = array();
public function init()
{
parent::init();
@ -136,16 +135,22 @@ class AssetManager extends Component
}
/**
* @var array published assets
*/
private $_published = array();
/**
* Publishes a file or a directory.
* This method will copy the specified asset to a web accessible directory
* and return the URL for accessing the published asset.
* <ul>
* <li>If the asset is a file, its file modification time will be checked
* to avoid unnecessary file copying;</li>
* <li>If the asset is a directory, all files and subdirectories under it will
* be published recursively. Note, in case $forceCopy is false the method only checks the
* existence of the target directory to avoid repetitive copying.</li>
* </ul>
*
* This method will copy the specified file or directory to [[basePath]] so that
* it can be accessed via the Web server.
*
* If the asset is a file, its file modification time will be checked to avoid
* unnecessary file copying.
*
* If the asset is a directory, all files and subdirectories under it will be published recursively.
* Note, in case $forceCopy is false the method only checks the existence of the target
* directory to avoid repetitive copying (which is very expensive).
*
* Note: On rare scenario, a race condition can develop that will lead to a
* one-time-manifestation of a non-critical problem in the creation of the directory
@ -155,23 +160,14 @@ class AssetManager extends Component
* discussion: http://code.google.com/p/yii/issues/detail?id=2579
*
* @param string $path the asset (file or directory) to be published
* @param boolean $hashByName whether the published directory should be named as the hashed basename.
* If false, the name will be the hash taken from dirname of the path being published and path mtime.
* Defaults to false. Set true if the path being published is shared among
* different extensions.
* @param integer $level level of recursive copying when the asset is a directory.
* Level -1 means publishing all subdirectories and files;
* Level 0 means publishing only the files DIRECTLY under the directory;
* level N means copying those directories that are within N levels.
* @param boolean $forceCopy whether we should copy the asset file or directory even if it is already published before.
* This parameter is set true mainly during development stage when the original
* assets are being constantly changed. The consequence is that the performance
* @param boolean $forceCopy whether the asset should ALWAYS be copied even if it is found
* in the target directory. This parameter is mainly useful during the development stage
* when the original assets are being constantly changed. The consequence is that the performance
* is degraded, which is not a concern during development, however.
* This parameter has been available since version 1.1.2.
* @return string an absolute URL to the published asset
* @throws CException if the asset to be published does not exist.
* @throws InvalidParamException if the asset to be published does not exist.
*/
public function publish($path, $hashByName = false, $level = -1, $forceCopy = false)
public function publish($path, $forceCopy = false)
{
if (isset($this->_published[$path])) {
return $this->_published[$path];
@ -183,13 +179,13 @@ class AssetManager extends Component
}
if (is_file($src)) {
$dir = $this->hash($hashByName ? basename($src) : dirname($src) . filemtime($src));
$dir = $this->hash(dirname($src) . filemtime($src));
$fileName = basename($src);
$dstDir = $this->basePath . DIRECTORY_SEPARATOR . $dir;
$dstFile = $dstDir . DIRECTORY_SEPARATOR . $fileName;
if (!is_dir($dstDir)) {
@mkdir($dstDir, $this->newDirMode, true);
@mkdir($dstDir, $this->dirMode, true);
}
@ -197,30 +193,27 @@ class AssetManager extends Component
if (!is_file($dstFile)) {
symlink($src, $dstFile);
}
} elseif (@filemtime($dstFile) < @filemtime($src)) {
} elseif (@filemtime($dstFile) < @filemtime($src) || $forceCopy) {
copy($src, $dstFile);
@chmod($dstFile, $this->newFileMode);
if ($this->fileMode !== null) {
@chmod($dstFile, $this->fileMode);
}
}
$url = $this->baseUrl . "/$dir/$fileName";
} else {
$dir = $this->hash($hashByName ? basename($src) : $src . filemtime($src));
$dir = $this->hash($src . filemtime($src));
$dstDir = $this->basePath . DIRECTORY_SEPARATOR . $dir;
if ($this->linkAssets) {
if (!is_dir($dstDir)) {
symlink($src, $dstDir);
}
} else {
if (!is_dir($dstDir) || $forceCopy) {
} elseif (!is_dir($dstDir) || $forceCopy) {
FileHelper::copyDirectory($src, $dstDir, array(
'exclude' => $this->excludeFiles,
'level' => $level,
'newDirMode' => $this->newDirMode,
'newFileMode' => $this->newFileMode,
'dirMode' => $this->dirMode,
'fileMode' => $this->fileMode,
));
}
}
$url = $this->baseUrl . '/' . $dir;
}
@ -232,20 +225,16 @@ class AssetManager extends Component
* This method does not perform any publishing. It merely tells you
* if the file or directory is published, where it will go.
* @param string $path directory or file path being published
* @param boolean $hashByName whether the published directory should be named as the hashed basename.
* If false, the name will be the hash taken from dirname of the path being published and path mtime.
* Defaults to false. Set true if the path being published is shared among
* different extensions.
* @return string the published file path. False if the file or directory does not exist
*/
public function getPublishedPath($path, $hashByName = false)
public function getPublishedPath($path)
{
if (($path = realpath($path)) !== false) {
$base = $this->basePath . DIRECTORY_SEPARATOR;
if (is_file($path)) {
return $base . $this->hash($hashByName ? basename($path) : dirname($path) . filemtime($path)) . DIRECTORY_SEPARATOR . basename($path);
return $base . $this->hash(dirname($path) . filemtime($path)) . DIRECTORY_SEPARATOR . basename($path);
} else {
return $base . $this->hash($hashByName ? basename($path) : $path . filemtime($path));
return $base . $this->hash($path . filemtime($path));
}
} else {
return false;
@ -257,22 +246,18 @@ class AssetManager extends Component
* This method does not perform any publishing. It merely tells you
* if the file path is published, what the URL will be to access it.
* @param string $path directory or file path being published
* @param boolean $hashByName whether the published directory should be named as the hashed basename.
* If false, the name will be the hash taken from dirname of the path being published and path mtime.
* Defaults to false. Set true if the path being published is shared among
* different extensions.
* @return string the published URL for the file or directory. False if the file or directory does not exist.
*/
public function getPublishedUrl($path, $hashByName = false)
public function getPublishedUrl($path)
{
if (isset($this->_published[$path])) {
return $this->_published[$path];
}
if (($path = realpath($path)) !== false) {
if (is_file($path)) {
return $this->baseUrl . '/' . $this->hash($hashByName ? basename($path) : dirname($path) . filemtime($path)) . '/' . basename($path);
return $this->baseUrl . '/' . $this->hash(dirname($path) . filemtime($path)) . '/' . basename($path);
} else {
return $this->baseUrl . '/' . $this->hash($hashByName ? basename($path) : $path . filemtime($path));
return $this->baseUrl . '/' . $this->hash($path . filemtime($path));
}
} else {
return false;

Loading…
Cancel
Save