From 809a652bb80a187aa255e636688ffff72fb2efe0 Mon Sep 17 00:00:00 2001 From: Guy Sartorelli Date: Fri, 1 Nov 2024 14:14:37 +1300 Subject: [PATCH 1/2] API Update API to suit its status as its own module --- .editorconfig | 27 +++++++++++ .gitattributes | 8 ++++ .github/workflows/ci.yml | 10 ++++ .gitignore | 3 ++ composer.json | 39 +++++++++++++++ phpcs.xml.dist | 44 +++++++++++++++++ phpstan.neon.dist | 3 ++ phpunit.xml.dist | 8 ++++ ...orSupport.php => BasicIteratorSupport.php} | 4 +- src/Exception/MissingTemplateException.php | 12 ----- .../SSTemplateParseException.php | 2 +- src/SSTemplateEngine.php | 18 ++++--- src/SSTemplateParser.peg | 20 ++++---- src/SSTemplateParser.php | 15 +++--- src/{SSViewer_Scope.php => ScopeManager.php} | 47 ++++++++++--------- src/TemplateIteratorProvider.php | 4 +- src/TemplateParser.php | 2 +- tests/php/SSTemplateEngineCacheBlockTest.php | 6 +-- .../TestModel.php | 2 +- .../VersionedModel.php | 2 +- .../php/SSTemplateEngineFindTemplateTest.php | 4 +- tests/php/SSTemplateEngineTest.php | 10 ++-- .../SSTemplateEngineTest/CacheTestData.php | 2 +- .../SSTemplateEngineTest/LevelTestData.php | 2 +- .../php/SSTemplateEngineTest/TestFixture.php | 6 +-- .../TestGlobalProvider.php | 2 +- .../SSTemplateEngineTest/TestModelData.php | 2 +- tests/php/SSTemplateEngineTest/TestObject.php | 2 +- 28 files changed, 218 insertions(+), 88 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 composer.json create mode 100644 phpcs.xml.dist create mode 100644 phpstan.neon.dist create mode 100644 phpunit.xml.dist rename src/{SSViewer_BasicIteratorSupport.php => BasicIteratorSupport.php} (98%) delete mode 100644 src/Exception/MissingTemplateException.php rename src/{ => Exception}/SSTemplateParseException.php (94%) rename src/{SSViewer_Scope.php => ScopeManager.php} (92%) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..178b5ae --- /dev/null +++ b/.editorconfig @@ -0,0 +1,27 @@ +# For more information about the properties used in +# this file, please see the EditorConfig documentation: +# http://editorconfig.org/ + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,js,json,css,scss,eslintrc,feature}] +indent_size = 2 +indent_style = space + +[composer.json] +indent_size = 4 + +# Don't perform any clean-up on thirdparty files + +[thirdparty/**] +trim_trailing_whitespace = false +insert_final_newline = false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..549b9c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +/tests/php export-ignore +/.tx export-ignore +/.gitattributes export-ignore +/.gitignore export-ignore +/.github export-ignore +/*.dist export-ignore +/phpcs.xml.dist export-ignore +/.editorconfig export-ignore diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2004851 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,10 @@ +name: CI + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + ci: + uses: silverstripe/gha-ci/.github/workflows/ci.yml@v1 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..52e8214 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/vendor/ +composer.lock +silverstripe-cache/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..eace2cf --- /dev/null +++ b/composer.json @@ -0,0 +1,39 @@ +{ + "name": "silverstripe/template-engine", + "description": "Template engine for rendering templates in Silverstripe CMS projects", + "type": "silverstripe-vendormodule", + "license": "BSD-3-Clause", + "authors": [ + { + "name": "Silverstripe", + "homepage": "https://silverstripe.com" + }, + { + "name": "The Silverstripe Community", + "homepage": "https://silverstripe.org" + } + ], + "require": { + "php": "^8.3", + "silverstripe/framework": "^6" + }, + "require-dev": { + "silverstripe/recipe-testing": "^4", + "silverstripe/standards": "^1", + "squizlabs/php_codesniffer": "^3", + "phpstan/extension-installer": "^1.3" + }, + "autoload": { + "psr-4": { + "SilverStripe\\TemplateEngine\\": "src/", + "SilverStripe\\TemplateEngine\\Tests\\": "tests/php/" + } + }, + "minimum-stability": "dev", + "prefer-stable": true, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } + } +} diff --git a/phpcs.xml.dist b/phpcs.xml.dist new file mode 100644 index 0000000..b01b1c6 --- /dev/null +++ b/phpcs.xml.dist @@ -0,0 +1,44 @@ + + + CodeSniffer ruleset for SilverStripe coding conventions. + + src + tests + + + + + + + + + + + + + + + + + + + --> + + + + + + */SSTemplateParser.php$ + + diff --git a/phpstan.neon.dist b/phpstan.neon.dist new file mode 100644 index 0000000..beb9de3 --- /dev/null +++ b/phpstan.neon.dist @@ -0,0 +1,3 @@ +parameters: + paths: + - src diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..a313a56 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,8 @@ + + + + + tests/php + + + diff --git a/src/SSViewer_BasicIteratorSupport.php b/src/BasicIteratorSupport.php similarity index 98% rename from src/SSViewer_BasicIteratorSupport.php rename to src/BasicIteratorSupport.php index 99d0210..c04a25a 100644 --- a/src/SSViewer_BasicIteratorSupport.php +++ b/src/BasicIteratorSupport.php @@ -1,12 +1,12 @@ render($data, $overlay, $scope); @@ -167,7 +171,7 @@ public function renderString(string $template, ViewLayerData $model, array $over return $output; } - public function render(ViewLayerData $model, array $overlay = [], ?SSViewer_Scope $scope = null): string + public function render(ViewLayerData $model, array $overlay = [], ?ScopeManager $scope = null): string { SSTemplateEngine::$topLevel[] = $model; $template = $this->chosen; @@ -221,7 +225,7 @@ public function render(ViewLayerData $model, array $overlay = [], ?SSViewer_Scop // Select the right template and render if the template exists $subtemplateViewer->setTemplate($sub); // If there's no template for that underlay, just don't render anything. - // This mirrors how SSViewer_Scope handles null values. + // This mirrors how ScopeManager handles null values. if (!$subtemplateViewer->chosen) { return null; } @@ -293,14 +297,14 @@ public function getPartialCacheStore(): CacheInterface * @param ViewLayerData $model The model to use as the root scope for the template * @param array $overlay Any variables to layer on top of the scope * @param array $underlay Any variables to layer underneath the scope - * @param SSViewer_Scope|null $inheritedScope The current scope of a parent template including a sub-template + * @param ScopeManager|null $inheritedScope The current scope of a parent template including a sub-template */ protected function includeGeneratedTemplate( string $cacheFile, ViewLayerData $model, array $overlay, array $underlay, - ?SSViewer_Scope $inheritedScope = null + ?ScopeManager $inheritedScope = null ): string { if (isset($_GET['showtemplate']) && $_GET['showtemplate'] && Permission::check('ADMIN')) { $lines = file($cacheFile ?? ''); @@ -313,7 +317,7 @@ protected function includeGeneratedTemplate( } $cache = $this->getPartialCacheStore(); - $scope = new SSViewer_Scope($model, $overlay, $underlay, $inheritedScope); + $scope = new ScopeManager($model, $overlay, $underlay, $inheritedScope); $val = ''; // Placeholder for values exposed to $cacheFile diff --git a/src/SSTemplateParser.peg b/src/SSTemplateParser.peg index f53d64b..8ac1059 100644 --- a/src/SSTemplateParser.peg +++ b/src/SSTemplateParser.peg @@ -9,29 +9,25 @@ parser. It gets run through the php-peg parser compiler to have those comments turned into code that match parts of the template language, producing the executable version SSTemplateParser.php -To recompile after changing this file, run this from the 'framework/View' directory via command line (in most cases -this is: framework/src/View): +To recompile after changing this file, run this from the 'src' directory via command line: - php ../../thirdparty/php-peg/cli.php SSTemplateParser.peg > SSTemplateParser.php + php ../thirdparty/php-peg/cli.php SSTemplateParser.peg > SSTemplateParser.php See the php-peg docs for more information on the parser format, and how to convert this file into SSTemplateParser.php This comment will not appear in the output */ -namespace SilverStripe\View; +namespace SilverStripe\TemplateEngine; use SilverStripe\Core\Injector\Injector; use Parser; use InvalidArgumentException; +use SilverStripe\TemplateEngine\Exception\SSTemplateParseException; -// We want this to work when run by hand too -if (defined('THIRDPARTY_PATH')) { - require_once(THIRDPARTY_PATH . '/php-peg/Parser.php'); -} else { - $base = dirname(__FILE__); - require_once($base.'/../thirdparty/php-peg/Parser.php'); -} +// Make sure to include the base parser code +$base = dirname(__FILE__); +require_once($base.'/../thirdparty/php-peg/Parser.php'); /** * This is the parser for the SilverStripe template language. It gets called on a string and uses a php-peg parser @@ -936,7 +932,7 @@ class SSTemplateParser extends Parser implements TemplateParser $arguments = $res['arguments']; // Note: 'type' here is important to disable subTemplates in SSTemplateEngine::getSubtemplateFor() - $res['php'] = '$val .= \\SilverStripe\\View\\SSTemplateEngine::execute_template([["type" => "Includes", '.$template.'], '.$template.'], $scope->getCurrentItem(), [' . + $res['php'] = '$val .= \\SilverStripe\\TemplateEngine\\SSTemplateEngine::execute_template([["type" => "Includes", '.$template.'], '.$template.'], $scope->getCurrentItem(), [' . implode(',', $arguments)."], \$scope, true);\n"; if ($this->includeDebuggingComments) { // Add include filename comments on dev sites diff --git a/src/SSTemplateParser.php b/src/SSTemplateParser.php index d391af0..27eb4b6 100644 --- a/src/SSTemplateParser.php +++ b/src/SSTemplateParser.php @@ -7,19 +7,16 @@ -namespace SilverStripe\View; +namespace SilverStripe\TemplateEngine; use SilverStripe\Core\Injector\Injector; use Parser; use InvalidArgumentException; +use SilverStripe\TemplateEngine\Exception\SSTemplateParseException; -// We want this to work when run by hand too -if (defined('THIRDPARTY_PATH')) { - require_once(THIRDPARTY_PATH . '/php-peg/Parser.php'); -} else { - $base = dirname(__FILE__); - require_once($base.'/../thirdparty/php-peg/Parser.php'); -} +// Make sure to include the base parser code +$base = dirname(__FILE__); +require_once($base.'/../thirdparty/php-peg/Parser.php'); /** * This is the parser for the SilverStripe template language. It gets called on a string and uses a php-peg parser @@ -3894,7 +3891,7 @@ function Include__finalise(&$res) $arguments = $res['arguments']; // Note: 'type' here is important to disable subTemplates in SSTemplateEngine::getSubtemplateFor() - $res['php'] = '$val .= \\SilverStripe\\View\\SSTemplateEngine::execute_template([["type" => "Includes", '.$template.'], '.$template.'], $scope->getCurrentItem(), [' . + $res['php'] = '$val .= \\SilverStripe\\TemplateEngine\\SSTemplateEngine::execute_template([["type" => "Includes", '.$template.'], '.$template.'], $scope->getCurrentItem(), [' . implode(',', $arguments)."], \$scope, true);\n"; if ($this->includeDebuggingComments) { // Add include filename comments on dev sites diff --git a/src/SSViewer_Scope.php b/src/ScopeManager.php similarity index 92% rename from src/SSViewer_Scope.php rename to src/ScopeManager.php index 5f7836c..dc655be 100644 --- a/src/SSViewer_Scope.php +++ b/src/ScopeManager.php @@ -1,12 +1,15 @@ item = $item; @@ -150,7 +153,7 @@ public function getCurrentItem(): ?ViewLayerData /** * Called at the start of every lookup chain by SSTemplateParser to indicate a new lookup from local scope * - * @return SSViewer_Scope + * @return ScopeManager */ public function locally() { @@ -218,8 +221,8 @@ public function scopeToIntermediateValue(string $name, array $arguments): static if ($overlayIndex !== false) { $itemStack = $this->getItemStack(); - if (!$this->overlay && isset($itemStack[$overlayIndex][SSViewer_Scope::ITEM_OVERLAY])) { - $this->overlay = $itemStack[$overlayIndex][SSViewer_Scope::ITEM_OVERLAY]; + if (!$this->overlay && isset($itemStack[$overlayIndex][ScopeManager::ITEM_OVERLAY])) { + $this->overlay = $itemStack[$overlayIndex][ScopeManager::ITEM_OVERLAY]; } } @@ -251,27 +254,27 @@ public function self(): ?ViewLayerData * Store the current overlay (as it doesn't directly apply to the new scope * that's being pushed). We want to store the overlay against the next item * "up" in the stack (hence upIndex), rather than the current item, because - * SSViewer_Scope::obj() has already been called and pushed the new item to + * ScopeManager::obj() has already been called and pushed the new item to * the stack by this point */ public function pushScope(): static { $newLocalIndex = count($this->itemStack ?? []) - 1; - $this->popIndex = $this->itemStack[$newLocalIndex][SSViewer_Scope::POP_INDEX] = $this->localIndex; + $this->popIndex = $this->itemStack[$newLocalIndex][ScopeManager::POP_INDEX] = $this->localIndex; $this->localIndex = $newLocalIndex; // $Up now becomes the parent scope - the parent of the current <% loop %> or <% with %> - $this->upIndex = $this->itemStack[$newLocalIndex][SSViewer_Scope::UP_INDEX] = $this->popIndex; + $this->upIndex = $this->itemStack[$newLocalIndex][ScopeManager::UP_INDEX] = $this->popIndex; // We normally keep any previous itemIterator around, so local $Up calls reference the right element. But // once we enter a new global scope, we need to make sure we use a new one - $this->itemIterator = $this->itemStack[$newLocalIndex][SSViewer_Scope::ITEM_ITERATOR] = null; + $this->itemIterator = $this->itemStack[$newLocalIndex][ScopeManager::ITEM_ITERATOR] = null; $upIndex = $this->getUpIndex() ?: 0; $itemStack = $this->getItemStack(); - $itemStack[$upIndex][SSViewer_Scope::ITEM_OVERLAY] = $this->overlay; + $itemStack[$upIndex][ScopeManager::ITEM_OVERLAY] = $this->overlay; $this->setItemStack($itemStack); // Remove the overlay when we're changing to a new scope, as values in @@ -297,7 +300,7 @@ public function popScope(): static if ($upIndex !== null) { $itemStack = $this->getItemStack(); - $this->overlay = $itemStack[$upIndex][SSViewer_Scope::ITEM_OVERLAY]; + $this->overlay = $itemStack[$upIndex][ScopeManager::ITEM_OVERLAY]; } $this->localIndex = $this->popIndex; @@ -331,8 +334,8 @@ public function next(): bool // which causes some iterators to no longer be iterable for some reason $this->itemIteratorTotal = $this->item->getIteratorCount(); - $this->itemStack[$this->localIndex][SSViewer_Scope::ITEM_ITERATOR] = $this->itemIterator; - $this->itemStack[$this->localIndex][SSViewer_Scope::ITEM_ITERATOR_TOTAL] = $this->itemIteratorTotal; + $this->itemStack[$this->localIndex][ScopeManager::ITEM_ITERATOR] = $this->itemIterator; + $this->itemStack[$this->localIndex][ScopeManager::ITEM_ITERATOR_TOTAL] = $this->itemIteratorTotal; } else { $this->itemIterator->next(); } @@ -487,11 +490,11 @@ protected function processTemplateOverride($property, $overrides) */ protected function cacheGlobalProperties() { - if (SSViewer_Scope::$globalProperties !== null) { + if (ScopeManager::$globalProperties !== null) { return; } - SSViewer_Scope::$globalProperties = SSViewer::getMethodsFromProvider( + ScopeManager::$globalProperties = SSViewer::getMethodsFromProvider( TemplateGlobalProvider::class, 'get_template_global_variables' ); @@ -502,11 +505,11 @@ protected function cacheGlobalProperties() */ protected function cacheIteratorProperties() { - if (SSViewer_Scope::$iteratorProperties !== null) { + if (ScopeManager::$iteratorProperties !== null) { return; } - SSViewer_Scope::$iteratorProperties = SSViewer::getMethodsFromProvider( + ScopeManager::$iteratorProperties = SSViewer::getMethodsFromProvider( TemplateIteratorProvider::class, 'get_template_iterator_variables', true // Call non-statically @@ -551,8 +554,8 @@ protected function getUnderlay(string $property, array $args, bool $getRaw = fal } // Then for iterator-specific overrides - if (array_key_exists($property, SSViewer_Scope::$iteratorProperties)) { - $source = SSViewer_Scope::$iteratorProperties[$property]; + if (array_key_exists($property, ScopeManager::$iteratorProperties)) { + $source = ScopeManager::$iteratorProperties[$property]; /** @var TemplateIteratorProvider $implementor */ $implementor = $source['implementor']; if ($this->itemIterator) { @@ -571,9 +574,9 @@ protected function getUnderlay(string $property, array $args, bool $getRaw = fal } // And finally for global overrides - if (array_key_exists($property, SSViewer_Scope::$globalProperties)) { + if (array_key_exists($property, ScopeManager::$globalProperties)) { return $this->getInjectedValue( - SSViewer_Scope::$globalProperties[$property], + ScopeManager::$globalProperties[$property], $property, $args, $getRaw diff --git a/src/TemplateIteratorProvider.php b/src/TemplateIteratorProvider.php index a3169af..5367dcf 100644 --- a/src/TemplateIteratorProvider.php +++ b/src/TemplateIteratorProvider.php @@ -1,12 +1,12 @@ getStaticPropertyValue('globalProperties'); if (array_key_exists($name, $globalProperties)) { return false; diff --git a/tests/php/SSTemplateEngineTest/TestGlobalProvider.php b/tests/php/SSTemplateEngineTest/TestGlobalProvider.php index 6896f43..8932a16 100644 --- a/tests/php/SSTemplateEngineTest/TestGlobalProvider.php +++ b/tests/php/SSTemplateEngineTest/TestGlobalProvider.php @@ -1,6 +1,6 @@ Date: Tue, 5 Nov 2024 15:46:28 +1300 Subject: [PATCH 2/2] ENH Resolve PHP linting issues --- phpcs.xml.dist | 22 --- src/Exception/SSTemplateParseException.php | 1 - src/SSTemplateEngine.php | 18 +- src/ScopeManager.php | 17 +- src/TemplateIteratorProvider.php | 1 - src/TemplateParser.php | 7 +- tests/php/SSTemplateEngineCacheBlockTest.php | 160 +++++++++--------- tests/php/SSTemplateEngineTest.php | 63 +++++-- .../SSTemplateEngineTest/CacheTestData.php | 1 - .../TestGlobalProvider.php | 1 - .../SSTemplateEngineTest/TestModelData.php | 1 - 11 files changed, 152 insertions(+), 140 deletions(-) diff --git a/phpcs.xml.dist b/phpcs.xml.dist index b01b1c6..25f7601 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -13,31 +13,9 @@ - - - - - - - - - - --> - - */SSTemplateParser.php$ diff --git a/src/Exception/SSTemplateParseException.php b/src/Exception/SSTemplateParseException.php index 955597c..bfe485d 100644 --- a/src/Exception/SSTemplateParseException.php +++ b/src/Exception/SSTemplateParseException.php @@ -11,7 +11,6 @@ */ class SSTemplateParseException extends Exception { - /** * SSTemplateParseException constructor. * @param string $message diff --git a/src/SSTemplateEngine.php b/src/SSTemplateEngine.php index 9a0e1d9..0a3b2fe 100644 --- a/src/SSTemplateEngine.php +++ b/src/SSTemplateEngine.php @@ -94,8 +94,12 @@ public function __construct(string|array $templateCandidates = []) * template as properties. These override properties and methods with the same name from $data and from global * template providers. */ - public static function execute_template(array|string $template, ViewLayerData $data, array $overlay = [], ?ScopeManager $scope = null): string - { + public static function execute_template( + array|string $template, + ViewLayerData $data, + array $overlay = [], + ?ScopeManager $scope = null + ): string { $engine = static::create($template); return $engine->render($data, $overlay, $scope); } @@ -148,8 +152,12 @@ public function hasTemplate(array|string $templateCandidates): bool return (bool) $this->findTemplate($templateCandidates); } - public function renderString(string $template, ViewLayerData $model, array $overlay = [], bool $cache = true): string - { + public function renderString( + string $template, + ViewLayerData $model, + array $overlay = [], + bool $cache = true + ): string { $hash = sha1($template); $cacheFile = TEMP_PATH . DIRECTORY_SEPARATOR . ".cache.$hash"; @@ -311,7 +319,7 @@ protected function includeGeneratedTemplate( echo "

