]> git.mxchange.org Git - friendica.git/commitdiff
Refactor template engine code
authorHypolite Petovan <hypolite@mrpetovan.com>
Mon, 18 May 2020 05:18:41 +0000 (01:18 -0400)
committerHypolite Petovan <hypolite@mrpetovan.com>
Mon, 18 May 2020 05:18:41 +0000 (01:18 -0400)
- Convert ITemplateEngine interface to abstract class
- Remove dependency to App in FriendicaSmarty and FriendicaSmartyEngine
- Normalize replaceMacro parameter behavior using Smarty template string prefixes
- Remove obsolete FriendicaSmarty->parsed method
- Update unused Smarty directory paths

src/Core/Renderer.php
src/Render/FriendicaSmarty.php
src/Render/FriendicaSmartyEngine.php
src/Render/ITemplateEngine.php [deleted file]
src/Render/TemplateEngine.php [new file with mode: 0644]
tests/Util/AppMockTrait.php

index 5ce47ad93107e3747b2f2674cf0866c6d6253971..4dab3184c77eb956c8e20830b25b85aad56746d6 100644 (file)
@@ -23,8 +23,7 @@ namespace Friendica\Core;
 
 use Exception;
 use Friendica\DI;
-use Friendica\Render\FriendicaSmarty;
-use Friendica\Render\ITemplateEngine;
+use Friendica\Render\TemplateEngine;
 
 /**
  * This class handles Renderer related functions.
@@ -66,25 +65,23 @@ class Renderer
        ];
 
        /**
-        * This is our template processor
+        * Returns the rendered template output from the template string and variables
         *
-        * @param string|FriendicaSmarty $s    The string requiring macro substitution or an instance of FriendicaSmarty
-        * @param array                  $vars Key value pairs (search => replace)
-        *
-        * @return string substituted string
-        * @throws Exception
+        * @param string $template
+        * @param array  $vars
+        * @return string
         */
