diff --git a/src/CoreShop/Bundle/ResourceBundle/DeepCopy/PimcoreFieldCollectionDefinitionMatcher.php b/src/CoreShop/Bundle/ResourceBundle/DeepCopy/PimcoreFieldCollectionDefinitionMatcher.php new file mode 100644 index 0000000000..2bb6bc0b26 --- /dev/null +++ b/src/CoreShop/Bundle/ResourceBundle/DeepCopy/PimcoreFieldCollectionDefinitionMatcher.php @@ -0,0 +1,42 @@ +getType()); + + if ($collectionDef instanceof Fieldcollection\Definition) { + return $collectionDef->getFieldDefinition($property) instanceof $this->matchType; + } + } + + return false; + } +} diff --git a/src/CoreShop/Bundle/ResourceBundle/DeepCopy/PimcoreFieldCollectionDefinitionReplaceFilter.php b/src/CoreShop/Bundle/ResourceBundle/DeepCopy/PimcoreFieldCollectionDefinitionReplaceFilter.php new file mode 100644 index 0000000000..c64a9ad573 --- /dev/null +++ b/src/CoreShop/Bundle/ResourceBundle/DeepCopy/PimcoreFieldCollectionDefinitionReplaceFilter.php @@ -0,0 +1,51 @@ +getDefinition()->getFieldDefinition($property); + + if (!$fieldDefinition) { + return; + } + + $reflectionProperty = ReflectionHelper::getProperty($object, $property); + $reflectionProperty->setAccessible(true); + + $value = ($this->callback)($object, $fieldDefinition, $property, $reflectionProperty->getValue($object)); + + $reflectionProperty->setValue($object, $value); + } +} diff --git a/src/CoreShop/Bundle/ResourceBundle/EventListener/DeepCopySubscriber.php b/src/CoreShop/Bundle/ResourceBundle/EventListener/DeepCopySubscriber.php index 241c17ec72..eb46756014 100644 --- a/src/CoreShop/Bundle/ResourceBundle/EventListener/DeepCopySubscriber.php +++ b/src/CoreShop/Bundle/ResourceBundle/EventListener/DeepCopySubscriber.php @@ -18,13 +18,20 @@ namespace CoreShop\Bundle\ResourceBundle\EventListener; +use CoreShop\Bundle\ResourceBundle\DeepCopy\PimcoreFieldCollectionDefinitionMatcher; +use CoreShop\Bundle\ResourceBundle\DeepCopy\PimcoreFieldCollectionDefinitionReplaceFilter; use CoreShop\Bundle\ResourceBundle\Pimcore\CacheMarshallerInterface; +use CoreShop\Component\Resource\Model\ResourceInterface; use DeepCopy\DeepCopy; use DeepCopy\Filter\Doctrine\DoctrineCollectionFilter; use DeepCopy\Matcher\PropertyTypeMatcher; use DeepCopy\TypeMatcher\TypeMatcher; use Pimcore\Event\SystemEvents; +use Pimcore\Model\DataObject\ClassDefinition\Data; use Pimcore\Model\DataObject\Concrete; +use Pimcore\Model\DataObject\Fieldcollection\Data\AbstractData; +use Pimcore\Model\Element\DeepCopy\PimcoreClassDefinitionMatcher; +use Pimcore\Model\Element\DeepCopy\PimcoreClassDefinitionReplaceFilter; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\GenericEvent; @@ -55,6 +62,41 @@ public function addDoctrineCollectionFilter(GenericEvent $event): void $event->setArgument('copier', $copier); } + if (($context['source'] ?? false) === 'Pimcore\Model\Version::marshalData') { + /** + * Pimcore handles CustomVersionMarshallInterface for Objects, but not for Fieldcollections + * this means that our custom types, get fully copied and serialized in to the version file + * meaning that for Cart Price Rules, you can end up serializing 100MB of data.... 🙈 + */ + $copier->addFilter( + new PimcoreFieldCollectionDefinitionReplaceFilter( + function (AbstractData $object, Data $fieldDefinition, mixed $property, mixed $currentValue): mixed { + if ($fieldDefinition instanceof Data\CustomVersionMarshalInterface) { + return $fieldDefinition->marshalVersion($object->getObject(), $currentValue); + } + + return $currentValue; + } + ), + new PimcoreFieldCollectionDefinitionMatcher(Data\CustomVersionMarshalInterface::class) + ); + } + + if (($context['source'] ?? false) === 'Pimcore\Model\Version::unmarshalData') { + $copier->addFilter( + new PimcoreFieldCollectionDefinitionReplaceFilter( + function (AbstractData $object, Data $fieldDefinition, mixed $property, mixed $currentValue): mixed { + if ($fieldDefinition instanceof Data\CustomVersionMarshalInterface) { + return $fieldDefinition->unmarshalVersion($object->getObject(), $currentValue); + } + + return $currentValue; + } + ), + new PimcoreFieldCollectionDefinitionMatcher(Data\CustomVersionMarshalInterface::class) + ); + } + if (($context['source'] ?? false) === 'Pimcore\Cache\Core\CoreCacheHandler::storeCacheData') { /** * This honestly absolutely sucks: