Skip to content

Commit

Permalink
Merge pull request #52 from aligent/feature/export_improvements
Browse files Browse the repository at this point in the history
Feature/export improvements
  • Loading branch information
aligent-lturner authored Nov 22, 2024
2 parents 01bae5e + cc6736b commit 7b94906
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 71 deletions.
95 changes: 95 additions & 0 deletions src/export/Controller/Adminhtml/Exports/Data.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);
namespace Aligent\FredhopperExport\Controller\Adminhtml\Exports;

use Aligent\FredhopperExport\Api\Data\ExportInterface;
use Aligent\FredhopperExport\Model\Data\Export;
use Aligent\FredhopperExport\Model\Data\ExportFactory;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export as ExportResource;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\App\Response\Http\FileFactory;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Filesystem\Io\File as Filesystem;
use Psr\Log\LoggerInterface;

class Data extends Action
{

public const string ADMIN_RESOURCE = 'Aligent_FredhopperExport::manage';

/**
* @param Context $context
* @param ExportFactory $exportFactory
* @param ExportResource $exportResource
* @param FileFactory $fileFactory
* @param LoggerInterface $logger
* @param Filesystem $filesystem
*/
public function __construct(
readonly Context $context,
private readonly ExportFactory $exportFactory,
private readonly ExportResource $exportResource,
private readonly FileFactory $fileFactory,
private readonly LoggerInterface $logger,
private readonly Filesystem $filesystem
) {
parent::__construct($context);
}

/**
* @inheritDoc
*/
public function execute(): ResponseInterface
{
$exportId = (int)$this->getRequest()->getParam('id');
if (empty($exportId)) {
$this->getMessageManager()->addErrorMessage(__('Export ID is required.'));
$this->_redirect('*/*/index');
return $this->_response;
}
$isZip = (bool)$this->getRequest()->getParam('zip');
/** @var Export $export */
$export = $this->exportFactory->create();
$this->exportResource->load($export, $exportId);
if ($export->isEmpty()) {
$this->getMessageManager()->addErrorMessage(__('Could not load export data.'));
$this->_redirect('*/*/index');
return $this->_response;
}
$directory = $export->getDirectory();
$filename = match ($export->getExportType()) {
ExportInterface::EXPORT_TYPE_INCREMENTAL => ExportInterface::ZIP_FILENAME_INCREMENTAL,
ExportInterface::EXPORT_TYPE_FULL => ExportInterface::ZIP_FILENAME_FULL,
ExportInterface::EXPORT_TYPE_SUGGEST => ExportInterface::ZIP_FILENAME_SUGGEST,
default => ''
};
if (empty($filename)) {
$this->getMessageManager()->addErrorMessage(__('Could not download data file.'));
$this->_redirect('*/*/index');
return $this->_response;
}

$filename = $directory . DIRECTORY_SEPARATOR . $filename;
$name = $this->filesystem->getPathInfo($filename)['basename'] ?? $filename;
try {
return $this->fileFactory->create(
$name,
[
'type' => 'filename',
'value' => $filename,
'rm' => false
],
DirectoryList::VAR_DIR,
'application/zip'
);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
$this->getMessageManager()->addErrorMessage(__('Could not download data file.'));
$this->_redirect('*/*/index');
return $this->_response;
}
}
}
8 changes: 8 additions & 0 deletions src/export/Cron/Generate/Suggest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,19 @@

class Suggest
{
/**
* @param GenerateSuggestExport $generateSuggestExport
*/
public function __construct(
private readonly GenerateSuggestExport $generateSuggestExport
) {
}

/**
* Generate a suggest export
*
* @return void
*/
public function execute(): void
{
$this->generateSuggestExport->execute();
Expand Down
9 changes: 8 additions & 1 deletion src/export/Cron/Trigger.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use Aligent\FredhopperExport\Api\Data\ExportInterface;
use Aligent\FredhopperExport\Model\Data\Export;
use Aligent\FredhopperExport\Model\GetExportIsInProgress;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\Collection;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\CollectionFactory;
use Aligent\FredhopperExport\Model\TriggerDataLoad;
Expand All @@ -14,10 +15,12 @@ class Trigger
/**
* @param CollectionFactory $exportCollectionFactory
* @param TriggerDataLoad $triggerDataLoad
* @param GetExportIsInProgress $getExportIsInProgress
*/
public function __construct(
private readonly CollectionFactory $exportCollectionFactory,
private readonly TriggerDataLoad $triggerDataLoad
private readonly TriggerDataLoad $triggerDataLoad,
private readonly GetExportIsInProgress $getExportIsInProgress
) {
}

Expand All @@ -28,6 +31,10 @@ public function __construct(
*/
public function execute(): void
{
// don't trigger if an export has already been triggered
if ($this->getExportIsInProgress->execute(true)) {
return;
}
/** @var Collection $collection */
$collection = $this->exportCollectionFactory->create();
$collection->addFieldToFilter(ExportInterface::FIELD_STATUS, ExportInterface::STATUS_UPLOADED);
Expand Down
39 changes: 4 additions & 35 deletions src/export/Cron/UpdateInvalidExports.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,16 @@
declare(strict_types=1);
namespace Aligent\FredhopperExport\Cron;

use Aligent\FredhopperExport\Api\Data\ExportInterface;
use Aligent\FredhopperExport\Model\Data\Export;
use Aligent\FredhopperExport\Model\Data\GetCurrentExportedVersion;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export as ExportResource;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\Collection;
use Aligent\FredhopperExport\Model\InvalidateExports;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\CollectionFactory;
use Psr\Log\LoggerInterface;

class UpdateInvalidExports
{
/**
* @param CollectionFactory $collectionFactory
* @param GetCurrentExportedVersion $getCurrentExportedVersion
* @param ExportResource $exportResource
* @param LoggerInterface $logger
* @param InvalidateExports $invalidateExports
*/
public function __construct(
private readonly CollectionFactory $collectionFactory,
private readonly GetCurrentExportedVersion $getCurrentExportedVersion,
private readonly ExportResource $exportResource,
private readonly LoggerInterface $logger
private readonly InvalidateExports $invalidateExports,
) {
}

Expand All @@ -34,26 +23,6 @@ public function __construct(
*/
public function execute(): void
{
$currentExportedVersion = $this->getCurrentExportedVersion->execute();

/** @var Collection $collection */
$collection = $this->collectionFactory->create();
// need to check pending and uploaded exports only
$collection->addFieldToFilter(ExportInterface::FIELD_STATUS, ExportInterface::STATUS_PENDING);
$collection->addFieldToFilter(ExportInterface::FIELD_EXPORT_TYPE, ExportInterface::EXPORT_TYPE_INCREMENTAL);
/** @var Export[] $exports */
$exports = $collection->getItems();
foreach ($exports as $export) {
// mark incremental update as invalid if a more recent export has been uploaded already
if ($currentExportedVersion > $export->getVersionId()) {
$export->setStatus(ExportInterface::STATUS_INVALID);
try {
$this->exportResource->save($export);
} catch (\Exception $e) {
$message = sprintf('Error updating status of export %i', $export->getExportId());
$this->logger->error($message, ['exception' => $e]);
}
}
}
$this->invalidateExports->execute();
}
}
31 changes: 25 additions & 6 deletions src/export/Cron/Upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

use Aligent\FredhopperExport\Api\Data\ExportInterface;
use Aligent\FredhopperExport\Model\Data\Export;
use Aligent\FredhopperExport\Model\Data\GetCurrentExportedVersion;
use Aligent\FredhopperExport\Model\GetExportIsInProgress;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\Collection;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\CollectionFactory;
use Aligent\FredhopperExport\Model\UploadExport;
Expand All @@ -14,10 +16,14 @@ class Upload
/**
* @param CollectionFactory $collectionFactory
* @param UploadExport $uploadExport
* @param GetExportIsInProgress $getExportIsInProgress
* @param GetCurrentExportedVersion $getCurrentExportedVersion
*/
public function __construct(
private readonly CollectionFactory $collectionFactory,
private readonly UploadExport $uploadExport
private readonly UploadExport $uploadExport,
private readonly GetExportIsInProgress $getExportIsInProgress,
private readonly GetCurrentExportedVersion $getCurrentExportedVersion
) {
}

Expand All @@ -28,13 +34,26 @@ public function __construct(
*/
public function execute(): void
{
// don't upload any export when an export is in progress
if ($this->getExportIsInProgress->execute()) {
return;
}
/** @var Collection $collection */
$collection = $this->collectionFactory->create();
$collection->addFieldToFilter('status', ExportInterface::STATUS_PENDING);
/** @var Export[] $exports */
$exports = $collection->getItems();
foreach ($exports as $export) {
$this->uploadExport->execute($export);
$collection->addFieldToFilter(ExportInterface::FIELD_STATUS, ExportInterface::STATUS_PENDING);
// do not upload any export behind the current version
$currentVersion = $this->getCurrentExportedVersion->execute();
if ($currentVersion > 0) {
$collection->addFieldToFilter(ExportInterface::FIELD_VERSION_ID, ['gt' => $currentVersion]);
}
// order by the version number descending to get the latest export
$collection->setOrder(ExportInterface::FIELD_VERSION_ID);
// we only ever want to upload a single export. Trying to upload multiple at once could prove troublesome
/** @var ExportInterface $firstExport */
$firstExport = $collection->getFirstItem();
if (!$firstExport->isEmpty()) {
/** @var Export $export */
$this->uploadExport->execute($firstExport);
}
}
}
1 change: 1 addition & 0 deletions src/export/Model/DownloadQualityReport.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function execute(string $directory, string $triggerId, bool $isSummary):
}
} catch (FileSystemException $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
return null;
}

$qualityReportData = $this->dataIntegrationClient->getDataQualityReport($triggerId, $isSummary);
Expand Down
5 changes: 3 additions & 2 deletions src/export/Model/GenerateSuggestExport.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public function execute(): void

// create directory
$directory = $this->createDirectory->execute(ExportInterface::EXPORT_TYPE_SUGGEST);
$export->setDirectory($directory);

// create all required files
$files = [];
Expand All @@ -74,13 +75,13 @@ public function execute(): void
$files
);
if (!$zipCreated) {
throw new LocalizedException(__('Error while creating ZIP file.'));
throw new LocalizedException(__(__METHOD__ . ': Error while creating ZIP file.'));
}

// save export
$this->exportResource->save($export);
} catch (\Exception $e) {
$this->logger->error($e->getMessage(), ['exception' => $e]);
$this->logger->error(__METHOD__ . ': ' . $e->getMessage(), ['exception' => $e]);
}
}
}
41 changes: 41 additions & 0 deletions src/export/Model/GetExportIsInProgress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);
namespace Aligent\FredhopperExport\Model;

use Aligent\FredhopperExport\Api\Data\ExportInterface;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\Collection;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\CollectionFactory;

class GetExportIsInProgress
{
private const array IN_PROGRESS_STATUSES = [
ExportInterface::STATUS_UPLOADED,
ExportInterface::STATUS_TRIGGERED
];

/**
* @param CollectionFactory $collectionFactory
*/
public function __construct(
private readonly CollectionFactory $collectionFactory
) {
}

/**
* Check if there is already an export in uploaded/triggered status.
*
* If $triggeredOnly is true, only check for triggered status
*
* @param bool $triggeredOnly
* @return bool
*/
public function execute(bool $triggeredOnly = false): bool
{
/** @var Collection $collection */
$collection = $this->collectionFactory->create();
$statusesToCheck = $triggeredOnly ? [ExportInterface::STATUS_TRIGGERED] : self::IN_PROGRESS_STATUSES;
$collection->addFieldToFilter('status', ['in' => self::IN_PROGRESS_STATUSES]);
return $collection->getSize() > 0;
}
}
59 changes: 59 additions & 0 deletions src/export/Model/InvalidateExports.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);
namespace Aligent\FredhopperExport\Model;

use Aligent\FredhopperExport\Api\Data\ExportInterface;
use Aligent\FredhopperExport\Model\Data\Export;
use Aligent\FredhopperExport\Model\Data\GetCurrentExportedVersion;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export as ExportResource;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\Collection;
use Aligent\FredhopperExport\Model\ResourceModel\Data\Export\CollectionFactory;
use Psr\Log\LoggerInterface;

class InvalidateExports
{
/**
* @param CollectionFactory $collectionFactory
* @param GetCurrentExportedVersion $getCurrentExportedVersion
* @param ExportResource $exportResource
* @param LoggerInterface $logger
*/
public function __construct(
private readonly CollectionFactory $collectionFactory,
private readonly GetCurrentExportedVersion $getCurrentExportedVersion,
private readonly ExportResource $exportResource,
private readonly LoggerInterface $logger
) {
}

/**
* Update the status of pending exports
*
* @return void
*/
public function execute(): void
{
$currentExportedVersion = $this->getCurrentExportedVersion->execute();

/** @var Collection $collection */
$collection = $this->collectionFactory->create();
// need to check pending and uploaded exports only
$collection->addFieldToFilter(ExportInterface::FIELD_STATUS, ExportInterface::STATUS_PENDING);
$collection->addFieldToFilter(ExportInterface::FIELD_EXPORT_TYPE, ExportInterface::EXPORT_TYPE_INCREMENTAL);
/** @var Export[] $exports */
$exports = $collection->getItems();
foreach ($exports as $export) {
// mark incremental update as invalid if a more recent export has been uploaded already
if ($currentExportedVersion > $export->getVersionId()) {
$export->setStatus(ExportInterface::STATUS_INVALID);
try {
$this->exportResource->save($export);
} catch (\Exception $e) {
$message = sprintf('Error updating status of export %i', $export->getExportId());
$this->logger->error($message, ['exception' => $e]);
}
}
}
}
}
Loading

0 comments on commit 7b94906

Please sign in to comment.