├── .github
├── CODE_OF_CONDUCT.md
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── coding-standard.yml
│ ├── mess-detector.yml
│ └── phpstan.yml
├── .gitignore
├── Api
├── ActionEntityRepositoryInterface.php
├── ActionInterface.php
├── Data
│ ├── ActionContextInterface.php
│ ├── ActionEntityInterface.php
│ ├── ActionEntitySearchResultsInterface.php
│ ├── ActionResultInterface.php
│ ├── EraseEntityInterface.php
│ ├── EraseEntitySearchResultsInterface.php
│ ├── ExportEntityInterface.php
│ └── ExportEntitySearchResultsInterface.php
├── EraseEntityCheckerInterface.php
├── EraseEntityManagementInterface.php
├── EraseEntityRepositoryInterface.php
├── EraseSalesInformationInterface.php
├── ExportEntityCheckerInterface.php
├── ExportEntityManagementInterface.php
└── ExportEntityRepositoryInterface.php
├── Block
└── Adminhtml
│ ├── Action
│ └── Edit
│ │ ├── BackButton.php
│ │ ├── ExecuteButton.php
│ │ └── ResetButton.php
│ ├── Config
│ └── Form
│ │ └── Field
│ │ ├── AttributesAnonymizers.php
│ │ ├── EraseComponentsProcessors.php
│ │ └── Select
│ │ └── OptionSourceSelect.php
│ ├── Customer
│ └── Edit
│ │ ├── EraseButton.php
│ │ └── ExportButton.php
│ └── Order
│ └── Edit
│ ├── EraseButton.php
│ └── ExportButton.php
├── Console
└── Command
│ ├── EraseCommand.php
│ └── ExportCommand.php
├── Controller
├── AbstractAction.php
├── AbstractGuest.php
├── AbstractPrivacy.php
├── Adminhtml
│ ├── AbstractAction.php
│ ├── Action
│ │ ├── Execute.php
│ │ ├── Index.php
│ │ ├── InlineEdit.php
│ │ ├── MassDelete.php
│ │ └── NewAction.php
│ ├── Guest
│ │ ├── Erase.php
│ │ └── Export.php
│ └── Privacy
│ │ ├── Erase.php
│ │ ├── Export.php
│ │ ├── MassErase.php
│ │ └── MassExport.php
├── Guest
│ ├── Download.php
│ ├── Erase.php
│ ├── Export.php
│ └── UndoErase.php
└── Privacy
│ ├── Download.php
│ ├── Erase.php
│ ├── ErasePost.php
│ ├── Export.php
│ ├── Settings.php
│ └── UndoErase.php
├── Cron
├── EraseEntity.php
├── EraseEntityScheduler.php
├── ExportEntity.php
└── ExportEntityExpired.php
├── LICENSE
├── Model
├── Action
│ ├── AbstractAction.php
│ ├── ActionComposite.php
│ ├── ActionFactory.php
│ ├── ArgumentReader.php
│ ├── Context.php
│ ├── ContextBuilder.php
│ ├── Erase
│ │ ├── ArgumentReader.php
│ │ ├── CancelAction.php
│ │ ├── CreateAction.php
│ │ ├── ExecuteAction.php
│ │ └── NotifierActionBundle.php
│ ├── Export
│ │ ├── ArgumentReader.php
│ │ ├── CreateAction.php
│ │ ├── CreateOrExportAction.php
│ │ ├── ExportAction.php
│ │ └── NotifierActionBundle.php
│ ├── PerformedBy
│ │ ├── AdminUser.php
│ │ ├── Console.php
│ │ ├── Customer.php
│ │ ├── Guest.php
│ │ └── NotEmptyStrategy.php
│ ├── PerformedByInterface.php
│ ├── Result.php
│ └── ResultBuilder.php
├── ActionEntity.php
├── ActionEntityBuilder.php
├── ActionEntityRepository.php
├── Archive
│ ├── ArchiveManager.php
│ └── Zip.php
├── Config.php
├── Config
│ ├── Backend
│ │ └── Export.php
│ ├── PrivacyMessage.php
│ └── Source
│ │ ├── ActionStates.php
│ │ ├── EraseComponents.php
│ │ ├── OrderPendingStates.php
│ │ ├── VirtualArrayArgumentList.php
│ │ ├── VirtualCustomerAttributes.php
│ │ └── VirtualEntityAttributes.php
├── Customer
│ ├── Anonymize
│ │ └── Processor
│ │ │ ├── CustomerAddressDataProcessor.php
│ │ │ ├── CustomerDataProcessor.php
│ │ │ ├── OrderDataProcessor.php
│ │ │ ├── QuoteDataProcessor.php
│ │ │ └── SubscriberDataProcessor.php
│ ├── CustomerChecker.php
│ ├── Delete
│ │ └── Processor
│ │ │ ├── CustomerAddressDataProcessor.php
│ │ │ ├── CustomerDataProcessor.php
│ │ │ ├── OrderDataProcessor.php
│ │ │ ├── QuoteDataProcessor.php
│ │ │ └── SubscriberDataProcessor.php
│ ├── Erase
│ │ └── Notifier.php
│ ├── Export
│ │ ├── Notifier.php
│ │ └── Processor
│ │ │ ├── CustomerAddressDataProcessor.php
│ │ │ ├── CustomerDataProcessor.php
│ │ │ ├── OrderDataProcessor.php
│ │ │ ├── QuoteDataProcessor.php
│ │ │ └── SubscriberDataProcessor.php
│ ├── Notifier
│ │ ├── MailSender.php
│ │ └── SenderInterface.php
│ ├── OrigDataRegistry.php
│ └── SourceProvider
│ │ └── IdleFilterModifier.php
├── Entity
│ ├── DataCollector.php
│ ├── DataCollectorGeneric.php
│ ├── DataCollectorInterface.php
│ ├── Document.php
│ ├── DocumentInterface.php
│ ├── EntityCheckerFactory.php
│ ├── EntityCheckerInterface.php
│ ├── EntityIterator.php
│ ├── EntityIteratorInterface.php
│ ├── EntityTypeList.php
│ ├── EntityTypeResolver.php
│ ├── EntityValue
│ │ ├── CustomAttributesProcessor.php
│ │ ├── ExtensibleDataProcessor.php
│ │ └── StrategyProcessor.php
│ ├── EntityValueProcessorInterface.php
│ ├── Metadata.php
│ ├── MetadataInterface.php
│ ├── SourceProvider
│ │ ├── FilterModifier.php
│ │ ├── ModifierComposite.php
│ │ ├── ModifierFactory.php
│ │ ├── ModifierInterface.php
│ │ └── NotErasedFilterModifier.php
│ └── SourceProviderFactory.php
├── Erase
│ ├── EraseEntityScheduler.php
│ ├── EraseSalesInformation.php
│ ├── NotifierInterface.php
│ └── SecureEraseEntityManagement.php
├── EraseEntity.php
├── EraseEntityChecker.php
├── EraseEntityManagement.php
├── EraseEntityRepository.php
├── Export
│ ├── ExportEntityData.php
│ ├── ExportToFile.php
│ └── NotifierInterface.php
├── ExportEntity.php
├── ExportEntityChecker.php
├── ExportEntityManagement.php
├── ExportEntityRepository.php
├── Newsletter
│ └── Subscriber.php
├── Notifier
│ └── AbstractMailSender.php
├── Order
│ ├── Anonymize
│ │ └── Processor
│ │ │ ├── OrderDataProcessor.php
│ │ │ ├── QuoteDataProcessor.php
│ │ │ └── SubscriberDataProcessor.php
│ ├── Delete
│ │ └── Processor
│ │ │ ├── OrderDataProcessor.php
│ │ │ ├── QuoteDataProcessor.php
│ │ │ └── SubscriberDataProcessor.php
│ ├── Erase
│ │ └── Notifier.php
│ ├── Export
│ │ ├── Notifier.php
│ │ └── Processor
│ │ │ ├── AbstractDataProcessor.php
│ │ │ ├── OrderDataProcessor.php
│ │ │ ├── QuoteDataProcessor.php
│ │ │ └── SubscriberDataProcessor.php
│ ├── Notifier
│ │ ├── MailSender.php
│ │ └── SenderInterface.php
│ ├── OrderChecker.php
│ └── SourceProvider
│ │ └── GuestFilterModifier.php
└── ResourceModel
│ ├── ActionEntity.php
│ ├── ActionEntity
│ ├── Collection.php
│ ├── Validator.php
│ └── Validator
│ │ └── StateValidator.php
│ ├── EraseEntity.php
│ ├── EraseEntity
│ └── Collection.php
│ ├── ExportEntity.php
│ └── ExportEntity
│ └── Collection.php
├── Observer
├── DeleteExport.php
└── InvalidateExport.php
├── README.md
├── Service
├── Anonymize
│ ├── Anonymizer
│ │ ├── AlphaLower.php
│ │ ├── AlphaNum.php
│ │ ├── AlphaUpper.php
│ │ ├── Anonymous.php
│ │ ├── Date.php
│ │ ├── Email.php
│ │ ├── Entity.php
│ │ ├── NullValue.php
│ │ ├── Number.php
│ │ ├── Phone.php
│ │ └── Street.php
│ ├── AnonymizerFactory.php
│ ├── AnonymizerInterface.php
│ ├── Metadata.php
│ ├── MetadataInterface.php
│ └── Processor
│ │ └── Entity
│ │ └── EntityValue
│ │ ├── Processor.php
│ │ └── SmartProcessor.php
├── Erase
│ ├── Metadata.php
│ ├── MetadataInterface.php
│ ├── Processor
│ │ └── EraseProcessor.php
│ ├── ProcessorFactory.php
│ ├── ProcessorInterface.php
│ ├── ProcessorResolver
│ │ ├── ProcessorResolver.php
│ │ └── ProcessorResolverStrategy.php
│ ├── ProcessorResolverFactory.php
│ └── ProcessorResolverInterface.php
└── Export
│ ├── Processor
│ ├── AbstractDataProcessor.php
│ ├── CompositeProcessor.php
│ └── Entity
│ │ └── EntityValue
│ │ ├── DataProcessor.php
│ │ └── EntityProcessor.php
│ ├── ProcessorFactory.php
│ ├── ProcessorInterface.php
│ ├── Renderer
│ ├── AbstractRenderer.php
│ ├── CsvRenderer.php
│ ├── HtmlRenderer.php
│ ├── HtmlRenderer
│ │ ├── LayoutInitiator.php
│ │ ├── LayoutInitiatorInterface.php
│ │ └── View
│ │ │ └── Renderer.php
│ ├── JsonRenderer.php
│ ├── PdfRenderer.php
│ └── XmlRenderer.php
│ ├── RendererFactory.php
│ └── RendererInterface.php
├── TODO.md
├── ViewModel
├── Cookie
│ └── NoticeDataProvider.php
└── Customer
│ ├── Guest
│ ├── EraseDataProvider.php
│ └── ExportDataProvider.php
│ └── Privacy
│ ├── EraseCustomerDataProvider.php
│ ├── EraseDataProvider.php
│ ├── ExportCustomerDataProvider.php
│ ├── ExportDataProvider.php
│ └── SettingsDataProvider.php
├── composer.json
├── etc
├── acl.xml
├── adminhtml
│ ├── di.xml
│ ├── menu.xml
│ ├── routes.xml
│ ├── system.xml
│ └── system
│ │ ├── action.xml
│ │ ├── cookie.xml
│ │ ├── erasure.xml
│ │ ├── export.xml
│ │ ├── general.xml
│ │ └── notification.xml
├── config.xml
├── cron_groups.xml
├── crontab.xml
├── db_schema.xml
├── db_schema_whitelist.json
├── di.xml
├── email_templates.xml
├── events.xml
├── frontend
│ ├── di.xml
│ └── routes.xml
└── module.xml
├── i18n
├── bg_BG.csv
├── da_DK.csv
├── de_DE.csv
├── en_US.csv
├── fr_FR.csv
├── it_IT.csv
├── nl_NL.csv
├── pl_PL.csv
└── th_TH.csv
├── registration.php
└── view
├── adminhtml
├── layout
│ ├── gdpr_action_index.xml
│ ├── gdpr_action_new.xml
│ └── sales_order_view.xml
└── ui_component
│ ├── customer_form.xml
│ ├── customer_listing.xml
│ ├── gdpr_action_form.xml
│ └── gdpr_action_listing.xml
├── base
├── layout
│ ├── customer_privacy_export_personal_data.xml
│ └── customer_privacy_export_personal_data_renderers.xml
├── layouts.xml
├── page_layout
│ └── customer_privacy_export.xml
├── templates
│ ├── export
│ │ ├── renderer
│ │ │ └── default.phtml
│ │ └── result.phtml
│ └── root.phtml
└── web
│ └── css
│ └── export.less
└── frontend
├── email
├── erase_canceled.html
├── erase_canceled_guest.html
├── erase_pending.html
├── erase_pending_guest.html
├── erase_succeeded.html
├── erase_succeeded_guest.html
├── export_pending.html
├── export_pending_guest.html
├── export_ready.html
└── export_ready_guest.html
├── layout
├── customer_account.xml
├── customer_privacy_erase.xml
├── customer_privacy_settings.xml
├── default.xml
└── sales_guest_view.xml
├── templates
├── account
│ ├── erase.phtml
│ ├── privacy
│ │ ├── erase.phtml
│ │ └── export.phtml
│ └── settings.phtml
├── cookie
│ └── notices.phtml
└── order
│ └── info
│ ├── buttons
│ ├── download.phtml
│ ├── erase.phtml
│ └── export.phtml
│ ├── erase.phtml
│ └── export.phtml
└── web
└── css
└── source
└── _module.less
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | #github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | #patreon: # Replace with a single Patreon username
5 | #open_collective: # Replace with a single Open Collective username
6 | #ko_fi: # Replace with a single Ko-fi username
7 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | #community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | #liberapay: # Replace with a single Liberapay username
10 | #issuehunt: # Replace with a single IssueHunt username
11 | #otechie: # Replace with a single Otechie username
12 | custom: ['https://www.helloasso.com/associations/opengento/formulaires/1']
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: "[BUG]"
5 | labels: bug
6 | assignees: thomas-kl1
7 |
8 | ---
9 |
10 | ## Description
11 | A clear and concise description of what the bug is.
12 |
13 | ## Prerequisites
14 |
15 | **PHP Version:**
16 | - [e.g. 7.2.19]
17 |
18 | **Magento Version:**
19 | - [e.g. 2.3.2]
20 |
21 | **Module Version:**
22 | - [e.g. 1.0.0]
23 |
24 | **Desktop (if applicable):**
25 | - OS: [e.g. iOS]
26 | - Browser [e.g. chrome, safari]
27 | - Version [e.g. 22]
28 |
29 | **Smartphone (if applicable):**
30 | - Device: [e.g. iPhone6]
31 | - OS: [e.g. iOS8.1]
32 | - Browser [e.g. stock browser, safari]
33 | - Version [e.g. 22]
34 |
35 | ## Issue Details
36 |
37 | **Steps to reproduce the behavior**
38 | 1. Go to '...'
39 | 2. Click on '....'
40 | 3. Scroll down to '....'
41 | 4. See error
42 |
43 | **Expected behavior**
44 | A clear and concise description of what you expected to happen.
45 |
46 | **Screenshots**
47 | If applicable, add screenshots to help explain your problem.
48 |
49 | **Additional context**
50 | Add any other context about the problem here.
51 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: "[ENHANCEMENT]"
5 | labels: enhancement
6 | assignees: thomas-kl1
7 |
8 | ---
9 |
10 | ## Description
11 |
12 | - [ ] It's related to an existing issue: #[issueId]
13 |
14 | - [ ] It requires major modifications.
15 |
16 | Priority of the change:
17 | - [ ] High
18 | - [ ] Medium
19 | - [ ] Low
20 |
21 | **Which problem the feature would fix?**
22 | A clear and concise description of what the problem is.
23 |
24 | **Describe the solution as simple as possible**
25 | A clear and concise description of how it should works.
26 |
27 | **List the alternative solutions**
28 | Curated list of the alternative solutions.
29 |
30 | **Additional context**
31 | Add any other context or screenshots about the feature request here.
32 |
33 | ## Contributing
34 |
35 | - [ ] Would you want to contribute and to be assigned to this enhancement?
36 |
--------------------------------------------------------------------------------
/.github/workflows/coding-standard.yml:
--------------------------------------------------------------------------------
1 | name: M2 Coding Standard
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | static:
6 | name: M2 Coding Standard
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: extdn/github-actions-m2/magento-coding-standard@master
11 |
--------------------------------------------------------------------------------
/.github/workflows/mess-detector.yml:
--------------------------------------------------------------------------------
1 | name: M2 Mess Detector
2 | on: [push, pull_request]
3 |
4 | jobs:
5 | phpmd:
6 | name: M2 Mess Detector
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: extdn/github-actions-m2/magento-mess-detector@master
11 |
--------------------------------------------------------------------------------
/.github/workflows/phpstan.yml:
--------------------------------------------------------------------------------
1 | name: M2 PHPStan
2 | on: [push, pull_request, workflow_dispatch]
3 |
4 | jobs:
5 | phpstan:
6 | name: M2 PHPStan
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | - uses: extdn/github-actions-m2/magento-phpstan@master
11 | with:
12 | composer_name: opengento/module-gdpr
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
--------------------------------------------------------------------------------
/Api/ActionInterface.php:
--------------------------------------------------------------------------------
1 | urlBuilder = $urlBuilder;
25 | }
26 |
27 | public function getButtonData(): array
28 | {
29 | return [
30 | 'label' => new Phrase('Back'),
31 | 'on_click' => 'location.href = "' . $this->urlBuilder->getUrl('*/*/') . '";',
32 | 'class' => 'back',
33 | 'sort_order' => 10,
34 | ];
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Action/Edit/ExecuteButton.php:
--------------------------------------------------------------------------------
1 | new Phrase('Execute Action'),
19 | 'class' => 'primary',
20 | 'data_attribute' => [
21 | 'mage-init' => ['button' => ['event' => 'save']],
22 | 'form-role' => 'save',
23 | ],
24 | 'on_click' => 'location.reload();',
25 | 'sort_order' => 30,
26 | 'aclResource' => 'Opengento_Gdpr::gdpr_actions_execute',
27 | ];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Action/Edit/ResetButton.php:
--------------------------------------------------------------------------------
1 | new Phrase('Reset'),
19 | 'class' => 'reset',
20 | 'on_click' => 'location.reload();',
21 | 'sort_order' => 20,
22 | ];
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Config/Form/Field/Select/OptionSourceSelect.php:
--------------------------------------------------------------------------------
1 | optionSource = $optionSource;
27 | parent::__construct($context, $data);
28 | }
29 |
30 | public function setInputName(string $inputName): self
31 | {
32 | return $this->setData('name', $inputName);
33 | }
34 |
35 | protected function _toHtml(): string
36 | {
37 | if (!$this->getOptions()) {
38 | $this->setOptions($this->optionSource->toOptionArray());
39 | }
40 |
41 | return parent::_toHtml();
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Customer/Edit/ExportButton.php:
--------------------------------------------------------------------------------
1 | config = $config;
27 | parent::__construct($context, $registry);
28 | }
29 |
30 | public function getButtonData(): array
31 | {
32 | $customerId = $this->getCustomerId();
33 | $buttonData = [];
34 |
35 | if ($customerId && $this->config->isModuleEnabled()) {
36 | $buttonData = [
37 | 'label' => new Phrase('Export Personal Data'),
38 | 'class' => 'Export',
39 | 'id' => 'opengento-gdpr-customer-edit-export-button',
40 | 'on_click' => 'deleteConfirm("' . new Phrase('Are you sure you want to do this?') . '", '
41 | . '"' . $this->getUrl('customer/privacy/export', ['id' => $customerId]) . '", {"data": {}})',
42 | 'sort_order' => 15,
43 | 'aclResource' => 'Opengento_Gdpr::customer_export',
44 | ];
45 | }
46 |
47 | return $buttonData;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Block/Adminhtml/Order/Edit/ExportButton.php:
--------------------------------------------------------------------------------
1 | getLayout()->getBlock('sales_order_edit');
27 | $orderId = (int) $orderView->getOrderId();
28 |
29 | if ($this->_authorization->isAllowed('Opengento_Gdpr::order_export')) {
30 | $orderView->addButton(
31 | 'opengento-gdpr-order-view-export-button',
32 | [
33 | 'label' => new Phrase('Export Personal Data'),
34 | 'class' => 'export',
35 | 'onclick' => 'setLocation("' . $this->getUrl('sales/guest/export', ['id' => $orderId]) . '")',
36 | ]
37 | );
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Controller/AbstractGuest.php:
--------------------------------------------------------------------------------
1 | orderLoader = $orderLoader;
37 | $this->registry = $registry;
38 | parent::__construct($request, $resultFactory, $messageManager, $config);
39 | }
40 |
41 | public function execute()
42 | {
43 | $result = $this->orderLoader->load($this->request);
44 |
45 | return $result instanceof ResultInterface ? $result : parent::execute();
46 | }
47 |
48 | protected function currentOrder(): OrderInterface
49 | {
50 | return $this->registry->registry('current_order');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/AbstractAction.php:
--------------------------------------------------------------------------------
1 | config = $config;
28 | parent::__construct($context);
29 | }
30 |
31 | public function execute()
32 | {
33 | if ($this->isAllowed()) {
34 | return $this->executeAction();
35 | }
36 |
37 | return $this->forwardNoRoute();
38 | }
39 |
40 | /**
41 | * Execute action based on request and return result
42 | *
43 | * @return ResultInterface|ResponseInterface
44 | * @throws NotFoundException
45 | */
46 | abstract protected function executeAction();
47 |
48 | protected function isAllowed(): bool
49 | {
50 | return $this->config->isModuleEnabled();
51 | }
52 |
53 | protected function forwardNoRoute(): ResultInterface
54 | {
55 | /** @var Forward $resultForward */
56 | $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD);
57 |
58 | return $resultForward->forward('no_route');
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Action/Index.php:
--------------------------------------------------------------------------------
1 | resultFactory->create(ResultFactory::TYPE_PAGE);
24 | $resultPage->setActiveMenu('Opengento_Gdpr::gdpr_actions');
25 | $resultPage->getConfig()->getTitle()->set(new Phrase('View Actions'));
26 | $resultPage->addBreadcrumb(new Phrase('GDPR'), new Phrase('GDPR'));
27 | $resultPage->addBreadcrumb(new Phrase('View Actions'), new Phrase('View Actions'));
28 |
29 | return $resultPage;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Controller/Adminhtml/Action/NewAction.php:
--------------------------------------------------------------------------------
1 | resultFactory->create(ResultFactory::TYPE_PAGE);
24 | $resultPage->setActiveMenu('Opengento_Gdpr::gdpr_actions');
25 | $resultPage->getConfig()->getTitle()->set(new Phrase('Execute New Action'));
26 | $resultPage->addBreadcrumb(new Phrase('GDPR'), new Phrase('GDPR'));
27 | $resultPage->addBreadcrumb(new Phrase('Execute New Action'), new Phrase('Execute New Action'));
28 |
29 | return $resultPage;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Controller/Privacy/Settings.php:
--------------------------------------------------------------------------------
1 | resultFactory->create(ResultFactory::TYPE_PAGE);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) OpenGento
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Model/Action/AbstractAction.php:
--------------------------------------------------------------------------------
1 | resultBuilder = $resultBuilder;
28 | }
29 |
30 | protected function createActionResult(
31 | array $result = [],
32 | string $message = self::DEFAULT_MESSAGE
33 | ): ActionResultInterface {
34 | $this->resultBuilder->setState(ActionEntityInterface::STATE_SUCCEEDED);
35 | $this->resultBuilder->setPerformedAt(new DateTime());
36 | $this->resultBuilder->setMessage($message);
37 | $this->resultBuilder->setResult($result);
38 |
39 | return $this->resultBuilder->create();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Model/Action/ActionFactory.php:
--------------------------------------------------------------------------------
1 | actions = $actions;
37 | $this->objectManager = $objectManager;
38 | $this->instances = [];
39 | }
40 |
41 | public function get(string $type): ActionInterface
42 | {
43 | if (!isset($this->instances[$type])) {
44 | if (!isset($this->actions[$type])) {
45 | throw new InvalidArgumentException(sprintf('Unknown action for type "%s".', $type));
46 | }
47 |
48 | $this->instances[$type] = $this->objectManager->create($this->actions[$type], ['type' => $type]);
49 | }
50 |
51 | return $this->instances[$type];
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Model/Action/ArgumentReader.php:
--------------------------------------------------------------------------------
1 | getParameters()[self::ENTITY_TYPE] ?? null;
20 | }
21 |
22 | public static function getEntityId(ActionContextInterface $actionContext): ?int
23 | {
24 | return $actionContext->getParameters()[self::ENTITY_ID] ?? null;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Model/Action/Context.php:
--------------------------------------------------------------------------------
1 | performedFrom = $performedFrom;
26 | $this->performedBy = $performedBy;
27 | $this->parameters = $parameters;
28 | }
29 |
30 | public function getPerformedFrom(): string
31 | {
32 | return $this->performedFrom;
33 | }
34 |
35 | public function getPerformedBy(): string
36 | {
37 | return $this->performedBy;
38 | }
39 |
40 | public function getParameters(): array
41 | {
42 | return $this->parameters;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Model/Action/Erase/ArgumentReader.php:
--------------------------------------------------------------------------------
1 | getParameters()[self::ERASE_ENTITY] ?? null;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Model/Action/Erase/ExecuteAction.php:
--------------------------------------------------------------------------------
1 | eraseManagement = $eraseManagement;
26 | parent::__construct($resultBuilder);
27 | }
28 |
29 | public function execute(ActionContextInterface $actionContext): ActionResultInterface
30 | {
31 | $eraseEntity = ArgumentReader::getEntity($actionContext);
32 |
33 | if ($eraseEntity === null) {
34 | throw InputException::requiredField('entity');
35 | }
36 |
37 | return $this->createActionResult(
38 | [ArgumentReader::ERASE_ENTITY => $this->eraseManagement->process($eraseEntity)]
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Model/Action/Export/ArgumentReader.php:
--------------------------------------------------------------------------------
1 | getParameters()[self::EXPORT_ENTITY] ?? null;
21 | }
22 |
23 | public static function getFileName(ActionContextInterface $actionContext): ?string
24 | {
25 | return $actionContext->getParameters()[self::EXPORT_FILE_NAME] ?? null;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Model/Action/PerformedBy/AdminUser.php:
--------------------------------------------------------------------------------
1 | authSession = $authSession;
29 | $this->attributeName = $attributeName;
30 | }
31 |
32 | public function get(): string
33 | {
34 | return self::PERFORMED_BY . $this->resolveUserName();
35 | }
36 |
37 | private function resolveUserName(): string
38 | {
39 | return $this->authSession->getUser() ? $this->authSession->getUser()->getData($this->attributeName) : 'Unknown';
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Model/Action/PerformedBy/Console.php:
--------------------------------------------------------------------------------
1 | customerSession = $customerSession;
28 | $this->attributeName = $attributeName;
29 | }
30 |
31 | public function get(): string
32 | {
33 | return $this->customerSession->isLoggedIn()
34 | ? $this->customerSession->getCustomer()->getData($this->attributeName)
35 | : '';
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Model/Action/PerformedBy/Guest.php:
--------------------------------------------------------------------------------
1 | coreRegistry = $coreRegistry;
26 | $this->attributeName = $attributeName;
27 | }
28 |
29 | public function get(): string
30 | {
31 | $order = $this->coreRegistry->registry('current_order');
32 |
33 | return $order && $order instanceof Order ? $order->getData($this->attributeName) : '';
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Model/Action/PerformedBy/NotEmptyStrategy.php:
--------------------------------------------------------------------------------
1 | performedByList = $performedByList;
25 | }
26 |
27 | public function get(): string
28 | {
29 | $performer = self::PERFORMED_BY;
30 |
31 | foreach ($this->performedByList as $performedBy) {
32 | $performer = $performedBy->get() ?: $performer;
33 | }
34 |
35 | return $performer;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Model/Action/PerformedByInterface.php:
--------------------------------------------------------------------------------
1 | performedAt = $performedAt;
33 | $this->state = $state;
34 | $this->message = $message;
35 | $this->result = $result;
36 | }
37 |
38 | public function getPerformedAt(): DateTime
39 | {
40 | return $this->performedAt;
41 | }
42 |
43 | public function getState(): string
44 | {
45 | return $this->state;
46 | }
47 |
48 | public function getMessage(): string
49 | {
50 | return $this->message;
51 | }
52 |
53 | public function getResult(): array
54 | {
55 | return $this->result;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Model/Action/ResultBuilder.php:
--------------------------------------------------------------------------------
1 | actionResultFactory = $actionResultFactory;
30 | $this->data = [];
31 | }
32 |
33 | public function setPerformedAt(DateTime $performedAt): ResultBuilder
34 | {
35 | $this->data['performedAt'] = $performedAt;
36 |
37 | return $this;
38 | }
39 |
40 | public function setState(string $state): ResultBuilder
41 | {
42 | $this->data['state'] = $state;
43 |
44 | return $this;
45 | }
46 |
47 | public function setMessage(string $message): ResultBuilder
48 | {
49 | $this->data['message'] = $message;
50 |
51 | return $this;
52 | }
53 |
54 | public function setResult(array $result): ResultBuilder
55 | {
56 | $this->data['result'] = $result;
57 |
58 | return $this;
59 | }
60 |
61 | public function create(): ActionResultInterface
62 | {
63 | /** @var ActionResultInterface $result */
64 | $result = $this->actionResultFactory->create($this->data);
65 | $this->data = [];
66 |
67 | return $result;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Model/Archive/Zip.php:
--------------------------------------------------------------------------------
1 | filesystem = $filesystem;
34 | $this->zip = $zip;
35 | }
36 |
37 | public function pack($source, $destination): string
38 | {
39 | $directoryRead = $this->filesystem->getDirectoryReadByPath($source);
40 |
41 | $zip = new ZipArchive();
42 | $zip->open($destination, ZipArchive::CREATE);
43 | $zip->addFile($source, $directoryRead->isDirectory($source) ? '' : basename($source));
44 | $zip->close();
45 |
46 | return $destination;
47 | }
48 |
49 | public function unpack($source, $destination): string
50 | {
51 | return $this->zip->unpack($source, $destination);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/Model/Config/Source/OrderPendingStates.php:
--------------------------------------------------------------------------------
1 | collectionFactory = $collectionFactory;
26 | }
27 |
28 | public function toOptionArray(): array
29 | {
30 | return $this->options ??= $this->collectionFactory->create()->joinStates()->toOptionArray();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Model/Config/Source/VirtualCustomerAttributes.php:
--------------------------------------------------------------------------------
1 | metadata = $metadata;
24 | $this->options = [];
25 | }
26 |
27 | public function toOptionArray(): array
28 | {
29 | if (!$this->options) {
30 | try {
31 | $attributes = $this->metadata->getAllAttributesMetadata();
32 | } catch (LocalizedException $e) {
33 | $attributes = [];
34 | }
35 |
36 | foreach ($attributes as $attribute) {
37 | $this->options[] = [
38 | 'value' => $attribute->getAttributeCode(),
39 | 'label' => $attribute->getFrontendLabel(),
40 | ];
41 | }
42 | }
43 |
44 | return $this->options;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Model/Config/Source/VirtualEntityAttributes.php:
--------------------------------------------------------------------------------
1 | attributeProvider = $attributeProvider;
35 | $this->entityType = $entityType;
36 | $this->options = [];
37 | }
38 |
39 | public function toOptionArray(): array
40 | {
41 | if (!$this->options) {
42 | foreach (array_keys($this->attributeProvider->getAttributes($this->entityType)) as $attribute) {
43 | $this->options[] = ['value' => $attribute, 'label' => $attribute];
44 | }
45 | }
46 |
47 | return $this->options;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Model/Customer/Anonymize/Processor/CustomerAddressDataProcessor.php:
--------------------------------------------------------------------------------
1 | anonymizer = $anonymizer;
33 | $this->addressRepository = $addressRepository;
34 | $this->criteriaBuilder = $criteriaBuilder;
35 | }
36 |
37 | /**
38 | * @inheritdoc
39 | * @throws LocalizedException
40 | */
41 | public function execute(int $customerId): bool
42 | {
43 | $this->criteriaBuilder->addFilter('parent_id', $customerId);
44 | $addressList = $this->addressRepository->getList($this->criteriaBuilder->create());
45 |
46 | foreach ($addressList->getItems() as $address) {
47 | $this->addressRepository->save($this->anonymizer->anonymize($address));
48 | }
49 |
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Model/Customer/Anonymize/Processor/SubscriberDataProcessor.php:
--------------------------------------------------------------------------------
1 | anonymizer = $anonymizer;
31 | $this->subscriberFactory = $subscriberFactory;
32 | $this->subscriberResource = $subscriberResource;
33 | }
34 |
35 | /**
36 | * @inheritdoc
37 | * @throws Exception
38 | */
39 | public function execute(int $customerId): bool
40 | {
41 | /** @var Subscriber $subscriber */
42 | $subscriber = $this->subscriberFactory->create();
43 | $subscriber->loadByCustomerId($customerId);
44 | $this->anonymizer->anonymize($subscriber);
45 | $this->subscriberResource->save($subscriber->getRealSubscriber());
46 |
47 | return true;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Model/Customer/CustomerChecker.php:
--------------------------------------------------------------------------------
1 | orderRepository = $orderRepository;
35 | $this->criteriaBuilder = $criteriaBuilder;
36 | $this->config = $config;
37 | $this->cache = [];
38 | }
39 |
40 | public function canErase(int $customerId): bool
41 | {
42 | if (!isset($this->cache[$customerId])) {
43 | $this->criteriaBuilder->addFilter(OrderInterface::STATE, $this->config->getAllowedStatesToErase(), 'nin');
44 | $this->criteriaBuilder->addFilter(OrderInterface::CUSTOMER_ID, $customerId);
45 | $orderList = $this->orderRepository->getList($this->criteriaBuilder->create());
46 |
47 | $this->cache[$customerId] = !$orderList->getTotalCount();
48 | }
49 |
50 | return $this->cache[$customerId];
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Model/Customer/Delete/Processor/CustomerAddressDataProcessor.php:
--------------------------------------------------------------------------------
1 | addressRepository = $addressRepository;
29 | $this->criteriaBuilder = $criteriaBuilder;
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws LocalizedException
35 | */
36 | public function execute(int $customerId): bool
37 | {
38 | $this->criteriaBuilder->addFilter('parent_id', $customerId);
39 | $addressList = $this->addressRepository->getList($this->criteriaBuilder->create());
40 |
41 | foreach ($addressList->getItems() as $address) {
42 | $this->addressRepository->delete($address);
43 | }
44 |
45 | return true;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Model/Customer/Delete/Processor/CustomerDataProcessor.php:
--------------------------------------------------------------------------------
1 | customerRepository = $customerRepository;
33 | $this->sessionCleaner = $sessionCleaner;
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | * @throws LocalizedException
39 | */
40 | public function execute(int $customerId): bool
41 | {
42 | $this->sessionCleaner->clearFor($customerId);
43 |
44 | try {
45 | $this->customerRepository->deleteById($customerId);
46 | } catch (NoSuchEntityException $e) {
47 | /** Silence is golden */
48 | }
49 |
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Model/Customer/Delete/Processor/QuoteDataProcessor.php:
--------------------------------------------------------------------------------
1 | quoteRepository = $quoteRepository;
25 | $this->criteriaBuilder = $criteriaBuilder;
26 | }
27 |
28 | public function execute(int $customerId): bool
29 | {
30 | $this->criteriaBuilder->addFilter('customer_id', $customerId);
31 | $quoteList = $this->quoteRepository->getList($this->criteriaBuilder->create());
32 |
33 | foreach ($quoteList->getItems() as $quote) {
34 | $this->quoteRepository->delete($quote);
35 | }
36 |
37 | return true;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Model/Customer/Delete/Processor/SubscriberDataProcessor.php:
--------------------------------------------------------------------------------
1 | subscriberFactory = $subscriberFactory;
27 | $this->subscriberResource = $subscriberResource;
28 | }
29 |
30 | /**
31 | * @inheritdoc
32 | * @throws Exception
33 | */
34 | public function execute(int $customerId): bool
35 | {
36 | /** @var Subscriber $subscriber */
37 | $subscriber = $this->subscriberFactory->create();
38 | $subscriber->loadByCustomerId($customerId);
39 | $this->subscriberResource->delete($subscriber);
40 |
41 | return true;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Model/Customer/Export/Notifier.php:
--------------------------------------------------------------------------------
1 | senders = $senders;
32 | $this->customerRepository = $customerRepository;
33 | $this->logger = $logger;
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | * @throws LocalizedException
39 | */
40 | public function notify(ExportEntityInterface $exportEntity): void
41 | {
42 | $customer = $this->customerRepository->getById($exportEntity->getEntityId());
43 |
44 | foreach ($this->senders as $sender) {
45 | try {
46 | $sender->send($customer);
47 | } catch (LocalizedException $e) {
48 | $this->logger->error($e->getLogMessage(), $e->getTrace());
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Model/Customer/Export/Processor/CustomerDataProcessor.php:
--------------------------------------------------------------------------------
1 | customerRepository = $customerRepository;
28 | parent::__construct($dataCollector);
29 | }
30 |
31 | /**
32 | * @inheritdoc
33 | * @throws NoSuchEntityException
34 | * @throws LocalizedException
35 | */
36 | public function execute(int $customerId, array $data): array
37 | {
38 | $data['customer'] = $this->collectData($this->customerRepository->getById($customerId));
39 |
40 | return $data;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Model/Customer/Export/Processor/SubscriberDataProcessor.php:
--------------------------------------------------------------------------------
1 | subscriberFactory = $subscriberFactory;
24 | parent::__construct($dataCollector);
25 | }
26 |
27 | public function execute(int $customerId, array $data): array
28 | {
29 | /** @var Subscriber $subscriber */
30 | $subscriber = $this->subscriberFactory->create();
31 | $subscriber->loadByCustomerId($customerId);
32 | $data['subscriber'] = $this->collectData($subscriber);
33 |
34 | return $data;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Model/Customer/Notifier/SenderInterface.php:
--------------------------------------------------------------------------------
1 | customers[$customerId] ?? null;
22 | }
23 |
24 | public function set(CustomerInterface $customer): void
25 | {
26 | $this->customers[(int) $customer->getId()] = $customer;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Model/Entity/DataCollector.php:
--------------------------------------------------------------------------------
1 | entityIterator = $entityIterator;
27 | $this->document = $document;
28 | }
29 |
30 | public function collect(object $entity): array
31 | {
32 | $this->entityIterator->iterate($entity);
33 | $data = $this->document->getData();
34 | $this->document->setData([]);
35 |
36 | return $data;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Model/Entity/DataCollectorGeneric.php:
--------------------------------------------------------------------------------
1 | typeResolver = $typeResolver;
29 | $this->dataCollectors = $dataCollectors;
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws Exception
35 | */
36 | public function collect(object $entity): array
37 | {
38 | $entityType = $this->typeResolver->resolve($entity);
39 |
40 | if (!isset($this->dataCollectors[$entityType])) {
41 | throw new LogicException(
42 | sprintf('There is no registered data collector for the entity type "%s".', $entityType)
43 | );
44 | }
45 |
46 | return $this->dataCollectors[$entityType]->collect($entity);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Model/Entity/DataCollectorInterface.php:
--------------------------------------------------------------------------------
1 | data = $data;
17 | }
18 |
19 | public function setData(array $data): void
20 | {
21 | $this->data = $data;
22 | }
23 |
24 | public function addData(string $key, $value): void
25 | {
26 | $this->data[$key] = $value;
27 | }
28 |
29 | public function getData(): array
30 | {
31 | return $this->data;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Model/Entity/DocumentInterface.php:
--------------------------------------------------------------------------------
1 | checkers = $checkers;
35 | $this->objectManager = $objectManager;
36 | }
37 |
38 | public function get(string $entityType): EntityCheckerInterface
39 | {
40 | if (!isset($this->checkers[$entityType])) {
41 | throw new InvalidArgumentException(sprintf('Unknown checker for entity type "%s".', $entityType));
42 | }
43 |
44 | return $this->objectManager->get($this->checkers[$entityType]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Model/Entity/EntityCheckerInterface.php:
--------------------------------------------------------------------------------
1 | hydratorPool = $hydratorPool;
28 | $this->typeResolver = $typeResolver;
29 | $this->processor = $processor;
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws Exception
35 | */
36 | public function iterate(object $entity): void
37 | {
38 | $values = $this->hydratorPool->getHydrator($this->typeResolver->resolve($entity))->extract($entity);
39 |
40 | foreach ($values as $key => $value) {
41 | $this->processor->process($key, $value);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Model/Entity/EntityIteratorInterface.php:
--------------------------------------------------------------------------------
1 | list = $list;
32 | }
33 |
34 | public function getList(): array
35 | {
36 | return $this->list;
37 | }
38 |
39 | public function getEntityTypes(): array
40 | {
41 | $entityTypes = [];
42 |
43 | foreach ($this->getList() as $types) {
44 | $entityTypes[] = array_keys($types);
45 | }
46 |
47 | return $this->entityTypes ??= array_merge([], ...$entityTypes);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Model/Entity/EntityTypeResolver.php:
--------------------------------------------------------------------------------
1 | typeResolver = $typeResolver;
27 | $this->entityTypeList = $entityTypeList;
28 | }
29 |
30 | /**
31 | * @param object $entity
32 | * @return string[]
33 | * @throws Exception
34 | */
35 | public function resolve(object $entity): array
36 | {
37 | return $this->entityTypeList->getList()[$this->typeResolver->resolve($entity)] ?? [];
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Model/Entity/EntityValue/CustomAttributesProcessor.php:
--------------------------------------------------------------------------------
1 | processor = $processor;
22 | }
23 |
24 | public function process(string $key, $values): void
25 | {
26 | if ($key === CustomAttributesDataInterface::CUSTOM_ATTRIBUTES && is_iterable($values)) {
27 | foreach ($values as $value) {
28 | $this->processor->process($key, $value);
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Model/Entity/EntityValue/ExtensibleDataProcessor.php:
--------------------------------------------------------------------------------
1 | processor = $processor;
22 | }
23 |
24 | public function process(string $key, $values): void
25 | {
26 | if ($key === ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY && is_iterable($values)) {
27 | foreach ($values as $value) {
28 | $this->processor->process($key, $value);
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Model/Entity/EntityValue/StrategyProcessor.php:
--------------------------------------------------------------------------------
1 | processors = $processors;
23 | }
24 |
25 | public function process(string $key, $value): void
26 | {
27 | ($this->processors[$key] ?? $this->processors['default'])->process($key, $value);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Model/Entity/EntityValueProcessorInterface.php:
--------------------------------------------------------------------------------
1 | scopeConfig = $scopeConfig;
27 | $this->configPath = $configPath;
28 | $this->scopeType = $scopeType;
29 | }
30 |
31 | public function getAttributes(?string $scopeCode = null): array
32 | {
33 | return explode(',', $this->scopeConfig->getValue($this->configPath, $this->scopeType, $scopeCode) ?? '');
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Model/Entity/MetadataInterface.php:
--------------------------------------------------------------------------------
1 | filterIdentifier = $filterIdentifier;
25 | $this->fieldToFilter = $fieldToFilter;
26 | }
27 |
28 | /**
29 | * @inheritdoc
30 | * @throws LocalizedException
31 | */
32 | public function apply(Collection $collection, Filter $filter): void
33 | {
34 | if ($filter->getField() === $this->filterIdentifier) {
35 | $collection->addFieldToFilter(
36 | $this->fieldToFilter,
37 | [$filter->getConditionType() => $filter->getValue()]
38 | );
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Model/Entity/SourceProvider/ModifierComposite.php:
--------------------------------------------------------------------------------
1 | modifiers = $modifiers;
27 | }
28 |
29 | public function apply(Collection $collection, Filter $filter): void
30 | {
31 | foreach ($this->modifiers as $modifier) {
32 | $modifier->apply($collection, $filter);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Model/Entity/SourceProvider/ModifierFactory.php:
--------------------------------------------------------------------------------
1 | modifiers = $modifiers;
33 | $this->objectManager = $objectManager;
34 | }
35 |
36 | public function get(string $entityType): ModifierInterface
37 | {
38 | return $this->objectManager->get($this->modifiers[$entityType] ?? $this->modifiers['default']);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Model/Entity/SourceProvider/ModifierInterface.php:
--------------------------------------------------------------------------------
1 | sourceProviders = $sourceProviders;
36 | $this->objectManager = $objectManager;
37 | }
38 |
39 | public function create(string $entityType): Collection
40 | {
41 | if (!isset($this->sourceProviders[$entityType])) {
42 | throw new InvalidArgumentException(sprintf('Unknown source provider for entity type "%s".', $entityType));
43 | }
44 |
45 | return $this->objectManager->create($this->sourceProviders[$entityType]);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Model/Erase/NotifierInterface.php:
--------------------------------------------------------------------------------
1 | exportRepository = $exportRepository;
22 | }
23 |
24 | public function exists(int $entityId, string $entityType): bool
25 | {
26 | try {
27 | return (bool) $this->exportRepository->getByEntity($entityId, $entityType)->getExportId();
28 | } catch (NoSuchEntityException $e) {
29 | return false;
30 | }
31 | }
32 |
33 | public function isExported(int $entityId, string $entityType): bool
34 | {
35 | try {
36 | $entity = $this->exportRepository->getByEntity($entityId, $entityType);
37 | } catch (NoSuchEntityException $e) {
38 | return false;
39 | }
40 |
41 | return $entity->getExportedAt() !== null && $entity->getFilePath() !== null;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Model/Newsletter/Subscriber.php:
--------------------------------------------------------------------------------
1 | subscriber = $subscriberFactory->create(['data' => $data]);
28 | }
29 |
30 | public function getRealSubscriber(): SubscriberModel
31 | {
32 | return $this->subscriber;
33 | }
34 |
35 | public function __call($method, $args)
36 | {
37 | return $this->subscriber->{$method}(...$args);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Model/Order/Delete/Processor/OrderDataProcessor.php:
--------------------------------------------------------------------------------
1 | orderRepository = $orderRepository;
27 | $this->salesInformation = $salesInformation;
28 | }
29 |
30 | /**
31 | * @inheritdoc
32 | * @throws Exception
33 | */
34 | public function execute(int $orderId): bool
35 | {
36 | $order = $this->orderRepository->get($orderId);
37 | $lastActive = new DateTime($order->getUpdatedAt());
38 |
39 | if ($this->salesInformation->isAlive($lastActive)) {
40 | $this->salesInformation->scheduleEraseEntity((int) $order->getEntityId(), 'order', $lastActive);
41 |
42 | return true;
43 | }
44 |
45 | return $this->orderRepository->delete($order);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/Model/Order/Delete/Processor/QuoteDataProcessor.php:
--------------------------------------------------------------------------------
1 | orderRepository = $orderRepository;
26 | $this->quoteRepository = $quoteRepository;
27 | }
28 |
29 | public function execute(int $orderId): bool
30 | {
31 | try {
32 | $order = $this->orderRepository->get($orderId);
33 | $this->quoteRepository->delete($this->quoteRepository->get($order->getQuoteId()));
34 | } catch (NoSuchEntityException $e) {
35 | /** Silence is golden */
36 | }
37 |
38 | return true;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Model/Order/Erase/Notifier.php:
--------------------------------------------------------------------------------
1 | senders = $senders;
32 | $this->orderRepository = $orderRepository;
33 | $this->logger = $logger;
34 | }
35 |
36 | public function notify(EraseEntityInterface $eraseEntity): void
37 | {
38 | $order = $this->orderRepository->get($eraseEntity->getEntityId());
39 |
40 | foreach ($this->senders as $sender) {
41 | try {
42 | $sender->send($order);
43 | } catch (LocalizedException $e) {
44 | $this->logger->error($e->getLogMessage(), $e->getTrace());
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Model/Order/Export/Notifier.php:
--------------------------------------------------------------------------------
1 | senders = $senders;
32 | $this->orderRepository = $orderRepository;
33 | $this->logger = $logger;
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | */
39 | public function notify(ExportEntityInterface $exportEntity): void
40 | {
41 | $order = $this->orderRepository->get($exportEntity->getEntityId());
42 |
43 | foreach ($this->senders as $sender) {
44 | try {
45 | $sender->send($order);
46 | } catch (LocalizedException $e) {
47 | $this->logger->error($e->getLogMessage(), $e->getTrace());
48 | }
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Model/Order/Export/Processor/AbstractDataProcessor.php:
--------------------------------------------------------------------------------
1 | orderRepository = $orderRepository;
24 | parent::__construct($dataCollector);
25 | }
26 |
27 | public function execute(int $entityId, array $data): array
28 | {
29 | return $this->export($this->orderRepository->get($entityId), $data);
30 | }
31 |
32 | /**
33 | * Execute the export processor for the given order entity.
34 | * It allows to retrieve the related data as an array.
35 | *
36 | * @param OrderInterface $order
37 | * @param array $ata
38 | * @return array
39 | */
40 | abstract protected function export(OrderInterface $order, array $ata): array;
41 | }
42 |
--------------------------------------------------------------------------------
/Model/Order/Export/Processor/OrderDataProcessor.php:
--------------------------------------------------------------------------------
1 | getEntityId();
20 | $data['orders'][$key] = $this->collectData($order);
21 |
22 | /** @var OrderAddressInterface|null $orderAddress */
23 | foreach ([$order->getBillingAddress(), $order->getShippingAddress()] as $orderAddress) {
24 | if ($orderAddress) {
25 | $data['orders'][$key][$orderAddress->getAddressType()] = $this->collectData($orderAddress);
26 | }
27 | }
28 |
29 | return $data;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Model/Order/Export/Processor/SubscriberDataProcessor.php:
--------------------------------------------------------------------------------
1 | subscriberFactory = $subscriberFactory;
26 | parent::__construct($orderRepository, $dataCollector);
27 | }
28 |
29 | protected function export(OrderInterface $order, array $data): array
30 | {
31 | /** @var Subscriber $subscriber */
32 | $subscriber = $this->subscriberFactory->create();
33 | $subscriber->loadByEmail($order->getCustomerEmail());
34 | $data['subscriber'] = $this->collectData($subscriber);
35 |
36 | return $data;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Model/Order/Notifier/SenderInterface.php:
--------------------------------------------------------------------------------
1 | orderRepository = $orderRepository;
26 | $this->config = $config;
27 | }
28 |
29 | public function canErase(int $orderId): bool
30 | {
31 | $order = $this->orderRepository->get($orderId);
32 |
33 | return in_array($order->getState(), $this->config->getAllowedStatesToErase(), true);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Model/Order/SourceProvider/GuestFilterModifier.php:
--------------------------------------------------------------------------------
1 | config = $config;
24 | }
25 |
26 | /**
27 | * @inheritdoc
28 | * @throws LocalizedException
29 | */
30 | public function apply(Collection $collection, Filter $filter): void
31 | {
32 | $collection->addFieldToFilter(OrderInterface::CUSTOMER_ID, ['null' => true]);
33 | $collection->addFieldToFilter(OrderInterface::CUSTOMER_IS_GUEST, ['eq' => 1]);
34 | $collection->addFieldToFilter(OrderInterface::STATE, ['in' => $this->config->getAllowedStatesToErase()]);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ActionEntity.php:
--------------------------------------------------------------------------------
1 | validator = $validator;
32 | parent::__construct($context, $entitySnapshot, $relationComposite, $connectionName);
33 | }
34 |
35 | protected function _construct(): void
36 | {
37 | $this->_init(self::TABLE, ActionEntityInterface::ID);
38 | $this->_serializableFields = [ActionEntityInterface::PARAMETERS => [[], []]];
39 | }
40 |
41 | public function getValidationRulesBeforeSave(): ValidatorInterface
42 | {
43 | return $this->validator;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ActionEntity/Collection.php:
--------------------------------------------------------------------------------
1 | _init(ActionEntity::class, ActionEntityResourceModel::class);
20 | $this->_setIdFieldName(ActionEntityInterface::ID);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ActionEntity/Validator.php:
--------------------------------------------------------------------------------
1 | validators = $validators;
24 | }
25 |
26 | public function isValid($value): bool
27 | {
28 | $this->_clearMessages();
29 |
30 | foreach ($this->validators as $validator) {
31 | if (!$validator->isValid($value)) {
32 | $this->_addMessages($validator->getMessages());
33 | }
34 | }
35 |
36 | return !$this->hasMessages();
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ActionEntity/Validator/StateValidator.php:
--------------------------------------------------------------------------------
1 | actionStates = $actionStates;
25 | }
26 |
27 | /**
28 | * @param ActionEntityInterface $actionEntity
29 | * @return bool
30 | */
31 | public function isValid($actionEntity): bool
32 | {
33 | $this->_clearMessages();
34 | $isValid = in_array(
35 | $actionEntity->getState(),
36 | array_column($this->actionStates->toOptionArray(), 'value'),
37 | true
38 | );
39 |
40 | if (!$isValid) {
41 | $this->_addMessages([
42 | 'state' => new Phrase('State "%1" does not exists.', [$actionEntity->getState()])
43 | ]);
44 | }
45 |
46 | return $isValid;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Model/ResourceModel/EraseEntity.php:
--------------------------------------------------------------------------------
1 | _init(self::TABLE, EraseEntityInterface::ID);
25 | }
26 |
27 | /**
28 | * @inheritdoc
29 | * @param string|array $field
30 | * @param mixed $value
31 | * @param AbstractModel $object
32 | * @return Select
33 | * @throws LocalizedException
34 | */
35 | protected function _getLoadSelect($field, $value, $object): Select
36 | {
37 | if (!is_array($field) && !is_array($value)) {
38 | return parent::_getLoadSelect($field, $value, $object);
39 | }
40 |
41 | $select = $this->getConnection()->select()->from($this->getMainTable());
42 |
43 | foreach ($field as $i => $identifier) {
44 | $primaryKey = $this->getConnection()->quoteIdentifier(sprintf('%s.%s', $this->getMainTable(), $identifier));
45 | $select->where($primaryKey . '=?', $value[$i]);
46 | }
47 |
48 | return $select;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Model/ResourceModel/EraseEntity/Collection.php:
--------------------------------------------------------------------------------
1 | _init(EraseEntity::class, EraseEntityResourceModel::class);
20 | $this->_setIdFieldName(EraseEntityInterface::ID);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ExportEntity.php:
--------------------------------------------------------------------------------
1 | _init(self::TABLE, ExportEntityInterface::ID);
25 | }
26 |
27 | /**
28 | * @inheritdoc
29 | * @param string|array $field
30 | * @param mixed $value
31 | * @param AbstractModel $object
32 | * @return Select
33 | * @throws LocalizedException
34 | */
35 | protected function _getLoadSelect($field, $value, $object): Select
36 | {
37 | if (!is_array($field) && !is_array($value)) {
38 | return parent::_getLoadSelect($field, $value, $object);
39 | }
40 |
41 | $select = $this->getConnection()->select()->from($this->getMainTable());
42 |
43 | foreach ($field as $i => $identifier) {
44 | $primaryKey = $this->getConnection()->quoteIdentifier(sprintf('%s.%s', $this->getMainTable(), $identifier));
45 | $select->where($primaryKey . '=?', $value[$i]);
46 | }
47 |
48 | return $select;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Model/ResourceModel/ExportEntity/Collection.php:
--------------------------------------------------------------------------------
1 | _init(ExportEntity::class, ExportEntityResourceModel::class);
20 | $this->_setIdFieldName(ExportEntityInterface::ID);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/AlphaLower.php:
--------------------------------------------------------------------------------
1 | mathRandom = $mathRandom;
30 | $this->length = $length;
31 | }
32 |
33 | /**
34 | * @inheritdoc
35 | * @throws LocalizedException
36 | */
37 | public function anonymize($value): ?string
38 | {
39 | return $value ? $this->mathRandom->getRandomString($this->length, Random::CHARS_LOWERS) : null;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/AlphaNum.php:
--------------------------------------------------------------------------------
1 | mathRandom = $mathRandom;
30 | $this->length = $length;
31 | }
32 |
33 | /**
34 | * @inheritdoc
35 | * @throws LocalizedException
36 | */
37 | public function anonymize($value): ?string
38 | {
39 | return $value ? $this->mathRandom->getRandomString($this->length) : null;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/AlphaUpper.php:
--------------------------------------------------------------------------------
1 | mathRandom = $mathRandom;
30 | $this->length = $length;
31 | }
32 |
33 | /**
34 | * @inheritdoc
35 | * @throws LocalizedException
36 | */
37 | public function anonymize($value): ?string
38 | {
39 | return $value ? $this->mathRandom->getRandomString($this->length, Random::CHARS_UPPERS) : null;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/Anonymous.php:
--------------------------------------------------------------------------------
1 | mathRandom = $mathRandom;
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws LocalizedException
35 | */
36 | public function anonymize($value): ?string
37 | {
38 | return $value
39 | ? (new Phrase(
40 | self::PHRASE,
41 | [
42 | $this->mathRandom->getRandomString(self::PREFIX_LENGTH),
43 | $this->mathRandom->getRandomString(self::SUFFIX_LENGTH),
44 | ]
45 | ))->render()
46 | : null;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/Date.php:
--------------------------------------------------------------------------------
1 | randomDateTime()->format(StdlibDateTime::DATETIME_PHP_FORMAT) : null;
28 | }
29 |
30 | /**
31 | * @return DateTime
32 | * @throws LocalizedException
33 | */
34 | private function randomDateTime(): DateTime
35 | {
36 | $dateTime = new DateTime();
37 | $dateTime->setTimestamp(Random::getRandomNumber(self::MIN_TIMESTAMP, self::MAX_TIMESTAMP));
38 |
39 | return $dateTime;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/Email.php:
--------------------------------------------------------------------------------
1 | mathRandom = $mathRandom;
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws LocalizedException
35 | */
36 | public function anonymize($value): ?string
37 | {
38 | return $value
39 | ? (new Phrase(
40 | self::PHRASE,
41 | [
42 | $this->mathRandom->getRandomString(self::PREFIX_LENGTH, Random::CHARS_LOWERS),
43 | $this->mathRandom->getRandomString(self::SUFFIX_LENGTH, Random::CHARS_LOWERS),
44 | ]
45 | ))->render()
46 | : null;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/Entity.php:
--------------------------------------------------------------------------------
1 | dataCollector = $dataCollector;
34 | $this->typeResolver = $typeResolver;
35 | $this->hydratorPool = $hydratorPool;
36 | }
37 |
38 | /**
39 | * @inheritdoc
40 | * @throws Exception
41 | */
42 | public function anonymize($entity): object
43 | {
44 | if (!is_object($entity)) {
45 | throw new InvalidArgumentException(
46 | sprintf('Argument "$entity" must be an object, type "%s" given.', gettype($entity))
47 | );
48 | }
49 |
50 | $hydrator = $this->hydratorPool->getHydrator($this->typeResolver->resolve($entity));
51 | $hydrator->hydrate($entity, $this->dataCollector->collect($entity));
52 |
53 | return $entity;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/NullValue.php:
--------------------------------------------------------------------------------
1 | min = $min < PHP_INT_MIN ? PHP_INT_MIN : $min;
33 | $this->max = $max !== null && $max > PHP_INT_MAX ? PHP_INT_MAX : $max;
34 | }
35 |
36 | /**
37 | * @inheritdoc
38 | * @throws LocalizedException
39 | */
40 | public function anonymize($value): ?int
41 | {
42 | return $value ? Random::getRandomNumber($this->min, $this->max) : null;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Service/Anonymize/Anonymizer/Phone.php:
--------------------------------------------------------------------------------
1 | random = $random;
30 | }
31 |
32 | /**
33 | * @throws LocalizedException
34 | */
35 | public function anonymize($value): array
36 | {
37 | return [sprintf(
38 | '%s %s',
39 | Random::getRandomNumber(self::MIN_NUM, self::MAX_NUM),
40 | $this->random->getRandomString(self::STREET_LENGTH)
41 | )];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Service/Anonymize/AnonymizerFactory.php:
--------------------------------------------------------------------------------
1 | anonymizers = $anonymizers;
30 | $this->objectManager = $objectManager;
31 | }
32 |
33 | public function get(string $anonymizerCode): AnonymizerInterface
34 | {
35 | if (!isset($this->anonymizers[$anonymizerCode])) {
36 | throw new InvalidArgumentException(sprintf('Unknown anonymizer type "%s".', $anonymizerCode));
37 | }
38 |
39 | return $this->objectManager->get($this->anonymizers[$anonymizerCode]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Anonymize/AnonymizerInterface.php:
--------------------------------------------------------------------------------
1 | document = $document;
33 | $this->metadata = $metadata;
34 | $this->anonymizer = $anonymizer;
35 | }
36 |
37 | public function process(string $key, $value): void
38 | {
39 | if (in_array($key, $this->metadata->getAttributes(), true)) {
40 | $this->document->addData($key, $this->anonymizer->anonymize($value));
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Service/Anonymize/Processor/Entity/EntityValue/SmartProcessor.php:
--------------------------------------------------------------------------------
1 | document = $document;
36 | $this->metadata = $metadata;
37 | $this->anonymizerFactory = $anonymizerFactory;
38 | }
39 |
40 | public function process(string $key, $value): void
41 | {
42 | if (in_array($key, $this->metadata->getAttributes(), true)) {
43 | $this->document->addData(
44 | $key,
45 | $this->anonymizerFactory->get(
46 | $this->metadata->getAnonymizerStrategiesByAttributes()[$key] ?? AnonymizerFactory::DEFAULT_KEY
47 | )->anonymize($value)
48 | );
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Service/Erase/MetadataInterface.php:
--------------------------------------------------------------------------------
1 | processorResolver = $processorResolver;
32 | $this->eraseComponents = $eraseComponents;
33 | }
34 |
35 | public function execute(int $entityId): bool
36 | {
37 | $components = array_column($this->eraseComponents->toOptionArray(), 'value');
38 |
39 | foreach ($components as $component) {
40 | $processor = $this->processorResolver->resolve($component);
41 | if (!$processor->execute($entityId)) {
42 | return false;
43 | }
44 | }
45 |
46 | return true;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/Service/Erase/ProcessorFactory.php:
--------------------------------------------------------------------------------
1 | erasers = $erasers;
31 | $this->objectManager = $objectManager;
32 | }
33 |
34 | public function get(string $entityType): ProcessorInterface
35 | {
36 | if (!isset($this->erasers[$entityType])) {
37 | throw new InvalidArgumentException(sprintf('Unknown eraser for entity type "%s".', $entityType));
38 | }
39 |
40 | return $this->objectManager->get($this->erasers[$entityType]);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Service/Erase/ProcessorInterface.php:
--------------------------------------------------------------------------------
1 | processors = $processors;
30 | $this->objectManager = $objectManager;
31 | }
32 |
33 | public function resolve(string $component): ProcessorInterface
34 | {
35 | if (!isset($this->processors[$component])) {
36 | throw new InvalidArgumentException(sprintf('Unknown processor type "%s".', $component));
37 | }
38 |
39 | return $this->objectManager->get($this->processors[$component]);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Erase/ProcessorResolver/ProcessorResolverStrategy.php:
--------------------------------------------------------------------------------
1 | resolverFactory = $resolverFactory;
29 | $this->metadata = $metadata;
30 | }
31 |
32 | public function resolve(string $component): ProcessorInterface
33 | {
34 | return $this->resolverFactory->get($this->metadata->getComponentProcessor($component))->resolve($component);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Service/Erase/ProcessorResolverFactory.php:
--------------------------------------------------------------------------------
1 | processorResolvers = $processorResolvers;
35 | $this->objectManager = $objectManager;
36 | }
37 |
38 | public function get(string $processorCode): ProcessorResolverInterface
39 | {
40 | if (!isset($this->processorResolvers[$processorCode])) {
41 | throw new InvalidArgumentException(sprintf('Unknown renderer type "%s".', $processorCode));
42 | }
43 |
44 | return $this->objectManager->get($this->processorResolvers[$processorCode]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Service/Erase/ProcessorResolverInterface.php:
--------------------------------------------------------------------------------
1 | dataCollector = $dataCollector;
21 | }
22 |
23 | protected function collectData(object $entity): array
24 | {
25 | return $this->dataCollector->collect($entity);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Service/Export/Processor/CompositeProcessor.php:
--------------------------------------------------------------------------------
1 | processors = $processors;
24 | }
25 |
26 | public function execute(int $entityId, array $data): array
27 | {
28 | return array_reduce(
29 | $this->processors,
30 | static function (array $data, ProcessorInterface $processor) use ($entityId): array {
31 | return $processor->execute($entityId, $data);
32 | },
33 | $data
34 | );
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Service/Export/Processor/Entity/EntityValue/DataProcessor.php:
--------------------------------------------------------------------------------
1 | document = $document;
29 | $this->metadata = $metadata;
30 | }
31 |
32 | public function process(string $key, $value): void
33 | {
34 | if (in_array($key, $this->metadata->getAttributes(), true)) {
35 | $this->document->addData($key, $value);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Service/Export/Processor/Entity/EntityValue/EntityProcessor.php:
--------------------------------------------------------------------------------
1 | document = $document;
33 | $this->metadata = $metadata;
34 | $this->dataCollector = $dataCollector;
35 | }
36 |
37 | public function process(string $key, $value): void
38 | {
39 | if (in_array($key, $this->metadata->getAttributes(), true)) {
40 | $this->document->addData($key, $this->dataCollector->collect($value));
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Service/Export/ProcessorFactory.php:
--------------------------------------------------------------------------------
1 | exporters = $exporters;
35 | $this->objectManager = $objectManager;
36 | }
37 |
38 | public function get(string $entityType): ProcessorInterface
39 | {
40 | if (!isset($this->exporters[$entityType])) {
41 | throw new InvalidArgumentException(sprintf('Unknown exporter for entity type "%s".', $entityType));
42 | }
43 |
44 | return $this->objectManager->get($this->exporters[$entityType]);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Service/Export/ProcessorInterface.php:
--------------------------------------------------------------------------------
1 | fileSystem = $filesystem;
26 | $this->fileExtension = $fileExtension;
27 | }
28 |
29 | /**
30 | * @inheritdoc
31 | * @throws FileSystemException
32 | */
33 | public function saveData(string $fileName, array $data): string
34 | {
35 | $fileName .= '.' . $this->fileExtension;
36 | $tmpWrite = $this->fileSystem->getDirectoryWrite(DirectoryList::TMP);
37 | $tmpWrite->writeFile($fileName, $this->render($data));
38 |
39 | return $tmpWrite->getAbsolutePath($fileName);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Service/Export/Renderer/CsvRenderer.php:
--------------------------------------------------------------------------------
1 | $value) {
29 | $csv .= is_array($value)
30 | ? $key . ',' . rtrim($this->render($value), ',') . PHP_EOL
31 | : '"' . str_replace('"', '""', $value) . '",';
32 | }
33 |
34 | return $csv;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Service/Export/Renderer/HtmlRenderer/LayoutInitiatorInterface.php:
--------------------------------------------------------------------------------
1 | jsonSerializer = $jsonSerializer;
22 | parent::__construct($filesystem, 'json');
23 | }
24 |
25 | public function render(array $data): string
26 | {
27 | return $this->jsonSerializer->serialize($data);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Service/Export/Renderer/PdfRenderer.php:
--------------------------------------------------------------------------------
1 | htmlRenderer = $htmlRenderer;
23 | parent::__construct($filesystem, 'pdf');
24 | }
25 |
26 | /**
27 | * @inheritdoc
28 | * @throws Exception
29 | */
30 | public function render(array $data): string
31 | {
32 | $pdf = new TCPDF();
33 | $pdf->AddPage('P', 'A4');
34 | $pdf->writeHTML($this->htmlRenderer->render($data));
35 |
36 | return $pdf->Output('', 'S');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Service/Export/Renderer/XmlRenderer.php:
--------------------------------------------------------------------------------
1 | convertArray = $convertArray;
28 | $this->rootName = $rootName;
29 | parent::__construct($filesystem, 'xml');
30 | }
31 |
32 | /**
33 | * @inheritdoc
34 | * @throws LocalizedException
35 | */
36 | public function render(array $data): string
37 | {
38 | return $this->convertArray->assocToXml($data, $this->rootName)->saveXML();
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Service/Export/RendererFactory.php:
--------------------------------------------------------------------------------
1 | renderers = $renderers;
31 | $this->objectManager = $objectManager;
32 | }
33 |
34 | public function get(string $rendererCode): RendererInterface
35 | {
36 | if (!isset($this->renderers[$rendererCode])) {
37 | throw new InvalidArgumentException(sprintf('Unknown renderer type "%s".', $rendererCode));
38 | }
39 |
40 | return $this->objectManager->get($this->renderers[$rendererCode]);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Service/Export/RendererInterface.php:
--------------------------------------------------------------------------------
1 | privacyMessage = $privacyMessage;
20 | }
21 |
22 | public function getTemplate(string $defaultTemplate, string $customTemplate): string
23 | {
24 | return $this->privacyMessage->isEnabled() ? $customTemplate : $defaultTemplate;
25 | }
26 |
27 | public function getLearnMoreUrl(): ?string
28 | {
29 | return $this->privacyMessage->getLearnMoreUrl();
30 | }
31 |
32 | public function getNoticeHtml(): string
33 | {
34 | return $this->privacyMessage->getDisclosureInformationHtml();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/ViewModel/Customer/Guest/EraseDataProvider.php:
--------------------------------------------------------------------------------
1 | eraseEntityChecker = $eraseEntityChecker;
36 | $this->registry = $registry;
37 | }
38 |
39 | public function canCancel(): bool
40 | {
41 | return $this->canCancel ??
42 | $this->canCancel = $this->eraseEntityChecker->canCancel($this->currentOrderId(), 'order');
43 | }
44 |
45 | public function canCreate(): bool
46 | {
47 | return $this->canCreate ??
48 | $this->canCreate = $this->eraseEntityChecker->canCreate($this->currentOrderId(), 'order');
49 | }
50 |
51 | private function currentOrderId(): int
52 | {
53 | /** @var OrderInterface $order */
54 | $order = $this->registry->registry('current_order');
55 |
56 | return (int) $order->getEntityId();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/ViewModel/Customer/Guest/ExportDataProvider.php:
--------------------------------------------------------------------------------
1 | exportEntityChecker = $exportEntityChecker;
36 | $this->registry = $registry;
37 | }
38 |
39 | public function hasExport(): bool
40 | {
41 | return $this->isExportEntityExists ??
42 | $this->isExportEntityExists = $this->exportEntityChecker->exists($this->currentOrderId(), 'order');
43 | }
44 |
45 | public function isExported(): bool
46 | {
47 | return $this->isExported ??
48 | $this->isExported = $this->exportEntityChecker->isExported($this->currentOrderId(), 'order');
49 | }
50 |
51 | private function currentOrderId(): int
52 | {
53 | /** @var OrderInterface $order */
54 | $order = $this->registry->registry('current_order');
55 |
56 | return (int) $order->getEntityId();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/ViewModel/Customer/Privacy/EraseCustomerDataProvider.php:
--------------------------------------------------------------------------------
1 | eraseEntityChecker = $eraseEntityChecker;
38 | $this->session = $session;
39 | }
40 |
41 | public function canCancel(): bool
42 | {
43 | return $this->canCancel ??= $this->eraseEntityChecker->canCancel($this->currentCustomerId(), 'customer');
44 | }
45 |
46 | public function canCreate(): bool
47 | {
48 | return $this->canCreate ??= $this->eraseEntityChecker->canCreate($this->currentCustomerId(), 'customer');
49 | }
50 |
51 | private function currentCustomerId(): int
52 | {
53 | return (int) $this->session->getCustomerId();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ViewModel/Customer/Privacy/ExportCustomerDataProvider.php:
--------------------------------------------------------------------------------
1 | exportEntityChecker = $exportEntityChecker;
38 | $this->session = $session;
39 | }
40 |
41 | public function hasExport(): bool
42 | {
43 | return $this->isExportEntityExists ??= $this->exportEntityChecker->exists($this->currentCustomerId(), 'customer');
44 | }
45 |
46 | public function isExported(): bool
47 | {
48 | return $this->isExported ??= $this->exportEntityChecker->isExported($this->currentCustomerId(), 'customer');
49 | }
50 |
51 | private function currentCustomerId(): int
52 | {
53 | return (int) $this->session->getCustomerId();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/ViewModel/Customer/Privacy/ExportDataProvider.php:
--------------------------------------------------------------------------------
1 | scopeConfig = $scopeConfig;
31 | $this->blockFactory = $blockFactory;
32 | }
33 |
34 | public function getExportInformationHtml(): string
35 | {
36 | return $this->exportInformation ??= $this->blockFactory->createBlock(
37 | BlockByIdentifier::class,
38 | ['data' => ['identifier' => (string) $this->scopeConfig->getValue(
39 | self::CONFIG_PATH_EXPORT_INFORMATION_BLOCK,
40 | ScopeInterface::SCOPE_STORE
41 | )]]
42 | )->toHtml();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ViewModel/Customer/Privacy/SettingsDataProvider.php:
--------------------------------------------------------------------------------
1 | scopeConfig = $scopeConfig;
31 | $this->blockFactory = $blockFactory;
32 | }
33 |
34 | public function getPrivacyInformationHtml(): string
35 | {
36 | return $this->informationHtml ??= $this->blockFactory->createBlock(
37 | BlockByIdentifier::class,
38 | ['data' => ['identifier' => (string) $this->scopeConfig->getValue(
39 | self::CONFIG_PATH_GENERAL_INFORMATION_BLOCK,
40 | ScopeInterface::SCOPE_STORE
41 | )]]
42 | )->toHtml();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/etc/adminhtml/menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to cancel the erasure of the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 | |
23 |
26 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 27 | |
28 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to cancel the erasure of the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 | |
23 |
26 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 27 | |
28 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to erase the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 |{{trans 'You can cancel the erase within %delay hours by logging into your account.' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}} 23 | |
24 |
27 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 28 | |
29 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to erase the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 |{{trans 'You can cancel the erase within %delay hours by logging into your account.' account_url=$this.getUrl($store,'customer/account/',[_nosid:1]) |raw}} 23 | |
24 |
27 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 28 | |
29 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have successfully erased the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 | |
23 |
26 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 27 | |
28 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have successfully erased the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 | |
23 |
26 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 27 | |
28 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to export the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 |{{trans "We will notify you when the export will be ready. The action will be available in your account."}} 23 | |
24 |
27 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 28 | |
29 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to export the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 |{{trans "We will notify you when the export will be ready. The action will be available in your account."}} 23 | |
24 |
27 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 28 | |
29 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to export the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 |{{trans "The export of you personal data is ready. The action is now available in your account."}} 23 | |
24 |
27 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 28 | |
29 |
16 | {{trans "%name," name=$customer_data.customer_name}} 17 | |
18 |
21 | {{trans "We have received a request to export the information associated with your account at %store_name." store_name=$store.getFrontendName()}} 22 |{{trans "The export of you personal data is ready. The action is now available in your account."}} 23 | |
24 |
27 | {{trans 'If you have not authorized this action, please contact us immediately at %store_email' store_email=$store_email |raw}}{{depend store_phone}} {{trans 'or call us at %store_phone' store_phone=$store_phone |raw}}{{/depend}}. 28 | |
29 |