From 480d0ecd3d7668acfe33bc78c812a526133aa487 Mon Sep 17 00:00:00 2001 From: Abel Hoogeveen Date: Sun, 2 Dec 2018 23:09:28 +0100 Subject: [PATCH] Initial commit --- .gitattributes | 4 + .gitignore | 6 + LICENSE | 21 + README.md | 59 ++ composer.json | 37 ++ src/FuzeWorks/Event/LayoutDisplayEvent.php | 72 +++ src/FuzeWorks/Event/LayoutLoadEvent.php | 86 +++ src/FuzeWorks/Exception/LanguageException.php | 49 ++ src/FuzeWorks/Exception/LayoutException.php | 49 ++ src/FuzeWorks/Languages.php | 43 ++ src/FuzeWorks/Layout.php | 539 ++++++++++++++++++ src/FuzeWorks/LayoutComponent.php | 57 ++ src/FuzeWorks/TemplateEngine/JsonEngine.php | 114 ++++ src/FuzeWorks/TemplateEngine/LatteEngine.php | 112 ++++ src/FuzeWorks/TemplateEngine/PHPEngine.php | 94 +++ src/FuzeWorks/TemplateEngine/SmartyEngine.php | 172 ++++++ .../TemplateEngine/TemplateEngine.php | 75 +++ test/autoload.php | 63 ++ test/bootstrap.php | 61 ++ test/layout/LayoutTest.php | 485 ++++++++++++++++ test/layout/LayoutTestAbstract.php | 68 +++ test/phpunit.xml | 34 ++ test/temp/placeholder | 0 .../testCustomEngine/layout.test.test | 0 .../testCustomEngine/layout.test.test2 | 0 .../testEngineVariables/layout.json.json | 0 .../testEngineVariables/layout.php.php | 2 + .../testEngineVariables/layout.smarty.tpl | 1 + test/templates/testEngines/layout.json.json | 1 + test/templates/testEngines/layout.php.php | 1 + test/templates/testEngines/layout.smarty.tpl | 1 + .../testGetFilePath/Deeper/layout.test.php | 0 .../testGetFilePath/layout.JSON.json | 0 .../templates/testGetFilePath/layout.test.php | 0 test/templates/testLayoutGet/layout.test.php | 1 + .../layout.test.php | 1 + .../layout.test.php | 1 + .../testLayoutGetRepeat/layout.first.php | 1 + .../testLayoutGetRepeat/layout.second.php | 1 + .../testMissingFile/layout.test.json | 0 .../layout.test.unknown | 0 41 files changed, 2311 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 composer.json create mode 100644 src/FuzeWorks/Event/LayoutDisplayEvent.php create mode 100644 src/FuzeWorks/Event/LayoutLoadEvent.php create mode 100644 src/FuzeWorks/Exception/LanguageException.php create mode 100644 src/FuzeWorks/Exception/LayoutException.php create mode 100644 src/FuzeWorks/Languages.php create mode 100644 src/FuzeWorks/Layout.php create mode 100644 src/FuzeWorks/LayoutComponent.php create mode 100644 src/FuzeWorks/TemplateEngine/JsonEngine.php create mode 100644 src/FuzeWorks/TemplateEngine/LatteEngine.php create mode 100644 src/FuzeWorks/TemplateEngine/PHPEngine.php create mode 100644 src/FuzeWorks/TemplateEngine/SmartyEngine.php create mode 100644 src/FuzeWorks/TemplateEngine/TemplateEngine.php create mode 100644 test/autoload.php create mode 100644 test/bootstrap.php create mode 100644 test/layout/LayoutTest.php create mode 100644 test/layout/LayoutTestAbstract.php create mode 100644 test/phpunit.xml create mode 100644 test/temp/placeholder create mode 100644 test/templates/testCustomEngine/layout.test.test create mode 100644 test/templates/testCustomEngine/layout.test.test2 create mode 100644 test/templates/testEngineVariables/layout.json.json create mode 100644 test/templates/testEngineVariables/layout.php.php create mode 100644 test/templates/testEngineVariables/layout.smarty.tpl create mode 100644 test/templates/testEngines/layout.json.json create mode 100644 test/templates/testEngines/layout.php.php create mode 100644 test/templates/testEngines/layout.smarty.tpl create mode 100644 test/templates/testGetFilePath/Deeper/layout.test.php create mode 100644 test/templates/testGetFilePath/layout.JSON.json create mode 100644 test/templates/testGetFilePath/layout.test.php create mode 100644 test/templates/testLayoutGet/layout.test.php create mode 100644 test/templates/testLayoutGetCancelledEvent/layout.test.php create mode 100644 test/templates/testLayoutGetEventWrongFile/layout.test.php create mode 100644 test/templates/testLayoutGetRepeat/layout.first.php create mode 100644 test/templates/testLayoutGetRepeat/layout.second.php create mode 100644 test/templates/testMissingFile/layout.test.json create mode 100644 test/templates/testUnknownFileExtension/layout.test.unknown diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d2012c6 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +.gitattributes export-ignore +.gitignore export-ignore +.gitlab-ci.yml export-ignore +tests/ export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb2af7b --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +composer.lock +composer.phar +.idea/ +build/ +test/temp/ +vendor/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ba1d7c2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2013-2018 TechFuze + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..0629396 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +FuzeWorks::Layout Component - Readme +=================== + +Version 1.2.0 + +A versatile PHP Framework built to perform. + +https://techfuze.net/fuzeworks + +Summary +------- + +The FuzeWorks Layout Component provides a wrapper for multiple template engines +into FuzeWorks. This allows the developer to easily switch between different engines and +integrate these into FuzeWorks projects. This system consists of a ``Component`` and thus should +be loaded before creating the FuzeWorks ``Container``. + +Copyright +--------- + +Copyright © 2013 onwards -- TechFuze + +Certain libraries are copyrighted by their respective authors; +see the full copyright list for details. + +License +------- + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Licensing of current contributions +---------------------------------- + +Beginning on 2018-04-17, new contributions to this codebase are all licensed +under terms compatible with the MIT license. FuzeWorks is currently +transitioning older code to the MIT License, but work is not yet complete. + +Enjoy! +------ + +TechFuze \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..13df262 --- /dev/null +++ b/composer.json @@ -0,0 +1,37 @@ +{ + "name": "fuzeworks/layout", + "description": "FuzeWorks Framework Layout Template System", + "license": ["MIT"], + "authors": [ + { + "name": "TechFuze", + "homepage": "https://techfuze.net" + }, + { + "name": "FuzeWorks Community", + "homepage": "https://techfuze.net/fuzeworks/contributors" + } + ], + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "fuzeworks/core": "dev-development", + "ext-json": "*", + "smarty/smarty": "~3.1", + "latte/latte": "~2.4", + "phpunit/phpunit": "^7", + "mikey179/vfsStream": "1.6.5", + "tracy/tracy": "2.4.*" + }, + "suggest": { + "smarty/smarty": "Template Engine that is natively supported by FuzeWorks.", + "latte/latte": "Template Engine that is natively supported by FuzeWorks" + }, + "autoload": { + "psr-4": { + "FuzeWorks\\": "src/FuzeWorks/" + } + } + +} \ No newline at end of file diff --git a/src/FuzeWorks/Event/LayoutDisplayEvent.php b/src/FuzeWorks/Event/LayoutDisplayEvent.php new file mode 100644 index 0000000..88f03ea --- /dev/null +++ b/src/FuzeWorks/Event/LayoutDisplayEvent.php @@ -0,0 +1,72 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class LayoutDisplayEvent extends Event +{ + /** + * @var string Contents of the layout + */ + public $contents; + + /** + * @var string File. File that the contents derived from + */ + public $file; + + /** + * @var string directory. Directory that the layout file resides in. + */ + public $directory; + + public function init(string $contents, string $file, string $directory) + { + $this->contents = $contents; + $this->file = $file; + $this->directory = $directory; + } +} diff --git a/src/FuzeWorks/Event/LayoutLoadEvent.php b/src/FuzeWorks/Event/LayoutLoadEvent.php new file mode 100644 index 0000000..9a584f2 --- /dev/null +++ b/src/FuzeWorks/Event/LayoutLoadEvent.php @@ -0,0 +1,86 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class LayoutLoadEvent extends Event +{ + /** + * The directory of the layout to be loaded. + * + * @var string + */ + public $directory; + + /** + * The file of the layout to be loaded. + * + * @var string + */ + public $file; + + /** + * The engine the file will be loaded with. + * + * @var object + */ + public $engine; + + /** + * The assigned variables to the template. + * + * @var array + */ + public $assigned_variables; + + public function init($file, $directory, $engine, $assigned_variables) + { + $this->file = $file; + $this->directory = $directory; + $this->engine = $engine; + $this->assigned_variables = $assigned_variables; + } +} diff --git a/src/FuzeWorks/Exception/LanguageException.php b/src/FuzeWorks/Exception/LanguageException.php new file mode 100644 index 0000000..4b2f5a1 --- /dev/null +++ b/src/FuzeWorks/Exception/LanguageException.php @@ -0,0 +1,49 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class LanguageException extends Exception +{ +} + +?> \ No newline at end of file diff --git a/src/FuzeWorks/Exception/LayoutException.php b/src/FuzeWorks/Exception/LayoutException.php new file mode 100644 index 0000000..372a392 --- /dev/null +++ b/src/FuzeWorks/Exception/LayoutException.php @@ -0,0 +1,49 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class LayoutException extends Exception +{ +} + +?> \ No newline at end of file diff --git a/src/FuzeWorks/Languages.php b/src/FuzeWorks/Languages.php new file mode 100644 index 0000000..91210d8 --- /dev/null +++ b/src/FuzeWorks/Languages.php @@ -0,0 +1,43 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class Layout +{ + + /** + * @var Factory + */ + protected $factory; + + /** + * The file to be loaded by the layout manager. + * + * @var null|string + */ + public $file = null; + + /** + * The directory of the file to be loaded by the layout manager. + * + * @var string + */ + public $directory; + + /** + * All assigned currently assigned to the template. + * + * @var array Associative Assigned Variable Array + */ + protected $assigned_variables = array(); + + /** + * All engines that can be used for templates. + * + * @var array of engines + */ + protected $engines = array(); + + /** + * All file extensions that can be used and are bound to a template engine. + * + * @var array of names of engines + */ + protected $file_extensions = array(); + + /** + * whether the template engines are already called. + * + * @var bool True if loaded + */ + protected $engines_loaded = false; + + /** + * The currently selected template engine. + * + * @var string name of engine + */ + protected $current_engine; + + /** + * Standard Component method for initializing components after adding extensions + */ + public function init() + { + $this->factory = Factory::getInstance(); + $this->directory = Core::$appDirs[0] . DS .'Layout'; + } + + /** + * Retrieve a template file using a string and a directory and immediatly parse it to the output class. + * + * What template file gets loaded depends on the template engine that is being used. + * PHP for example uses .php files. Providing this function with 'home/dashboard' will load the home/layout.dashboard.php file. + * You can also provide no particular engine, and the manager will decide what template to load. + * Remember that doing so will result in a LayoutException when multiple compatible files are found. + * + * @param string $file File to load + * @param string $directory Directory to load it from + * + * @return mixed + * @throws LayoutException On error + * @throws EventException + */ + public function display($file, $directory = null) + { + $directory = (is_null($directory) ? $this->directory : $directory); + $contents = $this->get($file, $directory); + + $event = Events::fireEvent('layoutDisplayEvent', $contents, $file, $directory); + if (!$event->isCancelled()) + echo $event->contents; + + return true; + } + + /** + * Retrieve a template file using a string and a directory. + * + * What template file gets loaded depends on the template engine that is being used. + * PHP for example uses .php files. Providing this function with 'home/dashboard' will load the home/layout.dashboard.php file. + * You can also provide no particular engine, and the manager will decide what template to load. + * Remember that doing so will result in a LayoutException when multiple compatible files are found. + * + * @param string $file File to load + * @param string $directory Directory to load it from + * + * @return string The output of the template + * @throws LayoutException On error + */ + public function get($file, $directory = null): string + { + $directory = (is_null($directory) ? $this->directory : $directory); + Logger::newLevel("Loading template file '".$file."' in '".$directory."'"); + + // First load the template engines + $this->loadTemplateEngines(); + + // First retrieve the filePath + if (is_null($this->current_engine)) { + $this->setFileFromString($file, $directory, array_keys($this->file_extensions)); + } else { + $this->setFileFromString($file, $directory, $this->current_engine->getFileExtensions()); + } + + // Then assign some basic variables for the template + $main_config = $this->factory->config->get('main'); + $this->assigned_variables['wwwDir'] = $main_config->base_url; + $this->assigned_variables['siteURL'] = $main_config->base_url; + $this->assigned_variables['serverName'] = $main_config->server_name; + $this->assigned_variables['adminMail'] = $main_config->administrator_mail; + // @TODO: Implement csrfTokenName and csrfHash from security under layoutLoadEvent + + // Select an engine if one is not already selected + if (is_null($this->current_engine)) { + $this->current_engine = $this->getEngineFromExtension($this->getExtensionFromFile($this->file)); + } + + $this->current_engine->setDirectory($this->directory); + + // And run an Event to see what other parts have to say about it + try { + /** @var LayoutLoadEvent $event */ + $event = Events::fireEvent('layoutLoadEvent', $this->file, $this->directory, $this->current_engine, $this->assigned_variables); + // @codeCoverageIgnoreStart + } catch (EventException $e) { + throw new LayoutException("layoutEvent threw exception: '".$e->getMessage()."''", 1); + // @codeCoverageIgnoreEnd + } + + // The event has been cancelled + if ($event->isCancelled()) { + return 'cancelled'; + } + + // And refetch the data from the event + $this->current_engine = $event->engine; + $this->assigned_variables = $event->assigned_variables; + + Logger::stopLevel(); + + // And finally run it + if (file_exists($event->file)) { + return $this->current_engine->get($event->file, $this->assigned_variables); + } + + throw new LayoutException('The requested file was not found', 1); + } + + /** + * Retrieve a Template Engine from a File Extension. + * + * @param string $extension File extention to look for + * + * @return TemplateEngine + * @throws LayoutException + */ + public function getEngineFromExtension($extension): TemplateEngine + { + if (isset($this->file_extensions[strtolower($extension)])) { + return $this->engines[ $this->file_extensions[strtolower($extension)]]; + } + + throw new LayoutException('Could not get Template Engine. No engine has corresponding file extension', 1); + } + + /** + * Retrieve the extension from a file string. + * + * @param string $fileString The path to the file + * + * @return string Extension of the file + */ + public function getExtensionFromFile($fileString): string + { + return substr($fileString, strrpos($fileString, '.') + 1); + } + + /** + * Converts a layout string to a file using the directory and the used extensions. + * + * It will detect whether the file exists and choose a file according to the provided extensions + * + * @param string $string The string used by a controller. eg: 'dashboard/home' + * @param string $directory The directory to search in for the template + * @param array $extensions Extensions to use for this template. Eg array('php', 'tpl') etc. + * + * @return string Filepath of the template + * @throws LayoutException On error + */ + public function getFileFromString($string, $directory, $extensions = array()): string + { + $directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : $this->directory).DS); + + // @TODO Malformed strings pass. Write better function + if (strpbrk($directory, "\\/?%*:|\"<>") === TRUE || strpbrk($string, "\\/?%*:|\"<>") === TRUE) + { + // @codeCoverageIgnoreStart + throw new LayoutException('Could not get file. Invalid file string', 1); + // @codeCoverageIgnoreEnd + } + + if (!file_exists($directory)) { + throw new LayoutException('Could not get file. Directory does not exist', 1); + } + + // Set the file name and location + $layoutSelector = explode('/', $string); + if (count($layoutSelector) == 1) { + $layoutSelector = 'layout.'.$layoutSelector[0]; + } else { + // Get last file + $file = end($layoutSelector); + + // Reset to start + reset($layoutSelector); + + // Remove last value + array_pop($layoutSelector); + + $layoutSelector[] = 'layout.'.$file; + + // And create the final value + $layoutSelector = implode(DS, $layoutSelector); + } + + // Then try and select a file + $fileSelected = false; + $selectedFile = null; + foreach ($extensions as $extension) { + $file = $directory.$layoutSelector.'.'.strtolower($extension); + $file = preg_replace('#/+#', '/', $file); + if (file_exists($file) && !$fileSelected) { + $selectedFile = $file; + $fileSelected = true; + Logger::log("Found matching file: '".$file."'"); + } elseif (file_exists($file) && $fileSelected) { + throw new LayoutException('Could not select template. Multiple valid extensions detected. Can not choose.', 1); + } + } + + // And choose what to output + if (!$fileSelected) { + throw new LayoutException('Could not select template. No matching file found.'); + } + + return $selectedFile; + } + + /** + * Converts a layout string to a file using the directory and the used extensions. + * It also sets the file variable of this class. + * + * It will detect whether the file exists and choose a file according to the provided extensions + * + * @param string $string The string used by a controller. eg: 'dashboard/home' + * @param string $directory The directory to search in for the template + * @param array $extensions Extensions to use for this template. Eg array('php', 'tpl') etc. + * + * @throws LayoutException On error + */ + public function setFileFromString($string, $directory, $extensions = array()) + { + $this->file = $this->getFileFromString($string, $directory, $extensions); + $this->directory = preg_replace('#/+#', '/', (!is_null($directory) ? $directory : $this->directory).DS); + } + + /** + * Get the current file to be loaded. + * + * @return null|string Path to the file + */ + public function getFile() + { + return $this->file; + } + + /** + * Set the file to be loaded. + * + * @param string $file Path to the file + */ + public function setFile($file) + { + $this->file = $file; + } + + /** + * Get the directory of the file to be loaded. + * + * @return null|string Path to the directory + */ + public function getDirectory() + { + return $this->directory; + } + + /** + * Set the directory of the file to be loaded. + * + * @param string $directory Path to the directory + */ + public function setDirectory($directory) + { + $this->directory = $directory; + } + + /** + * Assign a variable for the template. + * + * @param string $key Key of the variable + * @param mixed $value Value of the variable + */ + public function assign($key, $value) + { + $this->assigned_variables[$key] = $value; + } + + /** + * Set the title of the template. + * + * @param string $title title of the template + */ + public function setTitle($title) + { + $this->assigned_variables['title'] = $title; + } + + /** + * Get the title of the template. + * + * @return string|bool title of the template + */ + public function getTitle() + { + if (!isset($this->assigned_variables['title'])) + { + return false; + } + return $this->assigned_variables['title']; + } + + /** + * Set the engine for the next layout. + * + * @param string $name Name of the template engine + * + * @return bool true on success + * @throws LayoutException on error + */ + public function setEngine($name): bool + { + $this->loadTemplateEngines(); + if (isset($this->engines[$name])) { + $this->current_engine = $this->engines[$name]; + Logger::log('Set the Template Engine to '.$name); + + return true; + } + throw new LayoutException('Could not set engine. Engine does not exist', 1); + } + + /** + * Get a loaded template engine. + * + * @param string $name Name of the template engine + * + * @return TemplateEngine + * @throws LayoutException + */ + public function getEngine(string $name): TemplateEngine + { + $this->loadTemplateEngines(); + if (isset($this->engines[$name])) { + return $this->engines[$name]; + } + throw new LayoutException('Could not return engine. Engine does not exist', 1); + } + + /** + * Register a new template engine. + * + * @param TemplateEngine $engineClass Object that implements the \FuzeWorks\TemplateEngine + * @param string $engineName Name of the template engine + * @param array $engineFileExtensions File extensions this template engine should be used for + * + * @return bool true on success + * @throws LayoutException + */ + public function registerEngine(TemplateEngine $engineClass, string $engineName, array $engineFileExtensions = array()): bool + { + // First check if the engine already exists + if (isset($this->engines[$engineName])) + throw new LayoutException("Could not register engine. Engine '".$engineName."' already registered", 1); + + // Install it + $this->engines[$engineName] = $engineClass; + + // Then install them + foreach ($engineFileExtensions as $extension) { + if (isset($this->file_extensions[strtolower($extension)])) { + throw new LayoutException('Could not register engine. File extension already bound to engine', 1); + } + + // And add it + $this->file_extensions[strtolower($extension)] = $engineName; + } + + // And log it + Logger::log('Registered Template Engine: '.$engineName); + + return true; + } + + /** + * Load the template engines by sending a layoutLoadEngineEvent. + * @throws LayoutException + * @returns bool True on loading. False when already loaded + */ + public function loadTemplateEngines(): bool + { + if (!$this->engines_loaded) { + // Fire Engine Event + try { + Events::fireEvent('layoutLoadEngineEvent'); + } catch (Exception\EventException $e) { + throw new LayoutException("Could not loadTemplateEngines. layoutLoadEngineEvent threw exception: '".$e->getMessage()."''", 1); + } + + // Load the engines provided in this file + // PHP Engine + $this->registerEngine(new PHPEngine(), 'PHP', array('php')); + + // JSON Engine + if (extension_loaded('json')) + $this->registerEngine(new JsonEngine(), 'JSON', array('json')); + + // Latte Engine + if (class_exists('\Latte\Engine', true)) + $this->registerEngine(new LatteEngine(), 'Latte', array('latte')); + + // Smarty Engine + if (class_exists('\Smarty', true)) + $this->registerEngine(new SmartyEngine(), 'Smarty', array('tpl')); + + $this->engines_loaded = true; + return true; + } + + return false; + } + + /** + * Resets the layout manager to its default state. + */ + public function reset() + { + if (!is_null($this->current_engine)) { + $this->current_engine->reset(); + } + + // Unload the engines + $this->engines = array(); + $this->engines_loaded = false; + $this->file_extensions = array(); + + $this->current_engine = null; + $this->assigned_variables = array(); + $this->directory = Core::$appDirs[0]. DS . 'Layout'; + Logger::log('Reset the layout manager to its default state'); + } +} \ No newline at end of file diff --git a/src/FuzeWorks/LayoutComponent.php b/src/FuzeWorks/LayoutComponent.php new file mode 100644 index 0000000..c0df840 --- /dev/null +++ b/src/FuzeWorks/LayoutComponent.php @@ -0,0 +1,57 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class LayoutComponent implements iComponent +{ + + public function getClasses(): array + { + return [ + 'layouts' => '\FuzeWorks\Layout', + 'languages' => '\FuzeWorks\Languages' + ]; + } +} \ No newline at end of file diff --git a/src/FuzeWorks/TemplateEngine/JsonEngine.php b/src/FuzeWorks/TemplateEngine/JsonEngine.php new file mode 100644 index 0000000..426efff --- /dev/null +++ b/src/FuzeWorks/TemplateEngine/JsonEngine.php @@ -0,0 +1,114 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class JsonEngine implements TemplateEngine +{ + /** + * All the currently assigned variables. + * + * @var array + */ + protected $assigned_variables = array(); + + /** + * Whether the JSON data should be parsed or left as is. + * + * @var bool true if to be parsed + */ + protected static $string_return = true; + + /** + * Whether the JSON data should be parsed or left as is. + * + * @param true if to be parsed + */ + public static function returnAsString($boolean = true) + { + self::$string_return = $boolean; + } + + public function setDirectory($directory) + { + return true; + } + + public function get($file, $assigned_variables) + { + // First set all the variables + $this->assigned_variables = $assigned_variables; + + // First set up the JSON array + $json = array(); + + // Look up if a file is provided + if (!is_null($file)) { + // Retrieve a file + $string = file_get_contents($file); + $json = json_decode($string, true); + } + + // Then assign all variables + $json['data'] = $this->assigned_variables; + + // And return it + if (self::$string_return) { + return json_encode($json); + } + + return $json; + } + + public function getFileExtensions(): array + { + return array('json'); + } + + public function reset(): bool + { + $this->assigned_variables = array(); + self::$string_return = true; + + return true; + } +} \ No newline at end of file diff --git a/src/FuzeWorks/TemplateEngine/LatteEngine.php b/src/FuzeWorks/TemplateEngine/LatteEngine.php new file mode 100644 index 0000000..7e71bb8 --- /dev/null +++ b/src/FuzeWorks/TemplateEngine/LatteEngine.php @@ -0,0 +1,112 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class LatteEngine implements TemplateEngine +{ + + /** + * Instance of the Latte Engine + * + * @var Latte\Engine The Latte Engine to be used + */ + protected $latte; + + /** + * Set the directory of the current template. + * + * @param string $directory Template Directory + * @throws LayoutException + */ + public function setDirectory($directory) + { + if (class_exists('\Latte\Engine', true)) + { + // If possible, load Latte\Engine + $this->latte = new Latte; + $this->latte->setTempDirectory(realpath(Core::$tempDir . DS . 'Latte')); + } + else + { + throw new LayoutException("Could not load LatteEngine. Is it installed or Composer not loaded?", 1); + } + } + + /** + * Handle and retrieve a template file. + * + * @param string $file Template File + * @param array $assigned_variables All the variables used in this layout + * + * @return string Output of the template + */ + public function get($file, $assigned_variables) + { + return $this->latte->renderToString($file, $assigned_variables); + } + + /** + * Retrieve the file extensions that this template engine uses. + * + * @return array All used extensions. eg: array('php') + */ + public function getFileExtensions(): array + { + return array('latte'); + } + + /** + * Reset the template engine to its default state, so it can be used again clean. + */ + public function reset(): bool + { + // If possible, load Latte\Engine + $this->latte = null; + + return true; + } +} \ No newline at end of file diff --git a/src/FuzeWorks/TemplateEngine/PHPEngine.php b/src/FuzeWorks/TemplateEngine/PHPEngine.php new file mode 100644 index 0000000..e22b032 --- /dev/null +++ b/src/FuzeWorks/TemplateEngine/PHPEngine.php @@ -0,0 +1,94 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class PHPEngine implements TemplateEngine +{ + /** + * The currently used directory by the template. + * + * @var string + */ + protected $directory; + + /** + * All the currently assigned variables. + * + * @var array + */ + protected $assigned_variables = array(); + + public function setDirectory($directory) + { + $this->directory = $directory; + } + + public function get($file, $assigned_variables) + { + // First set all the variables + $this->assigned_variables = $assigned_variables; + $vars = $this->assigned_variables; + $directory = $this->directory; + + // Then run the file + if (!is_null($file)) { + ob_start(); + include $file; + + return ob_get_clean(); + } + } + + public function getFileExtensions(): array + { + return array('php'); + } + + public function reset(): bool + { + $this->directory = null; + $this->assigned_variables = array(); + + return true; + } +} \ No newline at end of file diff --git a/src/FuzeWorks/TemplateEngine/SmartyEngine.php b/src/FuzeWorks/TemplateEngine/SmartyEngine.php new file mode 100644 index 0000000..5165ece --- /dev/null +++ b/src/FuzeWorks/TemplateEngine/SmartyEngine.php @@ -0,0 +1,172 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +class SmartyEngine implements TemplateEngine +{ + /** + * The currently used directory by the template. + * + * @var string + */ + protected $directory; + + /** + * All the currently assigned variables. + * + * @var array + */ + protected $assigned_variables = array(); + + /** + * Instance of the Smarty Template Engine. + * + * @var \Smarty + */ + protected $smartyInstance; + + public function setDirectory($directory) + { + $this->directory = $directory; + } + + public function get($file, $assigned_variables) + { + // First set all the variables + $this->assigned_variables = $assigned_variables; + + // Load Smarty + $this->loadSmarty(); + + // Set the directory + $this->smartyInstance->setTemplateDir($this->directory); + + // Then assign all variables + foreach ($this->assigned_variables as $key => $value) { + $this->smartyInstance->assign($key, $value); + } + + // And finally, load the template + return $this->smartyInstance->fetch($file); + } + + /** + * Loads a Smarty instance if it is not already loaded. + */ + private function loadSmarty() + { + if (is_null($this->smartyInstance)) { + $this->smartyInstance = new Smarty(); + + // Then prepare all variables + $this->smartyInstance->setCompileDir(Core::$tempDir . DS . 'Smarty' . DS . 'Compile'); + $this->smartyInstance->setCacheDir(Core::$tempDir . DS . 'Smarty'); + } + } + + public function getFileExtensions(): array + { + return array('tpl'); + } + + public function reset(): bool + { + $this->smartyInstance = null; + $this->directory = null; + $this->assigned_variables = array(); + + return true; + } + + /** + * Retrieve a value from Smarty. + * + * @param string $name Variable name + * + * @return mixed Variable Value + * + * @throws \FuzeWorks\LayoutException on error + */ + public function __get($name) + { + // First load Smarty + $this->loadSmarty(); + + return $this->smartyInstance->$name; + } + + /** + * Set a variable in Smarty. + * + * @param string $name Variable Name + * @param mixed $value Variable Value + * + * @throws \FuzeWorks\LayoutException on error + */ + public function __set($name, $value) + { + // First load Smarty + $this->loadSmarty(); + + $this->smartyInstance->$name = $value; + } + + /** + * Calls a function in Smarty. + * + * @param string $name Name of the function to be called + * @param Paramaters $params Parameters to be used + * + * @return mixed Function output + */ + public function __call($name, $params) + { + // First load Smarty + $this->loadSmarty(); + + return call_user_func_array(array($this->smartyInstance, $name), $params); + } +} \ No newline at end of file diff --git a/src/FuzeWorks/TemplateEngine/TemplateEngine.php b/src/FuzeWorks/TemplateEngine/TemplateEngine.php new file mode 100644 index 0000000..8fe1033 --- /dev/null +++ b/src/FuzeWorks/TemplateEngine/TemplateEngine.php @@ -0,0 +1,75 @@ + + * @copyright Copyright (c) 2013 - 2018, TechFuze. (http://techfuze.net) + */ +interface TemplateEngine +{ + /** + * Set the directory of the current template. + * + * @param string $directory Template Directory + */ + public function setDirectory($directory); + + /** + * Handle and retrieve a template file. + * + * @param string $file Template File + * @param array $assigned_variables All the variables used in this layout + * + * @return string Output of the template + */ + public function get($file, $assigned_variables); + + /** + * Retrieve the file extensions that this template engine uses. + * + * @return array All used extensions. eg: array('php') + */ + public function getFileExtensions(): array; + + /** + * Reset the template engine to its default state, so it can be used again clean. + */ + public function reset(): bool; +} \ No newline at end of file diff --git a/test/autoload.php b/test/autoload.php new file mode 100644 index 0000000..173f2e2 --- /dev/null +++ b/test/autoload.php @@ -0,0 +1,63 @@ +addDirectory(dirname(__FILE__) . '/application'); +$configurator->setTempDirectory(dirname(__FILE__) . '/temp'); +$configurator->setLogDirectory(dirname(__FILE__) . '/temp'); + +// Other values +$configurator->setTimeZone('Europe/Amsterdam'); +$configurator->enableDebugMode(true); + +// Implement the Layout Component +$configurator->addComponent(new \FuzeWorks\LayoutComponent()); + +// Create container +$container = $configurator->createContainer(); +$container->init(); + +// And return the result +return $container; + diff --git a/test/layout/LayoutTest.php b/test/layout/LayoutTest.php new file mode 100644 index 0000000..a4b6823 --- /dev/null +++ b/test/layout/LayoutTest.php @@ -0,0 +1,485 @@ +factory = Factory::getInstance(); + $this->layout = Factory::getInstance()->layouts; + $this->layout->reset(); + } + + /** + * @covers \FuzeWorks\Layout::init + * @covers \FuzeWorks\LayoutComponent::getClasses + */ + public function testComponent() + { + // Load the component + $component = new FuzeWorks\LayoutComponent(); + + // Prepare container + $configurator = new \FuzeWorks\Configurator(); + $configurator->addComponent($component); + $configurator->addDirectory(dirname(__DIR__) . '/application'); + + // Create container + $container = $configurator->createContainer(); + + // Init container + $container = $container->init(); + $this->assertTrue(property_exists($container, 'layouts')); + $this->assertInstanceOf('FuzeWorks\Layout', $container->layouts); + } + + /** + * @covers \FuzeWorks\Layout::setFile + * @covers \FuzeWorks\Layout::getFile + * @covers \FuzeWorks\Layout::setDirectory + * @covers \FuzeWorks\Layout::getDirectory + */ + public function testFileAndDirectory() + { + // File test + $file = 'test.php'; + $this->layout->setFile($file); + $this->assertEquals($file, $this->layout->getFile()); + + // Directory test + $directory = 'test'.DS.'templates'.DS.'testFileAndDirectory'; + $this->layout->setDirectory($directory); + $this->assertEquals($directory, $this->layout->getDirectory()); + } + + /** + * @covers \FuzeWorks\Layout::getExtensionFromFile + */ + public function testGetFileExtensions() + { + // Test getting php files + $this->assertEquals('php', $this->layout->getExtensionFromFile('class.test.php')); + $this->assertEquals('php', $this->layout->getExtensionFromFile('class.test.org.php')); + $this->assertEquals('random', $this->layout->getExtensionFromFile('class.test.something.random')); + } + + /** + * @depends testGetFileExtensions + * @covers \FuzeWorks\Layout::setFileFromString + * @covers \FuzeWorks\Layout::getFileFromString + */ + public function testGetFilePath() + { + // Extensions to be used in this test + $extensions = array('php', 'json'); + + // Basic path + $this->layout->setFileFromString('test', 'test'.DS.'templates'.DS.'testGetFilePath', $extensions); + $this->assertEquals('test'.DS.'templates'.DS.'testGetFilePath'.DS.'layout.test.php', $this->layout->getFile()); + $this->assertEquals('test'.DS.'templates'.DS.'testGetFilePath'.DS, $this->layout->getDirectory()); + + // Alternate file extension + $this->layout->setFileFromString('JSON', 'test'.DS.'templates'.DS.'testGetFilePath', $extensions); + $this->assertEquals('test'.DS.'templates'.DS.'testGetFilePath'.DS.'layout.JSON.json', $this->layout->getFile()); + $this->assertEquals('test'.DS.'templates'.DS.'testGetFilePath'.DS, $this->layout->getDirectory()); + + // Complex deeper path + $this->layout->setFileFromString('Deeper/test', 'test'.DS.'templates'.DS.'testGetFilePath', $extensions); + $this->assertEquals('test'.DS.'templates'.DS.'testGetFilePath'.DS.'Deeper'.DS.'layout.test.php', $this->layout->getFile()); + $this->assertEquals('test'.DS.'templates'.DS.'testGetFilePath'.DS, $this->layout->getDirectory()); + } + + /** + * @depends testGetFilePath + * @expectedException FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::setFileFromString + * @covers \FuzeWorks\Layout::getFileFromString + */ + public function testMalformedPaths() + { + // Extensions to be used in this test + $extensions = array('php', 'json'); + + $this->layout->setFileFromString('test?\/<>', 'test|?/*<>', $extensions); + } + + /** + * @expectedException FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::setFileFromString + * @covers \FuzeWorks\Layout::getFileFromString + */ + public function testMissingDirectory() + { + // Directory that does not exist + $this->layout->setFileFromString('test', 'test'.DS.'templates'.DS.'doesNotExist'.DS, array('php')); + } + + /** + * @expectedException FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::setFileFromString + * @covers \FuzeWorks\Layout::getFileFromString + */ + public function testMissingFile() + { + $this->layout->setFileFromString('test', 'test'.DS.'templates'.DS.'testMissingFile'.DS, array('php')); + } + + /** + * @expectedException FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::setFileFromString + * @covers \FuzeWorks\Layout::getFileFromString + */ + public function testUnknownFileExtension() + { + $this->layout->setFileFromString('test', 'test'.DS.'templates'.DS.'testUnknownFileExtension'.DS, array('php')); + } + + /** + * @covers \FuzeWorks\Layout::get + */ + public function testLayoutGet() + { + // Directory of these tests + $directory = 'test'.DS.'templates'.DS.'testLayoutGet'.DS; + + $this->assertEquals('Retrieved Data', $this->layout->get('test', $directory)); + } + + /** + * @covers \FuzeWorks\Layout::get + */ + public function testLayoutGetRepeat() + { + $directory = 'test'.DS.'templates'.DS.'testLayoutGetRepeat'.DS; + $this->assertEquals('First Data', $this->layout->get('first', $directory)); + $this->assertEquals('Second Data', $this->layout->get('second', $directory)); + } + + /** + * @covers \FuzeWorks\Layout::get + * @covers \FuzeWorks\Event\LayoutLoadEvent::init + */ + public function testLayoutGetCancelledEvent() + { + $directory = 'test'.DS.'templates'.DS.'testLayoutGetCancelledEvent'; + Events::addListener(function($event){ + $event->setCancelled(true); + }, 'layoutLoadEvent', EventPriority::NORMAL); + $this->assertEquals('cancelled', $this->layout->get('test', $directory)); + } + + /** + * @expectedException FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::get + * @covers \FuzeWorks\Event\LayoutLoadEvent::init + */ + public function testLayoutGetEventWrongFile() + { + $directory = 'test'.DS.'templates'.DS.'testLayoutGetEventWrongFile'; + Events::addListener(function($event){ + $event->file = 'does_not_exist'; + }, 'layoutLoadEvent', EventPriority::NORMAL); + $this->layout->get('test', $directory); + } + + /** + * @covers \FuzeWorks\Layout::display + * @covers \FuzeWorks\Event\LayoutDisplayEvent::init + */ + public function testLayoutDisplayEventAndDisplay() + { + // Directory of these tests + $directory = 'test'.DS.'templates'.DS.'testLayoutGet'.DS; + Events::addListener(function($event){ + $this->assertEquals('Retrieved Data', $event->contents); + }, 'layoutDisplayEvent', EventPriority::NORMAL); + + ob_start(); + $this->layout->display('test', $directory); + $this->assertEquals('Retrieved Data', ob_get_contents()); + ob_end_clean(); + } + + /** + * @covers \FuzeWorks\Layout::reset + * @covers \FuzeWorks\Layout::setTitle + * @covers \FuzeWorks\Layout::getTitle + */ + public function testReset() + { + // First the the variables + $this->layout->setTitle('Test Title'); + $this->layout->setDirectory('test'.DS.'templates'.DS.'testLayoutGet'); + + // Test if they are actually set + $this->assertEquals('Test Title', $this->layout->getTitle()); + $this->assertEquals('test'.DS.'templates'.DS.'testLayoutGet', $this->layout->getDirectory()); + + // Reset the layout system + $this->layout->reset(); + + // Test for default values + $this->assertFalse($this->layout->getTitle()); + $this->assertTrue(strpos($this->layout->getDirectory(), 'application' . DS . 'Layout') !== false); + } + + /** + * @covers \FuzeWorks\Layout::getEngineFromExtension + */ + public function testGetEngineFromExtension() + { + $this->layout->loadTemplateEngines(); + + // Test all the default engines + $this->assertInstanceOf('FuzeWorks\TemplateEngine\PHPEngine', $this->layout->getEngineFromExtension('php')); + $this->assertInstanceOf('FuzeWorks\TemplateEngine\JsonEngine', $this->layout->getEngineFromExtension('json')); + $this->assertInstanceOf('FuzeWorks\TemplateEngine\SmartyEngine', $this->layout->getEngineFromExtension('tpl')); + } + + /** + * @depends testGetEngineFromExtension + * @expectedException FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::getEngineFromExtension + */ + public function testGetEngineFromExtensionFail() + { + $this->layout->getEngineFromExtension('faulty'); + } + + /** + * @covers \FuzeWorks\Layout::loadTemplateEngines + */ + public function testLoadTemplateEngines() + { + // Load first try + $this->assertTrue($this->layout->loadTemplateEngines()); + + // Try second time + $this->assertFalse($this->layout->loadTemplateEngines()); + + // Reset + $this->layout->reset(); + $this->assertTrue($this->layout->loadTemplateEngines()); + } + + /** + * @covers \FuzeWorks\Layout::loadTemplateEngines + * @expectedException \FuzeWorks\Exception\LayoutException + */ + public function testLoadLoadEngineEvent() + { + Events::addListener(function($event){ + $this->assertInstanceOf('\FuzeWorks\Event\NotifierEvent', $event); + throw new \FuzeWorks\Exception\EventException('Forcing failure in loadTemplateEngines()'); + }, 'layoutLoadEngineEvent', EventPriority::NORMAL); + + $this->layout->loadTemplateEngines(); + } + + /** + * @depends testGetEngineFromExtension + * @covers \FuzeWorks\Layout::registerEngine + */ + public function testCustomEngine() + { + // Create the engine + $mock = $this->getMockBuilder('FuzeWorks\TemplateEngine\TemplateEngine')->getMock(); + + // Add the methods + $mock->method('get')->willReturn('output'); + + // And listen for usage + $mock->expects($this->once())->method('get')->with('test'.DS.'templates'.DS.'testCustomEngine'.DS.'layout.test.test'); + + // Register the engine + $this->layout->registerEngine($mock, 'Custom', array('test')); + + // And run the engine + $this->assertEquals('output', $this->layout->get('test', 'test'.DS.'templates'.DS.'testCustomEngine')); + } + + + /** + * @depends testCustomEngine + * @expectedException \FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::registerEngine + */ + public function testExistingCustomEngine() + { + // Create mock + $mock = $this->getMockBuilder('FuzeWorks\TemplateEngine\TemplateEngine')->getMock(); + $mock->method('get')->willReturn('output'); + + // And register + $this->assertTrue($this->layout->registerEngine($mock, 'Custom', ['test'])); + + // And re-register + $this->layout->registerEngine($mock, 'Custom', ['othertest']); + } + + /** + * @depends testCustomEngine + * @expectedException \FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::registerEngine + */ + public function testCustomEngineWithExistingExtensions() + { + // Create mock + $mock = $this->getMockBuilder('FuzeWorks\TemplateEngine\TemplateEngine')->getMock(); + $mock->method('get')->willReturn('output'); + + // Register initial + $this->assertTrue($this->layout->registerEngine($mock, 'Custom', ['test'])); + + // Register failing + $this->layout->registerEngine($mock, 'other', ['test']); + } + + /** + * @depends testCustomEngine + * @covers \FuzeWorks\Layout::setEngine + * @covers \FuzeWorks\Layout::getEngine + */ + public function testSetEngine() + { + // Create mocks + $mock = $this->getMockBuilder('FuzeWorks\TemplateEngine\TemplateEngine')->getMock(); + $mock2 = $this->getMockBuilder('FuzeWorks\TemplateEngine\TemplateEngine')->getMock(); + $mock->method('get')->willReturn('output'); + $mock2->method('get')->willReturn('output2'); + + // Register custom engine + $this->assertTrue($this->layout->registerEngine($mock, 'custom', ['test'])); + $this->assertTrue($this->layout->registerEngine($mock2, 'custom2', ['test2'])); + + // Test getEngine + $this->assertInstanceOf(get_class($mock), $this->layout->getEngine('custom')); + $this->assertInstanceOf(get_class($mock2), $this->layout->getEngine('custom2')); + + // Test setEngine1 + $this->assertTrue($this->layout->setEngine('custom')); + $this->assertTrue($this->layout->setEngine('custom2')); + } + + /** + * @depends testSetEngine + * @expectedException \FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::setEngine + */ + public function testSetInvalidEngine() + { + $this->layout->setEngine('invalid'); + } + + /** + * @depends testSetEngine + * @expectedException \FuzeWorks\Exception\LayoutException + * @covers \FuzeWorks\Layout::getEngine + */ + public function testGetInvalidEngine() + { + $this->layout->getEngine('invalid'); + } + + /** + * @covers \FuzeWorks\Layout::registerEngine + */ + public function testEnginesLoadLayout() + { + // Directory of these tests + $directory = 'test'.DS.'templates'.DS.'testEngines'.DS; + + // First the PHP Engine + $this->assertEquals('PHP Template Check', $this->layout->get('php', $directory)); + $this->layout->reset(); + + // Then the JSON Engine + $this->assertEquals('JSON Template Check', json_decode($this->layout->get('json', $directory), true)[0]); + $this->layout->reset(); + + // And the Smarty Engine + $this->assertEquals('Smarty Template Check', $this->layout->get('smarty', $directory)); + } + + /** + * @covers \FuzeWorks\Layout::assign + */ + public function testEngineVariables() + { + // Directory of these tests + $directory = 'test'.DS.'templates'.DS.'testEngineVariables'.DS; + + // First the PHP Engine + $this->layout->assign('key', 'value'); + $this->assertEquals('value', $this->layout->get('php', $directory)); + $this->layout->reset(); + + // Then the JSON Engine + $this->layout->assign('key', 'value'); + $this->assertEquals('value', json_decode($this->layout->get('json', $directory), true)['data']['key']); + $this->layout->reset(); + + // And the Smarty Engine + $this->layout->assign('key', 'value'); + $this->assertEquals('value', $this->layout->get('smarty', $directory)); + } +} + +class MockEngine { + +} diff --git a/test/layout/LayoutTestAbstract.php b/test/layout/LayoutTestAbstract.php new file mode 100644 index 0000000..5bced0a --- /dev/null +++ b/test/layout/LayoutTestAbstract.php @@ -0,0 +1,68 @@ +config->discardConfigFiles(); + + // Re-enable events, in case they have been disabled + Events::enable(); + + // Reset the HTTP status code + Core::$http_status_code = 200; + } +} diff --git a/test/phpunit.xml b/test/phpunit.xml new file mode 100644 index 0000000..c758298 --- /dev/null +++ b/test/phpunit.xml @@ -0,0 +1,34 @@ + + + + + ./ + + + + + + + + + + + + + ../ + + ../vendor/ + ../tests/ + + + + \ No newline at end of file diff --git a/test/temp/placeholder b/test/temp/placeholder new file mode 100644 index 0000000..e69de29 diff --git a/test/templates/testCustomEngine/layout.test.test b/test/templates/testCustomEngine/layout.test.test new file mode 100644 index 0000000..e69de29 diff --git a/test/templates/testCustomEngine/layout.test.test2 b/test/templates/testCustomEngine/layout.test.test2 new file mode 100644 index 0000000..e69de29 diff --git a/test/templates/testEngineVariables/layout.json.json b/test/templates/testEngineVariables/layout.json.json new file mode 100644 index 0000000..e69de29 diff --git a/test/templates/testEngineVariables/layout.php.php b/test/templates/testEngineVariables/layout.php.php new file mode 100644 index 0000000..73714f0 --- /dev/null +++ b/test/templates/testEngineVariables/layout.php.php @@ -0,0 +1,2 @@ +