Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache warming #9

Merged
merged 13 commits into from
Sep 8, 2011
73 changes: 73 additions & 0 deletions CacheWarmer/TemplatePathsCacheWarmer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

/*
* This file is part of the Liip/ThemeBundle
*
* (c) Liip AG
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Liip\ThemeBundle\CacheWarmer;

use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplatePathsCacheWarmer as BaseTemplatePathsCacheWarmer,
Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer,
Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator,
Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplateFinderInterface;

use Liip\ThemeBundle\ActiveTheme;

class TemplatePathsCacheWarmer extends BaseTemplatePathsCacheWarmer
{
protected $activeTheme;

/**
* Constructor.
*
* @param TemplateFinderInterface $finder A template finder
* @param TemplateLocator $locator The template locator
*/
public function __construct(TemplateFinderInterface $finder, TemplateLocator $locator, ActiveTheme $activeTheme = null)
{
$this->activeTheme = $activeTheme;

parent::__construct($finder, $locator);
}

/**
* Warms up the cache.
*
* @param string $cacheDir The cache directory
*/
public function warmUp($cacheDir)
{
if (empty($this->activeTheme)) {
return;
}

$locator = $this->locator->getLocator();

$allTemplates = $this->finder->findAllTemplates();

$templates = array();
foreach ($this->activeTheme->getThemes() as $theme) {
$this->activeTheme->setName($theme);
foreach ($allTemplates as $template) {
$templates[$template->getLogicalName().'|'.$theme] = $locator->locate($template->getPath());
}
}

$this->writeCacheFile($cacheDir.'/templates.php', sprintf('<?php return %s;', var_export($templates, true)));
}

/**
* Checks whether this warmer is optional or not.
*
* @return Boolean always true
*/
public function isOptional()
{
return true;
}
}
21 changes: 17 additions & 4 deletions DependencyInjection/Compiler/ThemeCompilerPass.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<?php

