-
-
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
Improve the way we append parent object if any #6171
Improve the way we append parent object if any #6171
Conversation
Could you please rebase your PR and fix merge conflicts? |
690aa10
to
479f1b4
Compare
fdbca2e
to
f7bfe9e
Compare
f7bfe9e
to
27b2958
Compare
942f72e
to
46c9d00
Compare
src/Admin/AdminHelper.php
Outdated
} | ||
|
||
/** | ||
* @template T of 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.
You should use @phpstan-template
, there were some problem with the general @template
annotation, as it may be used for symfony templates
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 should also move the template generic to the AdminHelper class, not the method
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 should also move the template generic to the AdminHelper class, not the method
It's allowed for method https://arnaud.le-blanc.net/post/phpstan-generics.html
In this case, I don't think the template should be moved to the class. This is not class-related.
I can use the method with an object Foo and then use it with an object Bar.
IMHO, you add the template tag when it's related to a property of the class (with construct, add, get, ...).
I still changed template
for phpstan-template
.
46c9d00
to
c34c0e6
Compare
If this is fixing a bug why is not a patch instead of minor? |
I added deprecation. |
/** | ||
* Set the parent object, if any, to the provided object. | ||
*/ | ||
final protected function appendParentObject(object $object): void |
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 you need this method or can you make 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.
I don't need it.
But since it's called in the getNewInstance
and I know some users are overridden this method (maybe without calling the parent method), I was thinking it could be useful to expose the appendParentObject
method.
f077ee8
to
c1119bc
Compare
c1119bc
to
e31ebc6
Compare
@core23 Your approval is required to merge this bugfix. Thanks :) |
e31ebc6
to
c50c60a
Compare
if (null !== $this->adminHelper) { | ||
$subject = $this->adminHelper->addNewInstance($parentSubject, $parentFieldDescription); | ||
} | ||
$subject = ObjectManipulator::setObject($admin->getNewInstance(), $parentSubject, $parentFieldDescription); |
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.
@VincentLanglet There is BC break here, parent object is set to new instance instead of adding new instance to parent collection, and this does not work for me
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.
That's intended, to solve #6166
And it works well for me since month.
If you think a special case is missed create an issue with a precise description.
But without any information, I would say that your setter or mapping has something wrong.
@@ -3382,26 +3386,6 @@ protected function buildForm() | |||
|
|||
$this->loaded['form'] = true; | |||
|
|||
// append parent object if any | |||
// todo : clean the way the Admin class can retrieve set the object | |||
if ($this->isChild() && $this->getParentAssociationMapping()) { |
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.
Hi, @VincentLanglet There is BC break here.
In case of a create form in a subadmin, the parent is not anymore associated.
In my case, to workaround it, I need to associate the parent entity in the subAdmin::preCreate.
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.
Can you create an issue with as much information as you have.
Or directly create the PR to call appendParentObject
if needed and explain why ?
I called appendParentObject
directly in getNewInstance
which should be enough IMO, do you override this method ? @Kal74
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.
Right, I overrided the getNewInstance!
Thanks.
* NEXT_MAJOR: Use BadMethodCallException instead | ||
*/ | ||
throw new \RuntimeException( | ||
sprintf('Method %s::%s() does not exist.', ClassUtils::getClass($instance), $method) |
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.
@VincentLanglet Why did you stop using a Symfony PropertyAccess? I got this exception because my DTO has no setters and getters, but only public properties.
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 are multiple issue with PropertyAccess, see symfony/symfony#5013 (comment)
In our case, we wanted
- To have different behavior when it's passed by reference or not.
- To sometimes use Setter over Adder.
But I didn't change the strategy in this PR, it was already like this in AdminHelper:: addNewInstance
.
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 can still add a check for a public property. Do you want to create the PR ?
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.
But I didn't change the strategy in this PR, it was already like this in
AdminHelper:: addNewInstance
.
So i messed up something.
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.
But I didn't change the strategy in this PR, it was already like this in
AdminHelper:: addNewInstance
.So i messed up something.
I did review again, and I changed something
Previously, only getter
and adder
was used.
Now, getter
and setter
or adder
are used.
Instead of $parent->addChild()
, I sometimes call $child->setParent()
.
} | ||
} elseif ($this->hasParentFieldDescription()) { | ||
$parentAdmin = $this->getParentFieldDescription()->getAdmin(); | ||
$parentObject = $parentAdmin->getObject($this->request->get($parentAdmin->getIdParameter())); |
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 fails with embedded documents (MongoDB) when adding new document (let's say it's called Level2NestedDoc
) at 2nd level of nesting: Class "App\Document\Level1NestedDoc" does not have an identifier
.
Maybe nesting such deep is not a good design (isn't it OK-ish with MongoDB's embedded documents?), but it worked on Sonata Admin v.3.
Now, after update to v.4, to work around the issue we have to override AbstractAdmin::createNewInstance()
to omit this method's call. But maybe instead we could
- first check the mapping for
embedded
flag, and/or - then verify that request's id parameter matches parent admin by looking at request's admin code?
What do you think? Should I open an issue?
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.
Better open an issue, this PR is 2 years old.
But, we won't check embedded in SonataAdmin since it's not related to any persistence bundle.
getObject is doing
final public function getObject($id): ?object
{
if (null === $id) {
return null;
}
$object = $this->getModelManager()->find($this->getClass(), $id);
if (null === $object) {
return null;
}
$this->alterObject($object);
foreach ($this->getExtensions() as $extension) {
$extension->alterObject($this, $object);
}
return $object;
}
Where does come from the Exception ?
If it's in the
$this->getModelManager()->find($this->getClass(), $id);
call, we could add some check in https://github.com/sonata-project/SonataDoctrineMongoDBAdminBundle/blob/4.x/src/Model/ModelManager.php
But its weird to have an entity without identifier, since all the admin (and parent admin) are supposed to be related to an entity/document.
Subject
I am targeting this branch, because this is BC (or at least I'm trying to).
When working on Embedded Admin and OneToMany field, I had a subject without the parent set, even if I was on the parent admin. After some investigations, I find out it was coming from this call:
https://github.com/sonata-project/SonataAdminBundle/blob/3.x/src/Resources/views/CRUD/Association/edit_one_to_many_inline_table.html.twig#L47
associationadmin.formfielddescriptions
is callinggetFormFieldDescriptions
, which build the form.There was some code to set the parent admin
https://github.com/sonata-project/SonataAdminBundle/blob/3.x/src/Admin/AbstractAdmin.php#L3356-L3373
but, it seems like the association admin was (obviously) returning
false
toisChild
. I could instead use theparentFieldDescription
like I did in some other situation.https://github.com/sonata-project/SonataAdminBundle/blob/3.x/src/Form/Type/AdminType.php#L112
Moreover, as an improvement, I move the code who set the parent object to the subject in the newInstance method. Indeed:
getNewInstance
method is called beforebuildForm
. This way, the parent object is set sooner.buildForm
shouldn't modify the object.Finally, I fixed the following bug #6166, by calling the child setter instead of the parent adder.
Close #6166
Changelog