-
-
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
Deprecate some AbstractAdmin methods #6885
Conversation
d4bf913
to
df65be8
Compare
@@ -2690,7 +2716,9 @@ public function configureActionButtons($action, $object = null) | |||
|
|||
if (\in_array($action, ['show', 'delete', 'acl', 'history'], true) | |||
&& $this->hasRoute('edit') | |||
&& $this->canAccessObject('edit', $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.
Do we have to remove this one?
IMO looks better to use a method to check this rather than substitute this call with null !== $object && $this->hasAccess('x', $object)
everywhere.
There is also this check inside the canAccessObject
method: if (!$this->id($object)) { }
, that I don't know if can be removed.
EDIT: Looking at the calls, I think we can even add in that method a check for $this->hasRoute('route')
to make those if
smaller.
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.
- There is a lot of methods in the AdminInterface. I don't think we should exposing two methods with almost the same behavior.
- We're mixing the
access
notion in both theAccessRegistryInterface
and theAdminInterface
- Both can be called with an object (
hasAccess('edit', $object)
andcanAccessObject('edit', $object)
). How to know which one I should use ? If you look at the code, sometimes we were using one, sometimes the second one, this is really confusing.
Maybe deprecating this method is not the right thing to do.
- Changing
AccessRegistryInterface::hasAccess($action, $object)
toAccessRegistryInterface::hasAccess($action)
? This way it's clear, if you're concerned about the action access, use hasAccess ; if you're concerned about the object, use canAccessObject. - Renaming the
canAccessObject
method ?
And we could also move the canAccessObject
method to the AccessRegistryInterface
.
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 take a new look at the code.
Firstly, the check $this->id($object)
is needed.
Secondly, when you look at the following code
{% if admin.canAccessObject('edit', object)
and admin.hasRoute('edit')
%}
<li>
<a class="sonata-action-element" href="{{ admin.generateObjectUrl('edit', object) }}">
<i class="fa fa-edit" aria-hidden="true"></i>
{{ 'link_action_edit'|trans({}, 'SonataAdminBundle') }}
</a>
</li>
{% endif %}
Nothing can guarantee that
- the object is not null. User could have a different implementation of
canAccessObject
, and thengenerateObjectUrl
will give a TypeError. canAccessObject
andgenerateObjectUrl
are related. There are in different interfaces.
So I still think it's better to deprecate canAccessObject and using explicit checks.
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.
To be honest I don't understand the reasoning behind removing a meaningful method name in favor of explicit checks:
if ($this->hasRoute('acl')
&& null !== $object
&& null !== $this->id($object)
&& $this->hasAccess('acl', $object)
)
vs:
if ($this->canAccessObject('acl', object))
Every time there is a call to canAccessObject
, there is also a hasRoute
call, so I guess that method (don't know if canAccessObject
or other) could also check that.
IMHO (for the sake of maintainability) it is better to have a method as a concept that the developer can understand when looking at it rather than several checks.
the object is not null. User could have a different implementation of canAccessObject, and then generateObjectUrl will give a TypeError.
I think this is different, in this case if there is a call to generateObjectUrl
that needs an object, makes sense to check if that exists.
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.
To be honest I don't understand the reasoning behind removing a meaningful method name in favor of explicit checks:
if ($this->hasRoute('acl') && null !== $object && null !== $this->id($object) && $this->hasAccess('acl', $object) )
vs:
if ($this->canAccessObject('acl', object))
You're not always calling $this->canAccessObject
, you're often calling $admin->canAccessObject
, so you're calling this in the AdminInterface
, not the AbstractAdmin
. You don't know how the developer will implement this method.
I should be allowed to have this implementation:
public function canAccessObject($action, $object) {
return true;
}
Does the SonataAdmin code still works with this implementation ? No. We rely on a specific implementation. So this method shouldn't be in the interface. It could be in a service, but since we're not using it a lot, using specific checks seems enough to me.
Every time there is a call to
canAccessObject
, there is also ahasRoute
call, so I guess that method (don't know ifcanAccessObject
or other) could also check that.
IMHO (for the sake of maintainability) it is better to have a method as a concept that the developer can understand when looking at it rather than several checks.
Still, If you do this, you'll rely on a specific implementation of canAccessObject
which is against the purpose of an interface.
If a method should exist, it would be canGenerateObjectUrl
and be in the UrlGeneratorInterface
.
the object is not null. User could have a different implementation of canAccessObject, and then generateObjectUrl will give a TypeError.
I think this is different, in this case if there is a call to
generateObjectUrl
that needs an object, makes sense to check if that exists.
With the implementation I gave you, the twig template is giving a TypeError.
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 object is not null. User could have a different implementation of canAccessObject, and then generateObjectUrl will give a TypeError.
I think this is different, in this case if there is a call to generateObjectUrl that needs an object, makes sense to check if that exists.
With the implementation I gave you, the twig template is giving a TypeError.
This is precisely what I meant with my previous comment, in case we need to check that object is not null (because there is call that needs that object), make sense to add that extra check (admin.whatever and object != null
).
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 misunderstood that part. But the rest of my message is still valid.
We're relying on the implementation of canAccessObject
when it's not even in the same interface.
For a list
, we're doing hasRoute
and hasAccess
.
If for a show
, you're doing hasRoute
and canAccessObject
or worst, just doing canAccessObject
it won't be consistent with the list
, it could lead to weird behavior if I override the canAccessObject
method.
That's why I think it's better to keep the checks we need instead of hiding them inside a method which is in the public API. Given that fact, only the $this->id($object) !== null
is useful to keep inside this method. Does it worth a method ? I'm not sure about this.
If you look more at it, you can even see that the $this->id($object) !== null
check is wrong. Since generateObjectUrl
is relying on getUrlSafeIdentifier
.
If we want to keep abstraction, the only method to provide would be
public function canGenerateObjectUrl(object $object) {
return nul !== $this->getUrlSafeIdentifier($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.
Friendly ping @franmomu @sonata-project/contributors WDYT ?
Are there any replacements for this methods? |
|
This information should be added to the |
The changelog should be better now. |
Could you please rebase your PR and fix merge conflicts? |
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.
LGTM.
I also had a look and from what I can tell it does not impact any of my projects where I'm using SonataAdminBundle.
340fa08
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.
GitHub is responding with 502.
At src/Admin/AbstractAdmin.php:2914:
.' and will be removed an in 4.0. Use `hasAccess()` instead.',
@@ -3179,10 +3243,18 @@ protected function buildList() | |||
} | |||
|
|||
/** | |||
* Build the form FieldDescription collection. | |||
* NEXT_MAJOR: Change visibility to 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.
Shouldn't we add a @deprecated
annotation, just in case the users are overriding this method without calling parent
?
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.
Done
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 about buildShow()
?
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.
IMO, the chengelog must explicitly tell which deprecated methods will reduce its visibility.
If it's private, it's the same no ? |
Yes, I mean the cases where we are deprecating a method but not for removal, but for reduced visibility. |
I did:
|
These methods will reduce its visibility from public/protected to private, but the changelog just states that they are deprecated:
That's what I mean. |
But since private and removed have the same impact for the developer, I don't think we should be more precise. |
I agree with this fact. Dismiss my suggestion. |
Subject
I am targeting this branch, because BC
Changelog