-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Added FilterPersister to customize the way filters are stored #4331
Added FilterPersister to customize the way filters are stored #4331
Conversation
Admin/AbstractAdmin.php
Outdated
*/ | ||
protected $persistFilters = false; | ||
protected $filterPersister; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a BC break
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you're right... if we want to do it cleanly, we should remove this property
If we can stay BC |
Admin/AbstractAdmin.php
Outdated
/** | ||
* @param FilterPersisterInterface $filterPersister | ||
*/ | ||
public function setFilterPersister($filterPersister) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use type hinting here, and make it optional so that null
can be passed.
Admin/AbstractAdmin.php
Outdated
* Whether or not to persist the filters in the session. | ||
* | ||
* @var bool | ||
* @var FilterPersisterInterface|bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FilterPersisterInterface|null
Admin/AbstractAdmin.php
Outdated
@@ -766,16 +766,28 @@ public function getFilterParameters() | |||
{ | |||
$parameters = array(); | |||
|
|||
// if filter persister was configured with `true`, use the default persister (session) | |||
if ($this->filterPersister === true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null
Admin/AbstractAdmin.php
Outdated
@@ -766,16 +766,28 @@ public function getFilterParameters() | |||
{ | |||
$parameters = array(); | |||
|
|||
// if filter persister was configured with `true`, use the default persister (session) | |||
if ($this->filterPersister === true) { | |||
$this->filterPersister = new SessionFilterPersister($this->request->getSession()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this be done with DI, BTW? If no filterPersister is set, inject this default service?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my aim was to avoid deprecation, but yeah i can do it like it, but the boolean mode will have to be removed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Getting rid of the boolean mode is a good thing, b/c then it will be easier to reason on the type of filterPersister
, and use native checks like type hinting.
Admin/AbstractAdmin.php
Outdated
if ($filters == array() && $this->request->query->get('filters') != 'reset') { | ||
$filters = $this->request->getSession()->get($this->getCode().'.filter.parameters', array()); | ||
// if filter persistence is configured | ||
if ($this->filterPersister instanceof FilterPersisterInterface) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What else can it be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm not a big fan of falsy
tests, i rather test type of my object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big fan either, it was an honest question b/c I hadn't seen it could be boolean yet.
// if persist filters is a boolean use session persister as default | ||
// if persist filters is a string, use service reference instead | ||
if (is_bool($persistFilters)) { | ||
$definition->addMethodCall('setPersistFilters', array($persistFilters)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If true
, inject default service, if false
, don't do anything.
Should I close this PR, and reopen onto the master branch, with service injection ? |
You mean it can't be BC? |
*/ | ||
public function reset($admin) | ||
{ | ||
$this->session->remove($admin.'.filter.parameters'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please isolate the pattern building in a dedicated method.
* Set persisted filters for given admin. | ||
* | ||
* @param string $admin The admin code | ||
* @param array $filters The filters to persist |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please document what the array is supposed to look like (can it be multidimensional? What type are the keys, what are they?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The structure is the same than the filter values. It depends on what filters you are using.
@greg0ire I think so. We need to remove the this is a BC right ? |
Removing a protected property is not BC. It's a BC-break and the property should be deprecated instead. Can you try making the PR on 3.x? If we can't find a solution, then you'll have to rebase on master, but right now it's hard for me to imagine what would be a BC-break. |
Ok, I juste pushed a new version. |
Admin/AbstractAdmin.php
Outdated
* | ||
* @var FilterPersisterInterface|null | ||
*/ | ||
protected $filterPersister; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about making it private?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a code for myself, everything is private, but here, other properties are protected, i just tried to code like the rest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, good thinking, but please make it private
anyway, we're trying to change things.
Admin/AbstractAdmin.php
Outdated
* @var bool | ||
* | ||
* @deprecated since 3.x, to be removed in 4.0. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use magic to trigger deprecation notices here, but since it's the admin class, which is already big, and other properties could be deprecated, this could become a maintenance nightmare, so I'd say leave it like that.
* | ||
* @return string The storage key | ||
*/ | ||
protected function buildStorageKey($admin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private
please
* | ||
* @author Yann Eugoné <eugone.yann@gmail.com> | ||
*/ | ||
class SessionFilterPersister implements FilterPersisterInterface |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make it final
please
* "_page" => {int page num}, | ||
* "_sort_by" => {string sort property}, | ||
* "_sort_order" => {string sort order (ASC|DESC)}, | ||
* "_per_page" => {int count rows per page} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
Looks BC to me. |
} | ||
|
||
$definition->addMethodCall('setPersistFilters', array($persistFilters)); | ||
// if boolean config value provided, use the default persister : session | ||
if (is_bool($persistFilters) && $persistFilters) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we have to check if is_bool($persistFilters)
? This property is set from container parameter or from the attributes, and we can cast it previously on the other case.
Maybe we can change from scalarNode to booleanNode on the Bundle Configuration?
Just to have properties that we know they are a concrete type and can't be other things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code may also receive value from the tag of an admin service. I think that allowing true
to be provided, may be a short but efficient way to configure the persistence.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
got it. So if it is a boolean and true, we just change its value to the default persister, otherwise we chech if the value is there set by config (other provider or default) and then we call to setFilterPersister. It is something like that? was confused at first
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you got it. configuring persist_filters
to true
means
i don't care how you persist it, just do it
This is super nice! We should remember to update other bundles mocking some classes that extends AbstractAdmin, because those test will broke. |
@OskarStark see? Don't mock what you don't own ;) |
Agree with that, but when you are extending a class that you dont own. Either you mock it or you dont test your logic. Ideally extend classes is not a good practice in TDD but in some cases like sonataMedia we are not TDDing, but just adding test for the current code. If I have to choose between fragile test or fragile code IMO prefer to fix test all day long. |
👍 |
@yann-eugone can you please fix StyleCi? |
@OskarStark just pushed the fix, but not sure to understand the problem with |
0eab2d8
@greg0ire @OskarStark @jordisala1991 @core23 just rebased the whole Pull Request for the 2nd time, hope everything will be OK this time |
Thanks a lot for this! |
Thank you very much, great work @yann-eugone 👍 |
Happy to finally find a way to contribute 😄 |
$persistFilters = (bool) $attributes['persist_filters']; | ||
} else { | ||
$persistFilters = (bool) $container->getParameter('sonata.admin.configuration.filters.persist'); | ||
$persistFilters = $attributes['persist_filters']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could be located here? @soullivaneuh , before we had a cast to (bool) and now we don't. Maybe the value is getting there but not with the correct type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, "true" would also be considered as a true so not sure that is it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"true" !== true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if strict is used 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SonataAdminBundle/src/DependencyInjection/Compiler/AddDependencyCallsCompilerPass.php
Lines 314 to 323 in 0344393
if (isset($attributes['persist_filters'])) { | |
$persistFilters = $attributes['persist_filters']; | |
} | |
$filtersPersister = $container->getParameter('sonata.admin.configuration.filters.persister'); | |
// override default configuration with admin config if set | |
if (isset($attributes['filter_persister'])) { | |
$filtersPersister = $attributes['filter_persister']; | |
} | |
// configure filters persistence, if configured to | |
if ($persistFilters) { |
and it is not
I am targetting this branch, because this feature as a backward compatibility.
Changelog
To do
Subject
I had to persist filters accross sessions, so I decided to persist values to a database.
But as all the code remains in the AbstractAdmin, I had to redefine the whole method in my admin base class.
I did this PR so we can extend easily the way filters are persisted. We can also create more out-of-the-box filter persisters, such as : ORM, ODM, Redis...