Commit 41ea9485 by Qiang Xue

refactoring and documentation for asset/script management.

parent 4e8f9cea
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\base;
use Yii;
use yii\helpers\Html;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class ViewContent extends Component
{
const POS_HEAD = 1;
const POS_BEGIN = 2;
const POS_END = 3;
const TOKEN_HEAD = '<![CDATA[YII-BLOCK-HEAD]]>';
const TOKEN_BODY_BEGIN = '<![CDATA[YII-BLOCK-BODY-BEGIN]]>';
const TOKEN_BODY_END = '<![CDATA[YII-BLOCK-BODY-END]]>';
public $assetBundles;
public $title;
public $metaTags;
public $linkTags;
public $css;
public $cssFiles;
public $js;
public $jsFiles;
public $jsInHead;
public $jsFilesInHead;
public $jsInBody;
public $jsFilesInBody;
public function reset()
{
$this->assetBundles = null;
$this->title = null;
$this->metaTags = null;
$this->linkTags = null;
$this->css = null;
$this->cssFiles = null;
$this->js = null;
$this->jsFiles = null;
$this->jsInHead = null;
$this->jsFilesInHead = null;
$this->jsInBody = null;
$this->jsFilesInBody = null;
}
private $_assetManager;
/**
* @return \yii\web\AssetManager
*/
public function getAssetManager()
{
return $this->_assetManager ?: Yii::$app->getAssets();
}
public function setAssetManager($value)
{
$this->_assetManager = $value;
}
public function begin()
{
ob_start();
ob_implicit_flush(false);
}
public function end()
{
$content = ob_get_clean();
echo $this->populate($content);
}
public function beginBody()
{
echo self::TOKEN_BODY_BEGIN;
}
public function endBody()
{
echo self::TOKEN_BODY_END;
}
public function head()
{
echo self::TOKEN_HEAD;
}
public function registerAssetBundle($name)
{
if (!isset($this->assetBundles[$name])) {
$am = $this->getAssetManager();
$bundle = $am->getBundle($name);
if ($bundle !== null) {
$this->assetBundles[$name] = false;
$bundle->registerAssets($this, $am);
$this->assetBundles[$name] = true;
} else {
throw new InvalidConfigException("Unknown asset bundle: $name");
}
} elseif ($this->assetBundles[$name] === false) {
throw new InvalidConfigException("A cyclic dependency is detected for bundle '$name'.");
}
}
public function registerMetaTag($options, $key = null)
{
if ($key === null) {
$this->metaTags[] = Html::tag('meta', '', $options);
} else {
$this->metaTags[$key] = Html::tag('meta', '', $options);
}
}
public function registerLinkTag($options, $key = null)
{
if ($key === null) {
$this->linkTags[] = Html::tag('link', '', $options);
} else {
$this->linkTags[$key] = Html::tag('link', '', $options);
}
}
public function registerCss($css, $options = array(), $key = null)
{
$key = $key ?: $css;
$this->css[$key] = Html::style($css, $options);
}
public function registerCssFile($url, $options = array(), $key = null)
{
$key = $key ?: $url;
$this->cssFiles[$key] = Html::cssFile($url, $options);
}
public function registerJs($js, $options = array(), $key = null)
{
$position = isset($options['position']) ? $options['position'] : self::POS_END;
unset($options['position']);
$key = $key ?: $js;
$html = Html::script($js, $options);
if ($position == self::POS_END) {
$this->js[$key] = $html;
} elseif ($position == self::POS_HEAD) {
$this->jsInHead[$key] = $html;
} elseif ($position == self::POS_BEGIN) {
$this->jsInBody[$key] = $html;
} else {
throw new InvalidParamException("Unknown position: $position");
}
}
public function registerJsFile($url, $options = array(), $key = null)
{
$position = isset($options['position']) ? $options['position'] : self::POS_END;
unset($options['position']);
$key = $key ?: $url;
$html = Html::jsFile($url, $options);
if ($position == self::POS_END) {
$this->jsFiles[$key] = $html;
} elseif ($position == self::POS_HEAD) {
$this->jsFilesInHead[$key] = $html;
} elseif ($position == self::POS_BEGIN) {
$this->jsFilesInBody[$key] = $html;
} else {
throw new InvalidParamException("Unknown position: $position");
}
}
protected function populate($content)
{
return strtr($content, array(
self::TOKEN_HEAD => $this->getHeadHtml(),
self::TOKEN_BODY_BEGIN => $this->getBodyBeginHtml(),
self::TOKEN_BODY_END => $this->getBodyEndHtml(),
));
}
protected function getHeadHtml()
{
$lines = array();
if (!empty($this->metaTags)) {
$lines[] = implode("\n", $this->cssFiles);
}
if (!empty($this->linkTags)) {
$lines[] = implode("\n", $this->cssFiles);
}
if (!empty($this->cssFiles)) {
$lines[] = implode("\n", $this->cssFiles);
}
if (!empty($this->css)) {
$lines[] = implode("\n", $this->css);
}
if (!empty($this->jsFilesInHead)) {
$lines[] = implode("\n", $this->jsFilesInHead);
}
if (!empty($this->jsInHead)) {
$lines[] = implode("\n", $this->jsInHead);
}
return implode("\n", $lines);
}
protected function getBodyBeginHtml()
{
$lines = array();
if (!empty($this->jsFilesInBody)) {
$lines[] = implode("\n", $this->jsFilesInBody);
}
if (!empty($this->jsInHead)) {
$lines[] = implode("\n", $this->jsInBody);
}
return implode("\n", $lines);
}
protected function getBodyEndHtml()
{
$lines = array();
if (!empty($this->jsFiles)) {
$lines[] = implode("\n", $this->jsFiles);
}
if (!empty($this->js)) {
$lines[] = implode("\n", $this->js);
}
return implode("\n", $lines);
}
}
\ No newline at end of file
...@@ -101,9 +101,9 @@ class Application extends \yii\base\Application ...@@ -101,9 +101,9 @@ class Application extends \yii\base\Application
* Returns the asset manager. * Returns the asset manager.
* @return AssetManager the asset manager component * @return AssetManager the asset manager component
*/ */
public function getAssets() public function getAssetManager()
{ {
return $this->getComponent('assets'); return $this->getComponent('assetManager');
} }
/** /**
...@@ -126,7 +126,7 @@ class Application extends \yii\base\Application ...@@ -126,7 +126,7 @@ class Application extends \yii\base\Application
'user' => array( 'user' => array(
'class' => 'yii\web\User', 'class' => 'yii\web\User',
), ),
'assets' => array( 'assetManager' => array(
'class' => 'yii\web\AssetManager', 'class' => 'yii\web\AssetManager',
), ),
)); ));
......
...@@ -12,6 +12,14 @@ use yii\base\InvalidConfigException; ...@@ -12,6 +12,14 @@ use yii\base\InvalidConfigException;
use yii\base\Object; use yii\base\Object;
/** /**
* AssetBundle represents a collection of asset files, such as CSS, JS, images.
*
* Each asset bundle has a unique name that globally identifies it among all asset bundles
* used in an application.
*
* An asset bundle can depend on other asset bundles. When registering an asset bundle
* with a view, all its dependent asset bundles will be automatically registered.
*
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
*/ */
...@@ -66,7 +74,7 @@ class AssetBundle extends Object ...@@ -66,7 +74,7 @@ class AssetBundle extends Object
* *
* Each JavaScript file may be associated with options. In this case, the array key * 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 * should be the JavaScript file path, while the corresponding array value should
* be the option array. The options will be passed to [[ViewContent::registerJsFile()]]. * be the option array. The options will be passed to [[View::registerJsFile()]].
*/ */
public $js = array(); public $js = array();
/** /**
...@@ -78,7 +86,7 @@ class AssetBundle extends Object ...@@ -78,7 +86,7 @@ class AssetBundle extends Object
* *
* Each CSS file may be associated with options. In this case, the array key * 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 * should be the CSS file path, while the corresponding array value should
* be the option array. The options will be passed to [[ViewContent::registerCssFile()]]. * be the option array. The options will be passed to [[View::registerCssFile()]].
*/ */
public $css = array(); public $css = array();
/** /**
...@@ -108,14 +116,20 @@ class AssetBundle extends Object ...@@ -108,14 +116,20 @@ class AssetBundle extends Object
} }
/** /**
* @param \yii\base\ViewContent $page * Registers the CSS and JS files with the given view.
* @param AssetManager $am * This method will first register all dependent asset bundles.
* @throws InvalidConfigException * It will then try to convert non-CSS or JS files (e.g. LESS, Sass) into the corresponding
* CSS or JS files using [[AssetManager::converter|asset converter]].
* @param \yii\base\View $view the view that the asset files to be registered with.
* @throws InvalidConfigException if [[baseUrl]] or [[basePath]] is not set when the bundle
* contains internal CSS or JS files.
*/ */
public function registerAssets($page, $am) public function registerAssets($view)
{ {
$am = $view->getAssetManager();
foreach ($this->depends as $name) { foreach ($this->depends as $name) {
$page->registerAssetBundle($name); $view->registerAssetBundle($name);
} }
if ($this->sourcePath !== null) { if ($this->sourcePath !== null) {
...@@ -128,23 +142,23 @@ class AssetBundle extends Object ...@@ -128,23 +142,23 @@ class AssetBundle extends Object
$js = is_string($options) ? $options : $js; $js = is_string($options) ? $options : $js;
if (strpos($js, '/') !== 0 && strpos($js, '://') === false) { if (strpos($js, '/') !== 0 && strpos($js, '://') === false) {
if (isset($this->basePath, $this->baseUrl)) { if (isset($this->basePath, $this->baseUrl)) {
$js = $converter->convert(ltrim($js, '/'), $this->basePath, $this->baseUrl); $js = $converter->convert($js, $this->basePath, $this->baseUrl);
} else { } else {
throw new InvalidConfigException('Both of the "baseUrl" and "basePath" properties must be set.'); throw new InvalidConfigException('Both of the "baseUrl" and "basePath" properties must be set.');
} }
} }
$page->registerJsFile($js, is_array($options) ? $options : array()); $view->registerJsFile($js, is_array($options) ? $options : array());
} }
foreach ($this->css as $css => $options) { foreach ($this->css as $css => $options) {
$css = is_string($options) ? $options : $css; $css = is_string($options) ? $options : $css;
if (strpos($css, '//') !== 0 && strpos($css, '://') === false) { if (strpos($css, '/') !== 0 && strpos($css, '://') === false) {
if (isset($this->basePath, $this->baseUrl)) { if (isset($this->basePath, $this->baseUrl)) {
$css = $converter->convert(ltrim($css, '/'), $this->basePath, $this->baseUrl); $css = $converter->convert($css, $this->basePath, $this->baseUrl);
} else { } else {
throw new InvalidConfigException('Both of the "baseUrl" and "basePath" properties must be set.'); throw new InvalidConfigException('Both of the "baseUrl" and "basePath" properties must be set.');
} }
} }
$page->registerCssFile($css, is_array($options) ? $options : array()); $view->registerCssFile($css, is_array($options) ? $options : array());
} }
} }
} }
\ No newline at end of file
...@@ -14,6 +14,7 @@ use yii\base\InvalidParamException; ...@@ -14,6 +14,7 @@ use yii\base\InvalidParamException;
use yii\helpers\FileHelper; use yii\helpers\FileHelper;
/** /**
* AssetManager manages asset bundles and asset publishing.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0 * @since 2.0
...@@ -135,7 +136,8 @@ class AssetManager extends Component ...@@ -135,7 +136,8 @@ class AssetManager extends Component
private $_converter; private $_converter;
/** /**
* @return IAssetConverter * Returns the asset converter.
* @return IAssetConverter the asset converter.
*/ */
public function getConverter() public function getConverter()
{ {
...@@ -149,6 +151,12 @@ class AssetManager extends Component ...@@ -149,6 +151,12 @@ class AssetManager extends Component
return $this->_converter; return $this->_converter;
} }
/**
* Sets the asset converter.
* @param array|IAssetConverter $value the asset converter. This can be either
* an object implementing the [[IAssetConverter]] interface, or a configuration
* array that can be used to create the asset converter object.
*/
public function setConverter($value) public function setConverter($value)
{ {
$this->_converter = $value; $this->_converter = $value;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment