-
Notifications
You must be signed in to change notification settings - Fork 822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ENH Convert scalars and arrays to viewable data #11227
ENH Convert scalars and arrays to viewable data #11227
Conversation
df462f4
to
7d863cd
Compare
7d863cd
to
abc2262
Compare
2c39936
to
f35e66c
Compare
f35e66c
to
f672441
Compare
// Cast arrays to ArrayList by default | ||
if (is_array($value) && $castingHelper === $this->config()->get('default_cast')) { | ||
$value = ArrayList::create($value); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ArrayList
converts associative arrays to ArrayData
- should we do the same here?
if (is_array($value) && $castingHelper === $this->config()->get('default_cast')) { | ||
$value = ArrayList::create($value); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this conditional on the casting helper being identical to the default cast?
$valueObject = Injector::inst()->create($castingHelper, $fieldName); | ||
$valueObject->setValue($value, $this); | ||
$value = $valueObject; | ||
// Cast arrays to ArrayList by default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Cast arrays to ArrayList by default | |
// Wrap arrays in ArrayList by default |
foreach ($this->items as $i => $item) { | ||
foreach ($this->items as $item) { | ||
if (is_array($item)) { | ||
yield new ArrayData($item); | ||
if (array_is_list($item)) { | ||
yield new ArrayList($item); | ||
} else { | ||
yield new ArrayData($item); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should be changing the way ArrayList
works - people use ArrayList
for purposes other than just use in templates, and this could break some logic people have that assumes the current logic will remain as-is.
if (is_a($value, ArrayList::class)) { | ||
$this->convertArrayListItemsToViewableData($value); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about other list types? We have to assume someone has made other implementations of SS_List
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making these changes in obj()
is going to have wider ranging effects than just making things work in the templating system. These changes should all be done inside the template parser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way things are setup I really don't know how to do this.
My PageController has this
public function ArrayTest()
{
return ['item3', 'item4'];
}
My template has this
<% loop $ArrayTest %>
$Me
<% end_loop %>
The generated template is this
$scope->locally()->obj('ArrayTest', null, true); $scope->pushScope(); while (($key = $scope->next()) !== false) {
$val .= '
';
$val .= $scope->locally()->XML_val('Me', null, true);
$val .= '
';
}; $scope->popScope();
$scope->locally()->obj('ArrayTest', null, true);
will call SSViewer_DataPresenter::obj()
which will call SSViewer_Scope::obj()
which calls SSViewer_DataPresenter::getObj()
which calls SSViewer_Scope::getObj()
which call ViewableData::obj()
which is where the code changes are. ViewableData::obj()
is what actually gets stuff, in this case PageController::ArrayTest()
AND it wraps the results in a cache.
When ViewableData::obj()
encounters an array, before this PR, it would convert it to a DBText
because that's the ViewableData.default_cast
. So all I get to work with in SSViewer_Scope::getObj() is a DBText which is obviously no usable
While this recipe-sink CI has gone green with this PR, it seems fair enough being concerned about ViewableData::obj() having potential side-effects. Given that, we could target this to CMS 6 instead?
I had to dive in and try to get this working myself to wrap my head around it. I ended up with these commits which handle allowing primitives to be used in templates, and allowing iterators such as I cam to the same conclusion as you regarding arrays though - even though What should we do?I think we need to do two things:
I'd say update this PR to handle point 1 above, and raise a new card to look at point 2 since that'll need to go through refinement. Considering there's a ton of ways point 2 could go, that may even be worth discussing in an architecture catchup. |
I'll close the PR to retain the diff for the CMS 6 card and open a new one to do just the scalars |
Issue #11196