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

Update all operation to prevent data loss #209

Merged
merged 9 commits into from
Nov 7, 2021

Conversation

AlexandruGG
Copy link
Collaborator

@AlexandruGG AlexandruGG commented Oct 30, 2021

This PR:

  • Modifies the all operation to apply normalize by default. Also allows usage without normalize via a bool param
  • It breaks backward compatibility
  • Has unit tests (phpspec)
  • Has static analysis tests (psalm, phpstan)
  • Has documentation

Fixes #208.

AlexandruGG added 2 commits October 30, 2021 19:21
- apply `normalize` by default
- allow usage without normalize via bool param
@AlexandruGG
Copy link
Collaborator Author

@drupol hey, let me know what you think of the comments above and the implementation; if all is good I will continue to complete the outstanding checkboxes

@drupol
Copy link
Collaborator

drupol commented Nov 1, 2021

It seems to go in the proper direction, nothing to add here, all good.

Copy link
Collaborator

@drupol drupol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯 !

If you want to ensure no data is lost in the case of duplicate keys, look at the ``Collection::normalize()`` operation.
.. warning:: An earlier version of this operation did not re-index keys by default, which meant at times data loss could occur.
The reason data loss could occur is because PHP array keys cannot be duplicated and must either be ``int`` or ``string``.
The old behaviour can still be achieved by using the operation with the ``$normalize`` parameter as *false*.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should remove this parameter in the next major version and keep this behavior, WDYT ?

To restore the previous behavior, users can do: iterator_to_array($collection->getIterator());

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's a bit trickier because of this: #208 (comment). Also see the serialization comment below

Comment on lines -38 to -39
$piped = Pipe::of()(Filter::of()($even), All::of())(new ArrayIterator([1, 2, 3, 4]));
print_r($piped); // [2, 4]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this standalone usage is actually not valid. In order to use Pipe every operation needs to return an Iterator, but All returns an array.

This was missed when introducing the All operation because there isn't any enforcement of the return type at the Operation interface level. It's not easy to implement that however because you could return multiple closures and only the last one needs to return an Iterator.

I will look to make a separate PR after this to update the All operation to return a Generator though, and move the conversion to array back into the Collection method

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, let's fix that in the next PR.

@@ -624,7 +624,7 @@ public function isEmpty(): bool
*/
public function jsonSerialize(): array
{
return $this->all();
return $this->all(false);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we cannot normalize by default in jsonSerialize because that would break usage with a "map" collection, e.g.:

// Correct -> using `all(false)`
json_encode(Collection::fromIterable(['foo' => 1, 'bar' => 2])); // '{"foo": 1, "bar": 2}'

// Incorrect -> using the new `all()`
json_encode(Collection::fromIterable(['foo' => 1, 'bar' => 2])); // '[1, 2]'

@drupol also I realised there's no mention in the documentation that Collection can be serialized. I am thinking to write about it and mention this behaviour as well. What do you think is the best place for it? I would say we could mention it in 2 places:

  • usage.rst -> have a short "Serialization" section
  • api.rst -> mentioning the jsonSerialize method

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Nice catch.

I would do it in both files - as serialization is a feature AND part of the API.

@AlexandruGG AlexandruGG marked this pull request as ready for review November 7, 2021 10:44
@AlexandruGG
Copy link
Collaborator Author

@drupol hey, I'd say this is ready for final review. Let me know if there's anything else we should add/modify in here

Copy link
Collaborator

@drupol drupol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, ready to be merged!

@AlexandruGG AlexandruGG merged commit a895d51 into master Nov 7, 2021
@AlexandruGG AlexandruGG deleted the feature/all-normalize-default branch November 7, 2021 15:45
@drupol
Copy link
Collaborator

drupol commented Nov 7, 2021

Youhou! Thanks!

@AlexandruGG
Copy link
Collaborator Author

Youhou! Thanks!

Thank you as well!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modify all operation to prevent data loss
2 participants