/*
* This file is part of the Liip/ThemeBundle
*
* (c) Liip AG
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Liip\ThemeBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Reference;
Expand All @@ -10,9 +19,13 @@ class ThemeCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
// Replace templating.
$container->getDefinition('templating.locator')
->replaceArgument(0, new Reference('liip_theme.file_locator'))
;
$container->setAlias('templating.locator', 'liip_theme.templating_locator');

$container->setAlias('templating.cache_warmer.template_paths', 'liip_theme.templating.cache_warmer.template_paths');

if (!$container->getParameter('liip_theme.cache_warming')) {
$container->getDefinition('liip_theme.templating.cache_warmer.template_paths')
->replaceArgument(2, null);
}
}
}
10 changes: 10 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
<?php

/*
* This file is part of the Liip/ThemeBundle
*
* (c) Liip AG
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Liip\ThemeBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\NodeBuilder;
Expand Down Expand Up @@ -34,6 +43,7 @@ public function getConfigTree()
->end()
->scalarNode('active_theme')->defaultNull()->end()
->scalarNode('theme_cookie')->defaultNull()->end()
->booleanNode('cache_warming')->defaultTrue()->end()
->end();
return $treeBuilder->buildTree();
}
Expand Down
7 changes: 4 additions & 3 deletions DependencyInjection/LiipThemeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@ public function load(array $configs, ContainerBuilder $container)

$config = $processor->process($configuration->getConfigTree(), $configs);

// Set parameters first, services depend on them.
$container->setParameter($this->getAlias().'.themes', $config['themes']);
$container->setParameter($this->getAlias().'.active_theme', $config['active_theme']);

$container->setParameter($this->getAlias().'.cache_warming', $config['cache_warming']);

$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
if (! empty($config['theme_cookie'])) {

if (!empty($config['theme_cookie'])) {
$container->setParameter($this->getAlias().'.theme_cookie', $config['theme_cookie']);
$loader->load('theme_request_listener.xml');
}

$loader->load('templating.xml');
}
}
4 changes: 2 additions & 2 deletions EventListener/ThemeRequestListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
namespace Liip\ThemeBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;

use Liip\ThemeBundle\ActiveTheme;

/**
Expand All @@ -22,9 +23,8 @@
*/
class ThemeRequestListener
{

/**
* @var Liip\ThemeBundle\ActiveTheme
* @var ActiveTheme
*/
protected $activeTheme;

Expand Down
1 change: 1 addition & 0 deletions LiipThemeBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\HttpKernel\Bundle\Bundle;
use Symfony\Component\DependencyInjection\ContainerBuilder;

use Liip\ThemeBundle\DependencyInjection\Compiler\ThemeCompilerPass;

class LiipThemeBundle extends Bundle
Expand Down
37 changes: 23 additions & 14 deletions Locator/FileLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Config\FileLocator as BaseFileLocator;

use Liip\ThemeBundle\ActiveTheme;

/**
* FileLocator uses the HttpKernel FileLocator to locate resources in bundles
* and follow a configurable file path.
Expand All @@ -31,10 +33,13 @@ class FileLocator extends BaseFileLocator
/**
* @var ActiveTheme
*/
protected $theme;

protected $activeTheme;

/**
* @var string
*/
protected $lastTheme;

/**
* Constructor.
*
Expand All @@ -43,27 +48,29 @@ class FileLocator extends BaseFileLocator
*
* @throws \InvalidArgumentException if the active theme is not in the themes list
*/
public function __construct(KernelInterface $kernel, $path = null, array $paths = array())
public function __construct(KernelInterface $kernel, ActiveTheme $activeTheme, $path = null, array $paths = array())
{
$this->kernel = $kernel;
$this->activeTheme = $activeTheme;
$this->path = $path;
$container = $kernel->getContainer();
$this->theme = $container->get('liip_theme.active_theme');
$this->basePaths = $paths;

$this->setActiveTheme($this->theme->getName());
$this->setCurrentTheme($this->activeTheme->getName());
}

/**
* Set the active theme.
*
* @param string $theme
*/
private function setActiveTheme($theme)
public function setCurrentTheme($theme)
{
$this->lastTheme = $theme;

$paths = $this->basePaths;
$this->activeTheme = $theme;
$paths[] = $this->path . "/themes/" . $this->activeTheme; // add active theme as Resources/themes/views folder aswell.

// add active theme as Resources/themes/views folder as well.
$paths[] = $this->path . '/themes/' . $theme;
$paths[] = $this->path;

$this->paths = $paths;
Expand Down Expand Up @@ -91,14 +98,16 @@ private function setActiveTheme($theme)
*/
public function locate($name, $dir = null, $first = true)
{
// update active theme if necessary.
if($this->activeTheme !== $this->theme->getName()) {
$this->setActiveTheme($this->theme->getName());
// update the paths if the theme changed since the last lookup
$theme = $this->activeTheme->getName();
if ($this->lastTheme !== $theme) {
$this->setCurrentTheme($theme);
}

if ('@' === $name[0]) {
return $this->locateResource($name, $this->path, $first);
}

return parent::locate($name, $dir, $first);
}

Expand Down Expand Up @@ -136,10 +145,10 @@ public function locateResource($name, $dir = null, $first = true)
foreach ($bundles as $bundle) {
$checkPaths = array();
if ($dir) {
$checkPaths[] = $dir.'/themes/'.$this->activeTheme.'/'.$bundle->getName().$overridePath;
$checkPaths[] = $dir.'/themes/'.$this->lastTheme.'/'.$bundle->getName().$overridePath;
$checkPaths[] = $dir.'/'.$bundle->getName().$overridePath;
}
$checkPaths[] = $bundle->getPath() . '/Resources/themes/'.$this->activeTheme.substr($path, 15);
$checkPaths[] = $bundle->getPath() . '/Resources/themes/'.$this->lastTheme.substr($path, 15);
foreach ($checkPaths as $checkPath) {
if (file_exists($file = $checkPath)) {
if (null !== $resourceBundle) {
Expand Down
94 changes: 94 additions & 0 deletions Locator/TemplateLocator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

/*
* This file is part of the Liip/ThemeBundle
*
* (c) Liip AG
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Liip\ThemeBundle\Locator;

use Symfony\Bundle\FrameworkBundle\Templating\Loader\TemplateLocator as BaseTemplateLocator;
use Symfony\Component\Config\FileLocatorInterface;
use Symfony\Component\Templating\TemplateReferenceInterface;

use Liip\ThemeBundle\ActiveTheme;

class TemplateLocator extends BaseTemplateLocator
{
/**
* @var ActiveTheme|null
*/
protected $activeTheme;

/**
* Constructor.
*
* @param FileLocatorInterface $locator A FileLocatorInterface instance
* @param string $cacheDir The cache path
* @param ActiveTheme $theme The theme instance
*/
public function __construct(FileLocatorInterface $locator, $cacheDir = null, ActiveTheme $activeTheme = null)
{
$this->activeTheme = $activeTheme;

parent::__construct($locator, $cacheDir);
}

public function getLocator()
{
return $this->locator;
}

/**
* Returns a full path for a given file.
*
* @param TemplateReferenceInterface $template A template
*
* @return string The full path for the file
*/
protected function getCacheKey($template)
{
$name = $template->getLogicalName();

if ($this->activeTheme) {
$name.= '|'.$this->activeTheme->getName();
}

return $name;
}

/**
* Returns a full path for a given file.
*
* @param TemplateReferenceInterface $template A template
* @param string $currentPath Unused
* @param Boolean $first Unused
*
* @return string The full path for the file
*
* @throws \InvalidArgumentException When the template is not an instance of TemplateReferenceInterface
* @throws \InvalidArgumentException When the template file can not be found
*/
public function locate($template, $currentPath = null, $first = true)
{
if (!$template instanceof TemplateReferenceInterface) {
throw new \InvalidArgumentException("The template must be an instance of TemplateReferenceInterface.");
}

$key = $this->getCacheKey($template);

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

try {
return $this->cache[$key] = $this->locator->locate($template->getPath(), $currentPath);
} catch (\InvalidArgumentException $e) {
throw new \InvalidArgumentException(sprintf('Unable to find template "%s" in "%s".', $template, $this->path), 0, $e);
}
}
}
Loading