Browse Source

[Templating] reworked asset helper and packages

Added support for a configurable format string used to apply version to a path (defaults to '%s?%s').

Moved base url/base path logic to packages.
Kris Wallsmith 14 years ago
parent
commit
2642b0012f

+ 0 - 59
src/Symfony/Component/Templating/Asset/AssetPackage.php

@@ -1,59 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (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 Symfony\Component\Templating\Asset;
-
-/**
- * An asset package.
- *
- * @author Kris Wallsmith <kris@symfony.com>
- */
-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)];
-    }
-}

+ 71 - 0
src/Symfony/Component/Templating/Asset/Package.php

@@ -0,0 +1,71 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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 Symfony\Component\Templating\Asset;
+
+/**
+ * The basic package will add a version to asset URLs.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+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;
+    }
+}

+ 5 - 5
src/Symfony/Component/Templating/Asset/AssetPackageInterface.php

@@ -16,7 +16,7 @@ namespace Symfony\Component\Templating\Asset;
  *
  * @author Kris Wallsmith <kris@symfony.com>
  */
-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);
 }

+ 70 - 0
src/Symfony/Component/Templating/Asset/PathPackage.php

@@ -0,0 +1,70 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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 Symfony\Component\Templating\Asset;
+
+/**
+ * The path packages adds a version and a base path to asset URLs.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+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;
+    }
+}

+ 77 - 0
src/Symfony/Component/Templating/Asset/UrlPackage.php

@@ -0,0 +1,77 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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 Symfony\Component\Templating\Asset;
+
+/**
+ * The URL packages adds a version and a base URL to asset URLs.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+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)];
+        }
+    }
+}

+ 17 - 140
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 @@ use Symfony\Component\Templating\Asset\AssetPackageInterface;
  * </code>
  *
  * @author Fabien Potencier <fabien@symfony.com>
+ * @author Kris Wallsmith <kris@symfony.com>
  */
-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);
     }
 }

+ 128 - 0
src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php

@@ -0,0 +1,128 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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 Symfony\Component\Templating\Helper;
+
+use Symfony\Component\Templating\Asset\PackageInterface;
+
+/**
+ * CoreAssetsHelper helps manage asset URLs.
+ *
+ * Usage:
+ *
+ * <code>
+ *   <img src="<?php echo $view['assets']->getUrl('foo.png') ?>" />
+ * </code>
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+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';
+    }
+}

+ 0 - 20
tests/Symfony/Tests/Component/Templating/Helper/AssetsHelperTest.php

@@ -16,26 +16,6 @@ use Symfony\Component\Templating\Helper\AssetsHelper;
 
 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');