From 6a406e5e38a25ce3f69b00aab9a3ccc838849a8e Mon Sep 17 00:00:00 2001 From: Rodrigue Millard Date: Thu, 14 May 2020 10:28:41 +0200 Subject: [PATCH 1/7] scalability-product-import: Modify family filters and product import to launch one per imported family --- Block/Adminhtml/Import.php | 13 ++ .../Command/AkeneoConnectorImportCommand.php | 39 ++++- Controller/Adminhtml/Import/Run.php | 6 +- Controller/Adminhtml/Import/RunProduct.php | 94 ++++++++++++ Helper/ProductFilters.php | 39 ++++- Job/Product.php | 138 ++++++++++++++++-- view/adminhtml/templates/import.phtml | 59 ++++---- view/adminhtml/web/js/akeneo_connector.js | 52 ++++++- 8 files changed, 394 insertions(+), 46 deletions(-) create mode 100644 Controller/Adminhtml/Import/RunProduct.php diff --git a/Block/Adminhtml/Import.php b/Block/Adminhtml/Import.php index 9bdaa7a7..988db5ea 100644 --- a/Block/Adminhtml/Import.php +++ b/Block/Adminhtml/Import.php @@ -84,9 +84,12 @@ public function _toHtml() { /** @var string $runUrl */ $runUrl = $this->_getRunUrl(); + /** @var string $runProductUrl */ + $runProductUrl = $this->_getRunProductUrl(); $this->assign( [ + 'runProductUrl' => $this->_escaper->escapeHtml($runProductUrl), 'runUrl' => $this->_escaper->escapeHtml($runUrl), ] ); @@ -103,4 +106,14 @@ public function _getRunUrl() { return $this->urlModel->getUrl('akeneo_connector/import/run'); } + + /** + * Retrieve run URL + * + * @return string + */ + public function _getRunProductUrl() + { + return $this->urlModel->getUrl('akeneo_connector/import/runProduct'); + } } diff --git a/Console/Command/AkeneoConnectorImportCommand.php b/Console/Command/AkeneoConnectorImportCommand.php index d19a5fb2..9e93d31e 100755 --- a/Console/Command/AkeneoConnectorImportCommand.php +++ b/Console/Command/AkeneoConnectorImportCommand.php @@ -32,6 +32,12 @@ class AkeneoConnectorImportCommand extends Command * @var string IMPORT_CODE */ const IMPORT_CODE = 'code'; + /** + * This constant contains a string + * + * @var string IMPORT_CODE_PRODUCT + */ + const IMPORT_CODE_PRODUCT = 'product'; /** * This variable contains a State * @@ -98,7 +104,6 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - /** * Check if multiple entities have been specified * in the command line @@ -154,8 +159,40 @@ protected function import(string $code, OutputInterface $output) return false; } + // If product import, run the import once per family + /** @var array $productFamiliesToImport */ + $productFamiliesToImport = []; + if ($code == self::IMPORT_CODE_PRODUCT) { + $productFamiliesToImport = $import->getFamiliesToImport(); + foreach ($productFamiliesToImport as $family) { + $this->runImport($import, $output, $family); + $import->setIdentifier(null); + } + + return true; + } + + // Run the import normaly + $this->runImport($import, $output); + + return true; + } + + /** + * Run the import + * + * @param Import $import + * @param OutputInterface $output + * @param null|string $family + * + * @return void + */ + protected function runImport(Import $import, OutputInterface $output, $family = null) { try { $import->setStep(0); + if ($family) { + $import->setFamily($family); + } while ($import->canExecute()) { /** @var string $comment */ diff --git a/Controller/Adminhtml/Import/Run.php b/Controller/Adminhtml/Import/Run.php index d7184522..5748f819 100644 --- a/Controller/Adminhtml/Import/Run.php +++ b/Controller/Adminhtml/Import/Run.php @@ -79,7 +79,8 @@ public function execute() $code = $request->getParam('code'); /** @var string $identifier */ $identifier = $request->getParam('identifier'); - + /** @var string $family */ + $family = $request->getParam('family'); /** @var Import $import */ $import = $this->importRepository->getByCode($code); @@ -92,6 +93,9 @@ public function execute() $import->setIdentifier($identifier)->setStep($step)->setSetFromAdmin(true); + if ($family) { + $import->setFamily($family); + } /** @var array $response */ $response = $import->execute(); diff --git a/Controller/Adminhtml/Import/RunProduct.php b/Controller/Adminhtml/Import/RunProduct.php new file mode 100644 index 00000000..02a2b026 --- /dev/null +++ b/Controller/Adminhtml/Import/RunProduct.php @@ -0,0 +1,94 @@ + + * @copyright 2020 Agence Dn'D + * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) + * @link https://www.dnd.fr/ + */ +class RunProduct extends Action +{ + /** + * This variable contains an OutputHelper + * + * @var OutputHelper $outputHelper + */ + protected $outputHelper; + /** + * This variable contains an ImportRepositoryInterface + * + * @var ImportRepositoryInterface $importRepository + */ + protected $importRepository; + /** + * This variable contains a ArrayToJsonResponseConverter + * + * @var ArrayToJsonResponseConverter $arrayToJsonResponseConverter + */ + protected $arrayToJsonResponseConverter; + /** + * This variable contains a JobProduct + * + * @var JobProduct $jobProduct + */ + protected $jobProduct; + + /** + * Run constructor. + * + * @param Context $context + * @param ImportRepositoryInterface $importRepository + * @param OutputHelper $output + * @param ArrayToJsonResponseConverter $arrayToJsonResponseConverter + * @param JobProduct $jobProduct + */ + public function __construct( + Context $context, + ImportRepositoryInterface $importRepository, + OutputHelper $output, + ArrayToJsonResponseConverter $arrayToJsonResponseConverter, + JobProduct $jobProduct + ) { + parent::__construct($context); + + $this->outputHelper = $output; + $this->importRepository = $importRepository; + $this->arrayToJsonResponseConverter = $arrayToJsonResponseConverter; + $this->jobProduct = $jobProduct; + } + + /** + * Action triggered by request + * + * @return Json + */ + public function execute() + { + /** @var string[] $families */ + $families = $this->jobProduct->getFamiliesToImport(); + return $this->arrayToJsonResponseConverter->convert($families); + } + + /** + * {@inheritdoc} + */ + protected function _isAllowed() + { + return $this->_authorization->isAllowed('Akeneo_Connector::import'); + } +} diff --git a/Helper/ProductFilters.php b/Helper/ProductFilters.php index 639100a1..2f705e62 100644 --- a/Helper/ProductFilters.php +++ b/Helper/ProductFilters.php @@ -72,9 +72,11 @@ public function __construct( /** * Get the filters for the product API query * + * @param string|null $productFamily + * * @return mixed[]|string[] */ - public function getFilters() + public function getFilters($productFamily = null) { /** @var mixed[] $mappedChannels */ $mappedChannels = $this->configHelper->getMappedChannels(); @@ -91,12 +93,38 @@ public function getFilters() $filters = []; /** @var mixed[] $search */ $search = []; - + /** @var $productFilterAdded */ + $productFilterAdded = false; /** @var string $mode */ $mode = $this->configHelper->getFilterMode(); if ($mode == Mode::ADVANCED) { /** @var mixed[] $advancedFilters */ $advancedFilters = $this->getAdvancedFilters(); + // If product import gave a family, add it to the filter + if ($productFamily) { + if (isset($advancedFilters['search']['family'])) { + /** + * @var int $key + * @var string[] $familyFilter + */ + foreach ($advancedFilters['search']['family'] as $key => $familyFilter) { + if (isset($familyFilter['operator']) && $familyFilter['operator'] == 'IN') { + $advancedFilters['search']['family'][$key]['value'][] = $productFamily; + $productFilterAdded = true; + + break; + } + } + } + + if (!$productFilterAdded) { + /** @var string[] $familyFilter */ + $familyFilter = ['operator' => 'IN', 'value' => [$productFamily]]; + $advancedFilters['search']['family'][] = $familyFilter; + $productFilterAdded = true; + } + } + if (!empty($advancedFilters['scope'])) { if (!in_array($advancedFilters['scope'], $mappedChannels)) { /** @var string[] $error */ @@ -121,6 +149,13 @@ public function getFilters() $search = $this->searchBuilder->getFilters(); } + // If import product gave a family, add this family to the search + if ($productFamily && !$productFilterAdded) { + $familyFilter = ['operator' => 'IN', 'value' => [$productFamily]]; + $search['family'][] = $familyFilter; + $productFilterAdded = true; + } + /** @var string $channel */ foreach ($mappedChannels as $channel) { /** @var string[] $filter */ diff --git a/Job/Product.php b/Job/Product.php index b500bdbd..282b4961 100644 --- a/Job/Product.php +++ b/Job/Product.php @@ -14,6 +14,7 @@ use Akeneo\Connector\Job\Option as JobOption; use Akeneo\Connector\Job\Import as JobImport; use Akeneo\Connector\Model\Source\Attribute\Metrics as AttributeMetrics; +use Akeneo\Connector\Model\Source\Filters\Mode; use Akeneo\Pim\ApiClient\Pagination\PageInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; use Magento\Catalog\Model\Category as CategoryModel; @@ -76,12 +77,19 @@ class Product extends JobImport * @var Entities $entities */ protected $entities; + /** + * This variable contains a string + * + * @var string $step + */ + protected $family = null; /** * This variable contains a string value * * @var string $name */ protected $name = 'Product'; + /** * Akeneo default association types, reformatted as column names * @@ -306,8 +314,30 @@ public function createTable() return; } + // Stop the import if the family is not imported + if ($this->getFamily()) { + /** @var AdapterInterface $connection */ + $connection = $this->entitiesHelper->getConnection(); + /** @var string $connectorEntitiesTable */ + $connectorEntitiesTable = $this->entities->getTable($this->entities::TABLE_NAME); + /** @var bool $isFamilyImported */ + $isFamilyImported = (bool)$connection->fetchOne( + $connection->select() + ->from($connectorEntitiesTable, ['code']) + ->where('code = ?', $this->getFamily()) + ->limit(1) + ); + + if (!$isFamilyImported) { + $this->setMessage(__('The family %1 is not imported yet, please run Family import.', $this->getFamily())); + $this->stop(true); + + return; + } + } + /** @var mixed[] $filters */ - $filters = $this->getFilters(); + $filters = $this->getFilters($this->getFamily()); $filters = reset($filters); /** @var PageInterface $products */ $products = $this->akeneoClient->getProductApi()->listPerPage(1, false, $filters); @@ -315,13 +345,17 @@ public function createTable() $products = $products->getItems(); $product = reset($products); if (empty($products)) { - $this->setMessage(__('No results from Akeneo')); + $this->setMessage(__('No results from Akeneo for the family: %1', $this->getFamily())); $this->stop(true); return; } $this->entitiesHelper->createTmpTableFromApi($product, $this->getCode()); + + /** @var string $message */ + $message = __('Family imported in this batch: %1', $this->getFamily()); + $this->setMessage($message); } /** @@ -336,7 +370,7 @@ public function insertData() /** @var int $index */ $index = 0; /** @var mixed[] $filters */ - $filters = $this->getFilters(); + $filters = $this->getFilters($this->getFamily()); /** @var mixed[] $metricsConcatSettings */ $metricsConcatSettings = $this->configHelper->getMetricsColumns(null, true); /** @var string[] $metricSymbols */ @@ -2501,19 +2535,97 @@ public function cleanCache() * * @return mixed[] */ - protected function getFilters() + protected function getFilters($family = null) { - if (empty($this->filters)) { - /** @var mixed[] $filters */ - $filters = $this->productFilters->getFilters(); - if (array_key_exists('error', $filters)) { - $this->setMessage($filters['error']); - $this->stop(true); - } - - $this->filters = $filters; + /** @var mixed[] $filters */ + $filters = $this->productFilters->getFilters($family); + if (array_key_exists('error', $filters)) { + $this->setMessage($filters['error']); + $this->stop(true); } + $this->filters = $filters; + return $this->filters; } + + /** + * Get the families to imported based on the config + * + * @return array + */ + public function getFamiliesToImport() + { + if (!$this->akeneoClient) { + $this->akeneoClient = $this->getAkeneoClient(); + } + /** @var string[] $families */ + $families = []; + /** @var string[] $apiFamilies */ + $apiFamilies = $this->akeneoClient->getFamilyApi()->all(); + /** @var mixed[] $family */ + foreach ($apiFamilies as $family) { + if (!isset($family['code'])) { + continue; + } + $families[] = $family['code']; + } + /** @var string $mode */ + $mode = $this->configHelper->getFilterMode(); + if ($mode == Mode::ADVANCED) { + /** @var string[] $filters */ + $filters = $this->configHelper->getAdvancedFilters(); + if (isset($advancedFilters['search']['family'])) { + foreach ($advancedFilters['search']['family'] as $key => $familyFilter) { + if (isset($familyFilter['operator']) && $familyFilter['operator'] == 'NOT IN') { + foreach ($familyFilter['value'] as $familyToRemove) { + if (($familyKey = array_search($familyFilter, $families)) !== false) { + unset($families[$familyKey]); + } + } + } + } + } + } + if ($mode == Mode::STANDARD) { + /** @var mixed $filter */ + $familiesFilter = $this->configHelper->getFamiliesFilter(); + if ($familiesFilter) { + $familiesFilter = explode(',', $familiesFilter); + foreach ($familiesFilter as $familyFilter) { + if (($key = array_search($familyFilter, $families)) !== false) { + unset($families[$key]); + } + } + } + } + + $families = array_values($families); + + return $families; + } + + /** + * Set current family + * + * @param string $family + * + * @return Import + */ + public function setFamily($family) + { + $this->family = $family; + + return $this; + } + + /** + * Get current family + * + * @return string + */ + public function getFamily() + { + return $this->family; + } } diff --git a/view/adminhtml/templates/import.phtml b/view/adminhtml/templates/import.phtml index 5c3b95e6..ec7679c5 100644 --- a/view/adminhtml/templates/import.phtml +++ b/view/adminhtml/templates/import.phtml @@ -8,43 +8,52 @@ /** * @var string $runUrl + * @var string $runProductUrl * @var \Akeneo\Connector\Block\Adminhtml\Import $block */ ?>
-
-

-
- getCollection() ?> - - - isAllowed($import->getCode())): ?> -
- getName() ?> -
- - -
+
+

+
+ getCollection() ?> + + + isAllowed($import->getCode())): ?> +
+ getName() ?> +
+ +
-
-
+
+ -
+ +
diff --git a/view/adminhtml/web/js/akeneo_connector.js b/view/adminhtml/web/js/akeneo_connector.js index 1049eaa3..653fe594 100644 --- a/view/adminhtml/web/js/akeneo_connector.js +++ b/view/adminhtml/web/js/akeneo_connector.js @@ -14,18 +14,26 @@ define(['jquery'], function ($) { type: null, step: 0, runUrl: null, + runProductUrl: null, console: null, - identifier: null + identifier: null, + currentFamily: null, + familyCount: 0, + families: null }, - init: function (url, console) { + init: function (url, urlProduct, console) { this.options.runUrl = url; + this.options.runProductUrl = urlProduct; this.console = $(console); }, type: function (type, object) { this.options.type = type; this.step('type', $(object)); + this.options.currentFamily = null; + this.options.familyCount = null; + this.options.families = null; }, step: function (type, object) { @@ -50,8 +58,32 @@ define(['jquery'], function ($) { object.addClass('active'); }, - run: function () { + runProduct: function () { var akeneoConnector = this; + $.ajax({ + url: akeneoConnector.options.runProductUrl, + type: 'post', + context: this, + data: { + 'identifier': akeneoConnector.options.identifier + }, + success: function (response) { + akeneoConnector.options.families = response; + akeneoConnector.run(akeneoConnector); + } + }); + }, + + run: function (context = null) { + var akeneoConnector = this; + + if (context != null) { + var akeneoConnector = context; + } + + if (akeneoConnector.options.currentFamily == null && akeneoConnector.options.families != null && akeneoConnector.options.families.length > 1) { + akeneoConnector.options.currentFamily = akeneoConnector.options.families[0]; + } akeneoConnector.disabledImport(true); @@ -63,7 +95,8 @@ define(['jquery'], function ($) { data: { 'code': akeneoConnector.options.type, 'step': akeneoConnector.options.step, - 'identifier': akeneoConnector.options.identifier + 'identifier': akeneoConnector.options.identifier, + 'family': akeneoConnector.options.currentFamily }, success: function (response) { akeneoConnector.removeWaiting(); @@ -90,6 +123,17 @@ define(['jquery'], function ($) { akeneoConnector.run(); } + if (!response.continue && akeneoConnector.options.type == "product") { + akeneoConnector.options.identifier = null; + akeneoConnector.options.step = 0; + akeneoConnector.options.familyCount++; + + if (akeneoConnector.options.families != null && akeneoConnector.options.families.hasOwnProperty(akeneoConnector.options.familyCount)) { + akeneoConnector.options.currentFamily = akeneoConnector.options.families[akeneoConnector.options.familyCount]; + akeneoConnector.run(); + } + } + akeneoConnector.console.scrollTop(100000); } }); From 085986f9b4da91dccd9f9b7524c24dd8e3b6d68b Mon Sep 17 00:00:00 2001 From: Rodrigue Millard Date: Mon, 18 May 2020 15:58:30 +0200 Subject: [PATCH 2/7] product-model-filters: Add basic filters to product model import --- Helper/ProductFilters.php | 52 +++++++++++++++++++++++++++++++++++++++ Job/ProductModel.php | 45 +++++++++++++++++++++++++++++++-- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/Helper/ProductFilters.php b/Helper/ProductFilters.php index 639100a1..b5b00007 100644 --- a/Helper/ProductFilters.php +++ b/Helper/ProductFilters.php @@ -166,6 +166,58 @@ public function getFilters() return $filters; } + + /** + * Get the filters for the product model API query + * + * @return mixed[]|string[] + */ + public function getModelFilters() + { + /** @var mixed[] $mappedChannels */ + $mappedChannels = $this->configHelper->getMappedChannels(); + if (empty($mappedChannels)) { + /** @var string[] $error */ + $error = [ + 'error' => __('No website/channel mapped. Please check your configurations.'), + ]; + + return $error; + } + + /** @var mixed[] $filters */ + $filters = []; + /** @var mixed[] $search */ + $search = []; + + /** @var string $channel */ + foreach ($mappedChannels as $channel) { + /** @var string[] $filter */ + $filter = [ + 'search' => $search, + 'scope' => $channel, + ]; + + /** @var string[] $locales */ + $locales = $this->storeHelper->getChannelStoreLangs($channel); + if (!empty($locales)) { + /** @var string $locales */ + $akeneoLocales = $this->localesHelper->getAkeneoLocales(); + if (!empty($akeneoLocales)) { + $locales = array_intersect($locales, $akeneoLocales); + } + + /** @var string $locales */ + $locales = implode(',', $locales); + $filter['locales'] = $locales; + } + + $filters[] = $filter; + } + + return $filters; + } + /** * Retrieve advanced filters config * diff --git a/Job/ProductModel.php b/Job/ProductModel.php index 5035e73a..84f9344b 100644 --- a/Job/ProductModel.php +++ b/Job/ProductModel.php @@ -2,6 +2,7 @@ namespace Akeneo\Connector\Job; +use Akeneo\Connector\Helper\ProductFilters; use Akeneo\Connector\Model\Source\Attribute\Metrics as AttributeMetrics; use Akeneo\Pim\ApiClient\Pagination\PageInterface; use Akeneo\Pim\ApiClient\Pagination\ResourceCursorInterface; @@ -39,6 +40,12 @@ class ProductModel extends Import * @var string $name */ protected $name = 'Product Model'; + /** + * This variable contains product filters + * + * @var mixed[] $filters + */ + protected $filters; /** * This variable contains an EntitiesHelper * @@ -63,6 +70,12 @@ class ProductModel extends Import * @var AttributeMetrics $attributeMetrics */ protected $attributeMetrics; + /** + * This variable contains a ProductFilters + * + * @var ProductFilters $productFilters + */ + protected $productFilters; /** * ProductModel constructor @@ -73,6 +86,7 @@ class ProductModel extends Import * @param \Akeneo\Connector\Helper\Import\Product $entitiesHelper * @param ConfigHelper $configHelper * @param Config $eavConfig + * @param ProductFilters $productFilters * @param AttributeMetrics $attributeMetrics * @param array $data */ @@ -83,6 +97,7 @@ public function __construct( \Akeneo\Connector\Helper\Import\Product $entitiesHelper, ConfigHelper $configHelper, Config $eavConfig, + ProductFilters $productFilters, AttributeMetrics $attributeMetrics, array $data = [] ) { @@ -91,6 +106,7 @@ public function __construct( $this->entitiesHelper = $entitiesHelper; $this->configHelper = $configHelper; $this->eavConfig = $eavConfig; + $this->productFilters = $productFilters; $this->attributeMetrics = $attributeMetrics; } @@ -101,8 +117,11 @@ public function __construct( */ public function createTable() { + /** @var mixed[] $filters */ + $filters = $this->getFilters(); + $filters = reset($filters); /** @var PageInterface $productModels */ - $productModels = $this->akeneoClient->getProductModelApi()->listPerPage(1); + $productModels = $this->akeneoClient->getProductModelApi()->listPerPage(1, false, $filters); /** @var array $productModel */ $productModel = $productModels->getItems(); if (empty($productModel)) { @@ -122,10 +141,13 @@ public function createTable() */ public function insertData() { + /** @var mixed[] $filters */ + $filters = $this->getFilters(); + $filters = reset($filters); /** @var string|int $paginationSize */ $paginationSize = $this->configHelper->getPanigationSize(); /** @var ResourceCursorInterface $productModels */ - $productModels = $this->akeneoClient->getProductModelApi()->all($paginationSize); + $productModels = $this->akeneoClient->getProductModelApi()->all($paginationSize, $filters); /** @var string[] $attributeMetrics */ $attributeMetrics = $this->attributeMetrics->getMetricsAttributes(); @@ -409,4 +431,23 @@ protected function getEntityTypeId() return $productEntityTypeId; } + + /** + * Retrieve product filters + * + * @return mixed[] + */ + protected function getFilters() + { + /** @var mixed[] $filters */ + $filters = $this->productFilters->getModelFilters(); + if (array_key_exists('error', $filters)) { + $this->setMessage($filters['error']); + $this->stop(true); + } + + $this->filters = $filters; + + return $this->filters; + } } From 713f008ec558e88e2d874e49ddf65c962df5316c Mon Sep 17 00:00:00 2001 From: Rodrigue Millard Date: Mon, 18 May 2020 16:39:20 +0200 Subject: [PATCH 3/7] product-model-filters: Remove search array from product model filter and correct iteration of filters during product model import --- Helper/ProductFilters.php | 3 -- Job/ProductModel.php | 96 ++++++++++++++++++++------------------- 2 files changed, 49 insertions(+), 50 deletions(-) diff --git a/Helper/ProductFilters.php b/Helper/ProductFilters.php index b5b00007..12109a81 100644 --- a/Helper/ProductFilters.php +++ b/Helper/ProductFilters.php @@ -187,14 +187,11 @@ public function getModelFilters() /** @var mixed[] $filters */ $filters = []; - /** @var mixed[] $search */ - $search = []; /** @var string $channel */ foreach ($mappedChannels as $channel) { /** @var string[] $filter */ $filter = [ - 'search' => $search, 'scope' => $channel, ]; diff --git a/Job/ProductModel.php b/Job/ProductModel.php index 84f9344b..4e549b3c 100644 --- a/Job/ProductModel.php +++ b/Job/ProductModel.php @@ -143,69 +143,71 @@ public function insertData() { /** @var mixed[] $filters */ $filters = $this->getFilters(); - $filters = reset($filters); /** @var string|int $paginationSize */ $paginationSize = $this->configHelper->getPanigationSize(); - /** @var ResourceCursorInterface $productModels */ - $productModels = $this->akeneoClient->getProductModelApi()->all($paginationSize, $filters); - - /** @var string[] $attributeMetrics */ - $attributeMetrics = $this->attributeMetrics->getMetricsAttributes(); - /** @var mixed[] $metricsConcatSettings */ - $metricsConcatSettings = $this->configHelper->getMetricsColumns(null, true); - /** @var string[] $metricSymbols */ - $metricSymbols = $this->getMetricsSymbols(); - - /** - * @var int $index - * @var array $productModel - */ - foreach ($productModels as $index => $productModel) { - foreach ($attributeMetrics as $attributeMetric) { - if (!isset($productModel['values'][$attributeMetric])) { - continue; - } + /** @var mixed[] $filter */ + foreach ($filters as $filter) { + /** @var ResourceCursorInterface $productModels */ + $productModels = $this->akeneoClient->getProductModelApi()->all($paginationSize, $filter); + + /** @var string[] $attributeMetrics */ + $attributeMetrics = $this->attributeMetrics->getMetricsAttributes(); + /** @var mixed[] $metricsConcatSettings */ + $metricsConcatSettings = $this->configHelper->getMetricsColumns(null, true); + /** @var string[] $metricSymbols */ + $metricSymbols = $this->getMetricsSymbols(); - foreach ($productModel['values'][$attributeMetric] as $key => $metric) { - /** @var string|float $amount */ - $amount = $metric['data']['amount']; - if ($amount != null) { - $amount = floatval($amount); + /** + * @var int $index + * @var array $productModel + */ + foreach ($productModels as $index => $productModel) { + foreach ($attributeMetrics as $attributeMetric) { + if (!isset($productModel['values'][$attributeMetric])) { + continue; } - $productModel['values'][$attributeMetric][$key]['data']['amount'] = $amount; - } - } + foreach ($productModel['values'][$attributeMetric] as $key => $metric) { + /** @var string|float $amount */ + $amount = $metric['data']['amount']; + if ($amount != null) { + $amount = floatval($amount); + } - /** - * @var mixed[] $metricsConcatSetting - */ - foreach ($metricsConcatSettings as $metricsConcatSetting) { - if (!isset($productModel['values'][$metricsConcatSetting])) { - continue; + $productModel['values'][$attributeMetric][$key]['data']['amount'] = $amount; + } } /** - * @var int $key - * @var mixed[] $metric + * @var mixed[] $metricsConcatSetting */ - foreach ($productModel['values'][$metricsConcatSetting] as $key => $metric) { - /** @var string $unit */ - $unit = $metric['data']['unit']; - /** @var string|false $symbol */ - $symbol = array_key_exists($unit, $metricSymbols); - - if (!$symbol) { + foreach ($metricsConcatSettings as $metricsConcatSetting) { + if (!isset($productModel['values'][$metricsConcatSetting])) { continue; } - $productModel['values'][$metricsConcatSetting][$key]['data']['amount'] .= ' ' . $metricSymbols[$unit]; + /** + * @var int $key + * @var mixed[] $metric + */ + foreach ($productModel['values'][$metricsConcatSetting] as $key => $metric) { + /** @var string $unit */ + $unit = $metric['data']['unit']; + /** @var string|false $symbol */ + $symbol = array_key_exists($unit, $metricSymbols); + + if (!$symbol) { + continue; + } + + $productModel['values'][$metricsConcatSetting][$key]['data']['amount'] .= ' ' . $metricSymbols[$unit]; + } } - } - $this->entitiesHelper->insertDataFromApi($productModel, $this->getCode()); + $this->entitiesHelper->insertDataFromApi($productModel, $this->getCode()); + } + $index++; } - $index++; $this->setMessage( __('%1 line(s) found', $index) ); From cb0681068cba6f21badc6a0c5cd0aaadfe92721e Mon Sep 17 00:00:00 2001 From: Rodrigue Millard Date: Mon, 18 May 2020 16:55:41 +0200 Subject: [PATCH 4/7] product-model-filters: Move global declaration out of the foreach --- Job/ProductModel.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Job/ProductModel.php b/Job/ProductModel.php index 4e549b3c..7ffec109 100644 --- a/Job/ProductModel.php +++ b/Job/ProductModel.php @@ -145,18 +145,18 @@ public function insertData() $filters = $this->getFilters(); /** @var string|int $paginationSize */ $paginationSize = $this->configHelper->getPanigationSize(); + /** @var string[] $attributeMetrics */ + $attributeMetrics = $this->attributeMetrics->getMetricsAttributes(); + /** @var mixed[] $metricsConcatSettings */ + $metricsConcatSettings = $this->configHelper->getMetricsColumns(null, true); + /** @var string[] $metricSymbols */ + $metricSymbols = $this->getMetricsSymbols(); + /** @var mixed[] $filter */ foreach ($filters as $filter) { /** @var ResourceCursorInterface $productModels */ $productModels = $this->akeneoClient->getProductModelApi()->all($paginationSize, $filter); - /** @var string[] $attributeMetrics */ - $attributeMetrics = $this->attributeMetrics->getMetricsAttributes(); - /** @var mixed[] $metricsConcatSettings */ - $metricsConcatSettings = $this->configHelper->getMetricsColumns(null, true); - /** @var string[] $metricSymbols */ - $metricSymbols = $this->getMetricsSymbols(); - /** * @var int $index * @var array $productModel From 8e7aa4609242b8d35666cf10754f903cfd7849af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verri=C3=A8re?= Date: Wed, 27 May 2020 10:57:07 +0200 Subject: [PATCH 5/7] scalability-product: Fix import launch when no family are found --- Console/Command/AkeneoConnectorImportCommand.php | 8 ++++++++ Controller/Adminhtml/Import/RunProduct.php | 5 +++++ i18n/de_DE.csv | 3 ++- i18n/en_US.csv | 3 ++- i18n/fr_FR.csv | 3 ++- view/adminhtml/web/js/akeneo_connector.js | 11 ++++++++--- 6 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Console/Command/AkeneoConnectorImportCommand.php b/Console/Command/AkeneoConnectorImportCommand.php index 9e93d31e..fc414e56 100755 --- a/Console/Command/AkeneoConnectorImportCommand.php +++ b/Console/Command/AkeneoConnectorImportCommand.php @@ -164,6 +164,14 @@ protected function import(string $code, OutputInterface $output) $productFamiliesToImport = []; if ($code == self::IMPORT_CODE_PRODUCT) { $productFamiliesToImport = $import->getFamiliesToImport(); + + if (!count($productFamiliesToImport)) { + $message = __('No family to import'); + $this->displayError($message, $output); + + return false; + } + foreach ($productFamiliesToImport as $family) { $this->runImport($import, $output, $family); $import->setIdentifier(null); diff --git a/Controller/Adminhtml/Import/RunProduct.php b/Controller/Adminhtml/Import/RunProduct.php index 02a2b026..df641cc4 100644 --- a/Controller/Adminhtml/Import/RunProduct.php +++ b/Controller/Adminhtml/Import/RunProduct.php @@ -81,6 +81,11 @@ public function execute() { /** @var string[] $families */ $families = $this->jobProduct->getFamiliesToImport(); + + if (!count($families)) { + $families['message'] = __('No family to import'); + } + return $this->arrayToJsonResponseConverter->convert($families); } diff --git a/i18n/de_DE.csv b/i18n/de_DE.csv index 005570d3..a977b953 100755 --- a/i18n/de_DE.csv +++ b/i18n/de_DE.csv @@ -154,4 +154,5 @@ Zum Beispiel :
"Metric Attributes","Metrikverwaltung" "Akeneo Metric Attribute","Akeneo Metrikattribut" "Used As Variant","Als Variante verwenden" -"Concat Metric Unit","Metrische Einheit zum Wert hinzufügen" \ No newline at end of file +"Concat Metric Unit","Metrische Einheit zum Wert hinzufügen" +"No family to import","Keine Familie zu importieren" \ No newline at end of file diff --git a/i18n/en_US.csv b/i18n/en_US.csv index a7ece3ed..3bebe9ab 100755 --- a/i18n/en_US.csv +++ b/i18n/en_US.csv @@ -154,4 +154,5 @@ For example :
"Metric Attributes","Metric Attributes" "Akeneo Metric Attribute","Akeneo Metric Attribute" "Used As Variant","Used As Variant" -"Concat Metric Unit","Add metric unit to value" \ No newline at end of file +"Concat Metric Unit","Add metric unit to value" +"No family to import","No family to import" \ No newline at end of file diff --git a/i18n/fr_FR.csv b/i18n/fr_FR.csv index 354b91c0..43e6d081 100755 --- a/i18n/fr_FR.csv +++ b/i18n/fr_FR.csv @@ -154,4 +154,5 @@ Par exemple :
"Metric Attributes","Attributs Métriques" "Akeneo Metric Attribute","Attribut métrique Akeneo" "Used As Variant","Utiliser comme Variante" -"Concat Metric Unit","Ajouter l'unité métrique à la valeur" \ No newline at end of file +"Concat Metric Unit","Ajouter l'unité métrique à la valeur" +"No family to import","Aucune famille à importer" \ No newline at end of file diff --git a/view/adminhtml/web/js/akeneo_connector.js b/view/adminhtml/web/js/akeneo_connector.js index 653fe594..fc6a3104 100644 --- a/view/adminhtml/web/js/akeneo_connector.js +++ b/view/adminhtml/web/js/akeneo_connector.js @@ -68,8 +68,13 @@ define(['jquery'], function ($) { 'identifier': akeneoConnector.options.identifier }, success: function (response) { - akeneoConnector.options.families = response; - akeneoConnector.run(akeneoConnector); + if (response.message) { + akeneoConnector.disabledImport(true); + akeneoConnector.listElement(response.message, 'error'); + } else { + akeneoConnector.options.families = response; + akeneoConnector.run(akeneoConnector); + } } }); }, @@ -81,7 +86,7 @@ define(['jquery'], function ($) { var akeneoConnector = context; } - if (akeneoConnector.options.currentFamily == null && akeneoConnector.options.families != null && akeneoConnector.options.families.length > 1) { + if (akeneoConnector.options.currentFamily == null && akeneoConnector.options.families != null && akeneoConnector.options.families.length >= 1) { akeneoConnector.options.currentFamily = akeneoConnector.options.families[0]; } From db8b083e64be72cc9b67fc8525ebcd6d454aad33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verri=C3=A8re?= Date: Wed, 27 May 2020 11:07:13 +0200 Subject: [PATCH 6/7] all: Add version 100.4.6 changelogs --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b92bbdf..28373b14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,4 +93,8 @@ * Fix metric option creation when a value is set on a product model specific attribute * Fix metric value set to "0" when empty on Akeneo * Fix website association not deleted when website attribute value is empty for a product -* Optimize deletion of akeneo_connector_product_model columns during product model import job \ No newline at end of file +* Optimize deletion of akeneo_connector_product_model columns during product model import job + +### Version 100.4.6 : +* Add product import job batching family after family (https://help.akeneo.com/magento2-connector/v100/articles/overview.html#product-import-process) +* Optimize product model column number in temporary table by adding filter for API request on mapped channels and available locales \ No newline at end of file From 3363d62f88cbef73d6ed78c5438e21d8120cbf3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verri=C3=A8re?= Date: Wed, 27 May 2020 11:08:26 +0200 Subject: [PATCH 7/7] all: Bump composer.json version to 100.4.6 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 2eba46ff..8cb3dbca 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "php-http/guzzle6-adapter": "^1.1" }, "type": "magento2-module", - "version": "100.4.5", + "version": "100.4.6", "license": [ "OSL-3.0", "AFL-3.0"