diff --git a/core/lib/Drupal/Core/Asset/AssetInterface.php b/core/lib/Drupal/Core/Asset/AssetInterface.php index ebf7381..c8f2465 100644 --- a/core/lib/Drupal/Core/Asset/AssetInterface.php +++ b/core/lib/Drupal/Core/Asset/AssetInterface.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Asset; use Assetic\Asset\AssetInterface as AsseticAssetInterface; +use Drupal\Core\Asset\AssetLibraryReference; /** * Represents an asset. @@ -41,25 +42,75 @@ public function setPreprocessable($preprocess = TRUE); public function isPreprocessable(); /** - * Set an explicit weight for this asset. + * @todo can we do this with a filter? + */ + public function setBrowsers(); + + public function getBrowsers(); + + /** + * Declares that the current asset must follow the provided asset. + * + * This method describes sequencing, not a dependency. That is, passing an + * asset to this method does NOT declare that it should be used on the page; + * only that it IF that asset is declared elsewhere for use on the page, THEN + * this asset should always follow it. * - * Weight is used to determine asset ordering. Explicitly setting a weight - * is generally not a good idea, as weights are dynamically calculated. It is - * generally better to let the system determine the appropriate weight by - * looking at the entry point at which your asset was added to the stack. + * However, declaring an explicit dependency will trigger this method + * internally, so there is no need for client code to call it directly. * - * @param int $weight + * @param AssetInterface $asset + * The asset which the current asset should follow when rendered onto the + * page. * * @return void + * @throws \UnexpectedValueException + * If the current asset is of a different type (e.g. CSS vs. Javascript), an + * exception will be thrown. */ - public function setWeight($weight); + public function after(AssetInterface $asset); - public function getWeight(); + /** + * Indicates whether this asset has any sequencing requirements. + * + * Sequencing requirements are declared by calling AssetInterface::after(). + * + * @return bool + */ + public function hasSequencing(); /** - * @todo can we do this with a filter? + * Gets any assets that must precede this one in the rendering sequence. + * + * @return array + * An array of AssetInterface objects that should precede this one. */ - public function setBrowsers(); + public function getPreceders(); - public function getBrowsers(); + /** + * Declares a dependency on the provided asset library. + * + * @param AssetLibraryReference $reference + * + * @return void + */ + public function addDependency(AssetLibraryReference $reference); + + /** + * Indicates whether or not this asset has library dependencies. + * + * @return bool + */ + public function hasDependencies(); + + /** + * Gets the library dependencies attached to this asset, if any. + * + * This method may trigger some compilation steps, so if you only need to know + * whether or not the asset has dependencies but not what they are, call + * AssetInterface::hasDependencies(). + * + * @return array + */ + public function getDependencies(); } diff --git a/core/lib/Drupal/Core/Asset/BaseAsset.php b/core/lib/Drupal/Core/Asset/BaseAsset.php index c7fa521..97f8a80 100644 --- a/core/lib/Drupal/Core/Asset/BaseAsset.php +++ b/core/lib/Drupal/Core/Asset/BaseAsset.php @@ -41,10 +41,6 @@ protected $preprocess = TRUE; - protected $weightOffset = NULL; - - protected $explicitWeight = 0; - /** * Constructor. * @@ -191,40 +187,92 @@ public function isPreprocessable() { } /** - * Set an explicit weight for this asset. + * @todo can we do this with a filter? + */ + public function setBrowsers() { + // TODO: Implement setBrowsers() method. + } + + public function getBrowsers() { + // TODO: Implement getBrowsers() method. + } + + /** + * Declares that the current asset must follow the provided asset. + * + * This method describes sequencing, not a dependency. That is, passing an + * asset to this method does NOT declare that it should be used on the page; + * only that it IF that asset is declared elsewhere for use on the page, THEN + * this asset should always follow it. * - * Weight is used to determine asset ordering. Explicitly setting a weight - * is generally not a good idea, as weights are dynamically calculated. It is - * generally better to let the system determine the appropriate weight by - * looking at the entry point at which your asset was added to the stack. + * However, declaring an explicit dependency will trigger this method + * internally, so there is no need for client code to call it directly. * - * @param int $weight + * @param AssetInterface $asset + * The asset which the current asset should follow when rendered onto the + * page. * * @return void + * @throws \UnexpectedValueException + * If the current asset is of a different type (e.g. CSS vs. Javascript), an + * exception will be thrown. */ - public function setWeight($weight) { - $this->explicitWeight = (int) $weight; + public function after(AssetInterface $asset) { + // TODO: Implement after() method. } - public function getWeight($raw = FALSE) { - // @todo All of this is crap. - $weight = empty($this->explicitWeight) ? $this->weight : $this->explicitWeight; - if ($raw) { - return $weight; - } - else { - return $weight + $this->weightOffset; - } + /** + * Indicates whether this asset has any sequencing requirements. + * + * Sequencing requirements are declared by calling AssetInterface::after(). + * + * @return bool + */ + public function hasSequencing() { + // TODO: Implement hasSequencing() method. } /** - * @todo can we do this with a filter? + * Gets any assets that must precede this one in the rendering sequence. + * + * @return array + * An array of AssetInterface objects that should precede this one. */ - public function setBrowsers() { - // TODO: Implement setBrowsers() method. + public function getPreceders() { + // TODO: Implement getPreceders() method. } - public function getBrowsers() { - // TODO: Implement getBrowsers() method. + /** + * Declares a dependency on the provided asset library. + * + * @param AssetLibraryReference $reference + * + * @return void + */ + public function addDependency(AssetLibraryReference $reference) { + // TODO: Implement addDependency() method. + } + + /** + * Indicates whether or not this asset has library dependencies. + * + * @return bool + */ + public function hasDependencies() { + // TODO: Implement hasDependencies() method. } + + /** + * Gets the library dependencies attached to this asset, if any. + * + * This method may trigger some compilation steps, so if you only need to know + * whether or not the asset has dependencies but not what they are, call + * AssetInterface::hasDependencies(). + * + * @return array + */ + public function getDependencies() { + // TODO: Implement getDependencies() method. + } + } diff --git a/core/lib/Drupal/Core/Asset/JavascriptAssetInterface.php b/core/lib/Drupal/Core/Asset/JavascriptAssetInterface.php index 01f4930..ca4c220 100644 --- a/core/lib/Drupal/Core/Asset/JavascriptAssetInterface.php +++ b/core/lib/Drupal/Core/Asset/JavascriptAssetInterface.php @@ -19,10 +19,4 @@ public function setScope($scope); public function getScope(); public function getScopeDefault(); - -// public function addDependency($name); -// -// public function hasDependencies(); -// -// public function getDependencies(); } diff --git a/core/modules/system/lib/Drupal/system/Tests/Asset/AssetAssemblyTest.php b/core/modules/system/lib/Drupal/system/Tests/Asset/AssetAssemblyTest.php index 9c89370..d52e760 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Asset/AssetAssemblyTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Asset/AssetAssemblyTest.php @@ -73,17 +73,75 @@ public function testSingleBagAssetAssemblies() { public function testSortingAndDependencyResolution() { $bag = new AssetBag(); + // Populate a mock AssetLibraryManager with the jquery library. $alm = new AssetLibraryManager(); $alm->set('jquery', $this->createJQueryAssetLibrary()); $dep = new AssetLibraryReference('jquery', $alm); $css1 = new StylesheetFileAsset(DRUPAL_ROOT . '/core/misc/vertical-tabs.css'); $js1 = new JavascriptFileAsset(DRUPAL_ROOT . '/core/misc/ajax.js'); - // $js1->addDependency($dep); + $js1->addDependency($dep); $bag->add($css1); $bag->add($js1); - $this->assertEqual(array(new JavascriptFileAsset('core/misc/jquery.js'), $js1), $bag->getJs()); + // Calling getJs() should dereference the dependency into the object + // instance contained in the AssetLibraryManager. + $this->assertEqual(array($alm->get('jquery'), $js1), $bag->getJs()); + } + + /** + * Tests ensuring that multiple asset bags are combined together correctly. + * + * @todo introduce some dependency interweaving for real robustness. + */ + public function testMultiBagAssetAssemblies() { + $outer_bag = new AssetBag(); + + $css1 = new StylesheetFileAsset('core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Filter/fixtures/cssmin/main.css'); + $js1 = new JavascriptFileAsset('core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Filter/fixtures/jsmin/js.js'); + + $outer_bag->add($css1); + $outer_bag->add($js1); + + $inner_bag_one = new AssetBag(); + $inner_bag_two = new AssetBag(); + + $css2 = new StylesheetFileAsset('core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Filter/fixtures/cssmin/fonts.css'); + $js2 = new JavascriptFileAsset('core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Filter/fixtures/packer/example.js'); + $css3 = new StylesheetExternalAsset('http://example.com/style.css'); + $css4 = new StylesheetFileAsset('core/vendor/kriswallsmith/assetic/tests/Assetic/Test/Filter/fixtures/cssimport/import.css'); + + $inner_bag_one->add($css2); + $inner_bag_one->add($js2); + // The third asset goes to the inner-inner bag in order to test that it is + // spliced in correctly. + $inner_bag_two->add($css3); + $inner_bag_one->add($css4); + + $inner_bag_one->addAssetBag($inner_bag_two); + $outer_bag->addAssetBag($inner_bag_one); + + // Adding the bag will, by default, mark it as terminated and incapable of + // receiving new assets. + try { + $inner_bag_one->add(new JavascriptExternalAsset('http://example.com/script.js')); + $this->fail('Terminated AssetBag did not throw expected exception when attempting to add a new asset.'); + } + catch (\LogicException $e) { + $this->pass('Terminated AssetBag threw expected LogicException when attempting to add a new asset.'); + } + + $this->assertIdentical(array($css1, $css2, $css3, $css4), $outer_bag->getCss()); + $this->assertIdentical(array($js1, $js2), $outer_bag->getJs()); + } + + /** + * Tests to ensure expected variables for use by templates are retrievable. + * + * @todo variable-generated stage has not yet been dealt with. + */ + public function testTemplateVariableRetrieval() { + } }