Skip to content

Commit

Permalink
[Templating] Refactor the component
Browse files Browse the repository at this point in the history
  • Loading branch information
vicb authored and fabpot committed Feb 14, 2011
1 parent 12f99dd commit af81bca
Show file tree
Hide file tree
Showing 28 changed files with 516 additions and 217 deletions.
Expand Up @@ -15,6 +15,8 @@
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Bundle\FrameworkBundle\Templating\Template;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;

/**
* Computes the association between template names and their paths on the disk.
Expand All @@ -26,6 +28,7 @@ class TemplatePathsCacheWarmer extends CacheWarmer
protected $locator;
protected $kernel;
protected $rootDir;
protected $parser;

/**
* Constructor.
Expand Down Expand Up @@ -75,10 +78,8 @@ protected function computeTemplatePaths()
$finder = new Finder();
foreach ($finder->files()->followLinks()->in($dir) as $file) {
if (false !== $template = $this->parseTemplateName($file, $prefix.'/', $bundle->getName())) {
$controllerSegment = empty($template['controller']) ? '' : $template['controller'].'/';
$resource = '@'.$template['bundle'].'/Resources/views/'.$controllerSegment.$template['name'].'.'.$template['format'].'.'.$template['engine'];

$templates[md5(serialize($template))] = $this->locator->locate($resource, $this->rootDir);
$templates[$template->getSignature()] = $this->locator->locate($template->getPath(), $this->rootDir);
}
}
}
Expand All @@ -87,7 +88,7 @@ protected function computeTemplatePaths()
$finder = new Finder();
foreach ($finder->files()->followLinks()->in($this->rootDir) as $file) {
if (false !== $template = $this->parseTemplateName($file, strtr($this->rootDir, '\\', '/').'/')) {
$templates[md5(serialize($template))] = (string) $file;
$templates[$template->getSignature()] = $file->getRealPath();
}
}
}
Expand All @@ -97,23 +98,20 @@ protected function computeTemplatePaths()

protected function parseTemplateName($file, $prefix, $bundle = '')
{
if (null === $this->parser) {
$this->parser = $this->kernel->getContainer()->get('templating.name_parser');
}

$prefix = strtr($prefix, '\\', '/');
$path = strtr($file->getPathname(), '\\', '/');

list(, $tmp) = explode($prefix, $path, 2);
$parts = explode('/', $tmp);
list(, $file) = explode($prefix, $path, 2);

$elements = explode('.', array_pop($parts));
if (3 !== count($elements)) {
return false;
$template = $this->parser->parseFromFilename($file);
if (false !== $template) {
$template->set('bundle', $bundle);
}

return array(
'bundle' => $bundle,
'controller' => implode('/', $parts),
'name' => $elements[0],
'format' => $elements[1],
'engine' => $elements[2],
);
return $template;
}
}
Expand Up @@ -340,21 +340,24 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder

$this->addClassesToCompile(array(
'Symfony\\Bundle\\FrameworkBundle\\Templating\\EngineInterface',
'Symfony\\Component\\Templating\\TemplateNameParserInterface',
'Symfony\\Component\\Templating\\TemplateNameParser',
'Symfony\\Component\\Templating\\EngineInterface',
'Symfony\\Component\\Config\\FileLocatorInterface',
'Symfony\\Component\\Templating\\TemplateReferenceInterface',
'Symfony\\Component\\Templating\\TemplateReference',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser',
$container->findDefinition('templating.locator')->getClass(),
));

if (in_array('php', $config['engines'], true)) {
$this->addClassesToCompile(array(
'Symfony\\Component\\Templating\\PhpEngine',
'Symfony\\Component\\Templating\\TemplateNameParserInterface',
'Symfony\\Component\\Templating\\TemplateNameParser',
'Symfony\\Component\\Templating\\Loader\\LoaderInterface',
'Symfony\\Component\\Templating\\Storage\\Storage',
'Symfony\\Component\\Templating\\Storage\\FileStorage',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\PhpEngine',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser',
'Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\FilesystemLoader',
));
}
Expand Down
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Templating\Loader;

use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
* CachedTemplateLocator locates templates in the cache.
Expand All @@ -37,16 +38,17 @@ public function __construct($cacheDir)
/**
* Returns a full path for a given file.
*
* @param array $template The template name as an array
* @param string $currentPath The current path
* @param TemplateReferenceInterface $template The template
* @param string $currentPath Unused
* @param Boolean $first Unused
*
* @return string The full path for the file
*
* @throws \InvalidArgumentException When file is not found
*/
public function locate($template, $currentPath = null, $first = true)
{
$key = md5(serialize($template));
$key = $template->getSignature();

if (!isset($this->templates[$key])) {
throw new \InvalidArgumentException(sprintf('Unable to find template "%s".', json_encode($template)));
Expand Down
Expand Up @@ -14,6 +14,7 @@
use Symfony\Component\Templating\Storage\FileStorage;
use Symfony\Component\Templating\Loader\LoaderInterface;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
* FilesystemLoader is a loader that read templates from the filesystem.
Expand All @@ -37,13 +38,15 @@ public function __construct(FileLocatorInterface $locator)
/**
* Loads a template.
*
* @param array $template The template name as an array
* @param TemplateReferenceInterface $template A template
*
* @return Storage|Boolean false if the template cannot be loaded, a Storage instance otherwise
*/
public function load($template)
public function load(TemplateReferenceInterface $template)
{
if (false === $file = $this->locator->locate($template)) {
try {
$file = $this->locator->locate($template);
} catch (\InvalidArgumentException $e) {
return false;
}

Expand All @@ -53,15 +56,15 @@ public function load($template)
/**
* Returns true if the template is still fresh.
*
* @param array $template The template name as an array
* @param timestamp $time The last modification time of the cached template
* @param TemplateReferenceInterface $template The template name as an array
* @param integer $time The last modification time of the cached template (timestamp)
*/
public function isFresh($template, $time)
public function isFresh(TemplateReferenceInterface $template, $time)
{
if (false === $template = $this->load($template)) {
if (false === $storage = $this->load($template)) {
return false;
}

return filemtime((string) $template) < $time;
return filemtime((string) $storage) < $time;
}
}
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Templating\Loader;

use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;

/**
* TemplateLocator locates templates in bundles.
Expand Down Expand Up @@ -40,35 +41,26 @@ public function __construct(FileLocatorInterface $locator, $path)
/**
* Returns a full path for a given file.
*
* @param array $template The template name as an array
* @param string $currentPath The current path
* @param TemplateReferenceInterface $template A template
* @param string $currentPath Unused
* @param Boolean $first Unused
*
* @return string The full path for the file
*
* @throws \InvalidArgumentException When file is not found
*/
public function locate($template, $currentPath = null, $first = true)
{
$key = md5(serialize($template));
$key = $template->getSignature();

if (isset($this->cache[$key])) {
return $this->cache[$key];
}

if (!$template['bundle']) {
if (is_file($file = $this->path.'/views/'.$template['controller'].'/'.$template['name'].'.'.$template['format'].'.'.$template['engine'])) {
return $this->cache[$key] = $file;
}

throw new \InvalidArgumentException(sprintf('Unable to find template "%s" in "%s".', json_encode($template), $this->path));
}

$resource = $template['bundle'].'/Resources/views/'.$template['controller'].'/'.$template['name'].'.'.$template['format'].'.'.$template['engine'];

try {
return $this->locator->locate('@'.$resource, $this->path);
} catch (\Exception $e) {
throw new \InvalidArgumentException(sprintf('Unable to find template "%s".', json_encode($template), $this->path), 0, $e);
return $this->cache[$key] = $this->locator->locate($template->getPath(), $this->path);
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException(sprintf('Unable to find template "%s" in "%s".', json_encode($template), $this->path), 0, $e);
}
}
}
Expand Up @@ -12,18 +12,20 @@
namespace Symfony\Bundle\FrameworkBundle\Templating;

use Symfony\Component\Templating\TemplateNameParser as BaseTemplateNameParser;
use Symfony\Component\Templating\TemplateReferenceInterface;
use Symfony\Component\HttpKernel\KernelInterface;

/**
* TemplateNameParser parsers template name from the short notation
* "bundle:section:template.engine.format" to an array of
* template parameters.
* TemplateNameParser converts template names from the short notation
* "bundle:section:template.format.engine" to TemplateReferenceInterface
* instances.
*
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class TemplateNameParser extends BaseTemplateNameParser
{
protected $kernel;
protected $cache;

/**
* Constructor.
Expand All @@ -33,15 +35,18 @@ class TemplateNameParser extends BaseTemplateNameParser
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
$this->cache = array();
}

/**
* {@inheritdoc}
*/
public function parse($name)
{
if (is_array($name)) {
if ($name instanceof TemplateReferenceInterface) {
return $name;
} else if (isset($this->cache[$name])) {
return $this->cache[$name];
}

// normalize name
Expand All @@ -61,22 +66,36 @@ public function parse($name)
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid (format is "bundle:section:template.format.engine").', $name));
}

$parameters = array(
'bundle' => $parts[0],
'controller' => $parts[1],
'name' => $elements[0],
'format' => $elements[1],
'engine' => $elements[2],
);
$template = new TemplateReference($parts[0], $parts[1], $elements[0], $elements[1], $elements[2]);

if ($parameters['bundle']) {
if ($template->get('bundle')) {
try {
$this->kernel->getBundle($parameters['bundle']);
$this->kernel->getBundle($template->get('bundle'));
} catch (\Exception $e) {
throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name), 0, $e);
}
}

return $parameters;
return $this->cache[$name] = $template;
}

/**
* Convert a filename to a template.
*
* @param string $file The filename
*
* @return TemplateReferenceInterface A template
*/
public function parseFromFilename($file)
{
$parts = explode('/', strtr($file, '\\', '/'));

$elements = explode('.', array_pop($parts));
if (3 !== count($elements)) {
return false;
}

return new TemplateReference('', implode('/', $parts), $elements[0], $elements[1], $elements[2]);
}

}
@@ -0,0 +1,49 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\Templating;

use Symfony\Component\Templating\TemplateReference as BaseTemplateReference;

/**
* Internal representation of a template.
*
* @author Victor Berchet <victor@suumit.com>
*/
class TemplateReference extends BaseTemplateReference
{
public function __construct($bundle = null, $controller = null, $name = null, $format = null, $engine = null)
{
$this->parameters = array(
'bundle' => $bundle,
'controller' => $controller,
'name' => $name,
'format' => $format,
'engine' => $engine,
);
}

/**
* Returns the path to the template
* - as a path when the template is not part of a bundle
* - as a resource when the template is part of a bundle
*
* @return string A path to the template or a resource
*/
public function getPath()
{
$controller = $this->get('controller');
$path = (empty($controller) ? '' : $controller.'/').$this->get('name').'.'.$this->get('format').'.'.$this->get('engine');

return empty($this->parameters['bundle']) ? 'views/'.$path : '@'.$this->get('bundle').'/Resources/views/'.$path;
}

}

0 comments on commit af81bca

Please sign in to comment.