From 2c6c7b063d056c410d3a8d8f46ea89632e37070a Mon Sep 17 00:00:00 2001 From: Thomas Hampe Date: Sun, 18 Oct 2020 18:02:02 +0200 Subject: [PATCH] - Added Magento 2.4.0 compatibility - Removed helper functions from `app/functions.php` since the file is no longer available in Magento 2.4 - Removed deprecated function `layoutBlock` from twig environment - Updated to twig to 3.0.* --- Framework/View/TemplateEngine/Twig.php | 174 ++++++++----------------- Plugin/TemplatePlugin.php | 19 ++- README.md | 7 +- Twig/Loader/FilesystemLoader.php | 4 +- composer.json | 12 +- 5 files changed, 78 insertions(+), 138 deletions(-) diff --git a/Framework/View/TemplateEngine/Twig.php b/Framework/View/TemplateEngine/Twig.php index 9d9bce7..58455a8 100644 --- a/Framework/View/TemplateEngine/Twig.php +++ b/Framework/View/TemplateEngine/Twig.php @@ -2,6 +2,8 @@ namespace SchumacherFM\Twig\Framework\View\TemplateEngine; +use LogicException; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Event\ManagerInterface; use Magento\Framework\View\Element\AbstractBlock; @@ -11,30 +13,45 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\Config\ScopeConfigInterface; use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; +use Twig\Extension\DebugExtension; +use Twig\TemplateWrapper; +use Twig\TwigFilter; +use Twig\TwigFunction; class Twig extends Php { const TWIG_CACHE_DIR = 'twig'; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ - protected $_scopeConfig; + protected $scopeConfig; + /** - * @var \Twig_Environment + * @var Environment */ - private $twig = null; + protected $twig = null; + /** * @var DirectoryList */ - protected $_directoryList; + protected $directoryList; + /** * Event manager * - * @var \Magento\Framework\Event\ManagerInterface + * @var ManagerInterface */ protected $eventManager; + /** + * @var BlockInterface + */ + protected $currentBlock; + /** * @param ObjectManagerInterface $helperFactory * @param DirectoryList $directoryList @@ -42,7 +59,7 @@ class Twig extends Php * @param ManagerInterface $eventManager * @param Environment $twig * - * @throws \Magento\Framework\Exception\FileSystemException + * @throws FileSystemException */ public function __construct( ObjectManagerInterface $helperFactory, @@ -53,8 +70,8 @@ public function __construct( ) { parent::__construct($helperFactory); - $this->_directoryList = $directoryList; - $this->_scopeConfig = $scopeConfig; + $this->directoryList = $directoryList; + $this->scopeConfig = $scopeConfig; $this->eventManager = $eventManager; $this->twig = $twig; $this->initTwig(); @@ -63,68 +80,50 @@ public function __construct( /** * Initialises Twig with all Magento 2 necessary functions * - * @throws \Magento\Framework\Exception\FileSystemException + * @throws FileSystemException */ private function initTwig() { $this->twig->setCache($this->getCachePath()); - if ($this->_scopeConfig->isSetFlag('dev/twig/debug')) { + if ($this->scopeConfig->isSetFlag('dev/twig/debug')) { $this->twig->enableDebug(); } else { $this->twig->disableDebug(); } - if ($this->_scopeConfig->isSetFlag('dev/twig/auto_reload')) { + if ($this->scopeConfig->isSetFlag('dev/twig/auto_reload')) { $this->twig->enableAutoReload(); } else { $this->twig->disableAutoReload(); } - if ($this->_scopeConfig->isSetFlag('dev/twig/strict_variables')) { + if ($this->scopeConfig->isSetFlag('dev/twig/strict_variables')) { $this->twig->enableStrictVariables(); } else { $this->twig->disableStrictVariables(); } - $this->twig->setCharset($this->_scopeConfig->getValue('dev/twig/charset')); - $this->twig->addFunction(new \Twig\TwigFunction('helper', [$this, 'helper'])); - $this->twig->addFunction(new \Twig\TwigFunction('layoutBlock', [$this, 'layoutBlock'])); - $this->twig->addFunction(new \Twig\TwigFunction('get*', [$this, 'catchGet'])); - $this->twig->addFunction(new \Twig\TwigFunction('isset', [$this, '__isset'])); - $this->twig->addFunction(new \Twig\TwigFunction('child_html', [$this, 'getChildHtml'], [ + $this->twig->setCharset($this->scopeConfig->getValue('dev/twig/charset')); + $this->twig->addFunction(new TwigFunction('helper', [$this, 'helper'])); + $this->twig->addFunction(new TwigFunction('get*', [$this, 'catchGet'])); + $this->twig->addFunction(new TwigFunction('isset', [$this, '__isset'])); + $this->twig->addFunction(new TwigFunction('child_html', [$this, 'getChildHtml'], [ 'needs_context' => true, 'is_safe' => ['html'] ])); - $this->twig->addFilter(new \Twig\TwigFilter('trans', '__')); - $this->twig->addExtension(new \Twig\Extension\DebugExtension()); - foreach ($this->getDefinedFunctionsInHelpersFile() as $functionName) { - $this->twig->addFunction(new \Twig\TwigFunction($functionName, $functionName)); - } + $this->twig->addFilter(new TwigFilter('trans', '__')); + $this->twig->addExtension(new DebugExtension()); $this->eventManager->dispatch('twig_init', ['twig' => $this->twig]); } - /** - * @return \Twig\Loader\LoaderInterface - * @throws \Magento\Framework\Exception\FileSystemException - */ - private function getLoader() - { - $loader = new \stdClass(); - $this->eventManager->dispatch('twig_loader', ['loader' => $loader]); - if (false === ($loader instanceof \Twig\Loader\LoaderInterface)) { - $loader = new \Twig\Loader\FilesystemLoader($this->_directoryList->getPath(DirectoryList::ROOT)); - } - return $loader; - } - /** * @return string - * @throws \Magento\Framework\Exception\FileSystemException + * @throws FileSystemException */ private function getCachePath() { - if (false === $this->_scopeConfig->isSetFlag('dev/twig/cache')) { + if (false === $this->scopeConfig->isSetFlag('dev/twig/cache')) { return false; } - return $this->_directoryList->getPath(DirectoryList::VAR_DIR) . DIRECTORY_SEPARATOR . self::TWIG_CACHE_DIR; + return $this->directoryList->getPath(DirectoryList::VAR_DIR) . DIRECTORY_SEPARATOR . self::TWIG_CACHE_DIR; } /** @@ -136,19 +135,6 @@ public function catchGet(...$args) return $this->__call('get' . $name, $args); } - /** - * @param $method - * @param $args - * - * @deprecated since 1.7 - * @return mixed - */ - public function layoutBlock($method, $args) - { - @trigger_error(sprintf('Using the "layoutBlock" function in twig is deprecated since version 1.7, use the "block" variable instead.'), E_USER_DEPRECATED); - return $this->__call($method, $args); - } - /** * Render template * Render the named template in the context of a particular block and with @@ -158,33 +144,33 @@ public function layoutBlock($method, $args) * @param string $fileName * @param array $dictionary * @return string rendered template - * @throws \Magento\Framework\Exception\FileSystemException - * @throws \Twig\Error\LoaderError - * @throws \Twig\Error\RuntimeError - * @throws \Twig\Error\SyntaxError + * @throws FileSystemException + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError */ public function render(BlockInterface $block, $fileName, array $dictionary = []) { - $tmpBlock = $this->_currentBlock; - $this->_currentBlock = $block; + $tmpBlock = $this->currentBlock; + $this->currentBlock = $block; $this->twig->addGlobal('block', $block); $result = $this->getTemplate($fileName)->render($dictionary); - $this->_currentBlock = $tmpBlock; + $this->currentBlock = $tmpBlock; return $result; } /** * @param $fileName * - * @return \Twig\TemplateWrapper - * @throws \Magento\Framework\Exception\FileSystemException - * @throws \Twig\Error\LoaderError - * @throws \Twig\Error\RuntimeError - * @throws \Twig\Error\SyntaxError + * @return TemplateWrapper + * @throws FileSystemException + * @throws LoaderError + * @throws RuntimeError + * @throws SyntaxError */ private function getTemplate($fileName) { - $tf = str_replace($this->_directoryList->getPath(DirectoryList::ROOT) . DIRECTORY_SEPARATOR, '', $fileName); + $tf = str_replace($this->directoryList->getPath(DirectoryList::ROOT) . DIRECTORY_SEPARATOR, '', $fileName); return $this->twig->load($tf); } @@ -193,13 +179,13 @@ private function getTemplate($fileName) * * @param string $className * @return AbstractHelper - * @throws \LogicException + * @throws LogicException */ public function helper($className) { $helper = $this->_helperFactory->get($className); if (false === $helper instanceof AbstractHelper) { - throw new \LogicException($className . ' doesn\'t extends Magento\Framework\App\Helper\AbstractHelper'); + throw new LogicException($className . ' doesn\'t extends Magento\Framework\App\Helper\AbstractHelper'); } return $helper; } @@ -216,54 +202,4 @@ public function getChildHtml(array $context, $alias = '', $useCache = true) return $block->getChildHtml($alias, $useCache); } - /** - * @return array - * @throws \Magento\Framework\Exception\FileSystemException - */ - private function getDefinedFunctionsInHelpersFile() - { - $filepath = $this->_directoryList->getPath(DirectoryList::APP) . '/functions.php'; - $source = file_get_contents($filepath); - $tokens = token_get_all($source); - $functions = array(); - $nextStringIsFunc = false; - $inClass = false; - $bracesCount = 0; - foreach ($tokens as $token) { - switch ($token[0]) { - case T_CLASS: - $inClass = true; - break; - case T_FUNCTION: - if (!$inClass) { - $nextStringIsFunc = true; - } - break; - case T_STRING: - if ($nextStringIsFunc) { - $nextStringIsFunc = false; - $functions[] = $token[1]; - } - break; - // Anonymous functions - case '(': - case ';': - $nextStringIsFunc = false; - break; - // Exclude Classes - case '{': - if ($inClass) $bracesCount++; - break; - case '}': - if ($inClass) { - $bracesCount--; - if ($bracesCount === 0) { - $inClass = false; - } - } - break; - } - } - return $functions; - } } diff --git a/Plugin/TemplatePlugin.php b/Plugin/TemplatePlugin.php index e00b5cf..e7b0fb0 100644 --- a/Plugin/TemplatePlugin.php +++ b/Plugin/TemplatePlugin.php @@ -2,39 +2,36 @@ namespace SchumacherFM\Twig\Plugin; +use Magento\Framework\View\Element\Template; +use Magento\Framework\View\Element\Template\File\Validator; + /** * Class TemplatePlugin */ class TemplatePlugin { /** - * @var \Magento\Framework\View\Element\Template\File\Validator + * @var Validator */ protected $validator; /** * TemplatePlugin constructor. * - * @param \Magento\Framework\View\Element\Template\File\Validator $validator + * @param Validator $validator */ - public function __construct( - \Magento\Framework\View\Element\Template\File\Validator $validator - ) + public function __construct(Validator $validator) { $this->validator = $validator; } /** - * @param \Magento\Framework\View\Element\Template $subject + * @param Template $subject * @param callable $proceed * @param string $fileName * @return string */ - public function aroundFetchView( - \Magento\Framework\View\Element\Template $subject, - callable $proceed, - string $fileName - ): string + public function aroundFetchView(Template $subject, callable $proceed, string $fileName): string { $twigFile = $subject->getTemplateFile(str_replace('.phtml', '.html.twig', $subject->getTemplate())); diff --git a/README.md b/README.md index c6bd8fd..31232aa 100644 --- a/README.md +++ b/README.md @@ -163,9 +163,12 @@ For versioning have a look at [Semantic Versioning 2.0.0](http://semver.org/) History ------- -#### 0.1.0 +#### 2.0.0 -- Initial release +- Added Magento 2.4.0 compatibility +- Removed helper functions from `app/functions.php` since the file is no longer available in Magento 2.4 +- Removed deprecated function `layoutBlock` from twig environment +- Updated to twig to 3.0.* License ------- diff --git a/Twig/Loader/FilesystemLoader.php b/Twig/Loader/FilesystemLoader.php index 190bb1d..e09b8b6 100755 --- a/Twig/Loader/FilesystemLoader.php +++ b/Twig/Loader/FilesystemLoader.php @@ -1,9 +1,8 @@ -getInheritedThemes(); foreach ($inheritedThemes as $inheritanceLevel => $currentTheme) { $themeFiles = $this->themeFilesCollector->getFiles($currentTheme, 'templates'); diff --git a/composer.json b/composer.json index 5acba4b..c802eb1 100644 --- a/composer.json +++ b/composer.json @@ -2,14 +2,14 @@ "name": "schumacherfm/magento-twig", "description": "Twig template engine for Magento 2", "require": { - "php": "~5.6.0|7.0.2|7.0.4|~7.0.6|~7.1.0|~7.2.0|~7.3.0|~7.4.0", + "php": "~7.2.0|~7.3.0|~7.4.0", "magento/framework": ">=100.0.0", "magento/module-backend": ">=100.0.0", "magento/module-config": ">=100.0.0", - "twig/twig": "~2.0" + "twig/twig": "^3.0" }, "type": "magento2-module", - "version": "1.8.1", + "version": "2.0.0", "license": [ "OSL-3.0" ], @@ -20,6 +20,12 @@ "role": "Developer" } ], + "repositories": [ + { + "type": "composer", + "url": "https://repo.magento.com/" + } + ], "autoload": { "files": [ "registration.php"