Merge 154eb52f89
into 3b1d859baf
This commit is contained in:
commit
ddb65d3381
|
@ -172,6 +172,10 @@ class SSViewer_DataPresenter extends SSViewer_Scope
|
|||
// Get source for this value
|
||||
$result = $this->getValueSource($property);
|
||||
if (!array_key_exists('source', $result)) {
|
||||
// $Me is a special property. If nothing is providing an override, return the current item.
|
||||
if ($property === 'Me') {
|
||||
return ['obj' => $this->getItem()];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -130,6 +130,16 @@ class SSViewer_Scope
|
|||
if (is_scalar($item)) {
|
||||
$item = $this->convertScalarToDBField($item);
|
||||
}
|
||||
// Wrap arrays
|
||||
if (is_array($item)) {
|
||||
if (array_is_list($item)) {
|
||||
// Wrap in ArrayIterator to respect method signature
|
||||
$item = new ArrayIterator($item);
|
||||
} else {
|
||||
// Wrap in ArrayData so values can be accessed by key in templates
|
||||
$item = ArrayData::create($item);
|
||||
}
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
|
@ -308,6 +318,8 @@ class SSViewer_Scope
|
|||
// Item may be an array or a regular IteratorAggregate
|
||||
if (is_array($this->item)) {
|
||||
$this->itemIterator = new ArrayIterator($this->item);
|
||||
} elseif ($this->item instanceof Iterator) {
|
||||
$this->itemIterator = $this->item;
|
||||
} else {
|
||||
$this->itemIterator = $this->item->getIterator();
|
||||
|
||||
|
|
|
@ -537,7 +537,7 @@ class ViewableData implements IteratorAggregate
|
|||
* @param array $arguments
|
||||
* @param bool $cache Cache this object
|
||||
* @param string $cacheName a custom cache name
|
||||
* @return Object|DBField
|
||||
* @return object|DBField
|
||||
*/
|
||||
public function obj($fieldName, $arguments = [], $cache = false, $cacheName = null)
|
||||
{
|
||||
|
@ -558,6 +558,17 @@ class ViewableData implements IteratorAggregate
|
|||
$value = $this->$fieldName;
|
||||
}
|
||||
|
||||
// Wrap arrays
|
||||
if (is_array($value)) {
|
||||
if (array_is_list($value)) {
|
||||
// Wrap in ArrayIterator to respect method signature
|
||||
$value = new ArrayIterator($value);
|
||||
} else {
|
||||
// Wrap in ArrayData so values can be accessed by key in templates
|
||||
$value = ArrayData::create($value);
|
||||
}
|
||||
}
|
||||
|
||||
// Cast object
|
||||
if (!is_object($value)) {
|
||||
// Force cast
|
||||
|
@ -668,17 +679,6 @@ class ViewableData implements IteratorAggregate
|
|||
return SSViewer::get_templates_by_class(static::class, $suffix, self::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* When rendering some objects it is necessary to iterate over the object being rendered, to do this, you need
|
||||
* access to itself.
|
||||
*
|
||||
* @return ViewableData
|
||||
*/
|
||||
public function Me()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get part of the current classes ancestry to be used as a CSS class.
|
||||
*
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace SilverStripe\View\Tests;
|
||||
|
||||
use ArrayIterator;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use LogicException;
|
||||
|
@ -1331,6 +1332,50 @@ after'
|
|||
);
|
||||
}
|
||||
|
||||
public function provideLoop(): array
|
||||
{
|
||||
return [
|
||||
'nested array and iterator' => [
|
||||
'iterable' => [
|
||||
[
|
||||
'value 1',
|
||||
'value 2',
|
||||
],
|
||||
new ArrayIterator([
|
||||
'value 3',
|
||||
'value 4',
|
||||
]),
|
||||
],
|
||||
'template' => '<% loop $Iterable %><% loop $Me %>$Me<% end_loop %><% end_loop %>',
|
||||
'expected' => 'value 1 value 2 value 3 value 4',
|
||||
],
|
||||
'nested associative arrays' => [
|
||||
'iterable' => [
|
||||
[
|
||||
'Foo' => 'one',
|
||||
],
|
||||
[
|
||||
'Foo' => 'two',
|
||||
],
|
||||
[
|
||||
'Foo' => 'three',
|
||||
],
|
||||
],
|
||||
'template' => '<% loop $Iterable %>$Foo<% end_loop %>',
|
||||
'expected' => 'one two three',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideLoop
|
||||
*/
|
||||
public function testLoop(iterable $iterable, string $template, string $expected): void
|
||||
{
|
||||
$data = new ArrayData(['Iterable' => $iterable]);
|
||||
$this->assertEqualIgnoringWhitespace($expected, $this->render($template, $data));
|
||||
}
|
||||
|
||||
public function testSSViewerBasicIteratorSupport()
|
||||
{
|
||||
$data = new ArrayData(
|
||||
|
@ -2230,4 +2275,11 @@ EOC;
|
|||
$this->render('<% loop $Foo %>$Me<% end_loop %>', $data)
|
||||
);
|
||||
}
|
||||
|
||||
public function testMe(): void
|
||||
{
|
||||
$mockArrayData = $this->getMockBuilder(ArrayData::class)->addMethods(['forTemplate'])->getMock();
|
||||
$mockArrayData->expects($this->once())->method('forTemplate');
|
||||
$this->render('$Me', $mockArrayData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace SilverStripe\View\Tests;
|
||||
|
||||
use ArrayIterator;
|
||||
use ReflectionMethod;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
@ -278,4 +279,45 @@ class ViewableDataTest extends SapphireTest
|
|||
$this->assertSame($obj, $viewableData->getDynamicData('abc'));
|
||||
$this->assertSame($obj, $viewableData->abc);
|
||||
}
|
||||
|
||||
public function provideWrapArrayInObj(): array
|
||||
{
|
||||
return [
|
||||
'empty array' => [
|
||||
'arr' => [],
|
||||
'expectedClass' => ArrayIterator::class,
|
||||
],
|
||||
'fully indexed array' => [
|
||||
'arr' => [
|
||||
'value1',
|
||||
'value2',
|
||||
],
|
||||
'expectedClass' => ArrayIterator::class,
|
||||
],
|
||||
'fully associative array' => [
|
||||
'arr' => [
|
||||
'v1' => 'value1',
|
||||
'v2' => 'value2',
|
||||
],
|
||||
'expectedClass' => ArrayData::class,
|
||||
],
|
||||
'partially associative array' => [
|
||||
'arr' => [
|
||||
'value1',
|
||||
'v2' => 'value2',
|
||||
],
|
||||
'expectedClass' => ArrayData::class,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideWrapArrayInObj
|
||||
*/
|
||||
public function testWrapArrayInObj(array $arr, string $expectedClass): void
|
||||
{
|
||||
$viewableData = new ViewableData();
|
||||
$viewableData->arr = $arr;
|
||||
$this->assertInstanceOf($expectedClass, $viewableData->obj('arr'));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue