Important

You are browsing the documentation for version 4.1 of OroCommerce, OroCRM and OroPlatform, which is no longer maintained. Read version 5.1 (the latest LTS version) of the Oro documentation to get up-to-date information.

See our Release Process documentation for more information on the currently supported and upcoming releases.

How to Use a Draft Extension

An extension is a service that enables you to modify entity data when creating a draft entity. The extension is responsible for filters and matchers load. If the entity does not fit the extension criteria, it ignores the execution and does not change the entity.

How to Create an Extension

To create an extension, you must create a class, extend it from AbstractDuplicatorExtension, and register it as a service. Add the oro_draft.duplicator.extension tag to your extension configuration.

Extension

To simplify the implementation, you can use the default DuplicatorExtension extension and register it in the configuration.

Example:

 1 oro_draft.duplicator_extension.localization_extension:
 2     class: Oro\Bundle\DraftBundle\Duplicator\Extension\DuplicatorExtension
 3     arguments:
 4         - !service
 5             class: DeepCopy\Matcher\PropertyTypeMatcher
 6             arguments: ['Oro\Bundle\LocaleBundle\Entity\Localization']
 7         - !service
 8             class: DeepCopy\Filter\KeepFilter
 9     tags:
10         - { name: oro_draft.duplicator.extension, priority: 0 }

Note

Keep your extension priorities in mind. If two extensions have one area of ​​responsibility, then the higher priority extension will apply. All other extensions will be ignored.

context - use context parameter to control the expansion workflow. In the process, you will find actions that use the extension only at the draft creation stage and do not use it during the draft publication.

Default actions:

  1. DraftManager::ACTION_CREATE_DRAFT.

  2. DraftManager::ACTION_PUBLISH_DRAFT.

The example below illustrates the way to use context. We only update the draft entity creation date. The draft entity publication date remains unchanged.

 1<?php
 2
 3namespace Oro\Bundle\DraftBundle\Duplicator\Extension;
 4
 5use DeepCopy\Filter\Filter;
 6use DeepCopy\Matcher\Matcher;
 7use DeepCopy\Matcher\PropertyTypeMatcher;
 8use Oro\Bundle\DraftBundle\Duplicator\Filter\DateTimeFilter;
 9use Oro\Bundle\DraftBundle\Entity\DraftableInterface;
10use Oro\Bundle\DraftBundle\Manager\DraftManager;
11
12/**
13 * Responsible for copying behavior of DateTime type parameters.
14 */
15class DateTimeExtension extends AbstractDuplicatorExtension
16{
17    /**
18     * @return Filter
19     */
20    public function getFilter(): Filter
21    {
22        return new DateTimeFilter();
23    }
24
25    /**
26     * @return Matcher
27     */
28    public function getMatcher(): Matcher
29    {
30        return new PropertyTypeMatcher(\DateTime::class);
31    }
32
33    /**
34     * @inheritDoc
35     */
36    public function isSupport(DraftableInterface $source): bool
37    {
38        return $this->getContext()->offsetGet('action') === DraftManager::ACTION_CREATE_DRAFT;
39    }
40}

Filter

The filter is responsible for the entity data modification.

The example below illustrates the way to create and use the filter. This filter uses dependency to update the owner of a draft entity.

 1<?php
 2
 3namespace Oro\Bundle\DraftBundle\Duplicator\Filter;
 4
 5use Oro\Bundle\DraftBundle\Entity\DraftableInterface;
 6use Oro\Component\Duplicator\Filter\Filter;
 7use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
 8
 9/**
10 * Responsible for updating  draft owner field.
11 */
12class OwnerFilter implements Filter
13{
14    /**
15     * @var TokenStorageInterface
16     */
17    private $tokenStorage;
18
19    /**
20     * OwnerFilter constructor.
21     *
22     * @param TokenStorageInterface $tokenStorage
23     */
24    public function __construct(TokenStorageInterface $tokenStorage)
25    {
26        $this->tokenStorage = $tokenStorage;
27    }
28
29    /**
30     * @param DraftableInterface $object
31     * @param string $property
32     * @param callable $objectCopier
33     */
34    public function apply($object, $property, $objectCopier): void
35    {
36        $user = $this->tokenStorage->getToken()->getUser();
37        $object->setDraftOwner($user);
38    }
39}

Matcher

Matcher indicates the criteria that the filter is following to work successfully.

As an example, consider a matcher that takes properties names. This enables you to use one filter for multiple properties.

 1<?php
 2
 3namespace Oro\Bundle\DraftBundle\Duplicator\Matcher;
 4
 5use DeepCopy\Matcher\Matcher;
 6
 7/**
 8 * Determines whether a filter can be applied to the specified properties
 9 */
10class PropertiesNameMatcher implements Matcher
11{
12    /**
13     * @var string[]
14     */
15    private $properties;
16
17    /**
18     * @param string[] $properties
19     */
20    public function __construct(array $properties = [])
21    {
22        $this->properties = $properties;
23    }
24
25    /**
26     * @inheritDoc
27     */
28    public function matches($object, $property): bool
29    {
30        return in_array($property, $this->properties);
31    }
32}