Skip to content

Commit

Permalink
Merge pull request #7748 from magento-performance/ACPT-6
Browse files Browse the repository at this point in the history
ACPT-6: Improve Data Import Performance
  • Loading branch information
vzabaznov authored Aug 5, 2022
2 parents c6aeb6a + e393b30 commit 0d04908
Show file tree
Hide file tree
Showing 11 changed files with 360 additions and 125,841 deletions.
77 changes: 21 additions & 56 deletions app/code/Magento/ImportExport/Model/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Magento\Framework\HTTP\Adapter\FileTransferFactory;
use Magento\Framework\Indexer\IndexerRegistry;
use Magento\Framework\Math\Random;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\Stdlib\DateTime\DateTime;
use Magento\ImportExport\Helper\Data as DataHelper;
use Magento\ImportExport\Model\Export\Adapter\CsvFactory;
Expand All @@ -29,11 +30,10 @@
use Magento\ImportExport\Model\Import\Entity\Factory;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingError;
use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface;
use Magento\Framework\Message\ManagerInterface;
use Magento\ImportExport\Model\ResourceModel\Import\Data;
use Magento\ImportExport\Model\Source\Import\AbstractBehavior;
use Magento\ImportExport\Model\Source\Import\Behavior\Factory as BehaviorFactory;
use Magento\MediaStorage\Model\File\Uploader;
use Magento\ImportExport\Model\Source\Upload;
use Magento\MediaStorage\Model\File\UploaderFactory;
use Psr\Log\LoggerInterface;

Expand Down Expand Up @@ -122,6 +122,7 @@ class Import extends AbstractModel
protected $_entityAdapter;

/**
* @Deprecated Property isn't used
* @var DataHelper
*/
protected $_importExportData = null;
Expand Down Expand Up @@ -152,6 +153,7 @@ class Import extends AbstractModel
protected $_csvFactory;

/**
* @Deprecated Property isn't used
* @var FileTransferFactory
*/
protected $_httpFactory;
Expand Down Expand Up @@ -192,10 +194,16 @@ class Import extends AbstractModel
private $messageManager;

/**
* @Deprecated Property isn't used
* @var Random
*/
private $random;

/**
* @var Upload
*/
private $upload;

/**
* @param LoggerInterface $logger
* @param Filesystem $filesystem
Expand All @@ -214,6 +222,7 @@ class Import extends AbstractModel
* @param array $data
* @param ManagerInterface|null $messageManager
* @param Random|null $random
* @param Upload|null $upload
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
Expand All @@ -233,7 +242,8 @@ public function __construct(
DateTime $localeDate,
array $data = [],
ManagerInterface $messageManager = null,
Random $random = null
Random $random = null,
Upload $upload = null
) {
$this->_importExportData = $importExportData;
$this->_coreConfig = $coreConfig;
Expand All @@ -252,6 +262,8 @@ public function __construct(
->get(ManagerInterface::class);
$this->random = $random ?: ObjectManager::getInstance()
->get(Random::class);
$this->upload = $upload ?: ObjectManager::getInstance()
->get(Upload::class);
parent::__construct($logger, $filesystem, $data);
}

Expand Down Expand Up @@ -303,6 +315,8 @@ protected function _getEntityAdapter()
/**
* Returns source adapter object.
*
* @Deprecated
* @see \Magento\ImportExport\Model\Import\Source\Factory::create()
* @param string $sourceFile Full path to source file
* @return AbstractSource
* @throws FileSystemException
Expand Down Expand Up @@ -550,61 +564,12 @@ public function getErrorAggregator()
*/
public function uploadSource()
{
/** @var $adapter \Zend_File_Transfer_Adapter_Http */
$adapter = $this->_httpFactory->create();
if (!$adapter->isValid(self::FIELD_NAME_SOURCE_FILE)) {
$errors = $adapter->getErrors();
if ($errors[0] == \Zend_Validate_File_Upload::INI_SIZE) {
$errorMessage = $this->_importExportData->getMaxUploadSizeMessage();
} else {
$errorMessage = __('The file was not uploaded.');
}
throw new LocalizedException($errorMessage);
}

$entity = $this->getEntity();
/** @var $uploader Uploader */
$uploader = $this->_uploaderFactory->create(['fileId' => self::FIELD_NAME_SOURCE_FILE]);
$uploader->setAllowedExtensions(['csv', 'zip']);
$uploader->skipDbProcessing(true);
$fileName = $this->random->getRandomString(32) . '.' . $uploader->getFileExtension();
try {
$result = $uploader->save($this->getWorkingDir(), $fileName);
} catch (\Exception $e) {
throw new LocalizedException(__('The file cannot be uploaded.'));
}

$extension = '';
$uploadedFile = '';
if ($result !== false) {
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$extension = pathinfo($result['file'], PATHINFO_EXTENSION);
$uploadedFile = $result['path'] . $result['file'];
}

if (!$extension) {
$this->_varDirectory->delete($uploadedFile);
throw new LocalizedException(__('The file you uploaded has no extension.'));
}
$sourceFile = $this->getWorkingDir() . $entity;

$sourceFile .= '.' . $extension;
$result = $this->upload->uploadSource($entity);
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$extension = pathinfo($result['file'], PATHINFO_EXTENSION);
$sourceFile = $this->getWorkingDir() . $entity . '.' . $extension;
$sourceFileRelative = $this->_varDirectory->getRelativePath($sourceFile);

if (strtolower($uploadedFile) != strtolower($sourceFile)) {
if ($this->_varDirectory->isExist($sourceFileRelative)) {
$this->_varDirectory->delete($sourceFileRelative);
}

try {
$this->_varDirectory->renameFile(
$this->_varDirectory->getRelativePath($uploadedFile),
$sourceFileRelative
);
} catch (FileSystemException $e) {
throw new LocalizedException(__('The source file moving process failed.'));
}
}
$this->_removeBom($sourceFile);
$this->createHistoryReport($sourceFileRelative, $entity, $extension, $result);
return $sourceFile;
Expand Down
10 changes: 6 additions & 4 deletions app/code/Magento/ImportExport/Model/Import/Adapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
namespace Magento\ImportExport\Model\Import;

use Magento\Framework\Filesystem\Directory\Write;
use Magento\ImportExport\Model\Import\Source\Factory;

/**
* Import adapter model
*
* @Deprecated
* @see \Magento\ImportExport\Model\Import\Source\Factory
* @author Magento Core Team <core@magentocommerce.com>
*/
class Adapter
Expand All @@ -23,7 +25,7 @@ class Adapter
* @param mixed $options OPTIONAL Adapter constructor options
*
* @return AbstractSource
*
* phpcs:disable Magento2.Functions.StaticFunction
* @throws \Magento\Framework\Exception\LocalizedException
*/
public static function factory($type, $directory, $source, $options = null)
Expand Down Expand Up @@ -56,11 +58,11 @@ public static function factory($type, $directory, $source, $options = null)
* @param string $source Source file path.
* @param Write $directory
* @param mixed $options OPTIONAL Adapter constructor options
*
* phpcs:disable Magento2.Functions.StaticFunction
* @return AbstractSource
*/
public static function findAdapterFor($source, $directory, $options = null)
{
return self::factory(pathinfo($source, PATHINFO_EXTENSION), $directory, $source, $options);
return self::factory(pathinfo($source, PATHINFO_EXTENSION), $directory, $source, $options); // phpcs:ignore
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\ImportExport\Model\Import\Source;

use Magento\ImportExport\Model\Import\AbstractSource;

class Base64EncodedCsvData extends AbstractSource
{
/**
* @var array
*/
private $rows;

/**
* @var string
*/
private $delimiter = ',';

/**
* Read Data and detect column names
*
* @param string $file
*/
public function __construct(string $file)
{
// phpcs:ignore Magento2.Functions.DiscouragedFunction
$source = trim(base64_decode($file));
$rowsData = preg_split("/\r\n|\n|\r/", $source);
$colNames = explode($this->delimiter, $rowsData[0]);
$this->rows = array_splice($rowsData, 1);
parent::__construct($colNames);
}

/**
* Read next line from CSV data
*
* @return array
*/
public function _getNextRow()
{
if ($this->_key===count($this->rows)) {
return [];
}
$parsed =str_getcsv($this->rows[$this->_key], ',', '"');
if (is_array($parsed) && count($parsed) != $this->_colQty) {
foreach ($parsed as $element) {
if ($element && strpos($element, "'") !== false) {
$this->_foundWrongQuoteFlag = true;
break;
}
}
} else {
$this->_foundWrongQuoteFlag = false;
}
return is_array($parsed) ? $parsed : [];
}
}
71 changes: 71 additions & 0 deletions app/code/Magento/ImportExport/Model/Import/Source/Factory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\ImportExport\Model\Import\Source;

use Magento\Framework\Filesystem\Directory\Write;
use Magento\Framework\ObjectManagerInterface;
use Magento\ImportExport\Model\Import\AbstractSource;

class Factory
{
/**
* Object Manager Instance
*
* @var \Magento\Framework\ObjectManagerInterface
*/
private $objectManager;

/**
* @param ObjectManagerInterface $objectManager
*/
public function __construct(
ObjectManagerInterface $objectManager
) {
$this->objectManager = $objectManager;
}

/**
* Create class instance with specified parameters
*
* @param string $source
* @param Write $directory
* @param mixed $options
* @return AbstractSource
* @phpcs:disable Magento2.Functions.DiscouragedFunction
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function create($source, $directory = null, $options = null): AbstractSource
{
$adapterClass = 'Magento\ImportExport\Model\Import\Source\\';
if (file_exists($source)) {
$type = ucfirst(strtolower(pathinfo($source, PATHINFO_EXTENSION)));
} else {
$type = 'Base64EncodedCsvData';
}
if (!is_string($source) || !$source) {
throw new \Magento\Framework\Exception\LocalizedException(
__('The source type must be a non-empty string.')
);
}
$adapterClass.= $type;
if (!class_exists($adapterClass)) {
throw new \Magento\Framework\Exception\LocalizedException(
__('\'%1\' file extension is not supported', $type)
);
}
return $this->objectManager->create(
$adapterClass,
[
'file' => $source,
'directory' => $directory,
'options' => $options
]
);
}
}
Loading

0 comments on commit 0d04908

Please sign in to comment.