winter/modules/cms/twig/Loader.php
2017-05-13 09:34:20 +10:00

144 lines
3.2 KiB
PHP

<?php namespace Cms\Twig;
use Event;
use Twig_Source;
use Twig_LoaderInterface;
use Cms\Contracts\CmsObject;
use System\Twig\Loader as LoaderBase;
use Cms\Classes\Partial as CmsPartial;
/**
* This class implements a Twig template loader for the CMS.
*
* @package october\cms
* @author Alexey Bobkov, Samuel Georges
*/
class Loader extends LoaderBase implements Twig_LoaderInterface
{
/**
* @var \Cms\Classes\CmsCompoundObject A CMS object to load the template from.
*/
protected $obj;
/**
* @var array Cache
*/
protected $fallbackCache = [];
/**
* Sets a CMS object to load the template from.
* @param \Cms\Contracts\CmsObject $obj Specifies the CMS object.
*/
public function setObject(CmsObject $obj)
{
$this->obj = $obj;
}
/**
* Returns the Twig content string.
* This step is cached internally by Twig.
*/
public function getSourceContext($name)
{
if (!$this->validateCmsObject($name)) {
return parent::getSourceContext($name);
}
$content = $this->obj->getTwigContent();
/*
* Extensibility
*/
$dataHolder = (object) ['content' => $content];
Event::fire('cms.template.processTwigContent', [$this->obj, $dataHolder]);
return new Twig_Source($dataHolder->content, $name);
}
/**
* Returns the Twig cache key.
*/
public function getCacheKey($name)
{
if (!$this->validateCmsObject($name)) {
return parent::getCacheKey($name);
}
return $this->obj->getTwigCacheKey();
}
/**
* Determines if the content is fresh.
*/
public function isFresh($name, $time)
{
if (!$this->validateCmsObject($name)) {
return parent::isFresh($name, $time);
}
return $this->obj->mtime <= $time;
}
/**
* Returns the file name of the loaded template.
*/
public function getFilename($name)
{
if (!$this->validateCmsObject($name)) {
return parent::getFilename($name);
}
return $this->obj->getFilePath();
}
/**
* Checks that the template exists.
*/
public function exists($name)
{
if (!$this->validateCmsObject($name)) {
return parent::exists($name);
}
return $this->obj->exists;
}
/**
* Internal method that checks if the template name matches
* the loaded object, with fallback support to partials.
*
* @return bool
*/
protected function validateCmsObject($name)
{
if ($name == $this->obj->getFilePath()) {
return true;
}
if ($fallbackObj = $this->findFallbackObject($name)) {
$this->obj = $fallbackObj;
return true;
}
return false;
}
/**
* Looks up a fallback CMS partial object.
* @return Cms\Classes\Partial
*/
protected function findFallbackObject($name)
{
if (strpos($name, '::') !== false) {
return false;
}
if (array_key_exists($name, $this->fallbackCache)) {
return $this->fallbackCache[$name];
}
return $this->fallbackCache[$name] = CmsPartial::find($name);
}
}