diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index 802abe8cbdb4b..da0d6d6e7b714 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -179,21 +179,56 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
private function addTemplatingSection(ArrayNodeDefinition $rootNode)
{
+ $organizeUrls = function($urls)
+ {
+ $urls += array(
+ 'http' => array(),
+ 'ssl' => array(),
+ );
+
+ foreach ($urls as $i => $url) {
+ if (is_integer($i)) {
+ if (0 === strpos($url, 'https://') || 0 === strpos($url, '//')) {
+ $urls['http'][] = $urls['ssl'][] = $url;
+ } else {
+ $urls['http'][] = $url;
+ }
+ unset($urls[$i]);
+ }
+ }
+
+ return $urls;
+ };
+
$rootNode
->children()
->arrayNode('templating')
->canBeUnset()
->children()
->scalarNode('assets_version')->defaultValue(null)->end()
+ ->scalarNode('assets_version_format')->defaultValue(null)->end()
->end()
->fixXmlConfig('assets_base_url')
->children()
->arrayNode('assets_base_urls')
+ ->addDefaultsIfNotSet()
+ ->defaultValue(array('http' => array(), 'ssl' => array()))
->beforeNormalization()
- ->ifTrue(function($v){ return !is_array($v); })
- ->then(function($v){ return array($v); })
+ ->ifTrue(function($v) { return !is_array($v); })
+ ->then(function($v) { return array($v); })
+ ->end()
+ ->beforeNormalization()
+ ->always()
+ ->then($organizeUrls)
+ ->end()
+ ->children()
+ ->arrayNode('http')
+ ->prototype('scalar')->end()
+ ->end()
+ ->arrayNode('ssl')
+ ->prototype('scalar')->end()
+ ->end()
->end()
- ->prototype('scalar')->end()
->end()
->scalarNode('cache')->end()
->scalarNode('cache_warmer')->defaultFalse()->end()
@@ -228,8 +263,26 @@ private function addTemplatingSection(ArrayNodeDefinition $rootNode)
->fixXmlConfig('base_url')
->children()
->scalarNode('version')->defaultNull()->end()
+ ->scalarNode('version_format')->defaultNull()->end()
->arrayNode('base_urls')
- ->prototype('scalar')->end()
+ ->addDefaultsIfNotSet()
+ ->defaultValue(array('http' => array(), 'ssl' => array()))
+ ->beforeNormalization()
+ ->ifTrue(function($v) { return !is_array($v); })
+ ->then(function($v) { return array($v); })
+ ->end()
+ ->beforeNormalization()
+ ->always()
+ ->then($organizeUrls)
+ ->end()
+ ->children()
+ ->arrayNode('http')
+ ->prototype('scalar')->end()
+ ->end()
+ ->arrayNode('ssl')
+ ->prototype('scalar')->end()
+ ->end()
+ ->end()
->end()
->end()
->end()
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index c3d8abf4b8a52..a10b0548a5533 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -14,6 +14,7 @@
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Parameter;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
@@ -332,17 +333,19 @@ private function registerTemplatingConfiguration(array $config, $ide, ContainerB
$loader->load('templating_debug.xml');
}
- $packages = array();
+ // create package definitions and add them to the assets helper
+ $defaultPackage = $this->createPackageDefinition($container, $config['assets_base_urls']['http'], $config['assets_base_urls']['ssl'], $config['assets_version'], $config['assets_version_format']);
+ $container->setDefinition('templating.asset.default_package', $defaultPackage);
+ $namedPackages = array();
foreach ($config['packages'] as $name => $package) {
- $packages[$name] = new Definition('%templating.asset_package.class%', array(
- $package['base_urls'],
- $package['version'],
- ));
+ $namedPackage = $this->createPackageDefinition($container, $package['base_urls']['http'], $package['base_urls']['ssl'], $package['version'], $package['version_format'], $name);
+ $container->setDefinition('templating.asset.package.'.$name, $namedPackage);
+ $namedPackages[$name] = new Reference('templating.asset.package.'.$name);
}
-
- $container->setParameter('templating.helper.assets.assets_base_urls', isset($config['assets_base_urls']) ? $config['assets_base_urls'] : array());
- $container->setParameter('templating.helper.assets.assets_version', $config['assets_version']);
- $container->getDefinition('templating.helper.assets')->replaceArgument(3, $packages);
+ $container->getDefinition('templating.helper.assets')->setArguments(array(
+ new Reference('templating.asset.default_package'),
+ $namedPackages,
+ ));
if (!empty($config['loaders'])) {
$loaders = array_map(function($loader) { return new Reference($loader); }, $config['loaders']);
@@ -412,6 +415,73 @@ private function registerTemplatingConfiguration(array $config, $ide, ContainerB
}
}
+ /**
+ * Returns a definition for an asset package.
+ */
+ private function createPackageDefinition(ContainerBuilder $container, array $httpUrls, array $sslUrls, $version, $format, $name = null)
+ {
+ if (!$httpUrls) {
+ $package = new DefinitionDecorator('templating.asset.path_package');
+ $package
+ ->setPublic(false)
+ ->setScope('request')
+ ->replaceArgument(1, $version)
+ ->replaceArgument(2, $format)
+ ;
+
+ return $package;
+ }
+
+ if ($httpUrls == $sslUrls) {
+ $package = new DefinitionDecorator('templating.asset.url_package');
+ $package
+ ->setPublic(false)
+ ->replaceArgument(0, $sslUrls)
+ ->replaceArgument(1, $version)
+ ->replaceArgument(2, $format)
+ ;
+
+ return $package;
+ }
+
+ $prefix = $name ? 'templating.asset.package.'.$name : 'templating.asset.default_package';
+
+ $httpPackage = new DefinitionDecorator('templating.asset.url_package');
+ $httpPackage
+ ->replaceArgument(0, $httpUrls)
+ ->replaceArgument(1, $version)
+ ->replaceArgument(2, $format)
+ ;
+ $container->setDefinition($prefix.'.http', $httpPackage);
+
+ if ($sslUrls) {
+ $sslPackage = new DefinitionDecorator('templating.asset.url_package');
+ $sslPackage
+ ->replaceArgument(0, $sslUrls)
+ ->replaceArgument(1, $version)
+ ->replaceArgument(2, $format)
+ ;
+ } else {
+ $sslPackage = new DefinitionDecorator('templating.asset.path_package');
+ $sslPackage
+ ->setScope('request')
+ ->replaceArgument(1, $version)
+ ->replaceArgument(2, $format)
+ ;
+ }
+ $container->setDefinition($prefix.'.ssl', $sslPackage);
+
+ $package = new DefinitionDecorator('templating.asset.request_aware_package');
+ $package
+ ->setPublic(false)
+ ->setScope('request')
+ ->replaceArgument(1, $prefix.'.http')
+ ->replaceArgument(2, $prefix.'.ssl')
+ ;
+
+ return $package;
+ }
+
/**
* Loads the translator configuration.
*
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 161ad6690749a..16f8366a4135a 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
@@ -103,6 +103,7 @@
+
@@ -114,6 +115,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml
index f2b2eec5d4241..ebdf3e6181188 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml
@@ -7,7 +7,7 @@
Symfony\Bundle\FrameworkBundle\Templating\PhpEngine
Symfony\Component\Templating\Helper\SlotsHelper
- Symfony\Bundle\FrameworkBundle\Templating\Helper\AssetsHelper
+ Symfony\Component\Templating\Helper\CoreAssetsHelper
Symfony\Bundle\FrameworkBundle\Templating\Helper\ActionsHelper
Symfony\Bundle\FrameworkBundle\Templating\Helper\RouterHelper
Symfony\Bundle\FrameworkBundle\Templating\Helper\RequestHelper
@@ -16,7 +16,9 @@
Symfony\Bundle\FrameworkBundle\Templating\Helper\TranslatorHelper
Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper
Symfony\Bundle\FrameworkBundle\Templating\GlobalVariables
- Symfony\Component\Templating\Asset\AssetPackage
+ Symfony\Bundle\FrameworkBundle\Templating\Asset\PathPackage
+ Symfony\Component\Templating\Asset\UrlPackage
+ Symfony\Bundle\FrameworkBundle\Templating\Asset\PackageFactory
@@ -32,12 +34,32 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- %templating.helper.assets.assets_base_urls%
- %templating.helper.assets.assets_version%
-
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PackageFactory.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PackageFactory.php
new file mode 100644
index 0000000000000..de36a32831960
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PackageFactory.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Templating\Asset;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Creates packages based on whether the current request is secure.
+ *
+ * @author Kris Wallsmith
+ */
+class PackageFactory
+{
+ private $container;
+
+ public function __construct(ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * Returns either the HTTP or SSL version of an asset package.
+ *
+ * @param Request $request The current request
+ * @param string $httpId The id for the package to use when the current request is HTTP
+ * @param string $sslId The id for the package to use when the current request is SSL
+ *
+ * @return PackageInterface The package
+ */
+ public function getPackage(Request $request, $httpId, $sslId)
+ {
+ return $this->container->get($request->isSecure() ? $sslId : $httpId);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php
new file mode 100644
index 0000000000000..6aa8c58824669
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Templating\Asset;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Templating\Asset\PathPackage as BasePathPackage;
+
+/**
+ * The path packages adds a version and a base path to asset URLs.
+ *
+ * @author Kris Wallsmith
+ */
+class PathPackage extends BasePathPackage
+{
+ /**
+ * Constructor.
+ *
+ * @param Request $request The current request
+ * @param string $version The version
+ * @param string $format The version format
+ */
+ public function __construct(Request $request, $version = null, $format = null)
+ {
+ parent::__construct($request->getBasePath(), $version, $format);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php
deleted file mode 100644
index d73fcb28e2528..0000000000000
--- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php
+++ /dev/null
@@ -1,36 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Bundle\FrameworkBundle\Templating\Helper;
-
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\Templating\Helper\AssetsHelper as BaseAssetsHelper;
-
-/**
- * AssetsHelper is the base class for all helper classes that manages assets.
- *
- * @author Fabien Potencier
- */
-class AssetsHelper extends BaseAssetsHelper
-{
- /**
- * Constructor.
- *
- * @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, $packages = array())
- {
- parent::__construct($request->getBasePath(), $baseURLs, $version, $packages);
- }
-}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index af9e12b1e2620..4b6948c513155 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -97,11 +97,21 @@ public function testTemplating()
$container = $this->createContainerFromFile('full');
$this->assertTrue($container->hasDefinition('templating.name_parser'), '->registerTemplatingConfiguration() loads templating.xml');
- $arguments = $container->getDefinition('templating.helper.assets')->getArguments();
- $this->assertEquals('%templating.helper.assets.assets_version%', $arguments[2]);
- $this->assertEquals('SomeVersionScheme', $container->getParameter('templating.helper.assets.assets_version'));
- $this->assertEquals('%templating.helper.assets.assets_base_urls%', $arguments[1]);
- $this->assertEquals(array('http://cdn.example.com'), $container->getParameter('templating.helper.assets.assets_base_urls'));
+
+ // default package should have one http base url and path package ssl url
+ $this->assertTrue($container->hasDefinition('templating.asset.default_package.http'));
+ $package = $container->getDefinition('templating.asset.default_package.http');
+ $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\DefinitionDecorator', $package);
+ $this->assertEquals('templating.asset.url_package', $package->getParent());
+ $arguments = array_values($package->getArguments());
+ $this->assertEquals(array('http://cdn.example.com'), $arguments[0]);
+ $this->assertEquals('SomeVersionScheme', $arguments[1]);
+ $this->assertNull($arguments[2]);
+
+ $this->assertTrue($container->hasDefinition('templating.asset.default_package.ssl'));
+ $package = $container->getDefinition('templating.asset.default_package.ssl');
+ $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\DefinitionDecorator', $package);
+ $this->assertEquals('templating.asset.path_package', $package->getParent());
$this->assertTrue($container->getDefinition('templating.cache_warmer.template_paths')->hasTag('kernel.cache_warmer'), '->registerTemplatingConfiguration() tags templating cache warmer if cache warming is set');
$this->assertEquals('templating.locator.cached', (string) $container->getAlias('templating.locator'), '->registerTemplatingConfiguration() changes templating.locator alias to cached if cache warming is set');
diff --git a/src/Symfony/Component/Templating/Asset/AssetPackage.php b/src/Symfony/Component/Templating/Asset/AssetPackage.php
deleted file mode 100644
index 19ace2af3a0f2..0000000000000
--- a/src/Symfony/Component/Templating/Asset/AssetPackage.php
+++ /dev/null
@@ -1,59 +0,0 @@
-
- *
- * 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;
-
- foreach ((array) $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/Package.php b/src/Symfony/Component/Templating/Asset/Package.php
new file mode 100644
index 0000000000000..f693fd519a7fe
--- /dev/null
+++ b/src/Symfony/Component/Templating/Asset/Package.php
@@ -0,0 +1,71 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Templating\Asset;
+
+/**
+ * The basic package will add a version to asset URLs.
+ *
+ * @author Kris Wallsmith
+ */
+class Package implements PackageInterface
+{
+ private $version;
+ private $format;
+
+ /**
+ * Constructor.
+ *
+ * @param string $version The package version
+ * @param string $format The format used to apply the version
+ */
+ public function __construct($version = null, $format = null)
+ {
+ $this->version = $version;
+ $this->format = $format ?: '%s?%s';
+ }
+
+ public function getVersion()
+ {
+ return $this->version;
+ }
+
+ public function getUrl($path)
+ {
+ if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
+ return $path;
+ }
+
+ return $this->applyVersion($path);
+ }
+
+ /**
+ * Applies version to the supplied path.
+ *
+ * @param string $path A path
+ *
+ * @return string The versionized path
+ */
+ protected function applyVersion($path)
+ {
+ if (null === $this->version) {
+ return $path;
+ }
+
+ $versionized = sprintf($this->format, ltrim($path, '/'), $this->version);
+
+ if ($path && '/' == $path[0]) {
+ $versionized = '/'.$versionized;
+ }
+
+ return $versionized;
+ }
+}
diff --git a/src/Symfony/Component/Templating/Asset/AssetPackageInterface.php b/src/Symfony/Component/Templating/Asset/PackageInterface.php
similarity index 74%
rename from src/Symfony/Component/Templating/Asset/AssetPackageInterface.php
rename to src/Symfony/Component/Templating/Asset/PackageInterface.php
index b8d15d38e6d30..a3dcde979bd54 100644
--- a/src/Symfony/Component/Templating/Asset/AssetPackageInterface.php
+++ b/src/Symfony/Component/Templating/Asset/PackageInterface.php
@@ -16,7 +16,7 @@
*
* @author Kris Wallsmith
*/
-interface AssetPackageInterface
+interface PackageInterface
{
/**
* Returns the asset package version.
@@ -26,11 +26,11 @@ interface AssetPackageInterface
function getVersion();
/**
- * Returns a base URL for the supplied path.
+ * Returns an absolute or root-relative public path.
*
- * @param string $path An asset path
+ * @param string $path A path
*
- * @return string A base URL
+ * @return string The public path
*/
- function getBaseUrl($path);
+ function getUrl($path);
}
diff --git a/src/Symfony/Component/Templating/Asset/PathPackage.php b/src/Symfony/Component/Templating/Asset/PathPackage.php
new file mode 100644
index 0000000000000..c245560b204ed
--- /dev/null
+++ b/src/Symfony/Component/Templating/Asset/PathPackage.php
@@ -0,0 +1,70 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Templating\Asset;
+
+/**
+ * The path packages adds a version and a base path to asset URLs.
+ *
+ * @author Kris Wallsmith
+ */
+class PathPackage extends Package
+{
+ private $basePath;
+
+ /**
+ * Constructor.
+ *
+ * @param string $basePath The base path to be prepended to relative paths
+ * @param string $version The package version
+ * @param string $format The format used to apply the version
+ */
+ public function __construct($basePath = null, $version = null, $format = null)
+ {
+ parent::__construct($version, $format);
+
+ if (!$basePath) {
+ $this->basePath = '/';
+ } else {
+ if ('/' != $basePath[0]) {
+ $basePath = '/'.$basePath;
+ }
+
+ $this->basePath = rtrim($basePath, '/').'/';
+ }
+ }
+
+ public function getUrl($path)
+ {
+ if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
+ return $path;
+ }
+
+ $url = $this->applyVersion($path);
+
+ // apply the base path
+ if ($url && '/' != $url[0]) {
+ $url = $this->basePath.$url;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Returns the base path.
+ *
+ * @return string The base path
+ */
+ public function getBasePath()
+ {
+ return $this->basePath;
+ }
+}
diff --git a/src/Symfony/Component/Templating/Asset/UrlPackage.php b/src/Symfony/Component/Templating/Asset/UrlPackage.php
new file mode 100644
index 0000000000000..1a4c493fb614b
--- /dev/null
+++ b/src/Symfony/Component/Templating/Asset/UrlPackage.php
@@ -0,0 +1,77 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Templating\Asset;
+
+/**
+ * The URL packages adds a version and a base URL to asset URLs.
+ *
+ * @author Kris Wallsmith
+ */
+class UrlPackage extends Package
+{
+ private $baseUrls;
+
+ /**
+ * Constructor.
+ *
+ * @param string|array $baseUrls Base asset URLs
+ * @param string $version The package version
+ * @param string $format The format used to apply the version
+ */
+ public function __construct($baseUrls = array(), $version = null, $format = null)
+ {
+ parent::__construct($version, $format);
+
+ if (!is_array($baseUrls)) {
+ $baseUrls = (array) $baseUrls;
+ }
+
+ $this->baseUrls = array();
+ foreach ($baseUrls as $baseUrl) {
+ $this->baseUrls[] = rtrim($baseUrl, '/');
+ }
+ }
+
+ public function getUrl($path)
+ {
+ if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
+ return $path;
+ }
+
+ $url = $this->applyVersion($path);
+
+ if ($url && '/' != $url[0]) {
+ $url = '/'.$url;
+ }
+
+ return $this->getBaseUrl($path).$url;
+ }
+
+ /**
+ * Returns the base URL for a path.
+ *
+ * @return string The base URL
+ */
+ public function getBaseUrl($path)
+ {
+ switch ($count = count($this->baseUrls)) {
+ case 0:
+ return '';
+
+ case 1:
+ return $this->baseUrls[0];
+
+ default:
+ return $this->baseUrls[fmod(hexdec(substr(md5($path), 0, 10)), $count)];
+ }
+ }
+}
diff --git a/src/Symfony/Component/Templating/Helper/AssetsHelper.php b/src/Symfony/Component/Templating/Helper/AssetsHelper.php
index 04b4c6f407ccc..32cafafb1f799 100644
--- a/src/Symfony/Component/Templating/Helper/AssetsHelper.php
+++ b/src/Symfony/Component/Templating/Helper/AssetsHelper.php
@@ -11,11 +11,12 @@
namespace Symfony\Component\Templating\Helper;
-use Symfony\Component\Templating\Asset\AssetPackage;
-use Symfony\Component\Templating\Asset\AssetPackageInterface;
+use Symfony\Component\Templating\Asset\Package;
+use Symfony\Component\Templating\Asset\PathPackage;
+use Symfony\Component\Templating\Asset\UrlPackage;
/**
- * AssetsHelper is the base class for all helper classes that manages assets.
+ * AssetsHelper helps manage asset URLs.
*
* Usage:
*
@@ -24,151 +25,27 @@
*
*
* @author Fabien Potencier
+ * @author Kris Wallsmith
*/
-class AssetsHelper extends Helper implements AssetPackageInterface
+class AssetsHelper extends CoreAssetsHelper
{
- protected $version;
- protected $defaultPackage;
- protected $packages;
-
/**
* Constructor.
*
- * @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, $packages = array())
- {
- $this->setBasePath($basePath);
- $this->defaultPackage = new AssetPackage($baseUrls, $version);
- $this->packages = array();
-
- foreach ($packages as $name => $package) {
- $this->setPackage($name, $package);
- }
- }
-
- /**
- * Adds an asset package to the helper.
- *
- * @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
+ * @param string $basePath The base path
+ * @param string|array $baseUrls Base asset URLs
+ * @param string $version The asset version
+ * @param string $format The version format
+ * @param array $namedPackages Additional packages
*/
- public function getPackage($name = null)
+ public function __construct($basePath = null, $baseUrls = array(), $version = null, $format = null, $namedPackages = array())
{
- if (null === $name) {
- return $this->defaultPackage;
+ if ($baseUrls) {
+ $defaultPackage = new UrlPackage($baseUrls, $version, $format);
+ } else {
+ $defaultPackage = new PathPackage($basePath, $version, $format);
}
- if (!isset($this->packages[$name])) {
- throw new \InvalidArgumentException(sprintf('There is no "%s" asset package.', $name));
- }
-
- return $this->packages[$name];
- }
-
- /**
- * Gets the version to add to public URL.
- *
- * @param string $packageName A package name
- *
- * @return string The current version
- */
- public function getVersion($packageName = null)
- {
- return $this->getPackage($packageName)->getVersion();
- }
-
- /**
- * Gets the base path.
- *
- * @return string The base path
- */
- public function getBasePath()
- {
- return $this->basePath;
- }
-
- /**
- * Sets the base path.
- *
- * @param string $basePath The base path
- */
- public function setBasePath($basePath)
- {
- if (strlen($basePath) && '/' != $basePath[0]) {
- $basePath = '/'.$basePath;
- }
-
- $this->basePath = rtrim($basePath, '/').'/';
- }
-
- /**
- * Gets the base URL.
- *
- * If multiple base URLs have been defined a random one will be picked for each asset.
- * In other words: for one asset path the same base URL will always be picked among the available base URLs.
- *
- * @param string $path The path
- * @param string $packageName The package name
- *
- * @return string The base URL
- */
- public function getBaseUrl($path, $packageName = null)
- {
- return $this->getPackage($packageName)->getBaseUrl($path);
- }
-
- /**
- * Returns the 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, $packageName = null)
- {
- if (false !== strpos($path, '://') || 0 === strpos($path, '//')) {
- return $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.($version ? '?'.$version : '');
- }
-
- /**
- * Returns the canonical name of this helper.
- *
- * @return string The canonical name
- */
- public function getName()
- {
- return 'assets';
+ parent::__construct($defaultPackage, $namedPackages);
}
}
diff --git a/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php b/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php
new file mode 100644
index 0000000000000..95f2ff1bd3df0
--- /dev/null
+++ b/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php
@@ -0,0 +1,128 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Templating\Helper;
+
+use Symfony\Component\Templating\Asset\PackageInterface;
+
+/**
+ * CoreAssetsHelper helps manage asset URLs.
+ *
+ * Usage:
+ *
+ *
+ *
+ *
+ *
+ * @author Fabien Potencier
+ * @author Kris Wallsmith
+ */
+class CoreAssetsHelper extends Helper implements PackageInterface
+{
+ protected $defaultPackage;
+ protected $namedPackages;
+
+ /**
+ * Constructor.
+ *
+ * @param PackageInterface $defaultPackage The default package
+ * @param array $namedPackages Additional packages indexed by name
+ */
+ public function __construct(PackageInterface $defaultPackage, array $namedPackages = array())
+ {
+ $this->defaultPackage = $defaultPackage;
+ $this->namedPackages = array();
+
+ foreach ($namedPackages as $name => $package) {
+ $this->addPackage($name, $package);
+ }
+ }
+
+ /**
+ * Sets the default package.
+ *
+ * @param PackageInterface $defaultPackage The default package
+ */
+ public function setDefaultPackage(PackageInterface $defaultPackage)
+ {
+ $this->defaultPackage = $defaultPackage;
+ }
+
+ /**
+ * Adds an asset package to the helper.
+ *
+ * @param string $name The package name
+ * @param PackageInterface $package The package
+ */
+ public function addPackage($name, PackageInterface $package)
+ {
+ $this->namedPackages[$name] = $package;
+ }
+
+ /**
+ * Returns an asset package.
+ *
+ * @param string $name The name of the package or null for the default package
+ *
+ * @return PackageInterface An asset package
+ *
+ * @throws InvalidArgumentException If there is no package by that name
+ */
+ public function getPackage($name = null)
+ {
+ if (null === $name) {
+ return $this->defaultPackage;
+ }
+
+ if (!isset($this->namedPackages[$name])) {
+ throw new \InvalidArgumentException(sprintf('There is no "%s" asset package.', $name));
+ }
+
+ return $this->namedPackages[$name];
+ }
+
+ /**
+ * Gets the version to add to public URL.
+ *
+ * @param string $packageName A package name
+ *
+ * @return string The current version
+ */
+ public function getVersion($packageName = null)
+ {
+ return $this->getPackage($packageName)->getVersion();
+ }
+
+ /**
+ * Returns the 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, $packageName = null)
+ {
+ return $this->getPackage($packageName)->getUrl($path);
+ }
+
+ /**
+ * Returns the canonical name of this helper.
+ *
+ * @return string The canonical name
+ */
+ public function getName()
+ {
+ return 'assets';
+ }
+}
diff --git a/tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php b/tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php
index e7b6d90d943f4..3f500051ca6c1 100644
--- a/tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php
+++ b/tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php
@@ -16,26 +16,6 @@
class AssetsHelperTest extends \PHPUnit_Framework_TestCase
{
- 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(new AssetPackage('http://www.example.com', 'abcd'), $helper->getPackage(), '->__construct() creates a default asset package');
- }
-
- public function testGetSetBasePath()
- {
- $helper = new AssetsHelper();
- $helper->setBasePath('foo/');
- $this->assertEquals('/foo/', $helper->getBasePath(), '->setBasePath() prepends a / if needed');
- $helper->setBasePath('/foo');
- $this->assertEquals('/foo/', $helper->getBasePath(), '->setBasePath() appends a / is needed');
- $helper->setBasePath('');
- $this->assertEquals('/', $helper->getBasePath(), '->setBasePath() returns / if no base path is defined');
- $helper->setBasePath('0');
- $this->assertEquals('/0/', $helper->getBasePath(), '->setBasePath() returns /0/ if 0 is given');
- }
-
public function testGetVersion()
{
$helper = new AssetsHelper(null, array(), 'foo');