merged vicb:template-factorization

This commit is contained in:
Fabien Potencier 2011-04-26 14:38:47 +02:00
commit e45d5fa857
14 changed files with 232 additions and 98 deletions

View File

@ -12,9 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; namespace Symfony\Bundle\FrameworkBundle\CacheWarmer;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer;
use Symfony\Component\HttpKernel\KernelInterface; use \Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateFinderInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator; use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator;
/** /**
@ -24,25 +22,19 @@ use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator;
*/ */
class TemplatePathsCacheWarmer extends CacheWarmer class TemplatePathsCacheWarmer extends CacheWarmer
{ {
protected $kernel; protected $finder;
protected $parser;
protected $rootDir;
protected $locator; protected $locator;
/** /**
* Constructor. * Constructor.
* *
* @param KernelInterface $kernel A KernelInterface instance * @param TemplateFinderInterface $finder A template finder
* @param TemplateNameParser $parser A TemplateNameParser instance * @param TemplateLocator $locator The template locator
* @param TemplateLocator $locator The template locator
* @param string $rootDir The directory where global templates can be stored
*/ */
public function __construct(KernelInterface $kernel, TemplateNameParser $parser, TemplateLocator $locator, $rootDir) public function __construct(TemplateFinderInterface $finder, TemplateLocator $locator)
{ {
$this->kernel = $kernel; $this->finder = $finder;
$this->parser = $parser;
$this->locator = $locator; $this->locator = $locator;
$this->rootDir = $rootDir;
} }
/** /**
@ -54,12 +46,10 @@ class TemplatePathsCacheWarmer extends CacheWarmer
{ {
$templates = array(); $templates = array();
foreach ($this->kernel->getBundles() as $name => $bundle) { foreach ($this->finder->findAllTemplates() as $template) {
$templates += $this->findTemplatesIn($bundle->getPath().'/Resources/views', $name); $templates[$template->getSignature()] = $this->locator->locate($template);
} }
$templates += $this->findTemplatesIn($this->rootDir.'/views');
$this->writeCacheFile($cacheDir.'/templates.php', sprintf('<?php return %s;', var_export($templates, true))); $this->writeCacheFile($cacheDir.'/templates.php', sprintf('<?php return %s;', var_export($templates, true)));
} }
@ -72,32 +62,4 @@ class TemplatePathsCacheWarmer extends CacheWarmer
{ {
return false; return false;
} }
/**
* Find templates in the given directory
*
* @param string $dir The folder where to look for templates
* @param string $bundle The name of the bundle (null when out of a bundle)
*
* @return array An array of template paths
*/
protected function findTemplatesIn($dir, $bundle = null)
{
$templates = array();
if (is_dir($dir)) {
$finder = new Finder();
foreach ($finder->files()->followLinks()->in($dir) as $file) {
$template = $this->parser->parseFromFilename($file->getRelativePathname());
if (false !== $template) {
if (null !== $bundle) {
$template->set('bundle', $bundle);
}
$templates[$template->getSignature()] = $this->locator->locate($template);
}
}
}
return $templates;
}
} }

View File

@ -13,6 +13,7 @@
<parameter key="templating.loader.filesystem.class">Symfony\Bundle\FrameworkBundle\Templating\Loader\FilesystemLoader</parameter> <parameter key="templating.loader.filesystem.class">Symfony\Bundle\FrameworkBundle\Templating\Loader\FilesystemLoader</parameter>
<parameter key="templating.loader.cache.class">Symfony\Component\Templating\Loader\CacheLoader</parameter> <parameter key="templating.loader.cache.class">Symfony\Component\Templating\Loader\CacheLoader</parameter>
<parameter key="templating.loader.chain.class">Symfony\Component\Templating\Loader\ChainLoader</parameter> <parameter key="templating.loader.chain.class">Symfony\Component\Templating\Loader\ChainLoader</parameter>
<parameter key="templating.finder.class">Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateFinder</parameter>
</parameters> </parameters>
<services> <services>
@ -34,13 +35,17 @@
<argument type="service" id="file_locator" /> <argument type="service" id="file_locator" />
</service> </service>
<service id="templating.cache_warmer.template_paths" class="%templating.cache_warmer.template_paths.class%" public="false"> <service id="templating.finder" class="%templating.finder.class%" public="false">
<argument type="service" id="kernel" /> <argument type="service" id="kernel" />
<argument type="service" id="templating.name_parser" /> <argument type="service" id="templating.name_parser" />
<argument type="service" id="templating.locator.uncached" />
<argument>%kernel.root_dir%/Resources</argument> <argument>%kernel.root_dir%/Resources</argument>
</service> </service>
<service id="templating.cache_warmer.template_paths" class="%templating.cache_warmer.template_paths.class%" public="false">
<argument type="service" id="templating.finder" />
<argument type="service" id="templating.locator.uncached" />
</service>
<service id="templating.loader.filesystem" class="%templating.loader.filesystem.class%" public="false"> <service id="templating.loader.filesystem" class="%templating.loader.filesystem.class%" public="false">
<argument type="service" id="templating.locator" /> <argument type="service" id="templating.locator" />
</service> </service>

View File

@ -0,0 +1,109 @@
<?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\Bundle\FrameworkBundle\Templating\Loader;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
/**
* Finds all the templates.
*
* @author Victor Berchet <victor@suumit.com>
*/
class TemplateFinder implements TemplateFinderInterface
{
private $kernel;
private $parser;
private $rootDir;
private $templates;
/**
* Constructor.
*
* @param KernelInterface $kernel A KernelInterface instance
* @param TemplateNameParser $parser A TemplateNameParser instance
* @param string $rootDir The directory where global templates can be stored
*/
public function __construct(KernelInterface $kernel, TemplateNameParser $parser, $rootDir)
{
$this->kernel = $kernel;
$this->parser = $parser;
$this->rootDir = $rootDir;
}
/**
* Find all the templates in the bundle and in the kernel Resources folder.
*
* @return array An array of templates of type TemplateReferenceInterface
*/
public function findAllTemplates()
{
if (null !== $this->templates) {
return $this->templates;
}
$templates = array();
foreach ($this->kernel->getBundles() as $name => $bundle) {
$templates = array_merge($templates, $this->findTemplatesInBundle($bundle));
}
$templates = array_merge($templates, $this->findTemplatesInFolder($this->rootDir.'/views'));
return $this->templates = $templates;
}
/**
* Find templates in the given directory.
*
* @param string $dir The folder where to look for templates
*
* @return array An array of templates of type TemplateReferenceInterface
*/
private function findTemplatesInFolder($dir)
{
$templates = array();
if (is_dir($dir)) {
$finder = new Finder();
foreach ($finder->files()->followLinks()->in($dir) as $file) {
$template = $this->parser->parseFromFilename($file->getRelativePathname());
if (false !== $template) {
$templates[] = $template;
}
}
}
return $templates;
}
/**
* Find templates in the given bundle.
*
* @param BundleInterface $bundle The bundle where to look for templates
*
* @return array An array of templates of type TemplateReferenceInterface
*/
private function findTemplatesInBundle(BundleInterface $bundle)
{
$templates = $this->findTemplatesInFolder($bundle->getPath().'/Resources/views');
$name = $bundle->getName();
foreach ($templates as $i => $template) {
$templates[$i] = $template->set('bundle', $name);
}
return $templates;
}
}

View File

@ -0,0 +1,28 @@
<?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\Bundle\FrameworkBundle\Templating\Loader;
/**
* Interface for finding all the templates.
*
* @author Victor Berchet <victor@suumit.com>
*/
interface TemplateFinderInterface
{
/**
* Find all the templates.
*
* @return array An array of templates of type TemplateReferenceInterface
*/
function findAllTemplates();
}

View File

@ -0,0 +1,9 @@
<?php
namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BaseBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
class BaseBundle extends Bundle
{
}

View File

@ -0,0 +1,56 @@
<?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\Bundle\FrameworkBundle\Tests\Templating\Loader;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
use Symfony\Bundle\FrameworkBundle\Templating\TemplateNameParser;
use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateFinder;
use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\BaseBundle\BaseBundle;
class TemplateFinderTest extends TestCase
{
public function testFindAllTemplates()
{
$kernel = $this
->getMockBuilder('Symfony\Component\HttpKernel\Kernel')
->disableOriginalConstructor()
->getMock()
;
$kernel
->expects($this->any())
->method('getBundle')
;
$kernel
->expects($this->once())
->method('getBundles')
->will($this->returnValue(array('BaseBundle' => new BaseBundle())))
;
$parser = new TemplateNameParser($kernel);
$finder = new TemplateFinder($kernel, $parser, __DIR__.'/../../Fixtures/Resources');
$templates = array_map(
function ($template) { return $template->getLogicalName(); },
$finder->findAllTemplates()
);
$this->assertEquals(3, count($templates), '->findAllTemplates() find all templates in the bundles and global folders');
$this->assertContains('BaseBundle::base.format.engine', $templates);
$this->assertContains('BaseBundle:controller:base.format.engine', $templates);
$this->assertContains('::resource.format.engine', $templates);
}
}

View File

@ -11,9 +11,10 @@
namespace Symfony\Bundle\TwigBundle\CacheWarmer; namespace Symfony\Bundle\TwigBundle\CacheWarmer;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer;
use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplatePathsCacheWarmer;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Finder\Finder; use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateFinder;
/** /**
* Generates the Twig cache for all templates. * Generates the Twig cache for all templates.
@ -26,25 +27,22 @@ use Symfony\Component\Finder\Finder;
class TemplateCacheCacheWarmer implements CacheWarmerInterface class TemplateCacheCacheWarmer implements CacheWarmerInterface
{ {
protected $container; protected $container;
protected $parser; protected $warmer;
protected $kernel;
/** /**
* Constructor. * Constructor.
* *
* @param ContainerInterface $container The dependency injection container * @param ContainerInterface $container The dependency injection container
* @param string $rootDir The directory where global templates can be stored * @param TemplatePathsCacheWarmer $warmer The template paths cache warmer
*/ */
public function __construct(ContainerInterface $container, $rootDir) public function __construct(ContainerInterface $container, TemplateFinder $finder)
{ {
// we don't inject the Twig environment directly as it needs // We don't inject the Twig environment directly as it depends on the
// the loader, which is a cached one, and the cache is not // template locator (via the loader) which might be a cached one.
// yet available when this instance is created (the // The cached template locator is available once the TemplatePathsCacheWarmer
// TemplateCacheCacheWarmer has not been run yet). // has been warmed up
$this->container = $container; $this->container = $container;
$this->parser = $container->get('templating.name_parser'); $this->finder = $finder;
$this->kernel = $container->get('kernel');
$this->rootDir = $rootDir;
} }
/** /**
@ -56,15 +54,11 @@ class TemplateCacheCacheWarmer implements CacheWarmerInterface
{ {
$twig = $this->container->get('twig'); $twig = $this->container->get('twig');
foreach ($this->kernel->getBundles() as $name => $bundle) { foreach ($this->finder->findAllTemplates() as $template) {
foreach ($this->findTemplatesIn($bundle->getPath().'/Resources/views', $name) as $template) { if ('twig' === $template->get('engine')) {
$twig->loadTemplate($template); $twig->loadTemplate($template);
} }
} }
foreach ($this->findTemplatesIn($this->rootDir.'/views') as $template) {
$twig->loadTemplate($template);
}
} }
/** /**
@ -76,32 +70,4 @@ class TemplateCacheCacheWarmer implements CacheWarmerInterface
{ {
return true; return true;
} }
/**
* Find templates in the given directory
*
* @param string $dir The folder where to look for templates
* @param string $bundle The name of the bundle (null when out of a bundle)
*
* @return array An array of TemplateReference
*/
protected function findTemplatesIn($dir, $bundle = null)
{
$templates = array();
if (is_dir($dir)) {
$finder = new Finder();
foreach ($finder->files()->followLinks()->in($dir) as $file) {
$template = $this->parser->parseFromFilename($file->getRelativePathname());
if (false !== $template && 'twig' == $template->get('engine')) {
if (null !== $bundle) {
$template->set('bundle', $bundle);
}
$templates[] = $template->getLogicalName();
}
}
}
return $templates;
}
} }

View File

@ -19,7 +19,7 @@
<service id="twig.cache_warmer" class="%twig.cache_warmer.class%" public="false"> <service id="twig.cache_warmer" class="%twig.cache_warmer.class%" public="false">
<argument type="service" id="service_container" /> <argument type="service" id="service_container" />
<argument>%kernel.root_dir%/Resources</argument> <argument type="service" id="templating.finder" />
</service> </service>
<service id="twig.loader" class="%twig.loader.class%"> <service id="twig.loader" class="%twig.loader.class%">

View File

@ -13,7 +13,6 @@ namespace Symfony\Bundle\WebProfilerBundle;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\HttpKernel;
use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Bundle\TwigBundle\TwigEngine; use Symfony\Bundle\TwigBundle\TwigEngine;