-       public static function replaceMacros($s, array $vars = [])
+       public static function replaceMacros(string $template, array $vars)
        {
                $stamp1 = microtime(true);
 
                // pass $baseurl to all templates if it isn't set
-               $vars = array_merge(['$baseurl' => DI::baseUrl()->get()], $vars);
+               $vars = array_merge(['$baseurl' => DI::baseUrl()->get(), '$APP' => DI::app()], $vars);
 
                $t = self::getTemplateEngine();
 
                try {
-                       $output = $t->replaceMacros($s, $vars);
+                       $output = $t->replaceMacros($template, $vars);
                } catch (Exception $e) {
                        echo "<pre><b>" . __FUNCTION__ . "</b>: " . $e->getMessage() . "</pre>";
                        exit();
@@ -98,19 +95,19 @@ class Renderer
        /**
         * Load a given template $s
         *
-        * @param string $   Template to load.
+        * @param string $file   Template to load.
         * @param string $subDir Subdirectory (Optional)
         *
         * @return string template.
         * @throws Exception
         */
-       public static function getMarkupTemplate($s, $subDir = '')
+       public static function getMarkupTemplate($file, $subDir = '')
        {
                $stamp1 = microtime(true);
                $t = self::getTemplateEngine();
 
                try {
-                       $template = $t->getTemplateFile($s, $subDir);
+                       $template = $t->getTemplateFile($file, $subDir);
                } catch (Exception $e) {
                        echo "<pre><b>" . __FUNCTION__ . "</b>: " . $e->getMessage() . "</pre>";
                        exit();
@@ -130,8 +127,7 @@ class Renderer
        {
                $v = get_class_vars($class);
 
-               if (!empty($v['name']))
-               {
+               if (!empty($v['name'])) {
                        $name = $v['name'];
                        self::$template_engines[$name] = $class;
                } else {
@@ -146,7 +142,7 @@ class Renderer
         * If $name is not defined, return engine defined by theme,
         * or default
         *
-        * @return ITemplateEngine Template Engine instance
+        * @return TemplateEngine Template Engine instance
         */
        public static function getTemplateEngine()
        {
@@ -156,8 +152,9 @@ class Renderer
                        if (isset(self::$template_engine_instance[$template_engine])) {
                                return self::$template_engine_instance[$template_engine];
                        } else {
+                               $a = DI::app();
                                $class = self::$template_engines[$template_engine];
-                               $obj = new $class;
+                               $obj = new $class($a->getCurrentTheme(), $a->theme_info);
                                self::$template_engine_instance[$template_engine] = $obj;
                                return $obj;
                        }
index 2b06c88c916b16d66c88822211de7d0aee433e7f..5a1e7ed100810eebb2697214d762e16963aaa0b3 100644 (file)
@@ -21,7 +21,6 @@
 
 namespace Friendica\Render;
 
-use Friendica\DI;
 use Smarty;
 use Friendica\Core\Renderer;
 
@@ -34,26 +33,23 @@ class FriendicaSmarty extends Smarty
 
        public $filename;
 
-       function __construct()
+       function __construct(string $theme, array $theme_info)
        {
                parent::__construct();
 
-               $a = DI::app();
-               $theme = $a->getCurrentTheme();
-
                // setTemplateDir can be set to an array, which Smarty will parse in order.
                // The order is thus very important here
                $template_dirs = ['theme' => "view/theme/$theme/" . self::SMARTY3_TEMPLATE_FOLDER . "/"];
-               if (!empty($a->theme_info['extends'])) {
-                       $template_dirs = $template_dirs + ['extends' => "view/theme/" . $a->theme_info["extends"] . "/" . self::SMARTY3_TEMPLATE_FOLDER . "/"];
+               if (!empty($theme_info['extends'])) {
+                       $template_dirs = $template_dirs + ['extends' => "view/theme/" . $theme_info["extends"] . "/" . self::SMARTY3_TEMPLATE_FOLDER . "/"];
                }
 
                $template_dirs = $template_dirs + ['base' => "view/" . self::SMARTY3_TEMPLATE_FOLDER . "/"];
                $this->setTemplateDir($template_dirs);
 
                $this->setCompileDir('view/smarty3/compiled/');
-               $this->setConfigDir('view/smarty3/config/');
-               $this->setCacheDir('view/smarty3/cache/');
+               $this->setConfigDir('view/smarty3/');
+               $this->setCacheDir('view/smarty3/');
 
                $this->left_delimiter = Renderer::getTemplateLeftDelimiter('smarty3');
                $this->right_delimiter = Renderer::getTemplateRightDelimiter('smarty3');
@@ -63,13 +59,4 @@ class FriendicaSmarty extends Smarty
                // Don't report errors so verbosely
                $this->error_reporting = E_ALL & ~E_NOTICE;
        }
-
-       function parsed($template = '')
-       {
-               if ($template) {
-                       return $this->fetch('string:' . $template);
-               }
-               return $this->fetch('file:' . $this->filename);
-       }
-
-}
\ No newline at end of file
+}
index 6984daa15871e41c4b4079f1eddc3989fec95a61..668b91ea5b5745c409d0f8b3a7919a4e16d73d44 100644 (file)
@@ -23,56 +23,69 @@ namespace Friendica\Render;
 
 use Friendica\Core\Hook;
 use Friendica\DI;
+use Friendica\Util\Strings;
 
 /**
- * Smarty implementation of the Friendica template engine interface
+ * Smarty implementation of the Friendica template abstraction
  */
-class FriendicaSmartyEngine implements ITemplateEngine
+final class FriendicaSmartyEngine extends TemplateEngine
 {
        static $name = "smarty3";
 
-       public function __construct()
+       const FILE_PREFIX = 'file:';
+       const STRING_PREFIX = 'string:';
+
+       /** @var FriendicaSmarty */
+       private $smarty;
+
+       /**
+        * @inheritDoc
+        */
+       public function __construct(string $theme, array $theme_info)
        {
-               if (!is_writable(__DIR__ . '/../../view/smarty3/')) {
+               $this->theme = $theme;
+               $this->theme_info = $theme_info;
+               $this->smarty = new FriendicaSmarty($this->theme, $this->theme_info);
+
+               if (!is_writable(DI::basePath() . '/view/smarty3')) {
                        echo "<b>ERROR:</b> folder <tt>view/smarty3/</tt> must be writable by webserver.";
                        exit();
                }
        }
 
-       // ITemplateEngine interface
-       public function replaceMacros($s, $r)
+       /**
+        * @inheritDoc
+        */
+       public function replaceMacros(string $template, array $vars)
        {
-               $template = '';
-               if (gettype($s) === 'string') {
-                       $template = $s;
-                       $s = new FriendicaSmarty();
+               if (!Strings::startsWith($template, self::FILE_PREFIX)) {
+                       $template = self::STRING_PREFIX . $template;
                }
 
-               $r['$APP'] = DI::app();
-
                // "middleware": inject variables into templates
                $arr = [
-                       "template" => basename($s->filename),
-                       "vars" => $r
+                       'template' => basename($this->smarty->filename),
+                       'vars' => $vars
                ];
-               Hook::callAll("template_vars", $arr);
-               $r = $arr['vars'];
+               Hook::callAll('template_vars', $arr);
+               $vars = $arr['vars'];
 
-               foreach ($r as $key => $value) {
+               foreach ($vars as $key => $value) {
                        if ($key[0] === '$') {
                                $key = substr($key, 1);
                        }
 
-                       $s->assign($key, $value);
+                       $this->smarty->assign($key, $value);
                }
-               return $s->parsed($template);
+
+               return $this->smarty->fetch($template);
        }
 
-       public function getTemplateFile($file, $subDir = '')
+       /**
+        * @inheritDoc
+        */
+       public function getTemplateFile(string $file, string $subDir = '')
        {
-               $a = DI::app();
-               $template = new FriendicaSmarty();
-
                // Make sure $root ends with a slash /
                if ($subDir !== '' && substr($subDir, -1, 1) !== '/') {
                        $subDir = $subDir . '/';
@@ -80,21 +93,20 @@ class FriendicaSmartyEngine implements ITemplateEngine
 
                $root = DI::basePath() . '/' . $subDir;
 
-               $theme = $a->getCurrentTheme();
-               $filename = $template::SMARTY3_TEMPLATE_FOLDER . '/' . $file;
+               $filename = $this->smarty::SMARTY3_TEMPLATE_FOLDER . '/' . $file;
 
-               if (file_exists("{$root}view/theme/$theme/$filename")) {
-                       $template_file = "{$root}view/theme/$theme/$filename";
-               } elseif (!empty($a->theme_info['extends']) && file_exists(sprintf('%sview/theme/%s}/%s', $root, $a->theme_info['extends'], $filename))) {
-                       $template_file = sprintf('%sview/theme/%s}/%s', $root, $a->theme_info['extends'], $filename);
+               if (file_exists("{$root}view/theme/$this->theme/$filename")) {
+                       $template_file = "{$root}view/theme/$this->theme/$filename";
+               } elseif (!empty($this->theme_info['extends']) && file_exists(sprintf('%sview/theme/%s}/%s', $root, $this->theme_info['extends'], $filename))) {
+                       $template_file = sprintf('%sview/theme/%s}/%s', $root, $this->theme_info['extends'], $filename);
                } elseif (file_exists("{$root}/$filename")) {
                        $template_file = "{$root}/$filename";
                } else {
                        $template_file = "{$root}view/$filename";
                }
 
-               $template->filename = $template_file;
+               $this->smarty->filename = $template_file;
 
-               return $template;
+               return self::FILE_PREFIX . $template_file;
        }
 }
diff --git a/src/Render/ITemplateEngine.php b/src/Render/ITemplateEngine.php
deleted file mode 100644 (file)
index b18af69..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-/**
- * @copyright Copyright (C) 2020, Friendica
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <https://www.gnu.org/licenses/>.
- *
- */
-
-namespace Friendica\Render;
-
-/**
- * Interface for template engines
- */
-interface ITemplateEngine
-{
-       public function replaceMacros($s, $v);
-       public function getTemplateFile($file, $subDir = '');
-}
diff --git a/src/Render/TemplateEngine.php b/src/Render/TemplateEngine.php
new file mode 100644 (file)
index 0000000..40fbfea
--- /dev/null
@@ -0,0 +1,60 @@
+<?php
+/**
+ * @copyright Copyright (C) 2020, Friendica
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Render;
+
+/**
+ * Interface for template engines
+ */
+abstract class TemplateEngine
+{
+       /** @var string */
+       static $name;
+
+       /** @var string */
+       protected $theme;
+       /** @var array */
+       protected $theme_info;
+
+       /**
+        * @param string $theme      The current theme name
+        * @param array  $theme_info The current theme info array
+        */
+       abstract public function __construct(string $theme, array $theme_info);
+
+       /**
+        * Returns the rendered template output from the template string and variables
+        *
+        * @param string $template
+        * @param array  $vars
+        * @return string
+        */
+       abstract public function replaceMacros(string $template, array $vars);
+
+       /**
+        * Returns the template string from a file path and an optional sub-directory from the project root
+        *
+        * @param string $file
+        * @param string $subDir
+        * @return mixed
+        */
+       abstract public function getTemplateFile(string $file, string $subDir = '');
+}
index 1f6605390c557d335019007a64cdf326bfffde74..59e1b3f556fd55b534344050317b40a06e2a4f19 100644 (file)
@@ -108,7 +108,7 @@ trait AppMockTrait
                        ->andReturn($this->configMock);
                $this->app
                        ->shouldReceive('getTemplateEngine')
-                       ->andReturn(new FriendicaSmartyEngine());
+                       ->andReturn(new FriendicaSmartyEngine('frio', []));
                $this->app
                        ->shouldReceive('getCurrentTheme')
                        ->andReturn('Smarty3');