diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 802abe8cbdb4..da0d6d6e7b71 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 c3d8abf4b8a5..a10b0548a553 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 161ad6690749..16f8366a4135 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 f2b2eec5d424..ebdf3e618118 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 000000000000..de36a3283196 --- /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 000000000000..6aa8c5882466 --- /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 d73fcb28e252..000000000000 --- 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 af9e12b1e262..4b6948c51315 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');