diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 991b64ca4564..a9c5f5341e73 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -166,21 +166,36 @@ private function addTemplatingSection(NodeBuilder $rootNode) ->beforeNormalization() ->ifTrue(function($v){ return !is_array($v); }) ->then(function($v){ return array($v); }) - ->end() + ->end() ->prototype('scalar') ->beforeNormalization() ->ifTrue(function($v) { return is_array($v) && isset($v['id']); }) ->then(function($v){ return $v['id']; }) ->end() - ->end() ->end() + ->end() ->fixXmlConfig('loader') ->arrayNode('loaders') ->beforeNormalization() ->ifTrue(function($v){ return !is_array($v); }) ->then(function($v){ return array($v); }) - ->end() + ->end() ->prototype('scalar')->end() + ->end() + ->fixXmlConfig('package') + ->arrayNode('packages') + ->useAttributeAsKey('name') + ->prototype('array') + ->scalarNode('version')->defaultNull()->end() + ->fixXmlConfig('base_url') + ->arrayNode('base_urls') + ->prototype('scalar') + ->beforeNormalization() + ->ifTrue(function($v) { return is_array($v) && isset($v['value']); }) + ->then(function($v){ return $v['value']; }) + ->end() + ->end() + ->end() ->end() ->end() ; diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index bc31dfa277e1..f77d0f05beb7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -312,6 +312,15 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder $container->setParameter('templating.assets.base_urls', $config['assets_base_urls']); } + $packages = array(); + foreach ($config['packages'] as $name => $package) { + $packages[$name] = new Definition('Symfony\\Component\\Templating\\Asset\\AssetPackage', array( + $package['base_urls'], + $package['version'], + )); + } + $container->setParameter('templating.assets.packages', $packages); + if (!empty($config['loaders'])) { $loaders = array_map(function($loader) { return new Reference($loader); }, $config['loaders']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd index 2fc04e86fa15..1bc8db6c6672 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd @@ -91,6 +91,7 @@ + @@ -102,6 +103,15 @@ + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml index 1d3323aa3aca..a64b3c094efc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml @@ -34,6 +34,7 @@ %templating.assets.base_urls% %templating.assets.version% + %templating.assets.packages% diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php index 8a61e31f627f..d73fcb28e252 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php @@ -27,9 +27,10 @@ class AssetsHelper extends BaseAssetsHelper * @param Request $request A Request instance * @param string|array $baseURLs The domain URL or an array of domain URLs * @param string $version The version + * @param array $packages Asset packages indexed by name */ - public function __construct(Request $request, $baseURLs = array(), $version = null) + public function __construct(Request $request, $baseURLs = array(), $version = null, $packages = array()) { - parent::__construct($request->getBasePath(), $baseURLs, $version); + parent::__construct($request->getBasePath(), $baseURLs, $version, $packages); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php index 7f201cffcf89..1b2fc7cd416f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -35,6 +35,18 @@ 'cache_warmer' => true, 'engines' => array('php', 'twig'), 'loader' => array('loader.foo', 'loader.bar'), + 'packages' => array( + 'images' => array( + 'version' => '1.0.0', + 'base_urls' => array('http://images1.example.com', 'http://images2.example.com'), + ), + 'foo' => array( + 'version' => '1.0.0', + ), + 'bar' => array( + 'base_urls' => array('http://bar1.example.com', 'http://bar2.example.com'), + ), + ), ), 'translator' => array( 'enabled' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 8cdd6929c318..b03ce66b24cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -18,6 +18,15 @@ http://cdn.example.com + + http://images1.example.com + http://images2.example.com + + + + http://bar1.example.com + http://bar2.example.com + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index b0c6ef141aec..b1d92ff195c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -28,6 +28,14 @@ framework: cache_warmer: true engines: [php, twig] loader: [loader.foo, loader.bar] + packages: + images: + version: 1.0.0 + base_urls: ["http://images1.example.com", "http://images2.example.com"] + foo: + version: 1.0.0 + bar: + base_urls: ["http://images1.example.com", "http://images2.example.com"] translator: enabled: true fallback: fr diff --git a/src/Symfony/Bundle/TwigBundle/Extension/TemplatingExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/TemplatingExtension.php index f7c84f3f477a..113e7226987d 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/TemplatingExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/TemplatingExtension.php @@ -83,9 +83,9 @@ public function getUrl($name, array $parameters = array()) return $this->container->get('router')->generate($name, $parameters, true); } - public function getAssetUrl($location) + public function getAssetUrl($location, $packageName = null) { - return $this->container->get('templating.helper.assets')->getUrl($location); + return $this->container->get('templating.helper.assets')->getUrl($location, $packageName); } /** diff --git a/src/Symfony/Component/Templating/Asset/AssetPackage.php b/src/Symfony/Component/Templating/Asset/AssetPackage.php new file mode 100644 index 000000000000..ae6f4c834bae --- /dev/null +++ b/src/Symfony/Component/Templating/Asset/AssetPackage.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Templating\Asset; + +/** + * An asset package. + * + * @author Kris Wallsmith + */ +class AssetPackage implements AssetPackageInterface +{ + private $baseUrls; + private $version; + + /** + * Constructor. + * + * @param array|string $baseUrls The domain URL or an array of domain URLs + * @param string $version The version + */ + public function __construct($baseUrls = array(), $version = null) + { + $this->baseUrls = array(); + $this->version = $version; + + if (!is_array($baseUrls)) { + $baseUrls = (array) $baseUrls; + } + + foreach ($baseUrls as $baseUrl) { + $this->baseUrls[] = rtrim($baseUrl, '/'); + } + } + + public function getVersion() + { + return $this->version; + } + + public function getBaseUrl($path) + { + $count = count($this->baseUrls); + + if (0 === $count) { + return ''; + } + + if (1 === $count) { + return $this->baseUrls[0]; + } + + return $this->baseUrls[fmod(hexdec(substr(md5($path), 0, 10)), $count)]; + } +} diff --git a/src/Symfony/Component/Templating/Asset/AssetPackageInterface.php b/src/Symfony/Component/Templating/Asset/AssetPackageInterface.php new file mode 100644 index 000000000000..b8d15d38e6d3 --- /dev/null +++ b/src/Symfony/Component/Templating/Asset/AssetPackageInterface.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Templating\Asset; + +/** + * Asset package interface. + * + * @author Kris Wallsmith + */ +interface AssetPackageInterface +{ + /** + * Returns the asset package version. + * + * @return string The version string + */ + function getVersion(); + + /** + * Returns a base URL for the supplied path. + * + * @param string $path An asset path + * + * @return string A base URL + */ + function getBaseUrl($path); +} diff --git a/src/Symfony/Component/Templating/Helper/AssetsHelper.php b/src/Symfony/Component/Templating/Helper/AssetsHelper.php index ff38cdbe6350..5b7b3c2c2fa9 100644 --- a/src/Symfony/Component/Templating/Helper/AssetsHelper.php +++ b/src/Symfony/Component/Templating/Helper/AssetsHelper.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Templating\Helper; +use Symfony\Component\Templating\Asset\AssetPackage; +use Symfony\Component\Templating\Asset\AssetPackageInterface; + /** * AssetsHelper is the base class for all helper classes that manages assets. * @@ -22,11 +25,11 @@ * * @author Fabien Potencier */ -class AssetsHelper extends Helper +class AssetsHelper extends Helper implements AssetPackageInterface { protected $version; - protected $baseURLs; - protected $basePath; + protected $defaultPackage; + protected $packages; /** * Constructor. @@ -34,32 +37,62 @@ class AssetsHelper extends Helper * @param string $basePath The base path * @param string|array $baseURLs The domain URL or an array of domain URLs * @param string $version The version + * @param array $packages Asset packages indexed by name */ - public function __construct($basePath = null, $baseURLs = array(), $version = null) + public function __construct($basePath = null, $baseUrls = array(), $version = null, $packages = array()) { $this->setBasePath($basePath); - $this->setBaseURLs($baseURLs); - $this->version = $version; + $this->defaultPackage = new AssetPackage($baseUrls, $version); + $this->packages = array(); + + foreach ($packages as $name => $package) { + $this->setPackage($name, $package); + } } /** - * Gets the version to add to public URL. + * Adds an asset package to the helper. * - * @return string The current version + * @param string $name The package name + * @param AssetPackageInterface $package The package + */ + public function setPackage($name, AssetPackageInterface $package) + { + $this->packages[$name] = $package; + } + + /** + * Returns an asset package. + * + * @param string $name The name of the package or null for the default package + * + * @return AssetPackageInterface An asset package + * + * @throws InvalidArgumentException If there is no package by that name */ - public function getVersion() + public function getPackage($name = null) { - return $this->version; + if (null === $name) { + return $this->defaultPackage; + } + + if (!isset($this->packages[$name])) { + throw new \InvalidArgumentException(sprintf('There is no "%s" asset package.', $name)); + } + + return $this->packages[$name]; } /** - * Sets the version that is added to each public URL. + * Gets the version to add to public URL. + * + * @param string $package A package name * - * @param string $id The version + * @return string The current version */ - public function setVersion($version) + public function getVersion($packageName = null) { - $this->version = $version; + return $this->getPackage($packageName)->getVersion(); } /** @@ -96,71 +129,36 @@ public function setBasePath($basePath) * * @return string The base URL */ - public function getBaseURL($path) - { - $count = count($this->baseURLs); - - if (0 === $count) { - return ''; - } - - if (1 === $count) { - return $this->baseURLs[0]; - } - - return $this->baseURLs[fmod(hexdec(substr(md5($path), 0, 10)), $count)]; - - } - - /** - * Gets the base URLs. - * - * @return array The base URLs - */ - public function getBaseURLs() - { - return $this->baseURLs; - } - - /** - * Sets the base URLs. - * - * If you pass an array, the getBaseURL() will return a - * randomly pick one to use for each asset. - * - * @param string|array $baseURLs The base URLs - */ - public function setBaseURLs($baseURLs) + public function getBaseUrl($path, $packageName = null) { - if (!is_array($baseURLs)) { - $baseURLs = array($baseURLs); - } - - $this->baseURLs = array(); - foreach ($baseURLs as $URL) { - $this->baseURLs[] = rtrim($URL, '/'); - } + return $this->getPackage($packageName)->getBaseUrl($path); } /** * Returns the public path. * - * @param string $path A public path + * Absolute paths (i.e. http://...) are returned unmodified. + * + * @param string $path A public path + * @param string $packageName The name of the asset package to use * * @return string A public path which takes into account the base path and URL path */ - public function getUrl($path) + public function getUrl($path, $packageName = null) { if (false !== strpos($path, '://')) { return $path; } - $base = $this->getBaseURL($path); + $package = $this->getPackage($packageName); + $base = $package->getBaseUrl($path); + $version = $package->getVersion(); + if (0 !== strpos($path, '/')) { $path = $base ? '/'.$path : $this->basePath.$path; } - return $base.$path.($this->version ? '?'.$this->version : ''); + return $base.$path.($version ? '?'.$version : ''); } /** diff --git a/tests/Symfony/Tests/Component/Templating/Helper/AssetsTest.php b/tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php similarity index 73% rename from tests/Symfony/Tests/Component/Templating/Helper/AssetsTest.php rename to tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php index e93044e02b06..fd5d01e0733b 100644 --- a/tests/Symfony/Tests/Component/Templating/Helper/AssetsTest.php +++ b/tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php @@ -11,6 +11,7 @@ namespace Symfony\Tests\Component\Templating\Helper; +use Symfony\Component\Templating\Asset\AssetPackage; use Symfony\Component\Templating\Helper\AssetsHelper; class AssetsHelperTest extends \PHPUnit_Framework_TestCase @@ -19,8 +20,7 @@ public function testConstructor() { $helper = new AssetsHelper('foo', 'http://www.example.com', 'abcd'); $this->assertEquals('/foo/', $helper->getBasePath(), '__construct() takes a base path as its first argument'); - $this->assertEquals(array('http://www.example.com'), $helper->getBaseURLs(), '__construct() takes a base URL as its second argument'); - $this->assertEquals('abcd', $helper->getVersion(), '__construct() takes a version as its thrid argument'); + $this->assertEquals(new AssetPackage('http://www.example.com', 'abcd'), $helper->getPackage(), '->__construct() creates a default asset package'); } public function testGetSetBasePath() @@ -36,28 +36,10 @@ public function testGetSetBasePath() $this->assertEquals('/0/', $helper->getBasePath(), '->setBasePath() returns /0/ if 0 is given'); } - public function testGetSetVersion() + public function testGetVersion() { - $helper = new AssetsHelper(); - $helper->setVersion('foo'); - $this->assertEquals('foo', $helper->getVersion(), '->setVersion() sets the version'); - } - - public function testSetGetBaseURLs() - { - $helper = new AssetsHelper(); - $helper->setBaseURLs('http://www.example.com/'); - $this->assertEquals(array('http://www.example.com'), $helper->getBaseURLs(), '->setBaseURLs() removes the / at the of an absolute base path'); - $helper->setBaseURLs(array('http://www1.example.com/', 'http://www2.example.com/')); - $URLs = array(); - for ($i = 0; $i < 20; $i++) { - $URLs[] = $helper->getBaseURL($i); - } - $URLs = array_values(array_unique($URLs)); - sort($URLs); - $this->assertEquals(array('http://www1.example.com', 'http://www2.example.com'), $URLs, '->getBaseURL() returns a random base URL if several are given'); - $helper->setBaseURLs(''); - $this->assertEquals('', $helper->getBaseURL(1), '->getBaseURL() returns an empty string if no base URL exist'); + $helper = new AssetsHelper(null, array(), 'foo'); + $this->assertEquals('foo', $helper->getVersion(), '->getVersion() returns the version'); } public function testGetUrl()