Template: $cacheFile

"; echo '
';
             foreach ($lines as $num => $line) {
-                echo str_pad($num+1, 5) . htmlentities($line, ENT_COMPAT, 'UTF-8');
+                echo str_pad($num + 1, 5) . htmlentities($line, ENT_COMPAT, 'UTF-8');
             }
             echo '
'; } diff --git a/src/ScopeManager.php b/src/ScopeManager.php index dc655be..4d72cdb 100644 --- a/src/ScopeManager.php +++ b/src/ScopeManager.php @@ -36,13 +36,13 @@ */ class ScopeManager { - const ITEM = 0; - const ITEM_ITERATOR = 1; - const ITEM_ITERATOR_TOTAL = 2; - const POP_INDEX = 3; - const UP_INDEX = 4; - const CURRENT_INDEX = 5; - const ITEM_OVERLAY = 6; + public const ITEM = 0; + public const ITEM_ITERATOR = 1; + public const ITEM_ITERATOR_TOTAL = 2; + public const POP_INDEX = 3; + public const UP_INDEX = 4; + public const CURRENT_INDEX = 5; + public const ITEM_OVERLAY = 6; /** * The stack of previous items ("scopes") - an indexed array of: item, item iterator, item iterator total, @@ -608,7 +608,8 @@ protected function getInjectedValue( return null; } - // TemplateGlobalProviders can provide an explicit service to cast to which works outside of the regular cast flow + // TemplateGlobalProviders can provide an explicit service to cast + // to which works outside of the regular cast flow if (!$getRaw && isset($source['casting'])) { $castObject = Injector::inst()->create($source['casting'], $property); if (!ClassInfo::hasMethod($castObject, 'setValue')) { diff --git a/src/TemplateIteratorProvider.php b/src/TemplateIteratorProvider.php index 5367dcf..926c095 100644 --- a/src/TemplateIteratorProvider.php +++ b/src/TemplateIteratorProvider.php @@ -10,7 +10,6 @@ */ interface TemplateIteratorProvider { - /** * Called by SSViewer to get a list of iterator variables to expose to the template, the instance method to call * on an instance of this class to get the value for those variables, and the class to use for casting the returned diff --git a/src/TemplateParser.php b/src/TemplateParser.php index 515727b..6fa9de0 100644 --- a/src/TemplateParser.php +++ b/src/TemplateParser.php @@ -7,7 +7,6 @@ */ interface TemplateParser { - /** * Compiles some passed template source code into the php code that will execute as per the template source. * @@ -16,5 +15,9 @@ interface TemplateParser * @param bool $includeDebuggingComments True is debugging comments should be included in the output * @return string The php that, when executed (via include or exec) will behave as per the template source */ - public function compileString(string $string, string $templateName = "", bool $includeDebuggingComments = false): string; + public function compileString( + string $string, + string $templateName = "", + bool $includeDebuggingComments = false + ): string; } diff --git a/tests/php/SSTemplateEngineCacheBlockTest.php b/tests/php/SSTemplateEngineCacheBlockTest.php index 71e8c56..511d4b8 100644 --- a/tests/php/SSTemplateEngineCacheBlockTest.php +++ b/tests/php/SSTemplateEngineCacheBlockTest.php @@ -40,7 +40,7 @@ public static function getExtraDataObjects() */ protected $data = null; - protected function _reset($cacheOn = true) + protected function reset($cacheOn = true) { $this->data = new SSTemplateEngineCacheBlockTest\TestModel(); @@ -56,7 +56,7 @@ protected function _reset($cacheOn = true) Injector::inst()->get(CacheInterface::class . '.cacheblock')->clear(); } - protected function _runtemplate($template, $data = null) + protected function runtemplate($template, $data = null) { if ($data === null) { $data = $this->data; @@ -75,32 +75,32 @@ public function testParsing() // ** Trivial checks ** // Make sure an empty cached block parses - $this->_reset(); - $this->assertEquals('', $this->_runtemplate('<% cached %><% end_cached %>')); + $this->reset(); + $this->assertEquals('', $this->runtemplate('<% cached %><% end_cached %>')); // Make sure an empty cacheblock block parses - $this->_reset(); - $this->assertEquals('', $this->_runtemplate('<% cacheblock %><% end_cacheblock %>')); + $this->reset(); + $this->assertEquals('', $this->runtemplate('<% cacheblock %><% end_cacheblock %>')); // Make sure an empty uncached block parses - $this->_reset(); - $this->assertEquals('', $this->_runtemplate('<% uncached %><% end_uncached %>')); + $this->reset(); + $this->assertEquals('', $this->runtemplate('<% uncached %><% end_uncached %>')); // ** Argument checks ** // Make sure a simple cacheblock parses - $this->_reset(); - $this->assertEquals('Yay', $this->_runtemplate('<% cached %>Yay<% end_cached %>')); + $this->reset(); + $this->assertEquals('Yay', $this->runtemplate('<% cached %>Yay<% end_cached %>')); // Make sure a moderately complicated cacheblock parses - $this->_reset(); - $this->assertEquals('Yay', $this->_runtemplate('<% cached \'block\', Foo, "jumping" %>Yay<% end_cached %>')); + $this->reset(); + $this->assertEquals('Yay', $this->runtemplate('<% cached \'block\', Foo, "jumping" %>Yay<% end_cached %>')); // Make sure a complicated cacheblock parses - $this->_reset(); + $this->reset(); $this->assertEquals( 'Yay', - $this->_runtemplate( + $this->runtemplate( '<% cached \'block\', Foo, Test.Test(4).Test(jumping).Foo %>Yay<% end_cached %>' ) ); @@ -108,18 +108,18 @@ public function testParsing() // ** Conditional Checks ** // Make sure a cacheblock with a simple conditional parses - $this->_reset(); - $this->assertEquals('Yay', $this->_runtemplate('<% cached if true %>Yay<% end_cached %>')); + $this->reset(); + $this->assertEquals('Yay', $this->runtemplate('<% cached if true %>Yay<% end_cached %>')); // Make sure a cacheblock with a complex conditional parses - $this->_reset(); - $this->assertEquals('Yay', $this->_runtemplate('<% cached if Test.Test(yank).Foo %>Yay<% end_cached %>')); + $this->reset(); + $this->assertEquals('Yay', $this->runtemplate('<% cached if Test.Test(yank).Foo %>Yay<% end_cached %>')); // Make sure a cacheblock with a complex conditional and arguments parses - $this->_reset(); + $this->reset(); $this->assertEquals( 'Yay', - $this->_runtemplate( + $this->runtemplate( '<% cached Foo, Test.Test(4).Test(jumping).Foo if Test.Test(yank).Foo %>Yay<% end_cached %>' ) ); @@ -131,16 +131,16 @@ public function testParsing() public function testBlocksCache() { // First, run twice without caching, to prove we get two different values - $this->_reset(false); + $this->reset(false); - $this->assertEquals('1', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 1])); - $this->assertEquals('2', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 2])); + $this->assertEquals('1', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 1])); + $this->assertEquals('2', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 2])); // Then twice with caching, should get same result each time - $this->_reset(true); + $this->reset(true); - $this->assertEquals('1', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 1])); - $this->assertEquals('1', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 2])); + $this->assertEquals('1', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 1])); + $this->assertEquals('1', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 2])); } /** @@ -149,20 +149,20 @@ public function testBlocksCache() public function testBlocksInvalidateOnFlush() { Director::test('/?flush=1'); - $this->_reset(true); + $this->reset(true); // Generate cached value for foo = 1 - $this->assertEquals('1', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 1])); + $this->assertEquals('1', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 1])); // Test without flush Injector::inst()->get(Kernel::class)->boot(); Director::test('/'); - $this->assertEquals('1', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 3])); + $this->assertEquals('1', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 3])); // Test with flush Injector::inst()->get(Kernel::class)->boot(true); Director::test('/?flush=1'); - $this->assertEquals('2', $this->_runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 2])); + $this->assertEquals('2', $this->runtemplate('<% cached %>$Foo<% end_cached %>', ['Foo' => 2])); } public function testVersionedCache() @@ -173,53 +173,53 @@ public function testVersionedCache() $origReadingMode = Versioned::get_reading_mode(); // Run without caching in stage to prove data is uncached - $this->_reset(false); + $this->reset(false); Versioned::set_stage(Versioned::DRAFT); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('default'); $this->assertEquals( 'default Stage.Stage', - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('first'); $this->assertEquals( 'first Stage.Stage', - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); // Run without caching in live to prove data is uncached - $this->_reset(false); + $this->reset(false); Versioned::set_stage(Versioned::LIVE); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('default'); $this->assertEquals( 'default Stage.Live', - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('first'); $this->assertEquals( 'first Stage.Live', - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); // Then with caching, initially in draft, and then in live, to prove that // changing the versioned reading mode doesn't cache between modes, but it does // within them - $this->_reset(true); + $this->reset(true); Versioned::set_stage(Versioned::DRAFT); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('default'); $this->assertEquals( 'default Stage.Stage', - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('first'); $this->assertEquals( 'default Stage.Stage', // entropy should be ignored due to caching - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); Versioned::set_stage(Versioned::LIVE); @@ -227,13 +227,13 @@ public function testVersionedCache() $data->setEntropy('first'); $this->assertEquals( 'first Stage.Live', // First hit in live, so display current entropy - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); $data = new SSTemplateEngineCacheBlockTest\VersionedModel(); $data->setEntropy('second'); $this->assertEquals( 'first Stage.Live', // entropy should be ignored due to caching - $this->_runtemplate('<% cached %>$Inspect<% end_cached %>', $data) + $this->runtemplate('<% cached %>$Inspect<% end_cached %>', $data) ); Versioned::set_reading_mode($origReadingMode); @@ -245,47 +245,47 @@ public function testVersionedCache() public function testBlocksConditionallyCacheWithIf() { // First, run twice with caching - $this->_reset(true); + $this->reset(true); - $this->assertEquals('1', $this->_runtemplate('<% cached if True %>$Foo<% end_cached %>', ['Foo' => 1])); - $this->assertEquals('1', $this->_runtemplate('<% cached if True %>$Foo<% end_cached %>', ['Foo' => 2])); + $this->assertEquals('1', $this->runtemplate('<% cached if True %>$Foo<% end_cached %>', ['Foo' => 1])); + $this->assertEquals('1', $this->runtemplate('<% cached if True %>$Foo<% end_cached %>', ['Foo' => 2])); // Then twice without caching - $this->_reset(true); + $this->reset(true); - $this->assertEquals('1', $this->_runtemplate('<% cached if False %>$Foo<% end_cached %>', ['Foo' => 1])); - $this->assertEquals('2', $this->_runtemplate('<% cached if False %>$Foo<% end_cached %>', ['Foo' => 2])); + $this->assertEquals('1', $this->runtemplate('<% cached if False %>$Foo<% end_cached %>', ['Foo' => 1])); + $this->assertEquals('2', $this->runtemplate('<% cached if False %>$Foo<% end_cached %>', ['Foo' => 2])); // Then once cached, once not (and the opposite) - $this->_reset(true); + $this->reset(true); $this->assertEquals( '1', - $this->_runtemplate( + $this->runtemplate( '<% cached if Cache %>$Foo<% end_cached %>', ['Foo' => 1, 'Cache' => true ] ) ); $this->assertEquals( '2', - $this->_runtemplate( + $this->runtemplate( '<% cached if Cache %>$Foo<% end_cached %>', ['Foo' => 2, 'Cache' => false] ) ); - $this->_reset(true); + $this->reset(true); $this->assertEquals( '1', - $this->_runtemplate( + $this->runtemplate( '<% cached if Cache %>$Foo<% end_cached %>', ['Foo' => 1, 'Cache' => false] ) ); $this->assertEquals( '2', - $this->_runtemplate( + $this->runtemplate( '<% cached if Cache %>$Foo<% end_cached %>', ['Foo' => 2, 'Cache' => true ] ) @@ -298,17 +298,17 @@ public function testBlocksConditionallyCacheWithIf() public function testBlocksConditionallyCacheWithUnless() { // First, run twice with caching - $this->_reset(true); + $this->reset(true); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached unless False %>$Foo<% end_cached %>', ['Foo' => 1] ), '1' ); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached unless False %>$Foo<% end_cached %>', ['Foo' => 2] ), @@ -316,17 +316,17 @@ public function testBlocksConditionallyCacheWithUnless() ); // Then twice without caching - $this->_reset(true); + $this->reset(true); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached unless True %>$Foo<% end_cached %>', ['Foo' => 1] ), '1' ); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached unless True %>$Foo<% end_cached %>', ['Foo' => 2] ), @@ -340,17 +340,17 @@ public function testBlocksConditionallyCacheWithUnless() public function testNestedUncachedBlocks() { // First, run twice with caching, to prove we get the same result back normally - $this->_reset(true); + $this->reset(true); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached %> A $Foo B <% end_cached %>', ['Foo' => 1] ), ' A 1 B ' ); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached %> A $Foo B <% end_cached %>', ['Foo' => 2] ), @@ -358,17 +358,17 @@ public function testNestedUncachedBlocks() ); // Then add uncached to the nested block - $this->_reset(true); + $this->reset(true); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached %> A <% uncached %>$Foo<% end_uncached %> B <% end_cached %>', ['Foo' => 1] ), ' A 1 B ' ); $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( '<% cached %> A <% uncached %>$Foo<% end_uncached %> B <% end_cached %>', ['Foo' => 2] ), @@ -381,13 +381,13 @@ public function testNestedUncachedBlocks() */ public function testNestedBlocks() { - $this->_reset(true); + $this->reset(true); $template = '<% cached Foo %> $Fooa <% cached Bar %>$Bara<% end_cached %> $Foob <% end_cached %>'; // Do it the first time to load the cache $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( $template, ['Foo' => 1, 'Fooa' => 1, 'Foob' => 3, 'Bar' => 1, 'Bara' => 2] ), @@ -396,7 +396,7 @@ public function testNestedBlocks() // Do it again, the input values are ignored as the cache is hit for both elements $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( $template, ['Foo' => 1, 'Fooa' => 9, 'Foob' => 9, 'Bar' => 1, 'Bara' => 9] ), @@ -405,7 +405,7 @@ public function testNestedBlocks() // Do it again with a new key for Bar, Bara is picked up, Fooa and Foob are not $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( $template, ['Foo' => 1, 'Fooa' => 9, 'Foob' => 9, 'Bar' => 2, 'Bara' => 9] ), @@ -414,7 +414,7 @@ public function testNestedBlocks() // Do it again with a new key for Foo, Fooa and Foob are picked up, Bara are not $this->assertEquals( - $this->_runtemplate( + $this->runtemplate( $template, ['Foo' => 2, 'Fooa' => 9, 'Foob' => 9, 'Bar' => 2, 'Bara' => 1] ), @@ -424,24 +424,24 @@ public function testNestedBlocks() public function testNoErrorMessageForControlWithinCached() { - $this->_reset(true); - $this->assertNotNull($this->_runtemplate('<% cached %><% with Foo %>$Bar<% end_with %><% end_cached %>')); + $this->reset(true); + $this->assertNotNull($this->runtemplate('<% cached %><% with Foo %>$Bar<% end_with %><% end_cached %>')); } public function testErrorMessageForCachedWithinControlWithinCached() { $this->expectException(SSTemplateParseException::class); - $this->_reset(true); - $this->_runtemplate( + $this->reset(true); + $this->runtemplate( '<% cached %><% with Foo %><% cached %>$Bar<% end_cached %><% end_with %><% end_cached %>' ); } public function testNoErrorMessageForCachedWithinControlWithinUncached() { - $this->_reset(true); + $this->reset(true); $this->assertNotNull( - $this->_runtemplate( + $this->runtemplate( '<% uncached %><% with Foo %><% cached %>$Bar<% end_cached %><% end_with %><% end_uncached %>' ) ); @@ -450,14 +450,14 @@ public function testNoErrorMessageForCachedWithinControlWithinUncached() public function testErrorMessageForCachedWithinIf() { $this->expectException(SSTemplateParseException::class); - $this->_reset(true); - $this->_runtemplate('<% cached %><% if Foo %><% cached %>$Bar<% end_cached %><% end_if %><% end_cached %>'); + $this->reset(true); + $this->runtemplate('<% cached %><% if Foo %><% cached %>$Bar<% end_cached %><% end_if %><% end_cached %>'); } public function testErrorMessageForInvalidConditional() { $this->expectException(SSTemplateParseException::class); - $this->_reset(true); - $this->_runtemplate('<% cached Foo if %>$Bar<% end_cached %>'); + $this->reset(true); + $this->runtemplate('<% cached Foo if %>$Bar<% end_cached %>'); } } diff --git a/tests/php/SSTemplateEngineTest.php b/tests/php/SSTemplateEngineTest.php index ae1139d..91d5898 100644 --- a/tests/php/SSTemplateEngineTest.php +++ b/tests/php/SSTemplateEngineTest.php @@ -59,7 +59,10 @@ public function testTemplateWithoutHeadRenders() $data = new ArrayData([ 'Var' => 'var value' ]); $engine = new SSTemplateEngine('SSTemplateEngineTestPartialTemplate'); $result = $engine->render(new ViewLayerData($data)); - $this->assertEquals('Test partial template: var value', trim(preg_replace("//U", '', $result ?? '') ?? '')); + $this->assertEquals( + 'Test partial template: var value', + trim(preg_replace("//U", '', $result ?? '') ?? '') + ); } /** @@ -70,7 +73,10 @@ public function testTemplateExecution() $data = new ArrayData([ 'Var' => 'phpinfo' ]); $engine = new SSTemplateEngine('SSTemplateEngineTestPartialTemplate'); $result = $engine->render(new ViewLayerData($data)); - $this->assertEquals('Test partial template: phpinfo', trim(preg_replace("//U", '', $result ?? '') ?? '')); + $this->assertEquals( + 'Test partial template: phpinfo', + trim(preg_replace("//U", '', $result ?? '') ?? '') + ); } public function testIncludeScopeInheritance() @@ -272,7 +278,9 @@ public function testGlobalVariableCallsWithArguments() ); $this->assertEquals( 'zreferencez', - $this->render('$SSTemplateEngineTest_GlobalThatTakesArguments($SSTemplateEngineTest_GlobalReferencedByString)') + $this->render( + '$SSTemplateEngineTest_GlobalThatTakesArguments($SSTemplateEngineTest_GlobalReferencedByString)' + ) ); } @@ -295,7 +303,10 @@ public function testGlobalVariablesAreEscaped() public function testGlobalVariablesReturnNull() { $this->assertEquals('

