Skip to content

Commit f3f5c6c

Browse files
committed
fix #87 NoSuchEntityException on Export
1 parent 5c46edf commit f3f5c6c

File tree

13 files changed

+200
-48
lines changed

13 files changed

+200
-48
lines changed

Api/ExportEntityManagementInterface.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Framework\Exception\CouldNotDeleteException;
1212
use Magento\Framework\Exception\CouldNotSaveException;
1313
use Magento\Framework\Exception\LocalizedException;
14+
use Magento\Framework\Exception\NoSuchEntityException;
1415
use Opengento\Gdpr\Api\Data\ExportEntityInterface;
1516

1617
/**
@@ -37,6 +38,7 @@ public function create(int $entityId, string $entityType, ?string $fileName = nu
3738
* @param ExportEntityInterface $exportEntity
3839
* @return ExportEntityInterface
3940
* @throws CouldNotSaveException
41+
* @throws NoSuchEntityException
4042
* @throws LocalizedException
4143
*/
4244
public function export(ExportEntityInterface $exportEntity): ExportEntityInterface;

Controller/Adminhtml/Privacy/MassExport.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
use Opengento\Gdpr\Model\Action\ArgumentReader;
2525
use Opengento\Gdpr\Model\Action\ContextBuilder;
2626
use Opengento\Gdpr\Model\Action\Export\ArgumentReader as ExportArgumentReader;
27-
use Opengento\Gdpr\Model\Archive\MoveToArchive;
27+
use Opengento\Gdpr\Model\Archive\ArchiveManager;
2828

2929
class MassExport extends AbstractMassAction
3030
{
@@ -36,9 +36,9 @@ class MassExport extends AbstractMassAction
3636
private $fileFactory;
3737

3838
/**
39-
* @var MoveToArchive
39+
* @var ArchiveManager
4040
*/
41-
private $moveToArchive;
41+
private $archiveManager;
4242

4343
/**
4444
* @var ActionInterface
@@ -55,12 +55,12 @@ public function __construct(
5555
Filter $filter,
5656
CollectionFactory $collectionFactory,
5757
FileFactory $fileFactory,
58-
MoveToArchive $moveToArchive,
58+
ArchiveManager $archiveManager,
5959
ActionInterface $action,
6060
ContextBuilder $actionContextBuilder
6161
) {
6262
$this->fileFactory = $fileFactory;
63-
$this->moveToArchive = $moveToArchive;
63+
$this->archiveManager = $archiveManager;
6464
$this->action = $action;
6565
$this->actionContextBuilder = $actionContextBuilder;
6666
parent::__construct($context, $filter, $collectionFactory);
@@ -79,7 +79,7 @@ protected function massAction(AbstractCollection $collection)
7979
$result = $this->action->execute($this->actionContextBuilder->create())->getResult();
8080
/** @var ExportEntityInterface $exportEntity */
8181
$exportEntity = $result[ExportArgumentReader::EXPORT_ENTITY];
82-
$this->moveToArchive->prepareArchive($exportEntity->getFilePath(), $archiveFileName, false);
82+
$this->archiveManager->addToArchive($exportEntity->getFilePath(), $archiveFileName, false);
8383
}
8484

8585
return $this->fileFactory->create(

Cron/ExportEntity.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
use Exception;
1111
use Magento\Framework\Api\SearchCriteriaBuilder;
12+
use Magento\Framework\Exception\NoSuchEntityException;
1213
use Opengento\Gdpr\Api\Data\ExportEntityInterface;
1314
use Opengento\Gdpr\Api\ExportEntityManagementInterface;
1415
use Opengento\Gdpr\Api\ExportEntityRepositoryInterface;
@@ -69,10 +70,15 @@ public function execute(): void
6970
$exportList = $this->exportRepository->getList($this->criteriaBuilder->create());
7071

7172
foreach ($exportList->getItems() as $exportEntity) {
72-
$this->exportManagement->export($exportEntity);
73+
try {
74+
$this->exportManagement->export($exportEntity);
75+
} catch (NoSuchEntityException $e) {
76+
$this->logger->error($e->getLogMessage(), $e->getTrace());
77+
$this->exportRepository->delete($exportEntity);
78+
}
7379
}
7480
} catch (Exception $e) {
75-
$this->logger->error($e->getMessage(), $e->getTrace());
81+
$this->logger->critical($e->getMessage(), $e->getTrace());
7682
}
7783
}
7884
}

Model/Action/Export/ExportAction.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,33 @@
88
namespace Opengento\Gdpr\Model\Action\Export;
99

1010
use Magento\Framework\Exception\InputException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
1112
use Opengento\Gdpr\Api\Data\ActionContextInterface;
1213
use Opengento\Gdpr\Api\Data\ActionResultInterface;
1314
use Opengento\Gdpr\Api\ExportEntityManagementInterface;
15+
use Opengento\Gdpr\Api\ExportEntityRepositoryInterface;
1416
use Opengento\Gdpr\Model\Action\AbstractAction;
1517
use Opengento\Gdpr\Model\Action\Export\ArgumentReader as ExportArgumentReader;
1618
use Opengento\Gdpr\Model\Action\ResultBuilder;
1719

1820
final class ExportAction extends AbstractAction
1921
{
22+
/**
23+
* @var ExportEntityRepositoryInterface
24+
*/
25+
private $exportRepository;
26+
2027
/**
2128
* @var ExportEntityManagementInterface
2229
*/
2330
private $exportManagement;
2431

2532
public function __construct(
2633
ResultBuilder $resultBuilder,
34+
ExportEntityRepositoryInterface $exportRepository,
2735
ExportEntityManagementInterface $exportManagement
2836
) {
37+
$this->exportRepository = $exportRepository;
2938
$this->exportManagement = $exportManagement;
3039
parent::__construct($resultBuilder);
3140
}
@@ -38,8 +47,16 @@ public function execute(ActionContextInterface $actionContext): ActionResultInte
3847
throw InputException::requiredField('entity');
3948
}
4049

50+
try {
51+
$exportEntity = $this->exportManagement->export($exportEntity);
52+
} catch (NoSuchEntityException $e) {
53+
$this->exportRepository->delete($exportEntity);
54+
55+
throw $e;
56+
}
57+
4158
return $this->createActionResult(
42-
[ExportArgumentReader::EXPORT_ENTITY => $this->exportManagement->export($exportEntity)]
59+
[ExportArgumentReader::EXPORT_ENTITY => $exportEntity]
4360
);
4461
}
4562
}

Model/Archive/MoveToArchive.php renamed to Model/Archive/ArchiveManager.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Magento\Framework\Filesystem;
1515
use Magento\Framework\Phrase;
1616

17-
final class MoveToArchive
17+
final class ArchiveManager
1818
{
1919
/**
2020
* @var ArchiveInterface
@@ -42,7 +42,7 @@ public function __construct(
4242
* @throws FileSystemException
4343
* @throws NotFoundException
4444
*/
45-
public function prepareArchive(string $source, string $destination, bool $remove = true): string
45+
public function addToArchive(string $source, string $destination, bool $remove = true): string
4646
{
4747
$tmpWrite = $this->filesystem->getDirectoryWrite(DirectoryList::TMP);
4848
$fileDriver = $tmpWrite->getDriver();

Model/Export/ExportEntityData.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,16 @@ public function export(int $entityId, string $entityType): ExportEntityInterface
6464
$exportEntity = $this->exportManagement->create($entityId, $entityType);
6565
}
6666

67-
return $this->exportEntityChecker->isExported($entityId, $entityType)
68-
? $exportEntity
69-
: $this->exportManagement->export($exportEntity);
67+
if (!$this->exportEntityChecker->isExported($entityId, $entityType)) {
68+
try {
69+
$exportEntity = $this->exportManagement->export($exportEntity);
70+
} catch (NoSuchEntityException $e) {
71+
$this->exportRepository->delete($exportEntity);
72+
73+
throw $e;
74+
}
75+
}
76+
77+
return $exportEntity;
7078
}
7179
}

Model/Export/ExportToFile.php

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99

1010
use Magento\Framework\App\Config\ScopeConfigInterface;
1111
use Magento\Framework\Exception\FileSystemException;
12+
use Magento\Framework\Exception\NoSuchEntityException;
1213
use Magento\Framework\Exception\NotFoundException;
1314
use Magento\Store\Model\ScopeInterface;
1415
use Opengento\Gdpr\Api\Data\ExportEntityInterface;
15-
use Opengento\Gdpr\Model\Archive\MoveToArchive;
16+
use Opengento\Gdpr\Model\Archive\ArchiveManager;
1617
use Opengento\Gdpr\Service\Export\ProcessorFactory;
1718
use Opengento\Gdpr\Service\Export\RendererFactory;
1819
use function explode;
@@ -34,9 +35,9 @@ final class ExportToFile
3435
private $rendererFactory;
3536

3637
/**
37-
* @var MoveToArchive
38+
* @var ArchiveManager
3839
*/
39-
private $archive;
40+
private $archiveManager;
4041

4142
/**
4243
* @var ScopeConfigInterface
@@ -46,12 +47,12 @@ final class ExportToFile
4647
public function __construct(
4748
ProcessorFactory $processorFactory,
4849
RendererFactory $rendererFactory,
49-
MoveToArchive $archive,
50+
ArchiveManager $archiveManager,
5051
ScopeConfigInterface $scopeConfig
5152
) {
5253
$this->processorFactory = $processorFactory;
5354
$this->rendererFactory = $rendererFactory;
54-
$this->archive = $archive;
55+
$this->archiveManager = $archiveManager;
5556
$this->scopeConfig = $scopeConfig;
5657
}
5758

@@ -60,20 +61,22 @@ public function __construct(
6061
* @return string|null
6162
* @throws FileSystemException
6263
* @throws NotFoundException
64+
* @throws NoSuchEntityException
6365
*/
64-
public function export(ExportEntityInterface $exportEntity): ?string
66+
public function export(ExportEntityInterface $exportEntity): string
6567
{
66-
$exporter = $this->processorFactory->get($exportEntity->getEntityType());
6768
$fileName = $this->prepareFileName($exportEntity);
68-
$data = $exporter->execute($exportEntity->getEntityId(), []);
69+
$archiveFileName = $fileName . 'zip';
70+
$data = $this->processorFactory->get($exportEntity->getEntityType())->execute($exportEntity->getEntityId(), []);
71+
6972
foreach ($this->resolveExportRendererCodes() as $rendererCode) {
70-
$filePath = $this->archive->prepareArchive(
73+
$this->archiveManager->addToArchive(
7174
$this->rendererFactory->get($rendererCode)->saveData($fileName, $data),
72-
$fileName . '.zip'
75+
$archiveFileName
7376
);
7477
}
7578

76-
return $filePath ?? null;
79+
return $archiveFileName;
7780
}
7881

7982
public function resolveExportRendererCodes(): array

Model/ExportEntityManagement.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Exception;
1212
use Magento\Framework\App\Config\ScopeConfigInterface;
1313
use Magento\Framework\Exception\AlreadyExistsException;
14+
use Magento\Framework\Exception\NoSuchEntityException;
1415
use Magento\Framework\Phrase;
1516
use Magento\Framework\Stdlib\DateTime as DateTimeFormat;
1617
use Magento\Store\Model\ScopeInterface;

Observer/DeleteExport.php

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
/**
3+
* Copyright © OpenGento, All rights reserved.
4+
* See LICENSE bundled with this library for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Opengento\Gdpr\Observer;
9+
10+
use Exception;
11+
use Magento\Framework\Api\Filter;
12+
use Magento\Framework\Api\FilterBuilder;
13+
use Magento\Framework\Api\SearchCriteriaBuilder;
14+
use Magento\Framework\Api\SearchResultsInterface;
15+
use Magento\Framework\Event\Observer;
16+
use Magento\Framework\Event\ObserverInterface;
17+
use Magento\Framework\Exception\LocalizedException;
18+
use Magento\Framework\Model\AbstractModel;
19+
use Opengento\Gdpr\Api\Data\ExportEntityInterface;
20+
use Opengento\Gdpr\Api\Data\ExportEntitySearchResultsInterface;
21+
use Opengento\Gdpr\Api\ExportEntityRepositoryInterface;
22+
use Opengento\Gdpr\Model\Entity\EntityTypeResolver;
23+
use Psr\Log\LoggerInterface;
24+
25+
final class DeleteExport implements ObserverInterface
26+
{
27+
/**
28+
* @var ExportEntityRepositoryInterface
29+
*/
30+
private $exportRepository;
31+
32+
/**
33+
* @var SearchCriteriaBuilder
34+
*/
35+
private $criteriaBuilder;
36+
37+
/**
38+
* @var FilterBuilder
39+
*/
40+
private $filterBuilder;
41+
42+
/**
43+
* @var EntityTypeResolver
44+
*/
45+
private $entityTypeResolver;
46+
47+
/**
48+
* @var LoggerInterface
49+
*/
50+
private $logger;
51+
52+
public function __construct(
53+
ExportEntityRepositoryInterface $exportRepository,
54+
SearchCriteriaBuilder $criteriaBuilder,
55+
FilterBuilder $filterBuilder,
56+
EntityTypeResolver $entityTypeResolver,
57+
LoggerInterface $logger
58+
) {
59+
$this->exportRepository = $exportRepository;
60+
$this->criteriaBuilder = $criteriaBuilder;
61+
$this->filterBuilder = $filterBuilder;
62+
$this->entityTypeResolver = $entityTypeResolver;
63+
$this->logger = $logger;
64+
}
65+
66+
public function execute(Observer $observer): void
67+
{
68+
/** @var AbstractModel $entity */
69+
$entity = $observer->getData('data_object');
70+
71+
try {
72+
foreach ($this->fetchExportEntities($entity)->getItems() as $exportEntity) {
73+
$this->exportRepository->delete($exportEntity);
74+
}
75+
} catch (LocalizedException $e) {
76+
$this->logger->error($e->getLogMessage(), $e->getTrace());
77+
} catch (Exception $e) {
78+
$this->logger->error($e->getMessage(), $e->getTrace());
79+
}
80+
}
81+
82+
/**
83+
* @param AbstractModel $entity
84+
* @return ExportEntitySearchResultsInterface
85+
* @throws LocalizedException
86+
* @throws Exception
87+
*/
88+
private function fetchExportEntities(AbstractModel $entity): SearchResultsInterface
89+
{
90+
$entityTypes = $this->entityTypeResolver->resolve($entity);
91+
92+
foreach ($entityTypes as $entityType => $idFieldName) {
93+
$this->criteriaBuilder->addFilters([
94+
$this->createEntityIdFilter((int) $entity->getData($idFieldName)),
95+
$this->createEntityTypeFilter($entityType)
96+
]);
97+
}
98+
99+
return $this->exportRepository->getList($this->criteriaBuilder->create());
100+
}
101+
102+
private function createEntityIdFilter(int $entityId): Filter
103+
{
104+
$this->filterBuilder->setField(ExportEntityInterface::ENTITY_ID);
105+
$this->filterBuilder->setValue($entityId);
106+
$this->filterBuilder->setConditionType('eq');
107+
108+
return $this->filterBuilder->create();
109+
}
110+
111+
private function createEntityTypeFilter(string $entityType): Filter
112+
{
113+
$this->filterBuilder->setField(ExportEntityInterface::ENTITY_TYPE);
114+
$this->filterBuilder->setValue($entityType);
115+
$this->filterBuilder->setConditionType('eq');
116+
117+
return $this->filterBuilder->create();
118+
}
119+
}

Observer/InvalidateExport.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ private function fetchExportEntities(AbstractModel $entity): SearchResultsInterf
103103
$this->createEntityTypeFilter($entityType)
104104
]);
105105
}
106+
$this->criteriaBuilder->addFilter(ExportEntityInterface::EXPORTED_AT, true, 'notnull');
107+
$this->criteriaBuilder->addFilter(ExportEntityInterface::FILE_PATH, true, 'notnull');
106108

107109
return $this->exportRepository->getList($this->criteriaBuilder->create());
108110
}

0 commit comments

Comments
 (0)