I am working on a FOSS plugin to clone categories including sub categories in Shopware 6 (as suggested in NEXT-11360).
It's mostly based on this code from the German forum.
async duplicateElement(contextItem) {
const behavior = {
cloneChildren: true,
overwrites: {
name: `${contextItem.data.name} ${this.$tc('global.default.copy')}`,
path: null,
afterCategoryId: null,
updatedAt: null,
}
};
await this.categoryRepository.clone(contextItem.id, Shopware.Context.api, behavior).then((clone) => {
const criteria = new Criteria();
criteria.setIds([clone.id]);
this.categoryRepository.search(criteria).then((categories) => {
this.addCategories(categories);
});
}).catch(() => {
this.createNotificationError({
message: this.$tc('global.notification.unspecifiedSaveErrorMessage'),
});
});
},
This works suprisingly well at the first glance.
The current problem is, that the afterCategoryId is just copied, then pointing to the source categories and thus sort order is not maintained.
I tried to set this null in the overwrites, but this is not working recursively. Also I tried to set it to null as a proof of concept in the VersionManager
foreach(array_keys($data['children']) as $key) {
unset($data['children'][$key]['afterCategoryId']);
}
but then there is no sort order at all :-)
My next approach would be to subscribe to
\Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent
and fix the sort order after the entities have been copied.
I believe there is no suitable even to fix up the data before it is persisted?
Or is there an elegant way?
While it is convenient to be able to clone the complete tree with the root, I think it will probably less of a headache to implement your own clone endpoint, if you want to maintain the order of categories within a branch.
Here's a quick, untested implementation of an endpoint: