Skip to content
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

Fix mapping objects implementing ArrayAccess (not collections) #224

Closed
wants to merge 3 commits into from

Conversation

daniser
Copy link

@daniser daniser commented Jan 30, 2024

This PR fixes issue introduced by PR #197.

PR #197 replaced ArrayObject check with more broad ArrayAccess, thus breaking BC.
This PR added additional check for Traversable to make sure given item is a collection and not a simple array-like object.
Every collection implementation I know implements either Iterator or IteratorAggregate (both are Traversable descendants).
Moreover, sample collection from original issue #175 implements Iterator too, so I can state with great confidence that this PR won't introduce more BC breaks.

@cweiske
Copy link
Owner

cweiske commented Jan 31, 2024

Thank you for the patch. This is indeed a BC break that I did not think about.
Given that the release that introduced it is already 10 months old, I will not publish it in a patch level release: This patch does introduce a BC break for people that do indeed rely on the crude/broken ArrayAccess behavior.
It will be released as 5.0.0.

A question - do we need ArrayAccess at all, isn't Traversable enough?

@daniser
Copy link
Author

daniser commented Jan 31, 2024

We can add boolean flag to control behaviour and keep this feature in v4.0. What do you think?

ArrayAccess is indeed needed, as mapArray uses it to set values. Traversable is just a flag to differ collections from array-like objects.

P.S. Just noticed we may apply same treatment for nested arrays/collections (if I got this code right):

} else if (is_a($class, 'ArrayObject', true)) {

# Conflicts:
#	tests/ArrayTest.php
#	tests/support/JsonMapperTest/Array.php
#	tests/support/JsonMapperTest/ArrayAccessCollection.php
#	tests/support/JsonMapperTest/ArrayAccessObject.php
@daniser
Copy link
Author

daniser commented Mar 19, 2024

@cweiske Any progress on this?

@cweiske
Copy link
Owner

cweiske commented May 17, 2024

@daniser I rebased against current master and fixed all the conflicts that appeared because #232 was merged before.
It is merged now, with a lengthy explanation about the reasoning.

Thanks for the patch.

cweiske pushed a commit that referenced this pull request May 17, 2024
Only handle objects as array when they implement both
ArrayAccess and Traversable.

BC break!

----

Originally, JsonMapper handled objects extending ArrayObject as arrays.

Extending own collection classes from ArrayObject is not always feasible
(issue #175, #175),
so a way was sought to rely on interfaces only.

Patch #197 (#197) changed
the implementation to check for the ArrayAccess interface instead of
ArrayObject.

This unfortunately breaks
objects-that-allow-array-access-but-are-not-traversable-arrays
(issue #224, #224),
for example when you allow array access to properties stored
in some internal variable.

The correct solution is to check that the object implements
ArrayAcces *and* Traversable - then we can be sure the object
is intended to be used with e.g. foreach().

Resolves: #224
cweiske pushed a commit that referenced this pull request Sep 8, 2024
Only handle objects as array when they implement both
ArrayAccess and Traversable.

BC break!

----

Originally, JsonMapper handled objects extending ArrayObject as arrays.

Extending own collection classes from ArrayObject is not always feasible
(issue #175, #175),
so a way was sought to rely on interfaces only.

Patch #197 (#197) changed
the implementation to check for the ArrayAccess interface instead of
ArrayObject.

This unfortunately breaks
objects-that-allow-array-access-but-are-not-traversable-arrays
(issue #224, #224),
for example when you allow array access to properties stored
in some internal variable.

The correct solution is to check that the object implements
ArrayAcces *and* Traversable - then we can be sure the object
is intended to be used with e.g. foreach().

Resolves: #224
@cweiske
Copy link
Owner

cweiske commented Sep 8, 2024

Released with v5.0.0.

@daniser daniser deleted the fix/array-access-object branch September 9, 2024 07:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants