diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..e98d4ce --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: thomas_klein # Replace with a single Patreon username +#open_collective: # Replace with a single Open Collective username +#ko_fi: # Replace with a single Ko-fi username +#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +#liberapay: # Replace with a single Liberapay username +#issuehunt: # Replace with a single IssueHunt username +#otechie: # Replace with a single Otechie username +custom: ['https://secure.payplug.com/p/jlnSz'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/Api/ActionEntityRepositoryInterface.php b/Api/ActionEntityRepositoryInterface.php new file mode 100644 index 0000000..f629683 --- /dev/null +++ b/Api/ActionEntityRepositoryInterface.php @@ -0,0 +1,59 @@ +urlBuilder = $urlBuilder; + } + + public function getButtonData(): array + { + return [ + 'label' => new Phrase('Back'), + 'on_click' => 'location.href = "' . $this->urlBuilder->getUrl('*/*/') . '";', + 'class' => 'back', + 'sort_order' => 10 + ]; + } +} diff --git a/Block/Adminhtml/Action/Edit/ExecuteButton.php b/Block/Adminhtml/Action/Edit/ExecuteButton.php new file mode 100644 index 0000000..b8a7c52 --- /dev/null +++ b/Block/Adminhtml/Action/Edit/ExecuteButton.php @@ -0,0 +1,29 @@ + new Phrase('Execute Action'), + 'class' => 'primary', + 'data_attribute' => [ + 'mage-init' => ['button' => ['event' => 'save']], + 'form-role' => 'save', + ], + 'on_click' => 'location.reload();', + 'sort_order' => 30, + 'aclResource' => 'Opengento_Gdpr::gdpr_actions_execute', + ]; + } +} diff --git a/Block/Adminhtml/Action/Edit/ResetButton.php b/Block/Adminhtml/Action/Edit/ResetButton.php new file mode 100644 index 0000000..e9cad17 --- /dev/null +++ b/Block/Adminhtml/Action/Edit/ResetButton.php @@ -0,0 +1,24 @@ + new Phrase('Reset'), + 'class' => 'reset', + 'on_click' => 'location.reload();', + 'sort_order' => 20 + ]; + } +} diff --git a/Block/Adminhtml/Config/Form/Field/AttributesAnonymizers.php b/Block/Adminhtml/Config/Form/Field/AttributesAnonymizers.php index 65813da..6e98899 100644 --- a/Block/Adminhtml/Config/Form/Field/AttributesAnonymizers.php +++ b/Block/Adminhtml/Config/Form/Field/AttributesAnonymizers.php @@ -9,21 +9,16 @@ use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray; use Magento\Framework\DataObject; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\View\Element\Html\Select; -/** - * Class AttributesAnonymizers - */ -final class AttributesAnonymizers extends AbstractFieldArray +class AttributesAnonymizers extends AbstractFieldArray { private const ANONYMIZERS_SELECT = '\Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\Anonymizers'; /** - * Retrieve the anonymizers select renderer - * - * @return \Magento\Framework\View\Element\Html\Select - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getAnonymizersSelectRenderer(): Select { @@ -43,7 +38,7 @@ public function getAnonymizersSelectRenderer(): Select /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function _prepareToRender(): void { @@ -67,7 +62,7 @@ protected function _prepareToRender(): void /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function _prepareArrayRow(DataObject $row): void { diff --git a/Block/Adminhtml/Config/Form/Field/EraseComponentsProcessors.php b/Block/Adminhtml/Config/Form/Field/EraseComponentsProcessors.php index b1f6a66..1d72b76 100644 --- a/Block/Adminhtml/Config/Form/Field/EraseComponentsProcessors.php +++ b/Block/Adminhtml/Config/Form/Field/EraseComponentsProcessors.php @@ -9,30 +9,22 @@ use Magento\Config\Block\System\Config\Form\Field\FieldArray\AbstractFieldArray; use Magento\Framework\DataObject; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\View\Element\Html\Select; -use Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\EraseComponents; -/** - * Class EraseComponentsProcessors - */ -final class EraseComponentsProcessors extends AbstractFieldArray +class EraseComponentsProcessors extends AbstractFieldArray { - private const ERASE_PROCESSORS_SELECT = '\Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\EraseProcessors'; - /** - * Retrieve the erase components select renderer - * - * @return \Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\EraseComponents - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ - public function getEraseComponentsSelectRenderer(): EraseComponents + public function getEraseComponentsSelectRenderer(): Select { if (!$this->hasData('erase_components_select_renderer')) { $this->setData( 'erase_components_select_renderer', $this->getLayout()->createBlock( - EraseComponents::class, + $this->getData('erase_components_select'), '', ['data' => ['is_render_to_js_template' => true]] ) @@ -43,10 +35,7 @@ public function getEraseComponentsSelectRenderer(): EraseComponents } /** - * Retrieve the erase processors select renderer - * - * @return \Magento\Framework\View\Element\Html\Select - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getEraseProcessorsSelectRenderer(): Select { @@ -54,7 +43,7 @@ public function getEraseProcessorsSelectRenderer(): Select $this->setData( 'erase_processors_select_renderer', $this->getLayout()->createBlock( - self::ERASE_PROCESSORS_SELECT, + $this->getData('erase_processors_select'), '', ['data' => ['is_render_to_js_template' => true]] ) @@ -66,7 +55,7 @@ public function getEraseProcessorsSelectRenderer(): Select /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function _prepareToRender(): void { @@ -90,7 +79,7 @@ protected function _prepareToRender(): void /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function _prepareArrayRow(DataObject $row): void { diff --git a/Block/Adminhtml/Config/Form/Field/Select/EraseComponents.php b/Block/Adminhtml/Config/Form/Field/Select/EraseComponents.php deleted file mode 100644 index 3c9265b..0000000 --- a/Block/Adminhtml/Config/Form/Field/Select/EraseComponents.php +++ /dev/null @@ -1,60 +0,0 @@ -eraseComponentSource = $eraseComponentSource; - parent::__construct($context, $data); - } - - /** - * Set the input name - * - * @param string $value - * @return $this - */ - public function setInputName($value): self - { - return $this->setData('name', $value); - } - - /** - * @inheritdoc - */ - protected function _toHtml(): string - { - if (!$this->getOptions()) { - $this->setOptions($this->eraseComponentSource->toOptionArray()); - } - - return parent::_toHtml(); - } -} diff --git a/Block/Adminhtml/Config/Form/Field/Select/OptionSourceSelect.php b/Block/Adminhtml/Config/Form/Field/Select/OptionSourceSelect.php index c230498..0c9aa6f 100644 --- a/Block/Adminhtml/Config/Form/Field/Select/OptionSourceSelect.php +++ b/Block/Adminhtml/Config/Form/Field/Select/OptionSourceSelect.php @@ -11,21 +11,13 @@ use Magento\Framework\View\Element\Context; use Magento\Framework\View\Element\Html\Select; -/** - * Class OptionSourceSelect - */ -final class OptionSourceSelect extends Select +class OptionSourceSelect extends Select { /** - * @var \Magento\Framework\Data\OptionSourceInterface + * @var OptionSourceInterface */ private $optionSource; - /** - * @param \Magento\Framework\View\Element\Context $context - * @param \Magento\Framework\Data\OptionSourceInterface $optionSource - * @param array $data - */ public function __construct( Context $context, OptionSourceInterface $optionSource, @@ -35,20 +27,11 @@ public function __construct( parent::__construct($context, $data); } - /** - * Set the input name - * - * @param string $value - * @return $this - */ - public function setInputName($value): self + public function setInputName(string $inputName): self { - return $this->setData('name', $value); + return $this->setData('name', $inputName); } - /** - * @inheritdoc - */ protected function _toHtml(): string { if (!$this->getOptions()) { diff --git a/Block/Adminhtml/Customer/Edit/EraseButton.php b/Block/Adminhtml/Customer/Edit/EraseButton.php index 088f7bc..8a78d4f 100644 --- a/Block/Adminhtml/Customer/Edit/EraseButton.php +++ b/Block/Adminhtml/Customer/Edit/EraseButton.php @@ -15,27 +15,18 @@ use Opengento\Gdpr\Api\EraseEntityCheckerInterface; use Opengento\Gdpr\Model\Config; -/** - * Class EraseButton - */ final class EraseButton extends GenericButton implements ButtonProviderInterface { /** - * @var \Opengento\Gdpr\Api\EraseEntityCheckerInterface + * @var EraseEntityCheckerInterface */ private $eraseCustomerChecker; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; - /** - * @param \Magento\Backend\Block\Widget\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Opengento\Gdpr\Api\EraseEntityCheckerInterface $eraseCustomerChecker - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( Context $context, Registry $registry, @@ -47,9 +38,6 @@ public function __construct( parent::__construct($context, $registry); } - /** - * @inheritdoc - */ public function getButtonData(): array { $customerId = $this->getCustomerId(); diff --git a/Block/Adminhtml/Customer/Edit/ExportButton.php b/Block/Adminhtml/Customer/Edit/ExportButton.php index 09b4d5a..0240691 100644 --- a/Block/Adminhtml/Customer/Edit/ExportButton.php +++ b/Block/Adminhtml/Customer/Edit/ExportButton.php @@ -14,21 +14,13 @@ use Magento\Framework\View\Element\UiComponent\Control\ButtonProviderInterface; use Opengento\Gdpr\Model\Config; -/** - * Class ExportButton - */ final class ExportButton extends GenericButton implements ButtonProviderInterface { /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; - /** - * @param \Magento\Backend\Block\Widget\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( Context $context, Registry $registry, @@ -38,9 +30,6 @@ public function __construct( parent::__construct($context, $registry); } - /** - * @inheritdoc - */ public function getButtonData(): array { $customerId = $this->getCustomerId(); diff --git a/Block/Adminhtml/Order/Edit/EraseButton.php b/Block/Adminhtml/Order/Edit/EraseButton.php index 8c25748..46328df 100644 --- a/Block/Adminhtml/Order/Edit/EraseButton.php +++ b/Block/Adminhtml/Order/Edit/EraseButton.php @@ -9,24 +9,18 @@ use Magento\Backend\Block\AbstractBlock; use Magento\Backend\Block\Context; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; +use Magento\Sales\Block\Adminhtml\Order\View; use Opengento\Gdpr\Api\EraseEntityCheckerInterface; -/** - * Class EraseButton - */ -final class EraseButton extends AbstractBlock +class EraseButton extends AbstractBlock { /** - * @var \Opengento\Gdpr\Api\EraseEntityCheckerInterface + * @var EraseEntityCheckerInterface */ private $eraseEntityChecker; - /** - * @param \Magento\Backend\Block\Context $context - * @param \Opengento\Gdpr\Api\EraseEntityCheckerInterface $eraseEntityChecker - * @param array $data - */ public function __construct( Context $context, EraseEntityCheckerInterface $eraseEntityChecker, @@ -43,13 +37,13 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function _construct(): void { parent::_construct(); - /** @var \Magento\Sales\Block\Adminhtml\Order\View $orderView */ + /** @var View $orderView */ $orderView = $this->getLayout()->getBlock('sales_order_edit'); $orderId = (int) $orderView->getOrderId(); diff --git a/Block/Adminhtml/Order/Edit/ExportButton.php b/Block/Adminhtml/Order/Edit/ExportButton.php index 75ce175..c2826d4 100644 --- a/Block/Adminhtml/Order/Edit/ExportButton.php +++ b/Block/Adminhtml/Order/Edit/ExportButton.php @@ -9,22 +9,12 @@ use Magento\Backend\Block\AbstractBlock; use Magento\Backend\Block\Context; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; +use Magento\Sales\Block\Adminhtml\Order\View; -/** - * Class ExportButton - */ -final class ExportButton extends AbstractBlock +class ExportButton extends AbstractBlock { - /** - * @var \Magento\Framework\AuthorizationInterface - */ - protected $_authorization; - - /** - * @param \Magento\Backend\Block\Context $context - * @param array $data - */ public function __construct( Context $context, array $data = [] @@ -39,13 +29,13 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function _construct(): void { parent::_construct(); - /** @var \Magento\Sales\Block\Adminhtml\Order\View $orderView */ + /** @var View $orderView */ $orderView = $this->getLayout()->getBlock('sales_order_edit'); $orderId = (int) $orderView->getOrderId(); diff --git a/Block/Messages/PrivacyMessagePopup.php b/Block/Messages/PrivacyMessagePopup.php index 6f8941f..27b0ae3 100644 --- a/Block/Messages/PrivacyMessagePopup.php +++ b/Block/Messages/PrivacyMessagePopup.php @@ -15,35 +15,25 @@ use Magento\Framework\View\Element\Template\Context; use Opengento\Gdpr\Model\Config; -/** - * Class PrivacyMessagePopup - */ -final class PrivacyMessagePopup extends Template +class PrivacyMessagePopup extends Template { public const COOKIE_NAME = 'cookies-policy'; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; /** - * @var \Magento\Cms\Helper\Page + * @var HelperPage */ private $helperPage; /** - * @var \Magento\Framework\Serialize\Serializer\Json + * @var Json */ private $jsonSerializer; - /** - * @param \Magento\Framework\View\Element\Template\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Cms\Helper\Page $helperPage - * @param \Magento\Framework\Serialize\Serializer\Json $jsonSerializer - * @param array $data - */ public function __construct( Context $context, Config $config, @@ -57,34 +47,18 @@ public function __construct( parent::__construct($context, $data); } - /** - * @inheritdoc - */ public function getJsLayout(): string { $this->jsLayout['components']['enhanced-privacy-cookie-policy']['config'] = [ 'cookieName' => self::COOKIE_NAME, 'learnMore' => $this->helperPage->getPageUrl($this->config->getPrivacyInformationPageId()), - 'notificationText' => $this->getCookieDisclosureInformation(), + 'notificationText' => $this->getCookieDisclosureInformationHtml(), ]; return $this->jsonSerializer->serialize($this->jsLayout); } - /** - * @inheritdoc - */ - protected function _toHtml(): string - { - return $this->config->isCookieDisclosureEnabled() ? parent::_toHtml() : ''; - } - - /** - * Retrieve the cookie disclosure information html - * - * @return string - */ - private function getCookieDisclosureInformation(): string + public function getCookieDisclosureInformationHtml(): string { if (!$this->hasData('cookie_disclosure_information')) { try { @@ -101,4 +75,9 @@ private function getCookieDisclosureInformation(): string return (string) $this->_getData('cookie_disclosure_information'); } + + protected function _toHtml(): string + { + return $this->config->isCookieDisclosureEnabled() ? parent::_toHtml() : ''; + } } diff --git a/Console/Command/EraseCommand.php b/Console/Command/EraseCommand.php index 6639225..6786dfe 100644 --- a/Console/Command/EraseCommand.php +++ b/Console/Command/EraseCommand.php @@ -12,60 +12,53 @@ use Magento\Framework\Console\Cli; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Registry; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -/** - * Class EraseCommand - */ class EraseCommand extends Command { - /**#@+ - * Input Variables Names - */ private const INPUT_ARGUMENT_ENTITY_ID = 'entity_id'; private const INPUT_ARGUMENT_ENTITY_TYPE = 'entity_type'; - /**#@-*/ /** - * @var \Magento\Framework\App\State + * @var State */ private $appState; /** - * @var \Magento\Framework\Registry + * @var Registry */ private $registry; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Framework\App\State $appState - * @param \Magento\Framework\Registry $registry - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement - * @param string $name + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( State $appState, Registry $registry, - EraseEntityManagementInterface $eraseEntityManagement, + ActionInterface $action, + ContextBuilder $actionContextBuilder, string $name = 'gdpr:entity:erase' ) { $this->appState = $appState; $this->registry = $registry; - $this->eraseEntityManagement = $eraseEntityManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($name); } - /** - * @inheritdoc - */ protected function configure(): void { parent::configure(); @@ -87,7 +80,7 @@ protected function configure(): void /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function execute(InputInterface $input, OutputInterface $output): int { @@ -102,10 +95,12 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { foreach ($entityIds as $entityId) { - // todo disable individual check: use mass validator - $this->eraseEntityManagement->process( - $this->eraseEntityManagement->create((int) $entityId, $entityType) - ); + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => $entityId, + ArgumentReader::ENTITY_TYPE => $entityType + ]); + $this->action->execute($this->actionContextBuilder->create()); + $output->writeln( 'Entity\'s (' . $entityType . ') with ID "' . $entityId . '" has been erased.' ); diff --git a/Console/Command/ExportCommand.php b/Console/Command/ExportCommand.php index ebe7380..98b6b55 100644 --- a/Console/Command/ExportCommand.php +++ b/Console/Command/ExportCommand.php @@ -10,55 +10,51 @@ use Magento\Framework\App\Area; use Magento\Framework\App\State; use Magento\Framework\Console\Cli; -use Opengento\Gdpr\Api\ExportEntityManagementInterface; -use Opengento\Gdpr\Model\ExportEntity; +use Magento\Framework\Exception\LocalizedException; +use Opengento\Gdpr\Api\ActionInterface; +use Opengento\Gdpr\Api\Data\ExportEntityInterface; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; +use Opengento\Gdpr\Model\Action\Export\ArgumentReader as ExportArgumentReader; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -/** - * Class ExportCommand - */ class ExportCommand extends Command { - /**#@+ - * Input Variables Names - */ private const INPUT_ARGUMENT_ENTITY_ID = 'entity_id'; private const INPUT_ARGUMENT_ENTITY_TYPE = 'entity_type'; private const INPUT_OPTION_FILENAME = 'filename'; - /**#@-*/ /** - * @var \Magento\Framework\App\State + * @var State */ private $appState; /** - * @var \Opengento\Gdpr\Api\ExportEntityManagementInterface + * @var ActionInterface */ - private $exportManagement; + private $action; /** - * @param \Magento\Framework\App\State $appState - * @param \Opengento\Gdpr\Api\ExportEntityManagementInterface $exportManagement - * @param string $name + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( State $appState, - ExportEntityManagementInterface $exportManagement, + ActionInterface $action, + ContextBuilder $actionContextBuilder, string $name = 'gdpr:entity:export' ) { $this->appState = $appState; - $this->exportManagement = $exportManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($name); } - /** - * @inheritdoc - */ protected function configure(): void { parent::configure(); @@ -87,7 +83,7 @@ protected function configure(): void /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ protected function execute(InputInterface $input, OutputInterface $output): int { @@ -100,10 +96,18 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { foreach ($entityIds as $entityId) { - $out = $this->exportManagement->export( - new ExportEntity((int) $entityId, $entityType, $fileName . '_' . $entityId) + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => $entityId, + ArgumentReader::ENTITY_TYPE => $entityType, + ExportArgumentReader::EXPORT_FILE_NAME => $fileName . '_' . $entityId + ]); + $result = $this->action->execute($this->actionContextBuilder->create())->getResult(); + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $result[ExportArgumentReader::EXPORT_ENTITY]; + + $output->writeln( + 'Entity\'s related data have been exported to: ' . $exportEntity->getFilePath() . '.' ); - $output->writeln('Entity\'s related data have been exported to: ' . $out . '.'); } } catch (\Exception $e) { $output->writeln('' . $e->getMessage() . ''); diff --git a/Controller/AbstractAction.php b/Controller/AbstractAction.php index 09bbaca..37f5794 100644 --- a/Controller/AbstractAction.php +++ b/Controller/AbstractAction.php @@ -9,24 +9,20 @@ use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; +use Magento\Framework\App\ResponseInterface; +use Magento\Framework\Controller\Result\Forward; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Exception\NotFoundException; use Opengento\Gdpr\Model\Config; -/** - * Class AbstractAction - */ abstract class AbstractAction extends Action { /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ protected $config; - /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( Context $context, Config $config @@ -35,9 +31,6 @@ public function __construct( parent::__construct($context); } - /** - * @inheritdoc - */ public function execute() { if ($this->isAllowed()) { @@ -50,29 +43,19 @@ public function execute() /** * Execute action based on request and return result * - * @return \Magento\Framework\Controller\ResultInterface|\Magento\Framework\App\ResponseInterface - * @throws \Magento\Framework\Exception\NotFoundException + * @return ResultInterface|ResponseInterface + * @throws NotFoundException */ abstract protected function executeAction(); - /** - * Check if the execution of the action is allowed - * - * @return bool - */ protected function isAllowed(): bool { return $this->config->isModuleEnabled(); } - /** - * Create a result forward to 404 - * - * @return \Magento\Framework\Controller\ResultInterface - */ protected function forwardNoRoute(): ResultInterface { - /** @var \Magento\Framework\Controller\Result\Forward $resultForward */ + /** @var Forward $resultForward */ $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); return $resultForward->forward('no_route'); diff --git a/Controller/AbstractGuest.php b/Controller/AbstractGuest.php index 019a5be..ee1ac85 100644 --- a/Controller/AbstractGuest.php +++ b/Controller/AbstractGuest.php @@ -14,27 +14,18 @@ use Magento\Sales\Controller\AbstractController\OrderLoaderInterface; use Opengento\Gdpr\Model\Config; -/** - * Class AbstractGuest - */ abstract class AbstractGuest extends AbstractAction { /** - * @var \Magento\Sales\Controller\AbstractController\OrderLoaderInterface + * @var OrderLoaderInterface */ protected $orderLoader; /** - * @var \Magento\Framework\Registry + * @var Registry */ protected $registry; - /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Sales\Controller\AbstractController\OrderLoaderInterface $orderLoader - * @param \Magento\Framework\Registry $registry - */ public function __construct( Context $context, Config $config, @@ -46,30 +37,17 @@ public function __construct( parent::__construct($context, $config); } - /** - * @inheritdoc - */ public function execute() { if (($result = $this->orderLoader->load($this->getRequest())) instanceof ResultInterface) { return $result; } - if (!($this->registry->registry('current_order') instanceof OrderInterface)) { - return $this->forwardNoRoute(); - } return parent::execute(); } - /** - * Retrieve the current guest order ID - * - * @return int - */ - protected function retrieveOrderId(): int + protected function currentOrder(): OrderInterface { - $order = $this->registry->registry('current_order'); - - return $order && $order instanceof OrderInterface ? (int) $order->getEntityId() : -1; + return $this->registry->registry('current_order'); } } diff --git a/Controller/AbstractPrivacy.php b/Controller/AbstractPrivacy.php index 855a6e4..d2d5f31 100644 --- a/Controller/AbstractPrivacy.php +++ b/Controller/AbstractPrivacy.php @@ -7,9 +7,6 @@ namespace Opengento\Gdpr\Controller; -/** - * Controller AbstractPrivacy - */ abstract class AbstractPrivacy extends AbstractAction { } diff --git a/Controller/Adminhtml/AbstractAction.php b/Controller/Adminhtml/AbstractAction.php index 42e1015..9d9ec12 100644 --- a/Controller/Adminhtml/AbstractAction.php +++ b/Controller/Adminhtml/AbstractAction.php @@ -9,24 +9,20 @@ use Magento\Backend\App\Action; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Forward; +use Magento\Framework\App\ResponseInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Exception\NotFoundException; use Opengento\Gdpr\Model\Config; -/** - * Class AbstractAction - */ abstract class AbstractAction extends Action { /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ protected $config; - /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( Context $context, Config $config @@ -35,9 +31,6 @@ public function __construct( parent::__construct($context); } - /** - * @inheritdoc - */ public function execute() { if ($this->isAllowed()) { @@ -50,29 +43,19 @@ public function execute() /** * Execute action based on request and return result * - * @return \Magento\Framework\Controller\ResultInterface|\Magento\Framework\App\ResponseInterface - * @throws \Magento\Framework\Exception\NotFoundException + * @return ResultInterface|ResponseInterface + * @throws NotFoundException */ abstract protected function executeAction(); - /** - * Check if the execution of the action is allowed - * - * @return bool - */ protected function isAllowed(): bool { return $this->config->isModuleEnabled(); } - /** - * Create a result forward to 404 - * - * @return \Magento\Framework\Controller\ResultInterface - */ protected function forwardNoRoute(): ResultInterface { - /** @var \Magento\Backend\Model\View\Result\Forward $resultForward */ + /** @var Forward $resultForward */ $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); return $resultForward->forward('no_route'); diff --git a/Controller/Adminhtml/Action/Execute.php b/Controller/Adminhtml/Action/Execute.php new file mode 100644 index 0000000..ac2e8d1 --- /dev/null +++ b/Controller/Adminhtml/Action/Execute.php @@ -0,0 +1,91 @@ +actionFactory = $actionFactory; + $this->contextBuilder = $contextBuilder; + $this->actionStates = $actionStates; + parent::__construct($context); + } + + public function execute() + { + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setPath('*/*/new'); + + try { + $result = $this->proceed($this->getRequest()->getParam('type')); + $resultRedirect->setPath('*/*/'); + $this->messageManager->addSuccessMessage( + new Phrase('The action state is now: %1.', [$this->actionStates->getOptionText($result->getState())]) + ); + } catch (LocalizedException $e) { + $this->messageManager->addErrorMessage($e->getMessage()); + } catch (Exception $e) { + $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.')); + } + + return $resultRedirect; + } + + /** + * @param string $actionType + * @return ActionResultInterface + * @throws LocalizedException + */ + private function proceed(string $actionType): ActionResultInterface + { + $parameters = []; + /** @var array $param */ + foreach ((array) $this->getRequest()->getParam('parameters', []) as $param) { + $parameters[$param['name']] = $param['value']; + } + $this->contextBuilder->setParameters($parameters); + + return $this->actionFactory->get($actionType)->execute($this->contextBuilder->create()); + } +} diff --git a/Controller/Adminhtml/Action/Index.php b/Controller/Adminhtml/Action/Index.php new file mode 100644 index 0000000..46aa997 --- /dev/null +++ b/Controller/Adminhtml/Action/Index.php @@ -0,0 +1,31 @@ +resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Opengento_Gdpr::gdpr_actions'); + $resultPage->getConfig()->getTitle()->set(new Phrase('View Actions')); + $resultPage->addBreadcrumb(new Phrase('GDPR'), new Phrase('GDPR')); + $resultPage->addBreadcrumb(new Phrase('View Actions'), new Phrase('View Actions')); + + return $resultPage; + } +} diff --git a/Controller/Adminhtml/Action/InlineEdit.php b/Controller/Adminhtml/Action/InlineEdit.php new file mode 100644 index 0000000..0a14e61 --- /dev/null +++ b/Controller/Adminhtml/Action/InlineEdit.php @@ -0,0 +1,121 @@ +actionEntityRepository = $actionEntityRepository; + $this->hydratorPool = $hydratorPool; + $this->logger = $logger; + $this->allowedAttributesByState = $allowedAttributesByState; + parent::__construct($context); + } + + public function execute() + { + /** @var Json $resultJson */ + $resultJson = $this->resultFactory->create(ResultFactory::TYPE_JSON); + $error = false; + $messages = []; + $postItems = $this->getRequest()->getParam('items', []); + + if (!$postItems || !is_array($postItems) || !$this->getRequest()->getParam('isAjax')) { + return $resultJson->setData(['messages' => [new Phrase('Please correct the data sent.')], 'error' => true]); + } + + foreach ($postItems as $actionId => $item) { + try { + $this->edit($actionId, $item); + } catch (LocalizedException $e) { + $messages[] = new Phrase('Action with ID "%1": %2', [$actionId, $e->getMessage()]); + $error = true; + } catch (Exception $e) { + $this->logger->error($e->getMessage(), $e->getTrace()); + $messages[] = new Phrase( + 'Action with ID "%1": %2', + [$actionId, new Phrase('An error occurred on the server.')] + ); + $error = true; + } + } + + return $resultJson->setData(compact('messages', 'error')); + } + + /** + * @param int $actionId + * @param array $data + * @return void + * @throws LocalizedException + * @todo improve extensibility: these settings should be global and be used to disable field in the ui grid + */ + private function edit(int $actionId, array $data): void + { + $hydrator = $this->hydratorPool->getHydrator(ActionEntityInterface::class); + $actionEntity = $this->actionEntityRepository->getById($actionId); + + $allowedAttributes = array_merge( + $this->allowedAttributesByState['*'] ?? [], + $this->allowedAttributesByState[$actionEntity->getState()] ?? [] + ); + + /** @var ActionEntityInterface $actionEntity */ + $actionEntity = $hydrator->hydrate( + $actionEntity, + array_intersect_key($data, array_fill_keys($allowedAttributes, null)) + ); + + $this->actionEntityRepository->save($actionEntity); + } +} diff --git a/Controller/Adminhtml/Action/NewAction.php b/Controller/Adminhtml/Action/NewAction.php new file mode 100644 index 0000000..068b0b2 --- /dev/null +++ b/Controller/Adminhtml/Action/NewAction.php @@ -0,0 +1,31 @@ +resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Opengento_Gdpr::gdpr_actions'); + $resultPage->getConfig()->getTitle()->set(new Phrase('Execute New Action')); + $resultPage->addBreadcrumb(new Phrase('GDPR'), new Phrase('GDPR')); + $resultPage->addBreadcrumb(new Phrase('Execute New Action'), new Phrase('Execute New Action')); + + return $resultPage; + } +} diff --git a/Controller/Adminhtml/Guest/Erase.php b/Controller/Adminhtml/Guest/Erase.php index 29a084a..08588d7 100644 --- a/Controller/Adminhtml/Guest/Erase.php +++ b/Controller/Adminhtml/Guest/Erase.php @@ -8,49 +8,51 @@ namespace Opengento\Gdpr\Controller\Adminhtml\Guest; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\Adminhtml\AbstractAction; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -/** - * Class Erase - */ class Erase extends AbstractAction implements HttpPostActionInterface { public const ADMIN_RESOURCE = 'Opengento_Gdpr::order_erase'; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Config $config, - EraseEntityManagementInterface $eraseEntityManagement + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { - $this->eraseEntityManagement = $eraseEntityManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function executeAction() { + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->getRequest()->getParam('id'), + ArgumentReader::ENTITY_TYPE => 'order' + ]); + try { - $this->eraseEntityManagement->process( - $this->eraseEntityManagement->create((int) $this->getRequest()->getParam('id'), 'order') - ); + $this->action->execute($this->actionContextBuilder->create()); $this->messageManager->addSuccessMessage(new Phrase('You erased the order.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); @@ -58,7 +60,7 @@ protected function executeAction() $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.')); } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setPath('sales/order/index'); diff --git a/Controller/Adminhtml/Guest/Export.php b/Controller/Adminhtml/Guest/Export.php index 168110e..4dff6d3 100644 --- a/Controller/Adminhtml/Guest/Export.php +++ b/Controller/Adminhtml/Guest/Export.php @@ -8,82 +8,71 @@ namespace Opengento\Gdpr\Controller\Adminhtml\Guest; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\Response\Http\FileFactory; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\ExportEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; +use Opengento\Gdpr\Api\Data\ExportEntityInterface; use Opengento\Gdpr\Controller\Adminhtml\AbstractAction; -use Opengento\Gdpr\Model\Archive\MoveToArchive; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; +use Opengento\Gdpr\Model\Action\Export\ArgumentReader as ExportArgumentReader; use Opengento\Gdpr\Model\Config; -use Opengento\Gdpr\Model\Export\ExportEntityFactory; -/** - * Class Export - */ class Export extends AbstractAction { public const ADMIN_RESOURCE = 'Opengento_Gdpr::order_export'; /** - * @var \Magento\Framework\App\Response\Http\FileFactory + * @var FileFactory */ private $fileFactory; /** - * @var \Opengento\Gdpr\Model\Archive\MoveToArchive - */ - private $moveToArchive; - - /** - * @var \Opengento\Gdpr\Api\ExportEntityManagementInterface + * @var ActionInterface */ - private $exportManagement; + private $action; /** - * @var \Opengento\Gdpr\Model\Export\ExportEntityFactory + * @var ContextBuilder */ - private $exportEntityFactory; + private $actionContextBuilder; - /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory - * @param \Opengento\Gdpr\Model\Archive\MoveToArchive $moveToArchive - * @param \Opengento\Gdpr\Api\ExportEntityManagementInterface $exportManagement - * @param \Opengento\Gdpr\Model\Export\ExportEntityFactory $exportEntityFactory - */ public function __construct( Context $context, Config $config, FileFactory $fileFactory, - MoveToArchive $moveToArchive, - ExportEntityManagementInterface $exportManagement, - ExportEntityFactory $exportEntityFactory + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { $this->fileFactory = $fileFactory; - $this->moveToArchive = $moveToArchive; - $this->exportManagement = $exportManagement; - $this->exportEntityFactory = $exportEntityFactory; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function executeAction() { + $entityId = (int) $this->getRequest()->getParam('id'); + + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => $entityId, + ArgumentReader::ENTITY_TYPE => 'order' + ]); + try { - $entityId = (int) $this->getRequest()->getParam('id'); - $fileName = $this->exportManagement->export($this->exportEntityFactory->create($entityId)); - $archiveFileName = 'guest_privacy_data_' . $entityId . '.zip'; + $result = $this->action->execute($this->actionContextBuilder->create())->getResult(); + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $result[ExportArgumentReader::EXPORT_ENTITY]; return $this->fileFactory->create( - $archiveFileName, + 'guest_privacy_data_' . $entityId . '.zip', [ 'type' => 'filename', - 'value' => $this->moveToArchive->prepareArchive($fileName, $archiveFileName), + 'value' => $exportEntity->getFilePath(), 'rm' => true, ], DirectoryList::TMP @@ -94,7 +83,7 @@ protected function executeAction() $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.')); } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setRefererOrBaseUrl(); diff --git a/Controller/Adminhtml/Privacy/Erase.php b/Controller/Adminhtml/Privacy/Erase.php index bdabb7b..42f7ef6 100644 --- a/Controller/Adminhtml/Privacy/Erase.php +++ b/Controller/Adminhtml/Privacy/Erase.php @@ -8,49 +8,51 @@ namespace Opengento\Gdpr\Controller\Adminhtml\Privacy; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\Adminhtml\AbstractAction; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -/** - * Class Erase - */ class Erase extends AbstractAction implements HttpPostActionInterface { public const ADMIN_RESOURCE = 'Opengento_Gdpr::customer_erase'; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Config $config, - EraseEntityManagementInterface $eraseEntityManagement + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { - $this->eraseEntityManagement = $eraseEntityManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function executeAction() { + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->getRequest()->getParam('id'), + ArgumentReader::ENTITY_TYPE => 'customer' + ]); + try { - $this->eraseEntityManagement->process( - $this->eraseEntityManagement->create((int) $this->getRequest()->getParam('id'), 'customer') - ); + $this->action->execute($this->actionContextBuilder->create()); $this->messageManager->addSuccessMessage(new Phrase('You erased the customer.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); @@ -58,7 +60,7 @@ protected function executeAction() $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.')); } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setPath('customer/index'); diff --git a/Controller/Adminhtml/Privacy/Export.php b/Controller/Adminhtml/Privacy/Export.php index 216637e..bac2ba0 100644 --- a/Controller/Adminhtml/Privacy/Export.php +++ b/Controller/Adminhtml/Privacy/Export.php @@ -8,82 +8,71 @@ namespace Opengento\Gdpr\Controller\Adminhtml\Privacy; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\Response\Http\FileFactory; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\ExportEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; +use Opengento\Gdpr\Api\Data\ExportEntityInterface; use Opengento\Gdpr\Controller\Adminhtml\AbstractAction; -use Opengento\Gdpr\Model\Archive\MoveToArchive; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; +use Opengento\Gdpr\Model\Action\Export\ArgumentReader as ExportArgumentReader; use Opengento\Gdpr\Model\Config; -use Opengento\Gdpr\Model\Export\ExportEntityFactory; -/** - * Class Export - */ class Export extends AbstractAction { public const ADMIN_RESOURCE = 'Opengento_Gdpr::customer_export'; /** - * @var \Magento\Framework\App\Response\Http\FileFactory + * @var FileFactory */ private $fileFactory; /** - * @var \Opengento\Gdpr\Model\Archive\MoveToArchive - */ - private $moveToArchive; - - /** - * @var \Opengento\Gdpr\Api\ExportEntityManagementInterface + * @var ActionInterface */ - private $exportManagement; + private $action; /** - * @var \Opengento\Gdpr\Model\Export\ExportEntityFactory + * @var ContextBuilder */ - private $exportEntityFactory; + private $actionContextBuilder; - /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory - * @param \Opengento\Gdpr\Model\Archive\MoveToArchive $moveToArchive - * @param \Opengento\Gdpr\Api\ExportEntityManagementInterface $exportManagement - * @param \Opengento\Gdpr\Model\Export\ExportEntityFactory $exportEntityFactory - */ public function __construct( Context $context, Config $config, FileFactory $fileFactory, - MoveToArchive $moveToArchive, - ExportEntityManagementInterface $exportManagement, - ExportEntityFactory $exportEntityFactory + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { $this->fileFactory = $fileFactory; - $this->moveToArchive = $moveToArchive; - $this->exportManagement = $exportManagement; - $this->exportEntityFactory = $exportEntityFactory; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function executeAction() { + $customerId = (int) $this->getRequest()->getParam('id'); + + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => $customerId, + ArgumentReader::ENTITY_TYPE => 'customer' + ]); + try { - $customerId = (int) $this->getRequest()->getParam('id'); - $fileName = $this->exportManagement->export($this->exportEntityFactory->create($customerId)); - $archiveFileName = 'customer_privacy_data_' . $customerId . '.zip'; + $result = $this->action->execute($this->actionContextBuilder->create())->getResult(); + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $result[ExportArgumentReader::EXPORT_ENTITY]; return $this->fileFactory->create( - $archiveFileName, + 'customer_privacy_data_' . $customerId . '.zip', [ 'type' => 'filename', - 'value' => $this->moveToArchive->prepareArchive($fileName, $archiveFileName), + 'value' => $exportEntity->getFilePath(), 'rm' => true, ], DirectoryList::TMP @@ -94,7 +83,7 @@ protected function executeAction() $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.')); } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setRefererOrBaseUrl(); diff --git a/Controller/Adminhtml/Privacy/MassErase.php b/Controller/Adminhtml/Privacy/MassErase.php index 73a46a9..8284dcc 100644 --- a/Controller/Adminhtml/Privacy/MassErase.php +++ b/Controller/Adminhtml/Privacy/MassErase.php @@ -8,6 +8,7 @@ namespace Opengento\Gdpr\Controller\Adminhtml\Privacy; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; use Magento\Customer\Controller\Adminhtml\Index\AbstractMassAction; use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory; use Magento\Eav\Model\Entity\Collection\AbstractCollection; @@ -15,47 +16,48 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Ui\Component\MassAction\Filter; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; -/** - * Class MassErase - */ class MassErase extends AbstractMassAction { public const ADMIN_RESOURCE = 'Opengento_Gdpr::customer_erase'; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Ui\Component\MassAction\Filter $filter - * @param \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $collectionFactory - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Filter $filter, CollectionFactory $collectionFactory, - EraseEntityManagementInterface $eraseEntityManagement + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { - $this->eraseEntityManagement = $eraseEntityManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $filter, $collectionFactory); } - /** - * @inheritdoc - */ protected function massAction(AbstractCollection $collection) { $customerErased = 0; foreach ($collection->getAllIds() as $customerId) { + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $customerId, + ArgumentReader::ENTITY_TYPE => 'customer' + ]); + try { - // todo disable individual check: use mass validator - $this->eraseEntityManagement->process($this->eraseEntityManagement->create((int) $customerId, 'customer')); + $this->action->execute($this->actionContextBuilder->create()); $customerErased++; } catch (LocalizedException $e) { $this->messageManager->addErrorMessage( @@ -72,7 +74,7 @@ protected function massAction(AbstractCollection $collection) ); } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setPath('customer/index/index'); diff --git a/Controller/Adminhtml/Privacy/MassExport.php b/Controller/Adminhtml/Privacy/MassExport.php index a1db7df..08114b1 100644 --- a/Controller/Adminhtml/Privacy/MassExport.php +++ b/Controller/Adminhtml/Privacy/MassExport.php @@ -8,6 +8,7 @@ namespace Opengento\Gdpr\Controller\Adminhtml\Privacy; use Magento\Backend\App\Action\Context; +use Magento\Backend\Model\View\Result\Redirect; use Magento\Customer\Controller\Adminhtml\Index\AbstractMassAction; use Magento\Customer\Model\ResourceModel\Customer\CollectionFactory; use Magento\Eav\Model\Entity\Collection\AbstractCollection; @@ -17,78 +18,67 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Ui\Component\MassAction\Filter; -use Opengento\Gdpr\Api\ExportEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; +use Opengento\Gdpr\Api\Data\ExportEntityInterface; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; +use Opengento\Gdpr\Model\Action\Export\ArgumentReader as ExportArgumentReader; use Opengento\Gdpr\Model\Archive\MoveToArchive; -use Opengento\Gdpr\Model\Export\ExportEntityFactory; -/** - * Class MassExport - */ class MassExport extends AbstractMassAction { public const ADMIN_RESOURCE = 'Opengento_Gdpr::customer_export'; /** - * @var \Magento\Framework\App\Response\Http\FileFactory + * @var FileFactory */ private $fileFactory; /** - * @var \Opengento\Gdpr\Model\Archive\MoveToArchive + * @var MoveToArchive */ private $moveToArchive; /** - * @var \Opengento\Gdpr\Api\ExportEntityManagementInterface + * @var ActionInterface */ - private $exportManagement; + private $action; /** - * @var \Opengento\Gdpr\Model\Export\ExportEntityFactory + * @var ContextBuilder */ - private $exportEntityFactory; + private $actionContextBuilder; - /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Ui\Component\MassAction\Filter $filter - * @param \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $collectionFactory - * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory - * @param \Opengento\Gdpr\Model\Archive\MoveToArchive $moveToArchive - * @param \Opengento\Gdpr\Api\ExportEntityManagementInterface $exportManagement - * @param \Opengento\Gdpr\Model\Export\ExportEntityFactory $exportEntityFactory - */ public function __construct( Context $context, Filter $filter, CollectionFactory $collectionFactory, FileFactory $fileFactory, MoveToArchive $moveToArchive, - ExportEntityManagementInterface $exportManagement, - ExportEntityFactory $exportEntityFactory + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { $this->fileFactory = $fileFactory; $this->moveToArchive = $moveToArchive; - $this->exportManagement = $exportManagement; - $this->exportEntityFactory = $exportEntityFactory; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $filter, $collectionFactory); } - /** - * @inheritdoc - */ protected function massAction(AbstractCollection $collection) { $archiveFileName = 'customers_privacy_data.zip'; try { foreach ($collection->getAllIds() as $customerId) { - $this->moveToArchive->prepareArchive( - $this->moveToArchive->prepareArchive( - $this->exportManagement->export($this->exportEntityFactory->create((int) $customerId)), - 'customer_privacy_data_' . $customerId . '.zip' - ), - $archiveFileName - ); + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $customerId, + ArgumentReader::ENTITY_TYPE => 'customer' + ]); + $result = $this->action->execute($this->actionContextBuilder->create())->getResult(); + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $result[ExportArgumentReader::EXPORT_ENTITY]; + $this->moveToArchive->prepareArchive($exportEntity->getFilePath(), $archiveFileName); } return $this->fileFactory->create( @@ -108,7 +98,7 @@ protected function massAction(AbstractCollection $collection) $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.')); } - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); return $resultRedirect->setPath('customer/index/index'); diff --git a/Controller/Guest/Download.php b/Controller/Guest/Download.php new file mode 100755 index 0000000..7fb712c --- /dev/null +++ b/Controller/Guest/Download.php @@ -0,0 +1,86 @@ +fileFactory = $fileFactory; + $this->exportRepository = $exportRepository; + parent::__construct($context, $config, $orderLoader, $registry); + } + + protected function isAllowed(): bool + { + return parent::isAllowed() && $this->config->isExportEnabled(); + } + + protected function executeAction() + { + try { + /** @var OrderInterface $order */ + $order = $this->registry->registry('current_order'); + + return $this->fileFactory->create( + 'customer_privacy_data_' . $order->getCustomerLastname() . '.zip', + [ + 'type' => 'filename', + 'value' => $this->exportRepository->getByEntity((int) $order->getEntityId(), 'order')->getFilePath(), + 'rm' => true, + ], + DirectoryList::TMP + ); + } catch (NoSuchEntityException $e) { + $this->messageManager->addErrorMessage( + new Phrase('The document does not exists and may have expired. Please renew your demand.') + ); + } catch (LocalizedException $e) { + $this->messageManager->addErrorMessage($e->getMessage()); + } catch (\Exception $e) { + $this->messageManager->addExceptionMessage($e, new Phrase('Something went wrong, please try again later!')); + } + + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + + return $resultRedirect->setRefererOrBaseUrl(); + } +} diff --git a/Controller/Guest/Erase.php b/Controller/Guest/Erase.php index c69d1ab..2c3a22b 100644 --- a/Controller/Guest/Erase.php +++ b/Controller/Guest/Erase.php @@ -8,62 +8,62 @@ namespace Opengento\Gdpr\Controller\Guest; use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\Registry; use Magento\Sales\Controller\AbstractController\OrderLoaderInterface; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\AbstractGuest; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -/** - * Class Erase - */ -class Erase extends AbstractGuest +class Erase extends AbstractGuest implements HttpGetActionInterface //todo should be post action { /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Sales\Controller\AbstractController\OrderLoaderInterface $orderLoader - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement - * @param \Magento\Framework\Registry $registry + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Config $config, OrderLoaderInterface $orderLoader, - EraseEntityManagementInterface $eraseEntityManagement, - Registry $registry + Registry $registry, + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { - $this->eraseEntityManagement = $eraseEntityManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config, $orderLoader, $registry); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isErasureEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $resultRedirect->setRefererOrBaseUrl(); + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->currentOrder()->getEntityId(), + ArgumentReader::ENTITY_TYPE => 'order' + ]); + try { - $this->eraseEntityManagement->create($this->retrieveOrderId(), 'order'); + $this->action->execute($this->actionContextBuilder->create()); $this->messageManager->addWarningMessage(new Phrase('Your personal data is being removed soon.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); diff --git a/Controller/Guest/Export.php b/Controller/Guest/Export.php index a1de941..b3fb490 100755 --- a/Controller/Guest/Export.php +++ b/Controller/Guest/Export.php @@ -8,108 +8,72 @@ namespace Opengento\Gdpr\Controller\Guest; use Magento\Framework\App\Action\Context; -use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\App\Response\Http\FileFactory; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\Registry; use Magento\Sales\Controller\AbstractController\OrderLoaderInterface; -use Opengento\Gdpr\Api\ExportEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\AbstractGuest; -use Opengento\Gdpr\Model\Archive\MoveToArchive; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -use Opengento\Gdpr\Model\Export\ExportEntityFactory; -/** - * Class Export - */ -class Export extends AbstractGuest +class Export extends AbstractGuest implements HttpGetActionInterface { /** - * @var \Magento\Framework\App\Response\Http\FileFactory - */ - private $fileFactory; - - /** - * @var \Opengento\Gdpr\Model\Archive\MoveToArchive + * @var ActionInterface */ - private $moveToArchive; + private $action; /** - * @var \Opengento\Gdpr\Api\ExportEntityManagementInterface + * @var ContextBuilder */ - private $exportManagement; + private $actionContextBuilder; - /** - * @var \Opengento\Gdpr\Model\Export\ExportEntityFactory - */ - private $exportEntityFactory; - - /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory - * @param \Opengento\Gdpr\Model\Archive\MoveToArchive $moveToArchive - * @param \Opengento\Gdpr\Api\ExportEntityManagementInterface $exportManagement - * @param \Opengento\Gdpr\Model\Export\ExportEntityFactory $exportEntityFactory - * @param \Magento\Sales\Controller\AbstractController\OrderLoaderInterface $orderLoader - * @param \Magento\Framework\Registry $registry - */ public function __construct( Context $context, Config $config, - FileFactory $fileFactory, - MoveToArchive $moveToArchive, - ExportEntityManagementInterface $exportManagement, - ExportEntityFactory $exportEntityFactory, OrderLoaderInterface $orderLoader, - Registry $registry + Registry $registry, + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { - $this->fileFactory = $fileFactory; - $this->moveToArchive = $moveToArchive; - $this->exportManagement = $exportManagement; - $this->exportEntityFactory = $exportEntityFactory; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config, $orderLoader, $registry); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isExportEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { - try { - /** @var \Magento\Sales\Api\Data\OrderInterface $order */ - $order = $this->registry->registry('current_order'); - $fileName = $this->exportManagement->export($this->exportEntityFactory->create($this->retrieveOrderId())); - $archiveFileName = 'customer_privacy_data_' . $order->getCustomerLastname() . '.zip'; + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setRefererOrBaseUrl(); + + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->currentOrder()->getCustomerId(), + ArgumentReader::ENTITY_TYPE => 'order' + ]); - return $this->fileFactory->create( - $archiveFileName, - [ - 'type' => 'filename', - 'value' => $this->moveToArchive->prepareArchive($fileName, $archiveFileName), - 'rm' => true, - ], - DirectoryList::TMP - ); + try { + $this->action->execute($this->actionContextBuilder->create()); + $this->messageManager->addSuccessMessage(new Phrase('You will be notified when the export is ready.')); + } catch (AlreadyExistsException $e) { + $this->messageManager->addNoticeMessage(new Phrase('A document is already available in your order page.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, new Phrase('Something went wrong, please try again later!')); } - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ - $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - - return $resultRedirect->setRefererOrBaseUrl(); + return $resultRedirect; } } diff --git a/Controller/Guest/UndoErase.php b/Controller/Guest/UndoErase.php index c373b49..3ef62c7 100644 --- a/Controller/Guest/UndoErase.php +++ b/Controller/Guest/UndoErase.php @@ -8,62 +8,62 @@ namespace Opengento\Gdpr\Controller\Guest; use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\Registry; use Magento\Sales\Controller\AbstractController\OrderLoaderInterface; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\AbstractGuest; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -/** - * Class UndoErase - */ -class UndoErase extends AbstractGuest +class UndoErase extends AbstractGuest implements HttpGetActionInterface //todo should be post action { /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Sales\Controller\AbstractController\OrderLoaderInterface $orderLoader - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement - * @param \Magento\Framework\Registry $registry + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Config $config, OrderLoaderInterface $orderLoader, - EraseEntityManagementInterface $eraseEntityManagement, - Registry $registry + Registry $registry, + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { - $this->eraseEntityManagement = $eraseEntityManagement; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config, $orderLoader, $registry); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isErasureEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $resultRedirect->setRefererOrBaseUrl(); + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->currentOrder()->getEntityId(), + ArgumentReader::ENTITY_TYPE => 'order' + ]); + try { - $this->eraseEntityManagement->cancel($this->retrieveOrderId(), 'order'); + $this->action->execute($this->actionContextBuilder->create()); $this->messageManager->addWarningMessage(new Phrase('You canceled your personal data deletion.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); diff --git a/Controller/Privacy/Download.php b/Controller/Privacy/Download.php new file mode 100755 index 0000000..734216a --- /dev/null +++ b/Controller/Privacy/Download.php @@ -0,0 +1,88 @@ +fileFactory = $fileFactory; + $this->exportRepository = $exportRepository; + $this->customerSession = $customerSession; + parent::__construct($context, $config); + } + + protected function isAllowed(): bool + { + return parent::isAllowed() && $this->config->isExportEnabled(); + } + + protected function executeAction() + { + try { + $customerId = (int) $this->customerSession->getCustomerId(); + + return $this->fileFactory->create( + 'customer_privacy_data_' . $customerId . '.zip', + [ + 'type' => 'filename', + 'value' => $this->exportRepository->getByEntity($customerId, 'customer')->getFilePath(), + 'rm' => true, + ], + DirectoryList::TMP + ); + } catch (NoSuchEntityException $e) { + $this->messageManager->addErrorMessage( + new Phrase('The document does not exists and may have expired. Please renew your demand.') + ); + } catch (LocalizedException $e) { + $this->messageManager->addErrorMessage($e->getMessage()); + } catch (\Exception $e) { + $this->messageManager->addExceptionMessage($e, new Phrase('Something went wrong, please try again later!')); + } + + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + + return $resultRedirect->setRefererOrBaseUrl(); + } +} diff --git a/Controller/Privacy/Erase.php b/Controller/Privacy/Erase.php index 8b331a4..11be597 100755 --- a/Controller/Privacy/Erase.php +++ b/Controller/Privacy/Erase.php @@ -9,6 +9,7 @@ use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Phrase; @@ -16,27 +17,18 @@ use Opengento\Gdpr\Controller\AbstractPrivacy; use Opengento\Gdpr\Model\Config; -/** - * Action Index Erase - */ class Erase extends AbstractPrivacy implements HttpGetActionInterface { /** - * @var \Magento\Customer\Model\Session + * @var Session */ private $session; /** - * @var \Opengento\Gdpr\Api\EraseEntityCheckerInterface + * @var EraseEntityCheckerInterface */ private $eraseCustomerChecker; - /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Customer\Model\Session $session - * @param \Opengento\Gdpr\Api\EraseEntityCheckerInterface $eraseCustomerChecker - */ public function __construct( Context $context, Config $config, @@ -48,22 +40,16 @@ public function __construct( parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isErasureEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { if ($this->eraseCustomerChecker->exists((int) $this->session->getCustomerId(), 'customer')) { $this->messageManager->addErrorMessage(new Phrase('Your account is already being removed.')); - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $resultRedirect->setRefererOrBaseUrl(); diff --git a/Controller/Privacy/ErasePost.php b/Controller/Privacy/ErasePost.php index e39e155..811f017 100755 --- a/Controller/Privacy/ErasePost.php +++ b/Controller/Privacy/ErasePost.php @@ -11,83 +11,82 @@ use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context; use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\InvalidEmailOrPasswordException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\State\UserLockedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\AbstractPrivacy; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -/** - * Class ErasePost - */ class ErasePost extends AbstractPrivacy implements HttpPostActionInterface { /** - * @var \Magento\Customer\Model\AuthenticationInterface + * @var AuthenticationInterface */ private $authentication; /** - * @var \Magento\Customer\Model\Session + * @var Session */ - private $session; + private $customerSession; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Customer\Model\AuthenticationInterface $authentication - * @param \Magento\Customer\Model\Session $session - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Config $config, AuthenticationInterface $authentication, - Session $session, - EraseEntityManagementInterface $eraseEntityManagement + Session $customerSession, + ActionInterface $action, + ContextBuilder $actionContextBuilder ) { $this->authentication = $authentication; - $this->session = $session; - $this->eraseEntityManagement = $eraseEntityManagement; + $this->customerSession = $customerSession; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isErasureEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); $resultRedirect->setPath('customer/privacy/settings'); + $customerId = (int) $this->customerSession->getCustomerId(); + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => $customerId, + ArgumentReader::ENTITY_TYPE => 'customer' + ]); + try { - $customerId = (int) $this->session->getCustomerId(); $this->authentication->authenticate($customerId, $this->getRequest()->getParam('password')); - $this->eraseEntityManagement->create($customerId, 'customer'); + $this->action->execute($this->actionContextBuilder->create()); $this->messageManager->addWarningMessage(new Phrase('Your personal data is being removed soon.')); } catch (InvalidEmailOrPasswordException $e) { $this->messageManager->addErrorMessage($e->getMessage()); $resultRedirect->setRefererOrBaseUrl(); } catch (UserLockedException $e) { - $this->session->logout(); - $this->session->start(); + $this->customerSession->logout(); + $this->customerSession->start(); $this->messageManager->addErrorMessage( new Phrase('You did not sign in correctly or your account is temporarily disabled.') ); diff --git a/Controller/Privacy/Export.php b/Controller/Privacy/Export.php index f8e94fb..5a617a2 100755 --- a/Controller/Privacy/Export.php +++ b/Controller/Privacy/Export.php @@ -10,109 +10,74 @@ use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context; use Magento\Framework\App\Action\HttpGetActionInterface; -use Magento\Framework\App\Filesystem\DirectoryList; -use Magento\Framework\App\Response\Http\FileFactory; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; +use Magento\Framework\Exception\AlreadyExistsException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\ExportEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\AbstractPrivacy; -use Opengento\Gdpr\Model\Archive\MoveToArchive; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -use Opengento\Gdpr\Model\Export\ExportEntityFactory; -/** - * Action Export Export - */ class Export extends AbstractPrivacy implements HttpGetActionInterface { /** - * @var \Magento\Framework\App\Response\Http\FileFactory - */ - private $fileFactory; - - /** - * @var \Opengento\Gdpr\Model\Archive\MoveToArchive + * @var ActionInterface */ - private $moveToArchive; + private $action; /** - * @var \Opengento\Gdpr\Api\ExportEntityManagementInterface + * @var ContextBuilder */ - private $exportManagement; + private $actionContextBuilder; /** - * @var \Opengento\Gdpr\Model\Export\ExportEntityFactory - */ - private $exportEntityFactory; - - /** - * @var \Magento\Customer\Model\Session + * @var Session */ private $customerSession; - /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory - * @param \Opengento\Gdpr\Model\Archive\MoveToArchive $moveToArchive - * @param \Opengento\Gdpr\Api\ExportEntityManagementInterface $exportManagement - * @param \Opengento\Gdpr\Model\Export\ExportEntityFactory $exportEntityFactory - * @param \Magento\Customer\Model\Session $customerSession - */ public function __construct( Context $context, Config $config, - FileFactory $fileFactory, - MoveToArchive $moveToArchive, - ExportEntityManagementInterface $exportManagement, - ExportEntityFactory $exportEntityFactory, + ActionInterface $action, + ContextBuilder $actionContextBuilder, Session $customerSession ) { - $this->fileFactory = $fileFactory; - $this->moveToArchive = $moveToArchive; - $this->exportManagement = $exportManagement; - $this->exportEntityFactory = $exportEntityFactory; + $this->action = $action; + $this->actionContextBuilder = $actionContextBuilder; $this->customerSession = $customerSession; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isExportEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { - try { - $customerId = (int) $this->customerSession->getCustomerId(); - $fileName = $this->exportManagement->export($this->exportEntityFactory->create($customerId)); - $archiveFileName = 'customer_privacy_data_' . $customerId . '.zip'; + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setRefererOrBaseUrl(); + + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->customerSession->getCustomerId(), + ArgumentReader::ENTITY_TYPE => 'customer' + ]); - return $this->fileFactory->create( - $archiveFileName, - [ - 'type' => 'filename', - 'value' => $this->moveToArchive->prepareArchive($fileName, $archiveFileName), - 'rm' => true, - ], - DirectoryList::TMP - ); + try { + $this->action->execute($this->actionContextBuilder->create()); + $this->messageManager->addSuccessMessage(new Phrase('You will be notified when the export is ready.')); + } catch (AlreadyExistsException $e) { + $this->messageManager->addNoticeMessage(new Phrase('A document is already available in your account.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); } catch (\Exception $e) { $this->messageManager->addExceptionMessage($e, new Phrase('Something went wrong, please try again later!')); } - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ - $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); - - return $resultRedirect->setRefererOrBaseUrl(); + return $resultRedirect; } } diff --git a/Controller/Privacy/Settings.php b/Controller/Privacy/Settings.php index f72f138..8938c30 100755 --- a/Controller/Privacy/Settings.php +++ b/Controller/Privacy/Settings.php @@ -11,14 +11,8 @@ use Magento\Framework\Controller\ResultFactory; use Opengento\Gdpr\Controller\AbstractPrivacy; -/** - * Action Index Settings - */ class Settings extends AbstractPrivacy implements HttpGetActionInterface { - /** - * @inheritdoc - */ protected function executeAction() { return $this->resultFactory->create(ResultFactory::TYPE_PAGE); diff --git a/Controller/Privacy/UndoErase.php b/Controller/Privacy/UndoErase.php index 53e6fe2..f827618 100755 --- a/Controller/Privacy/UndoErase.php +++ b/Controller/Privacy/UndoErase.php @@ -10,63 +10,62 @@ use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context; use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\Controller\Result\Redirect; use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; -use Opengento\Gdpr\Api\EraseEntityManagementInterface; +use Opengento\Gdpr\Api\ActionInterface; use Opengento\Gdpr\Controller\AbstractPrivacy; +use Opengento\Gdpr\Model\Action\ArgumentReader; +use Opengento\Gdpr\Model\Action\ContextBuilder; use Opengento\Gdpr\Model\Config; -/** - * Action Undo Erase - */ -class UndoErase extends AbstractPrivacy implements HttpGetActionInterface +class UndoErase extends AbstractPrivacy implements HttpGetActionInterface //todo should be post action { /** - * @var \Magento\Customer\Model\Session + * @var Session */ - private $session; + private $customerSession; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var ActionInterface */ - private $eraseEntityManagement; + private $action; /** - * @param \Magento\Framework\App\Action\Context $context - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Customer\Model\Session $session - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement + * @var ContextBuilder */ + private $actionContextBuilder; + public function __construct( Context $context, Config $config, - Session $session, - EraseEntityManagementInterface $eraseEntityManagement + Session $customerSession, + ActionInterface $action ) { - $this->session = $session; - $this->eraseEntityManagement = $eraseEntityManagement; + $this->customerSession = $customerSession; + $this->action = $action; parent::__construct($context, $config); } - /** - * @inheritdoc - */ protected function isAllowed(): bool { return parent::isAllowed() && $this->config->isErasureEnabled(); } - /** - * @inheritdoc - */ protected function executeAction() { - /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ + /** @var Redirect $resultRedirect */ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + $resultRedirect->setPath('customer/privacy/settings'); + + $this->actionContextBuilder->setParameters([ + ArgumentReader::ENTITY_ID => (int) $this->customerSession->getCustomerId(), + ArgumentReader::ENTITY_TYPE => 'customer' + ]); try { - $this->eraseEntityManagement->cancel((int) $this->session->getCustomerId(), 'customer'); + $this->action->execute($this->actionContextBuilder->create()); $this->messageManager->addSuccessMessage(new Phrase('You canceled your account deletion.')); } catch (LocalizedException $e) { $this->messageManager->addErrorMessage($e->getMessage()); @@ -74,6 +73,6 @@ protected function executeAction() $this->messageManager->addExceptionMessage($e, new Phrase('Something went wrong, please try again later!')); } - return $resultRedirect->setPath('customer/privacy/settings'); + return $resultRedirect; } } diff --git a/Cron/EraseEntity.php b/Cron/EraseEntity.php index 609009b..635564d 100755 --- a/Cron/EraseEntity.php +++ b/Cron/EraseEntity.php @@ -8,70 +8,61 @@ namespace Opengento\Gdpr\Cron; use Magento\Framework\Api\SearchCriteriaBuilder; -use Magento\Framework\Api\SearchResultsInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Registry; use Magento\Framework\Stdlib\DateTime\DateTime; use Opengento\Gdpr\Api\Data\EraseEntityInterface; +use Opengento\Gdpr\Api\Data\EraseEntitySearchResultsInterface; use Opengento\Gdpr\Api\EraseEntityManagementInterface; use Opengento\Gdpr\Api\EraseEntityRepositoryInterface; use Opengento\Gdpr\Model\Config; use Psr\Log\LoggerInterface; /** - * Class EraseEntity + * Process erase of all scheduled entities */ final class EraseEntity { /** - * @var \Psr\Log\LoggerInterface + * @var LoggerInterface */ private $logger; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; /** - * @var \Magento\Framework\Registry + * @var Registry */ private $registry; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var EraseEntityManagementInterface */ - private $eraseEntityManagement; + private $eraseManagement; /** - * @var \Opengento\Gdpr\Api\EraseEntityRepositoryInterface + * @var EraseEntityRepositoryInterface */ private $eraseEntityRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** - * @var \Magento\Framework\Stdlib\DateTime\DateTime + * @var DateTime */ private $dateTime; - /** - * @param \Psr\Log\LoggerInterface $logger - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Framework\Registry $registry - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement - * @param \Opengento\Gdpr\Api\EraseEntityRepositoryInterface $eraseEntityRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Magento\Framework\Stdlib\DateTime\DateTime $dateTime - */ public function __construct( LoggerInterface $logger, Config $config, Registry $registry, - EraseEntityManagementInterface $eraseEntityManagement, + EraseEntityManagementInterface $eraseManagement, EraseEntityRepositoryInterface $eraseEntityRepository, SearchCriteriaBuilder $searchCriteriaBuilder, DateTime $dateTime @@ -79,30 +70,23 @@ public function __construct( $this->logger = $logger; $this->config = $config; $this->registry = $registry; - $this->eraseEntityManagement = $eraseEntityManagement; + $this->eraseManagement = $eraseManagement; $this->eraseEntityRepository = $eraseEntityRepository; $this->searchCriteriaBuilder = $searchCriteriaBuilder; $this->dateTime = $dateTime; } - /** - * Process erase of all scheduled entities - * - * @return void - */ public function execute(): void { if ($this->config->isModuleEnabled() && $this->config->isErasureEnabled()) { $oldValue = $this->registry->registry('isSecureArea'); $this->registry->register('isSecureArea', true, true); - /** @var \Opengento\Gdpr\Api\Data\EraseEntityInterface $eraseEntity */ foreach ($this->retrieveEraseEntityList()->getItems() as $eraseEntity) { try { - // todo disable individual check: use mass validator - $this->eraseEntityManagement->process($eraseEntity); + $this->eraseManagement->process($eraseEntity); } catch (\Exception $e) { - $this->logger->error($e->getMessage()); + $this->logger->error($e->getMessage(), $e->getTrace()); } } @@ -110,12 +94,7 @@ public function execute(): void } } - /** - * Retrieve erase entity scheduler list - * - * @return \Magento\Framework\Api\SearchResultsInterface - */ - private function retrieveEraseEntityList(): SearchResultsInterface + private function retrieveEraseEntityList(): EraseEntitySearchResultsInterface { $this->searchCriteriaBuilder->addFilter( EraseEntityInterface::SCHEDULED_AT, diff --git a/Cron/EraseEntityScheduler.php b/Cron/EraseEntityScheduler.php index 30810e5..8557111 100644 --- a/Cron/EraseEntityScheduler.php +++ b/Cron/EraseEntityScheduler.php @@ -7,33 +7,35 @@ namespace Opengento\Gdpr\Cron; +use DateTime; +use Exception; use Magento\Framework\Api\FilterBuilder; use Opengento\Gdpr\Model\Config; use Opengento\Gdpr\Model\Erase\EraseEntityScheduler as EraseEntitySchedulerService; use Psr\Log\LoggerInterface; /** - * Class EraseEntityScheduler + * Schedule entities to erase */ final class EraseEntityScheduler { /** - * @var \Psr\Log\LoggerInterface + * @var LoggerInterface */ private $logger; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; /** - * @var \Opengento\Gdpr\Model\Erase\EraseEntityScheduler + * @var EraseEntitySchedulerService */ private $eraseEntityScheduler; /** - * @var \Magento\Framework\Api\FilterBuilder + * @var FilterBuilder */ private $filterBuilder; @@ -43,10 +45,10 @@ final class EraseEntityScheduler private $entityTypes; /** - * @param \Psr\Log\LoggerInterface $logger - * @param \Opengento\Gdpr\Model\Config $config - * @param \Opengento\Gdpr\Model\Erase\EraseEntityScheduler $eraseEntityScheduler - * @param \Magento\Framework\Api\FilterBuilder $filterBuilder + * @param LoggerInterface $logger + * @param Config $config + * @param EraseEntitySchedulerService $eraseEntityScheduler + * @param FilterBuilder $filterBuilder * @param string[] $entityTypes */ public function __construct( @@ -63,22 +65,16 @@ public function __construct( $this->entityTypes = $entityTypes; } - /** - * Schedule entities to erase - * - * @return void - */ public function execute(): void { if ($this->config->isModuleEnabled() && $this->config->isErasureEnabled()) { try { $this->filterBuilder->setField('created_at'); - $this->filterBuilder->setValue(new \DateTime('-' . $this->config->getErasureMaxAge() . 'days')); + $this->filterBuilder->setValue(new DateTime('-' . $this->config->getErasureMaxAge() . 'days')); $this->filterBuilder->setConditionType('lteq'); - // todo disable individual check: use mass validator $this->eraseEntityScheduler->schedule($this->entityTypes, $this->filterBuilder->create()); - } catch (\Exception $e) { - $this->logger->error($e->getMessage()); + } catch (Exception $e) { + $this->logger->error($e->getMessage(), $e->getTrace()); } } } diff --git a/Cron/ExportEntity.php b/Cron/ExportEntity.php new file mode 100644 index 0000000..c0d4e02 --- /dev/null +++ b/Cron/ExportEntity.php @@ -0,0 +1,79 @@ +logger = $logger; + $this->config = $config; + $this->exportEntityRepository = $exportEntityRepository; + $this->exportEntityManagement = $exportEntityManagement; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + } + + public function execute(): void + { + if ($this->config->isModuleEnabled() && $this->config->isExportEnabled()) { + $this->searchCriteriaBuilder->addFilter(ExportEntityInterface::EXPORTED_AT, true, 'null'); + $this->searchCriteriaBuilder->addFilter(ExportEntityInterface::FILE_PATH, true, 'null'); + + try { + $exportList = $this->exportEntityRepository->getList($this->searchCriteriaBuilder->create()); + + foreach ($exportList->getItems() as $exportEntity) { + $this->exportEntityManagement->export($exportEntity); + } + } catch (Exception $e) { + $this->logger->error($e->getMessage(), $e->getTrace()); + } + } + } +} diff --git a/Cron/ExportEntityExpired.php b/Cron/ExportEntityExpired.php new file mode 100644 index 0000000..52eb305 --- /dev/null +++ b/Cron/ExportEntityExpired.php @@ -0,0 +1,75 @@ +logger = $logger; + $this->config = $config; + $this->exportEntityRepository = $exportEntityRepository; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + } + + public function execute(): void + { + if ($this->config->isModuleEnabled() && $this->config->isExportEnabled()) { + $this->searchCriteriaBuilder->addFilter( + ExportEntityInterface::EXPIRED_AT, + (new \DateTime())->format(DateTime::DATE_PHP_FORMAT), + 'lteq' + ); + + try { + $exportList = $this->exportEntityRepository->getList($this->searchCriteriaBuilder->create()); + + foreach ($exportList->getItems() as $exportEntity) { + $this->exportEntityRepository->delete($exportEntity); + } + } catch (Exception $e) { + $this->logger->error($e->getMessage(), $e->getTrace()); + } + } + } +} diff --git a/Model/AbstractConsent.php b/Model/AbstractConsent.php new file mode 100644 index 0000000..9935187 --- /dev/null +++ b/Model/AbstractConsent.php @@ -0,0 +1,64 @@ +_getData(self::ID); + } + + public function setConsentId(int $consentId): ConsentInterface + { + return $this->setData(self::ID, $consentId); + } + + public function getAgreementIdentifier(): string + { + return (string) $this->_getData(self::AGREEMENT_IDENTIFIER); + } + + public function setAgreementIdentifier(string $agreementIdentifier): ConsentInterface + { + return $this->setData(self::AGREEMENT_IDENTIFIER, $agreementIdentifier); + } + + public function isApproved(): bool + { + return (bool) $this->_getData(self::IS_APPROVED); + } + + public function setIsApproved(bool $isApproved): ConsentInterface + { + return $this->setData(self::IS_APPROVED, $isApproved); + } + + public function isOutDated(): bool + { + return (bool) $this->_getData(self::IS_OUTDATED); + } + + public function setIsOutDated(bool $isOutDated): ConsentInterface + { + return $this->setData(self::IS_OUTDATED, $isOutDated); + } + + public function getSubmittedAt(): string + { + return (string) $this->_getData(self::SUBMITTED_AT); + } + + public function setSubmittedAt(string $submittedAt): ConsentInterface + { + return $this->setData(self::SUBMITTED_AT, $submittedAt); + } +} diff --git a/Model/Action/AbstractAction.php b/Model/Action/AbstractAction.php new file mode 100644 index 0000000..15650ea --- /dev/null +++ b/Model/Action/AbstractAction.php @@ -0,0 +1,36 @@ +resultBuilder = $resultBuilder; + } + + protected function createActionResult(array $result = []): ActionResultInterface + { + $this->resultBuilder->setState(ActionEntityInterface::STATE_SUCCEEDED); + $this->resultBuilder->setPerformedAt(new DateTime()); + $this->resultBuilder->setResult($result); + + return $this->resultBuilder->create(); + } +} diff --git a/Model/Action/ActionComposite.php b/Model/Action/ActionComposite.php new file mode 100644 index 0000000..b9e0c92 --- /dev/null +++ b/Model/Action/ActionComposite.php @@ -0,0 +1,132 @@ +type = $type; + $this->actions = (static function (ActionInterface ...$actions): array { + return $actions; + })(...array_values($actions)); + $this->contextBuilder = $contextBuilder; + $this->actionEntityBuilder = $actionEntityBuilder; + $this->resultBuilder = $resultBuilder; + $this->actionEntityRepository = $actionEntityRepository; + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $this->actionEntityBuilder->setType($this->type); + $this->actionEntityBuilder->setParameters($actionContext->getParameters()); + $this->actionEntityBuilder->setPerformedFrom($actionContext->getPerformedFrom()); + $this->actionEntityBuilder->setPerformedBy($actionContext->getPerformedBy()); + $this->actionEntityBuilder->setPerformedAt(new DateTime()); + + try { + $this->actionEntityBuilder->setState(ActionEntityInterface::STATE_SUCCEEDED); + $this->actionEntityBuilder->setResult($this->process($actionContext)); + } catch (LocalizedException $e) { + $this->actionEntityBuilder->setState(ActionEntityInterface::STATE_FAILED); + $this->actionEntityBuilder->setMessage($e->getMessage()); + } + + $result = $this->result($this->actionEntityRepository->save($this->actionEntityBuilder->create())); + + if (isset($e)) { + throw $e; + } + + return $result; + } + + /** + * @param ActionContextInterface $actionContext + * @return array + * @throws LocalizedException + */ + private function process(ActionContextInterface $actionContext): array + { + foreach ($this->actions as $action) { + $this->contextBuilder->setPerformedFrom($actionContext->getPerformedFrom()); + $this->contextBuilder->setPerformedBy($actionContext->getPerformedBy()); + $this->contextBuilder->setParameters( + array_merge($actionContext->getParameters(), $action->execute($actionContext)->getResult()) + ); + $actionContext = $this->contextBuilder->create(); + } + + return $actionContext->getParameters(); + } + + private function result(ActionEntityInterface $actionEntity): ActionResultInterface + { + $this->resultBuilder->setPerformedAt(new DateTime()); + $this->resultBuilder->setState($actionEntity->getState()); + $this->resultBuilder->setMessage($actionEntity->getMessage()); + $this->resultBuilder->setResult($actionEntity->getResult()); + + return $this->resultBuilder->create(); + } +} diff --git a/Model/Action/ActionFactory.php b/Model/Action/ActionFactory.php new file mode 100644 index 0000000..0562918 --- /dev/null +++ b/Model/Action/ActionFactory.php @@ -0,0 +1,56 @@ +actions = $actions; + $this->objectManager = $objectManager; + $this->instances = []; + } + + public function get(string $type): ActionInterface + { + if (!isset($this->instances[$type])) { + if (!isset($this->actions[$type])) { + throw new InvalidArgumentException(sprintf('Unknown action for type "%s".', $type)); + } + + $this->instances[$type] = $this->objectManager->create($this->actions[$type], ['type' => $type]); + } + + return $this->instances[$type]; + } +} diff --git a/Model/Action/ArgumentReader.php b/Model/Action/ArgumentReader.php new file mode 100644 index 0000000..653a5db --- /dev/null +++ b/Model/Action/ArgumentReader.php @@ -0,0 +1,26 @@ +getParameters()[self::ENTITY_TYPE] ?? null; + } + + public static function getEntityId(ActionContextInterface $actionContext): ?int + { + return $actionContext->getParameters()[self::ENTITY_ID] ?? null; + } +} diff --git a/Model/Action/Context.php b/Model/Action/Context.php new file mode 100644 index 0000000..874884d --- /dev/null +++ b/Model/Action/Context.php @@ -0,0 +1,53 @@ +performedFrom = $performedFrom; + $this->performedBy = $performedBy; + $this->parameters = $parameters; + } + + public function getPerformedFrom(): string + { + return $this->performedFrom; + } + + public function getPerformedBy(): string + { + return $this->performedBy; + } + + public function getParameters(): array + { + return $this->parameters; + } +} diff --git a/Model/Action/ContextBuilder.php b/Model/Action/ContextBuilder.php new file mode 100644 index 0000000..a08b34d --- /dev/null +++ b/Model/Action/ContextBuilder.php @@ -0,0 +1,90 @@ +actionContextFactory = $actionContextFactory; + $this->stateArea = $stateArea; + $this->performedBy = $performedBy; + $this->data = []; + } + + public function setPerformedFrom(string $performedFrom): ContextBuilder + { + $this->data['performedFrom'] = $performedFrom; + + return $this; + } + + public function setPerformedBy(string $performedBy): ContextBuilder + { + $this->data['performedBy'] = $performedBy; + + return $this; + } + + public function setParameters(array $parameters): ContextBuilder + { + $this->data['parameters'] = $parameters; + + return $this; + } + + /** + * @throws LocalizedException + */ + public function create(): ActionContextInterface + { + if (!isset($this->data['performedFrom'])) { + $this->data['performedFrom'] = $this->stateArea->getAreaCode(); + } + if (!isset($this->data['performedBy'])) { + $this->data['performedBy'] = $this->performedBy->get(); + } + + /** @var ActionContextInterface $context */ + $context = $this->actionContextFactory->create($this->data); + $this->data = []; + + return $context; + } +} diff --git a/Model/Action/Erase/ArgumentReader.php b/Model/Action/Erase/ArgumentReader.php new file mode 100644 index 0000000..1723d50 --- /dev/null +++ b/Model/Action/Erase/ArgumentReader.php @@ -0,0 +1,21 @@ +getParameters()[self::ERASE_ENTITY] ?? null; + } +} diff --git a/Model/Action/Erase/CancelAction.php b/Model/Action/Erase/CancelAction.php new file mode 100644 index 0000000..8356f76 --- /dev/null +++ b/Model/Action/Erase/CancelAction.php @@ -0,0 +1,46 @@ +eraseEntityManagement = $eraseEntityManagement; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $entityId = ArgumentReader::getEntityId($actionContext); + $entityType = ArgumentReader::getEntityType($actionContext); + + if ($entityId === null || $entityType === null) { + throw new InvalidArgumentException('Arguments "entity_id" and "entity_type" are required.'); + } + + return $this->createActionResult( + ['canceled' => $this->eraseEntityManagement->cancel($entityId, $entityType)] + ); + } +} diff --git a/Model/Action/Erase/CreateAction.php b/Model/Action/Erase/CreateAction.php new file mode 100644 index 0000000..6229da1 --- /dev/null +++ b/Model/Action/Erase/CreateAction.php @@ -0,0 +1,46 @@ +eraseEntityManagement = $eraseEntityManagement; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $entityId = ArgumentReader::getEntityId($actionContext); + $entityType = ArgumentReader::getEntityType($actionContext); + + if ($entityId === null || $entityType === null) { + throw new InvalidArgumentException('Arguments "entity_id" and "entity_type" are required.'); + } + + return $this->createActionResult( + [ArgumentReader::ENTITY_TYPE => $this->eraseEntityManagement->create($entityId, $entityType)] + ); + } +} diff --git a/Model/Action/Erase/ExecuteAction.php b/Model/Action/Erase/ExecuteAction.php new file mode 100644 index 0000000..e0fc57d --- /dev/null +++ b/Model/Action/Erase/ExecuteAction.php @@ -0,0 +1,44 @@ +eraseEntityManagement = $eraseEntityManagement; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $eraseEntity = ArgumentReader::getEntity($actionContext); + + if ($eraseEntity === null) { + throw new InvalidArgumentException('Argument "entity" is required.'); + } + + return $this->createActionResult( + [ArgumentReader::ERASE_ENTITY => $this->eraseEntityManagement->process($eraseEntity)] + ); + } +} diff --git a/Model/Action/Erase/NotifierActionBundle.php b/Model/Action/Erase/NotifierActionBundle.php new file mode 100644 index 0000000..9f3a09d --- /dev/null +++ b/Model/Action/Erase/NotifierActionBundle.php @@ -0,0 +1,59 @@ +notifiers = $notifiers; + $this->objectManager = $objectManager; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $this->resolveNotifier($actionContext)->notify(ArgumentReader::getEntity($actionContext)); + + return $this->createActionResult(['is_notify' => true]); + } + + private function resolveNotifier(ActionContextInterface $actionContext): NotifierInterface + { + $entityType = ActionArgumentReader::getEntityType($actionContext); + + if (!isset($this->notifiers[$entityType])) { + throw new InvalidArgumentException(sprintf('Unknown notifier for entity type "%s".', $entityType)); + } + + return $this->objectManager->get($this->notifiers[$entityType]); + } +} diff --git a/Model/Action/Export/ArgumentReader.php b/Model/Action/Export/ArgumentReader.php new file mode 100644 index 0000000..540c56b --- /dev/null +++ b/Model/Action/Export/ArgumentReader.php @@ -0,0 +1,27 @@ +getParameters()[self::EXPORT_ENTITY] ?? null; + } + + public static function getFileName(ActionContextInterface $actionContext): ?string + { + return $actionContext->getParameters()[self::EXPORT_FILE_NAME] ?? null; + } +} diff --git a/Model/Action/Export/CreateAction.php b/Model/Action/Export/CreateAction.php new file mode 100644 index 0000000..98db893 --- /dev/null +++ b/Model/Action/Export/CreateAction.php @@ -0,0 +1,53 @@ +exportEntityManagement = $exportEntityManagement; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $entityId = ArgumentReader::getEntityId($actionContext); + $entityType = ArgumentReader::getEntityType($actionContext); + + if ($entityId === null || $entityType === null) { + throw new InvalidArgumentException('Arguments "entity_id" and "entity_type" are required.'); + } + + return $this->createActionResult( + [ + ArgumentReader::ENTITY_TYPE => $this->exportEntityManagement->create( + $entityId, + $entityType, + ExportArgumentReader::getFileName($actionContext) + ) + ] + ); + } +} diff --git a/Model/Action/Export/CreateOrExportAction.php b/Model/Action/Export/CreateOrExportAction.php new file mode 100644 index 0000000..7fc3156 --- /dev/null +++ b/Model/Action/Export/CreateOrExportAction.php @@ -0,0 +1,47 @@ +exportEntityData = $exportEntityData; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $entityId = ArgumentReader::getEntityId($actionContext); + $entityType = ArgumentReader::getEntityType($actionContext); + + if ($entityId === null || $entityType === null) { + throw new InvalidArgumentException('Arguments "entity_id" and "entity_type" are required.'); + } + + return $this->createActionResult( + [ExportArgumentReader::EXPORT_ENTITY => $this->exportEntityData->export($entityId, $entityType)] + ); + } +} diff --git a/Model/Action/Export/ExportAction.php b/Model/Action/Export/ExportAction.php new file mode 100644 index 0000000..3a57021 --- /dev/null +++ b/Model/Action/Export/ExportAction.php @@ -0,0 +1,45 @@ +exportEntityManagement = $exportEntityManagement; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $exportEntity = ArgumentReader::getEntity($actionContext); + + if ($exportEntity === null) { + throw new InvalidArgumentException('Argument "entity" is required.'); + } + + return $this->createActionResult( + [ExportArgumentReader::EXPORT_ENTITY => $this->exportEntityManagement->export($exportEntity)] + ); + } +} diff --git a/Model/Action/Export/NotifierActionBundle.php b/Model/Action/Export/NotifierActionBundle.php new file mode 100644 index 0000000..bec5e34 --- /dev/null +++ b/Model/Action/Export/NotifierActionBundle.php @@ -0,0 +1,59 @@ +notifiers = $notifiers; + $this->objectManager = $objectManager; + parent::__construct($resultBuilder); + } + + public function execute(ActionContextInterface $actionContext): ActionResultInterface + { + $this->resolveNotifier($actionContext)->notify(ArgumentReader::getEntity($actionContext)); + + return $this->createActionResult(['is_notify' => true]); + } + + private function resolveNotifier(ActionContextInterface $actionContext): NotifierInterface + { + $entityType = ActionArgumentReader::getEntityType($actionContext); + + if (!isset($this->notifiers[$entityType])) { + throw new InvalidArgumentException(sprintf('Unknown notifier for entity type "%s".', $entityType)); + } + + return $this->objectManager->get($this->notifiers[$entityType]); + } +} diff --git a/Model/Action/PerformedBy/AdminUser.php b/Model/Action/PerformedBy/AdminUser.php new file mode 100644 index 0000000..522fcef --- /dev/null +++ b/Model/Action/PerformedBy/AdminUser.php @@ -0,0 +1,41 @@ +authSession = $authSession; + $this->attributeName = $attributeName; + } + + public function get(): string + { + return self::PERFORMED_BY . ($this->authSession->getUser() + ? $this->authSession->getUser()->getData($this->attributeName) + : ''); + } +} diff --git a/Model/Action/PerformedBy/Console.php b/Model/Action/PerformedBy/Console.php new file mode 100644 index 0000000..364b6e5 --- /dev/null +++ b/Model/Action/PerformedBy/Console.php @@ -0,0 +1,20 @@ +customerSession = $customerSession; + $this->attributeName = $attributeName; + } + + public function get(): string + { + return $this->customerSession->isLoggedIn() + ? $this->customerSession->getCustomer()->getData($this->attributeName) + : ''; + } +} diff --git a/Model/Action/PerformedBy/Guest.php b/Model/Action/PerformedBy/Guest.php new file mode 100644 index 0000000..bbc13c3 --- /dev/null +++ b/Model/Action/PerformedBy/Guest.php @@ -0,0 +1,43 @@ +coreRegistry = $coreRegistry; + $this->attributeName = $attributeName; + } + + public function get(): string + { + $order = $this->coreRegistry->registry('current_order'); + + return $order && $order instanceof Order + ? $order->getData($this->attributeName) + : ''; + } +} diff --git a/Model/Action/PerformedBy/NotEmptyStrategy.php b/Model/Action/PerformedBy/NotEmptyStrategy.php new file mode 100644 index 0000000..61246ff --- /dev/null +++ b/Model/Action/PerformedBy/NotEmptyStrategy.php @@ -0,0 +1,44 @@ +performedByList = (static function (PerformedByInterface ...$performedByList) { + return $performedByList; + })(...$performedByList); + } + + public function get(): string + { + foreach ($this->performedByList as $performedBy) { + $performer = $performedBy->get(); + + if (!empty($performer)) { + return $performer; + } + } + + return self::PERFORMED_BY; + } +} diff --git a/Model/Action/PerformedByInterface.php b/Model/Action/PerformedByInterface.php new file mode 100644 index 0000000..c122637 --- /dev/null +++ b/Model/Action/PerformedByInterface.php @@ -0,0 +1,16 @@ +performedAt = $performedAt; + $this->state = $state; + $this->message = $message; + $this->result = $result; + } + + public function getPerformedAt(): DateTime + { + return $this->performedAt; + } + + public function getState(): string + { + return $this->state; + } + + public function getMessage(): string + { + return $this->message; + } + + public function getResult(): array + { + return $this->result; + } +} diff --git a/Model/Action/ResultBuilder.php b/Model/Action/ResultBuilder.php new file mode 100644 index 0000000..34f31b9 --- /dev/null +++ b/Model/Action/ResultBuilder.php @@ -0,0 +1,72 @@ +actionResultFactory = $actionResultFactory; + $this->data = []; + } + + public function setPerformedAt(DateTime $performedAt): ResultBuilder + { + $this->data['performedAt'] = $performedAt; + + return $this; + } + + public function setState(string $state): ResultBuilder + { + $this->data['state'] = $state; + + return $this; + } + + public function setMessage(string $message): ResultBuilder + { + $this->data['message'] = $message; + + return $this; + } + + public function setResult(array $result): ResultBuilder + { + $this->data['result'] = $result; + + return $this; + } + + public function create(): ActionResultInterface + { + /** @var ActionResultInterface $result */ + $result = $this->actionResultFactory->create($this->data); + $this->data = []; + + return $result; + } +} diff --git a/Model/ActionEntity.php b/Model/ActionEntity.php new file mode 100644 index 0000000..b3bf37f --- /dev/null +++ b/Model/ActionEntity.php @@ -0,0 +1,120 @@ +_eventPrefix = 'opengento_gdpr_action_entity'; + $this->_eventObject = 'action_entity'; + $this->_init(ActionEntityResource::class); + } + + public function getActionId(): int + { + return (int) $this->_getData(self::ID); + } + + public function setActionId(int $actionId): ActionEntityInterface + { + return $this->setData(self::ID, $actionId); + } + + public function getType(): string + { + return (string) $this->_getData(self::TYPE); + } + + public function setType(string $type): ActionEntityInterface + { + return $this->setData(self::TYPE, $type); + } + + public function getPerformedFrom(): string + { + return (string) $this->_getData(self::PERFORMED_FROM); + } + + public function setPerformedFrom(?string $performedFrom): ActionEntityInterface + { + return $this->setData(self::PERFORMED_FROM, $performedFrom); + } + + public function getPerformedBy(): string + { + return (string) $this->_getData(self::PERFORMED_BY); + } + + public function setPerformedBy(?string $performedBy): ActionEntityInterface + { + return $this->setData(self::PERFORMED_BY, $performedBy); + } + + /** + * @throws Exception + */ + public function getPerformedAt(): DateTime + { + return is_string($this->_getData(self::PERFORMED_AT)) + ? new DateTime($this->_getData(self::PERFORMED_AT)) + : $this->_getData(self::PERFORMED_AT); + } + + public function setPerformedAt(string $performedAt): ActionEntityInterface + { + return $this->setData(self::PERFORMED_AT, $performedAt); + } + + public function getState(): string + { + return (string) $this->_getData(self::STATE); + } + + public function setState(string $state): ActionEntityInterface + { + return $this->setData(self::STATE, $state); + } + + public function getMessage(): string + { + return (string) $this->_getData(self::MESSAGE); + } + + public function setMessage(string $message): ActionEntityInterface + { + return $this->setData(self::MESSAGE, $message); + } + + public function getParameters(): array + { + return (array) $this->_getData(self::PARAMETERS); + } + + public function setParameters(array $parameters): ActionEntityInterface + { + return $this->setData(self::PARAMETERS, $parameters); + } + + public function getResult(): array + { + return $this->_getData(self::RESULT) ?? []; + } + + public function setResult(array $result): ActionEntityInterface + { + return $this->setData(self::RESULT, $result); + } +} diff --git a/Model/ActionEntityBuilder.php b/Model/ActionEntityBuilder.php new file mode 100644 index 0000000..2b6a537 --- /dev/null +++ b/Model/ActionEntityBuilder.php @@ -0,0 +1,100 @@ +actionEntityFactory = $actionEntityFactory; + $this->data = []; + } + + public function setType(string $type): ActionEntityBuilder + { + $this->data[ActionEntityInterface::TYPE] = $type; + + return $this; + } + + public function setPerformedFrom(string $performedFrom): ActionEntityBuilder + { + $this->data[ActionEntityInterface::PERFORMED_FROM] = $performedFrom; + + return $this; + } + + public function setPerformedBy(string $performedBy): ActionEntityBuilder + { + $this->data[ActionEntityInterface::PERFORMED_BY] = $performedBy; + + return $this; + } + + public function setPerformedAt(DateTime $performedAt): ActionEntityBuilder + { + $this->data[ActionEntityInterface::PERFORMED_AT] = $performedAt; + + return $this; + } + + public function setState(string $state): ActionEntityBuilder + { + $this->data[ActionEntityInterface::STATE] = $state; + + return $this; + } + + public function setMessage(string $message): ActionEntityBuilder + { + $this->data[ActionEntityInterface::MESSAGE] = $message; + + return $this; + } + + public function setParameters(array $parameters): ActionEntityBuilder + { + $this->data[ActionEntityInterface::PARAMETERS] = $parameters; + + return $this; + } + + public function setResult(array $result): ActionEntityBuilder + { + $this->data[ActionEntityInterface::RESULT] = $result; + + return $this; + } + + public function create(): ActionEntityInterface + { + /** @var ActionEntityInterface $actionEntity */ + $actionEntity = $this->actionEntityFactory->create(['data' => $this->data]); + $this->data = []; + + return $actionEntity; + } +} diff --git a/Model/ActionEntityRepository.php b/Model/ActionEntityRepository.php new file mode 100644 index 0000000..0891bd1 --- /dev/null +++ b/Model/ActionEntityRepository.php @@ -0,0 +1,131 @@ +actionEntityResource = $actionEntityResource; + $this->actionCustomerFactory = $actionCustomerFactory; + $this->collectionFactory = $collectionFactory; + $this->collectionProcessor = $collectionProcessor; + $this->searchResultsFactory = $searchResultsFactory; + } + + public function save(ActionEntityInterface $actionEntity): ActionEntityInterface + { + try { + $this->actionEntityResource->save($actionEntity); + $this->instances[$actionEntity->getActionId()] = $actionEntity; + } catch (Exception $e) { + throw new CouldNotSaveException(new Phrase('Could not save the entity.'), $e); + } + + return $actionEntity; + } + + public function getById(int $actionId): ActionEntityInterface + { + if (!isset($this->instances[$actionId])) { + /** @var ActionEntityInterface $actionEntity */ + $actionEntity = $this->actionCustomerFactory->create(); + $this->actionEntityResource->load($actionEntity, $actionId, ActionEntityInterface::ID); + + if (!$actionEntity->getActionId()) { + throw NoSuchEntityException::singleField(ActionEntityInterface::ID, $actionId); + } + + $this->instances[$actionId] = $actionEntity; + } + + return $this->instances[$actionId]; + } + + public function getList(SearchCriteriaInterface $searchCriteria): ActionEntitySearchResultsInterface + { + /** @var Collection $collection */ + $collection = $this->collectionFactory->create(); + + $this->collectionProcessor->process($searchCriteria, $collection); + + /** @var ActionEntitySearchResultsInterface $searchResults */ + $searchResults = $this->searchResultsFactory->create(); + $searchResults->setSearchCriteria($searchCriteria); + $searchResults->setItems($collection->getItems()); + $searchResults->setTotalCount($collection->getSize()); + + return $searchResults; + } + + public function delete(ActionEntityInterface $actionEntity): bool + { + try { + unset($this->instances[$actionEntity->getActionId()]); + $this->actionEntityResource->delete($actionEntity); + } catch (Exception $e) { + throw new CouldNotDeleteException( + new Phrase('Could not delete entity with id "%1".', [$actionEntity->getActionId()]), + $e + ); + } + + return true; + } +} diff --git a/Model/Archive/MoveToArchive.php b/Model/Archive/MoveToArchive.php index 235788e..287e308 100644 --- a/Model/Archive/MoveToArchive.php +++ b/Model/Archive/MoveToArchive.php @@ -9,29 +9,23 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Archive\ArchiveInterface; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Exception\NotFoundException; use Magento\Framework\Filesystem; use Magento\Framework\Phrase; -/** - * Class MoveToArchive - */ final class MoveToArchive { /** - * @var \Magento\Framework\Archive\ArchiveInterface + * @var ArchiveInterface */ private $archive; /** - * @var \Magento\Framework\Filesystem + * @var Filesystem */ private $filesystem; - /** - * @param \Magento\Framework\Archive\ArchiveInterface $archive - * @param \Magento\Framework\Filesystem $filesystem - */ public function __construct( ArchiveInterface $archive, Filesystem $filesystem @@ -41,13 +35,11 @@ public function __construct( } /** - * Pack the source and delete it to the file system - * * @param string $source * @param string $destination * @return string - * @throws \Magento\Framework\Exception\FileSystemException - * @throws \Magento\Framework\Exception\NotFoundException + * @throws FileSystemException + * @throws NotFoundException */ public function prepareArchive(string $source, string $destination): string { diff --git a/Model/Archive/Zip.php b/Model/Archive/Zip.php index 6ae2d06..0e29f1c 100644 --- a/Model/Archive/Zip.php +++ b/Model/Archive/Zip.php @@ -10,6 +10,8 @@ use Magento\Framework\Archive\ArchiveInterface; use Magento\Framework\Archive\Zip as ArchiveZip; use Magento\Framework\Filesystem; +use ZipArchive; +use function basename; /** * Zip compressed file archive with local file name. @@ -18,19 +20,15 @@ final class Zip implements ArchiveInterface { /** - * @var \Magento\Framework\Filesystem + * @var Filesystem */ private $filesystem; /** - * @var \Magento\Framework\Archive\Zip + * @var ArchiveZip */ private $zip; - /** - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\Framework\Archive\Zip $zip - */ public function __construct( Filesystem $filesystem, ArchiveZip $zip @@ -39,24 +37,18 @@ public function __construct( $this->zip = $zip; } - /** - * @inheritdoc - */ public function pack($source, $destination): string { $directoryRead = $this->filesystem->getDirectoryReadByPath($source); - $zip = new \ZipArchive(); - $zip->open($destination, \ZipArchive::CREATE); - $zip->addFile($source, $directoryRead->isDirectory($source) ? '' : \basename($source)); + $zip = new ZipArchive(); + $zip->open($destination, ZipArchive::CREATE); + $zip->addFile($source, $directoryRead->isDirectory($source) ? '' : basename($source)); $zip->close(); return $destination; } - /** - * @inheritdoc - */ public function unpack($source, $destination): string { return $this->zip->unpack($source, $destination); diff --git a/Model/Config.php b/Model/Config.php index 9b2902d..9669a40 100644 --- a/Model/Config.php +++ b/Model/Config.php @@ -9,13 +9,14 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\ScopeInterface; +use function explode; /** - * Class Config + * @todo split config */ final class Config { - /**#@+ + /** * Scope Config: Data Settings Paths */ public const CONFIG_PATH_GENERAL_ENABLED = 'gdpr/general/enabled'; @@ -30,31 +31,24 @@ final class Config public const CONFIG_PATH_ERASURE_REMOVE_CUSTOMER = 'gdpr/erasure/remove_customer'; public const CONFIG_PATH_ANONYMIZE_INFORMATION_BLOCK = 'gdpr/anonymize/block_id'; public const CONFIG_PATH_EXPORT_ENABLED = 'gdpr/export/enabled'; + public const CONFIG_PATH_EXPORT_FILE_NAME = 'gdpr/export/file_name'; + public const CONFIG_PATH_EXPORT_LIFE_TIME = 'gdpr/export/life_time'; public const CONFIG_PATH_EXPORT_INFORMATION_BLOCK = 'gdpr/export/block_id'; - public const CONFIG_PATH_EXPORT_RENDERER = 'gdpr/export/renderer'; + public const CONFIG_PATH_EXPORT_RENDERERS = 'gdpr/export/renderers'; public const CONFIG_PATH_COOKIE_DISCLOSURE_ENABLED = 'gdpr/cookie/enabled'; public const CONFIG_PATH_COOKIE_INFORMATION_BLOCK = 'gdpr/cookie/block_id'; - /**#@-*/ /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ private $scopeConfig; - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - */ public function __construct( ScopeConfigInterface $scopeConfig ) { $this->scopeConfig = $scopeConfig; } - /** - * Check if the current module is enabled - * - * @return bool - */ public function isModuleEnabled(): bool { return $this->scopeConfig->isSetFlag( @@ -63,11 +57,6 @@ public function isModuleEnabled(): bool ); } - /** - * Retrieve the privacy information page ID - * - * @return string - */ public function getPrivacyInformationPageId(): string { return (string) $this->scopeConfig->getValue( @@ -76,11 +65,6 @@ public function getPrivacyInformationPageId(): string ); } - /** - * Retrieve the privacy information block ID - * - * @return string - */ public function getPrivacyInformationBlockId(): string { return (string) $this->scopeConfig->getValue( @@ -89,11 +73,6 @@ public function getPrivacyInformationBlockId(): string ); } - /** - * Check if the erasure is enabled - * - * @return bool - */ public function isErasureEnabled(): bool { return $this->scopeConfig->isSetFlag( @@ -104,8 +83,6 @@ public function isErasureEnabled(): bool /** * Check if the customer can be removed if he has no orders - * - * @return bool */ public function isCustomerRemovedNoOrders(): bool { @@ -117,8 +94,6 @@ public function isCustomerRemovedNoOrders(): bool /** * Retrieve the erasure delay in minutes before execution - * - * @return int */ public function getErasureDelay(): int { @@ -130,8 +105,6 @@ public function getErasureDelay(): int /** * Retrieve the maximum age for the entities before the erasure - * - * @return int */ public function getErasureMaxAge(): int { @@ -143,8 +116,6 @@ public function getErasureMaxAge(): int /** * Retrieve the maximum age for the sales information before the erasure - * - * @return int */ public function getErasureSalesMaxAge(): int { @@ -155,23 +126,16 @@ public function getErasureSalesMaxAge(): int } /** - * Retrieve the allowed order states to erase - * * @return string[] */ public function getAllowedStatesToErase(): array { - return \explode(',', (string) $this->scopeConfig->getValue( + return explode(',', (string) $this->scopeConfig->getValue( self::CONFIG_PATH_ERASURE_ALLOWED_STATES, ScopeInterface::SCOPE_STORE )); } - /** - * Retrieve the erasure information block ID - * - * @return string - */ public function getErasureInformationBlockId(): string { return (string) $this->scopeConfig->getValue( @@ -180,11 +144,6 @@ public function getErasureInformationBlockId(): string ); } - /** - * Retrieve the anonymize information block ID - * - * @return string - */ public function getAnonymizeInformationBlockId(): string { return (string) $this->scopeConfig->getValue( @@ -193,11 +152,6 @@ public function getAnonymizeInformationBlockId(): string ); } - /** - * Check if the export is enabled - * - * @return bool - */ public function isExportEnabled(): bool { return $this->scopeConfig->isSetFlag( @@ -206,37 +160,41 @@ public function isExportEnabled(): bool ); } - /** - * Retrieve the export information block ID - * - * @return string - */ - public function getExportInformationBlockId(): string + public function getExportFileName(): string { return (string) $this->scopeConfig->getValue( - self::CONFIG_PATH_EXPORT_INFORMATION_BLOCK, + self::CONFIG_PATH_EXPORT_FILE_NAME, ScopeInterface::SCOPE_STORE ); } /** - * Retrieve the export renderer code - * - * @return string + * Retrieve the export file life time in minutes */ - public function getExportRendererCode(): string + public function getExportLifetime(): int + { + return (int) $this->scopeConfig->getValue( + self::CONFIG_PATH_EXPORT_LIFE_TIME, + ScopeInterface::SCOPE_STORE + ); + } + + public function getExportInformationBlockId(): string { return (string) $this->scopeConfig->getValue( - self::CONFIG_PATH_EXPORT_RENDERER, + self::CONFIG_PATH_EXPORT_INFORMATION_BLOCK, ScopeInterface::SCOPE_STORE ); } - /** - * Check if the cookie disclosure is enabled - * - * @return bool - */ + public function getExportRendererCodes(): array + { + return explode(',', (string) $this->scopeConfig->getValue( + self::CONFIG_PATH_EXPORT_RENDERERS, + ScopeInterface::SCOPE_STORE + )); + } + public function isCookieDisclosureEnabled(): bool { return $this->scopeConfig->isSetFlag( @@ -245,11 +203,6 @@ public function isCookieDisclosureEnabled(): bool ); } - /** - * Retrieve the cookie disclosure information block ID - * - * @return string - */ public function getCookieDisclosureInformationBlockId(): string { return (string) $this->scopeConfig->getValue( diff --git a/Model/Config/Source/ActionStates.php b/Model/Config/Source/ActionStates.php new file mode 100644 index 0000000..e07a957 --- /dev/null +++ b/Model/Config/Source/ActionStates.php @@ -0,0 +1,71 @@ +additionalOptions = $additionalOptions; + $this->options = []; + $this->optionArray = []; + } + + public function toOptionArray(): array + { + if (!$this->optionArray) { + foreach ($this->loadOptions() as $value => $label) { + $this->optionArray[] = compact('value', 'label'); + } + } + + return $this->optionArray; + } + + public function getOptionText(string $state): ?string + { + return isset($this->loadOptions()[$state]) ? (string) $this->loadOptions()[$state] : null; + } + + private function loadOptions(): array + { + if (!$this->options) { + $this->options = array_merge( + [ + ActionEntityInterface::STATE_SUCCEEDED => new Phrase('Succeeded'), + ActionEntityInterface::STATE_FAILED => new Phrase('Failed'), + ], + $this->additionalOptions + ); + } + + return $this->options; + } +} diff --git a/Model/Config/Source/EraseComponents.php b/Model/Config/Source/EraseComponents.php index 142aade..905f0b5 100644 --- a/Model/Config/Source/EraseComponents.php +++ b/Model/Config/Source/EraseComponents.php @@ -10,14 +10,13 @@ use Magento\Framework\Data\OptionSourceInterface; use Magento\Framework\ObjectManager\ConfigInterface; use Magento\Framework\Phrase; +use function array_keys; +use function array_merge; -/** - * Class EraseComponents - */ final class EraseComponents implements OptionSourceInterface { /** - * @var \Magento\Framework\ObjectManager\ConfigInterface + * @var ConfigInterface */ private $objectManagerConfig; @@ -33,10 +32,6 @@ final class EraseComponents implements OptionSourceInterface */ private $options; - /** - * @param \Magento\Framework\ObjectManager\ConfigInterface $objectManagerConfig - * @param string $processorResolverFactoryClassName - */ public function __construct( ConfigInterface $objectManagerConfig, string $processorResolverFactoryClassName @@ -45,9 +40,6 @@ public function __construct( $this->processorResolverFactoryClassName = $processorResolverFactoryClassName; } - /** - * @inheritdoc - */ public function toOptionArray(): array { if (!$this->options) { @@ -60,23 +52,23 @@ public function toOptionArray(): array } /** - * Retrieve the delegate processors - * * @return string[] */ private function retrieveDelegateProcessors(): array { $delegateProcessors = []; + /** @var string[] $resolvers */ + $resolvers = $this->retrieveArgument($this->processorResolverFactoryClassName, 'processorResolvers', []); - foreach ($this->retrieveArgument($this->processorResolverFactoryClassName, 'processors', []) as $processor) { - $processorPool = $this->retrieveArgument($processor, 'processorPool'); + foreach ($resolvers as $resolver) { + $processorPool = $this->retrieveArgument($resolver, 'processorPool'); if ($processorPool) { $delegateProcessors[] = $this->retrieveArgument($processorPool, 'array', []); } } - return \array_keys(\array_merge(...$delegateProcessors)); + return array_keys(array_merge(...$delegateProcessors)); } /** @@ -84,7 +76,7 @@ private function retrieveDelegateProcessors(): array * * @param string $className * @param string $argumentName - * @param null $defaultValue + * @param mixed $defaultValue * @return mixed */ private function retrieveArgument(string $className, string $argumentName, $defaultValue = null) diff --git a/Model/Config/Source/OrderPendingStates.php b/Model/Config/Source/OrderPendingStates.php index ba330ac..6afdc41 100644 --- a/Model/Config/Source/OrderPendingStates.php +++ b/Model/Config/Source/OrderPendingStates.php @@ -10,13 +10,10 @@ use Magento\Framework\Data\OptionSourceInterface; use Magento\Sales\Model\ResourceModel\Order\Status\CollectionFactory; -/** - * Class OrderPendingStates - */ final class OrderPendingStates implements OptionSourceInterface { /** - * @var \Magento\Sales\Model\ResourceModel\Order\Status\CollectionFactory + * @var CollectionFactory */ private $collectionFactory; @@ -25,18 +22,12 @@ final class OrderPendingStates implements OptionSourceInterface */ private $options; - /** - * @param \Magento\Sales\Model\ResourceModel\Order\Status\CollectionFactory $collectionFactory - */ public function __construct( CollectionFactory $collectionFactory ) { $this->collectionFactory = $collectionFactory; } - /** - * @inheritdoc - */ public function toOptionArray(): array { return $this->options ?? $this->options = $this->collectionFactory->create()->joinStates()->toOptionArray(); diff --git a/Model/Config/Source/VirtualArrayArgumentList.php b/Model/Config/Source/VirtualArrayArgumentList.php index 2f53990..8dfb9b3 100644 --- a/Model/Config/Source/VirtualArrayArgumentList.php +++ b/Model/Config/Source/VirtualArrayArgumentList.php @@ -10,14 +10,12 @@ use Magento\Framework\Data\OptionSourceInterface; use Magento\Framework\ObjectManager\ConfigInterface; use Magento\Framework\Phrase; +use function array_keys; -/** - * Class VirtualArrayArgumentList - */ final class VirtualArrayArgumentList implements OptionSourceInterface { /** - * @var \Magento\Framework\ObjectManager\ConfigInterface + * @var ConfigInterface */ private $objectManagerConfig; @@ -36,11 +34,6 @@ final class VirtualArrayArgumentList implements OptionSourceInterface */ private $options; - /** - * @param \Magento\Framework\ObjectManager\ConfigInterface $objectManagerConfig - * @param string $className - * @param string $argumentName - */ public function __construct( ConfigInterface $objectManagerConfig, string $className, @@ -51,13 +44,10 @@ public function __construct( $this->argumentName = $argumentName; } - /** - * @inheritdoc - */ public function toOptionArray(): array { if (!$this->options) { - foreach (\array_keys($this->retrieveItems()) as $item) { + foreach (array_keys($this->retrieveItems()) as $item) { $this->options[] = ['value' => $item, 'label' => new Phrase($item)]; } } diff --git a/Model/Config/Source/VirtualCustomerAttributes.php b/Model/Config/Source/VirtualCustomerAttributes.php index 77045dd..a436688 100644 --- a/Model/Config/Source/VirtualCustomerAttributes.php +++ b/Model/Config/Source/VirtualCustomerAttributes.php @@ -11,13 +11,10 @@ use Magento\Framework\Data\OptionSourceInterface; use Magento\Framework\Exception\LocalizedException; -/** - * Class VirtualCustomerAttributes - */ final class VirtualCustomerAttributes implements OptionSourceInterface { /** - * @var \Magento\Customer\Api\MetadataInterface + * @var MetadataInterface */ private $metadata; @@ -26,46 +23,30 @@ final class VirtualCustomerAttributes implements OptionSourceInterface */ private $options; - /** - * @param \Magento\Customer\Api\MetadataInterface $metadata - * @param array $options - */ public function __construct( - MetadataInterface $metadata, - array $options = [] + MetadataInterface $metadata ) { $this->metadata = $metadata; - $this->options = $this->loadOptions($options); + $this->options = []; } - /** - * @inheritdoc - */ public function toOptionArray(): array { - return $this->options; - } - - /** - * Load an prepare customer address attributes options - * - * @param array $defaultOptions - * @return array - */ - public function loadOptions(array $defaultOptions = []): array - { - $options = []; - - try { - $attributes = $this->metadata->getAllAttributesMetadata(); - } catch (LocalizedException $e) { - $attributes = []; - } - - foreach ($attributes as $attribute) { - $options[] = ['value' => $attribute->getAttributeCode(), 'label' => $attribute->getFrontendLabel()]; + if (!$this->options) { + try { + $attributes = $this->metadata->getAllAttributesMetadata(); + } catch (LocalizedException $e) { + $attributes = []; + } + + foreach ($attributes as $attribute) { + $this->options[] = [ + 'value' => $attribute->getAttributeCode(), + 'label' => $attribute->getFrontendLabel(), + ]; + } } - return \array_merge($options, $defaultOptions); + return $this->options; } } diff --git a/Model/Config/Source/VirtualEntityAttributes.php b/Model/Config/Source/VirtualEntityAttributes.php new file mode 100644 index 0000000..a8ce575 --- /dev/null +++ b/Model/Config/Source/VirtualEntityAttributes.php @@ -0,0 +1,55 @@ +attributeProvider = $attributeProvider; + $this->entityType = $entityType; + $this->options = []; + } + + public function toOptionArray(): array + { + if (!$this->options) { + foreach (array_keys($this->attributeProvider->getAttributes($this->entityType)) as $attribute) { + $this->options[] = ['value' => $attribute, 'label' => $attribute]; + } + } + + return $this->options; + } +} diff --git a/Model/Customer/Anonymize/AccountBlocker.php b/Model/Customer/Anonymize/AccountBlocker.php index ae259b2..369ae6d 100644 --- a/Model/Customer/Anonymize/AccountBlocker.php +++ b/Model/Customer/Anonymize/AccountBlocker.php @@ -8,9 +8,13 @@ namespace Opengento\Gdpr\Model\Customer\Anonymize; use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\Visitor\Collection; use Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory as VisitorCollectionFactory; +use Magento\Customer\Model\Visitor; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Encryption\EncryptorInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Intl\DateTimeFactory; use Magento\Framework\Math\Random; use Magento\Framework\Session\Config; @@ -18,55 +22,43 @@ use Magento\Framework\Stdlib\DateTime; use Magento\Store\Model\ScopeInterface; -/** - * Class AccountBlocker - */ final class AccountBlocker { /** - * @var \Magento\Customer\Model\CustomerRegistry + * @var CustomerRegistry */ private $customerRegistry; /** - * @var \Magento\Framework\Session\SaveHandlerInterface + * @var SaveHandlerInterface */ private $saveHandler; /** - * @var \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory + * @var VisitorCollectionFactory */ private $visitorCollectionFactory; /** - * @var \Magento\Framework\Encryption\EncryptorInterface + * @var EncryptorInterface */ private $encryptor; /** - * @var \Magento\Framework\Intl\DateTimeFactory + * @var DateTimeFactory */ private $dateTimeFactory; /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ private $scopeConfig; - /** - * @param \Magento\Customer\Model\CustomerRegistry $customerRegistry - * @param \Magento\Framework\Encryption\EncryptorInterface $encryptor - * @param \Magento\Framework\Session\SaveHandlerInterface $saveHandler - * @param \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory $visitorCollectionFactory - * @param \Magento\Framework\Intl\DateTimeFactory $dateTimeFactory - * @param \Magento\Framework\Math\Random $mathRandom - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - */ public function __construct( CustomerRegistry $customerRegistry, EncryptorInterface $encryptor, @@ -86,12 +78,10 @@ public function __construct( } /** - * Invalid a customer account - * * @param int $customerId * @return bool - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\LocalizedException + * @throws NoSuchEntityException + * @throws LocalizedException */ public function invalid(int $customerId): bool { @@ -99,12 +89,10 @@ public function invalid(int $customerId): bool } /** - * Reset the customer password to unknown password - * * @param int $customerId * @return bool - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\LocalizedException + * @throws NoSuchEntityException + * @throws LocalizedException */ private function resetPassword(int $customerId): bool { @@ -117,8 +105,6 @@ private function resetPassword(int $customerId): bool } /** - * Close all sessions related to the customer - * * @param int $customerId * @return bool */ @@ -128,12 +114,12 @@ private function closeSessions(int $customerId): bool $dateTime = $this->dateTimeFactory->create(); $time = $dateTime->setTimestamp($dateTime->getTimestamp() - $sessionLifetime); - /** @var \Magento\Customer\Model\ResourceModel\Visitor\Collection $visitorCollection */ + /** @var Collection $visitorCollection */ $visitorCollection = $this->visitorCollectionFactory->create(); $visitorCollection->addFieldToFilter('customer_id', ['eq' => $customerId]); $visitorCollection->addFieldToFilter('last_visit_at', ['from' => $time->format(DateTime::DATETIME_PHP_FORMAT)]); - /** @var \Magento\Customer\Model\Visitor $visitor */ + /** @var Visitor $visitor */ foreach ($visitorCollection->getItems() as $visitor) { $this->saveHandler->destroy($visitor->getData('session_id')); } diff --git a/Model/Customer/Anonymize/Processor/CustomerAddressDataProcessor.php b/Model/Customer/Anonymize/Processor/CustomerAddressDataProcessor.php index fa47ec7..fd23a67 100644 --- a/Model/Customer/Anonymize/Processor/CustomerAddressDataProcessor.php +++ b/Model/Customer/Anonymize/Processor/CustomerAddressDataProcessor.php @@ -9,34 +9,27 @@ use Magento\Customer\Api\AddressRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\LocalizedException; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class CustomerAddressDataProcessor - */ final class CustomerAddressDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Magento\Customer\Api\AddressRepositoryInterface + * @var AddressRepositoryInterface */ private $customerAddressRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Magento\Customer\Api\AddressRepositoryInterface $customerAddressRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - */ public function __construct( AnonymizerInterface $anonymizer, AddressRepositoryInterface $customerAddressRepository, @@ -49,7 +42,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function execute(int $customerId): bool { diff --git a/Model/Customer/Anonymize/Processor/CustomerDataProcessor.php b/Model/Customer/Anonymize/Processor/CustomerDataProcessor.php index 1aef2cc..a395835 100644 --- a/Model/Customer/Anonymize/Processor/CustomerDataProcessor.php +++ b/Model/Customer/Anonymize/Processor/CustomerDataProcessor.php @@ -9,6 +9,7 @@ use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; @@ -17,49 +18,38 @@ use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class CustomerDataProcessor - */ final class CustomerDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Opengento\Gdpr\Model\Customer\Anonymize\AccountBlocker + * @var AccountBlocker */ private $accountBlocker; /** - * @var \Magento\Customer\Api\CustomerRepositoryInterface + * @var CustomerRepositoryInterface */ private $customerRepository; /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Opengento\Gdpr\Model\Customer\Anonymize\AccountBlocker $accountBlocker - * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( AnonymizerInterface $anonymizer, AccountBlocker $accountBlocker, @@ -78,7 +68,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function execute(int $customerId): bool { diff --git a/Model/Customer/Anonymize/Processor/OrderDataProcessor.php b/Model/Customer/Anonymize/Processor/OrderDataProcessor.php index ccbf964..b1428bb 100644 --- a/Model/Customer/Anonymize/Processor/OrderDataProcessor.php +++ b/Model/Customer/Anonymize/Processor/OrderDataProcessor.php @@ -7,7 +7,10 @@ namespace Opengento\Gdpr\Model\Customer\Anonymize\Processor; +use DateTime; +use Exception; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderAddressRepositoryInterface; use Magento\Sales\Api\OrderRepositoryInterface; @@ -16,43 +19,33 @@ use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class OrderDataProcessor - */ final class OrderDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Sales\Api\OrderAddressRepositoryInterface + * @var OrderAddressRepositoryInterface */ private $orderAddressRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** - * @var \Opengento\Gdpr\Api\EraseSalesInformationInterface + * @var EraseSalesInformationInterface */ private $eraseSalesInformation; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Sales\Api\OrderAddressRepositoryInterface $orderAddressRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Api\EraseSalesInformationInterface $eraseSalesInformation - */ public function __construct( AnonymizerInterface $anonymizer, OrderRepositoryInterface $orderRepository, @@ -69,37 +62,29 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $customerId): bool { $this->searchCriteriaBuilder->addFilter(OrderInterface::CUSTOMER_ID, $customerId); $orderList = $this->orderRepository->getList($this->searchCriteriaBuilder->create()); - /** @var \Magento\Sales\Model\Order $order */ + /** @var Order $order */ foreach ($orderList->getItems() as $order) { - $lastActive = new \DateTime($order->getUpdatedAt()); - if ($this->eraseSalesInformation->isAlive($lastActive)) { - $this->eraseSalesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive); - } else { - $this->anonymize($order); - } + $lastActive = new DateTime($order->getUpdatedAt()); + $this->eraseSalesInformation->isAlive($lastActive) + ? $this->eraseSalesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive) + : $this->anonymize($order); } return true; } - /** - * Anonymize the order entity - * - * @param \Magento\Sales\Model\Order $order - * @return void - */ private function anonymize(Order $order): void { $this->orderRepository->save($this->anonymizer->anonymize($order)); - /** @var \Magento\Sales\Api\Data\OrderAddressInterface|null $orderAddress */ + /** @var OrderAddressInterface|null $orderAddress */ foreach ([$order->getBillingAddress(), $order->getShippingAddress()] as $orderAddress) { if ($orderAddress) { $this->orderAddressRepository->save($this->anonymizer->anonymize($orderAddress)); diff --git a/Model/Customer/Anonymize/Processor/QuoteDataProcessor.php b/Model/Customer/Anonymize/Processor/QuoteDataProcessor.php index efe05f9..600053e 100644 --- a/Model/Customer/Anonymize/Processor/QuoteDataProcessor.php +++ b/Model/Customer/Anonymize/Processor/QuoteDataProcessor.php @@ -7,43 +7,36 @@ namespace Opengento\Gdpr\Model\Customer\Anonymize\Processor; +use Exception; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; use Magento\Quote\Model\ResourceModel\Quote\Address; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class QuoteDataProcessor - */ final class QuoteDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ private $quoteRepository; /** - * @var \Magento\Quote\Model\ResourceModel\Quote\Address + * @var Address */ private $quoteAddressResourceModel; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param \Magento\Quote\Model\ResourceModel\Quote\Address $quoteAddressResourceModel - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - */ public function __construct( AnonymizerInterface $anonymizer, CartRepositoryInterface $quoteRepository, @@ -58,18 +51,18 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $customerId): bool { $this->searchCriteriaBuilder->addFilter('customer_id', $customerId); $quoteList = $this->quoteRepository->getList($this->searchCriteriaBuilder->create()); - /** @var \Magento\Quote\Model\Quote $quote */ + /** @var Quote $quote */ foreach ($quoteList->getItems() as $quote) { $this->quoteRepository->save($this->anonymizer->anonymize($quote)); - /** @var \Magento\Quote\Model\Quote\Address|null $quoteAddress */ + /** @var Quote\Address|null $quoteAddress */ foreach ([$quote->getBillingAddress(), $quote->getShippingAddress()] as $quoteAddress) { if ($quoteAddress) { $this->quoteAddressResourceModel->save($this->anonymizer->anonymize($quoteAddress)); diff --git a/Model/Customer/Anonymize/Processor/SubscriberDataProcessor.php b/Model/Customer/Anonymize/Processor/SubscriberDataProcessor.php index 6c4254c..4bf35a4 100644 --- a/Model/Customer/Anonymize/Processor/SubscriberDataProcessor.php +++ b/Model/Customer/Anonymize/Processor/SubscriberDataProcessor.php @@ -7,36 +7,30 @@ namespace Opengento\Gdpr\Model\Customer\Anonymize\Processor; +use Exception; use Magento\Newsletter\Model\ResourceModel\Subscriber as ResourceSubscriber; +use Opengento\Gdpr\Model\Newsletter\Subscriber; use Opengento\Gdpr\Model\Newsletter\SubscriberFactory; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class SubscriberDataProcessor - */ final class SubscriberDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Opengento\Gdpr\Model\Newsletter\SubscriberFactory + * @var SubscriberFactory */ private $subscriberFactory; /** - * @var \Magento\Newsletter\Model\ResourceModel\Subscriber + * @var ResourceSubscriber */ private $subscriberResourceModel; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Opengento\Gdpr\Model\Newsletter\SubscriberFactory $subscriberFactory - * @param \Magento\Newsletter\Model\ResourceModel\Subscriber $subscriberResourceModel - */ public function __construct( AnonymizerInterface $anonymizer, SubscriberFactory $subscriberFactory, @@ -49,11 +43,11 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $customerId): bool { - /** @var \Opengento\Gdpr\Model\Newsletter\Subscriber $subscriber */ + /** @var Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); $subscriber->loadByCustomerId($customerId); $this->anonymizer->anonymize($subscriber); diff --git a/Model/Customer/CustomerChecker.php b/Model/Customer/CustomerChecker.php index 3696521..6953a2f 100644 --- a/Model/Customer/CustomerChecker.php +++ b/Model/Customer/CustomerChecker.php @@ -13,23 +13,20 @@ use Opengento\Gdpr\Model\Config; use Opengento\Gdpr\Model\Entity\EntityCheckerInterface; -/** - * Class CustomerChecker - */ final class CustomerChecker implements EntityCheckerInterface { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; @@ -38,11 +35,6 @@ final class CustomerChecker implements EntityCheckerInterface */ private $cache; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( OrderRepositoryInterface $orderRepository, SearchCriteriaBuilder $searchCriteriaBuilder, @@ -54,13 +46,9 @@ public function __construct( $this->cache = []; } - /** - * @inheritdoc - * @param bool $forceReload [optional] Flush the cache. - */ - public function canErase(int $customerId, bool $forceReload = false): bool + public function canErase(int $customerId): bool { - if ($forceReload || !isset($this->cache[$customerId])) { + if (!isset($this->cache[$customerId])) { $this->searchCriteriaBuilder->addFilter(OrderInterface::STATE, $this->config->getAllowedStatesToErase(), 'nin'); $this->searchCriteriaBuilder->addFilter(OrderInterface::CUSTOMER_ID, $customerId); $orderList = $this->orderRepository->getList($this->searchCriteriaBuilder->create()); diff --git a/Model/Customer/Delete/Processor/CustomerAddressDataProcessor.php b/Model/Customer/Delete/Processor/CustomerAddressDataProcessor.php index abaf7ab..429ea20 100644 --- a/Model/Customer/Delete/Processor/CustomerAddressDataProcessor.php +++ b/Model/Customer/Delete/Processor/CustomerAddressDataProcessor.php @@ -9,27 +9,21 @@ use Magento\Customer\Api\AddressRepositoryInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\LocalizedException; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class CustomerAddressDataProcessor - */ final class CustomerAddressDataProcessor implements ProcessorInterface { /** - * @var \Magento\Customer\Api\AddressRepositoryInterface + * @var AddressRepositoryInterface */ private $customerAddressRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Magento\Customer\Api\AddressRepositoryInterface $customerAddressRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - */ public function __construct( AddressRepositoryInterface $customerAddressRepository, SearchCriteriaBuilder $searchCriteriaBuilder @@ -40,7 +34,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function execute(int $customerId): bool { diff --git a/Model/Customer/Delete/Processor/CustomerDataProcessor.php b/Model/Customer/Delete/Processor/CustomerDataProcessor.php index 227962d..c8df462 100644 --- a/Model/Customer/Delete/Processor/CustomerDataProcessor.php +++ b/Model/Customer/Delete/Processor/CustomerDataProcessor.php @@ -8,22 +8,17 @@ namespace Opengento\Gdpr\Model\Customer\Delete\Processor; use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class CustomerDataProcessor - */ final class CustomerDataProcessor implements ProcessorInterface { /** - * @var \Magento\Customer\Api\CustomerRepositoryInterface + * @var CustomerRepositoryInterface */ private $customerRepository; - /** - * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository - */ public function __construct( CustomerRepositoryInterface $customerRepository ) { @@ -32,7 +27,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function execute(int $customerId): bool { diff --git a/Model/Customer/Delete/Processor/OrderDataProcessor.php b/Model/Customer/Delete/Processor/OrderDataProcessor.php index 94916b6..c5c4853 100644 --- a/Model/Customer/Delete/Processor/OrderDataProcessor.php +++ b/Model/Customer/Delete/Processor/OrderDataProcessor.php @@ -7,37 +7,31 @@ namespace Opengento\Gdpr\Model\Customer\Delete\Processor; +use DateTime; +use Exception; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Api\EraseSalesInformationInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class OrderDataProcessor - */ final class OrderDataProcessor implements ProcessorInterface { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; /** - * @var \Opengento\Gdpr\Api\EraseSalesInformationInterface + * @var EraseSalesInformationInterface */ private $eraseSalesInformation; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Api\EraseSalesInformationInterface $eraseSalesInformation - */ public function __construct( OrderRepositoryInterface $orderRepository, SearchCriteriaBuilder $searchCriteriaBuilder, @@ -50,7 +44,7 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $customerId): bool { @@ -58,12 +52,10 @@ public function execute(int $customerId): bool $orderList = $this->orderRepository->getList($this->searchCriteriaBuilder->create()); foreach ($orderList->getItems() as $order) { - $lastActive = new \DateTime($order->getUpdatedAt()); - if ($this->eraseSalesInformation->isAlive($lastActive)) { - $this->eraseSalesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive); - } else { - $this->orderRepository->delete($order); - } + $lastActive = new DateTime($order->getUpdatedAt()); + $this->eraseSalesInformation->isAlive($lastActive) + ? $this->eraseSalesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive) + : $this->orderRepository->delete($order); } return true; diff --git a/Model/Customer/Delete/Processor/QuoteDataProcessor.php b/Model/Customer/Delete/Processor/QuoteDataProcessor.php index 366c65d..37c6275 100644 --- a/Model/Customer/Delete/Processor/QuoteDataProcessor.php +++ b/Model/Customer/Delete/Processor/QuoteDataProcessor.php @@ -11,25 +11,18 @@ use Magento\Quote\Api\CartRepositoryInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class QuoteDataProcessor - */ final class QuoteDataProcessor implements ProcessorInterface { /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ private $quoteRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - */ public function __construct( CartRepositoryInterface $quoteRepository, SearchCriteriaBuilder $searchCriteriaBuilder @@ -38,9 +31,6 @@ public function __construct( $this->searchCriteriaBuilder = $searchCriteriaBuilder; } - /** - * @inheritdoc - */ public function execute(int $customerId): bool { $this->searchCriteriaBuilder->addFilter('customer_id', $customerId); diff --git a/Model/Customer/Delete/Processor/SubscriberDataProcessor.php b/Model/Customer/Delete/Processor/SubscriberDataProcessor.php index 87d318e..2074ab2 100644 --- a/Model/Customer/Delete/Processor/SubscriberDataProcessor.php +++ b/Model/Customer/Delete/Processor/SubscriberDataProcessor.php @@ -7,29 +7,24 @@ namespace Opengento\Gdpr\Model\Customer\Delete\Processor; +use Exception; use Magento\Newsletter\Model\ResourceModel\Subscriber as ResourceSubscriber; +use Magento\Newsletter\Model\Subscriber; use Magento\Newsletter\Model\SubscriberFactory; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class SubscriberDataProcessor - */ final class SubscriberDataProcessor implements ProcessorInterface { /** - * @var \Magento\Newsletter\Model\SubscriberFactory + * @var SubscriberFactory */ private $subscriberFactory; /** - * @var \Magento\Newsletter\Model\ResourceModel\Subscriber + * @var ResourceSubscriber */ private $subscriberResourceModel; - /** - * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory - * @param \Magento\Newsletter\Model\ResourceModel\Subscriber $subscriberResourceModel - */ public function __construct( SubscriberFactory $subscriberFactory, ResourceSubscriber $subscriberResourceModel @@ -40,11 +35,11 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $customerId): bool { - /** @var \Magento\Newsletter\Model\Subscriber $subscriber */ + /** @var Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); $subscriber->loadByCustomerId($customerId); $this->subscriberResourceModel->delete($subscriber); diff --git a/Model/Customer/Erase/Notifier.php b/Model/Customer/Erase/Notifier.php new file mode 100644 index 0000000..5ce8b2f --- /dev/null +++ b/Model/Customer/Erase/Notifier.php @@ -0,0 +1,50 @@ +senders = (static function (SenderInterface ...$senders): array { + return $senders; + })(...\array_values($senders)); + $this->customerRepository = $customerRepository; + } + + /** + * @inheritdoc + * @throws LocalizedException + */ + public function notify(EraseEntityInterface $eraseEntity): void + { + $customer = $this->customerRepository->getById($eraseEntity->getEntityId()); + + foreach ($this->senders as $sender) { + $sender->send($customer); + } + } +} diff --git a/Model/Customer/Export/ExportCustomer.php b/Model/Customer/Export/ExportCustomer.php deleted file mode 100644 index ce0a951..0000000 --- a/Model/Customer/Export/ExportCustomer.php +++ /dev/null @@ -1,26 +0,0 @@ -senders = (static function (SenderInterface ...$senders): array { + return $senders; + })(...\array_values($senders)); + $this->customerRepository = $customerRepository; + } + + /** + * @inheritdoc + * @throws LocalizedException + */ + public function notify(ExportEntityInterface $exportEntity): void + { + $customer = $this->customerRepository->getById($exportEntity->getEntityId()); + + foreach ($this->senders as $sender) { + $sender->send($customer); + } + } +} diff --git a/Model/Customer/Export/Processor/CustomerAddressDataProcessor.php b/Model/Customer/Export/Processor/CustomerAddressDataProcessor.php index 9fea033..1223987 100644 --- a/Model/Customer/Export/Processor/CustomerAddressDataProcessor.php +++ b/Model/Customer/Export/Processor/CustomerAddressDataProcessor.php @@ -8,30 +8,24 @@ namespace Opengento\Gdpr\Model\Customer\Export\Processor; use Magento\Customer\Api\AddressRepositoryInterface; +use Magento\Customer\Api\Data\AddressInterface; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Framework\Exception\LocalizedException; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Export\Processor\AbstractDataProcessor; -/** - * Class CustomerAddressDataProcessor - */ final class CustomerAddressDataProcessor extends AbstractDataProcessor { /** - * @var \Magento\Customer\Api\AddressRepositoryInterface + * @var AddressRepositoryInterface */ private $addressRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( AddressRepositoryInterface $addressRepository, SearchCriteriaBuilder $searchCriteriaBuilder, @@ -44,14 +38,14 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function execute(int $customerId, array $data): array { $this->searchCriteriaBuilder->addFilter('parent_id', $customerId); $addressList = $this->addressRepository->getList($this->searchCriteriaBuilder->create()); - /** @var \Magento\Customer\Api\Data\AddressInterface $entity */ + /** @var AddressInterface $entity */ foreach ($addressList->getItems() as $entity) { $data['customer_addresses']['customer_address_id_' . $entity->getId()] = $this->collectData($entity); } diff --git a/Model/Customer/Export/Processor/CustomerDataProcessor.php b/Model/Customer/Export/Processor/CustomerDataProcessor.php index d7b7527..92d1770 100644 --- a/Model/Customer/Export/Processor/CustomerDataProcessor.php +++ b/Model/Customer/Export/Processor/CustomerDataProcessor.php @@ -8,23 +8,18 @@ namespace Opengento\Gdpr\Model\Customer\Export\Processor; use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Export\Processor\AbstractDataProcessor; -/** - * Class CustomerDataProcessor - */ final class CustomerDataProcessor extends AbstractDataProcessor { /** - * @var \Magento\Customer\Api\CustomerRepositoryInterface + * @var CustomerRepositoryInterface */ private $customerRepository; - /** - * @param \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( CustomerRepositoryInterface $customerRepository, DataCollectorInterface $dataCollector @@ -35,8 +30,8 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\LocalizedException + * @throws NoSuchEntityException + * @throws LocalizedException */ public function execute(int $customerId, array $data): array { diff --git a/Model/Customer/Export/Processor/OrderDataProcessor.php b/Model/Customer/Export/Processor/OrderDataProcessor.php index 37ffb3e..48db9a0 100644 --- a/Model/Customer/Export/Processor/OrderDataProcessor.php +++ b/Model/Customer/Export/Processor/OrderDataProcessor.php @@ -8,31 +8,25 @@ namespace Opengento\Gdpr\Model\Customer\Export\Processor; use Magento\Framework\Api\SearchCriteriaBuilder; +use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Export\Processor\AbstractDataProcessor; -/** - * Class QuoteDataProcessor - */ final class OrderDataProcessor extends AbstractDataProcessor { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( OrderRepositoryInterface $orderRepository, SearchCriteriaBuilder $searchCriteriaBuilder, @@ -43,20 +37,17 @@ public function __construct( parent::__construct($dataCollector); } - /** - * @inheritdoc - */ public function execute(int $customerId, array $data): array { $this->searchCriteriaBuilder->addFilter(OrderInterface::CUSTOMER_ID, $customerId); $orderList = $this->orderRepository->getList($this->searchCriteriaBuilder->create()); - /** @var \Magento\Sales\Model\Order $order */ + /** @var Order $order */ foreach ($orderList->getItems() as $order) { $key = 'order_id_' . $order->getEntityId(); $data['orders'][$key] = $this->collectData($order); - /** @var \Magento\Sales\Api\Data\OrderAddressInterface|null $orderAddress */ + /** @var OrderAddressInterface|null $orderAddress */ foreach ([$order->getBillingAddress(), $order->getShippingAddress()] as $orderAddress) { if ($orderAddress) { $data['orders'][$key][$orderAddress->getAddressType()] = $this->collectData($orderAddress); diff --git a/Model/Customer/Export/Processor/QuoteDataProcessor.php b/Model/Customer/Export/Processor/QuoteDataProcessor.php index 2f8c381..dec45e5 100644 --- a/Model/Customer/Export/Processor/QuoteDataProcessor.php +++ b/Model/Customer/Export/Processor/QuoteDataProcessor.php @@ -9,29 +9,23 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Export\Processor\AbstractDataProcessor; -/** - * Class QuoteDataProcessor - */ final class QuoteDataProcessor extends AbstractDataProcessor { /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ private $quoteRepository; /** - * @var \Magento\Framework\Api\SearchCriteriaBuilder + * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; - /** - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( CartRepositoryInterface $quoteRepository, SearchCriteriaBuilder $searchCriteriaBuilder, @@ -42,20 +36,17 @@ public function __construct( parent::__construct($dataCollector); } - /** - * @inheritdoc - */ public function execute(int $customerId, array $data): array { $this->searchCriteriaBuilder->addFilter('customer_id', $customerId); $quoteList = $this->quoteRepository->getList($this->searchCriteriaBuilder->create()); - /** @var \Magento\Quote\Model\Quote $quote */ + /** @var Quote $quote */ foreach ($quoteList->getItems() as $quote) { $key = 'quote_id_' . $quote->getId(); $data['quotes'][$key] = $this->collectData($quote); - /** @var \Magento\Quote\Model\Quote\Address|null $quoteAddress */ + /** @var Address|null $quoteAddress */ foreach ([$quote->getBillingAddress(), $quote->getShippingAddress()] as $quoteAddress) { if ($quoteAddress) { $data['quotes'][$key][$quoteAddress->getAddressType()] = $this->collectData($quoteAddress); diff --git a/Model/Customer/Export/Processor/SubscriberDataProcessor.php b/Model/Customer/Export/Processor/SubscriberDataProcessor.php index 1c65231..3b97ff8 100644 --- a/Model/Customer/Export/Processor/SubscriberDataProcessor.php +++ b/Model/Customer/Export/Processor/SubscriberDataProcessor.php @@ -8,23 +8,17 @@ namespace Opengento\Gdpr\Model\Customer\Export\Processor; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; +use Opengento\Gdpr\Model\Newsletter\Subscriber; use Opengento\Gdpr\Model\Newsletter\SubscriberFactory; use Opengento\Gdpr\Service\Export\Processor\AbstractDataProcessor; -/** - * Class SubscriberDataProcessor - */ final class SubscriberDataProcessor extends AbstractDataProcessor { /** - * @var \Opengento\Gdpr\Model\Newsletter\SubscriberFactory + * @var SubscriberFactory */ private $subscriberFactory; - /** - * @param \Opengento\Gdpr\Model\Newsletter\SubscriberFactory $subscriberFactory - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( SubscriberFactory $subscriberFactory, DataCollectorInterface $dataCollector @@ -33,12 +27,9 @@ public function __construct( parent::__construct($dataCollector); } - /** - * @inheritdoc - */ public function execute(int $customerId, array $data): array { - /** @var \Opengento\Gdpr\Model\Newsletter\Subscriber $subscriber */ + /** @var Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); $subscriber->loadByCustomerId($customerId); $data['subscriber'] = $this->collectData($subscriber); diff --git a/Model/Customer/Notifier/MailSender.php b/Model/Customer/Notifier/MailSender.php new file mode 100644 index 0000000..c62e44b --- /dev/null +++ b/Model/Customer/Notifier/MailSender.php @@ -0,0 +1,53 @@ +customerViewHelper = $customerViewHelper; + parent::__construct($transportBuilder, $scopeConfig, $configPaths); + } + + /** + * @inheritdoc + * @throws LocalizedException + * @throws MailException + */ + public function send(CustomerInterface $customer): void + { + $storeId = $customer->getStoreId() === null ? null : (int) $customer->getStoreId(); + $vars = [];//todo convert customer as data array + + $this->sendMail($customer->getEmail(), $this->customerViewHelper->getCustomerName($customer), $storeId, $vars); + } +} diff --git a/Model/Customer/Notifier/SenderInterface.php b/Model/Customer/Notifier/SenderInterface.php new file mode 100644 index 0000000..603764b --- /dev/null +++ b/Model/Customer/Notifier/SenderInterface.php @@ -0,0 +1,18 @@ +document = $document; } - /** - * @inheritdoc - */ - public function collect($entity): array + public function collect(object $entity): array { $this->entityIterator->iterate($entity); + $data = $this->document->getData(); + $this->document->setData([]); - return $this->document->getData(); + return $data; } } diff --git a/Model/Entity/DataCollectorGeneric.php b/Model/Entity/DataCollectorGeneric.php index f9a3489..e37cebd 100644 --- a/Model/Entity/DataCollectorGeneric.php +++ b/Model/Entity/DataCollectorGeneric.php @@ -7,50 +7,53 @@ namespace Opengento\Gdpr\Model\Entity; +use Exception; +use LogicException; use Magento\Framework\EntityManager\TypeResolver; +use function array_combine; +use function array_keys; +use function array_values; +use function sprintf; -/** - * Class DataCollectorGeneric - */ final class DataCollectorGeneric implements DataCollectorInterface { /** - * @var \Magento\Framework\EntityManager\TypeResolver + * @var TypeResolver */ private $typeResolver; /** - * @var \Opengento\Gdpr\Model\Entity\DataCollectorInterface[] + * @var DataCollectorInterface[] */ private $dataCollectors; /** - * @param \Magento\Framework\EntityManager\TypeResolver $typeResolver - * @param array $dataCollectors + * @param TypeResolver $typeResolver + * @param DataCollectorInterface[] $dataCollectors */ public function __construct( TypeResolver $typeResolver, array $dataCollectors ) { $this->typeResolver = $typeResolver; - $this->dataCollectors = (static function (DataCollectorInterface ...$dataCollectors) { + $this->dataCollectors = (static function (DataCollectorInterface ...$dataCollectors): array { return $dataCollectors; - })(...\array_values($dataCollectors)); + })(...array_values($dataCollectors)); - $this->dataCollectors = \array_combine(\array_keys($dataCollectors), $this->dataCollectors); + $this->dataCollectors = array_combine(array_keys($dataCollectors), $this->dataCollectors); } /** * @inheritdoc - * @throws \Exception + * @throws Exception */ - public function collect($entity): array + public function collect(object $entity): array { $entityType = $this->typeResolver->resolve($entity); if (!isset($this->dataCollectors[$entityType])) { - throw new \LogicException( - \sprintf('There is no registered data collector for the entity type "%s".', $entityType) + throw new LogicException( + sprintf('There is no registered data collector for the entity type "%s".', $entityType) ); } diff --git a/Model/Entity/DataCollectorInterface.php b/Model/Entity/DataCollectorInterface.php index 56b30bf..48419c5 100644 --- a/Model/Entity/DataCollectorInterface.php +++ b/Model/Entity/DataCollectorInterface.php @@ -3,20 +3,14 @@ * Copyright © OpenGento, All rights reserved. * See LICENSE bundled with this library for license details. */ +declare(strict_types=1); namespace Opengento\Gdpr\Model\Entity; /** - * Interface DataCollectorInterface * @api */ interface DataCollectorInterface { - /** - * Collect data from the entity object - * - * @param object $entity - * @return array - */ - public function collect($entity): array; + public function collect(object $entity): array; } diff --git a/Model/Entity/Document.php b/Model/Entity/Document.php index 5f86c37..22ad2d3 100644 --- a/Model/Entity/Document.php +++ b/Model/Entity/Document.php @@ -7,9 +7,6 @@ namespace Opengento\Gdpr\Model\Entity; -/** - * Class Document - */ final class Document implements DocumentInterface { /** @@ -17,38 +14,23 @@ final class Document implements DocumentInterface */ private $data; - /** - * @param array $data - */ public function __construct(array $data = []) { $this->data = $data; } - /** - * @inheritdoc - */ public function setData(array $data): void { $this->data = $data; } - /** - * @inheritdoc - */ public function addData(string $key, $value): void { $this->data[$key] = $value; } - /** - * @inheritdoc - */ public function getData(): array { - $data = $this->data; - $this->data = []; - - return $data; + return $this->data; } } diff --git a/Model/Entity/DocumentInterface.php b/Model/Entity/DocumentInterface.php index e3ffa0f..c76d2e9 100644 --- a/Model/Entity/DocumentInterface.php +++ b/Model/Entity/DocumentInterface.php @@ -3,36 +3,18 @@ * Copyright © OpenGento, All rights reserved. * See LICENSE bundled with this library for license details. */ +declare(strict_types=1); namespace Opengento\Gdpr\Model\Entity; /** - * Interface DocumentInterface * @api */ interface DocumentInterface { - /** - * Set the document data - * - * @param array $data - * @return void - */ public function setData(array $data): void; - /** - * Append data by key to the document - * - * @param string $key - * @param mixed $value - * @return void - */ public function addData(string $key, $value): void; - /** - * Retrieve the data and empties the document - * - * @return array - */ public function getData(): array; } diff --git a/Model/Entity/EntityCheckerFactory.php b/Model/Entity/EntityCheckerFactory.php index ceaab46..4a889c9 100644 --- a/Model/Entity/EntityCheckerFactory.php +++ b/Model/Entity/EntityCheckerFactory.php @@ -7,10 +7,11 @@ namespace Opengento\Gdpr\Model\Entity; +use InvalidArgumentException; use Magento\Framework\ObjectManagerInterface; +use function sprintf; /** - * Class EntityCheckerFactory * @api */ final class EntityCheckerFactory @@ -21,13 +22,13 @@ final class EntityCheckerFactory private $checkers; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $checkers - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $checkers, @@ -37,16 +38,10 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Retrieve the export processor by entity type - * - * @param string $entityType - * @return \Opengento\Gdpr\Model\Entity\EntityCheckerInterface - */ public function get(string $entityType): EntityCheckerInterface { if (!isset($this->checkers[$entityType])) { - throw new \InvalidArgumentException(\sprintf('Unknown checker for entity type "%s".', $entityType)); + throw new InvalidArgumentException(sprintf('Unknown checker for entity type "%s".', $entityType)); } return $this->objectManager->get($this->checkers[$entityType]); diff --git a/Model/Entity/EntityCheckerInterface.php b/Model/Entity/EntityCheckerInterface.php index b71c08c..2df798b 100644 --- a/Model/Entity/EntityCheckerInterface.php +++ b/Model/Entity/EntityCheckerInterface.php @@ -8,13 +8,12 @@ namespace Opengento\Gdpr\Model\Entity; /** - * Interface EntityCheckerInterface * @api */ interface EntityCheckerInterface { /** - * Checks wether or not the entity has pending orders within its relations + * Checks whether or not the entity has pending orders within its relations * * @param int $entityId * @return bool diff --git a/Model/Entity/EntityIterator.php b/Model/Entity/EntityIterator.php index f4df0dc..b7030b1 100644 --- a/Model/Entity/EntityIterator.php +++ b/Model/Entity/EntityIterator.php @@ -7,34 +7,27 @@ namespace Opengento\Gdpr\Model\Entity; +use Exception; use Magento\Framework\EntityManager\HydratorPool; use Magento\Framework\EntityManager\TypeResolver; -/** - * Class EntityIterator - */ final class EntityIterator implements EntityIteratorInterface { /** - * @var \Magento\Framework\EntityManager\HydratorPool + * @var HydratorPool */ private $hydratorPool; /** - * @var \Magento\Framework\EntityManager\TypeResolver + * @var TypeResolver */ private $typeResolver; /** - * @var \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface + * @var EntityValueProcessorInterface */ private $processor; - /** - * @param \Magento\Framework\EntityManager\HydratorPool $hydratorPool - * @param \Magento\Framework\EntityManager\TypeResolver $typeResolver - * @param \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface $processor - */ public function __construct( HydratorPool $hydratorPool, TypeResolver $typeResolver, @@ -47,7 +40,7 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function iterate($entity): void { diff --git a/Model/Entity/EntityIteratorInterface.php b/Model/Entity/EntityIteratorInterface.php index bcd0c54..40d1e97 100644 --- a/Model/Entity/EntityIteratorInterface.php +++ b/Model/Entity/EntityIteratorInterface.php @@ -3,18 +3,16 @@ * Copyright © OpenGento, All rights reserved. * See LICENSE bundled with this library for license details. */ +declare(strict_types=1); namespace Opengento\Gdpr\Model\Entity; /** - * Interface EntityIteratorInterface * @api */ interface EntityIteratorInterface { /** - * Iterate through the entity object values - * * @param object $entity * @return void */ diff --git a/Model/Entity/EntityValue/CustomAttributesProcessor.php b/Model/Entity/EntityValue/CustomAttributesProcessor.php index 5198ac6..92a5651 100644 --- a/Model/Entity/EntityValue/CustomAttributesProcessor.php +++ b/Model/Entity/EntityValue/CustomAttributesProcessor.php @@ -9,29 +9,21 @@ use Magento\Framework\Api\CustomAttributesDataInterface; use Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface; +use function is_iterable; -/** - * Class CustomAttributesProcessor - */ final class CustomAttributesProcessor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface + * @var EntityValueProcessorInterface */ private $processor; - /** - * @param \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface $processor - */ public function __construct( EntityValueProcessorInterface $processor ) { $this->processor = $processor; } - /** - * @inheritdoc - */ public function process($entity, string $key, $values): void { if ($this->isValid($entity, $key, $values)) { @@ -42,7 +34,7 @@ public function process($entity, string $key, $values): void } /** - * Check wether the entity object and the value key are valid + * Check whether the entity object and the value key are valid * * @param object $entity * @param string $key @@ -53,6 +45,6 @@ private function isValid($entity, string $key, $values): bool { return $entity instanceof CustomAttributesDataInterface && $key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES && - \is_iterable($values); + is_iterable($values); } } diff --git a/Model/Entity/EntityValue/ExtensibleDataProcessor.php b/Model/Entity/EntityValue/ExtensibleDataProcessor.php index e80392d..86533c3 100644 --- a/Model/Entity/EntityValue/ExtensibleDataProcessor.php +++ b/Model/Entity/EntityValue/ExtensibleDataProcessor.php @@ -9,29 +9,21 @@ use Magento\Framework\Api\ExtensibleDataInterface; use Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface; +use function is_iterable; -/** - * Class ExtensibleDataProcessor - */ final class ExtensibleDataProcessor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface + * @var EntityValueProcessorInterface */ private $processor; - /** - * @param \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface $processor - */ public function __construct( EntityValueProcessorInterface $processor ) { $this->processor = $processor; } - /** - * @inheritdoc - */ public function process($entity, string $key, $values): void { if ($this->isValid($entity, $key, $values)) { @@ -42,7 +34,7 @@ public function process($entity, string $key, $values): void } /** - * Check wether the entity object and the value key are valid + * Check whether the entity object and the value key are valid * * @param object $entity * @param string $key @@ -53,6 +45,6 @@ private function isValid($entity, string $key, $values): bool { return $entity instanceof ExtensibleDataInterface && $key === ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY && - \is_iterable($values); + is_iterable($values); } } diff --git a/Model/Entity/EntityValue/StrategyProcessor.php b/Model/Entity/EntityValue/StrategyProcessor.php index 905c050..ce09200 100644 --- a/Model/Entity/EntityValue/StrategyProcessor.php +++ b/Model/Entity/EntityValue/StrategyProcessor.php @@ -8,33 +8,30 @@ namespace Opengento\Gdpr\Model\Entity\EntityValue; use Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface; +use function array_combine; +use function array_keys; +use function array_values; -/** - * Class StrategyProcessor - */ final class StrategyProcessor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface[] + * @var EntityValueProcessorInterface[] */ private $processors; /** - * @param \Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface[] $processors + * @param EntityValueProcessorInterface[] $processors */ public function __construct( array $processors ) { $this->processors = (static function (EntityValueProcessorInterface ...$processors): array { return $processors; - })(...\array_values($processors)); + })(...array_values($processors)); - $this->processors = \array_combine(\array_keys($processors), $this->processors); + $this->processors = array_combine(array_keys($processors), $this->processors); } - /** - * @inheritdoc - */ public function process($entity, string $key, $value): void { ($this->processors[$key] ?? $this->processors['default'])->process($entity, $key, $value); diff --git a/Model/Entity/EntityValueProcessorInterface.php b/Model/Entity/EntityValueProcessorInterface.php index 60da55d..88c75c3 100644 --- a/Model/Entity/EntityValueProcessorInterface.php +++ b/Model/Entity/EntityValueProcessorInterface.php @@ -3,18 +3,16 @@ * Copyright © OpenGento, All rights reserved. * See LICENSE bundled with this library for license details. */ +declare(strict_types=1); namespace Opengento\Gdpr\Model\Entity; /** - * Interface EntityValueProcessorInterface * @api */ interface EntityValueProcessorInterface { /** - * Process the entity by passing it a value and its key - * * @param object $entity * @param string $key * @param mixed $value diff --git a/Model/Entity/Metadata.php b/Model/Entity/Metadata.php index f894a81..5e417ac 100644 --- a/Model/Entity/Metadata.php +++ b/Model/Entity/Metadata.php @@ -8,14 +8,12 @@ namespace Opengento\Gdpr\Model\Entity; use Magento\Framework\App\Config\ScopeConfigInterface; +use function explode; -/** - * Class Metadata - */ final class Metadata implements MetadataInterface { /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ private $scopeConfig; @@ -29,11 +27,6 @@ final class Metadata implements MetadataInterface */ private $scopeType; - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param string $configPath - * @param string $scopeType - */ public function __construct( ScopeConfigInterface $scopeConfig, string $configPath, @@ -44,11 +37,8 @@ public function __construct( $this->scopeType = $scopeType; } - /** - * @inheritdoc - */ public function getAttributes(?string $scopeCode = null): array { - return \explode(',', $this->scopeConfig->getValue($this->configPath, $this->scopeType, $scopeCode) ?? ''); + return explode(',', $this->scopeConfig->getValue($this->configPath, $this->scopeType, $scopeCode) ?? ''); } } diff --git a/Model/Entity/MetadataInterface.php b/Model/Entity/MetadataInterface.php index c311f37..ef95eb2 100644 --- a/Model/Entity/MetadataInterface.php +++ b/Model/Entity/MetadataInterface.php @@ -3,11 +3,11 @@ * Copyright © OpenGento, All rights reserved. * See LICENSE bundled with this library for license details. */ +declare(strict_types=1); namespace Opengento\Gdpr\Model\Entity; /** - * Interface MetadataInterface * @api */ interface MetadataInterface @@ -15,7 +15,7 @@ interface MetadataInterface /** * Retrieve the registered attributes * - * @param string|null $scopeCode + * @param string|null $scopeCode [optional] Current scope will be used. * @return string[] */ public function getAttributes(?string $scopeCode = null): array; diff --git a/Model/Entity/SourceProvider/FilterModifier.php b/Model/Entity/SourceProvider/FilterModifier.php index 5bcf79f..fc13c06 100644 --- a/Model/Entity/SourceProvider/FilterModifier.php +++ b/Model/Entity/SourceProvider/FilterModifier.php @@ -9,10 +9,8 @@ use Magento\Framework\Api\Filter; use Magento\Framework\Data\Collection; +use Magento\Framework\Exception\LocalizedException; -/** - * Class FilterModifier - */ final class FilterModifier implements ModifierInterface { /** @@ -25,10 +23,6 @@ final class FilterModifier implements ModifierInterface */ private $fieldToFilter; - /** - * @param string $filterIdentifier - * @param string $fieldToFilter - */ public function __construct( string $filterIdentifier, string $fieldToFilter @@ -39,7 +33,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function apply(Collection $collection, Filter $filter): void { diff --git a/Model/Entity/SourceProvider/ModifierComposite.php b/Model/Entity/SourceProvider/ModifierComposite.php index 5c77204..ab0e62f 100644 --- a/Model/Entity/SourceProvider/ModifierComposite.php +++ b/Model/Entity/SourceProvider/ModifierComposite.php @@ -17,12 +17,12 @@ final class ModifierComposite implements ModifierInterface { /** - * @var \Opengento\Gdpr\Model\Entity\SourceProvider\ModifierInterface[] + * @var ModifierInterface[] */ private $modifiers; /** - * @param \Opengento\Gdpr\Model\Entity\SourceProvider\ModifierInterface[] $modifiers + * @param ModifierInterface[] $modifiers */ public function __construct( array $modifiers @@ -32,9 +32,6 @@ public function __construct( })(...\array_values($modifiers)); } - /** - * @inheritdoc - */ public function apply(Collection $collection, Filter $filter): void { foreach ($this->modifiers as $modifier) { diff --git a/Model/Entity/SourceProvider/ModifierFactory.php b/Model/Entity/SourceProvider/ModifierFactory.php index 293a981..5d7df4d 100644 --- a/Model/Entity/SourceProvider/ModifierFactory.php +++ b/Model/Entity/SourceProvider/ModifierFactory.php @@ -10,7 +10,6 @@ use Magento\Framework\ObjectManagerInterface; /** - * Class ModifierFactory * @api */ final class ModifierFactory @@ -21,13 +20,13 @@ final class ModifierFactory private $modifiers; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $modifiers - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $modifiers, @@ -37,12 +36,6 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Retrieve the source provider modifier by entity type - * - * @param string $entityType - * @return \Opengento\Gdpr\Model\Entity\SourceProvider\ModifierInterface - */ public function get(string $entityType): ModifierInterface { return $this->objectManager->get($this->modifiers[$entityType] ?? $this->modifiers['default']); diff --git a/Model/Entity/SourceProvider/ModifierInterface.php b/Model/Entity/SourceProvider/ModifierInterface.php index 35cfe07..dcf4993 100644 --- a/Model/Entity/SourceProvider/ModifierInterface.php +++ b/Model/Entity/SourceProvider/ModifierInterface.php @@ -11,17 +11,9 @@ use Magento\Framework\Data\Collection; /** - * Interface ModifierInterface * @api */ interface ModifierInterface { - /** - * Apply custom filter on the source provider instance - * - * @param \Magento\Framework\Data\Collection $collection - * @param \Magento\Framework\Api\Filter $filter - * @return void - */ public function apply(Collection $collection, Filter $filter): void; } diff --git a/Model/Entity/SourceProviderFactory.php b/Model/Entity/SourceProviderFactory.php index 473e6e9..b81eec6 100644 --- a/Model/Entity/SourceProviderFactory.php +++ b/Model/Entity/SourceProviderFactory.php @@ -7,11 +7,12 @@ namespace Opengento\Gdpr\Model\Entity; +use InvalidArgumentException; use Magento\Framework\Data\Collection; use Magento\Framework\ObjectManagerInterface; +use function sprintf; /** - * Class SourceProviderFactory * @api */ final class SourceProviderFactory @@ -22,13 +23,13 @@ final class SourceProviderFactory private $sourceProviders; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $sourceProviders - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $sourceProviders, @@ -38,16 +39,10 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Create a new source provider by entity type - * - * @param string $entityType - * @return \Magento\Framework\Data\Collection - */ public function create(string $entityType): Collection { if (!isset($this->sourceProviders[$entityType])) { - throw new \InvalidArgumentException(\sprintf('Unknown source provider for entity type "%s".', $entityType)); + throw new InvalidArgumentException(sprintf('Unknown source provider for entity type "%s".', $entityType)); } return $this->objectManager->create($this->sourceProviders[$entityType]); diff --git a/Model/Erase/EraseEntityScheduler.php b/Model/Erase/EraseEntityScheduler.php index 8b4c7fd..6e3e64f 100644 --- a/Model/Erase/EraseEntityScheduler.php +++ b/Model/Erase/EraseEntityScheduler.php @@ -7,71 +7,66 @@ namespace Opengento\Gdpr\Model\Erase; +use Generator; use Magento\Framework\Api\Filter; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\LocalizedException; use Opengento\Gdpr\Api\EraseEntityManagementInterface; use Opengento\Gdpr\Model\Entity\SourceProvider\ModifierFactory; use Opengento\Gdpr\Model\Entity\SourceProviderFactory; -/** - * Class EraseEntityScheduler - */ final class EraseEntityScheduler { /** - * @var \Opengento\Gdpr\Model\Entity\SourceProviderFactory + * @var SourceProviderFactory */ private $sourceProviderFactory; /** - * @var \Opengento\Gdpr\Model\Entity\SourceProvider\ModifierFactory + * @var ModifierFactory */ private $sourceProviderModifierFactory; /** - * @var \Opengento\Gdpr\Api\EraseEntityManagementInterface + * @var EraseEntityManagementInterface */ - private $eraseEntityManagement; + private $eraseManagement; - /** - * @param \Opengento\Gdpr\Model\Entity\SourceProviderFactory $sourceProviderFactory - * @param \Opengento\Gdpr\Model\Entity\SourceProvider\ModifierFactory $sourceProviderModifierFactory - * @param \Opengento\Gdpr\Api\EraseEntityManagementInterface $eraseEntityManagement - */ public function __construct( SourceProviderFactory $sourceProviderFactory, ModifierFactory $sourceProviderModifierFactory, - EraseEntityManagementInterface $eraseEntityManagement + EraseEntityManagementInterface $eraseManagement ) { $this->sourceProviderFactory = $sourceProviderFactory; $this->sourceProviderModifierFactory = $sourceProviderModifierFactory; - $this->eraseEntityManagement = $eraseEntityManagement; + $this->eraseManagement = $eraseManagement; } /** - * Schedule filtered entities to erase - * * @param string[] $entityTypes - * @param \Magento\Framework\Api\Filter $filter - * @throws \Magento\Framework\Exception\CouldNotSaveException - * @throws \Magento\Framework\Exception\LocalizedException + * @param Filter $filter + * @throws CouldNotSaveException + * @throws LocalizedException */ public function schedule(array $entityTypes, Filter $filter): void { + /** + * @var string $entityType + * @var string[] $entityIds + */ foreach ($this->collectEntityIds($entityTypes, $filter) as $entityType => $entityIds) { foreach ($entityIds as $entityId) { - $this->eraseEntityManagement->create((int) $entityId, $entityType); + $this->eraseManagement->create((int) $entityId, $entityType); } } } /** - * Collect available entity ids by entity type - * * @param string[] $entityTypes - * @param \Magento\Framework\Api\Filter $filter - * @return \Generator + * @param Filter $filter + * @return Generator */ - private function collectEntityIds(array $entityTypes, Filter $filter): \Generator + private function collectEntityIds(array $entityTypes, Filter $filter): Generator { foreach ($entityTypes as $entityType) { $source = $this->sourceProviderFactory->create($entityType); diff --git a/Model/Erase/EraseSalesInformation.php b/Model/Erase/EraseSalesInformation.php index a6ab7ac..89a259b 100644 --- a/Model/Erase/EraseSalesInformation.php +++ b/Model/Erase/EraseSalesInformation.php @@ -7,6 +7,9 @@ namespace Opengento\Gdpr\Model\Erase; +use DateTimeImmutable; +use Exception; +use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Stdlib\DateTime; use Opengento\Gdpr\Api\Data\EraseEntityInterface; use Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory; @@ -14,31 +17,23 @@ use Opengento\Gdpr\Api\EraseSalesInformationInterface; use Opengento\Gdpr\Model\Config; -/** - * Class EraseSalesInformation - */ final class EraseSalesInformation implements EraseSalesInformationInterface { /** - * @var \Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory + * @var EraseEntityInterfaceFactory */ private $eraseEntityFactory; /** - * @var \Opengento\Gdpr\Api\EraseEntityRepositoryInterface + * @var EraseEntityRepositoryInterface */ private $eraseEntityRepository; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; - /** - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory $eraseEntityFactory - * @param \Opengento\Gdpr\Api\EraseEntityRepositoryInterface $eraseEntityRepository - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct( EraseEntityInterfaceFactory $eraseEntityFactory, EraseEntityRepositoryInterface $eraseEntityRepository, @@ -51,14 +46,14 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\CouldNotSaveException + * @throws CouldNotSaveException */ public function scheduleEraseEntity(int $entityId, string $entityType, \DateTime $lastActive): EraseEntityInterface { - $dateTime = \DateTimeImmutable::createFromMutable($lastActive); + $dateTime = DateTimeImmutable::createFromMutable($lastActive); $scheduleAt = $dateTime->modify('+' . $this->config->getErasureSalesMaxAge() . + 'days'); - /** @var \Opengento\Gdpr\Api\Data\EraseEntityInterface $eraseEntity */ + /** @var EraseEntityInterface $eraseEntity */ $eraseEntity = $this->eraseEntityFactory->create(); $eraseEntity->setEntityId($entityId); $eraseEntity->setEntityType($entityType); @@ -73,7 +68,7 @@ public function scheduleEraseEntity(int $entityId, string $entityType, \DateTime /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function isAlive(\DateTime $dateTime): bool { diff --git a/Model/Erase/NotifierInterface.php b/Model/Erase/NotifierInterface.php new file mode 100644 index 0000000..4765d66 --- /dev/null +++ b/Model/Erase/NotifierInterface.php @@ -0,0 +1,18 @@ +eraseEntityManagement = $eraseEntityManagement; + $this->eraseEntityChecker = $eraseEntityChecker; + } + + public function create(int $entityId, string $entityType): EraseEntityInterface + { + if ($this->eraseEntityChecker->canCreate($entityId, $entityType)) { + return $this->eraseEntityManagement->create($entityId, $entityType); + } + + throw new LocalizedException( + new Phrase( + 'Impossible to initiate the erasure, it\'s already processing or there is still pending orders.' + ) + ); + } + + public function cancel(int $entityId, string $entityType): bool + { + if ($this->eraseEntityChecker->canCancel($entityId, $entityType)) { + return $this->eraseEntityManagement->cancel($entityId, $entityType); + } + + throw new LocalizedException(new Phrase('The erasure process is running and cannot be undone.')); + } + + public function process(EraseEntityInterface $entity): EraseEntityInterface + { + if ($this->eraseEntityChecker->canProcess($entity->getEntityId(), $entity->getEntityType())) { + return $this->eraseEntityManagement->process($entity); + } + + throw new LocalizedException(new Phrase('Impossible to process the erasure, there is still pending orders.')); + } +} diff --git a/Model/EraseEntity.php b/Model/EraseEntity.php index 9c8470e..55433d2 100755 --- a/Model/EraseEntity.php +++ b/Model/EraseEntity.php @@ -9,154 +9,92 @@ use Magento\Framework\Model\AbstractExtensibleModel; use Opengento\Gdpr\Api\Data\EraseEntityInterface; -use Opengento\Gdpr\Model\ResourceModel\EraseEntity as EraseCustomerResource; +use Opengento\Gdpr\Model\ResourceModel\EraseEntity as EraseEntityResource; -/** - * Class EraseEntity - */ -final class EraseEntity extends AbstractExtensibleModel implements EraseEntityInterface +class EraseEntity extends AbstractExtensibleModel implements EraseEntityInterface { - /** - * @inheritdoc - */ - protected $_eventPrefix = 'opengento_gdpr_erase_entity'; - - /** - * @inheritdoc - */ - protected $_eventObject = 'erase_entity'; - - /** - * @inheritdoc - */ protected function _construct(): void { - $this->_init(EraseCustomerResource::class); + $this->_eventPrefix = 'opengento_gdpr_erase_entity'; + $this->_eventObject = 'erase_entity'; + $this->_init(EraseEntityResource::class); } - /** - * @inheritdoc - */ public function getEraseId(): int { return (int) $this->getId(); } - /** - * @inheritdoc - */ public function setEraseId(int $eraseId): EraseEntityInterface { return $this->setId($eraseId); } - /** - * @inheritdoc - */ public function getEntityId(): int { return (int) $this->_getData(self::ENTITY_ID); } - /** - * @inheritdoc - */ public function setEntityId($entityId): EraseEntityInterface { return $this->setData(self::ENTITY_ID, $entityId); } - /** - * @inheritdoc - */ public function getEntityType(): string { return (string) $this->_getData(self::ENTITY_TYPE); } - /** - * @inheritdoc - */ public function setEntityType(string $entityType): EraseEntityInterface { return $this->setData(self::ENTITY_TYPE, $entityType); } - /** - * @inheritdoc - */ public function getScheduledAt(): string { return (string) $this->_getData(self::SCHEDULED_AT); } - /** - * @inheritdoc - */ public function setScheduledAt(string $scheduledAt): EraseEntityInterface { return $this->setData(self::SCHEDULED_AT, $scheduledAt); } - /** - * @inheritdoc - */ public function getState(): string { return (string) $this->_getData(self::STATE); } - /** - * @inheritdoc - */ public function setState(string $state): EraseEntityInterface { return $this->setData(self::STATE, $state); } - /** - * @inheritdoc - */ public function getStatus(): string { return (string) $this->_getData(self::STATUS); } - /** - * @inheritdoc - */ public function setStatus(string $status): EraseEntityInterface { return $this->setData(self::STATUS, $status); } - /** - * @inheritdoc - */ public function getMessage(): ?string { return $this->_getData(self::MESSAGE) === null ? null : (string) $this->_getData(self::MESSAGE); } - /** - * @inheritdoc - */ public function setMessage(?string $message): EraseEntityInterface { return $this->setData(self::MESSAGE, $message); } - /** - * @inheritdoc - */ public function getErasedAt(): string { return (string) $this->_getData(self::ERASED_AT); } - /** - * @inheritdoc - */ public function setErasedAt(string $erasedAt): EraseEntityInterface { return $this->setData(self::ERASED_AT, $erasedAt); diff --git a/Model/EraseEntityChecker.php b/Model/EraseEntityChecker.php index a769f7a..d84987a 100644 --- a/Model/EraseEntityChecker.php +++ b/Model/EraseEntityChecker.php @@ -13,25 +13,18 @@ use Opengento\Gdpr\Api\EraseEntityRepositoryInterface; use Opengento\Gdpr\Model\Entity\EntityCheckerFactory; -/** - * Class EraseEntityChecker - */ final class EraseEntityChecker implements EraseEntityCheckerInterface { /** - * @var \Opengento\Gdpr\Api\EraseEntityRepositoryInterface + * @var EraseEntityRepositoryInterface */ private $eraseEntityRepository; /** - * @var \Opengento\Gdpr\Model\Entity\EntityCheckerFactory + * @var EntityCheckerFactory */ private $entityCheckerFactory; - /** - * @param \Opengento\Gdpr\Api\EraseEntityRepositoryInterface $eraseEntityRepository - * @param \Opengento\Gdpr\Model\Entity\EntityCheckerFactory $entityCheckerFactory - */ public function __construct( EraseEntityRepositoryInterface $eraseEntityRepository, EntityCheckerFactory $entityCheckerFactory @@ -40,9 +33,6 @@ public function __construct( $this->entityCheckerFactory = $entityCheckerFactory; } - /** - * @inheritdoc - */ public function exists(int $entityId, string $entityType): bool { try { @@ -52,9 +42,6 @@ public function exists(int $entityId, string $entityType): bool } } - /** - * @inheritdoc - */ public function canCreate(int $entityId, string $entityType): bool { $entityChecker = $this->entityCheckerFactory->get($entityType); @@ -62,9 +49,6 @@ public function canCreate(int $entityId, string $entityType): bool return !$this->exists($entityId, $entityType) && $entityChecker->canErase($entityId); } - /** - * @inheritdoc - */ public function canCancel(int $entityId, string $entityType): bool { try { @@ -77,9 +61,6 @@ public function canCancel(int $entityId, string $entityType): bool && $entity->getStatus() === EraseEntityInterface::STATUS_READY; } - /** - * @inheritdoc - */ public function canProcess(int $entityId, string $entityType): bool { try { diff --git a/Model/EraseEntityManagement.php b/Model/EraseEntityManagement.php index da0cbf5..dd610f8 100644 --- a/Model/EraseEntityManagement.php +++ b/Model/EraseEntityManagement.php @@ -7,90 +7,62 @@ namespace Opengento\Gdpr\Model; +use Exception; +use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Phrase; use Magento\Framework\Stdlib\DateTime as DateTimeFormat; use Magento\Framework\Stdlib\DateTime\DateTime; use Opengento\Gdpr\Api\Data\EraseEntityInterface; use Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory; -use Opengento\Gdpr\Api\EraseEntityCheckerInterface; use Opengento\Gdpr\Api\EraseEntityManagementInterface; use Opengento\Gdpr\Api\EraseEntityRepositoryInterface; use Opengento\Gdpr\Service\Erase\ProcessorFactory; -/** - * Class EraseEntityManagement - */ final class EraseEntityManagement implements EraseEntityManagementInterface { /** - * @var \Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory + * @var EraseEntityInterfaceFactory */ private $eraseEntityFactory; /** - * @var \Opengento\Gdpr\Api\EraseEntityRepositoryInterface + * @var EraseEntityRepositoryInterface */ private $eraseEntityRepository; /** - * @var \Opengento\Gdpr\Api\EraseEntityCheckerInterface - */ - private $eraseEntityChecker; - - /** - * @var \Opengento\Gdpr\Service\Erase\ProcessorFactory + * @var ProcessorFactory */ private $eraseProcessorFactory; /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; /** - * @var \Magento\Framework\Stdlib\DateTime\DateTime + * @var DateTime */ private $localeDate; - /** - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory $eraseEntityFactory - * @param \Opengento\Gdpr\Api\EraseEntityRepositoryInterface $eraseEntityRepository - * @param \Opengento\Gdpr\Api\EraseEntityCheckerInterface $eraseEntityChecker - * @param \Opengento\Gdpr\Service\Erase\ProcessorFactory $eraseProcessorFactory - * @param \Opengento\Gdpr\Model\Config $config - * @param \Magento\Framework\Stdlib\DateTime\DateTime $localeDate - */ public function __construct( EraseEntityInterfaceFactory $eraseEntityFactory, EraseEntityRepositoryInterface $eraseEntityRepository, - EraseEntityCheckerInterface $eraseEntityChecker, ProcessorFactory $eraseProcessorFactory, Config $config, DateTime $localeDate ) { $this->eraseEntityFactory = $eraseEntityFactory; $this->eraseEntityRepository = $eraseEntityRepository; - $this->eraseEntityChecker = $eraseEntityChecker; $this->eraseProcessorFactory = $eraseProcessorFactory; $this->config = $config; $this->localeDate = $localeDate; } - /** - * @inheritdoc - */ public function create(int $entityId, string $entityType): EraseEntityInterface { - if (!$this->eraseEntityChecker->canCreate($entityId, $entityType)) { - throw new LocalizedException( - new Phrase( - 'Impossible to initiate the erasure, it\'s already processing or there is still pending orders.' - ) - ); - } - - /** @var \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity */ + /** @var EraseEntityInterface $entity */ $entity = $this->eraseEntityFactory->create(); $entity->setEntityId($entityId); $entity->setEntityType($entityType); @@ -101,30 +73,13 @@ public function create(int $entityId, string $entityType): EraseEntityInterface return $this->eraseEntityRepository->save($entity); } - /** - * @inheritdoc - */ public function cancel(int $entityId, string $entityType): bool { - if (!$this->eraseEntityChecker->canCancel($entityId, $entityType)) { - throw new LocalizedException(new Phrase('The erasure process is running and cannot be undone.')); - } - return $this->eraseEntityRepository->delete($this->eraseEntityRepository->getByEntity($entityId, $entityType)); } - /** - * @inheritdoc - * @throws \Exception - */ public function process(EraseEntityInterface $entity): EraseEntityInterface { - if (!$this->eraseEntityChecker->canProcess($entity->getEntityId(), $entity->getEntityType())) { - throw new LocalizedException( - new Phrase('Impossible to process the erasure, there is still pending orders.') - ); - } - $entity->setState(EraseEntityInterface::STATE_PROCESSING); $entity->setStatus(EraseEntityInterface::STATUS_RUNNING); $entity = $this->eraseEntityRepository->save($entity); @@ -136,18 +91,16 @@ public function process(EraseEntityInterface $entity): EraseEntityInterface } return $this->fail($entity); - } catch (\Exception $e) { + } catch (Exception $e) { $this->fail($entity, $e->getMessage()); - throw $e; + throw new LocalizedException(new Phrase('Impossible to process the erasure: %1', [$e->getMessage()])); } } /** - * Erasure has succeeded - * - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity - * @return \Opengento\Gdpr\Api\Data\EraseEntityInterface - * @throws \Magento\Framework\Exception\CouldNotSaveException + * @param EraseEntityInterface $entity + * @return EraseEntityInterface + * @throws CouldNotSaveException */ private function success(EraseEntityInterface $entity): EraseEntityInterface { @@ -160,12 +113,10 @@ private function success(EraseEntityInterface $entity): EraseEntityInterface } /** - * Erasure has failed - * - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity - * @param string|null $message - * @return \Opengento\Gdpr\Api\Data\EraseEntityInterface - * @throws \Magento\Framework\Exception\CouldNotSaveException + * @param EraseEntityInterface $entity + * @param string|null $message [optional] + * @return EraseEntityInterface + * @throws CouldNotSaveException */ private function fail(EraseEntityInterface $entity, ?string $message = null): EraseEntityInterface { @@ -176,11 +127,6 @@ private function fail(EraseEntityInterface $entity, ?string $message = null): Er return $this->eraseEntityRepository->save($entity); } - /** - * Retrieve the final scheduled at date from config - * - * @return string - */ private function retrieveScheduledAt(): string { return $this->localeDate->gmtDate( diff --git a/Model/EraseEntityRepository.php b/Model/EraseEntityRepository.php index bdb6074..966d48a 100644 --- a/Model/EraseEntityRepository.php +++ b/Model/EraseEntityRepository.php @@ -7,153 +7,136 @@ namespace Opengento\Gdpr\Model; +use Exception; use Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface; use Magento\Framework\Api\SearchCriteriaInterface; -use Magento\Framework\Api\SearchResultsInterface; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Phrase; use Opengento\Gdpr\Api\Data\EraseEntityInterface; use Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory; +use Opengento\Gdpr\Api\Data\EraseEntitySearchResultsInterface; use Opengento\Gdpr\Api\Data\EraseEntitySearchResultsInterfaceFactory; use Opengento\Gdpr\Api\EraseEntityRepositoryInterface; -use Opengento\Gdpr\Model\ResourceModel\EraseEntity as EraseCustomerResource; +use Opengento\Gdpr\Model\ResourceModel\EraseEntity as EraseEntityResource; +use Opengento\Gdpr\Model\ResourceModel\EraseEntity\Collection; use Opengento\Gdpr\Model\ResourceModel\EraseEntity\CollectionFactory; -/** - * Class EraseEntityRepository - */ final class EraseEntityRepository implements EraseEntityRepositoryInterface { /** - * @var \Opengento\Gdpr\Model\ResourceModel\EraseEntity + * @var EraseEntityResource */ - private $eraseCustomerResource; + private $eraseEntityResource; /** - * @var \Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory + * @var EraseEntityInterfaceFactory */ - private $eraseCustomerFactory; + private $eraseEntityFactory; /** - * @var \Opengento\Gdpr\Model\ResourceModel\EraseEntity\CollectionFactory + * @var CollectionFactory */ private $collectionFactory; /** - * @var \Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface + * @var CollectionProcessorInterface */ private $collectionProcessor; /** - * @var \Opengento\Gdpr\Api\Data\EraseEntitySearchResultsInterfaceFactory + * @var EraseEntitySearchResultsInterfaceFactory */ private $searchResultsFactory; /** - * @var \Opengento\Gdpr\Api\Data\EraseEntityInterface[] + * @var EraseEntityInterface[] */ private $instances = []; /** - * @var \Opengento\Gdpr\Api\Data\EraseEntityInterface[] + * @var EraseEntityInterface[] */ private $instancesByEntity = []; - /** - * @param \Opengento\Gdpr\Model\ResourceModel\EraseEntity $eraseCustomerResource - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterfaceFactory $eraseCustomerFactory - * @param \Opengento\Gdpr\Model\ResourceModel\EraseEntity\CollectionFactory $collectionFactory - * @param \Magento\Framework\Api\SearchCriteria\CollectionProcessorInterface $collectionProcessor - * @param \Opengento\Gdpr\Api\Data\EraseEntitySearchResultsInterfaceFactory $searchResultsFactory - */ public function __construct( - EraseCustomerResource $eraseCustomerResource, - EraseEntityInterfaceFactory $eraseCustomerFactory, + EraseEntityResource $eraseEntityResource, + EraseEntityInterfaceFactory $eraseEntityFactory, CollectionFactory $collectionFactory, CollectionProcessorInterface $collectionProcessor, EraseEntitySearchResultsInterfaceFactory $searchResultsFactory ) { - $this->eraseCustomerResource = $eraseCustomerResource; - $this->eraseCustomerFactory = $eraseCustomerFactory; + $this->eraseEntityResource = $eraseEntityResource; + $this->eraseEntityFactory = $eraseEntityFactory; $this->collectionFactory = $collectionFactory; $this->collectionProcessor = $collectionProcessor; $this->searchResultsFactory = $searchResultsFactory; } - /** - * @inheritdoc - */ - public function save(EraseEntityInterface $entity): EraseEntityInterface + public function save(EraseEntityInterface $eraseEntity): EraseEntityInterface { try { - $this->eraseCustomerResource->save($entity); - $this->register($entity); - } catch (\Exception $e) { + $this->eraseEntityResource->save($eraseEntity); + $this->register($eraseEntity); + } catch (Exception $e) { throw new CouldNotSaveException(new Phrase('Could not save the entity.'), $e); } - return $entity; + return $eraseEntity; } - /** - * @inheritdoc - */ - public function getById(int $entityId, bool $forceReload = false): EraseEntityInterface + public function getById(int $eraseId): EraseEntityInterface { - if ($forceReload || !isset($this->instances[$entityId])) { - /** @var \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity */ - $entity = $this->eraseCustomerFactory->create(); - $this->eraseCustomerResource->load($entity, $entityId, EraseEntityInterface::ID); + if (!isset($this->instances[$eraseId])) { + /** @var EraseEntityInterface $eraseEntity */ + $eraseEntity = $this->eraseEntityFactory->create(); + $this->eraseEntityResource->load($eraseEntity, $eraseId, EraseEntityInterface::ID); - if (!$entity->getEntityId()) { - throw new NoSuchEntityException(new Phrase('Entity with id "%1" does not exists.', [$entityId])); + if (!$eraseEntity->getEraseId()) { + throw NoSuchEntityException::singleField(EraseEntityInterface::ID, $eraseId); } - $this->register($entity); + $this->register($eraseEntity); } - return $this->instances[$entityId]; + return $this->instances[$eraseId]; } - /** - * @inheritdoc - */ - public function getByEntity(int $entityId, string $entityType, bool $forceReload = false): EraseEntityInterface + public function getByEntity(int $entityId, string $entityType): EraseEntityInterface { - if ($forceReload || !isset($this->instancesByEntity[$entityId])) { - /** @var \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity */ - $entity = $this->eraseCustomerFactory->create(); - $this->eraseCustomerResource->load( - $entity, + if (!isset($this->instancesByEntity[$entityType . '_' . $entityId])) { + /** @var EraseEntityInterface $eraseEntity */ + $eraseEntity = $this->eraseEntityFactory->create(); + $this->eraseEntityResource->load( + $eraseEntity, [$entityId, $entityType], [EraseEntityInterface::ENTITY_ID, EraseEntityInterface::ENTITY_TYPE] ); - if (!$entity->getEntityId()) { - throw new NoSuchEntityException( - new Phrase('Entity with customer id "%1" does not exist.', [$entityId]) + if (!$eraseEntity->getEraseId()) { + throw NoSuchEntityException::doubleField( + EraseEntityInterface::ENTITY_ID, + $entityId, + EraseEntityInterface::ENTITY_TYPE, + $entityType ); } - $this->register($entity); + $this->register($eraseEntity); } return $this->instancesByEntity[$entityType . '_' . $entityId]; } - /** - * @inheritdoc - */ - public function getList(SearchCriteriaInterface $searchCriteria): SearchResultsInterface + public function getList(SearchCriteriaInterface $searchCriteria): EraseEntitySearchResultsInterface { - /** @var \Opengento\Gdpr\Model\ResourceModel\EraseEntity\Collection $collection */ + /** @var Collection $collection */ $collection = $this->collectionFactory->create(); $this->collectionProcessor->process($searchCriteria, $collection); - /** @var \Opengento\Gdpr\Api\Data\EraseEntitySearchResultsInterface $searchResults */ + /** @var EraseEntitySearchResultsInterface $searchResults */ $searchResults = $this->searchResultsFactory->create(); $searchResults->setSearchCriteria($searchCriteria); $searchResults->setItems($collection->getItems()); @@ -162,17 +145,14 @@ public function getList(SearchCriteriaInterface $searchCriteria): SearchResultsI return $searchResults; } - /** - * @inheritdoc - */ - public function delete(EraseEntityInterface $entity): bool + public function delete(EraseEntityInterface $eraseEntity): bool { try { - $this->remove($entity); - $this->eraseCustomerResource->delete($entity); - } catch (\Exception $e) { + $this->remove($eraseEntity); + $this->eraseEntityResource->delete($eraseEntity); + } catch (Exception $e) { throw new CouldNotDeleteException( - new Phrase('Could not delete entity with id "%1".', [$entity->getEntityId()]), + new Phrase('Could not delete entity with id "%1".', [$eraseEntity->getEraseId()]), $e ); } @@ -180,29 +160,17 @@ public function delete(EraseEntityInterface $entity): bool return true; } - /** - * Register the entity into the registry - * - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity - * @return void - */ - private function register(EraseEntityInterface $entity): void + private function register(EraseEntityInterface $eraseEntity): void { - $this->instances[$entity->getEntityId()] = $entity; - $this->instancesByEntity[$entity->getEntityType() . '_' . $entity->getEntityId()] = $entity; + $this->instances[$eraseEntity->getEraseId()] = $eraseEntity; + $this->instancesByEntity[$eraseEntity->getEntityType() . '_' . $eraseEntity->getEntityId()] = $eraseEntity; } - /** - * Remove the entity from the registry - * - * @param \Opengento\Gdpr\Api\Data\EraseEntityInterface $entity - * @return void - */ - private function remove(EraseEntityInterface $entity): void + private function remove(EraseEntityInterface $eraseEntity): void { unset( - $this->instances[$entity->getEntityId()], - $this->instancesByEntity[$entity->getEntityType() . '_' . $entity->getEntityId()] + $this->instances[$eraseEntity->getEraseId()], + $this->instancesByEntity[$eraseEntity->getEntityType() . '_' . $eraseEntity->getEntityId()] ); } } diff --git a/Model/Export/AbstractExportEntityDecorator.php b/Model/Export/AbstractExportEntityDecorator.php deleted file mode 100644 index bdb42d5..0000000 --- a/Model/Export/AbstractExportEntityDecorator.php +++ /dev/null @@ -1,54 +0,0 @@ -exportEntity = $exportEntity; - } - - /** - * @inheritdoc - */ - public function getEntityId(): int - { - return $this->exportEntity->getEntityId(); - } - - /** - * @inheritdoc - */ - public function getEntityType(): string - { - return $this->exportEntity->getEntityType(); - } - - /** - * @inheritdoc - */ - public function getFileName(): string - { - return $this->exportEntity->getFileName(); - } -} diff --git a/Model/Export/ExportEntityData.php b/Model/Export/ExportEntityData.php new file mode 100644 index 0000000..66c9cfc --- /dev/null +++ b/Model/Export/ExportEntityData.php @@ -0,0 +1,70 @@ +exportEntityRepository = $exportEntityRepository; + $this->exportEntityManagement = $exportEntityManagement; + $this->exportEntityChecker = $exportEntityChecker; + } + + /** + * Export the entity to a file + * + * @param int $entityId + * @param string $entityType + * @return string + * @throws AlreadyExistsException + * @throws CouldNotSaveException + * @throws LocalizedException + */ + public function export(int $entityId, string $entityType): string + { + try { + $exportEntity = $this->exportEntityRepository->getByEntity($entityId, $entityType); + } catch (NoSuchEntityException $e) { + $exportEntity = $this->exportEntityManagement->create($entityId, $entityType); + } + + return $this->exportEntityChecker->isExported($entityId, $entityType) + ? $exportEntity->getFilePath() + : $this->exportEntityManagement->export($exportEntity); + } +} diff --git a/Model/Export/ExportEntityFactory.php b/Model/Export/ExportEntityFactory.php deleted file mode 100644 index 7756aba..0000000 --- a/Model/Export/ExportEntityFactory.php +++ /dev/null @@ -1,58 +0,0 @@ -exportEntityList = $exportEntityList; - $this->objectManager = $objectManager; - } - - /** - * Create export entity information - * - * @param int $entityId - * @return \Opengento\Gdpr\Api\Data\ExportEntityInterface - */ - public function create(int $entityId): ExportEntityInterface - { - $exportEntity = new ExportEntity($entityId); - - foreach ($this->exportEntityList as $exportEntityItem) { - $exportEntity = $this->objectManager->create($exportEntityItem, ['exportEntity' => $exportEntity]); - } - - return $exportEntity; - } -} diff --git a/Model/Export/ExportPersonalData.php b/Model/Export/ExportPersonalData.php deleted file mode 100644 index bd68cd4..0000000 --- a/Model/Export/ExportPersonalData.php +++ /dev/null @@ -1,24 +0,0 @@ -exportProcessorFactory = $exportProcessorFactory; + $this->exportRendererFactory = $exportRendererFactory; + $this->archive = $archive; + $this->config = $config; + } + + /** + * @param ExportEntityInterface $exportEntity + * @return string|null + * @throws FileSystemException + * @throws NotFoundException + */ + public function export(ExportEntityInterface $exportEntity): ?string + { + $exporter = $this->exportProcessorFactory->get($exportEntity->getEntityType()); + $fileName = $this->prepareFileName($exportEntity); + $data = $exporter->execute($exportEntity->getEntityId(), []); + foreach ($this->config->getExportRendererCodes() as $rendererCode) { + $filePath = $this->archive->prepareArchive( + $this->exportRendererFactory->get($rendererCode)->saveData($fileName, $data), + $fileName . '.zip' + ); + } + + return $filePath ?? null; + } + + private function prepareFileName(ExportEntityInterface $exportEntity): string + { + return 'gdpr' . + DIRECTORY_SEPARATOR . + sha1($exportEntity->getEntityType() . $exportEntity->getExportId()) . + DIRECTORY_SEPARATOR . + $exportEntity->getFileName(); + } +} diff --git a/Model/Export/NotifierInterface.php b/Model/Export/NotifierInterface.php new file mode 100644 index 0000000..637beec --- /dev/null +++ b/Model/Export/NotifierInterface.php @@ -0,0 +1,18 @@ +entityId = $entityId; - $this->entityType = $entityType; - $this->fileName = $fileName; - } - - /** - * @inheritdoc - */ + protected function _construct(): void + { + $this->_eventPrefix = 'opengento_gdpr_export_entity'; + $this->_eventObject = 'export_entity'; + $this->_init(EraseEntityResource::class); + } + + public function getExportId(): int + { + return (int) $this->getId(); + } + + public function setExportId(int $exportId): ExportEntityInterface + { + return $this->setId($exportId); + } + public function getEntityId(): int { - return $this->entityId; + return (int) $this->_getData(self::ENTITY_ID); + } + + public function setEntityId($entityId): ExportEntityInterface + { + return $this->setData(self::ENTITY_ID, $entityId); } - /** - * @inheritdoc - */ public function getEntityType(): string { - return $this->entityType; + return (string) $this->_getData(self::ENTITY_TYPE); + } + + public function setEntityType(string $entityType): ExportEntityInterface + { + return $this->setData(self::ENTITY_TYPE, $entityType); } - /** - * @inheritdoc - */ public function getFileName(): string { - return $this->fileName; + return (string) $this->_getData(self::FILE_NAME); + } + + public function setFileName(string $filename): ExportEntityInterface + { + return $this->setData(self::FILE_NAME, $filename); + } + + public function getFilePath(): ?string + { + return $this->_getData(self::FILE_PATH) === null ? null : (string) $this->_getData(self::FILE_PATH); + } + + public function setFilePath(?string $filePath): ExportEntityInterface + { + return $this->setData(self::FILE_PATH, $filePath); + } + + public function getCreatedAt(): string + { + return (string) $this->_getData(self::CREATED_AT); + } + + public function setCreatedAt(string $createdAt): ExportEntityInterface + { + return $this->setData(self::CREATED_AT, $createdAt); + } + + public function getExportedAt(): ?string + { + return $this->_getData(self::EXPORTED_AT) === null ? null : (string) $this->_getData(self::EXPORTED_AT); + } + + public function setExportedAt(string $exportedAt): ExportEntityInterface + { + return $this->setData(self::EXPORTED_AT, $exportedAt); + } + + public function getExpiredAt(): string + { + return (string) $this->_getData(self::EXPIRED_AT); + } + + public function setExpiredAt(string $expiredAt): ExportEntityInterface + { + return $this->setData(self::EXPIRED_AT, $expiredAt); } } diff --git a/Model/ExportEntityChecker.php b/Model/ExportEntityChecker.php new file mode 100644 index 0000000..8c82a19 --- /dev/null +++ b/Model/ExportEntityChecker.php @@ -0,0 +1,46 @@ +exportEntityRepository = $exportEntityRepository; + } + + public function exists(int $entityId, string $entityType): bool + { + try { + return (bool) $this->exportEntityRepository->getByEntity($entityId, $entityType)->getExportId(); + } catch (NoSuchEntityException $e) { + return false; + } + } + + public function isExported(int $entityId, string $entityType): bool + { + try { + $entity = $this->exportEntityRepository->getByEntity($entityId, $entityType); + } catch (NoSuchEntityException $e) { + return false; + } + + return $entity->getExportedAt() !== null && $entity->getFilePath() !== null; + } +} diff --git a/Model/ExportEntityManagement.php b/Model/ExportEntityManagement.php index 944382f..53cedb3 100644 --- a/Model/ExportEntityManagement.php +++ b/Model/ExportEntityManagement.php @@ -7,48 +7,92 @@ namespace Opengento\Gdpr\Model; +use Exception; +use Magento\Framework\Exception\AlreadyExistsException; +use Magento\Framework\Phrase; +use Magento\Framework\Stdlib\DateTime; use Opengento\Gdpr\Api\Data\ExportEntityInterface; +use Opengento\Gdpr\Api\Data\ExportEntityInterfaceFactory; +use Opengento\Gdpr\Api\ExportEntityCheckerInterface; use Opengento\Gdpr\Api\ExportEntityManagementInterface; -use Opengento\Gdpr\Service\Export\ProcessorFactory; -use Opengento\Gdpr\Service\Export\RendererInterface; +use Opengento\Gdpr\Api\ExportEntityRepositoryInterface; +use Opengento\Gdpr\Model\Export\ExportToFile; -/** - * Class ExportEntityManagement - */ final class ExportEntityManagement implements ExportEntityManagementInterface { /** - * @var \Opengento\Gdpr\Service\Export\ProcessorFactory + * @var ExportEntityInterfaceFactory + */ + private $exportEntityFactory; + + /** + * @var ExportEntityRepositoryInterface + */ + private $exportEntityRepository; + + /** + * @var ExportEntityCheckerInterface */ - private $exportProcessorFactory; + private $exportEntityChecker; /** - * @var \Opengento\Gdpr\Service\Export\RendererInterface + * @var ExportToFile */ - private $exportRenderer; + private $exportToFile; /** - * @param \Opengento\Gdpr\Service\Export\ProcessorFactory $exportProcessorFactory - * @param \Opengento\Gdpr\Service\Export\RendererInterface $exportRenderer + * @var Config */ + private $config; + public function __construct( - ProcessorFactory $exportProcessorFactory, - RendererInterface $exportRenderer + ExportEntityInterfaceFactory $exportEntityFactory, + ExportEntityRepositoryInterface $exportEntityRepository, + ExportEntityCheckerInterface $exportEntityChecker, + ExportToFile $exportToFile, + Config $config ) { - $this->exportProcessorFactory = $exportProcessorFactory; - $this->exportRenderer = $exportRenderer; + $this->exportEntityFactory = $exportEntityFactory; + $this->exportEntityRepository = $exportEntityRepository; + $this->exportEntityChecker = $exportEntityChecker; + $this->exportToFile = $exportToFile; + $this->config = $config; + } + + public function create(int $entityId, string $entityType, ?string $fileName = null): ExportEntityInterface + { + if ($this->exportEntityChecker->exists($entityId, $entityType)) { + throw new AlreadyExistsException( + new Phrase( + 'An export entity already exists for the entity type "%1" with ID "%2".', + [$entityType, $entityId] + ) + ); + } + + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $this->exportEntityFactory->create(); + $exportEntity->setEntityId($entityId); + $exportEntity->setEntityType($entityType); + $exportEntity->setFileName($fileName ?? $this->config->getExportFileName()); + $exportEntity = $this->exportEntityRepository->save($exportEntity); + + return $exportEntity; } /** * @inheritdoc + * @throws Exception */ - public function export(ExportEntityInterface $exportEntity): string + public function export(ExportEntityInterface $exportEntity): ExportEntityInterface { - $exporter = $this->exportProcessorFactory->get($exportEntity->getEntityType()); - - return $this->exportRenderer->saveData( - $exportEntity->getFileName(), - $exporter->execute($exportEntity->getEntityId(), []) + $exportEntity->setFilePath($this->exportToFile->export($exportEntity)); + $exportEntity->setExpiredAt( + (new \DateTime('+' . $this->config->getExportLifetime() . 'minutes'))->format(DateTime::DATETIME_PHP_FORMAT) ); + $exportEntity->setExportedAt((new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT)); + $this->exportEntityRepository->save($exportEntity); + + return $exportEntity; } } diff --git a/Model/ExportEntityRepository.php b/Model/ExportEntityRepository.php new file mode 100644 index 0000000..0783c59 --- /dev/null +++ b/Model/ExportEntityRepository.php @@ -0,0 +1,186 @@ +exportEntityResource = $exportEntityResource; + $this->exportEntityFactory = $exportEntityFactory; + $this->collectionFactory = $collectionFactory; + $this->collectionProcessor = $collectionProcessor; + $this->searchResultsFactory = $searchResultsFactory; + $this->fileSystem = $filesystem; + } + + public function save(ExportEntityInterface $exportEntity): ExportEntityInterface + { + try { + $this->exportEntityResource->save($exportEntity); + $this->register($exportEntity); + } catch (Exception $e) { + throw new CouldNotSaveException(new Phrase('Could not save the entity.'), $e); + } + + return $exportEntity; + } + + public function getById(int $exportId): ExportEntityInterface + { + if (!isset($this->instances[$exportId])) { + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $this->exportEntityFactory->create(); + $this->exportEntityResource->load($exportEntity, $exportId, ExportEntityInterface::ID); + + if (!$exportEntity->getExportId()) { + throw NoSuchEntityException::singleField(ExportEntityInterface::ID, $exportId); + } + + $this->register($exportEntity); + } + + return $this->instances[$exportId]; + } + + public function getByEntity(int $entityId, string $entityType): ExportEntityInterface + { + if (!isset($this->instancesByEntity[$entityType . '_' . $entityId])) { + /** @var ExportEntityInterface $exportEntity */ + $exportEntity = $this->exportEntityFactory->create(); + $this->exportEntityResource->load( + $exportEntity, + [$entityId, $entityType], + [ExportEntityInterface::ENTITY_ID, ExportEntityInterface::ENTITY_TYPE] + ); + + if (!$exportEntity->getExportId()) { + throw NoSuchEntityException::doubleField( + ExportEntityInterface::ENTITY_ID, + $entityId, + ExportEntityInterface::ENTITY_TYPE, + $entityType + ); + } + + $this->register($exportEntity); + } + + return $this->instancesByEntity[$entityType . '_' . $entityId]; + } + + public function getList(SearchCriteriaInterface $searchCriteria): ExportEntitySearchResultsInterface + { + /** @var Collection $collection */ + $collection = $this->collectionFactory->create(); + + $this->collectionProcessor->process($searchCriteria, $collection); + + /** @var ExportEntitySearchResultsInterface $searchResults */ + $searchResults = $this->searchResultsFactory->create(); + $searchResults->setSearchCriteria($searchCriteria); + $searchResults->setItems($collection->getItems()); + $searchResults->setTotalCount($collection->getSize()); + + return $searchResults; + } + + public function delete(ExportEntityInterface $exportEntity): bool + { + try { + $this->fileSystem->getDirectoryWrite(DirectoryList::TMP)->delete($exportEntity->getFilePath()); + $this->remove($exportEntity); + $this->exportEntityResource->delete($exportEntity); + } catch (Exception $e) { + throw new CouldNotDeleteException( + new Phrase('Could not delete entity with id "%1".', [$exportEntity->getExportId()]), + $e + ); + } + + return true; + } + + private function register(ExportEntityInterface $exportEntity): void + { + $this->instances[$exportEntity->getExportId()] = $exportEntity; + $this->instancesByEntity[$exportEntity->getEntityType() . '_' . $exportEntity->getEntityId()] = $exportEntity; + } + + private function remove(ExportEntityInterface $exportEntity): void + { + unset( + $this->instances[$exportEntity->getExportId()], + $this->instancesByEntity[$exportEntity->getEntityType() . '_' . $exportEntity->getEntityId()] + ); + } +} diff --git a/Model/Newsletter/Subscriber.php b/Model/Newsletter/Subscriber.php index 09deaa4..78a4b91 100644 --- a/Model/Newsletter/Subscriber.php +++ b/Model/Newsletter/Subscriber.php @@ -19,14 +19,10 @@ final class Subscriber { /** - * @var \Magento\Newsletter\Model\Subscriber + * @var SubscriberModel */ private $subscriber; - /** - * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory - * @param array $data [optional] - */ public function __construct( SubscriberFactory $subscriberFactory, array $data = [] @@ -34,19 +30,11 @@ public function __construct( $this->subscriber = $subscriberFactory->create(['data' => $data]); } - /** - * Retrieve the real subscriber subject - * - * @return \Magento\Newsletter\Model\Subscriber - */ public function getRealSubscriber(): SubscriberModel { return $this->subscriber; } - /** - * @inheritdoc - */ public function __call($method, $args) { return $this->subscriber->{$method}(...$args); diff --git a/Model/Notifier/AbstractMailSender.php b/Model/Notifier/AbstractMailSender.php new file mode 100644 index 0000000..5496a53 --- /dev/null +++ b/Model/Notifier/AbstractMailSender.php @@ -0,0 +1,167 @@ +transportBuilder = $transportBuilder; + $this->scopeConfig = $scopeConfig; + $this->configPaths = $configPaths; + } + + /** + * @param string $to + * @param string|null $name [optional] Specify the to name. + * @param int|null $storeId [optional Current store ID is used by default. + * @param array $vars + * @throws LocalizedException + * @throws MailException + */ + protected function sendMail(string $to, ?string $name = null, ?int $storeId = null, array $vars = []): void + { + if ($this->isAvailable($storeId)) { + $copyTo = $this->getCopyTo($storeId); + + if ($copyTo) { + $copyMethod = $this->getCopyMethod($storeId); + if ($copyMethod === 'copy') { + foreach ($copyTo as $email) { + $this->prepareMail($email, $name, $storeId, $vars); + $this->transportBuilder->getTransport()->sendMessage(); + } + } elseif ($copyMethod === 'bcc') { + foreach ($copyTo as $email) { + $this->transportBuilder->addBcc($email); + } + } + } + + $this->prepareMail($to, $name, $storeId, $vars); + $transport = $this->transportBuilder->getTransport(); + + $transport->sendMessage(); + } + } + + /** + * @param string $to + * @param string|null $name [optional] Specify the to name. + * @param int|null $storeId [optional Current store ID is used by default. + * @param array $vars + * @throws MailException + */ + protected function prepareMail(string $to, ?string $name = null, ?int $storeId = null, array $vars = []): void + { + $this->transportBuilder->setTemplateIdentifier($this->getTemplateIdentifier($storeId)) + ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId]) + ->setTemplateVars($vars) + ->setFromByScope($this->getFrom($storeId), $storeId) + ->addTo($to, $name); + } + + /** + * @param int|null $storeId [optional] Retrieves the value by scope. + * @return bool + */ + protected function isAvailable(?int $storeId = null): bool + { + return $this->scopeConfig->isSetFlag( + $this->configPaths['is_available'], + ScopeInterface::SCOPE_STORE, + $storeId + ); + } + + /** + * @param int|null $storeId [optional] Retrieves the value by scope. + * @return string + */ + protected function getFrom(?int $storeId = null): string + { + return (string) $this->scopeConfig->getValue( + $this->configPaths['from'], + ScopeInterface::SCOPE_STORE, + $storeId + ); + } + + /** + * @param int|null $storeId [optional] Retrieves the value by scope. + * @return array + */ + protected function getCopyTo(?int $storeId = null): array + { + return explode( + ',', + $this->scopeConfig->getValue( + $this->configPaths['copy_to'], + ScopeInterface::SCOPE_STORE, + $storeId + ) ?? '' + ); + } + + /** + * @param int|null $storeId [optional] Retrieves the value by scope. + * @return string + */ + protected function getCopyMethod(?int $storeId = null): string + { + return (string) $this->scopeConfig->getValue( + $this->configPaths['copy_method'], + ScopeInterface::SCOPE_STORE, + $storeId + ); + } + + /** + * @param int|null $storeId [optional] Retrieves the value by scope. + * @return string + */ + protected function getTemplateIdentifier(?int $storeId = null): string + { + return (string) $this->scopeConfig->getValue( + $this->configPaths['template_identifier'], + ScopeInterface::SCOPE_STORE, + $storeId + ); + } +} diff --git a/Model/Order/Anonymize/Processor/OrderDataProcessor.php b/Model/Order/Anonymize/Processor/OrderDataProcessor.php index 64738a8..87cd815 100644 --- a/Model/Order/Anonymize/Processor/OrderDataProcessor.php +++ b/Model/Order/Anonymize/Processor/OrderDataProcessor.php @@ -7,43 +7,38 @@ namespace Opengento\Gdpr\Model\Order\Anonymize\Processor; +use DateTime; +use Exception; +use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Api\OrderAddressRepositoryInterface; use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\Order; use Opengento\Gdpr\Api\EraseSalesInformationInterface; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class OrderDataProcessor - */ final class OrderDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Sales\Api\OrderAddressRepositoryInterface + * @var OrderAddressRepositoryInterface */ private $orderAddressRepository; /** - * @var \Opengento\Gdpr\Api\EraseSalesInformationInterface + * @var EraseSalesInformationInterface */ private $eraseSalesInformation; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Sales\Api\OrderAddressRepositoryInterface $orderAddressRepository - * @param \Opengento\Gdpr\Api\EraseSalesInformationInterface $eraseSalesInformation - */ public function __construct( AnonymizerInterface $anonymizer, OrderRepositoryInterface $orderRepository, @@ -58,13 +53,13 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $orderId): bool { - /** @var \Magento\Sales\Model\Order $order */ + /** @var Order $order */ $order = $this->orderRepository->get($orderId); - $lastActive = new \DateTime($order->getUpdatedAt()); + $lastActive = new DateTime($order->getUpdatedAt()); if ($this->eraseSalesInformation->isAlive($lastActive)) { $this->eraseSalesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive); @@ -74,7 +69,7 @@ public function execute(int $orderId): bool $this->orderRepository->save($this->anonymizer->anonymize($order)); - /** @var \Magento\Sales\Api\Data\OrderAddressInterface|null $orderAddress */ + /** @var OrderAddressInterface|null $orderAddress */ foreach ([$order->getBillingAddress(), $order->getShippingAddress()] as $orderAddress) { if ($orderAddress) { $this->orderAddressRepository->save($this->anonymizer->anonymize($orderAddress)); diff --git a/Model/Order/Anonymize/Processor/QuoteDataProcessor.php b/Model/Order/Anonymize/Processor/QuoteDataProcessor.php index 9dafd89..15b8626 100644 --- a/Model/Order/Anonymize/Processor/QuoteDataProcessor.php +++ b/Model/Order/Anonymize/Processor/QuoteDataProcessor.php @@ -7,44 +7,37 @@ namespace Opengento\Gdpr\Model\Order\Anonymize\Processor; +use Exception; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; use Magento\Quote\Model\ResourceModel\Quote\Address; use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class QuoteDataProcessor - */ final class QuoteDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ private $quoteRepository; /** - * @var \Magento\Quote\Model\ResourceModel\Quote\Address + * @var Address */ private $quoteAddressResourceModel; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param \Magento\Quote\Model\ResourceModel\Quote\Address $quoteAddressResourceModel - */ public function __construct( AnonymizerInterface $anonymizer, OrderRepositoryInterface $orderRepository, @@ -59,18 +52,18 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $orderId): bool { try { $order = $this->orderRepository->get($orderId); - /** @var \Magento\Quote\Model\Quote $quote */ + /** @var Quote $quote */ $quote = $this->quoteRepository->get($order->getQuoteId()); $this->quoteRepository->save($this->anonymizer->anonymize($quote)); - /** @var \Magento\Quote\Model\Quote\Address|null $quoteAddress */ + /** @var Quote\Address|null $quoteAddress */ foreach ([$quote->getBillingAddress(), $quote->getShippingAddress()] as $quoteAddress) { if ($quoteAddress) { $this->quoteAddressResourceModel->save($this->anonymizer->anonymize($quoteAddress)); diff --git a/Model/Order/Anonymize/Processor/SubscriberDataProcessor.php b/Model/Order/Anonymize/Processor/SubscriberDataProcessor.php index e6892e9..f7a8272 100644 --- a/Model/Order/Anonymize/Processor/SubscriberDataProcessor.php +++ b/Model/Order/Anonymize/Processor/SubscriberDataProcessor.php @@ -7,43 +7,36 @@ namespace Opengento\Gdpr\Model\Order\Anonymize\Processor; +use Exception; use Magento\Newsletter\Model\ResourceModel\Subscriber as ResourceSubscriber; use Magento\Sales\Api\OrderRepositoryInterface; +use Opengento\Gdpr\Model\Newsletter\Subscriber; use Opengento\Gdpr\Model\Newsletter\SubscriberFactory; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class SubscriberDataProcessor - */ final class SubscriberDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Opengento\Gdpr\Model\Newsletter\SubscriberFactory + * @var SubscriberFactory */ private $subscriberFactory; /** - * @var \Magento\Newsletter\Model\ResourceModel\Subscriber + * @var ResourceSubscriber */ private $subscriberResourceModel; - /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Opengento\Gdpr\Model\Newsletter\SubscriberFactory $subscriberFactory - * @param \Magento\Newsletter\Model\ResourceModel\Subscriber $subscriberResourceModel - */ public function __construct( AnonymizerInterface $anonymizer, OrderRepositoryInterface $orderRepository, @@ -58,13 +51,13 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $orderId): bool { $order = $this->orderRepository->get($orderId); - /** @var \Opengento\Gdpr\Model\Newsletter\Subscriber $subscriber */ + /** @var Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); $subscriber->loadByEmail($order->getCustomerEmail()); $this->anonymizer->anonymize($subscriber); diff --git a/Model/Order/Delete/Processor/OrderDataProcessor.php b/Model/Order/Delete/Processor/OrderDataProcessor.php index b50d331..e502b2e 100644 --- a/Model/Order/Delete/Processor/OrderDataProcessor.php +++ b/Model/Order/Delete/Processor/OrderDataProcessor.php @@ -7,29 +7,24 @@ namespace Opengento\Gdpr\Model\Order\Delete\Processor; +use DateTime; +use Exception; use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Api\EraseSalesInformationInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class OrderDataProcessor - */ final class OrderDataProcessor implements ProcessorInterface { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Opengento\Gdpr\Api\EraseSalesInformationInterface + * @var EraseSalesInformationInterface */ private $eraseSalesInformation; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Opengento\Gdpr\Api\EraseSalesInformationInterface $eraseSalesInformation - */ public function __construct( OrderRepositoryInterface $orderRepository, EraseSalesInformationInterface $eraseSalesInformation @@ -40,12 +35,12 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $orderId): bool { $order = $this->orderRepository->get($orderId); - $lastActive = new \DateTime($order->getUpdatedAt()); + $lastActive = new DateTime($order->getUpdatedAt()); if ($this->eraseSalesInformation->isAlive($lastActive)) { $this->eraseSalesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive); diff --git a/Model/Order/Delete/Processor/QuoteDataProcessor.php b/Model/Order/Delete/Processor/QuoteDataProcessor.php index dedb06b..55d7ef1 100644 --- a/Model/Order/Delete/Processor/QuoteDataProcessor.php +++ b/Model/Order/Delete/Processor/QuoteDataProcessor.php @@ -12,25 +12,18 @@ use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class QuoteDataProcessor - */ final class QuoteDataProcessor implements ProcessorInterface { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ private $quoteRepository; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - */ public function __construct( OrderRepositoryInterface $orderRepository, CartRepositoryInterface $quoteRepository @@ -39,9 +32,6 @@ public function __construct( $this->quoteRepository = $quoteRepository; } - /** - * @inheritdoc - */ public function execute(int $orderId): bool { try { diff --git a/Model/Order/Delete/Processor/SubscriberDataProcessor.php b/Model/Order/Delete/Processor/SubscriberDataProcessor.php index 10f0cd5..00234a9 100644 --- a/Model/Order/Delete/Processor/SubscriberDataProcessor.php +++ b/Model/Order/Delete/Processor/SubscriberDataProcessor.php @@ -7,36 +7,30 @@ namespace Opengento\Gdpr\Model\Order\Delete\Processor; +use Exception; use Magento\Newsletter\Model\ResourceModel\Subscriber as ResourceSubscriber; +use Magento\Newsletter\Model\Subscriber; use Magento\Newsletter\Model\SubscriberFactory; use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Service\Erase\ProcessorInterface; -/** - * Class SubscriberDataProcessor - */ final class SubscriberDataProcessor implements ProcessorInterface { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; /** - * @var \Magento\Newsletter\Model\SubscriberFactory + * @var SubscriberFactory */ private $subscriberFactory; /** - * @var \Magento\Newsletter\Model\ResourceModel\Subscriber + * @var ResourceSubscriber */ private $subscriberResourceModel; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory - * @param \Magento\Newsletter\Model\ResourceModel\Subscriber $subscriberResourceModel - */ public function __construct( OrderRepositoryInterface $orderRepository, SubscriberFactory $subscriberFactory, @@ -49,13 +43,13 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function execute(int $orderId): bool { $order = $this->orderRepository->get($orderId); - /** @var \Magento\Newsletter\Model\Subscriber $subscriber */ + /** @var Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); $subscriber->loadByEmail($order->getCustomerEmail()); $this->subscriberResourceModel->delete($subscriber); diff --git a/Model/Order/Erase/Notifier.php b/Model/Order/Erase/Notifier.php new file mode 100644 index 0000000..0e3a54e --- /dev/null +++ b/Model/Order/Erase/Notifier.php @@ -0,0 +1,49 @@ +senders = (static function (SenderInterface ...$senders): array { + return $senders; + })(...\array_values($senders)); + $this->orderRepository = $orderRepository; + } + + public function notify(EraseEntityInterface $eraseEntity): void + { + $order = $this->orderRepository->get($eraseEntity->getEntityId()); + + foreach ($this->senders as $sender) { + $sender->send($order); + } + } +} diff --git a/Model/Order/Export/ExportOrder.php b/Model/Order/Export/ExportOrder.php deleted file mode 100644 index 2dabe98..0000000 --- a/Model/Order/Export/ExportOrder.php +++ /dev/null @@ -1,26 +0,0 @@ -senders = (static function (SenderInterface ...$senders): array { + return $senders; + })(...\array_values($senders)); + $this->orderRepository = $orderRepository; + } + + /** + * @inheritdoc + */ + public function notify(ExportEntityInterface $exportEntity): void + { + $order = $this->orderRepository->get($exportEntity->getEntityId()); + + foreach ($this->senders as $sender) { + $sender->send($order); + } + } +} diff --git a/Model/Order/Export/Processor/AbstractDataProcessor.php b/Model/Order/Export/Processor/AbstractDataProcessor.php index df2cfe4..1132a26 100644 --- a/Model/Order/Export/Processor/AbstractDataProcessor.php +++ b/Model/Order/Export/Processor/AbstractDataProcessor.php @@ -12,20 +12,13 @@ use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Export\Processor\AbstractDataProcessor as AbstractExportDataProcessor; -/** - * Class AbstractDataProcessor - */ abstract class AbstractDataProcessor extends AbstractExportDataProcessor { /** - * @var \Magento\Sales\Api\OrderRepositoryInterface + * @var OrderRepositoryInterface */ private $orderRepository; - /** - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( OrderRepositoryInterface $orderRepository, DataCollectorInterface $dataCollector @@ -34,9 +27,6 @@ public function __construct( parent::__construct($dataCollector); } - /** - * @inheritdoc - */ public function execute(int $entityId, array $data): array { return $this->export($this->orderRepository->get($entityId), $data); @@ -46,7 +36,7 @@ public function execute(int $entityId, array $data): array * Execute the export processor for the given order entity. * It allows to retrieve the related data as an array. * - * @param \Magento\Sales\Api\Data\OrderInterface $order + * @param OrderInterface $order * @param array $ata * @return array */ diff --git a/Model/Order/Export/Processor/OrderDataProcessor.php b/Model/Order/Export/Processor/OrderDataProcessor.php index 5a92558..ed51842 100644 --- a/Model/Order/Export/Processor/OrderDataProcessor.php +++ b/Model/Order/Export/Processor/OrderDataProcessor.php @@ -7,23 +7,19 @@ namespace Opengento\Gdpr\Model\Order\Export\Processor; +use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Api\Data\OrderInterface; +use Magento\Sales\Model\Order; -/** - * Class OrderDataProcessor - */ final class OrderDataProcessor extends AbstractDataProcessor { - /** - * @inheritdoc - */ protected function export(OrderInterface $order, array $data): array { - /** @var \Magento\Sales\Model\Order $order */ + /** @var Order $order */ $key = 'order_id_' . $order->getEntityId(); $data['orders'][$key] = $this->collectData($order); - /** @var \Magento\Sales\Api\Data\OrderAddressInterface|null $orderAddress */ + /** @var OrderAddressInterface|null $orderAddress */ foreach ([$order->getBillingAddress(), $order->getShippingAddress()] as $orderAddress) { if ($orderAddress) { $data['orders'][$key][$orderAddress->getAddressType()] = $this->collectData($orderAddress); diff --git a/Model/Order/Export/Processor/QuoteDataProcessor.php b/Model/Order/Export/Processor/QuoteDataProcessor.php index 9b108cd..8f1151b 100644 --- a/Model/Order/Export/Processor/QuoteDataProcessor.php +++ b/Model/Order/Export/Processor/QuoteDataProcessor.php @@ -9,25 +9,19 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Api\CartRepositoryInterface; +use Magento\Quote\Model\Quote; +use Magento\Quote\Model\Quote\Address; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; -/** - * Class QuoteDataProcessor - */ final class QuoteDataProcessor extends AbstractDataProcessor { /** - * @var \Magento\Quote\Api\CartRepositoryInterface + * @var CartRepositoryInterface */ private $quoteRepository; - /** - * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( CartRepositoryInterface $quoteRepository, OrderRepositoryInterface $orderRepository, @@ -37,13 +31,10 @@ public function __construct( parent::__construct($orderRepository, $dataCollector); } - /** - * @inheritdoc - */ protected function export(OrderInterface $order, array $data): array { try { - /** @var \Magento\Quote\Model\Quote $quote */ + /** @var Quote $quote */ $quote = $this->quoteRepository->get($order->getQuoteId()); } catch (NoSuchEntityException $e) { return $data; @@ -52,7 +43,7 @@ protected function export(OrderInterface $order, array $data): array $key = 'quote_id_' . $quote->getId(); $data['quotes'][$key] = $this->collectData($quote); - /** @var \Magento\Quote\Model\Quote\Address|null $quoteAddress */ + /** @var Address|null $quoteAddress */ foreach ([$quote->getBillingAddress(), $quote->getShippingAddress()] as $quoteAddress) { if ($quoteAddress) { $data['quotes'][$key][$quoteAddress->getAddressType()] = $this->collectData($quoteAddress); diff --git a/Model/Order/Export/Processor/SubscriberDataProcessor.php b/Model/Order/Export/Processor/SubscriberDataProcessor.php index df6b1f4..428dbe9 100644 --- a/Model/Order/Export/Processor/SubscriberDataProcessor.php +++ b/Model/Order/Export/Processor/SubscriberDataProcessor.php @@ -10,23 +10,16 @@ use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; +use Opengento\Gdpr\Model\Newsletter\Subscriber; use Opengento\Gdpr\Model\Newsletter\SubscriberFactory; -/** - * Class SubscriberDataProcessor - */ final class SubscriberDataProcessor extends AbstractDataProcessor { /** - * @var \Opengento\Gdpr\Model\Newsletter\SubscriberFactory + * @var SubscriberFactory */ private $subscriberFactory; - /** - * @param \Opengento\Gdpr\Model\Newsletter\SubscriberFactory $subscriberFactory - * @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( SubscriberFactory $subscriberFactory, OrderRepositoryInterface $orderRepository, @@ -36,12 +29,9 @@ public function __construct( parent::__construct($orderRepository, $dataCollector); } - /** - * @inheritdoc - */ protected function export(OrderInterface $order, array $data): array { - /** @var \Opengento\Gdpr\Model\Newsletter\Subscriber $subscriber */ + /** @var Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); $subscriber->loadByEmail($order->getCustomerEmail()); $data['subscriber'] = $this->collectData($subscriber); diff --git a/Model/Order/Notifier/MailSender.php b/Model/Order/Notifier/MailSender.php new file mode 100644 index 0000000..6725bd5 --- /dev/null +++ b/Model/Order/Notifier/MailSender.php @@ -0,0 +1,31 @@ +getStoreId() === null ? null : (int) $order->getStoreId(); + $vars = [];//todo convert order as data array + + $this->sendMail($order->getCustomerEmail(), $order->getCustomerName(), $storeId, $vars); + } +} diff --git a/Model/Order/Notifier/SenderInterface.php b/Model/Order/Notifier/SenderInterface.php new file mode 100644 index 0000000..79941ad --- /dev/null +++ b/Model/Order/Notifier/SenderInterface.php @@ -0,0 +1,18 @@ +config = $config; } - /** - * @inheritdoc - */ public function canErase(int $orderId): bool { $order = $this->orderRepository->get($orderId); - return \in_array($order->getState(), $this->config->getAllowedStatesToErase(), true); + return in_array($order->getState(), $this->config->getAllowedStatesToErase(), true); } } diff --git a/Model/Order/SourceProvider/GuestModifier.php b/Model/Order/SourceProvider/GuestModifier.php index 1ece6d2..c10927d 100644 --- a/Model/Order/SourceProvider/GuestModifier.php +++ b/Model/Order/SourceProvider/GuestModifier.php @@ -9,23 +9,18 @@ use Magento\Framework\Api\Filter; use Magento\Framework\Data\Collection; +use Magento\Framework\Exception\LocalizedException; use Magento\Sales\Api\Data\OrderInterface; use Opengento\Gdpr\Model\Config; use Opengento\Gdpr\Model\Entity\SourceProvider\ModifierInterface; -/** - * Class GuestModifier - */ final class GuestModifier implements ModifierInterface { /** - * @var \Opengento\Gdpr\Model\Config + * @var Config */ private $config; - /** - * @param \Opengento\Gdpr\Model\Config $config - */ public function __construct(Config $config) { $this->config = $config; @@ -33,7 +28,7 @@ public function __construct(Config $config) /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function apply(Collection $collection, Filter $filter): void { diff --git a/Model/ResourceModel/ActionEntity.php b/Model/ResourceModel/ActionEntity.php new file mode 100755 index 0000000..e33f486 --- /dev/null +++ b/Model/ResourceModel/ActionEntity.php @@ -0,0 +1,48 @@ +validator = $validator; + parent::__construct($context, $entitySnapshot, $entityRelationComposite, $connectionName); + } + + protected function _construct(): void + { + $this->_init(self::TABLE, ActionEntityInterface::ID); + $this->_serializableFields = [ActionEntityInterface::PARAMETERS => [[], []]]; + } + + public function getValidationRulesBeforeSave(): ValidatorInterface + { + return $this->validator; + } +} diff --git a/Model/ResourceModel/ActionEntity/Collection.php b/Model/ResourceModel/ActionEntity/Collection.php new file mode 100755 index 0000000..5e118b0 --- /dev/null +++ b/Model/ResourceModel/ActionEntity/Collection.php @@ -0,0 +1,22 @@ +_init(ActionEntity::class, ActionEntityResourceModel::class); + $this->_setIdFieldName(ActionEntityInterface::ID); + } +} diff --git a/Model/ResourceModel/ActionEntity/Validator.php b/Model/ResourceModel/ActionEntity/Validator.php new file mode 100644 index 0000000..c4228f1 --- /dev/null +++ b/Model/ResourceModel/ActionEntity/Validator.php @@ -0,0 +1,46 @@ +validators = (static function (ValidatorInterface ...$validators): array { + return $validators; + })(...array_values($validators)); + } + + public function isValid($value): bool + { + $isValid = true; + $messages = []; + + foreach ($this->validators as $validator) { + $isValid = $isValid && $validator->isValid($value); + $messages[] = $validator->getMessages(); + } + $this->_addMessages(array_merge_recursive(...$messages)); + + return $isValid && !$this->hasMessages(); + } +} diff --git a/Model/ResourceModel/ActionEntity/Validator/StateValidator.php b/Model/ResourceModel/ActionEntity/Validator/StateValidator.php new file mode 100644 index 0000000..9ea79b6 --- /dev/null +++ b/Model/ResourceModel/ActionEntity/Validator/StateValidator.php @@ -0,0 +1,46 @@ +actionStates = $actionStates; + } + + /** + * @param ActionEntityInterface $actionEntity + * @return bool + */ + public function isValid($actionEntity): bool + { + if (!in_array($actionEntity->getState(), array_column($this->actionStates->toOptionArray(), 'value'), true)) { + $this->_addMessages([ + 'state' => new Phrase('State "%1" does not exists.', [$actionEntity->getState()]) + ]); + + return false; + } + + return true; + } +} diff --git a/Model/ResourceModel/EraseEntity.php b/Model/ResourceModel/EraseEntity.php index 3062191..195c550 100755 --- a/Model/ResourceModel/EraseEntity.php +++ b/Model/ResourceModel/EraseEntity.php @@ -8,36 +8,32 @@ namespace Opengento\Gdpr\Model\ResourceModel; use Magento\Framework\DB\Select; -use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Model\AbstractModel; +use Magento\Framework\Model\ResourceModel\Db\VersionControl\AbstractDb; use Opengento\Gdpr\Api\Data\EraseEntityInterface; +use function is_array; -/** - * Class EraseEntity - */ -final class EraseEntity extends AbstractDb +class EraseEntity extends AbstractDb { public const TABLE = 'opengento_gdpr_erase_entity'; - /** - * @inheritdoc - */ protected function _construct(): void { $this->_init(self::TABLE, EraseEntityInterface::ID); } /** - * Retrieve select object for load object data - * + * @inheritdoc * @param string|array $field * @param mixed $value - * @param \Magento\Framework\Model\AbstractModel $object - * @return \Magento\Framework\DB\Select - * @throws \Magento\Framework\Exception\LocalizedException + * @param AbstractModel $object + * @return Select + * @throws LocalizedException */ protected function _getLoadSelect($field, $value, $object): Select { - if (!\is_array($field) && !\is_array($value)) { + if (!is_array($field) && !is_array($value)) { return parent::_getLoadSelect($field, $value, $object); } diff --git a/Model/ResourceModel/EraseEntity/Collection.php b/Model/ResourceModel/EraseEntity/Collection.php index 5148156..48c9dad 100755 --- a/Model/ResourceModel/EraseEntity/Collection.php +++ b/Model/ResourceModel/EraseEntity/Collection.php @@ -12,14 +12,8 @@ use Opengento\Gdpr\Model\EraseEntity; use Opengento\Gdpr\Model\ResourceModel\EraseEntity as EraseEntityResourceModel; -/** - * Class Collection - */ -final class Collection extends AbstractCollection +class Collection extends AbstractCollection { - /** - * @inheritdoc - */ protected function _construct(): void { $this->_init(EraseEntity::class, EraseEntityResourceModel::class); diff --git a/Model/ResourceModel/ExportEntity.php b/Model/ResourceModel/ExportEntity.php new file mode 100755 index 0000000..ac26665 --- /dev/null +++ b/Model/ResourceModel/ExportEntity.php @@ -0,0 +1,49 @@ +_init(self::TABLE, ExportEntityInterface::ID); + } + + /** + * @inheritdoc + * @param string|array $field + * @param mixed $value + * @param AbstractModel $object + * @return Select + * @throws LocalizedException + */ + protected function _getLoadSelect($field, $value, $object): Select + { + if (!is_array($field) && !is_array($value)) { + return parent::_getLoadSelect($field, $value, $object); + } + + $select = $this->getConnection()->select()->from($this->getMainTable()); + + foreach ($field as $i => $identifier) { + $pk = $this->getConnection()->quoteIdentifier(\sprintf('%s.%s', $this->getMainTable(), $identifier)); + $select->where($pk . '=?', $value[$i]); + } + + return $select; + } +} diff --git a/Model/ResourceModel/ExportEntity/Collection.php b/Model/ResourceModel/ExportEntity/Collection.php new file mode 100755 index 0000000..e9dbc10 --- /dev/null +++ b/Model/ResourceModel/ExportEntity/Collection.php @@ -0,0 +1,22 @@ +_init(ExportEntity::class, ExportEntityResourceModel::class); + $this->_setIdFieldName(ExportEntityInterface::ID); + } +} diff --git a/README.md b/README.md index 56dccaa..fe71d35 100755 --- a/README.md +++ b/README.md @@ -2,17 +2,17 @@ [![Latest Stable Version](https://img.shields.io/packagist/v/opengento/module-gdpr.svg?style=flat-square)](https://packagist.org/packages/opengento/module-gdpr) [![License: MIT](https://img.shields.io/github/license/opengento/magento2-gdpr.svg?style=flat-square)](./LICENSE) -[![Packagist](https://img.shields.io/packagist/dt/opengento/module-gdpr.svg?style=flat-square)](https://packagist.org/packages/opengento/module-gdpr) -[![Packagist](https://img.shields.io/packagist/dm/opengento/module-gdpr.svg?style=flat-square)](https://packagist.org/packages/opengento/module-gdpr) +[![Packagist](https://img.shields.io/packagist/dt/opengento/module-gdpr.svg?style=flat-square)](https://packagist.org/packages/opengento/module-gdpr/stats) +[![Packagist](https://img.shields.io/packagist/dm/opengento/module-gdpr.svg?style=flat-square)](https://packagist.org/packages/opengento/module-gdpr/stats) -This extension allows users to delete, anonymize, and export their personal data. +This extension fullfill the GDPR requirements for Magento 2. - [Setup](#setup) - [Composer installation](#composer-installation) - [Setup the module](#setup-the-module) - - [Usage](#usage) + - [Features](#features) - [Settings](#settings) - - [Developers](#developers) + - [Documentation](#documentation) - [Support](#support) - [Authors](#authors) - [License](#license) @@ -21,13 +21,6 @@ This extension allows users to delete, anonymize, and export their personal data Magento 2 Open Source or Commerce edition is required. -- The version `3.x` is compliant with Magento `2.3.x`. -- The version `2.x` is compliant with Magento `2.2.x`. - -This module does not support Magento `2.0.x` and `2.1.x`, as these versions ar not anymore maintained. - -**The next stable release will break all previous versions, and will be published as the following tag: `100.0.0`** - ### Composer installation Run the following composer command: @@ -46,7 +39,11 @@ bin/magento setup:upgrade **If you are in production mode, do not forget to recompile and redeploy the static resources.** -## Usage +## Features + +Users, guest and customer can: + +* **[Art. 16 GDPR](https://gdpr-info.eu/art-16-gdpr/)** Edit their personal data (native in vanilla) * **[Art. 17 GDPR](https://gdpr-info.eu/art-17-gdpr/)** * Customers can use their 'right to be forgotten'. Account deletion and anonymization can be done in 'My Account > Privacy Settings'. @@ -57,6 +54,13 @@ bin/magento setup:upgrade The data will be erased within 1 hour, or as specified in the configuration. The guest can undo the action is this time spare. * The customers and guests will be erased after a configurable idle time. * The sales information are locked within a configurable time. These information are automatically erased after this period. + + As a merchant you can easily manage which type of entity must to be delete or anonymize. In the last case, +the module allows to define which attribute must to be anonymize, and how it is. + +Times are configurable too, you can define the period of cancellation for the erasure, +the idle time for the users before they are erase, and the sales information lifetime. + * **[Art. 20 GDPR](https://gdpr-info.eu/art-20-gdpr/)** * Customers can export their data in `.zip` archive containing file, `.html` (many others are available), with personal data. Personal data export can be done in 'My Account > Privacy Settings'. @@ -64,30 +68,35 @@ bin/magento setup:upgrade Personal data export can be done in the order view, they must fill the guest form first to show their order. * Cookie Policy in a disclosure popup are shown at the first time customer visit. -As a merchant you can easily manage which type of entity must to be delete or anonymize. In the last case, -the module allows to define which attribute must to be anonymize, and how it is. - -Times are configurable too, you can define the period of cancellation for the erasure, -the idle time for the users before they are erase, and the sales information lifetime. +Details: + +- [ ] Erasure: delete or anonymize specific data thanks to configurable settings in admin ui. +- [ ] Configure which order can be erased, regarding their state and life time. +- [ ] Privacy data will be automatically erased after a delay. +- [ ] Sales data are safely keeped till the preservation delay expired. +- [ ] Choose the file name and the format of your choice for the privacy data export. +- [ ] Choose which data is interpreted as privacy data and will be exported. +- [ ] Actions related to the GDPR compliance are reported in the admin ui. +- [ ] Merchants can execute and keep an eye on the performed actions from the admin ui. +- [ ] Choose the CMS static block to show on the storefront by scope and features. +- [ ] Enable or disable features for the storefront. +- [ ] Notify the user when a GDPR action is performed, configure the template and sending settings. +- [ ] Display the cookie disclosure pop-in and edit its content as you want. ## Settings -The configuration for this module is located in 'Stores > Configuration > Customers > Customer Configuration > Privacy (GDPR)'. -The whole documentation and guide is available at [our website](https://opengento.fr/magento2-gdpr/). +The configuration for this module is available in 'Stores > Configuration > Customers > Customer Configuration > Privacy (GDPR)'. -## Developers +## Documentation -The developer documentation is available at [our website](https://opengento.fr/magento2-gdpr/). -It explains how to add your own processors to the GDPR workflow. +The documentation is available [here](https://opengento.fr/magento2-gdpr/). ## Support -Raise a new [request](https://github.com/opengento/magento2-gdpr/issues) to the issue tracker. -Please provide your Magento 2 version and the module version. Explain how to reproduce your issue and what's expected. +Raise a new [request](https://github.com/opengento/magento2-gdpr/issues) to the issue tracker. ## Authors -- **Initial Inspiration** - *`Cookie PopUp` sources* - [flurrybox](https://github.com/flurrybox) - **Opengento Community** - *Lead* - [![Twitter Follow](https://img.shields.io/twitter/follow/opengento.svg?style=social)](https://twitter.com/opengento) - **Thomas Klein** - *Maintainer* - [![GitHub followers](https://img.shields.io/github/followers/thomas-kl1.svg?style=social)](https://github.com/thomas-kl1) - **Contributors** - *Contributor* - [![GitHub contributors](https://img.shields.io/github/contributors/opengento/magento2-gdpr.svg?style=flat-square)](https://github.com/opengento/magento2-gdpr/graphs/contributors) diff --git a/Service/Anonymize/Anonymizer/AlphaLower.php b/Service/Anonymize/Anonymizer/AlphaLower.php index 0d79756..65e073f 100644 --- a/Service/Anonymize/Anonymizer/AlphaLower.php +++ b/Service/Anonymize/Anonymizer/AlphaLower.php @@ -7,22 +7,16 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Math\Random; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class AlphaLower - */ final class AlphaLower implements AnonymizerInterface { - /**#@+ - * Constants for alpha lower anonymizer - */ private const DEFAULT_LENGTH = 5; - /**#@-*/ /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; @@ -31,10 +25,6 @@ final class AlphaLower implements AnonymizerInterface */ private $length; - /** - * @param \Magento\Framework\Math\Random $mathRandom - * @param int $length - */ public function __construct( Random $mathRandom, int $length = self::DEFAULT_LENGTH @@ -45,7 +35,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function anonymize($value): string { diff --git a/Service/Anonymize/Anonymizer/AlphaNum.php b/Service/Anonymize/Anonymizer/AlphaNum.php index c849e48..cb47906 100644 --- a/Service/Anonymize/Anonymizer/AlphaNum.php +++ b/Service/Anonymize/Anonymizer/AlphaNum.php @@ -7,22 +7,16 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Math\Random; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class AlphaNum - */ final class AlphaNum implements AnonymizerInterface { - /**#@+ - * Constants for alpha numeric anonymizer - */ private const DEFAULT_LENGTH = 5; - /**#@-*/ /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; @@ -31,10 +25,6 @@ final class AlphaNum implements AnonymizerInterface */ private $length; - /** - * @param \Magento\Framework\Math\Random $mathRandom - * @param int $length - */ public function __construct( Random $mathRandom, int $length = self::DEFAULT_LENGTH @@ -45,7 +35,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function anonymize($value): string { diff --git a/Service/Anonymize/Anonymizer/AlphaUpper.php b/Service/Anonymize/Anonymizer/AlphaUpper.php index 2c9993e..88c1570 100644 --- a/Service/Anonymize/Anonymizer/AlphaUpper.php +++ b/Service/Anonymize/Anonymizer/AlphaUpper.php @@ -7,22 +7,16 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Math\Random; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class AlphaUpper - */ final class AlphaUpper implements AnonymizerInterface { - /**#@+ - * Constants for alpha upper anonymizer - */ private const DEFAULT_LENGTH = 5; - /**#@-*/ /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; @@ -31,10 +25,6 @@ final class AlphaUpper implements AnonymizerInterface */ private $length; - /** - * @param \Magento\Framework\Math\Random $mathRandom - * @param int $length - */ public function __construct( Random $mathRandom, int $length = self::DEFAULT_LENGTH @@ -45,7 +35,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function anonymize($value): string { diff --git a/Service/Anonymize/Anonymizer/Anonymous.php b/Service/Anonymize/Anonymizer/Anonymous.php index f128d0c..7b3863d 100644 --- a/Service/Anonymize/Anonymizer/Anonymous.php +++ b/Service/Anonymize/Anonymizer/Anonymous.php @@ -7,31 +7,22 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Math\Random; use Magento\Framework\Phrase; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class Anonymous - */ final class Anonymous implements AnonymizerInterface { - /**#@+ - * Constants for anonymous anonymizer - */ private const PHRASE = '%1Anonymous%2'; private const PREFIX_LENGTH = 3; private const SUFFIX_LENGTH = 2; - /**#@-*/ /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; - /** - * @param \Magento\Framework\Math\Random $mathRandom - */ public function __construct( Random $mathRandom ) { @@ -40,7 +31,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function anonymize($value): string { diff --git a/Service/Anonymize/Anonymizer/ArrayValue.php b/Service/Anonymize/Anonymizer/ArrayValue.php index 8c19b44..a6c6dac 100644 --- a/Service/Anonymize/Anonymizer/ArrayValue.php +++ b/Service/Anonymize/Anonymizer/ArrayValue.php @@ -8,36 +8,31 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; +use function array_reduce; -/** - * Class ArrayValue - */ final class ArrayValue implements AnonymizerInterface { /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface[] + * @var AnonymizerInterface[] */ private $anonymizers; /** - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface[] $anonymizers + * @param AnonymizerInterface[] $anonymizers */ public function __construct( array $anonymizers ) { - $this->anonymizers = (static function (AnonymizerInterface ...$anonymizers) { + $this->anonymizers = (static function (AnonymizerInterface ...$anonymizers): array { return $anonymizers; })(... $anonymizers); } - /** - * @inheritdoc - */ public function anonymize($value): array { - return \array_reduce( + return array_reduce( $this->anonymizers, - static function ($array, AnonymizerInterface $anonymizer) use ($value) { + static function ($array, AnonymizerInterface $anonymizer) use ($value): array { $array[] = $anonymizer->anonymize($value); return $array; diff --git a/Service/Anonymize/Anonymizer/Date.php b/Service/Anonymize/Anonymizer/Date.php index c9ea8c6..4496313 100644 --- a/Service/Anonymize/Anonymizer/Date.php +++ b/Service/Anonymize/Anonymizer/Date.php @@ -7,25 +7,19 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Exception; use Magento\Framework\Math\Random; use Magento\Framework\Stdlib\DateTime; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class Date - */ final class Date implements AnonymizerInterface { - /**#@+ - * Constants for date anonymizer - */ private const MIN_TIMESTAMP = 0; private const MAX_TIMESTAMP = 1557480188; - /**#@-*/ /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function anonymize($value): string { diff --git a/Service/Anonymize/Anonymizer/Email.php b/Service/Anonymize/Anonymizer/Email.php index 3cad5d1..9f8103e 100644 --- a/Service/Anonymize/Anonymizer/Email.php +++ b/Service/Anonymize/Anonymizer/Email.php @@ -7,31 +7,22 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Math\Random; use Magento\Framework\Phrase; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class Email - */ final class Email implements AnonymizerInterface { - /**#@+ - * Constants for value anonymizer - */ private const PHRASE = '%1-anonymous-%2@gdpr.org'; private const PREFIX_LENGTH = 3; private const SUFFIX_LENGTH = 2; - /**#@-*/ /** - * @var \Magento\Framework\Math\Random + * @var Random */ private $mathRandom; - /** - * @param \Magento\Framework\Math\Random $mathRandom - */ public function __construct( Random $mathRandom ) { @@ -40,7 +31,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function anonymize($value): string { diff --git a/Service/Anonymize/Anonymizer/Entity.php b/Service/Anonymize/Anonymizer/Entity.php index c209215..4d7967e 100644 --- a/Service/Anonymize/Anonymizer/Entity.php +++ b/Service/Anonymize/Anonymizer/Entity.php @@ -7,36 +7,33 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Exception; +use InvalidArgumentException; use Magento\Framework\EntityManager\HydratorPool; use Magento\Framework\EntityManager\TypeResolver; use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; +use function gettype; +use function is_object; +use function sprintf; -/** - * Class Entity - */ final class Entity implements AnonymizerInterface { /** - * @var \Opengento\Gdpr\Model\Entity\DataCollectorInterface + * @var DataCollectorInterface */ private $dataCollector; /** - * @var \Magento\Framework\EntityManager\TypeResolver + * @var TypeResolver */ private $typeResolver; /** - * @var \Magento\Framework\EntityManager\HydratorPool + * @var HydratorPool */ private $hydratorPool; - /** - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - * @param \Magento\Framework\EntityManager\TypeResolver $typeResolver - * @param \Magento\Framework\EntityManager\HydratorPool $hydratorPool - */ public function __construct( DataCollectorInterface $dataCollector, TypeResolver $typeResolver, @@ -49,13 +46,13 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function anonymize($entity) { - if (!\is_object($entity)) { - throw new \InvalidArgumentException( - \sprintf('Argument "$entity" must be an object, type "%s" given.', \gettype($entity)) + if (!is_object($entity)) { + throw new InvalidArgumentException( + sprintf('Argument "$entity" must be an object, type "%s" given.', gettype($entity)) ); } diff --git a/Service/Anonymize/Anonymizer/NullValue.php b/Service/Anonymize/Anonymizer/NullValue.php index b645294..881cf83 100644 --- a/Service/Anonymize/Anonymizer/NullValue.php +++ b/Service/Anonymize/Anonymizer/NullValue.php @@ -9,14 +9,8 @@ use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class NullValue - */ final class NullValue implements AnonymizerInterface { - /** - * @inheritdoc - */ public function anonymize($value) { return null; diff --git a/Service/Anonymize/Anonymizer/Number.php b/Service/Anonymize/Anonymizer/Number.php index 9543280..3a69d09 100644 --- a/Service/Anonymize/Anonymizer/Number.php +++ b/Service/Anonymize/Anonymizer/Number.php @@ -7,12 +7,12 @@ namespace Opengento\Gdpr\Service\Anonymize\Anonymizer; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Math\Random; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; +use const PHP_INT_MAX; +use const PHP_INT_MIN; -/** - * Class Number - */ final class Number implements AnonymizerInterface { /** @@ -25,21 +25,17 @@ final class Number implements AnonymizerInterface */ private $max; - /** - * @param int|null $min - * @param int|null $max - */ public function __construct( ?int $min = null, ?int $max = null ) { - $this->min = $min !== null && $min < \PHP_INT_MIN ? \PHP_INT_MIN : $min; - $this->max = $max !== null && $max < \PHP_INT_MAX ? \PHP_INT_MAX : $max; + $this->min = $min !== null && $min < PHP_INT_MIN ? PHP_INT_MIN : $min; + $this->max = $max !== null && $max < PHP_INT_MAX ? PHP_INT_MAX : $max; } /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function anonymize($value): int { diff --git a/Service/Anonymize/Anonymizer/Phone.php b/Service/Anonymize/Anonymizer/Phone.php index 40c7b69..21e0e34 100644 --- a/Service/Anonymize/Anonymizer/Phone.php +++ b/Service/Anonymize/Anonymizer/Phone.php @@ -9,20 +9,10 @@ use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; -/** - * Class Phone - */ final class Phone implements AnonymizerInterface { - /**#@+ - * Constants for phone number anonymizer - */ private const PHONE_NUMBER = '9999999999'; - /**#@-*/ - /** - * @inheritdoc - */ public function anonymize($value): string { return self::PHONE_NUMBER; diff --git a/Service/Anonymize/AnonymizerFactory.php b/Service/Anonymize/AnonymizerFactory.php index a64ff84..a1cd60a 100644 --- a/Service/Anonymize/AnonymizerFactory.php +++ b/Service/Anonymize/AnonymizerFactory.php @@ -7,18 +7,16 @@ namespace Opengento\Gdpr\Service\Anonymize; +use InvalidArgumentException; use Magento\Framework\ObjectManagerInterface; +use function sprintf; -/** - * Class AnonymizerFactory - */ final class AnonymizerFactory { - /**#@+ + /** * Constants for the anonymizer key codes */ public const DEFAULT_ANONYMIZER = 'default'; - /**#@-*/ /** * @var string[] @@ -26,14 +24,10 @@ final class AnonymizerFactory private $anonymizers; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; - /** - * @param array $anonymizers - * @param \Magento\Framework\ObjectManagerInterface $objectManager - */ public function __construct( array $anonymizers, ObjectManagerInterface $objectManager @@ -42,16 +36,10 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Retrieve the anonymizer instance by its key code - * - * @param string $anonymizerCode - * @return \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface - */ public function get(string $anonymizerCode): AnonymizerInterface { if (!isset($this->anonymizers[$anonymizerCode])) { - throw new \InvalidArgumentException(\sprintf('Unknown anonymizer type "%s".', $anonymizerCode)); + throw new InvalidArgumentException(sprintf('Unknown anonymizer type "%s".', $anonymizerCode)); } return $this->objectManager->get($this->anonymizers[$anonymizerCode]); diff --git a/Service/Anonymize/AnonymizerInterface.php b/Service/Anonymize/AnonymizerInterface.php index 090bd1b..233cf90 100644 --- a/Service/Anonymize/AnonymizerInterface.php +++ b/Service/Anonymize/AnonymizerInterface.php @@ -8,7 +8,6 @@ namespace Opengento\Gdpr\Service\Anonymize; /** - * Interface AnonymizerInterface * @api */ interface AnonymizerInterface diff --git a/Service/Anonymize/Metadata.php b/Service/Anonymize/Metadata.php index 0fe013f..0c1c608 100644 --- a/Service/Anonymize/Metadata.php +++ b/Service/Anonymize/Metadata.php @@ -9,19 +9,19 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Serialize\SerializerInterface; +use function array_column; +use function array_combine; +use function array_keys; -/** - * Class Metadata - */ final class Metadata implements MetadataInterface { /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ private $scopeConfig; /** - * @var \Magento\Framework\Serialize\SerializerInterface + * @var SerializerInterface */ private $serializer; @@ -40,12 +40,6 @@ final class Metadata implements MetadataInterface */ private $cache; - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Framework\Serialize\SerializerInterface $serializer - * @param string $configPath - * @param string $scopeType - */ public function __construct( ScopeConfigInterface $scopeConfig, SerializerInterface $serializer, @@ -58,9 +52,6 @@ public function __construct( $this->scopeType = $scopeType; } - /** - * @inheritdoc - */ public function getAnonymizerStrategiesByAttributes(?string $scopeCode = null): array { $scope = $scopeCode ?? 'current_scope'; @@ -70,20 +61,17 @@ public function getAnonymizerStrategiesByAttributes(?string $scopeCode = null): $this->scopeConfig->getValue($this->configPath, $this->scopeType, $scopeCode) ?? '{}' ); - $this->cache[$scope] = \array_combine( - \array_column($metadata, 'attribute'), - \array_column($metadata, 'anonymizer') + $this->cache[$scope] = array_combine( + array_column($metadata, 'attribute'), + array_column($metadata, 'anonymizer') ); } return $this->cache[$scope]; } - /** - * @inheritdoc - */ public function getAttributes(?string $scopeCode = null): array { - return \array_keys($this->getAnonymizerStrategiesByAttributes($scopeCode)); + return array_keys($this->getAnonymizerStrategiesByAttributes($scopeCode)); } } diff --git a/Service/Anonymize/MetadataInterface.php b/Service/Anonymize/MetadataInterface.php index 0eafa3b..2835f78 100644 --- a/Service/Anonymize/MetadataInterface.php +++ b/Service/Anonymize/MetadataInterface.php @@ -3,22 +3,16 @@ * Copyright © OpenGento, All rights reserved. * See LICENSE bundled with this library for license details. */ +declare(strict_types=1); namespace Opengento\Gdpr\Service\Anonymize; use Opengento\Gdpr\Model\Entity\MetadataInterface as EntityMetadataInterface; /** - * Interface MetadataInterface * @api */ interface MetadataInterface extends EntityMetadataInterface { - /** - * Retrieve the anonymizer strategies associated by attribute code - * - * @param string|null $scopeCode - * @return array - */ public function getAnonymizerStrategiesByAttributes(?string $scopeCode = null): array; } diff --git a/Service/Anonymize/Processor/Entity/EntityValue/Processor.php b/Service/Anonymize/Processor/Entity/EntityValue/Processor.php index 9595083..1ce5100 100644 --- a/Service/Anonymize/Processor/Entity/EntityValue/Processor.php +++ b/Service/Anonymize/Processor/Entity/EntityValue/Processor.php @@ -11,32 +11,25 @@ use Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface; use Opengento\Gdpr\Model\Entity\MetadataInterface; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; +use function in_array; -/** - * Class Processor - */ final class Processor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\DocumentInterface + * @var DocumentInterface */ public $document; /** - * @var \Opengento\Gdpr\Model\Entity\MetadataInterface + * @var MetadataInterface */ private $metadata; /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface + * @var AnonymizerInterface */ private $anonymizer; - /** - * @param \Opengento\Gdpr\Model\Entity\DocumentInterface $document - * @param \Opengento\Gdpr\Model\Entity\MetadataInterface $metadata - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface $anonymizer - */ public function __construct( DocumentInterface $document, MetadataInterface $metadata, @@ -47,12 +40,9 @@ public function __construct( $this->anonymizer = $anonymizer; } - /** - * @inheritdoc - */ public function process($entity, string $key, $value): void { - if (\in_array($key, $this->metadata->getAttributes(), true)) { + if (in_array($key, $this->metadata->getAttributes(), true)) { $this->document->addData($key, $this->anonymizer->anonymize($value)); } } diff --git a/Service/Anonymize/Processor/Entity/EntityValue/SmartProcessor.php b/Service/Anonymize/Processor/Entity/EntityValue/SmartProcessor.php index 6ae9fa8..bfce41e 100644 --- a/Service/Anonymize/Processor/Entity/EntityValue/SmartProcessor.php +++ b/Service/Anonymize/Processor/Entity/EntityValue/SmartProcessor.php @@ -12,32 +12,25 @@ use Opengento\Gdpr\Service\Anonymize\AnonymizerFactory; use Opengento\Gdpr\Service\Anonymize\AnonymizerInterface; use Opengento\Gdpr\Service\Anonymize\MetadataInterface; +use function in_array; -/** - * Class SmartProcessor - */ final class SmartProcessor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\DocumentInterface + * @var DocumentInterface */ public $document; /** - * @var \Opengento\Gdpr\Service\Anonymize\MetadataInterface + * @var MetadataInterface */ private $metadata; /** - * @var \Opengento\Gdpr\Service\Anonymize\AnonymizerFactory + * @var AnonymizerFactory */ private $anonymizerFactory; - /** - * @param \Opengento\Gdpr\Model\Entity\DocumentInterface $document - * @param \Opengento\Gdpr\Service\Anonymize\MetadataInterface $metadata - * @param \Opengento\Gdpr\Service\Anonymize\AnonymizerFactory $anonymizerFactory - */ public function __construct( DocumentInterface $document, MetadataInterface $metadata, @@ -48,22 +41,13 @@ public function __construct( $this->anonymizerFactory = $anonymizerFactory; } - /** - * @inheritdoc - */ public function process($entity, string $key, $value): void { - if (\in_array($key, $this->metadata->getAttributes(), true)) { + if (in_array($key, $this->metadata->getAttributes(), true)) { $this->document->addData($key, $this->resolveAnonymizer($key)->anonymize($value)); } } - /** - * Resolve the the anonymizer code by attribute code - * - * @param string $key - * @return \Opengento\Gdpr\Service\Anonymize\AnonymizerInterface - */ private function resolveAnonymizer(string $key): AnonymizerInterface { return $this->anonymizerFactory->get( diff --git a/Service/Erase/Metadata.php b/Service/Erase/Metadata.php index 176a562..34d0efb 100644 --- a/Service/Erase/Metadata.php +++ b/Service/Erase/Metadata.php @@ -7,21 +7,22 @@ namespace Opengento\Gdpr\Service\Erase; +use InvalidArgumentException; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Serialize\SerializerInterface; +use function array_column; +use function array_combine; +use function sprintf; -/** - * Class Metadata - */ final class Metadata implements MetadataInterface { /** - * @var \Magento\Framework\App\Config\ScopeConfigInterface + * @var ScopeConfigInterface */ private $scopeConfig; /** - * @var \Magento\Framework\Serialize\SerializerInterface + * @var SerializerInterface */ private $serializer; @@ -40,12 +41,6 @@ final class Metadata implements MetadataInterface */ private $cache; - /** - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Framework\Serialize\SerializerInterface $serializer - * @param string $configPath - * @param string $scopeType - */ public function __construct( ScopeConfigInterface $scopeConfig, SerializerInterface $serializer, @@ -58,9 +53,6 @@ public function __construct( $this->scopeType = $scopeType; } - /** - * @inheritdoc - */ public function getComponentsProcessors(?string $scopeCode = null): array { $scope = $scopeCode ?? 'current_scope'; @@ -70,9 +62,9 @@ public function getComponentsProcessors(?string $scopeCode = null): array $this->scopeConfig->getValue($this->configPath, $this->scopeType, $scopeCode) ?? '{}' ); - $this->cache[$scope] = \array_combine( - \array_column($metadata, 'component'), - \array_column($metadata, 'processor') + $this->cache[$scope] = array_combine( + array_column($metadata, 'component'), + array_column($metadata, 'processor') ); } @@ -87,8 +79,8 @@ public function getComponentProcessor(string $component, ?string $scopeCode = nu $componentsProcessors = $this->getComponentsProcessors($scopeCode); if (!isset($componentsProcessors[$component])) { - throw new \InvalidArgumentException( - \sprintf('There is no erasure processor registered for the component "%s".', $component) + throw new InvalidArgumentException( + sprintf('There is no erasure processor registered for the component "%s".', $component) ); } diff --git a/Service/Erase/MetadataInterface.php b/Service/Erase/MetadataInterface.php index 45cf0ce..97c5d7a 100644 --- a/Service/Erase/MetadataInterface.php +++ b/Service/Erase/MetadataInterface.php @@ -8,7 +8,6 @@ namespace Opengento\Gdpr\Service\Erase; /** - * Interface MetadataInterface * @api */ interface MetadataInterface @@ -16,7 +15,7 @@ interface MetadataInterface /** * Retrieve the erase processor associated by components * - * @param string|null $scopeCode + * @param string|null $scopeCode [optional] Current scope code will be used by default. * @return array */ public function getComponentsProcessors(?string $scopeCode = null): array; @@ -25,7 +24,7 @@ public function getComponentsProcessors(?string $scopeCode = null): array; * Retrieve the erase processor by component * * @param string $component - * @param string|null $scopeCode + * @param string|null $scopeCode [optional] Current scope code will be used by default. * @return string */ public function getComponentProcessor(string $component, ?string $scopeCode = null): string; diff --git a/Service/Erase/Processor/EraseProcessor.php b/Service/Erase/Processor/EraseProcessor.php index 94a5cdd..7e6dbf1 100644 --- a/Service/Erase/Processor/EraseProcessor.php +++ b/Service/Erase/Processor/EraseProcessor.php @@ -10,26 +10,20 @@ use Opengento\Gdpr\Model\Config\Source\EraseComponents; use Opengento\Gdpr\Service\Erase\ProcessorInterface; use Opengento\Gdpr\Service\Erase\ProcessorResolverInterface; +use function array_column; -/** - * Class EraseProcessor - */ final class EraseProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Erase\ProcessorResolverInterface + * @var ProcessorResolverInterface */ private $eraseProcessorResolver; /** - * @var \Opengento\Gdpr\Model\Config\Source\EraseComponents + * @var EraseComponents */ private $eraseComponents; - /** - * @param \Opengento\Gdpr\Service\Erase\ProcessorResolverInterface $eraseProcessorResolver - * @param \Opengento\Gdpr\Model\Config\Source\EraseComponents $eraseComponents - */ public function __construct( ProcessorResolverInterface $eraseProcessorResolver, EraseComponents $eraseComponents @@ -38,12 +32,9 @@ public function __construct( $this->eraseComponents = $eraseComponents; } - /** - * @inheritdoc - */ public function execute(int $entityId): bool { - foreach (\array_column($this->eraseComponents->toOptionArray(), 'value') as $component) { + foreach (array_column($this->eraseComponents->toOptionArray(), 'value') as $component) { $processor = $this->eraseProcessorResolver->resolve($component); if (!$processor->execute($entityId)) { return false; diff --git a/Service/Erase/ProcessorFactory.php b/Service/Erase/ProcessorFactory.php index b2cc818..cb7779e 100644 --- a/Service/Erase/ProcessorFactory.php +++ b/Service/Erase/ProcessorFactory.php @@ -7,10 +7,11 @@ namespace Opengento\Gdpr\Service\Erase; +use InvalidArgumentException; use Magento\Framework\ObjectManagerInterface; +use function sprintf; /** - * Class ProcessorFactory * @api */ final class ProcessorFactory @@ -21,13 +22,13 @@ final class ProcessorFactory private $erasers; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $erasers - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $erasers, @@ -37,16 +38,10 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Create a new eraser processor - * - * @param string $entityType - * @return \Opengento\Gdpr\Service\Erase\ProcessorInterface - */ public function get(string $entityType): ProcessorInterface { if (!isset($this->erasers[$entityType])) { - throw new \InvalidArgumentException(\sprintf('Unknown eraser for entity type "%s".', $entityType)); + throw new InvalidArgumentException(sprintf('Unknown eraser for entity type "%s".', $entityType)); } return $this->objectManager->get($this->erasers[$entityType]); diff --git a/Service/Erase/ProcessorInterface.php b/Service/Erase/ProcessorInterface.php index f2633cf..5d6fc7a 100644 --- a/Service/Erase/ProcessorInterface.php +++ b/Service/Erase/ProcessorInterface.php @@ -8,17 +8,9 @@ namespace Opengento\Gdpr\Service\Erase; /** - * Interface ProcessorInterface * @api */ interface ProcessorInterface { - /** - * Execute the erase processor for the given entity ID. - * It allows to erase the related data. - * - * @param int $entityId - * @return bool - */ public function execute(int $entityId): bool; } diff --git a/Service/Erase/ProcessorResolver/AnonymizeProcessorResolver.php b/Service/Erase/ProcessorResolver/AnonymizeProcessorResolver.php index 7b57fd1..6e3e0cf 100644 --- a/Service/Erase/ProcessorResolver/AnonymizeProcessorResolver.php +++ b/Service/Erase/ProcessorResolver/AnonymizeProcessorResolver.php @@ -7,36 +7,29 @@ namespace Opengento\Gdpr\Service\Erase\ProcessorResolver; +use InvalidArgumentException; use Magento\Framework\ObjectManager\TMap; use Opengento\Gdpr\Service\Erase\ProcessorInterface; use Opengento\Gdpr\Service\Erase\ProcessorResolverInterface; +use function sprintf; -/** - * Class AnonymizeProcessorResolver - */ final class AnonymizeProcessorResolver implements ProcessorResolverInterface { /** - * @var \Magento\Framework\ObjectManager\TMap + * @var TMap */ private $processorPool; - /** - * @param \Magento\Framework\ObjectManager\TMap $processorPool - */ public function __construct( TMap $processorPool ) { $this->processorPool = $processorPool; } - /** - * @inheritdoc - */ public function resolve(string $component): ProcessorInterface { if (!$this->processorPool->offsetExists($component)) { - throw new \InvalidArgumentException(\sprintf('Unknown processor type "%s".', $component)); + throw new InvalidArgumentException(sprintf('Unknown processor type "%s".', $component)); } return $this->processorPool->offsetGet($component); diff --git a/Service/Erase/ProcessorResolver/DeleteProcessorResolver.php b/Service/Erase/ProcessorResolver/DeleteProcessorResolver.php index 7b63fc2..7ccb038 100644 --- a/Service/Erase/ProcessorResolver/DeleteProcessorResolver.php +++ b/Service/Erase/ProcessorResolver/DeleteProcessorResolver.php @@ -7,36 +7,29 @@ namespace Opengento\Gdpr\Service\Erase\ProcessorResolver; +use InvalidArgumentException; use Magento\Framework\ObjectManager\TMap; use Opengento\Gdpr\Service\Erase\ProcessorInterface; use Opengento\Gdpr\Service\Erase\ProcessorResolverInterface; +use function sprintf; -/** - * Class DeleteProcessor - */ final class DeleteProcessorResolver implements ProcessorResolverInterface { /** - * @var \Magento\Framework\ObjectManager\TMap + * @var TMap */ private $processorPool; - /** - * @param \Magento\Framework\ObjectManager\TMap $processorPool - */ public function __construct( TMap $processorPool ) { $this->processorPool = $processorPool; } - /** - * @inheritdoc - */ public function resolve(string $component): ProcessorInterface { if (!$this->processorPool->offsetExists($component)) { - throw new \InvalidArgumentException(\sprintf('Unknown processor type "%s".', $component)); + throw new InvalidArgumentException(sprintf('Unknown processor type "%s".', $component)); } return $this->processorPool->offsetGet($component); diff --git a/Service/Erase/ProcessorResolver/ProcessorResolverStrategy.php b/Service/Erase/ProcessorResolver/ProcessorResolverStrategy.php index 529546f..446ae4f 100644 --- a/Service/Erase/ProcessorResolver/ProcessorResolverStrategy.php +++ b/Service/Erase/ProcessorResolver/ProcessorResolverStrategy.php @@ -12,25 +12,18 @@ use Opengento\Gdpr\Service\Erase\ProcessorResolverFactory; use Opengento\Gdpr\Service\Erase\ProcessorResolverInterface; -/** - * Class ProcessorResolverStrategy - */ final class ProcessorResolverStrategy implements ProcessorResolverInterface { /** - * @var \Opengento\Gdpr\Service\Erase\ProcessorResolverFactory + * @var ProcessorResolverFactory */ private $processorResolverFactory; /** - * @var \Opengento\Gdpr\Service\Erase\MetadataInterface + * @var MetadataInterface */ private $metadata; - /** - * @param \Opengento\Gdpr\Service\Erase\ProcessorResolverFactory $processorResolverFactory - * @param \Opengento\Gdpr\Service\Erase\MetadataInterface $metadata - */ public function __construct( ProcessorResolverFactory $processorResolverFactory, MetadataInterface $metadata @@ -39,9 +32,6 @@ public function __construct( $this->metadata = $metadata; } - /** - * @inheritdoc - */ public function resolve(string $component): ProcessorInterface { return $this->processorResolverFactory->get($this->metadata->getComponentProcessor($component))->resolve($component); diff --git a/Service/Erase/ProcessorResolverFactory.php b/Service/Erase/ProcessorResolverFactory.php index 4509a4c..1c874da 100644 --- a/Service/Erase/ProcessorResolverFactory.php +++ b/Service/Erase/ProcessorResolverFactory.php @@ -7,10 +7,11 @@ namespace Opengento\Gdpr\Service\Erase; +use InvalidArgumentException; use Magento\Framework\ObjectManagerInterface; +use function sprintf; /** - * Class ProcessorResolverFactory * @api */ final class ProcessorResolverFactory @@ -21,13 +22,13 @@ final class ProcessorResolverFactory private $processorResolvers; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $processorResolvers - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $processorResolvers, @@ -37,16 +38,10 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Retrieve the processor instance by its key code - * - * @param string $processorCode - * @return \Opengento\Gdpr\Service\Erase\ProcessorResolverInterface - */ public function get(string $processorCode): ProcessorResolverInterface { if (!isset($this->processorResolvers[$processorCode])) { - throw new \InvalidArgumentException(\sprintf('Unknown renderer type "%s".', $processorCode)); + throw new InvalidArgumentException(sprintf('Unknown renderer type "%s".', $processorCode)); } return $this->objectManager->get($this->processorResolvers[$processorCode]); diff --git a/Service/Erase/ProcessorResolverInterface.php b/Service/Erase/ProcessorResolverInterface.php index 38aedbd..b14b2b8 100644 --- a/Service/Erase/ProcessorResolverInterface.php +++ b/Service/Erase/ProcessorResolverInterface.php @@ -8,16 +8,9 @@ namespace Opengento\Gdpr\Service\Erase; /** - * Interface ProcessorResolverInterface * @api */ interface ProcessorResolverInterface { - /** - * Resolve the erase processor for the given component - * - * @param string $component - * @return \Opengento\Gdpr\Service\Erase\ProcessorInterface - */ public function resolve(string $component): ProcessorInterface; } diff --git a/Service/Export/Processor/AbstractDataProcessor.php b/Service/Export/Processor/AbstractDataProcessor.php index 8c1e748..5217149 100644 --- a/Service/Export/Processor/AbstractDataProcessor.php +++ b/Service/Export/Processor/AbstractDataProcessor.php @@ -10,32 +10,20 @@ use Opengento\Gdpr\Model\Entity\DataCollectorInterface; use Opengento\Gdpr\Service\Export\ProcessorInterface; -/** - * Class AbstractDataProcessor - */ abstract class AbstractDataProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\DataCollectorInterface + * @var DataCollectorInterface */ private $dataCollector; - /** - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( DataCollectorInterface $dataCollector ) { $this->dataCollector = $dataCollector; } - /** - * Collect the entity data - * - * @param object $entity - * @return array - */ - protected function collectData($entity): array + protected function collectData(object $entity): array { return $this->dataCollector->collect($entity); } diff --git a/Service/Export/Processor/CompositeProcessor.php b/Service/Export/Processor/CompositeProcessor.php index 7c5f64d..ea436bc 100644 --- a/Service/Export/Processor/CompositeProcessor.php +++ b/Service/Export/Processor/CompositeProcessor.php @@ -8,38 +8,36 @@ namespace Opengento\Gdpr\Service\Export\Processor; use Opengento\Gdpr\Service\Export\ProcessorInterface; +use function array_combine; +use function array_keys; +use function array_reduce; +use function array_values; -/** - * Class CompositeProcessor - */ final class CompositeProcessor implements ProcessorInterface { /** - * @var \Opengento\Gdpr\Service\Export\ProcessorInterface[] + * @var ProcessorInterface[] */ private $processors; /** - * @param \Opengento\Gdpr\Service\Export\ProcessorInterface[] $processors + * @param ProcessorInterface[] $processors */ public function __construct( array $processors ) { $this->processors = (static function (ProcessorInterface ...$processors): array { return $processors; - })(...\array_values($processors)); + })(...array_values($processors)); - $this->processors = \array_combine(\array_keys($processors), $this->processors); + $this->processors = array_combine(array_keys($processors), $this->processors); } - /** - * @inheritdoc - */ public function execute(int $entityId, array $data): array { - return \array_reduce( + return array_reduce( $this->processors, - static function (array $data, ProcessorInterface $processor) use ($entityId) { + static function (array $data, ProcessorInterface $processor) use ($entityId): array { return $processor->execute($entityId, $data); }, $data diff --git a/Service/Export/Processor/Entity/EntityValue/DataProcessor.php b/Service/Export/Processor/Entity/EntityValue/DataProcessor.php index 4535833..3e2fdd5 100644 --- a/Service/Export/Processor/Entity/EntityValue/DataProcessor.php +++ b/Service/Export/Processor/Entity/EntityValue/DataProcessor.php @@ -10,26 +10,20 @@ use Opengento\Gdpr\Model\Entity\DocumentInterface; use Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface; use Opengento\Gdpr\Model\Entity\MetadataInterface; +use function in_array; -/** - * Class DataProcessor - */ final class DataProcessor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\DocumentInterface + * @var DocumentInterface */ public $document; /** - * @var \Opengento\Gdpr\Model\Entity\MetadataInterface + * @var MetadataInterface */ private $metadata; - /** - * @param \Opengento\Gdpr\Model\Entity\DocumentInterface $document - * @param \Opengento\Gdpr\Model\Entity\MetadataInterface $metadata - */ public function __construct( DocumentInterface $document, MetadataInterface $metadata @@ -38,12 +32,9 @@ public function __construct( $this->metadata = $metadata; } - /** - * @inheritdoc - */ public function process($entity, string $key, $value): void { - if (\in_array($key, $this->metadata->getAttributes(), true)) { + if (in_array($key, $this->metadata->getAttributes(), true)) { $this->document->addData($key, $value); } } diff --git a/Service/Export/Processor/Entity/EntityValue/EntityProcessor.php b/Service/Export/Processor/Entity/EntityValue/EntityProcessor.php index d4fa912..7d1fa50 100644 --- a/Service/Export/Processor/Entity/EntityValue/EntityProcessor.php +++ b/Service/Export/Processor/Entity/EntityValue/EntityProcessor.php @@ -11,32 +11,25 @@ use Opengento\Gdpr\Model\Entity\DocumentInterface; use Opengento\Gdpr\Model\Entity\EntityValueProcessorInterface; use Opengento\Gdpr\Model\Entity\MetadataInterface; +use function in_array; -/** - * Class EntityProcessor - */ final class EntityProcessor implements EntityValueProcessorInterface { /** - * @var \Opengento\Gdpr\Model\Entity\DocumentInterface + * @var DocumentInterface */ public $document; /** - * @var \Opengento\Gdpr\Model\Entity\MetadataInterface + * @var MetadataInterface */ private $metadata; /** - * @var \Opengento\Gdpr\Model\Entity\DataCollectorInterface + * @var DataCollectorInterface */ private $dataCollector; - /** - * @param \Opengento\Gdpr\Model\Entity\DocumentInterface $document - * @param \Opengento\Gdpr\Model\Entity\MetadataInterface $metadata - * @param \Opengento\Gdpr\Model\Entity\DataCollectorInterface $dataCollector - */ public function __construct( DocumentInterface $document, MetadataInterface $metadata, @@ -47,12 +40,9 @@ public function __construct( $this->dataCollector = $dataCollector; } - /** - * @inheritdoc - */ public function process($entity, string $key, $value): void { - if (\in_array($key, $this->metadata->getAttributes(), true)) { + if (in_array($key, $this->metadata->getAttributes(), true)) { $this->document->addData($key, $this->dataCollector->collect($value)); } } diff --git a/Service/Export/ProcessorFactory.php b/Service/Export/ProcessorFactory.php index 9e49a13..845d2aa 100644 --- a/Service/Export/ProcessorFactory.php +++ b/Service/Export/ProcessorFactory.php @@ -7,10 +7,11 @@ namespace Opengento\Gdpr\Service\Export; +use InvalidArgumentException; use Magento\Framework\ObjectManagerInterface; +use function sprintf; /** - * Class ProcessorFactory * @api */ final class ProcessorFactory @@ -21,13 +22,13 @@ final class ProcessorFactory private $exporters; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $exporters - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $exporters, @@ -37,16 +38,10 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Create a new export processor - * - * @param string $entityType - * @return \Opengento\Gdpr\Service\Export\ProcessorInterface - */ public function get(string $entityType): ProcessorInterface { if (!isset($this->exporters[$entityType])) { - throw new \InvalidArgumentException(\sprintf('Unknown exporter for entity type "%s".', $entityType)); + throw new InvalidArgumentException(sprintf('Unknown exporter for entity type "%s".', $entityType)); } return $this->objectManager->get($this->exporters[$entityType]); diff --git a/Service/Export/ProcessorInterface.php b/Service/Export/ProcessorInterface.php index 566ea08..a687d6b 100644 --- a/Service/Export/ProcessorInterface.php +++ b/Service/Export/ProcessorInterface.php @@ -8,18 +8,10 @@ namespace Opengento\Gdpr\Service\Export; /** - * Interface ProcessorInterface + * Execute the export processor for the given entity ID. It allows to retrieve the related data as an array. * @api */ interface ProcessorInterface { - /** - * Execute the export processor for the given entity ID. - * It allows to retrieve the related data as an array. - * - * @param int $entityId - * @param array $data - * @return array - */ public function execute(int $entityId, array $data): array; } diff --git a/Service/Export/Renderer/AbstractRenderer.php b/Service/Export/Renderer/AbstractRenderer.php index 80b5953..6ba59da 100644 --- a/Service/Export/Renderer/AbstractRenderer.php +++ b/Service/Export/Renderer/AbstractRenderer.php @@ -8,16 +8,14 @@ namespace Opengento\Gdpr\Service\Export\Renderer; use Magento\Framework\App\Filesystem\DirectoryList; +use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem; use Opengento\Gdpr\Service\Export\RendererInterface; -/** - * Class AbstractRenderer - */ abstract class AbstractRenderer implements RendererInterface { /** - * @var \Magento\Framework\Filesystem + * @var Filesystem */ protected $fileSystem; @@ -26,10 +24,6 @@ abstract class AbstractRenderer implements RendererInterface */ protected $fileExtension; - /** - * @param \Magento\Framework\Filesystem $filesystem - * @param string $fileExtension - */ public function __construct( Filesystem $filesystem, string $fileExtension @@ -40,7 +34,7 @@ public function __construct( /** * @inheritdoc - * @throws \Magento\Framework\Exception\FileSystemException + * @throws FileSystemException */ public function saveData(string $fileName, array $data): string { diff --git a/Service/Export/Renderer/CsvRenderer.php b/Service/Export/Renderer/CsvRenderer.php index 2eaeb9d..35dd8cc 100644 --- a/Service/Export/Renderer/CsvRenderer.php +++ b/Service/Export/Renderer/CsvRenderer.php @@ -8,32 +8,27 @@ namespace Opengento\Gdpr\Service\Export\Renderer; use Magento\Framework\Filesystem; +use function is_array; +use function rtrim; +use function str_replace; +use const PHP_EOL; -/** - * Class CsvRenderer - */ final class CsvRenderer extends AbstractRenderer { - /** - * @param \Magento\Framework\Filesystem $filesystem - */ public function __construct( Filesystem $filesystem ) { parent::__construct($filesystem, 'csv'); } - /** - * @inheritdoc - */ public function render(array $data): string { $csv = ''; foreach ($data as $key => $value) { - $csv .= \is_array($value) - ? $key . ',' . \rtrim($this->render($value), ',') . \PHP_EOL - : '"' . \str_replace('"', '""', $value) . '",'; + $csv .= is_array($value) + ? $key . ',' . rtrim($this->render($value), ',') . PHP_EOL + : '"' . str_replace('"', '""', $value) . '",'; } return $csv; diff --git a/Service/Export/Renderer/HtmlRenderer.php b/Service/Export/Renderer/HtmlRenderer.php index b5bc0a4..5fb4cf4 100644 --- a/Service/Export/Renderer/HtmlRenderer.php +++ b/Service/Export/Renderer/HtmlRenderer.php @@ -7,36 +7,41 @@ namespace Opengento\Gdpr\Service\Export\Renderer; +use Exception; +use InvalidArgumentException; use Magento\Framework\DataObject; use Magento\Framework\Filesystem; use Magento\Framework\Translate\InlineInterface; +use Magento\Framework\View\Element\Template; use Magento\Framework\View\FileSystem as ViewFileSystem; use Magento\Framework\View\Page\Config; +use Magento\Framework\View\Page\Config\Renderer; use Magento\Framework\View\Page\Config\RendererFactory; use Opengento\Gdpr\Service\Export\Renderer\HtmlRenderer\LayoutInitiatorInterface; +use function extract; +use function ob_end_clean; +use function ob_get_clean; +use function ob_start; -/** - * Class HtmlRenderer - */ final class HtmlRenderer extends AbstractRenderer { /** - * @var \Opengento\Gdpr\Service\Export\Renderer\HtmlRenderer\LayoutInitiatorInterface + * @var LayoutInitiatorInterface */ private $layoutInitiator; /** - * @var \Magento\Framework\View\Page\Config\Renderer + * @var Renderer */ private $pageConfigRenderer; /** - * @var \Magento\Framework\Translate\InlineInterface + * @var InlineInterface */ private $translateInline; /** - * @var \Magento\Framework\View\FileSystem + * @var ViewFileSystem */ private $viewFileSystem; @@ -45,15 +50,6 @@ final class HtmlRenderer extends AbstractRenderer */ private $template; - /** - * @param \Magento\Framework\Filesystem $filesystem - * @param \Opengento\Gdpr\Service\Export\Renderer\HtmlRenderer\LayoutInitiatorInterface $layoutInitiator - * @param \Magento\Framework\View\Page\Config $pageConfig - * @param \Magento\Framework\View\Page\Config\RendererFactory $pageConfigRendererFactory - * @param \Magento\Framework\Translate\InlineInterface $translateInline - * @param \Magento\Framework\View\FileSystem $viewFileSystem - * @param string $template - */ public function __construct( Filesystem $filesystem, LayoutInitiatorInterface $layoutInitiator, @@ -73,7 +69,7 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function render(array $data): string { @@ -81,7 +77,7 @@ public function render(array $data): string $addBlock = $layout->getBlock('head.additional'); $requireJs = $layout->getBlock('require.js'); - /** @var \Magento\Framework\View\Element\Template $block */ + /** @var Template $block */ $block = $layout->getBlock('main.content.customer.privacy.export.personal.data'); $block->setData('viewModel', new DataObject($data)); @@ -101,28 +97,26 @@ public function render(array $data): string } /** - * Render the layout page to html output - * * @param array $viewVars * @return string - * @throws \Exception + * @throws Exception */ private function renderPage(array $viewVars): string { $fileName = $this->viewFileSystem->getTemplateFileName($this->template); if (!$fileName) { - throw new \InvalidArgumentException('Template "' . $this->template . '" is not found'); + throw new InvalidArgumentException('Template "' . $this->template . '" is not found'); } - \ob_start(); + ob_start(); try { - \extract($viewVars, EXTR_SKIP); + extract($viewVars, EXTR_SKIP); include $fileName; - } catch (\Exception $exception) { - \ob_end_clean(); + } catch (Exception $exception) { + ob_end_clean(); throw $exception; } - return \ob_get_clean(); + return ob_get_clean(); } } diff --git a/Service/Export/Renderer/HtmlRenderer/LayoutInitiator.php b/Service/Export/Renderer/HtmlRenderer/LayoutInitiator.php index 281908b..938b6d8 100644 --- a/Service/Export/Renderer/HtmlRenderer/LayoutInitiator.php +++ b/Service/Export/Renderer/HtmlRenderer/LayoutInitiator.php @@ -7,46 +7,46 @@ namespace Opengento\Gdpr\Service\Export\Renderer\HtmlRenderer; +use LogicException; use Magento\Framework\View\Layout\BuilderFactory; use Magento\Framework\View\Layout\GeneratorPool; use Magento\Framework\View\Layout\ReaderPool; use Magento\Framework\View\LayoutFactory; use Magento\Framework\View\LayoutInterface; +use Magento\Framework\View\Model\Layout\Merge; use Magento\Framework\View\Page\Config; use Magento\Framework\View\Page\Layout\Reader; +use function str_replace; -/** - * Class LayoutInitiator - */ final class LayoutInitiator implements LayoutInitiatorInterface { /** - * @var \Magento\Framework\View\LayoutFactory + * @var LayoutFactory */ private $layoutFactory; /** - * @var \Magento\Framework\View\Layout\BuilderFactory + * @var BuilderFactory */ private $layoutBuilderFactory; /** - * @var \Magento\Framework\View\Layout\ReaderPool + * @var ReaderPool */ private $layoutReaderPool; /** - * @var \Magento\Framework\View\Layout\GeneratorPool + * @var GeneratorPool */ private $layoutGeneratorPool; /** - * @var \Magento\Framework\View\Page\Layout\Reader + * @var Reader */ private $pageLayoutReader; /** - * @var \Magento\Framework\View\Page\Config + * @var Config */ private $pageConfig; @@ -55,15 +55,6 @@ final class LayoutInitiator implements LayoutInitiatorInterface */ private $defaultLayoutHandle; - /** - * @param \Magento\Framework\View\LayoutFactory $layoutFactory - * @param \Magento\Framework\View\Layout\BuilderFactory $layoutBuilderFactory - * @param \Magento\Framework\View\Layout\ReaderPool $layoutReaderPool - * @param \Magento\Framework\View\Layout\GeneratorPool $layoutGeneratorPool - * @param \Magento\Framework\View\Page\Layout\Reader $pageLayoutReader - * @param \Magento\Framework\View\Page\Config $pageConfig - * @param string $defaultLayoutHandle - */ public function __construct( LayoutFactory $layoutFactory, BuilderFactory $layoutBuilderFactory, @@ -82,11 +73,6 @@ public function __construct( $this->defaultLayoutHandle = $defaultLayoutHandle; } - /** - * Create and initialize the page layout instructions - * - * @return \Magento\Framework\View\LayoutInterface - */ public function createLayout(): LayoutInterface { $layout = $this->layoutFactory->create([ @@ -97,7 +83,7 @@ public function createLayout(): LayoutInterface $layout->getUpdate()->addHandle('default'); $layout->getUpdate()->addHandle($this->defaultLayoutHandle); - /** @var \Magento\Framework\View\Model\Layout\Merge $update */ + /** @var Merge $update */ $update = $layout->getUpdate(); if ($update->isLayoutDefined()) { $update->removeHandle('default'); @@ -106,12 +92,6 @@ public function createLayout(): LayoutInterface return $this->addConfigLayout($layout); } - /** - * Add the default configuration to the page layout - * - * @param \Magento\Framework\View\LayoutInterface $layout - * @return \Magento\Framework\View\LayoutInterface - */ private function addConfigLayout(LayoutInterface $layout): LayoutInterface { $this->layoutBuilderFactory->create( @@ -123,15 +103,15 @@ private function addConfigLayout(LayoutInterface $layout): LayoutInterface ] )->build(); - /** @var \Magento\Framework\View\Model\Layout\Merge $update */ + /** @var Merge $update */ $update = $layout->getUpdate(); $pageLayout = $this->pageConfig->getPageLayout() ?: $update->getPageLayout(); if (!$pageLayout) { - throw new \LogicException('Page layout is missing.'); + throw new LogicException('Page layout is missing.'); } - $this->pageConfig->addBodyClass(\str_replace('_', '-', $this->defaultLayoutHandle)); + $this->pageConfig->addBodyClass(str_replace('_', '-', $this->defaultLayoutHandle)); $this->pageConfig->addBodyClass('page-layout-' . $pageLayout); return $layout; diff --git a/Service/Export/Renderer/HtmlRenderer/LayoutInitiatorInterface.php b/Service/Export/Renderer/HtmlRenderer/LayoutInitiatorInterface.php index cbead47..e130db9 100644 --- a/Service/Export/Renderer/HtmlRenderer/LayoutInitiatorInterface.php +++ b/Service/Export/Renderer/HtmlRenderer/LayoutInitiatorInterface.php @@ -10,15 +10,9 @@ use Magento\Framework\View\LayoutInterface; /** - * Interface LayoutInitiatorInterface * @api */ interface LayoutInitiatorInterface { - /** - * Create and initialize the page layout instructions - * - * @return \Magento\Framework\View\LayoutInterface - */ public function createLayout(): LayoutInterface; } diff --git a/Service/Export/Renderer/JsonRenderer.php b/Service/Export/Renderer/JsonRenderer.php index e91850e..3100e45 100644 --- a/Service/Export/Renderer/JsonRenderer.php +++ b/Service/Export/Renderer/JsonRenderer.php @@ -10,20 +10,13 @@ use Magento\Framework\Filesystem; use Magento\Framework\Serialize\Serializer\Json; -/** - * Class JsonRenderer - */ final class JsonRenderer extends AbstractRenderer { /** - * @var \Magento\Framework\Serialize\Serializer\Json + * @var Json */ private $jsonSerializer; - /** - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\Framework\Serialize\Serializer\Json $jsonSerializer - */ public function __construct( Filesystem $filesystem, Json $jsonSerializer @@ -32,9 +25,6 @@ public function __construct( parent::__construct($filesystem, 'json'); } - /** - * @inheritdoc - */ public function render(array $data): string { return $this->jsonSerializer->serialize($data); diff --git a/Service/Export/Renderer/PdfRenderer.php b/Service/Export/Renderer/PdfRenderer.php index be72de6..1617791 100644 --- a/Service/Export/Renderer/PdfRenderer.php +++ b/Service/Export/Renderer/PdfRenderer.php @@ -7,29 +7,24 @@ namespace Opengento\Gdpr\Service\Export\Renderer; +use Exception; use Magento\Framework\Filesystem; +use mikehaertl\wkhtmlto\Pdf; use mikehaertl\wkhtmlto\PdfFactory; +use RuntimeException; -/** - * Class PdfRenderer - */ final class PdfRenderer extends AbstractRenderer { /** - * @var \mikehaertl\wkhtmlto\PdfFactory + * @var PdfFactory */ private $pdfFactory; /** - * @var \Opengento\Gdpr\Service\Export\Renderer\HtmlRenderer + * @var HtmlRenderer */ private $htmlRenderer; - /** - * @param \Magento\Framework\Filesystem $filesystem - * @param \mikehaertl\wkhtmlto\PdfFactory $pdfFactory - * @param \Opengento\Gdpr\Service\Export\Renderer\HtmlRenderer $htmlRenderer - */ public function __construct( Filesystem $filesystem, PdfFactory $pdfFactory, @@ -42,11 +37,11 @@ public function __construct( /** * @inheritdoc - * @throws \Exception + * @throws Exception */ public function render(array $data): string { - /** @var \mikehaertl\wkhtmlto\Pdf $pdf */ + /** @var Pdf $pdf */ $pdf = $this->pdfFactory->create([ 'options' => [ 'ignoreWarnings' => true, @@ -68,7 +63,7 @@ public function render(array $data): string $pdf->addPage($this->htmlRenderer->render($data)); if (($result = $pdf->toString()) === false) { - throw new \RuntimeException('The PDF was not created successfully.'); + throw new RuntimeException('The PDF was not created successfully.'); } return $result; diff --git a/Service/Export/Renderer/RendererStrategy.php b/Service/Export/Renderer/RendererStrategy.php deleted file mode 100644 index bcbd404..0000000 --- a/Service/Export/Renderer/RendererStrategy.php +++ /dev/null @@ -1,72 +0,0 @@ -exportRendererFactory = $exportRendererFactory; - $this->config = $config; - } - - /** - * @inheritdoc - */ - public function render(array $data): string - { - return $this->resolveRenderer()->render($data); - } - - /** - * @inheritdoc - */ - public function saveData(string $fileName, array $data): string - { - return $this->resolveRenderer()->saveData($fileName, $data); - } - - /** - * Resolve and retrieve the current renderer - * - * @return \Opengento\Gdpr\Service\Export\RendererInterface - */ - private function resolveRenderer(): RendererInterface - { - return $this->renderer ?? - $this->renderer = $this->exportRendererFactory->create($this->config->getExportRendererCode()); - } -} diff --git a/Service/Export/Renderer/XmlRenderer.php b/Service/Export/Renderer/XmlRenderer.php index e4495a8..aabf298 100644 --- a/Service/Export/Renderer/XmlRenderer.php +++ b/Service/Export/Renderer/XmlRenderer.php @@ -8,36 +8,39 @@ namespace Opengento\Gdpr\Service\Export\Renderer; use Magento\Framework\Convert\ConvertArray; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Filesystem; -/** - * Class XmlRenderer - */ final class XmlRenderer extends AbstractRenderer { + private const ROOT_NAME = 'data'; + /** - * @var \Magento\Framework\Convert\ConvertArray + * @var ConvertArray */ private $convertArray; /** - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\Framework\Convert\ConvertArray $convertArray + * @var string */ + private $rootName; + public function __construct( Filesystem $filesystem, - ConvertArray $convertArray + ConvertArray $convertArray, + string $rootName = self::ROOT_NAME ) { $this->convertArray = $convertArray; + $this->rootName = $rootName; parent::__construct($filesystem, 'xml'); } /** * @inheritdoc - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function render(array $data): string { - return (string) $this->convertArray->assocToXml($data); + return $this->convertArray->assocToXml($data, $this->rootName)->saveXML(); } } diff --git a/Service/Export/RendererFactory.php b/Service/Export/RendererFactory.php index c819fff..3e31a18 100644 --- a/Service/Export/RendererFactory.php +++ b/Service/Export/RendererFactory.php @@ -7,10 +7,11 @@ namespace Opengento\Gdpr\Service\Export; +use InvalidArgumentException; use Magento\Framework\ObjectManagerInterface; +use function sprintf; /** - * Class ExportFactory * @api */ final class RendererFactory @@ -21,13 +22,13 @@ final class RendererFactory private $renderers; /** - * @var \Magento\Framework\ObjectManagerInterface + * @var ObjectManagerInterface */ private $objectManager; /** * @param string[] $renderers - * @param \Magento\Framework\ObjectManagerInterface $objectManager + * @param ObjectManagerInterface $objectManager */ public function __construct( array $renderers, @@ -37,19 +38,12 @@ public function __construct( $this->objectManager = $objectManager; } - /** - * Create a new export renderer - * - * @param string $rendererCode - * @param array $arguments - * @return \Opengento\Gdpr\Service\Export\RendererInterface - */ - public function create(string $rendererCode, array $arguments = []): RendererInterface + public function get(string $rendererCode): RendererInterface { if (!isset($this->renderers[$rendererCode])) { - throw new \InvalidArgumentException(\sprintf('Unknown renderer type "%s".', $rendererCode)); + throw new InvalidArgumentException(sprintf('Unknown renderer type "%s".', $rendererCode)); } - return $this->objectManager->create($this->renderers[$rendererCode], $arguments); + return $this->objectManager->get($this->renderers[$rendererCode]); } } diff --git a/Service/Export/RendererInterface.php b/Service/Export/RendererInterface.php index bd6c9c7..e805e20 100644 --- a/Service/Export/RendererInterface.php +++ b/Service/Export/RendererInterface.php @@ -8,25 +8,11 @@ namespace Opengento\Gdpr\Service\Export; /** - * Interface RendererInterface * @api */ interface RendererInterface { - /** - * Render the data to an output string format - * - * @param array $data - * @return string - */ public function render(array $data): string; - /** - * Render and save the data to an output format file - * - * @param string $fileName - * @param array $data - * @return string - */ public function saveData(string $fileName, array $data): string; } diff --git a/TODO.md b/TODO.md index 6747841..28d4b92 100644 --- a/TODO.md +++ b/TODO.md @@ -21,6 +21,9 @@ Area: - Payment Data - Invitation Data +- invalidate export document when personal data are altered + - in this way, add plugin / observer, depends of the entity persistence + ## Anonymizer - Payment Data @@ -69,10 +72,13 @@ Area: - Admin UI (OK) - Frontend UI (OK) - Console (OK) +- Notifier (OK) ## Notification notify customer from its requests +- Configuration +- Mail templates ## yu @@ -80,4 +86,4 @@ https://github.com/magento/architecture/pull/145/files ## Improvements -Disable checks and validators on mass actions (including cron) +Only one anonymization configuration grid: entity type | attribute code | anonymizer diff --git a/ViewModel/Customer/Guest/EraseDataProvider.php b/ViewModel/Customer/Guest/EraseDataProvider.php new file mode 100644 index 0000000..c9fb070 --- /dev/null +++ b/ViewModel/Customer/Guest/EraseDataProvider.php @@ -0,0 +1,64 @@ +eraseEntityChecker = $eraseEntityChecker; + $this->registry = $registry; + } + + public function canCancel(): bool + { + return $this->canCancel ?? + $this->canCancel = $this->eraseEntityChecker->canCancel($this->currentOrderId(), 'order'); + } + + public function canCreate(): bool + { + return $this->canCreate ?? + $this->canCreate = $this->eraseEntityChecker->canCreate($this->currentOrderId(), 'order'); + } + + private function currentOrderId(): int + { + /** @var OrderInterface $order */ + $order = $this->registry->registry('current_order'); + + return (int) $order->getEntityId(); + } +} diff --git a/ViewModel/Customer/Guest/ExportDataProvider.php b/ViewModel/Customer/Guest/ExportDataProvider.php new file mode 100644 index 0000000..e9aae61 --- /dev/null +++ b/ViewModel/Customer/Guest/ExportDataProvider.php @@ -0,0 +1,64 @@ +exportEntityChecker = $exportEntityChecker; + $this->registry = $registry; + } + + public function hasExport(): bool + { + return $this->isExportEntityExists ?? + $this->isExportEntityExists = $this->exportEntityChecker->exists($this->currentOrderId(), 'order'); + } + + public function isExported(): bool + { + return $this->isExported ?? + $this->isExported = $this->exportEntityChecker->isExported($this->currentOrderId(), 'order'); + } + + private function currentOrderId(): int + { + /** @var OrderInterface $order */ + $order = $this->registry->registry('current_order'); + + return (int) $order->getEntityId(); + } +} diff --git a/ViewModel/Customer/Privacy/EraseCustomerDataProvider.php b/ViewModel/Customer/Privacy/EraseCustomerDataProvider.php new file mode 100644 index 0000000..94a7702 --- /dev/null +++ b/ViewModel/Customer/Privacy/EraseCustomerDataProvider.php @@ -0,0 +1,60 @@ +eraseEntityChecker = $eraseEntityChecker; + $this->session = $session; + } + + public function canCancel(): bool + { + return $this->canCancel ?? + $this->canCancel = $this->eraseEntityChecker->canCancel($this->currentCustomerId(), 'customer'); + } + + public function canCreate(): bool + { + return $this->canCreate ?? + $this->canCreate = $this->eraseEntityChecker->canCreate($this->currentCustomerId(), 'customer'); + } + + private function currentCustomerId(): int + { + return (int) $this->session->getCustomerId(); + } +} diff --git a/ViewModel/Customer/Privacy/EraseDataProvider.php b/ViewModel/Customer/Privacy/EraseDataProvider.php new file mode 100644 index 0000000..fc60bde --- /dev/null +++ b/ViewModel/Customer/Privacy/EraseDataProvider.php @@ -0,0 +1,62 @@ +config = $config; + $this->blockFactory = $blockFactory; + } + + public function getErasureInformationHtml(): string + { + return $this->erasureInformation ?? + $this->erasureInformation = $this->blockFactory->createBlock( + Block::class, + ['data' => ['block_id' => $this->config->getErasureInformationBlockId()]] + )->toHtml(); + } + + public function getAnonymizeInformationHtml(): string + { + return $this->anonymizeInformation ?? + $this->anonymizeInformation = $this->blockFactory->createBlock( + Block::class, + ['data' => ['block_id' => $this->config->getAnonymizeInformationBlockId()]] + )->toHtml(); + } +} diff --git a/ViewModel/Customer/Privacy/ExportCustomerDataProvider.php b/ViewModel/Customer/Privacy/ExportCustomerDataProvider.php new file mode 100644 index 0000000..ef369f6 --- /dev/null +++ b/ViewModel/Customer/Privacy/ExportCustomerDataProvider.php @@ -0,0 +1,60 @@ +exportEntityChecker = $exportEntityChecker; + $this->session = $session; + } + + public function hasExport(): bool + { + return $this->isExportEntityExists ?? + $this->isExportEntityExists = $this->exportEntityChecker->exists($this->currentCustomerId(), 'customer'); + } + + public function isExported(): bool + { + return $this->isExported ?? + $this->isExported = $this->exportEntityChecker->isExported($this->currentCustomerId(), 'customer'); + } + + private function currentCustomerId(): int + { + return (int) $this->session->getCustomerId(); + } +} diff --git a/ViewModel/Customer/Privacy/ExportDataProvider.php b/ViewModel/Customer/Privacy/ExportDataProvider.php new file mode 100644 index 0000000..7eb04d1 --- /dev/null +++ b/ViewModel/Customer/Privacy/ExportDataProvider.php @@ -0,0 +1,48 @@ +config = $config; + $this->blockFactory = $blockFactory; + } + + public function getExportInformationHtml(): string + { + return $this->exportInformation ?? + $this->exportInformation = $this->blockFactory->createBlock( + Block::class, + ['data' => ['block_id' => $this->config->getExportInformationBlockId()]] + )->toHtml(); + } +} diff --git a/ViewModel/Customer/Privacy/SettingsDataProvider.php b/ViewModel/Customer/Privacy/SettingsDataProvider.php new file mode 100644 index 0000000..cc55d56 --- /dev/null +++ b/ViewModel/Customer/Privacy/SettingsDataProvider.php @@ -0,0 +1,48 @@ +config = $config; + $this->blockFactory = $blockFactory; + } + + public function getPrivacyInformationHtml(): string + { + return $this->privacyInformationHtml ?? + $this->privacyInformationHtml = $this->blockFactory->createBlock( + Block::class, + ['data' => ['block_id' => $this->config->getPrivacyInformationBlockId()]] + )->toHtml(); + } +} diff --git a/ViewModel/Privacy/EraseCustomerDataProvider.php b/ViewModel/Privacy/EraseCustomerDataProvider.php deleted file mode 100644 index c943e99..0000000 --- a/ViewModel/Privacy/EraseCustomerDataProvider.php +++ /dev/null @@ -1,74 +0,0 @@ -eraseEntityChecker = $eraseEntityChecker; - $this->session = $session; - parent::__construct($data); - } - - /** - * Check if the erasure is already planned and could be canceled - * - * @return bool - */ - public function canCancel(): bool - { - if (!$this->hasData('can_cancel')) { - $canCancel = $this->eraseEntityChecker->canCancel((int) $this->session->getCustomerId(), 'customer'); - $this->setData('can_cancel', $canCancel); - } - - return (bool) $this->_getData('can_cancel'); - } - - /** - * Check if the erasure can be planned and processed - * - * @return bool - */ - public function canCreate(): bool - { - if (!$this->hasData('can_create')) { - $canCreate = $this->eraseEntityChecker->canCreate((int) $this->session->getCustomerId(), 'customer'); - $this->setData('can_create', $canCreate); - } - - return (bool) $this->_getData('can_create'); - } -} diff --git a/ViewModel/Privacy/EraseDataProvider.php b/ViewModel/Privacy/EraseDataProvider.php deleted file mode 100644 index c1648c8..0000000 --- a/ViewModel/Privacy/EraseDataProvider.php +++ /dev/null @@ -1,91 +0,0 @@ -config = $config; - $this->blockFactory = $blockFactory; - parent::__construct($data); - } - - /** - * Check if the erasure is enabled - * - * @return bool - */ - public function isErasureEnabled(): bool - { - return $this->config->isExportEnabled(); - } - - /** - * Retrieve the erase information html - * - * @return string - */ - public function getErasureInformation(): string - { - if (!$this->hasData('erasure_information')) { - $block = $this->blockFactory->createBlock( - Block::class, - ['data' => ['block_id' => $this->config->getErasureInformationBlockId()]] - ); - $this->setData('erasure_information', $block->toHtml()); - } - - return (string) $this->_getData('erasure_information'); - } - - /** - * Retrieve the anonymize information html - * - * @return string - */ - public function getAnonymizeInformation(): string - { - if (!$this->hasData('anonymize_information')) { - $block = $this->blockFactory->createBlock( - Block::class, - ['data' => ['block_id' => $this->config->getAnonymizeInformationBlockId()]] - ); - $this->setData('anonymize_information', $block->toHtml()); - } - - return (string) $this->_getData('anonymize_information'); - } -} diff --git a/ViewModel/Privacy/EraseGuestDataProvider.php b/ViewModel/Privacy/EraseGuestDataProvider.php deleted file mode 100644 index 0031de9..0000000 --- a/ViewModel/Privacy/EraseGuestDataProvider.php +++ /dev/null @@ -1,85 +0,0 @@ -eraseEntityChecker = $eraseEntityChecker; - $this->registry = $registry; - parent::__construct($data); - } - - /** - * Check if the erasure is already planned and could be canceled - * - * @return bool - */ - public function canCancel(): bool - { - if (!$this->hasData('can_cancel')) { - $canCancel = $this->eraseEntityChecker->canCancel((int) $this->resolveOrder()->getEntityId(), 'order'); - $this->setData('can_cancel', $canCancel); - } - - return (bool) $this->_getData('can_cancel'); - } - - /** - * Check if the erasure can be planned and processed - * - * @return bool - */ - public function canCreate(): bool - { - if (!$this->hasData('can_create')) { - $canCreate = $this->eraseEntityChecker->canCreate((int) $this->resolveOrder()->getEntityId(), 'order'); - $this->setData('can_create', $canCreate); - } - - return (bool) $this->_getData('can_create'); - } - - /** - * Resolve the current order - * - * @return \Magento\Sales\Api\Data\OrderInterface - */ - private function resolveOrder(): OrderInterface - { - return $this->registry->registry('current_order'); - } -} diff --git a/ViewModel/Privacy/ExportDataProvider.php b/ViewModel/Privacy/ExportDataProvider.php deleted file mode 100644 index 78667b1..0000000 --- a/ViewModel/Privacy/ExportDataProvider.php +++ /dev/null @@ -1,73 +0,0 @@ -config = $config; - $this->blockFactory = $blockFactory; - parent::__construct($data); - } - - /** - * Check if the export is enabled - * - * @return bool - */ - public function isExportEnabled(): bool - { - return $this->config->isExportEnabled(); - } - - /** - * Retrieve the privacy information html - * - * @return string - */ - public function getExportInformation(): string - { - if (!$this->hasData('export_information')) { - $block = $this->blockFactory->createBlock( - Block::class, - ['data' => ['block_id' => $this->config->getExportInformationBlockId()]] - ); - $this->setData('export_information', $block->toHtml()); - } - - return (string) $this->_getData('export_information'); - } -} diff --git a/ViewModel/Privacy/SettingsDataProvider.php b/ViewModel/Privacy/SettingsDataProvider.php deleted file mode 100644 index 6b39008..0000000 --- a/ViewModel/Privacy/SettingsDataProvider.php +++ /dev/null @@ -1,73 +0,0 @@ -config = $config; - $this->blockFactory = $blockFactory; - parent::__construct($data); - } - - /** - * Check if the module is enabled - * - * @return bool - */ - public function isModuleEnabled(): bool - { - return $this->config->isModuleEnabled(); - } - - /** - * Retrieve the privacy information html - * - * @return string - */ - public function getPrivacyInformation(): string - { - if (!$this->hasData('privacy_information')) { - $block = $this->blockFactory->createBlock( - Block::class, - ['data' => ['block_id' => $this->config->getPrivacyInformationBlockId()]] - ); - $this->setData('privacy_information', $block->toHtml()); - } - - return (string) $this->_getData('privacy_information'); - } -} diff --git a/ViewModel/UrlsDataProvider.php b/ViewModel/UrlsDataProvider.php deleted file mode 100644 index 04cfee4..0000000 --- a/ViewModel/UrlsDataProvider.php +++ /dev/null @@ -1,119 +0,0 @@ -urlBuilder = $urlBuilder; - $this->helperPage = $helperPage; - $this->config = $config; - } - - /** - * Retrieve the information page url - * - * @return string - */ - public function getInformationPageUrl(): string - { - return (string) $this->helperPage->getPageUrl($this->config->getPrivacyInformationPageId()); - } - - /** - * Retrieve the settings page url - * - * @return string - */ - public function getSettingsPageUrl(): string - { - return $this->urlBuilder->getUrl(self::ROUTE_PATH_SETTINGS); - } - - /** - * Retrieve the erase page url - * - * @return string - */ - public function getErasePageUrl(): string - { - return $this->urlBuilder->getUrl(self::ROUTE_PATH_ERASE); - } - - /** - * Retrieve the erase action url - * - * @return string - */ - public function getEraseActionUrl(): string - { - return $this->urlBuilder->getUrl(self::ROUTE_PATH_ERASE_POST); - } - - /** - * Retrieve the undo erase action url - * - * @return string - */ - public function getUndoEraseActionUrl(): string - { - return $this->urlBuilder->getUrl(self::ROUTE_PATH_UNDO_ERASE); - } - - /** - * Retrieve the export action url - * - * @return string - */ - public function getExportActionUrl(): string - { - return $this->urlBuilder->getUrl(self::ROUTE_PATH_EXPORT); - } -} diff --git a/composer.json b/composer.json index bac182a..8e57418 100755 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "rgpd" ], "require": { + "php": ">=7.2", "ext-zip": "*", "mikehaertl/phpwkhtmltopdf": "^2.3.1", "magento/framework": "^102.0.0", diff --git a/etc/acl.xml b/etc/acl.xml index d657f60..cab04f6 100755 --- a/etc/acl.xml +++ b/etc/acl.xml @@ -28,6 +28,13 @@ + + + + + + + diff --git a/etc/adminhtml/di.xml b/etc/adminhtml/di.xml index a44c64b..0a58909 100644 --- a/etc/adminhtml/di.xml +++ b/etc/adminhtml/di.xml @@ -6,30 +6,59 @@ */ --> - + + - Opengento\Gdpr\Model\Archive\Zip + + + Opengento\Gdpr\Api\Data\ActionEntityInterface::MESSAGE + + - - + + - Opengento\Gdpr\Model\Archive\MoveToZip - Opengento\Gdpr\Model\Customer\Export\ExportCustomerFactory + Opengento\Gdpr\Model\Action\EraseCreateExecuteAction - + - Opengento\Gdpr\Model\Archive\MoveToZip - Opengento\Gdpr\Model\Customer\Export\ExportCustomerFactory + Opengento\Gdpr\Model\Action\EraseCreateExecuteAction + + + + + Opengento\Gdpr\Model\Action\EraseCreateExecuteAction + + + + + Opengento\Gdpr\Model\Action\ExportCreateOrExecuteAction + Opengento\Gdpr\Model\Action\ExportCreateOrExecuteAction + + + + + Opengento\Gdpr\Model\Action\ExportCreateOrExecuteAction Opengento\Gdpr\Model\Archive\MoveToZip - Opengento\Gdpr\Model\Order\Export\ExportOrderFactory + + + Opengento\Gdpr\Model\Action\ActionFactory + actions + + + + + Magento\Framework\Model\EntitySnapshot\AttributeProvider + + Magento\Customer\Api\CustomerMetadataInterface @@ -52,10 +81,16 @@ anonymizers - + + + Opengento\Gdpr\Model\Customer\Erase\ProcessorResolverFactory + processorResolvers + + + - Opengento\Gdpr\Service\Erase\ProcessorFactory - processors + Opengento\Gdpr\Model\Customer\Erase\ProcessorResolverFactory + processorResolvers @@ -63,9 +98,40 @@ Opengento\Gdpr\Model\Config\Source\Anonymizers - + + + Opengento\Gdpr\Model\Config\Source\Customer\EraseComponents + + + + + Opengento\Gdpr\Model\Config\Source\Order\EraseComponents + + + + + Opengento\Gdpr\Model\Config\Source\Customer\EraseProcessors + + + + + Opengento\Gdpr\Model\Config\Source\Order\EraseProcessors + + + + + + Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\Customer\EraseComponents + Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\Customer\EraseProcessors + + + + - Opengento\Gdpr\Model\Config\Source\EraseProcessors + + Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\Order\EraseComponents + Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Select\Order\EraseProcessors + diff --git a/etc/adminhtml/menu.xml b/etc/adminhtml/menu.xml new file mode 100644 index 0000000..974a9cf --- /dev/null +++ b/etc/adminhtml/menu.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/etc/adminhtml/routes.xml b/etc/adminhtml/routes.xml index 81c6c76..f8bb8ba 100644 --- a/etc/adminhtml/routes.xml +++ b/etc/adminhtml/routes.xml @@ -7,6 +7,9 @@ --> + + + diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 0b73d7a..5924a0e 100755 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -13,13 +13,17 @@ customer Opengento_Gdpr::config - + + + - + - + + + - + diff --git a/etc/adminhtml/system/action.xml b/etc/adminhtml/system/action.xml new file mode 100644 index 0000000..2d415a7 --- /dev/null +++ b/etc/adminhtml/system/action.xml @@ -0,0 +1,15 @@ + + + + + + + 1 + + + diff --git a/etc/adminhtml/system/cookie.xml b/etc/adminhtml/system/cookie.xml index 1e76705..67c47f1 100644 --- a/etc/adminhtml/system/cookie.xml +++ b/etc/adminhtml/system/cookie.xml @@ -6,7 +6,7 @@ */ --> - + 1 diff --git a/etc/adminhtml/system/erasure.xml b/etc/adminhtml/system/erasure.xml index 623ddd4..1817b82 100644 --- a/etc/adminhtml/system/erasure.xml +++ b/etc/adminhtml/system/erasure.xml @@ -6,7 +6,7 @@ */ --> - + 1 @@ -78,7 +78,7 @@ Defines the components erasure strategy with the component/erase processor mapper for the customers. - Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\EraseComponentsProcessors + Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Customer\EraseComponentsProcessors Magento\Config\Model\Config\Backend\Serialized\ArraySerialized 1 @@ -89,7 +89,7 @@ Defines the components erasure strategy with the component/erase processor mapper for the guests. - Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\EraseComponentsProcessors + Opengento\Gdpr\Block\Adminhtml\Config\Form\Field\Order\EraseComponentsProcessors Magento\Config\Model\Config\Backend\Serialized\ArraySerialized 1 diff --git a/etc/adminhtml/system/export.xml b/etc/adminhtml/system/export.xml index 1a315ae..c61ac98 100644 --- a/etc/adminhtml/system/export.xml +++ b/etc/adminhtml/system/export.xml @@ -6,7 +6,7 @@ */ --> - + 1 @@ -25,15 +25,48 @@ gdpr/export/block_id - - + + + Select formats of the export. Notice: At least one human and one machine readable format should be selected. Opengento\Gdpr\Model\Config\Source\ExportRenderer 1 - gdpr/export/renderer + gdpr/export/renderers - + + + We will use this value as file name of the document export. + validate-number + + 1 + + gdpr/export/file_name + + + + + 1 + + gdpr/export/entity_schedule + + + + Export life time in minute before it is removed from the server. + validate-number + + 1 + + gdpr/export/life_time + + + + + 1 + + gdpr/export/entity_expired_schedule + + @@ -47,7 +80,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -56,7 +89,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -64,7 +97,7 @@ gdpr/export/customer_extensible_data - + @@ -78,7 +111,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -87,7 +120,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -95,11 +128,11 @@ gdpr/export/customer_address_extensible_data - + - Attributes must be separated with comma. + Comma-separated 1 1 @@ -108,7 +141,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -117,7 +150,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -125,11 +158,11 @@ gdpr/export/quote_extensible_data - + - Attributes must be separated with comma. + Comma-separated 1 1 @@ -138,7 +171,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -147,7 +180,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -155,11 +188,11 @@ gdpr/export/quote_address_extensible_data - + - Attributes must be separated with comma. + Comma-separated 1 1 @@ -168,7 +201,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -177,7 +210,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -185,11 +218,11 @@ gdpr/export/order_extensible_data - + - Attributes must be separated with comma. + Comma-separated 1 1 @@ -198,7 +231,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -207,7 +240,7 @@ - Attributes must be separated with comma. + Comma-separated 1 1 @@ -215,11 +248,11 @@ gdpr/export/order_address_extensible_data - + - Attributes must be separated with comma. + Comma-separated 1 1 diff --git a/etc/adminhtml/system/notification.xml b/etc/adminhtml/system/notification.xml new file mode 100644 index 0000000..8206121 --- /dev/null +++ b/etc/adminhtml/system/notification.xml @@ -0,0 +1,205 @@ + + + + + + + + + + Magento\Config\Model\Config\Source\Yesno + + 1 + + gdpr/notification/erase_enabled + It will enable the module features in the admin and frontend ui. + + + + + + + + + Magento\Config\Model\Config\Source\Yesno + gdpr/notification/erase_pending_enabled + + + + Magento\Config\Model\Config\Source\Email\Identity + gdpr/notification/erase_pending_identity + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/erase_pending_template + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/erase_pending_guest_template + + + + Comma-separated + gdpr/notification/erase_pending_copy_to + + + + Magento\Config\Model\Config\Source\Email\Method + gdpr/notification/erase_pending_copy_method + + + + + + + Magento\Config\Model\Config\Source\Yesno + gdpr/notification/erase_succeeded_enabled + + + + Magento\Config\Model\Config\Source\Email\Identity + gdpr/notification/erase_succeeded_identity + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/erase_succeeded_template + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/erase_succeeded_guest_template + + + + Comma-separated + gdpr/notification/erase_succeeded_copy_to + + + + Magento\Config\Model\Config\Source\Email\Method + gdpr/notification/erase_succeeded_copy_method + + + + + + + Magento\Config\Model\Config\Source\Yesno + gdpr/notification/erase_canceled_enabled + + + + Magento\Config\Model\Config\Source\Email\Identity + gdpr/notification/erase_canceled_identity + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/erase_canceled_template + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/erase_canceled_guest_template + + + + Comma-separated + gdpr/notification/erase_canceled_copy_to + + + + Magento\Config\Model\Config\Source\Email\Method + gdpr/notification/erase_canceled_copy_method + + + + + + + + + + Magento\Config\Model\Config\Source\Yesno + gdpr/notification/export_pending_enabled + + + + Magento\Config\Model\Config\Source\Email\Identity + gdpr/notification/export_pending_identity + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/export_pending_template + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/export_pending_guest_template + + + + Comma-separated + gdpr/notification/export_pending_copy_to + + + + Magento\Config\Model\Config\Source\Email\Method + gdpr/notification/export_pending_copy_method + + + + + + + Magento\Config\Model\Config\Source\Yesno + gdpr/notification/export_ready_enabled + + + + Magento\Config\Model\Config\Source\Email\Identity + gdpr/notification/export_ready_identity + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/export_ready_template + + + + Email template chosen based on theme fallback when "Default" option is selected. + Magento\Config\Model\Config\Source\Email\Template + gdpr/notification/export_ready_guest_template + + + + Comma-separated + gdpr/notification/export_ready_copy_to + + + + Magento\Config\Model\Config\Source\Email\Method + gdpr/notification/export_ready_copy_method + + + + + diff --git a/etc/config.xml b/etc/config.xml index 84e7b70..0b262c6 100755 --- a/etc/config.xml +++ b/etc/config.xml @@ -12,6 +12,8 @@ 0 privacy-policy-cookie-restriction-mode + + 3650 canceled,closed,complete 1 - + - + + + + 0 - pdf + pdf,xml + personal_data + * * * * * + 3600 + * * * * * prefix,firstname,middlename,lastname,suffix,email,dob,gender,taxvat prefix,firstname,middlename,lastname,suffix,company,street,city,country_id,province,postcode,fax,telephone,vat_id customer_email,customer_prefix,customer_middlename,customer_lastname,customer_suffix,customer_dob,customer_gender,customer_taxvat,remote_ip @@ -147,6 +160,85 @@ city,company,country_id,fax,email,prefix,firstname,middlename,lastname,suffix,postcode,region,street,telephone,vat_id email + + + 0 + + + + + 0 + + general + bcc + + + 0 + + general + bcc + + + + + 0 + + general + bcc + + + 0 + + general + bcc + + + + + 0 + + general + bcc + + + 0 + + general + bcc + + + + + + + 0 + + general + bcc + + + 0 + + general + bcc + + + + + 0 + + general + bcc + + + 0 + + general + bcc + + + + 0 diff --git a/etc/crontab.xml b/etc/crontab.xml index 436ced6..d8c7880 100755 --- a/etc/crontab.xml +++ b/etc/crontab.xml @@ -13,5 +13,11 @@ gdpr/erasure/entity_max_age_schedule + + gdpr/erasure/entity_schedule + + + gdpr/export/entity_expired_schedule + diff --git a/etc/db_schema.xml b/etc/db_schema.xml index 15d5cec..d9a4d88 100644 --- a/etc/db_schema.xml +++ b/etc/db_schema.xml @@ -6,8 +6,8 @@ */ --> - - +
+ @@ -25,4 +25,74 @@
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + +
+ + + + + + + + + +
+ + + + + + + + + +
diff --git a/etc/di.xml b/etc/di.xml index 1ad4424..23b9c78 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -6,22 +6,175 @@ */ --> - + + + + + + + + + + + Opengento\Gdpr\Model\ResourceModel\ActionEntity\Validator\StateValidator + + + + - + + + + + + + + Opengento\Gdpr\Api\ActionEntityRepositoryInterface Opengento\Gdpr\Api\EraseEntityRepositoryInterface + Opengento\Gdpr\Api\ExportEntityRepositoryInterface + + + + + + + Magento\Framework\EntityManager\AbstractModelHydrator + Magento\Framework\EntityManager\AbstractModelHydrator + Magento\Framework\EntityManager\AbstractModelHydrator + Magento\Framework\EntityManager\AbstractModelHydrator + + Magento\Framework\EntityManager\AbstractModelHydrator + Magento\Framework\EntityManager\AbstractModelHydrator + Magento\Framework\EntityManager\AbstractModelHydrator + Magento\Framework\EntityManager\AbstractModelHydrator + + + + + + + + Opengento\Gdpr\Model\Customer\Erase\Notifier\Pending + Opengento\Gdpr\Model\Order\Erase\Notifier\Pending + + + + + + + Opengento\Gdpr\Model\Customer\Erase\Notifier\Succeeded + Opengento\Gdpr\Model\Order\Erase\Notifier\Succeeded + + + + + + + Opengento\Gdpr\Model\Customer\Erase\Notifier\Canceled + Opengento\Gdpr\Model\Order\Erase\Notifier\Canceled + + + + + + + + Opengento\Gdpr\Model\Customer\Export\Notifier\Pending + Opengento\Gdpr\Model\Order\Export\Notifier\Pending + + + + + + + Opengento\Gdpr\Model\Customer\Export\Notifier\Ready + Opengento\Gdpr\Model\Order\Export\Notifier\Ready + + + + + + + + Opengento\Gdpr\Model\Action\EraseCreateAction + Opengento\Gdpr\Model\Action\EraseExecuteAction + Opengento\Gdpr\Model\Action\EraseCancelAction + Opengento\Gdpr\Model\Action\EraseCreateExecuteAction + Opengento\Gdpr\Model\Action\ExportCreateAction + Opengento\Gdpr\Model\Action\ExportExecuteAction + Opengento\Gdpr\Model\Action\ExportCreateOrExecuteAction + + + erase_create + + Opengento\Gdpr\Model\Action\Erase\CreateAction + Opengento\Gdpr\Model\Action\Erase\CreateNotifier + + + + + + erase_execute + + Opengento\Gdpr\Model\Action\Erase\ExecuteAction + Opengento\Gdpr\Model\Action\Erase\ExecuteNotifier + + + + + + erase_cancel + + Opengento\Gdpr\Model\Action\Erase\CancelAction + Opengento\Gdpr\Model\Action\Erase\CancelNotifier + + + + + + erase_create_execute + + Opengento\Gdpr\Model\Action\Erase\CreateAction + Opengento\Gdpr\Model\Action\Erase\ExecuteAction + + + + + + export_create + + Opengento\Gdpr\Model\Action\Export\CreateAction + + + + + + export_execute + + Opengento\Gdpr\Model\Action\Export\ExportAction + + + + + + export_create_or_execute + + Opengento\Gdpr\Model\Action\Export\CreateOrExportAction + + + @@ -79,17 +232,6 @@ - - - - Magento\Framework\EntityManager\AbstractModelHydrator - Magento\Framework\EntityManager\AbstractModelHydrator - Magento\Framework\EntityManager\AbstractModelHydrator - Magento\Framework\EntityManager\AbstractModelHydrator - Magento\Framework\EntityManager\AbstractModelHydrator - - - @@ -654,7 +796,7 @@ - Opengento\Gdpr\Model\Customer\Erase\ProcessorResolver\ProcessorResolverStrategy + Opengento\Gdpr\Model\Customer\Erase\ProcessorResolverFactory @@ -702,7 +844,7 @@ - Opengento\Gdpr\Model\Order\Erase\ProcessorResolver\ProcessorResolverStrategy + Opengento\Gdpr\Model\Order\Erase\ProcessorResolverFactory @@ -793,14 +935,6 @@ - - - - Opengento\Gdpr\Model\Customer\Export\ExportCustomer - Opengento\Gdpr\Model\Export\ExportPersonalData - - - @@ -811,14 +945,6 @@ - - - - Opengento\Gdpr\Model\Order\Export\ExportOrder - Opengento\Gdpr\Model\Export\ExportPersonalData - - - @@ -1424,8 +1550,229 @@ - - + + + Opengento\Gdpr\Model\Archive\Zip + + + + + Opengento\Gdpr\Model\Archive\MoveToZip + + + + + + + gdpr/notification/erasure/pending/customer/enabled + gdpr/notification/erasure/pending/customer/identity + gdpr/notification/erasure/pending/customer/copy_to + gdpr/notification/erasure/pending/customer/copy_method + gdpr/notification/erasure/pending/customer/template + + + + + + + Opengento\Gdpr\Model\Customer\Erase\Notifier\Pending\MailSender + + + + + + + gdpr/notification/erasure/succeeded/customer/enabled + gdpr/notification/erasure/succeeded/customer/identity + gdpr/notification/erasure/succeeded/customer/copy_to + gdpr/notification/erasure/succeeded/customer/copy_method + gdpr/notification/erasure/succeeded/customer/template + + + + + + + Opengento\Gdpr\Model\Customer\Erase\Notifier\Succeeded\MailSender + + + + + + + gdpr/notification/erasure/canceled/customer/enabled + gdpr/notification/erasure/canceled/customer/identity + gdpr/notification/erasure/canceled/customer/copy_to + gdpr/notification/erasure/canceled/customer/copy_method + gdpr/notification/erasure/canceled/customer/template + + + + + + + Opengento\Gdpr\Model\Customer\Erase\Notifier\Canceled\MailSender + + + + + + + + gdpr/notification/erasure/pending/order/enabled + gdpr/notification/erasure/pending/order/identity + gdpr/notification/erasure/pending/order/copy_to + gdpr/notification/erasure/pending/order/copy_method + gdpr/notification/erasure/pending/order/template + + + + + + + Opengento\Gdpr\Model\Order\Erase\Notifier\Pending\MailSender + + + + + + + gdpr/notification/erasure/succeeded/order/enabled + gdpr/notification/erasure/succeeded/order/identity + gdpr/notification/erasure/succeeded/order/copy_to + gdpr/notification/erasure/succeeded/order/copy_method + gdpr/notification/erasure/succeeded/order/template + + + + + + + Opengento\Gdpr\Model\Order\Erase\Notifier\Succeeded\MailSender + + + + + + + gdpr/notification/erasure/canceled/order/enabled + gdpr/notification/erasure/canceled/order/identity + gdpr/notification/erasure/canceled/order/copy_to + gdpr/notification/erasure/canceled/order/copy_method + gdpr/notification/erasure/canceled/order/template + + + + + + + Opengento\Gdpr\Model\Order\Erase\Notifier\Canceled\MailSender + + + + + + + + gdpr/notification/export/pending/customer/enabled + gdpr/notification/export/pending/customer/identity + gdpr/notification/export/pending/customer/copy_to + gdpr/notification/export/pending/customer/copy_method + gdpr/notification/export/pending/customer/template + + + + + + + Opengento\Gdpr\Model\Customer\Export\Notifier\Pending\MailSender + + + + + + + gdpr/notification/export/ready/customer/enabled + gdpr/notification/export/ready/customer/identity + gdpr/notification/export/ready/customer/copy_to + gdpr/notification/export/ready/customer/copy_method + gdpr/notification/export/ready/customer/template + + + + + + + Opengento\Gdpr\Model\Customer\Export\Notifier\Ready\MailSender + + + + + + + + gdpr/notification/export/pending/order/enabled + gdpr/notification/export/pending/order/identity + gdpr/notification/export/pending/order/copy_to + gdpr/notification/export/pending/order/copy_method + gdpr/notification/export/pending/order/template + + + + + + + Opengento\Gdpr\Model\Order\Export\Notifier\Pending\MailSender + + + + + + + gdpr/notification/export/ready/order/enabled + gdpr/notification/export/ready/order/identity + gdpr/notification/export/ready/order/copy_to + gdpr/notification/export/ready/order/copy_method + gdpr/notification/export/ready/order/template + + + + + + + Opengento\Gdpr\Model\Order\Export\Notifier\Ready\MailSender + + + + + + + opengento_gdpr_action_entity + Opengento\Gdpr\Model\ResourceModel\ActionEntity + + + + + + Opengento\Gdpr\Model\ResourceModel\ActionEntity\SearchResult + Opengento\Gdpr\Model\ResourceModel\ActionEntity\SearchResult + + + + + + + Magento\Framework\App\State\Proxy + Magento\Framework\Registry\Proxy + Opengento\Gdpr\Model\Action\EraseCreateExecuteAction + + + + + Magento\Framework\App\State\Proxy + Opengento\Gdpr\Model\Action\ExportCreateOrExecuteAction + + diff --git a/etc/email_templates.xml b/etc/email_templates.xml new file mode 100644 index 0000000..1c69ef5 --- /dev/null +++ b/etc/email_templates.xml @@ -0,0 +1,19 @@ + + + +