Skip to content

Add FilterData#7022

Merged
VincentLanglet merged 1 commit intosonata-project:masterfrom
franmomu:filter_data_type_4
Apr 26, 2021
Merged

Add FilterData#7022
VincentLanglet merged 1 commit intosonata-project:masterfrom
franmomu:filter_data_type_4

Conversation

@franmomu
Copy link
Member

@franmomu franmomu commented Apr 7, 2021

Subject

I have doubts on where to do this, the easy way is to do it in 4.x, I thought about adding FilterDataType in 3.x, but removing buildForm from types is BC break, so not sure if is worth it to do it in 3.x.

My idea with filters was:

FilterDataType

This type will be used as a base of filter types, it contains type and value fields and it defines operator_type, field_type, operator_options and field_options options.

The idea is that other types will override getParent() method returning FilterDataType, so there is no need for them to override buildForm with type and value and only have to configure the operator_type and field_type options (and other options if they have).

The datatransform transforms from array to FilterData (I'll extract the CallbackTransformer to a class).

FilterData

This VO (ref: #6658) will be used instead of array for filters, this cannot be done with BC (at first I thought that implementing ArrayAccess could work, but array_key_exists does not work with objects and will break implementations).

I am targeting this branch, because this is not BC.

Closes #6658.

Changelog

### Added
- Added `FilterData` to model the data from a filter
### Changed
- Changed `FilterInterface::apply()` to accept a `FilterData` instance instead of `array` in argument 4

To do

  • Extract CallbackTransformer to a class.
  • Add tests.

@core23
Copy link
Member

core23 commented Apr 7, 2021

IMHO you can do this on the stable branch if you implement the ArrayAccess interface

@franmomu
Copy link
Member Author

franmomu commented Apr 8, 2021

IMHO you can do this on the stable branch if you implement the ArrayAccess interface

This is what I thought at first (it's in the description) and also implemented, but we (and maybe others) are using array_key_exists like in https://github.com/sonata-project/SonataDoctrineORMAdminBundle/blob/eb0f3b1ad0b1650bed6eedf732d320776f7aeccd/src/Filter/BooleanFilter.php#L40

And calling array_key_exists with an object doesn't work: https://3v4l.org/bZrdn

@SonataCI
Copy link
Collaborator

Could you please rebase your PR and fix merge conflicts?

phansys
phansys previously approved these changes Apr 11, 2021
@phansys phansys requested a review from a team April 11, 2021 09:32
@VincentLanglet
Copy link
Member

If we merge this, it will require to update the filter from persistence bundle.
I assume we'll update also all our filters (and the callback filters, so all the callback).
It will lead to a lot of code to update for a project will a lot of filters.

It would be great to find a way to provide a BC way... With an option maybe ?

@VincentLanglet
Copy link
Member

@phansys
Copy link
Member

phansys commented Apr 11, 2021

It would be great to find a way to provide a BC way... With an option maybe ?

Since these changes are targeting the next major, I think there is no need for a BC layer (which will require more work to maintain).

@VincentLanglet
Copy link
Member

Since these changes are targeting the next major, I think there is no need for a BC layer (which will require more work to maintain).

I had in mind to target 3.x instead. For a smooth update.
If the 4.0 update requires to rewrite every existing filters, it would be too big for some projects...

@phansys
Copy link
Member

phansys commented Apr 11, 2021

I had in mind to target 3.x instead. For a smooth update.

In that case, I think we could follow your suggestion about the switch parameter, deprecating its usage with the value that provides the array based filters and indicating that it will be removed in the next major.

@VincentLanglet
Copy link
Member

Maybe it could help to implement ArrayAccess in FilterData.
The only code needed to be update would be array_key_exist.

$data['value'] would still work.
And we deprecate the ArrayAccess implementation in 4.x

@franmomu
Copy link
Member Author

There are already PRs to use this in the persistence bundles: sonata-project/SonataDoctrineORMAdminBundle#1407 and sonata-project/SonataDoctrineMongoDBAdminBundle#574 (to be updated to the new namespace).

I don't think it's too much work to update to use FilterData, it feels weird to implement something (ArrayAccess) in 4.x (not released) which is already deprecated. But if you think it would be useful I can implement it.

And why this part https://github.com/sonata-project/SonataAdminBundle/blob/master/src/Datagrid/Datagrid.php#L290-L300 is untouched ?

Because it's not needed, FilterData comes from the forms, given a form (which parent is FilterDataType) when $form->getData() is called, it returns a FilterData (there is a DataTransformer).

@VincentLanglet
Copy link
Member

I don't think it's too much work to update to use FilterData, it feels weird to implement something (ArrayAccess) in 4.x (not released) which is already deprecated. But if you think it would be useful I can implement it.

It's not a lot of for persistence bundle indeed.
But I have 50 callback filters in my work project, for instance:

    /**
     * @param ProxyQuery $query
     * @param string     $alias
     * @param string     $field
     * @param array      $data
     *
     * @return bool
     */
    public function getByTotalSavingsFilter($query, $alias, $field, $data)
    {
        if (!$data['value']) {
            return false;
        }

        $contractSupportAlias = $this->getEntityAliasForPath($query, 'contractSupports.amount');
        $parameterName = $this->generateUniqParameterName($query, 'totalSavings');
        $operator = NumberFilter::CHOICES[$data['type']] ?? '=';

        $query->andHaving("SUM($contractSupportAlias.amount) $operator :$parameterName");
        $query->groupBy($alias);
        $query->setParameter($parameterName, $data['value']);

        return true;
    }

When I'll want to update to 4.0, I'll need to update all the other BC-break (for instance the typehint) for my code.
With this PR, i'll also have to update all my filters.
As a developer I would appreciate to do the filter update later and check first that my admin is working properly with 4.0.

But maybe it's better to do something here https://github.com/sonata-project/SonataDoctrineORMAdminBundle/blob/3.x/src/Filter/CallbackFilter.php#L44
Like an option for transforming the FilterData to an array before calling the callback. (Or a way to support both ??)

It could be something introduce in 4.0 - alpha/beta and removed before the real 4.0.
This way the developper could update step by step. But maybe I'm overthinking ?

Copy link
Member

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

I'd like to release the alpha before this merge ; if it's okay for you.
It could be the step I look for.

@VincentLanglet VincentLanglet requested a review from a team April 14, 2021 18:18
@VincentLanglet VincentLanglet added this to the 4.0 milestone Apr 14, 2021
@VincentLanglet
Copy link
Member

@franmomu @jordisala1991 If I merge this, do you prefer to

  1. Release an alpha2 and then we develop the support in the persistence bundle
  2. Change the minimum stability in persistence bundle to dev in order to use the dev-master branch and add compatibility before the alpha2
    ?

@jordisala1991
Copy link
Member

I think the second option is better but not strong opinion

public const CONDITION_AND = 'AND';

/**
* @phpstan-param array{type?: int|null, value?: mixed} $filterData
Copy link
Member Author

Choose a reason for hiding this comment

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

Just realised that type could not exists, but not sure if that makes sense.

With the current implementation FilterData::getType() would return null if type is not present in the array.

Copy link
Member

Choose a reason for hiding this comment

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

null and no value should behave the same IMHO.

Copy link
Member

@VincentLanglet VincentLanglet left a comment

Choose a reason for hiding this comment

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

I might be wrong but I think this PR need to be updated since this merge 6a0c277

This #7033 should use the FilterData isn't it ?

@franmomu
Copy link
Member Author

I might be wrong but I think this PR need to be updated since this merge 6a0c277

how so?

@franmomu
Copy link
Member Author

franmomu commented Apr 19, 2021

just squashed the two commits and renamed methods

@VincentLanglet
Copy link
Member

I might be wrong but I think this PR need to be updated since this merge 6a0c277

how so?

I saw here: https://github.com/sonata-project/SonataAdminBundle/pull/7033/files#diff-e279d5562ba068b14806eea28b5eea2b485848e73618a8a712dae6cc52e89e98R119 some $data['value'] and $data['type'] so I thought we had something to do...

I thought we got rid of this $data['value'], but I now understand that we only get rid of some of them

VincentLanglet
VincentLanglet previously approved these changes Apr 19, 2021
@VincentLanglet VincentLanglet requested review from a team and phansys April 19, 2021 22:04
@VincentLanglet
Copy link
Member

After this merge, we could update the persistence bundle and release an alpha-2. WDYT @sonata-project/contributors ?

@VincentLanglet
Copy link
Member

Do you have some time to finish this @franmomu ? :)

@franmomu franmomu force-pushed the filter_data_type_4 branch 2 times, most recently from e03427a to a49f757 Compare April 26, 2021 08:06
@franmomu franmomu force-pushed the filter_data_type_4 branch from a49f757 to 2a64bfa Compare April 26, 2021 08:09
@franmomu franmomu requested a review from phansys April 26, 2021 08:11
@phansys phansys requested a review from a team April 26, 2021 14:22
@VincentLanglet VincentLanglet merged commit 707d5a1 into sonata-project:master Apr 26, 2021
@franmomu franmomu deleted the filter_data_type_4 branch April 26, 2021 16:44
@franmomu
Copy link
Member Author

franmomu commented Apr 26, 2021

I was thinking that we can copy FilterData class in 3.x and for the CallbackFilter:

Before calling:

https://github.com/sonata-project/SonataDoctrineORMAdminBundle/blob/7493cfffcbe9996316e2dd0cdd9ac5092cf62a18/src/Filter/CallbackFilter.php#L44

We can maybe check with reflection the last parameter of $this->getOption('callback').

  • If the user has not defined type declaration or it is array we can trigger a deprecation that the user must add FilterData as type declaration.
  • If the user already has FilterData we transform the array to FilterData.

These callables are not supposed to implement FilterInterface so I think they would be fine (not forced to not have type declaration).

The only BC break in 4.0 would be for classes implementing FilterInterface as it is now.

@franmomu franmomu mentioned this pull request Apr 26, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants