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

[spiral/filters] Filters improvements #961

Merged
merged 13 commits into from
Aug 14, 2023

Conversation

msmakouz
Copy link
Member

@msmakouz msmakouz commented Aug 10, 2023

Q A
Bugfix? ✔️
Breaks BC?
New feature? ✔️

Features

1. Value casters for Filter properties

Introducing Spiral\Filters\Model\Mapper\Mapper that sets values for filter properties. It utilizes a collection of casters, each designed to handle a specific type of value. Default casters include:

  • EnumCaster: Allows the use of PHP enums in Filter properties. This caster verifies the property type as an enum and creates the necessary enumeration from the value passed to the filter.
  • UUIDCaster: Allows the use of Ramsey UUID in Filter properties. This caster confirms the property type as UUID and constructs a UUID object from the string provided to the Filter.
  • DefaultCaster: Used when other casters are unable to assign a value. It sets the property value without any transformations. Behavior prior to changes in this pull request.

Casters are extensible and can be created and added by users within the application. To achieve this, it's necessary to create a custom caster object, implement the Spiral\Filters\Model\Mapper\CasterInterface interface, and implements the supports and setValue methods. The supports method takes the property type as a parameter and must determine whether the caster can assign a value. The setValue method is called if the supports method returns true. It takes the Filter, property, and value as parameters and is responsible for setting the value in the Filter property. And register custom caster in the Spiral\Filters\Model\Mapper\CasterRegistryInterface via register method.

Closes: #957

Bugfixes

1. Fixed nullable Nested Filters

Suppose there was a nested nullable filter within the main filter, along with validation rules:

use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\NestedFilter;
use Spiral\Filters\Attribute\Setter;
use Spiral\Filters\Model\Filter;
use Spiral\Filters\Model\FilterDefinitionInterface;
use Spiral\Filters\Model\HasFilterDefinition;
use Spiral\Validator\FilterDefinition;

final class CreateUser extends Filter implements HasFilterDefinition
{
    #[Post]
    #[Setter('strval')]
    public string $name;

    #[NestedFilter(Address::class)]
    public ?Address $address = null;

    public function filterDefinition(): FilterDefinitionInterface
    {
        return new FilterDefinition([
            'name' => ['string', 'required'],
        ]);
    }
}
use Spiral\Filters\Attribute\Input\Post;
use Spiral\Filters\Attribute\Setter;
use Spiral\Filters\Model\Filter;
use Spiral\Filters\Model\FilterDefinitionInterface;
use Spiral\Filters\Model\HasFilterDefinition;
use Spiral\Validator\FilterDefinition;

final class Address extends Filter implements HasFilterDefinition
{
    #[Post]
    #[Setter('strval')]
    public string $city;

    #[Post]
    #[Setter('strval')]
    public string $street;

    public function filterDefinition(): FilterDefinitionInterface
    {
        return new FilterDefinition([
            'city' => ['string', 'required'],
            'street' => ['string', 'required'],
        ]);
    }
}

We send only the name and get an error:

{
  "errors": {
    "address": {
      "city": "This value is required.",
      "street": "This value is required."
    }
  }
}

Without validation rules, we get a filter object with uninitialized properties.

public ?App\Endpoint\Web\Request\Address $address =>
    class App\Endpoint\Web\Request\Address#554 (3) {
        private array $data =>
            array(0) {}
        public string $city => *uninitialized*
        public string $street => *uninitialized*
    }
}

After these changes, in these cases the address property will be null.

Closes: #910

@butschster butschster marked this pull request as draft August 10, 2023 08:13
@butschster butschster changed the title [spiral/filters] Filters improvements, draft [spiral/filters] Filters improvements Aug 10, 2023
@codecov
Copy link

codecov bot commented Aug 10, 2023

Codecov Report

Patch coverage: 93.90% and project coverage change: +0.03% 🎉

Comparison is base (e2b43f3) 83.83% compared to head (e45aaa2) 83.87%.

Additional details and impacted files
@@             Coverage Diff              @@
##             master     #961      +/-   ##
============================================
+ Coverage     83.83%   83.87%   +0.03%     
- Complexity     5988     6025      +37     
============================================
  Files           786      792       +6     
  Lines         16898    16971      +73     
============================================
+ Hits          14167    14234      +67     
- Misses         2731     2737       +6     
Files Changed Coverage Δ
src/Filters/src/Model/Schema/AttributeMapper.php 94.91% <84.21%> (-5.09%) ⬇️
src/Filters/src/Model/Mapper/UuidCaster.php 86.66% <86.66%> (ø)
src/Filters/src/Attribute/Setter.php 100.00% <100.00%> (ø)
src/Filters/src/Exception/SetterException.php 100.00% <100.00%> (ø)
src/Filters/src/Model/FilterProvider.php 96.42% <100.00%> (+0.27%) ⬆️
...rc/Model/Interceptor/ValidateFilterInterceptor.php 100.00% <100.00%> (ø)
src/Filters/src/Model/Mapper/CasterRegistry.php 100.00% <100.00%> (ø)
src/Filters/src/Model/Mapper/DefaultCaster.php 100.00% <100.00%> (ø)
src/Filters/src/Model/Mapper/EnumCaster.php 100.00% <100.00%> (ø)
src/Filters/src/Model/Mapper/Mapper.php 100.00% <100.00%> (ø)
... and 2 more

... and 1 file with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@msmakouz msmakouz self-assigned this Aug 10, 2023
@msmakouz msmakouz added this to the 3.8 milestone Aug 10, 2023
@msmakouz msmakouz marked this pull request as ready for review August 10, 2023 12:38
@msmakouz msmakouz marked this pull request as draft August 10, 2023 14:20
@msmakouz msmakouz marked this pull request as ready for review August 14, 2023 08:23
@butschster butschster merged commit ae602f6 into spiral:master Aug 14, 2023
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
2 participants