Your IP : 216.73.216.220


Current Path : /var/www/www.indacotrentino.com/www/app/code/Amasty/ImportCore/Import/Source/Type/Csv/
Upload File :
Current File : /var/www/www.indacotrentino.com/www/app/code/Amasty/ImportCore/Import/Source/Type/Csv/Reader.php

<?php

declare(strict_types=1);

/**
 * @author Amasty Team
 * @copyright Copyright (c) Amasty (https://www.amasty.com)
 * @package Import Core for Magento 2 (System)
 */

namespace Amasty\ImportCore\Import\Source\Type\Csv;

use Amasty\ImportCore\Api\ImportProcessInterface;
use Amasty\ImportCore\Api\Source\SourceReaderInterface;
use Amasty\ImportCore\Import\FileResolver\FileResolverAdapter;
use Amasty\ImportCore\Import\Source\Data\DataStructureProvider;
use Amasty\ImportCore\Import\Source\Utils\FileRowToArrayConverter;
use Amasty\ImportCore\Import\Source\Utils\HeaderStructureProcessor;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\File\ReadInterface as FileReader;

class Reader implements SourceReaderInterface
{
    public const TYPE_ID = 'csv';

    /**
     * @var FileReader
     */
    private $fileReader;

    /**
     * @var ConfigInterface
     */
    private $config;

    /**
     * @var FileResolverAdapter
     */
    private $fileResolverAdapter;

    /**
     * @var Filesystem
     */
    private $filesystem;

    /**
     * @var DataStructureProvider
     */
    private $dataStructureProvider;

    /**
     * @var FileRowToArrayConverter
     */
    private $fileRowToArrayConverter;

    /**
     * @var HeaderStructureProcessor
     */
    private $headerStructureProcessor;

    /**
     * @var array
     */
    protected $headerStructure;

    /**
     * Storage for next row if 'merge row' setting is disabled
     * @var array
     */
    protected $nextRow;

    public function __construct(
        FileResolverAdapter $fileResolverAdapter,
        Filesystem $filesystem,
        DataStructureProvider $dataStructureProvider,
        FileRowToArrayConverter $fileRowToArrayConverter,
        HeaderStructureProcessor $headerStructureProcessor
    ) {
        $this->fileResolverAdapter = $fileResolverAdapter;
        $this->filesystem = $filesystem;
        $this->dataStructureProvider = $dataStructureProvider;
        $this->fileRowToArrayConverter = $fileRowToArrayConverter;
        $this->headerStructureProcessor = $headerStructureProcessor;
    }

    public function initialize(ImportProcessInterface $importProcess)
    {
        $fileName = $this->fileResolverAdapter->getFileResolver(
            $importProcess->getProfileConfig()->getFileResolverType()
        )->execute($importProcess);
        $this->config = $importProcess->getProfileConfig()->getExtensionAttributes()->getCsvSource();

        $directoryRead = $this->filesystem->getDirectoryRead(DirectoryList::ROOT);
        $this->fileReader = $directoryRead->openFile($fileName);

        $dataStructure = $this->dataStructureProvider->getDataStructure(
            $importProcess->getEntityConfig(),
            $importProcess->getProfileConfig()
        );
        $this->headerStructure = $this->headerStructureProcessor->getHeaderStructure(
            $dataStructure,
            $this->readCsvRow(),
            $this->config->getPrefix()
        );
    }

    public function readRow()
    {
        if (!$this->nextRow) {
            $rowData = $this->readCsvRow();
        } else {
            $rowData = $this->nextRow;
        }

        if (!is_array($rowData)) {
            return false;
        }
        $rowData = $this->fileRowToArrayConverter->convertRowToHeaderStructure(
            $this->headerStructure,
            $rowData
        );

        if ($this->config->isCombineChildRows()) {
            $rowData = $this->fileRowToArrayConverter->formatMergedSubEntities(
                $rowData,
                $this->headerStructure,
                $this->config->getChildRowSeparator()
            );
        } else {
            $rowData = $this->checkAndMergeSubEntities($rowData);
        }

        return $rowData;
    }

    public function estimateRecordsCount(): int
    {
        $rows = 0;
        $filePosition = $this->fileReader->tell();
        while (!$this->fileReader->eof()) {
            if (!$this->readAndValidateEntityRow()) {
                break;
            }

            $rows++;
        }

        $this->clearNextRowCache();
        $this->fileReader->seek($filePosition);

        return $rows;
    }

    protected function readCsvRow()
    {
        do {
            $rowData = $this->fileReader->readCsv(
                $this->config->getMaxLineLength(),
                $this->config->getSeparator(),
                $this->config->getEnclosure()
            );
            if (!is_array($rowData)) {
                return false;
            }

            foreach ($this->headerStructureProcessor->getColNumbersToSkip() as $key) {
                unset($rowData[$key]);
            }
        } while ($this->isRowEmpty($rowData));

        return array_values($rowData);
    }

    protected function checkAndMergeSubEntities(array $currentRow)
    {
        $this->nextRow = $this->readCsvRow();

        if (!$this->isNextRowValidForMergeProcessing()) {
            return $currentRow;
        }

        do {
            $nextRow = $this->fileRowToArrayConverter->convertRowToHeaderStructure(
                $this->headerStructure,
                $this->nextRow
            );

            $currentRow = $this->fileRowToArrayConverter->mergeRows(
                $currentRow,
                $nextRow,
                $this->headerStructure
            );
            $this->nextRow = $this->readCsvRow();
        } while ($this->isNextRowValidForMergeProcessing());

        return $currentRow;
    }

    private function readAndValidateEntityRow(): bool
    {
        if (!$this->nextRow) {
            $rowData = $this->readCsvRow();
        } else {
            $rowData = $this->nextRow;
        }

        if (!is_array($rowData)) {
            return false;
        }

        if (!$this->config->isCombineChildRows()) {
            $this->readSubEntitiesRow();
        }

        return true;
    }

    /**
     * Reads the next line of data.
     * Used to move the pointer in the file to the next row of entity data
     *
     * @return void
     */
    private function readSubEntitiesRow(): void
    {
        $this->nextRow = $this->readCsvRow();

        if (!$this->isNextRowValidForMergeProcessing()) {
            return;
        }

        do {
            $this->nextRow = $this->readCsvRow();
        } while ($this->isNextRowValidForMergeProcessing());
    }

    private function clearNextRowCache()
    {
        $this->nextRow = null;
    }

    private function isNextRowValidForMergeProcessing(): bool
    {
        if (!is_array($this->nextRow)) {
            return false;
        }

        $row = $this->fileRowToArrayConverter->convertRowToHeaderStructure(
            $this->headerStructure,
            $this->nextRow
        );
        foreach ($row as $value) {
            if (!is_array($value) && !empty($value)) {
                return false;
            }
        }

        return true;
    }

    private function isRowEmpty(array $row): bool
    {
        return empty(array_filter($row));
    }
}