From 12a741feee8443e7a55f1153c315b9beb01abdb5 Mon Sep 17 00:00:00 2001 From: Steve Boyd Date: Wed, 15 May 2024 16:31:39 +1200 Subject: [PATCH] ENH Rendering scalars in ArrayList in templates --- src/View/SSViewer_DataPresenter.php | 2 +- src/View/SSViewer_Scope.php | 27 +++++++++++++++++++++++---- tests/php/View/SSViewerTest.php | 12 ++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/View/SSViewer_DataPresenter.php b/src/View/SSViewer_DataPresenter.php index 9a65d01fa..4735bba01 100644 --- a/src/View/SSViewer_DataPresenter.php +++ b/src/View/SSViewer_DataPresenter.php @@ -376,7 +376,7 @@ class SSViewer_DataPresenter extends SSViewer_Scope // Check if the method to-be-called exists on the target object - if so, don't check any further // injection locations - $on = $this->itemIterator ? $this->itemIterator->current() : $this->item; + $on = $this->getItem(); if (is_object($on) && (isset($on->$property) || method_exists($on, $property ?? ''))) { return []; } diff --git a/src/View/SSViewer_Scope.php b/src/View/SSViewer_Scope.php index aa4ee2065..3b0fe1a5e 100644 --- a/src/View/SSViewer_Scope.php +++ b/src/View/SSViewer_Scope.php @@ -5,6 +5,11 @@ namespace SilverStripe\View; use ArrayIterator; use Countable; use Iterator; +use SilverStripe\ORM\FieldType\DBBoolean; +use SilverStripe\ORM\FieldType\DBText; +use SilverStripe\ORM\FieldType\DBFloat; +use SilverStripe\ORM\FieldType\DBInt; +use SilverStripe\ORM\FieldType\DBField; /** * This tracks the current scope for an SSViewer instance. It has three goals: @@ -121,7 +126,11 @@ class SSViewer_Scope */ public function getItem() { - return $this->itemIterator ? $this->itemIterator->current() : $this->item; + $item = $this->itemIterator ? $this->itemIterator->current() : $this->item; + if (is_scalar($item)) { + $item = $this->convertScalarToDBField($item); + } + return $item; } /** @@ -176,7 +185,7 @@ class SSViewer_Scope */ public function getObj($name, $arguments = [], $cache = false, $cacheName = null) { - $on = $this->itemIterator ? $this->itemIterator->current() : $this->item; + $on = $this->getItem(); return $on->obj($name, $arguments, $cache, $cacheName); } @@ -240,7 +249,7 @@ class SSViewer_Scope */ public function self() { - $result = $this->itemIterator ? $this->itemIterator->current() : $this->item; + $result = $this->getItem(); $this->resetLocalScope(); return $result; @@ -338,7 +347,7 @@ class SSViewer_Scope */ public function __call($name, $arguments) { - $on = $this->itemIterator ? $this->itemIterator->current() : $this->item; + $on = $this->getItem(); $retval = $on ? $on->$name(...$arguments) : null; $this->resetLocalScope(); @@ -368,4 +377,14 @@ class SSViewer_Scope { return $this->upIndex; } + + private function convertScalarToDBField(bool|string|float|int $value): DBField + { + return match (gettype($value)) { + 'boolean' => DBBoolean::create()->setValue($value), + 'string' => DBText::create()->setValue($value), + 'double' => DBFloat::create()->setValue($value), + 'integer' => DBInt::create()->setValue($value), + }; + } } diff --git a/tests/php/View/SSViewerTest.php b/tests/php/View/SSViewerTest.php index ce91527f3..e5307a7c1 100644 --- a/tests/php/View/SSViewerTest.php +++ b/tests/php/View/SSViewerTest.php @@ -2218,4 +2218,16 @@ EOC; $this->assertTrue(file_exists($cacheFile ?? ''), 'Cache file wasn\'t created when it was meant to'); unlink($cacheFile ?? ''); } + + public function testPrimitivesConvertedToDBFields() + { + $data = new ArrayData([ + // null value should not be rendered, though should also not throw exception + 'Foo' => new ArrayList(['hello', true, 456, 7.89, null]) + ]); + $this->assertEqualIgnoringWhitespace( + 'hello 1 456 7.89', + $this->render('<% loop $Foo %>$Me<% end_loop %>', $data) + ); + } }