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

add handling for enum as haystack #168

Open
wants to merge 3 commits into
base: 2.30.x
Choose a base branch
from

Conversation

reinfi
Copy link

@reinfi reinfi commented Dec 29, 2022

Q A
Documentation no
Bugfix no
BC Break no
New Feature yes
RFC no
QA no

Description

See issue #167.

Suggestion was to allow the haystack to be an enum. Otherwise a new validator for just the case of enums would be suitable.

I am a bit unsure about the testcase and I hope it would work with the build pipeline, but I will see it afterwards.

And psalm is not working because it misses the classes on PHP 8.0.

Happy to hear your feedback.

Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

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

Ok, from a preliminary observation, I think we should leave the haystack alone, and just populate it from a new option containing the enum.

Changing the haystack itself is probably more trouble, especially for BC.

This also means having a new private setEnum() or such 🤔

@reinfi
Copy link
Author

reinfi commented Dec 30, 2022

Still Psalm will fail, but I have not really an idea how to handle that because I had nothing todo with psalm so far 🙈

Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

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

Overall, approach seems OK 👍

What I'm thinking about is how to get static analysis "happy" with this :D

Still Psalm will fail, but I have not really an idea how to handle that because I had nothing todo with psalm so far 🙈

We could use a .stub file with Psalm, for now, perhaps: we'd declare BackedEnum there, then drop the stub once we drop PHP 8.0 support 🤔

/cc @gsteel do you have any better ideas?

*/
public function setEnum(string $enum): self
{
if (! is_subclass_of($enum, UnitEnum::class)) {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can skip this particular check: class-string<UnitEnum> already verifies this, and code written in newer codebases generally respects types in a much cleaner way

*
* @var class-string<UnitEnum>|null
*/
protected $enum;
Copy link
Member

Choose a reason for hiding this comment

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

Let's make this private before it spreads :D

@@ -169,6 +204,35 @@ public function setRecursive($recursive)
*/
public function isValid($value)
{
$enum = $this->getEnum();
Copy link
Member

Choose a reason for hiding this comment

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

Since we make $this->enum private, we can directly access it here: no need for a method call

@@ -169,6 +204,35 @@ public function setRecursive($recursive)
*/
public function isValid($value)
{
$enum = $this->getEnum();
if (is_string($enum)) {
Copy link
Member

Choose a reason for hiding this comment

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

We should just check for !== null

Comment on lines +117 to +125
public function setEnum(string $enum): self
{
if (! is_subclass_of($enum, UnitEnum::class)) {
throw new Exception\RuntimeException('enum has invalid type');
}

$this->enum = $enum;
return $this;
}
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this method should call setHaystack(): that would remove the need for touching the isValid() implementation

@boesing
Copy link
Member

boesing commented Jan 3, 2023

@Ocramius one things we need to keep in mind is that filters and stuff are usually passed as attributes and/or annotations. I am working with these Interfaces for years now and I have never called setters directly. They are always called from provided factories from within this component and thus I only have to use the attributes/annotations which allow devs to declare a spec which then is processed. Thats why the abstract filter is used because options are being passed as array so that they can be passed to the plugin manager. thats why the "build" method has that optional options array.

imho, as long as we do not provide an alternative to that specification, we should not try to avoid the Standard which was declared years back.
So we should not rely on pseudo-types like class-string too much in validator/filter too much.


so I think what would be fine is that we provide a dedicated factory for the ToEnum filter @reinfi, yes. That should work - might be worth testing that in a real project before merging this tho. 😬

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.

None yet

3 participants