- Issue created by @bojanz
- 🇩🇪Germany hchonov 🇪🇺🇩🇪🇧🇬
@bojanz, I've proposed something similar for tracking the
revision_parent
of duplicate entities in #2725523-30: Add a revision_parent field to revisionable entities → :If for example we take a food magazine, then we create a duplicate of some recipe and want to offer different extended variants by the users, which create a duplicate and extend/modify the new recipe, but a link between the recipes is automatically created. This actually sounds like a really great out of the box feature for Umami and for presenting Drupal.
I think that this feature might be used by a lot of projects and as such, it would be good to be part of the Drupal core.I think that in case of revisionable entity types the duplicate entity should reference its source through the new field "revision_parent". For non-revisionable entity types we could add a simply entity reference "parent" field and for config entities we could add a "source" property.
- 🇷🇸Serbia bojanz
It is a fair suggestion, but maybe we don't even need to store this. Just knowing the source/parent at the time of hook firing would be enough as a first step.
Also note that Entity::create() currently calls the storage create() method, but createDuplicate() doesn't and no hook is fired.
It might make sense to introduce a storage-level createDuplicate() which calls a hook_entity_create_duplicate().
That would be a fairly non-controversial change, though it still doesn't solve the problem of generically knowing the source ID at save time. - 🇩🇪Germany hchonov 🇪🇺🇩🇪🇧🇬
It is a fair suggestion, but maybe we don't even need to store this. Just knowing the source/parent at the time of hook firing would be enough as a first step.
This will be for sure much easier to implement and maybe easier to get into core than what I am proposing and still makes it possible to add the persisting layer later :).
Also introduce a hook_entity_duplicate(). This would allow us to pass $original_entity / $source_entity as a second argument if we feel like $entity->original is too much of a historical oddity.
+1 on the hook, as it allows to duplicate nested referenced structures as well.
I think it would be good to also have a new "source" property and the respective
getSourceEntity()
method on theEntityBase
class, which we could access during the saving process.I am in favor of adding a new property and not reusing the "original" property, because while being similar those are different operations and it is assumed that "original" is not set during the saving process of new entities.
It might make sense to introduce a storage-level createDuplicate() which calls a hook_entity_create_duplicate().
Yes, this makes sense. We've done this for example with the
createRevision
method on the storage. - 🇷🇸Serbia bojanz
You are right about $entity->original being too unclear in this case. Entities often have preSave() logic that compares ->original values, that logic would be unexpectedly triggered in case of a duplicate.
We need a fresh property.
- 🇷🇸Serbia bojanz
Updating issue summary with the new plan, as thought-up with berdir and hchonov.
- 🇬🇧United Kingdom AaronMcHale Edinburgh, Scotland
I wonder if the proposed
getDuplicateSource()
method might be a little too ambiguous of a name and could potentially result in accidental incorrect use, maybegetOriginatingEntity()
andgetOriginatingEntityId()
(in the event you don't want to load the Entity and just want the ID)? To me that seems a little clearer that the entity which is being returned was the Entity that this Entity was based upon, but then as has previously been mentioned maybe that is out of the scope of this issue. - 🇨🇭Switzerland berdir Switzerland
I find getDuplicateSource() less ambiguous than your suggestions, especially because we already have $entity->original (which we want to deprecate in favor of methods) which is something entirely different.
Drupal 9.1.0-alpha1 → will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule → and the Allowed changes during the Drupal 9 release cycle → .
Drupal 8.9.0-beta1 → was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule → and the Allowed changes during the Drupal 8 and 9 release cycles → .
Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule → and the Allowed changes during the Drupal 8 and 9 release cycles → .
- 🇩🇪Germany hchonov 🇪🇺🇩🇪🇧🇬
In addition to #9 -
getOriginatingEntity()
is too general and sounds like there might be multiple origins, whilegetDuplicateSource()
is more specific and semantically relates tocreateDuplicate()
. - First commit to issue fork.
- @sakiland opened merge request.
- @sakiland opened merge request.
Drupal 9.2.0-alpha1 → will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule → and the Allowed changes during the Drupal core release cycle → .
- 🇷🇸Serbia sakiland
I've created an initial quick solution without creating hook support and move logic into entity storage. I need this so I can fix issue with duplicating paragraph via Layout Builder #3190523: Paragraph is not cloned in Layout builder → . This is just start point for this issue, but it's working solution.
I've also crated two branches (one for 8.x and another for 9.x) and created two MR.
If someone needs patch file to apply these changes via composer, near each MR there is 'plan diff' url to the appropriate patch.
Drupal 9.3.0-rc1 → was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule → and the Allowed changes during the Drupal core release cycle → .
- 🇩🇪Germany Anybody Porta Westfalica
Just ran into a situation with layout_paragraphs where this also seems to be a blocker: 🐛 Cloning Entities containing Layout Paragraphs breaks structure Needs work at least for some cloning strategies. I'll add it to the related issues.
- First commit to issue fork.
- 🇺🇸United States richgerdes New Jersey, USA
I've taken a pass at improvements here. I've updated the workflow for the
createDuplicate()
function to mirror that ofcreate()
, and making a call out to the storage service to handle the duplication. Similarly to thecreate()
on the storage class, this implements acreateDuplicate()
invokespreCreateDuplicate()
on the entity class, then callsdoCreateDuplicate()
, and ultimately calls$entity->postDuplicate()
before invoking new hooks (ENTITY_TYPE_duplicate_create
andentity_duplicate_create
).I've opted for the name `duplicate_create` for the hook, which follows the same format as `revision_create`. Additionally new apis for getting/setting the duplicate source entity and checking if the entity is a duplicate (like isNew) are included now.
- 🇺🇸United States richgerdes New Jersey, USA
Sorry for the spam. I rebased the branches so that I could roll a patch that applies against 9.4.x, instead of 9.2.x, but forgot that I don't have access to change the MR target branch. Someone will need to update the target branch to 9.4.x so this can be better reviewed....
In the mean time, I'm posting a patch here for reference. This should apply fine.
- 🇫🇷France julien.sibi
Hello @richgerdes,
I was having errors with your patch when cloning a display mode on a order entity type.
I got it working changing the following lines.
In entityStorageBase :
$duplicate->{$entity_type->getKey('id')} = NULL;
to
$duplicate->set($entity_type->getKey('id'), NULL);
$duplicate->{$entity_type->getKey('uuid')} = $this->uuidService->generate();
to
$duplicate->set($entity_type->getKey('uuid'), $this->uuidService->generate());
then in configEntityBase :
parent::postDuplicate();
to
parent::postDuplicate($storage);
But I don't really measure any consequences of this patch, and I think it needs review before using in production..
Julien
- First commit to issue fork.
- 🇺🇦Ukraine Taran2L Lviv
So, tests are green:
Changes since the #23:
- Removed class property
duplicateSource
(as this is run-time information; alsooriginal
property during update operation does not exist either) - Added uuid service to the base EntityStorageBase class
- Created a deprecation + a test for it
- Updated all children classes/related tests
- Moved duplicate test into the correct place
- Removed class property
- 🇨🇭Switzerland berdir Switzerland
> @berdir could you elaborate why adding a new method is a BC break?
Because it breaks implementations of that interface that implement it. We make exceptions in some cases, when we can safely assume that all implementations extend from a common base class, that is not really the case with EntityInterface, as for example the views module itself shows too
> Not so sure about optional direction, I think the point of this update - to allow devs to act upon any entity being duplicated/cloned. Optional support will limit this significantly.
My comment refers to the pre/post methods on the entity class, which would not hinder this in any way.
But there are also the new method on the storage interface, which is also complicated and has the same problem as EntityInterface. Limited support is somewhat theoretical, if core base classes support it then that means 99% of all entities out there do.
I didn't read through the whole issue, I guess the question is whether we _really_ need to apply the whole standard pattern here with storage methods. Invoking the hooks on the entity class directly would not be very pretty but it would be a trivial patch and would _not_ have to worry about all these BC concerns.
- 🇺🇦Ukraine Taran2L Lviv
@Berdir, thanks for your comments. I see your point here: the issue will be with code that uses the interfaces directly (without a base class).
It's hard for me to measure the impact here, but in core it's only single ViewUI class.By the way, EntityStorageInterface has been recently updated and will require a change anyway, see #2570593: Allow entities to be subclassed using "bundle classes" →
Maybe more ideas from someone else ?
- 🇺🇦Ukraine Taran2L Lviv
So, I have checked contrib that extends/implements EntityInterface/EntityStorageInterface and most of them, like maybe 99%, then extending base classes. So, probably not a huge problem in the real world. However, some amount of modules would be forced to add a new UUID service parameter ... but the number is not that big from my research, maybe ~100, maybe less
It's quite weird that ViewUI does that tbh, but it's not a proper entity, as it does not have annotations.
Drupal 9.4.0-alpha1 → was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule → and the Allowed changes during the Drupal core release cycle → .
- 🇷🇸Serbia sakiland
Thank you for your contribution on this issue,
Definitely, we need an appropriate way to react on entity being cloned (duplicated). This is needed for the proper functionality of the core Layout builder. Here's the issue → that I had with customizing the layout on the node level. It is related to the Entity Reference Revisions module, it doesn't react in the appropriate way when an entity is cloned, but it doesn't have a way how to react to this event. Here's some solution 🐛 New revision is not created via Layout Builder Active , but it depends on the method
isDuplicate
Also, each clone module has an issue with the paragraphs, and each fixes in a different way, but the core issue is in the Entity Reference Revisions module. For example:
- Entity Clone 🐛 Inline Blocks on Layout Builder Fail to Clone Correctly Needs work
- Quick Node Clone →
If you check the beginning of this issue
Every entity has a createDuplicate() method, but that method blasts away the original ID without saving it anywhere.
This makes it impossible to react to an entity being duplicated.so we need somewhere the reference to the original entity and also a way to check if an entity is a duplicate.
EntityInterface contains the method
isNew()
and I think it should also contains the methodisDuplicate
. Or if you think this is BC, we can move this method into EntityBase Drupal 9.5.0-beta2 → and Drupal 10.0.0-beta2 → were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule → and the Allowed changes during the Drupal core release cycle → .
- First commit to issue fork.
- @sakiland opened merge request.
- @sakiland opened merge request.
- 🇷🇸Serbia sakiland
It's impossible to do rebase against 9.5.x on the existing branch `3040556-duplicate-entity-source` (also on the branch `3040556-duplicate-entity-source-9.5.x`), so I've created a new branch `3040556-duplicate-entity-source-fix-rebase`
Let's wait weather test passing and I will do some branch clean up in the following days.
Thank you @ksenzee for your branch `3040556-duplicate-entity-source-9.5.x`, otherwise I will lost some code (it's my mistake, my Phpstorm rebased and pushed code at once :( ) - 🇷🇸Serbia sakiland
I've fixed main branch
3040556-duplicate-entity-source
. Now it contains valid code. Currently, MR 204 related to this branch, is created against 9.5.x; but after 9.5.x release date, I will move this to the 10.1.x@ksenzee after 9.5.x release date, please rebase your branch
3040556-duplicate-entity-source-9.5.x
to the latest 9.5.x code, in order to have a valid MR (patch) for the 9.5.x code base.All other branches without open MR are not valid (these are deprecated or temporary branches, but I don't have options to delete them).
Regarding failed test; I'm working on this, but I don't have an idea how to solve this.
In the unit testDrupal\Tests\Core\Config\Entity\ConfigEntityBaseUnitTest
there is configuration entity with random id. And for this entity, the storage is empty, and that's why test failed.$storage = $this->entityTypeManager()->getStorage($this->getEntityTypeId()); /** @var \Drupal\Core\Entity\EntityDuplicateInterface $duplicate */ $duplicate = $storage->createDuplicate($this);
- 🇷🇸Serbia sakiland
I fixed failed test via adding mocked storage service.
In commets above I can see some issues with search_api module. Can you please check if the last code from branch
3040556-duplicate-entity-source
produce this issue and give me more info regarding this?Thank you!
The Needs Review Queue Bot → tested this issue. It either no longer applies to Drupal core, or fails the Drupal core commit checks. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide → to find step-by-step guides for working with issues.
- 🇫🇮Finland jhuhta
In commets above I can see some issues with search_api module. Can you please check if the last code from branch 3040556-duplicate-entity-source produce this issue and give me more info regarding this?
I've been using the patch successfully on a busy production site since mid December on Drupal 9.4 and now also on Drupal 9.5. The site has also search_api enabled and in use.
- Status changed to Needs review
almost 2 years ago 2:55pm 8 February 2023 - Status changed to Needs work
almost 2 years ago 11:42am 10 February 2023 The Needs Review Queue Bot → tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".
Apart from a re-roll or rebase, this issue may need more work to address feedback in the issue or MR comments. To progress an issue, incorporate this feedback as part of the process of updating the issue. This helps other contributors to know what is outstanding.
Consult the Drupal Contributor Guide → to find step-by-step guides for working with issues.
- 🇫🇷France nod_ Lille
If this is a 9.x patch it's best to change the version for this issue metadata, otherwise the bot will keep putting back to needs work.
- Status changed to Needs review
almost 2 years ago 7:53am 11 February 2023 - 🇬🇧United Kingdom AaronMcHale Edinburgh, Scotland
I think the issue version should still be 10.1.x, the merge request just needs to be updated to 10.1.x. All development should be done against the latest version, and will be backported on commit if need be.
- 🇷🇸Serbia sakiland
Yes, that's right. Version should be 10.1.x
I will change that next week, but first we need branch for 9.5@ksenzee after can you please rebase your branch 3040556-duplicate-entity-source-9.5.x to the latest 9.5.x code, in order to have a valid MR (patch) for the 9.5.x code base.
After that I will change base version for main branch. Otherwise I will create a new branch for 9.5. But, I will prefer to keep as little as possible number of different branches if we don't need them.
- 🇬🇧United Kingdom AaronMcHale Edinburgh, Scotland
@sakiland We should only need a single branch and merge request, targeted at 10.1.x, multiple merge requests is going to make reviewing this more challenging. When it comes to committing, the core committers will commit it to 10.1.x, something like this is unlikely to get backported to 10.0 nor 9.5.
- 🇷🇸Serbia sakiland
Yes, I follow you, but Drupal 9.5 is supported until Nov 2023. We need MR against 9.5 too. That's why we need a separate branch. And the main branch should be against 10.1 as you suggested. And reviewing should only be done on the main branch (I use this patch over two years from 8.9 to 9.5 without issue, and I think there are couple of people who use it too, so I don't think we need extra reviewing for old version branches)
- 🇬🇧United Kingdom AaronMcHale Edinburgh, Scotland
@sakiland Like I said, if at the time of commit, the core committers feel that it makes sense to back-port this to 9.5 and 10.0, then they will do that by taking the 10.1 branch and back-porting it. Yes 9.5 is supported but it will only receive bug fixes and security fixes, all new development should be done only against 10.1.x, and so having a 9.5 branch here will only make it more challenging to review and get this to RTBC.
- Status changed to Needs work
almost 2 years ago 12:30pm 15 February 2023 - 🇷🇸Serbia sakiland
@aaronmchale Thank you for the suggestion, I appreciate it, and I understand what is your point. But, it seems you are missing the context of this issue. This issue is almost 4 years old, and there are couple of production sites already using this MR. These sites are probably still on the Drupal 9.5 (for my sites I'm sure they are on the 9.5 :), and it will be couple of next months)
That's why we need MR against 9.5 branch, in order to not break existing sites already using this patch.Also, I don't expect that this patch will be back-ported to the 9.5, this is too much effort for nothing (sites with Drupal 9.5 will continue to work with this patch in the same way as in previous couple of years. so there is no need for back-port).
I don't see any extra effort if we have separate MR for 9.5 branch. Core committer should only check the main branch (main MR) that will target 10.1.x (same approach when we have multiple patches on the issue, core committer will check only the last one that is tested by community). Yes, having multiple branches is not so clear when we have one branch and one MR, but I don't see any other solution for this kind of complications with multiple active versions (but, this out of scope for this issue, so for any other improvement regarding this, we can discuss on Slack :) )I will change status to need work until I make a valid MR to the 10.1
- 🇬🇧United Kingdom AaronMcHale Edinburgh, Scotland
@sakiland Given what you've said, I would suggest updating a patch file for 9.5 rather than have a MR, that way as you say for sites which do need this there is a patch they can apply, but that doesn't then risk complicating the review process.
So I recommend a MR against 10.1, and a 9.5 patch file for those who need it :)
- 🇷🇸Serbia sakiland
@aaronmchale Thank you for the recommendation. Ok, I will do as you suggested and create a patch file for 9.5
At the end, most important is to make it easier review process :) - 🇬🇧United Kingdom AaronMcHale Edinburgh, Scotland
Thanks @sakiland.
I'm going to change the version back to 10.1.x in line with core policy for new features.
- 🇷🇸Serbia sakiland
Here's the patch for the 9.5.x branch.
IMPORTANT: I will change the base branch for MR 204 to 10.1.x, so it will be no valid for the 9.5.
Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened → , as Drupal.org infrastructure cannot currently fully support a branch named
main
. New developments and disruptive changes should now be targeted for the11.x
branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule → and the Allowed changes during the Drupal core release cycle → .- 🇫🇮Finland jhuhta
Rebased the 9.5.x branch and re-rolled the 9.5.x patch: applies now against 9.5.7.
- 🇫🇮Finland jhuhta
Re-applied the patch against 10.1.x and 11.x branches. Didn't have that much luck with GitLab so here we go traditionally with patch files. Feel free to test and review.
- last update
about 1 year ago 29,658 pass, 2 fail - last update
about 1 year ago 30,461 pass, 2 fail - 🇫🇮Finland jhuhta
Here I removed a redundant test function, as the kernel test suffices. Got help with this from @lauriii.
- Status changed to Needs review
about 1 year ago 8:37pm 10 November 2023 - Issue was unassigned.
- Status changed to Needs work
about 1 year ago 10:14am 12 November 2023 - 🇨🇭Switzerland berdir Switzerland
I'm still not sure about this.
Moving to the storage is consistent with other API's, but it adds considerable new API surface, new interfaces, constructor deprecations. It's also not clear now whether the storage or the entity methods are the actual API, because calling the storage directly would be missing the setDuplicateSource() call.
I think this needs to be simplified if we ever want it to get committed. The minimal version to satisfy the issue title is a hook added to the existing createDuplicate() method. That hook can have two arguments entity and source. EntityBase and its subclasses can continue to override it.
What is the use case for the getDuplicateSource() and related methods? What operation can only be done when the duplicate entity is being saved and still needs to know the original?
There is also no new test coverage for the hooks yet, they should be implemented in a test module and do a modification that is asserted in a test.
- 🇷🇸Serbia sakiland
I started to work on this 3 years ago in order to fix issue with duplicate Entity reference 🐛 New revision is not created via Layout Builder Active
The main check in that issue 🐛 New revision is not created via Layout Builder Active is the code
if ($host->isNew() && $host->isDuplicate()) {
And this line will fix all issues related to the cloning process in multiple contributed modules (I've already wrote about this one year ago).
For that purpose we only need to know if entity is new one and also duplicate.As initial solution, I've implemented this method in
\Drupal\Core\Entity\EntityBase
(in the similar way as\Drupal\Core\Entity\EntityBase::isNew
That was working solution, easy to test and maintain.
Solution with hook is also ok if that can fix the issue with the related issue.
Unfortunately, I don't have any live project related to this issue (client left the Drupal technology).So, for this issue the main task should be to define in which direction we want to go. Otherwise we will waste valuable developer's time, loosing clients due the the issue with loosing data, etc.
- 🇬🇧United Kingdom joachim
I agree with @Berdir that this is pretty complicated.
Is the pre/postDuplicate stuff necessary?
Also, in passing:
* Due to the backward compatibility, we cannot put duplicate functionality * into the EntityInterface, and that's why this interface was introduced. * @see https://www.drupal.org/project/drupal/issues/3040556
The BC policy says:
> However, we reserve the ability to add methods to these interfaces in minor releases to support new features.
So we can add functionality to EntityInterface if we want to. But it seems like a lot of new API.
- First commit to issue fork.
Is there a d10 version of this patch? We'd been using !2980 on a D9 site and are trying to upgrade to D10. !204 looks like its set for D10.1, but for some reason that MR has over a thousand commits, most of which don't seem related.
- 🇺🇸United States richgerdes New Jersey, USA
@Mmillford, #60 should have a D10 patch that hopefully works. Probably need to test it though. The !204 MR has been rebased and remapped from D9, so that's likely where the extra commits came from.
- 🇺🇸United States richgerdes New Jersey, USA
So we can add functionality to EntityInterface if we want to.
While we can add new apis, it's better to not add BC breaks if we can avoid it. Similarly to the entity class, we are adding a function to the
EntityStorageInterface
too, which is also a BC break. We probably want to add an interface that add the create function. It would be nice to see these two new interfaces be removed in a future version of Drupal core (probably not 11 at this point, but 12 maybe?).Is the pre/postDuplicate stuff necessary?
Sure, technically a hook is all that's needed to cover the basic description, but when I ran into this issue, i also wanted to check the duplicate state at save time, which isn't covered by just using a hook unless I create those properties myself during the hook.
Both the config entity base and content entity base make use of the pre/post hooks. We could move that logic into the storage class, but I would recommend against it. If the api is setting an expectation for what will happen with an entity, then the logic should live on the entity class, even it its more functions. IMO the storage service should deal directly with loading entities, and not with managing entity properties field data. This is the best way to ensure that data is updated correctly over time.
Moving this logic to the entity storage class is a bad idea because a developer could override the storage class with a custom implementation. While we hope that the class override extends the existing base storage, we can't be sure that it will and that means the new class might not include the same logic for updating the entity during these events and for the duplicate operation to work consistently, then entity class is the best place for the logic.
The other question is what does core already do? The entity classes already have
pre/postSave()
andpre/postDelete()
functions, so there is precedence to have a similar api structure for duplicate. Additionally, since the duplicate process is similar to the create process, which would call the entity's constructor, we should have a way for the entity class to react to that as well, no?On the flip side, there is a lot of logic in the existing content/config entity storage base classes as well. For example both
createRevision()
andcreateTranslation()
exist on theContentEntityStorageBase
. Given the possibility of overriding the class the field value updates should probably be moved to the entity class instead, unless there is a strong need to tie the logic into the storage service such as loading the new serial id from the database. Given the current logic for these two functions, the main reason we need to use the storage handler for entity operations is to expose the module handler service in order to invoke info and alter hooks. If we want hooks, this may be unavoidable, but the hooks could be run along side.Given the above, I would still couple any entity data changes as closely to the entity class as possible, and for translation and revision support, that should likely live in the relevant traits instead of the generalized storage.
I am for simplifying logic where possible. Right now during clone the following happens.
- User calls
EntityBase::create()
- That gods to
EntityStorageBase->create()
- We then call
EntityBase::preCreate()
- Then
EntityStorageBase->doCreate()
which callsEntityBase::__construct()
EntityStorageBase->create()
then calls$entity->enforceIsNew()
- Folloed by
$entity->post create() ?</li> <li>Finally the "entity_create" hook</li> </ol> This flow is pretty lean, and doesn't expose any pre/post operations on the storage class itself, so either we would need need to add support for pre/post functions there, or a developer would be forced to override <?php EntityStorageBase->create()
to alter the logic, which seems more messy then adding a few extra functions to the process ahead of time. Maybe its not necessary, but seems like its a better Developer experience to provide the apis up front, which is what I think this patch is currently doing to mimic the create flow.
What is the use case for the getDuplicateSource() and related methods?
I think the duplicate source is a valid thing to keep track of during the duplication process. Sure this could just be a variable passed to the classes, but I think it makes sense to store it on the entity level as a temporary value, in order for use of the "duplicate" state outside of the hooks. For example would be nice if a module wanted to change something in the form during load, based on the duplicate state, there is no way for it to identify that without the class property/function.
What's left?
Skimming the comments, it seems like the last major issue outside of the above discussion is that "there is also no new test coverage for the hooks yet". Is there anything else that still needs to be done here?
- User calls
- 🇨🇭Switzerland berdir Switzerland
I still believe the easiest way forward is to add a single line to the existing createDuplicate() to trigger a hook. Yes, if we'd start from scratch, this is how we might design the duplicate API, it's consistent with other processes.
But again, it is a lot of methods and BC breaks for very little gain and this issue has been stuck for years on this. I agree, a duplicate source is neat for certain use cases during save, but it's also not impossible to work around this. If you need that you can fairly easily keep track of the reference on the duplicate hook and go back to that on save. Now with the new #Hook, you could probably even simply store it as a reference on the service. And the vast majority of use cases do not actually need this.
If someone reworks this, probably easiest as a new MR by adding a single hook call, API documentation and a basic test somewhere then I will RTBC this.
This also came up in Drupal CMS, where the current clone/replicate modules were evaluated: 📌 Evaluate cloning modules Active
- 🇦🇺Australia pameeela
+1 to taking the simple approach in the interest of progress.