', $this->render('

$SSTemplateEngineTest_GlobalReturnsNull

')); - $this->assertEquals('

', $this->render('

$SSTemplateEngineTest_GlobalReturnsNull.Chained.Properties

')); + $this->assertEquals( + '

', + $this->render('

$SSTemplateEngineTest_GlobalReturnsNull.Chained.Properties

') + ); } public function testCoreGlobalVariableCalls() @@ -1116,7 +1127,9 @@ public function testIncludeWithArguments() $this->assertEquals( '

A Bare String

B Bare String

', - $this->render('<% include SSTemplateEngineTestIncludeWithArguments Arg1=A Bare String, Arg2=B Bare String %>') + $this->render( + '<% include SSTemplateEngineTestIncludeWithArguments Arg1=A Bare String, Arg2=B Bare String %>' + ) ); $this->assertEquals( @@ -1170,7 +1183,7 @@ public function testIncludeWithArguments() 'A - B - A', $this->render( '<% include SSTemplateEngineTestIncludeScopeInheritanceWithArgsInWith Title="A" %>', - new ArrayData(['Item' => new ArrayData(['Title' =>'B'])]) + new ArrayData(['Item' => new ArrayData(['Title' => 'B'])]) ) ); @@ -1182,7 +1195,7 @@ public function testIncludeWithArguments() [ 'Item' => new ArrayData( [ - 'Title' =>'B', 'NestedItem' => new ArrayData(['Title' => 'C']) + 'Title' => 'B', 'NestedItem' => new ArrayData(['Title' => 'C']) ] )] ) @@ -1197,7 +1210,7 @@ public function testIncludeWithArguments() [ 'Item' => new ArrayData( [ - 'Title' =>'B', 'NestedItem' => new ArrayData(['Title' => 'C']) + 'Title' => 'B', 'NestedItem' => new ArrayData(['Title' => 'C']) ] )] ) @@ -1215,7 +1228,10 @@ public function testIncludeWithArguments() ] ); - $res = $this->render('<% include SSTemplateEngineTestIncludeObjectArguments A=$Nested.Object, B=$Object %>', $data); + $res = $this->render( + '<% include SSTemplateEngineTestIncludeObjectArguments A=$Nested.Object, B=$Object %>', + $data + ); $this->assertEqualIgnoringWhitespace('A B', $res, 'Objects can be passed as named arguments'); } @@ -1554,7 +1570,11 @@ public function testSSViewerBasicIteratorSupport() //test MultipleOf 10 $result = $this->render('<% loop Set %><% if MultipleOf(10,1) %>$Number<% end_if %><% end_loop %>', $data); - $this->assertEquals("10", $result, "Only numbers that are multiples of 10 (with 1-based indexing) are returned"); + $this->assertEquals( + "10", + $result, + "Only numbers that are multiples of 10 (with 1-based indexing) are returned" + ); //test MultipleOf 9 zero-based $result = $this->render('<% loop Set %><% if MultipleOf(9,0) %>$Number<% end_if %><% end_loop %>', $data); @@ -1932,7 +1952,7 @@ public static function provideRenderWithSourceFileComments(): array public function testRenderWithSourceFileComments(string $name, string $expected) { SSViewer::config()->set('source_file_comments', true); - $this->_renderWithSourceFileComments('SSTemplateEngineTestComments/' . $name, $expected); + $this->renderWithSourceFileComments('SSTemplateEngineTestComments/' . $name, $expected); } public static function provideRenderWithMissingTemplate(): array @@ -1957,7 +1977,8 @@ public static function provideRenderWithMissingTemplate(): array public function testRenderWithMissingTemplate(string|array $templateCandidates): void { if (empty($templateCandidates)) { - $message = 'No template to render. Try calling setTemplate() or passing template candidates into the constructor.'; + $message = 'No template to render. Try calling setTemplate() or passing template candidates' + . ' into the constructor.'; } else { $message = 'None of the following templates could be found: ' . print_r($templateCandidates, true) @@ -2077,7 +2098,8 @@ public function testRepeatedCallsAreCached() $this->assertEquals( 1, $data->testWithCalls, - 'SSTemplateEngineTest_CacheTestData::TestWithCall() should only be called once. Subsequent calls should be cached' + 'SSTemplateEngineTest_CacheTestData::TestWithCall() should only be called once.' + . ' Subsequent calls should be cached' ); $data = new SSTemplateEngineTest\CacheTestData(); @@ -2092,7 +2114,8 @@ public function testRepeatedCallsAreCached() $this->assertEquals( 1, $data->testLoopCalls, - 'SSTemplateEngineTest_CacheTestData::TestLoopCall() should only be called once. Subsequent calls should be cached' + 'SSTemplateEngineTest_CacheTestData::TestLoopCall() should only be called once.' + . ' Subsequent calls should be cached' ); } @@ -2227,8 +2250,12 @@ public function testGetterMethod(string $template, string $expected): void /** * Small helper to render templates from strings */ - private function render(string $templateString, mixed $data = null, array $overlay = [], bool $cache = false): string - { + private function render( + string $templateString, + mixed $data = null, + array $overlay = [], + bool $cache = false + ): string { $engine = new SSTemplateEngine(); if ($data === null) { $data = new SSTemplateEngineTest\TestFixture(); @@ -2237,7 +2264,7 @@ private function render(string $templateString, mixed $data = null, array $overl return trim('' . $engine->renderString($templateString, $data, $overlay, $cache)); } - private function _renderWithSourceFileComments($name, $expected) + private function renderWithSourceFileComments($name, $expected) { $viewer = new SSViewer([$name]); $data = new ArrayData([]); @@ -2266,7 +2293,7 @@ private function assertExpectedStrings($result, $expected) { foreach ($expected as $expectedStr) { $this->assertTrue( - (boolean) preg_match("/{$expectedStr}/", $result ?? ''), + (bool) preg_match("/{$expectedStr}/", $result ?? ''), "Didn't find '{$expectedStr}' in:\n{$result}" ); } diff --git a/tests/php/SSTemplateEngineTest/CacheTestData.php b/tests/php/SSTemplateEngineTest/CacheTestData.php index 3d97fb7..81cca83 100644 --- a/tests/php/SSTemplateEngineTest/CacheTestData.php +++ b/tests/php/SSTemplateEngineTest/CacheTestData.php @@ -9,7 +9,6 @@ class CacheTestData extends ModelData implements TestOnly { - public $testWithCalls = 0; public $testLoopCalls = 0; diff --git a/tests/php/SSTemplateEngineTest/TestGlobalProvider.php b/tests/php/SSTemplateEngineTest/TestGlobalProvider.php index 8932a16..1e87694 100644 --- a/tests/php/SSTemplateEngineTest/TestGlobalProvider.php +++ b/tests/php/SSTemplateEngineTest/TestGlobalProvider.php @@ -7,7 +7,6 @@ class TestGlobalProvider implements TemplateGlobalProvider, TestOnly { - public static function get_template_global_variables() { return [ diff --git a/tests/php/SSTemplateEngineTest/TestModelData.php b/tests/php/SSTemplateEngineTest/TestModelData.php index a5e35c3..6b2a53c 100644 --- a/tests/php/SSTemplateEngineTest/TestModelData.php +++ b/tests/php/SSTemplateEngineTest/TestModelData.php @@ -11,7 +11,6 @@ */ class TestModelData extends ModelData implements TestOnly { - private static $default_cast = 'Text'; private static $casting = [