Commit d99f8fb0 authored by Fabien Potencier's avatar Fabien Potencier

feature #1219 added a service provider for the Symfony Asset Component (fabpot)

This PR was merged into the 2.0.x-dev branch.

Discussion
----------

added a service provider for the Symfony Asset Component

Commits
-------

75351758 added a service provider for the Symfony Asset Component
parents ee118729 75351758
......@@ -24,6 +24,7 @@
"symfony/routing": "~2.7"
},
"require-dev": {
"symfony/asset": "~2.7",
"symfony/security": "~2.7",
"symfony/config": "~2.7",
"symfony/locale": "~2.7",
......
Managing Assets in Templates
============================
A Silex application is not always hosted at the web root directory. To avoid
repeating the base path whenever you link to another page, it is highly
recommended to use the :doc:`URL generator service provider
</providers/url_generator>`.
But what about images, stylesheets, or JavaScript files? Their URLs are not
managed by the Silex router, but nonetheless, they need to get prefixed by the
base path. Fortunately, the Request object contain the application base path
that needs to be prepended::
// generate a link to the stylesheets in /css/styles.css
$request->getBasePath().'/css/styles.css';
And doing the same in a Twig template is as easy as it can get:
.. code-block:: jinja
{{ app.request.basepath }}/css/styles.css
If your assets are hosted under a different host, you might want to abstract
the path by defining a Silex parameter::
$app['asset_path'] = 'http://assets.examples.com';
Using it in a template is as easy as before:
.. code-block:: jinja
{{ app.asset_path }}/css/styles.css
If you need to implement some logic independently of the asset, define a
service instead::
$app['asset_path'] = function () {
// implement whatever logic you need to determine the asset path
return 'http://assets.examples.com';
};
Usage is exactly the same as before:
.. code-block:: jinja
{{ app.asset_path }}/css/styles.css
If the asset location depends on the asset type or path, you will need more
abstraction; here is one way to do that with a Twig function::
$app->extend('twig', function($twig, $app) {
$twig->addFunction(new \Twig_SimpleFunction('asset', function ($asset) {
// implement whatever logic you need to determine the asset path
return sprintf('http://assets.examples.com/%s', ltrim($asset, '/'));
}));
return $twig;
});
The ``asset`` function can then be used in your templates:
.. code-block:: jinja
{{ asset('/css/styles.css') }}
......@@ -15,7 +15,6 @@ The cookbook section contains recipes for solving specific problems.
sub_requests
error_handler
multiple_loggers
assets
Recipes
-------
......
AssetServiceProvider
====================
The *AssetServiceProvider* provides a way to manage URL generation and
versioning of web assets such as CSS stylesheets, JavaScript files and image
files.
Parameters
----------
* **assets.version**: Default version for assets.
* **assets.format_version** (optional): Default format for assets.
* **assets.named_packages** (optional): Named packages. Keys are the package
names and values the configuration (supported keys are ``version``,
``version_format``, ``base_urls``, and ``base_path``).
Services
--------
* **assets.packages**: The asset service.
Registering
-----------
.. code-block:: php
$app->register(new Silex\Provider\AssetServiceProvider(), array(
'assets.version' => 'v1',
'assets.version_format' => '%s?version=%s',
'assets.named_packages' => array(
'css' => array('version' => 'css2', 'base_path' => '/whatever-makes-sense'),
'images' => array('base_urls' => array('https://img.example.com')),
),
));
.. note::
The Symfony Asset Component comes with the "fat" Silex archive but not with
the regular one. If you are using Composer, add it as a dependency:
.. code-block:: bash
composer require symfony/asset
Usage
-----
The AssetServiceProvider is mostly useful with the Twig provider:
.. code-block:: jinja
{{ asset('/css/foo.png') }}
{{ asset('/css/foo.css', 'css') }}
{{ asset('/img/foo.png', 'images') }}
{{ asset_version('/css/foo.png') }}
For more information, check out the `Asset Component documentation
<https://symfony.com/doc/current/components/asset/introduction.html>`_.
......@@ -10,6 +10,7 @@ Silex
swiftmailer
translation
twig
asset
validator
form
http_cache
......
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Silex\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Component\Asset\Packages;
use Symfony\Component\Asset\Package;
use Symfony\Component\Asset\PathPackage;
use Symfony\Component\Asset\UrlPackage;
use Symfony\Component\Asset\Context\RequestStackContext;
use Symfony\Component\Asset\VersionStrategy\EmptyVersionStrategy;
use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy;
/**
* Symfony Asset component Provider.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class AssetServiceProvider implements ServiceProviderInterface
{
public function register(Container $app)
{
$app['assets.packages'] = function ($app) {
$packages = array();
foreach ($app['assets.named_packages'] as $name => $package) {
$version = $app['assets.strategy_factory'](isset($package['version']) ? $package['version'] : '', isset($package['version_format']) ? $package['version_format'] : null);
$packages[$name] = $app['assets.package_factory'](isset($package['base_path']) ? $package['base_path'] : '', isset($package['base_urls']) ? $package['base_urls'] : array(), $version, $name);
}
return new Packages($app['assets.default_package'], $packages);
};
$app['assets.default_package'] = function ($app) {
$version = $app['assets.strategy_factory']($app['assets.version'], $app['assets.version_format']);
return $app['assets.package_factory']($app['assets.base_path'], $app['assets.base_urls'], $version, 'default');
};
$app['assets.context'] = function ($app) {
return new RequestStackContext($app['request_stack']);
};
$app['assets.base_path'] = '';
$app['assets.base_urls'] = array();
$app['assets.version'] = null;
$app['assets.version_format'] = null;
$app['assets.named_packages'] = array();
// prototypes
$app['assets.strategy_factory'] = $app->protect(function ($version, $format) use ($app) {
if (!$version) {
return new EmptyVersionStrategy();
}
return new StaticVersionStrategy($version, $format);
});
$app['assets.package_factory'] = $app->protect(function ($basePath, $baseUrls, $version, $name) use ($app) {
if ($basePath && $baseUrls) {
throw new \LogicException(sprintf('Asset package "%s" cannot have base URLs and base paths.', $name));
}
if (!$baseUrls) {
return new PathPackage($basePath, $version, $app['assets.context']);
}
return new UrlPackage($baseUrls, $version, $app['assets.context']);
});
}
}
......@@ -13,6 +13,7 @@ namespace Silex\Provider;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use Symfony\Bridge\Twig\Extension\AssetExtension;
use Symfony\Bridge\Twig\Extension\RoutingExtension;
use Symfony\Bridge\Twig\Extension\TranslationExtension;
use Symfony\Bridge\Twig\Extension\FormExtension;
......@@ -73,6 +74,10 @@ class TwigServiceProvider implements ServiceProviderInterface
$twig->addExtension(new HttpKernelExtension($app['fragment.handler']));
}
if (isset($app['assets.packages'])) {
$twig->addExtension(new AssetExtension($app['assets.packages']));
}
if (isset($app['form.factory'])) {
$app['twig.form.engine'] = function ($app) {
return new TwigRendererEngine($app['twig.form.templates']);
......
<?php
/*
* This file is part of the Silex framework.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\AssetServiceProvider;
class AssetServiceProviderTest extends \PHPUnit_Framework_TestCase
{
public function testGenerateAssetUrl()
{
$app = new Application();
$app->register(new AssetServiceProvider(), array(
'assets.version' => 'v1',
'assets.version_format' => '%s?version=%s',
'assets.named_packages' => array(
'css' => array('version' => 'css2', 'base_path' => '/whatever-makes-sense'),
'images' => array('base_urls' => array('https://img.example.com')),
),
));
$this->assertEquals('/foo.png?version=v1', $app['assets.packages']->getUrl('/foo.png'));
$this->assertEquals('/whatever-makes-sense/foo.css?css2', $app['assets.packages']->getUrl('/foo.css', 'css'));
$this->assertEquals('https://img.example.com/foo.png', $app['assets.packages']->getUrl('/foo.png', 'images'));
}
}
......@@ -13,6 +13,7 @@ namespace Silex\Tests\Provider;
use Silex\Application;
use Silex\Provider\TwigServiceProvider;
use Silex\Provider\AssetServiceProvider;
use Symfony\Component\HttpFoundation\Request;
/**
......@@ -67,4 +68,17 @@ class TwigServiceProviderTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('http://localhost/dir1/dir2/foo.css', $app['twig']->render('absolute'));
$this->assertEquals('../foo.css', $app['twig']->render('relative'));
}
public function testAssetIntegration()
{
$app = new Application();
$app->register(new TwigServiceProvider(), array(
'twig.templates' => array('hello' => '{{ asset("/foo.css") }}'),
));
$app->register(new AssetServiceProvider(), array(
'assets.version' => 1,
));
$this->assertEquals('/foo.css?1', $app['twig']->render('hello'));
}
}
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