Commit abc1e0c2 by Carsten Brandt

fix issue #700

adjust depended asset position or throw exception on conflict
parent a6784f4a
......@@ -146,7 +146,7 @@ class View extends Component
* are the registered [[AssetBundle]] objects.
* @see registerAssetBundle
*/
public $assetBundles;
public $assetBundles = array();
/**
* @var string the page title
*/
......@@ -523,6 +523,9 @@ class View extends Component
$this->trigger(self::EVENT_END_PAGE);
$content = ob_get_clean();
foreach(array_keys($this->assetBundles) as $bundle) {
$this->registerAssetFiles($bundle);
}
echo strtr($content, array(
self::PH_HEAD => $this->renderHeadHtml(),
self::PH_BODY_BEGIN => $this->renderBodyBeginHtml(),
......@@ -530,7 +533,6 @@ class View extends Component
));
unset(
$this->assetBundles,
$this->metaTags,
$this->linkTags,
$this->css,
......@@ -566,25 +568,58 @@ class View extends Component
echo self::PH_HEAD;
}
protected function registerAssetFiles($name)
{
if (!isset($this->assetBundles[$name])) {
return;
}
$bundle = $this->assetBundles[$name];
foreach($bundle->depends as $depName) {
$this->registerAssetFiles($depName);
}
$bundle->registerAssets($this);
unset($this->assetBundles[$name]);
}
/**
* Registers the named asset bundle.
* All dependent asset bundles will be registered.
* @param string $name the name of the asset bundle.
* @param integer|null $position optional parameter to force a minimum Javascript position TODO link to relevant method
* Null means to register on default position.
* @return AssetBundle the registered asset bundle instance
* @throws InvalidConfigException if the asset bundle does not exist or a circular dependency is detected
*/
public function registerAssetBundle($name)
public function registerAssetBundle($name, $position = null)
{
if (!isset($this->assetBundles[$name])) {
$am = $this->getAssetManager();
$bundle = $am->getBundle($name);
$this->assetBundles[$name] = false;
$bundle->registerAssets($this);
// register dependencies
$pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
foreach ($bundle->depends as $dep) {
$this->registerAssetBundle($dep, $pos);
}
$this->assetBundles[$name] = $bundle;
} elseif ($this->assetBundles[$name] === false) {
throw new InvalidConfigException("A circular dependency is detected for bundle '$name'.");
} else {
$bundle = $this->assetBundles[$name];
}
if ($position !== null) {
$pos = isset($bundle->jsOptions['position']) ? $bundle->jsOptions['position'] : null;
if ($pos === null) {
$bundle->jsOptions['position'] = $pos = $position;
} elseif ($pos > $position) {
throw new InvalidConfigException("A dependend AssetBundle of '$name' requires a higher position but it conflicts with the position set for '$name'!");
}
foreach ($bundle->depends as $dep) {
$this->registerAssetBundle($dep, $pos);
}
}
return $this->assetBundles[$name];
return $bundle;
}
/**
......
......@@ -130,7 +130,6 @@ class AssetBundle extends Object
/**
* Registers the CSS and JS files with the given view.
* This method will first register all dependent asset bundles.
* 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.
......@@ -139,10 +138,6 @@ class AssetBundle extends Object
*/
public function registerAssets($view)
{
foreach ($this->depends as $name) {
$view->registerAssetBundle($name);
}
$this->publish($view->getAssetManager());
foreach ($this->js as $js) {
......
<?php
/**
* @var $this \yii\base\View
* @var $content string
*/
?>
<?php $this->beginPage(); ?>
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<?php $this->head(); ?>
</head>
<body>
<?php $this->beginBody(); ?>
<?php echo $content; ?>
<?php $this->endBody(); ?>
</body>
</html>
<?php $this->endPage(); ?>
\ No newline at end of file
<?php
/**
* @var $this \yii\base\View
*/
?><?php $this->beginPage(); ?>1<?php $this->head(); ?>2<?php $this->beginBody(); ?>3<?php $this->endBody(); ?>4<?php $this->endPage(); ?>
\ No newline at end of file
This is a damn simple view file.
\ No newline at end of file
......@@ -45,6 +45,13 @@ class AssetBundleTest extends \yiiunit\TestCase
TestJqueryAsset::register($view);
$this->assertEquals(1, count($view->assetBundles));
$this->assertArrayHasKey('yiiunit\\framework\\web\\TestJqueryAsset', $view->assetBundles);
$this->assertTrue($view->assetBundles['yiiunit\\framework\\web\\TestJqueryAsset'] instanceof AssetBundle);
$expected = <<<EOF
123<script src="/js/jquery.js"></script>
4
EOF;
$this->assertEquals($expected, $view->renderFile('@yiiunit/data/views/rawlayout.php'));
}
public function testSimpleDependency()
......@@ -56,6 +63,125 @@ class AssetBundleTest extends \yiiunit\TestCase
$this->assertEquals(2, count($view->assetBundles));
$this->assertArrayHasKey('yiiunit\\framework\\web\\TestAssetBundle', $view->assetBundles);
$this->assertArrayHasKey('yiiunit\\framework\\web\\TestJqueryAsset', $view->assetBundles);
$this->assertTrue($view->assetBundles['yiiunit\\framework\\web\\TestAssetBundle'] instanceof AssetBundle);
$this->assertTrue($view->assetBundles['yiiunit\\framework\\web\\TestJqueryAsset'] instanceof AssetBundle);
$expected = <<<EOF
1<link href="/files/cssFile.css" rel="stylesheet">
23<script src="/js/jquery.js"></script>
<script src="/files/jsFile.js"></script>
4
EOF;
$this->assertEquals($expected, $view->renderFile('@yiiunit/data/views/rawlayout.php'));
}
public function positionProvider()
{
return array(
array(View::POS_HEAD, true),
array(View::POS_HEAD, false),
array(View::POS_BEGIN, true),
array(View::POS_BEGIN, false),
array(View::POS_END, true),
array(View::POS_END, false),
);
}
/**
* @dataProvider positionProvider
*/
public function testPositionDependency($pos, $jqAlreadyRegistered)
{
$view = $this->getView();
$view->getAssetManager()->bundles['yiiunit\\framework\\web\\TestAssetBundle'] = array(
'jsOptions' => array(
'position' => $pos,
),
);
$this->assertEmpty($view->assetBundles);
if ($jqAlreadyRegistered) {
TestJqueryAsset::register($view);
}
TestAssetBundle::register($view);
$this->assertEquals(2, count($view->assetBundles));
$this->assertArrayHasKey('yiiunit\\framework\\web\\TestAssetBundle', $view->assetBundles);
$this->assertArrayHasKey('yiiunit\\framework\\web\\TestJqueryAsset', $view->assetBundles);
$this->assertTrue($view->assetBundles['yiiunit\\framework\\web\\TestAssetBundle'] instanceof AssetBundle);
$this->assertTrue($view->assetBundles['yiiunit\\framework\\web\\TestJqueryAsset'] instanceof AssetBundle);
$this->assertArrayHasKey('position', $view->assetBundles['yiiunit\\framework\\web\\TestAssetBundle']->jsOptions);
$this->assertEquals($pos, $view->assetBundles['yiiunit\\framework\\web\\TestAssetBundle']->jsOptions['position']);
$this->assertArrayHasKey('position', $view->assetBundles['yiiunit\\framework\\web\\TestJqueryAsset']->jsOptions);
$this->assertEquals($pos, $view->assetBundles['yiiunit\\framework\\web\\TestJqueryAsset']->jsOptions['position']);
switch($pos)
{
case View::POS_HEAD:
$expected = <<<EOF
1<link href="/files/cssFile.css" rel="stylesheet">
<script src="/js/jquery.js"></script>
<script src="/files/jsFile.js"></script>
234
EOF;
break;
case View::POS_BEGIN:
$expected = <<<EOF
1<link href="/files/cssFile.css" rel="stylesheet">
2<script src="/js/jquery.js"></script>
<script src="/files/jsFile.js"></script>
34
EOF;
break;
default:
case View::POS_END:
$expected = <<<EOF
1<link href="/files/cssFile.css" rel="stylesheet">
23<script src="/js/jquery.js"></script>
<script src="/files/jsFile.js"></script>
4
EOF;
break;
}
$this->assertEquals($expected, $view->renderFile('@yiiunit/data/views/rawlayout.php'));
}
public function positionProvider2()
{
return array(
array(View::POS_BEGIN, true),
array(View::POS_BEGIN, false),
array(View::POS_END, true),
array(View::POS_END, false),
);
}
/**
* @dataProvider positionProvider
*/
public function testPositionDependencyConflict($pos, $jqAlreadyRegistered)
{
$view = $this->getView();
$view->getAssetManager()->bundles['yiiunit\\framework\\web\\TestAssetBundle'] = array(
'jsOptions' => array(
'position' => $pos - 1,
),
);
$view->getAssetManager()->bundles['yiiunit\\framework\\web\\TestJqueryAsset'] = array(
'jsOptions' => array(
'position' => $pos,
),
);
$this->assertEmpty($view->assetBundles);
if ($jqAlreadyRegistered) {
TestJqueryAsset::register($view);
}
$this->setExpectedException('yii\\base\\InvalidConfigException');
TestAssetBundle::register($view);
}
}
......
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