From 3832d3561bc429853a49675d377b327cb64afa1a Mon Sep 17 00:00:00 2001 From: "Bruno O. Notario" Date: Thu, 8 Feb 2024 00:41:19 -0300 Subject: [PATCH] Twig translate extension refactored Two new DI methods on Registry class --- system/engine/registry.php | 19 ++ system/engine/render.php | 9 +- .../Twig/Api/Extension/TranslateInterface.php | 53 +++++ .../Twig/Extension/ExacTITranslate.php | 184 ----------------- .../Twig/Extension/ExacTITranslate1x.php | 188 ------------------ .../Twig/Extension/Legacy/Node.php | 63 ++++++ .../Twig/Extension/Legacy/TokenParser.php | 96 +++++++++ .../Twig/Extension/Legacy/Translate.php | 59 ++++++ .../templateEngines/Twig/Extension/Node.php | 60 ++++++ .../Twig/Extension/TokenParser.php | 94 +++++++++ .../Twig/Extension/Translate.php | 60 ++++++ system/templateEngines/Twig/autoload.php | 15 +- 12 files changed, 516 insertions(+), 384 deletions(-) create mode 100644 system/templateEngines/Twig/Api/Extension/TranslateInterface.php delete mode 100644 system/templateEngines/Twig/Extension/ExacTITranslate.php delete mode 100644 system/templateEngines/Twig/Extension/ExacTITranslate1x.php create mode 100644 system/templateEngines/Twig/Extension/Legacy/Node.php create mode 100644 system/templateEngines/Twig/Extension/Legacy/TokenParser.php create mode 100644 system/templateEngines/Twig/Extension/Legacy/Translate.php create mode 100644 system/templateEngines/Twig/Extension/Node.php create mode 100644 system/templateEngines/Twig/Extension/TokenParser.php create mode 100644 system/templateEngines/Twig/Extension/Translate.php diff --git a/system/engine/registry.php b/system/engine/registry.php index c79430f..0826fc0 100644 --- a/system/engine/registry.php +++ b/system/engine/registry.php @@ -228,6 +228,25 @@ final class Registry { } } + /** + * + * @param string $for + * @param string $to + * @return void + */ + static public function addDIPreference($for, $to) { + self::$preferences = array_merge(self::$preferences, [$for => $to]); + } + + /** + * + * @param string $for + * @return bool + */ + static public function checkPreferenceExist($for) { + return isset(self::$preferences[$for]); + } + /** * Generate Glob case insensitive pattern * @param string $string diff --git a/system/engine/render.php b/system/engine/render.php index 9d7516a..c0fa149 100644 --- a/system/engine/render.php +++ b/system/engine/render.php @@ -217,13 +217,14 @@ } /** - * @var \transExtension + * @var \Phacil\Framework\templateEngines\Twig\Api\Extension\TranslateInterface */ - $twig->addExtension(new \transExtension()); + $translateExtension = $this->registry->getInstance('Phacil\Framework\templateEngines\Twig\Api\Extension\TranslateInterface'); + $twig->addExtension($translateExtension); - $twig->addFilter(new $Twig_SimpleFilter('translate', function ($str) { + $twig->addFilter(new $Twig_SimpleFilter('translate', function ($str) use ($translateExtension){ // do something different from the built-in date filter - return traduzir($str); + return $translateExtension->traduzir($str); })); $twig->addFilter(new $Twig_SimpleFilter('config', function ($str) { diff --git a/system/templateEngines/Twig/Api/Extension/TranslateInterface.php b/system/templateEngines/Twig/Api/Extension/TranslateInterface.php new file mode 100644 index 0000000..c782b15 --- /dev/null +++ b/system/templateEngines/Twig/Api/Extension/TranslateInterface.php @@ -0,0 +1,53 @@ +getLine(); - - $stream = $this->parser->getStream(); - - // recovers all inline parameters close to your tag name - $params = array_merge(array (), $this->getInlineParams($token)); - - $continue = true; - while ($continue) - { - // create subtree until the decidetransFork() callback returns true - $body = $this->parser->subparse(array ($this, 'decidetransFork')); - - // I like to put a switch here, in case you need to add middle tags, such - // as: {% trans %}, {% nexttrans %}, {% endtrans %}. - $tag = $stream->next()->getValue(); - - switch ($tag) - { - case TWIGtagClose: - $continue = false; - break; - default: - throw new \Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags '.TWIGtagClose.' to close the '.TWIGtagIni.' block started at line %d)', $lineno), -1); - } - - // you want $body at the beginning of your arguments - array_unshift($params, $body); - - // if your endtrans can also contains params, you can uncomment this line: - // $params = array_merge($params, $this->getInlineParams($token)); - // and comment this one: - $stream->expect(\Twig\Token::BLOCK_END_TYPE); - } - - return new transNode(new \Twig\Node\Node($params), $lineno, $this->getTag()); - } - - /** - * Recovers all tag parameters until we find a BLOCK_END_TYPE ( %} ) - * - * @param \Twig_Token $token - * @return array - */ - protected function getInlineParams(\Twig\Token $token) - { - $stream = $this->parser->getStream(); - $params = array (); - while (!$stream->test(\Twig\Token::BLOCK_END_TYPE)) - { - $params[] = $this->parser->getExpressionParser()->parseExpression(); - } - $stream->expect(\Twig\Token::BLOCK_END_TYPE); - return $params; - } - - /** - * Callback called at each tag name when subparsing, must return - * true when the expected end tag is reached. - * - * @param \Twig\Token $token - * @return bool - */ - public function decidetransFork(\Twig\Token $token) - { - return $token->test(array (TWIGtagClose)); - } - - /** - * Your tag name: if the parsed tag match the one you put here, your parse() - * method will be called. - * - * @return string - */ - public function getTag() - { - return TWIGtagIni; - } - -} - - -class transNode extends \Twig\Node\Node -{ - - public function __construct($params, $lineno = 0, $tag = null) - { - parent::__construct(array ('params' => $params), array (), $lineno, $tag); - } - - public function compile(\Twig\Compiler $compiler) - { - $count = count($this->getNode('params')); - - $compiler - ->addDebugInfo($this); - - for ($i = 0; ($i < $count); $i++) - { - // argument is not an expression (such as, a \Twig_Node_Textbody) - // we should trick with output buffering to get a valid argument to pass - // to the functionToCall() function. - if (!($this->getNode('params')->getNode($i) instanceof \Twig\Node\Expression\AbstractExpression)) - { - $compiler - ->write('ob_start();') - ->raw(PHP_EOL); - - $compiler - ->subcompile($this->getNode('params')->getNode($i)); - - $compiler - ->write('$_trans[] = ob_get_clean();') - ->raw(PHP_EOL); - } - else - { - $compiler - ->write('$_trans[] = ') - ->subcompile($this->getNode('params')->getNode($i)) - ->raw(';') - ->raw(PHP_EOL); - } - } - - $compiler - ->write('call_user_func_array(') - ->string('traduzir') - ->raw(', $_trans);') - ->raw(PHP_EOL); - - $compiler - ->write('unset($_trans);') - ->raw(PHP_EOL); - } - -} - - - -class transExtension extends \Twig\Extension\AbstractExtension -{ - - public function getTokenParsers() - { - return array ( - new transTokenParser(), - ); - } - - public function getName() - { - return TWIGtagIni; - } - -} - - -function traduzir() { - $params = func_get_args(); - $body = array_shift($params); - - /** @var \Phacil\Framework\Translate */ - $trans = \Phacil\Framework\Registry::getInstance("Phacil\Framework\Translate"); - echo ($trans->translation($body)); -} \ No newline at end of file diff --git a/system/templateEngines/Twig/Extension/ExacTITranslate1x.php b/system/templateEngines/Twig/Extension/ExacTITranslate1x.php deleted file mode 100644 index cb54b73..0000000 --- a/system/templateEngines/Twig/Extension/ExacTITranslate1x.php +++ /dev/null @@ -1,188 +0,0 @@ -getLine(); - - $stream = $this->parser->getStream(); - - // recovers all inline parameters close to your tag name - $params = array_merge(array (), $this->getInlineParams($token)); - - $continue = true; - while ($continue) - { - // create subtree until the decidetransFork() callback returns true - $body = $this->parser->subparse(array ($this, 'decidetransFork')); - - // I like to put a switch here, in case you need to add middle tags, such - // as: {% trans %}, {% nexttrans %}, {% endtrans %}. - $tag = $stream->next()->getValue(); - - switch ($tag) - { - case TWIGtagClose: - $continue = false; - break; - default: - throw new \Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags '.TWIGtagClose.' to close the '.TWIGtagIni.' block started at line %d)', $lineno), -1); - } - - // you want $body at the beginning of your arguments - array_unshift($params, $body); - - // if your endtrans can also contains params, you can uncomment this line: - // $params = array_merge($params, $this->getInlineParams($token)); - // and comment this one: - $stream->expect(\Twig_Token::BLOCK_END_TYPE); - } - - return new transNode(new \Twig_Node($params), $lineno, $this->getTag()); - } - - /** - * Recovers all tag parameters until we find a BLOCK_END_TYPE ( %} ) - * - * @param \Twig_Token $token - * @return array - */ - protected function getInlineParams(\Twig_Token $token) - { - $stream = $this->parser->getStream(); - $params = array (); - while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) - { - $params[] = $this->parser->getExpressionParser()->parseExpression(); - } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); - return $params; - } - - /** - * Callback called at each tag name when subparsing, must return - * true when the expected end tag is reached. - * - * @param \Twig_Token $token - * @return bool - */ - public function decidetransFork(\Twig_Token $token) - { - return $token->test(array (TWIGtagClose)); - } - - /** - * Your tag name: if the parsed tag match the one you put here, your parse() - * method will be called. - * - * @return string - */ - public function getTag() - { - return TWIGtagIni; - } - -} - - -class transNode extends \Twig_Node -{ - - public function __construct($params, $lineno = 0, $tag = null) - { - parent::__construct(array ('params' => $params), array (), $lineno, $tag); - } - - public function compile(\Twig_Compiler $compiler) - { - $count = count($this->getNode('params')); - - $compiler - ->addDebugInfo($this); - - for ($i = 0; ($i < $count); $i++) - { - // argument is not an expression (such as, a \Twig_Node_Textbody) - // we should trick with output buffering to get a valid argument to pass - // to the functionToCall() function. - if (!($this->getNode('params')->getNode($i) instanceof \Twig_Node_Expression)) - { - $compiler - ->write('ob_start();') - ->raw(PHP_EOL); - - $compiler - ->subcompile($this->getNode('params')->getNode($i)); - - $compiler - ->write('$_trans[] = ob_get_clean();') - ->raw(PHP_EOL); - } - else - { - $compiler - ->write('$_trans[] = ') - ->subcompile($this->getNode('params')->getNode($i)) - ->raw(';') - ->raw(PHP_EOL); - } - } - - $compiler - ->write('call_user_func_array(') - ->string('traduzir') - ->raw(', $_trans);') - ->raw(PHP_EOL); - - $compiler - ->write('unset($_trans);') - ->raw(PHP_EOL); - } - -} - - - -class transExtension extends \Twig_Extension -{ - - public function getTokenParsers() - { - return array ( - new transTokenParser(), - ); - } - - public function getName() - { - return TWIGtagIni; - } - -} - - -function traduzir() { - $params = func_get_args(); - $body = array_shift($params); - - if (class_exists('Translate')) { - $trans = new \Phacil\Framework\Translate(); - echo ($trans->translation($body)); - } else { - echo $body; - } - -} diff --git a/system/templateEngines/Twig/Extension/Legacy/Node.php b/system/templateEngines/Twig/Extension/Legacy/Node.php new file mode 100644 index 0000000..3f2b1e6 --- /dev/null +++ b/system/templateEngines/Twig/Extension/Legacy/Node.php @@ -0,0 +1,63 @@ + $params), array(), $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $count = count($this->getNode('params')); + + $compiler + ->addDebugInfo($this); + + for ($i = 0; ($i < $count); $i++) { + // argument is not an expression (such as, a \Twig_Node_Textbody) + // we should trick with output buffering to get a valid argument to pass + // to the functionToCall() function. + if (!($this->getNode('params')->getNode($i) instanceof \Twig_Node_Expression)) { + $compiler + ->write('ob_start();') + ->raw(PHP_EOL); + + $compiler + ->subcompile($this->getNode('params')->getNode($i)); + + $compiler + ->write('$_trans[] = ob_get_clean();') + ->raw(PHP_EOL); + } else { + $compiler + ->write('$_trans[] = ') + ->subcompile($this->getNode('params')->getNode($i)) + ->raw(';') + ->raw(PHP_EOL); + } + } + + $compiler + ->write('call_user_func_array(') + ->string('\Phacil\Framework\TemplateEngines\Twig\Extension\Legacy\Translate::translate') + ->raw(', $_trans);') + ->raw(PHP_EOL); + + $compiler + ->write('unset($_trans);') + ->raw(PHP_EOL); + } +} \ No newline at end of file diff --git a/system/templateEngines/Twig/Extension/Legacy/TokenParser.php b/system/templateEngines/Twig/Extension/Legacy/TokenParser.php new file mode 100644 index 0000000..cdf3714 --- /dev/null +++ b/system/templateEngines/Twig/Extension/Legacy/TokenParser.php @@ -0,0 +1,96 @@ +getLine(); + + $stream = $this->parser->getStream(); + + // recovers all inline parameters close to your tag name + $params = array_merge(array(), $this->getInlineParams($token)); + + $continue = true; + while ($continue) { + // create subtree until the decidetransFork() callback returns true + $body = $this->parser->subparse(array($this, 'decidetransFork')); + + // I like to put a switch here, in case you need to add middle tags, such + // as: {% trans %}, {% nexttrans %}, {% endtrans %}. + $tag = $stream->next()->getValue(); + + switch ($tag) { + case TranslateInterface::TWIG_TAG_CLOSE: + $continue = false; + break; + default: + throw new \Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags ' . TranslateInterface::TWIG_TAG_CLOSE . ' to close the ' . TranslateInterface::TWIG_TAG_INI . ' block started at line %d)', $lineno), -1); + } + + // you want $body at the beginning of your arguments + array_unshift($params, $body); + + // if your endtrans can also contains params, you can uncomment this line: + // $params = array_merge($params, $this->getInlineParams($token)); + // and comment this one: + $stream->expect(\Twig_Token::BLOCK_END_TYPE); + } + + return new Node(new \Twig_Node($params), $lineno, $this->getTag()); + } + + /** + * Recovers all tag parameters until we find a BLOCK_END_TYPE ( %} ) + * + * @param \Twig_Token $token + * @return array + */ + protected function getInlineParams(Token $token) + { + $stream = $this->parser->getStream(); + $params = array(); + while (!$stream->test(Token::BLOCK_END_TYPE)) { + $params[] = $this->parser->getExpressionParser()->parseExpression(); + } + $stream->expect(Token::BLOCK_END_TYPE); + return $params; + } + + /** + * Callback called at each tag name when subparsing, must return + * true when the expected end tag is reached. + * + * @param \Twig_Token $token + * @return bool + */ + public function decidetransFork(Token $token) + { + return $token->test(array(TranslateInterface::TWIG_TAG_CLOSE)); + } + + /** + * Your tag name: if the parsed tag match the one you put here, your parse() + * method will be called. + * + * @return string + */ + public function getTag() + { + return TranslateInterface::TWIG_TAG_INI; + } +} \ No newline at end of file diff --git a/system/templateEngines/Twig/Extension/Legacy/Translate.php b/system/templateEngines/Twig/Extension/Legacy/Translate.php new file mode 100644 index 0000000..833bc82 --- /dev/null +++ b/system/templateEngines/Twig/Extension/Legacy/Translate.php @@ -0,0 +1,59 @@ +translation($body)); + } + + /** + * {@inheritdoc} + */ + static public function translate() { + $params = func_get_args(); + $body = array_shift($params); + + /** @var \Phacil\Framework\Translate */ + $trans = \Phacil\Framework\Registry::getInstance("Phacil\Framework\Translate"); + echo ($trans->translation($body)); + } +} diff --git a/system/templateEngines/Twig/Extension/Node.php b/system/templateEngines/Twig/Extension/Node.php new file mode 100644 index 0000000..816b808 --- /dev/null +++ b/system/templateEngines/Twig/Extension/Node.php @@ -0,0 +1,60 @@ + $params), array(), $lineno, $tag); + } + + public function compile(\Twig\Compiler $compiler) + { + $count = count($this->getNode('params')); + + $compiler + ->addDebugInfo($this); + + for ($i = 0; ($i < $count); $i++) { + // argument is not an expression (such as, a \Twig_Node_Textbody) + // we should trick with output buffering to get a valid argument to pass + // to the functionToCall() function. + if (!($this->getNode('params')->getNode($i) instanceof \Twig\Node\Expression\AbstractExpression)) { + $compiler + ->write('ob_start();') + ->raw(PHP_EOL); + + $compiler + ->subcompile($this->getNode('params')->getNode($i)); + + $compiler + ->write('$_trans[] = ob_get_clean();') + ->raw(PHP_EOL); + } else { + $compiler + ->write('$_trans[] = ') + ->subcompile($this->getNode('params')->getNode($i)) + ->raw(';') + ->raw(PHP_EOL); + } + } + + $compiler + ->write('call_user_func_array(') + ->string('\Phacil\Framework\templateEngines\Twig\Extension\Translate::translate') + ->raw(', $_trans);') + ->raw(PHP_EOL); + + $compiler + ->write('unset($_trans);') + ->raw(PHP_EOL); + } +} \ No newline at end of file diff --git a/system/templateEngines/Twig/Extension/TokenParser.php b/system/templateEngines/Twig/Extension/TokenParser.php new file mode 100644 index 0000000..baded5b --- /dev/null +++ b/system/templateEngines/Twig/Extension/TokenParser.php @@ -0,0 +1,94 @@ +getLine(); + + $stream = $this->parser->getStream(); + + // recovers all inline parameters close to your tag name + $params = array_merge(array(), $this->getInlineParams($token)); + + $continue = true; + while ($continue) { + // create subtree until the decidetransFork() callback returns true + $body = $this->parser->subparse(array($this, 'decidetransFork')); + + // I like to put a switch here, in case you need to add middle tags, such + // as: {% trans %}, {% nexttrans %}, {% endtrans %}. + $tag = $stream->next()->getValue(); + + switch ($tag) { + case TranslateInterface::TWIG_TAG_CLOSE: + $continue = false; + break; + default: + throw new \Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags ' . TranslateInterface::TWIG_TAG_CLOSE . ' to close the ' . TranslateInterface::TWIG_TAG_INI . ' block started at line %d)', $lineno), -1); + } + + // you want $body at the beginning of your arguments + array_unshift($params, $body); + + // if your endtrans can also contains params, you can uncomment this line: + // $params = array_merge($params, $this->getInlineParams($token)); + // and comment this one: + $stream->expect(\Twig\Token::BLOCK_END_TYPE); + } + + return new Node(new \Twig\Node\Node($params), $lineno, $this->getTag()); + } + + /** + * Recovers all tag parameters until we find a BLOCK_END_TYPE ( %} ) + * + * @param \Twig_Token $token + * @return array + */ + protected function getInlineParams(\Twig\Token $token) + { + $stream = $this->parser->getStream(); + $params = array(); + while (!$stream->test(\Twig\Token::BLOCK_END_TYPE)) { + $params[] = $this->parser->getExpressionParser()->parseExpression(); + } + $stream->expect(\Twig\Token::BLOCK_END_TYPE); + return $params; + } + + /** + * Callback called at each tag name when subparsing, must return + * true when the expected end tag is reached. + * + * @param \Twig\Token $token + * @return bool + */ + public function decidetransFork(\Twig\Token $token) + { + return $token->test(array(TranslateInterface::TWIG_TAG_CLOSE)); + } + + /** + * Your tag name: if the parsed tag match the one you put here, your parse() + * method will be called. + * + * @return string + */ + public function getTag() + { + return TranslateInterface::TWIG_TAG_INI; + } +} \ No newline at end of file diff --git a/system/templateEngines/Twig/Extension/Translate.php b/system/templateEngines/Twig/Extension/Translate.php new file mode 100644 index 0000000..4feda14 --- /dev/null +++ b/system/templateEngines/Twig/Extension/Translate.php @@ -0,0 +1,60 @@ +translation($body)); + } + + /** + * {@inheritdoc} + */ + static public function translate() + { + $params = func_get_args(); + $body = array_shift($params); + + /** @var \Phacil\Framework\Translate */ + $trans = \Phacil\Framework\Registry::getInstance("Phacil\Framework\Translate"); + echo ($trans->translation($body)); + } +} \ No newline at end of file diff --git a/system/templateEngines/Twig/autoload.php b/system/templateEngines/Twig/autoload.php index eda9031..03b1399 100644 --- a/system/templateEngines/Twig/autoload.php +++ b/system/templateEngines/Twig/autoload.php @@ -1,5 +1,6 @@ ') == false) { define('TwigFolderLoad', 'Twig1x'); define('TwigLoaderFilesystem', 'Twig_Loader_Filesystem'); @@ -7,23 +8,21 @@ namespace { define('TwigSimpleFilter', 'Twig_SimpleFilter'); define('TwigExtensionDebug', 'Twig_Extension_Debug'); + if(!\Phacil\Framework\Registry::checkPreferenceExist($preferenceDIObj)){ + \Phacil\Framework\Registry::addDIPreference($preferenceDIObj, "Phacil\\Framework\\templateEngines\\Twig\\Extension\\Legacy\\Translate"); + } } else { define('TwigLoaderFilesystem', '\Twig\Loader\FilesystemLoader'); define('TwigEnvironment', '\Twig\Environment'); define('TwigSimpleFilter', '\Twig\TwigFilter'); define('TwigExtensionDebug', '\Twig\Extension\DebugExtension'); - + if (!\Phacil\Framework\Registry::checkPreferenceExist($preferenceDIObj)) { + \Phacil\Framework\Registry::addDIPreference($preferenceDIObj, 'Phacil\Framework\templateEngines\Twig\Extension\Translate'); + } } if(defined('TwigFolderLoad')){ include_once TwigFolderLoad."/vendor/autoload.php"; } - - - if(defined('TwigFolderLoad') && TwigFolderLoad == 'Twig1x') { - if (file_exists(__DIR__ . "/Extension/ExacTITranslate1x.php")) include __DIR__ . "/Extension/ExacTITranslate1x.php"; - } else { - if (file_exists(__DIR__ . "/Extension/ExacTITranslate.php")) include __DIR__ . "/Extension/ExacTITranslate.php"; - } } \ No newline at end of file