2014-05-14 13:24:20 +00:00
|
|
|
<?php namespace Cms\Twig;
|
|
|
|
|
|
2015-06-05 07:43:32 +00:00
|
|
|
use Event;
|
2019-07-18 14:50:37 +00:00
|
|
|
use Twig\Source as TwigSource;
|
2019-03-27 19:15:17 +00:00
|
|
|
use Twig\Loader\LoaderInterface as TwigLoaderInterface;
|
2016-03-09 09:51:04 +00:00
|
|
|
use Cms\Contracts\CmsObject;
|
2016-12-07 09:58:25 +00:00
|
|
|
use System\Twig\Loader as LoaderBase;
|
|
|
|
|
use Cms\Classes\Partial as CmsPartial;
|
2014-05-14 13:24:20 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* This class implements a Twig template loader for the CMS.
|
|
|
|
|
*
|
|
|
|
|
* @package october\cms
|
|
|
|
|
* @author Alexey Bobkov, Samuel Georges
|
|
|
|
|
*/
|
2019-03-27 19:15:17 +00:00
|
|
|
class Loader extends LoaderBase implements TwigLoaderInterface
|
2014-05-14 13:24:20 +00:00
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* @var \Cms\Classes\CmsCompoundObject A CMS object to load the template from.
|
|
|
|
|
*/
|
|
|
|
|
protected $obj;
|
|
|
|
|
|
2016-12-07 09:58:25 +00:00
|
|
|
/**
|
|
|
|
|
* @var array Cache
|
|
|
|
|
*/
|
|
|
|
|
protected $fallbackCache = [];
|
|
|
|
|
|
2014-05-14 13:24:20 +00:00
|
|
|
/**
|
|
|
|
|
* Sets a CMS object to load the template from.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
2016-03-09 09:51:04 +00:00
|
|
|
* @param \Cms\Contracts\CmsObject $obj Specifies the CMS object.
|
2020-09-11 21:47:49 +00:00
|
|
|
* @return void
|
2014-05-14 13:24:20 +00:00
|
|
|
*/
|
|
|
|
|
public function setObject(CmsObject $obj)
|
|
|
|
|
{
|
|
|
|
|
$this->obj = $obj;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-05 07:43:32 +00:00
|
|
|
/**
|
|
|
|
|
* Returns the Twig content string.
|
|
|
|
|
* This step is cached internally by Twig.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
|
|
|
|
* @param string $name The template name
|
|
|
|
|
* @return TwigSource
|
2015-06-05 07:43:32 +00:00
|
|
|
*/
|
2017-05-12 23:34:20 +00:00
|
|
|
public function getSourceContext($name)
|
2014-05-14 13:24:20 +00:00
|
|
|
{
|
2016-12-07 09:58:25 +00:00
|
|
|
if (!$this->validateCmsObject($name)) {
|
2017-05-12 23:34:20 +00:00
|
|
|
return parent::getSourceContext($name);
|
2016-12-07 09:58:25 +00:00
|
|
|
}
|
|
|
|
|
|
2015-06-05 07:43:32 +00:00
|
|
|
$content = $this->obj->getTwigContent();
|
|
|
|
|
|
2018-10-12 01:28:17 +00:00
|
|
|
/**
|
|
|
|
|
* @event cms.template.processTwigContent
|
2019-08-15 03:39:26 +00:00
|
|
|
* Provides an opportunity to modify Twig content before being processed by Twig. `$dataHolder` = {content: $twigContent}
|
2018-10-12 01:28:17 +00:00
|
|
|
*
|
|
|
|
|
* Example usage:
|
|
|
|
|
*
|
|
|
|
|
* Event::listen('cms.template.processTwigContent', function ((\Cms\Classes\CmsObject) $thisObject, (object) $dataHolder) {
|
|
|
|
|
* $dataHolder->content = "NO CONTENT FOR YOU!";
|
|
|
|
|
* });
|
|
|
|
|
*
|
2015-06-05 07:43:32 +00:00
|
|
|
*/
|
|
|
|
|
$dataHolder = (object) ['content' => $content];
|
|
|
|
|
Event::fire('cms.template.processTwigContent', [$this->obj, $dataHolder]);
|
|
|
|
|
|
2019-03-27 19:17:26 +00:00
|
|
|
return new TwigSource((string) $dataHolder->content, $name);
|
2014-05-14 13:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
2015-06-05 07:43:32 +00:00
|
|
|
/**
|
|
|
|
|
* Returns the Twig cache key.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
|
|
|
|
* @param string $name The template name
|
|
|
|
|
* @return string
|
2015-06-05 07:43:32 +00:00
|
|
|
*/
|
2014-05-14 13:24:20 +00:00
|
|
|
public function getCacheKey($name)
|
|
|
|
|
{
|
2016-12-07 09:58:25 +00:00
|
|
|
if (!$this->validateCmsObject($name)) {
|
|
|
|
|
return parent::getCacheKey($name);
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-21 06:51:14 +00:00
|
|
|
return $this->obj->getTwigCacheKey();
|
2014-05-14 13:24:20 +00:00
|
|
|
}
|
|
|
|
|
|
2015-06-05 07:43:32 +00:00
|
|
|
/**
|
|
|
|
|
* Determines if the content is fresh.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
|
|
|
|
* @param string $name The template name
|
|
|
|
|
* @param mixed $time The time to check against the template
|
|
|
|
|
* @return bool
|
2015-06-05 07:43:32 +00:00
|
|
|
*/
|
2014-05-14 13:24:20 +00:00
|
|
|
public function isFresh($name, $time)
|
|
|
|
|
{
|
2016-12-07 09:58:25 +00:00
|
|
|
if (!$this->validateCmsObject($name)) {
|
|
|
|
|
return parent::isFresh($name, $time);
|
|
|
|
|
}
|
|
|
|
|
|
2016-01-02 02:41:57 +00:00
|
|
|
return $this->obj->mtime <= $time;
|
2014-05-14 13:24:20 +00:00
|
|
|
}
|
2016-12-07 09:58:25 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns the file name of the loaded template.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
|
|
|
|
* @param string $name The template name
|
|
|
|
|
* @return string
|
2016-12-07 09:58:25 +00:00
|
|
|
*/
|
|
|
|
|
public function getFilename($name)
|
|
|
|
|
{
|
|
|
|
|
if (!$this->validateCmsObject($name)) {
|
|
|
|
|
return parent::getFilename($name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->obj->getFilePath();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Checks that the template exists.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
|
|
|
|
* @param string $name The template name
|
|
|
|
|
* @return bool
|
2016-12-07 09:58:25 +00:00
|
|
|
*/
|
|
|
|
|
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.
|
|
|
|
|
*
|
2020-09-11 21:47:49 +00:00
|
|
|
* @param string $name The template name to validate
|
2016-12-07 09:58:25 +00:00
|
|
|
* @return bool
|
|
|
|
|
*/
|
|
|
|
|
protected function validateCmsObject($name)
|
|
|
|
|
{
|
2020-09-11 21:47:49 +00:00
|
|
|
if ($this->obj && $name === $this->obj->getFilePath()) {
|
2016-12-07 09:58:25 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($fallbackObj = $this->findFallbackObject($name)) {
|
|
|
|
|
$this->obj = $fallbackObj;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Looks up a fallback CMS partial object.
|
2020-09-11 21:47:49 +00:00
|
|
|
*
|
|
|
|
|
* @param string $name The filename to attempt to load a fallback CMS partial for
|
|
|
|
|
* @return Cms\Classes\Partial|bool Returns false if a CMS partial can't be found
|
2016-12-07 09:58:25 +00:00
|
|
|
*/
|
|
|
|
|
protected function findFallbackObject($name)
|
|
|
|
|
{
|
2020-09-11 21:47:49 +00:00
|
|
|
// Ignore Laravel views
|
2016-12-07 09:58:25 +00:00
|
|
|
if (strpos($name, '::') !== false) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-11 21:47:49 +00:00
|
|
|
// Check the cache
|
2016-12-07 09:58:25 +00:00
|
|
|
if (array_key_exists($name, $this->fallbackCache)) {
|
|
|
|
|
return $this->fallbackCache[$name];
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-11 21:47:49 +00:00
|
|
|
// Attempt to load the path as a CMS Partial object
|
|
|
|
|
try {
|
|
|
|
|
$partial = CmsPartial::find($name);
|
|
|
|
|
} catch (\Exception $e) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->fallbackCache[$name] = $partial;
|
2016-12-07 09:58:25 +00:00
|
|
|
}
|
2014-10-10 23:42:04 +00:00
|
|
|
}
|