Your IP : 216.73.216.158


Current Path : /home/rtorresani/www/app/code/Amasty/ImportCore/Model/EntityManager/
Upload File :
Current File : //home/rtorresani/www/app/code/Amasty/ImportCore/Model/EntityManager/SequenceHandler.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\Model\EntityManager;

use Magento\Framework\App\ResourceConnection;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\EntityManager\Sequence\SequenceManager;
use Magento\Framework\EntityManager\Sequence\SequenceRegistry;

class SequenceHandler
{
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;

    /**
     * @var SequenceManager
     */
    private $sequenceManager;

    /**
     * @var SequenceRegistry
     */
    private $sequenceRegistry;

    /**
     * @var MetadataPool
     */
    private $metadataPool;

    public function __construct(
        ResourceConnection $resourceConnection,
        SequenceManager $sequenceManager,
        SequenceRegistry $sequenceRegistry,
        MetadataPool $metadataPool
    ) {
        $this->resourceConnection = $resourceConnection;
        $this->sequenceManager = $sequenceManager;
        $this->sequenceRegistry = $sequenceRegistry;
        $this->metadataPool = $metadataPool;
    }

    /**
     * Adds/generates sequence values for new entities creation
     *
     * @param array $data
     * @param string $entityType
     * @throws \Exception
     */
    public function handleNew(array &$data, string $entityType)
    {
        if (!$this->getSequenceInfo($entityType)) {
            return;
        }
        $metadata = $this->metadataPool->getMetadata($entityType);
        $identifierField = $metadata->getIdentifierField();

        $existingSeqValues = $this->getSequenceValues($data, $entityType);
        foreach ($data as &$row) {
            if (isset($row[$identifierField])
                && !in_array($row[$identifierField], $existingSeqValues)
            ) {
                $this->sequenceManager->force(
                    $entityType,
                    $row[$identifierField]
                );
            } else {
                $id = $metadata->generateIdentifier();
                if ($id) {
                    $row[$identifierField] = $id;
                }
            }
        }
    }

    /**
     * Adds/generates sequence values for new entities creation or exiting entities update
     *
     * @param array $data
     * @param string $entityType
     * @throws \Exception
     */
    public function handleNewOrUpdate(array &$data, string $entityType)
    {
        if (!$this->getSequenceInfo($entityType)) {
            return;
        }
        $metadata = $this->metadataPool->getMetadata($entityType);
        $identifierField = $metadata->getIdentifierField();
        $linkField = $metadata->getLinkField();

        $existingEntries = $this->getEntityEntries($data, $entityType);
        $existingSeqValues = $this->getSequenceValues($data, $entityType);

        foreach ($data as &$row) {
            if (isset($row[$linkField]) && in_array($row[$linkField], $existingEntries)) { // update
                if (isset($row[$identifierField])
                    && !in_array($row[$identifierField], $existingSeqValues)
                ) {
                    $this->sequenceManager->force(
                        $entityType,
                        $row[$identifierField]
                    );
                }
            } else { // new
                if (isset($row[$linkField])
                    && isset($row[$identifierField])
                    && !in_array($row[$identifierField], $existingSeqValues)
                ) {
                    $this->sequenceManager->force(
                        $entityType,
                        $row[$identifierField]
                    );
                } else {
                    $id = $metadata->generateIdentifier();
                    if ($id) {
                        $row[$identifierField] = $id;
                    }
                }
            }
        }
    }

    /**
     * Adds sequence values for exiting entities update
     *
     * @param array $data
     * @param string $entityType
     * @throws \Exception
     */
    public function handleUpdate(array &$data, string $entityType)
    {
        if (!$this->getSequenceInfo($entityType)) {
            return;
        }
        $metadata = $this->metadataPool->getMetadata($entityType);
        $identifierField = $metadata->getIdentifierField();

        $existingSeqValues = $this->getSequenceValues($data, $entityType);
        foreach ($data as $row) {
            if (isset($row[$identifierField])
                && !in_array($row[$identifierField], $existingSeqValues)
            ) {
                $this->sequenceManager->force(
                    $entityType,
                    $row[$identifierField]
                );
            }
        }
    }

    /**
     * Get existing entity entries
     *
     * @param array $data
     * @param string $entityType
     * @return array
     * @throws \Exception
     */
    private function getEntityEntries(array $data, string $entityType): array
    {
        $connection = $this->resourceConnection->getConnection();
        $metadata = $this->metadataPool->getMetadata($entityType);
        $identifier = $metadata->getLinkField();

        $select = $connection->select()
            ->from($metadata->getEntityTable(), [$identifier])
            ->where($identifier . ' IN (?)', array_column($data, $identifier));

        return $connection->fetchCol($select);
    }

    /**
     * Get existing sequence values
     *
     * @param array $data
     * @param string $entityType
     * @return array
     * @throws \Exception
     */
    private function getSequenceValues(array $data, string $entityType): array
    {
        $connection = $this->resourceConnection->getConnection();
        $sequenceInfo = $this->sequenceRegistry->retrieve($entityType);
        $metadata = $this->metadataPool->getMetadata($entityType);

        $select = $connection->select()
            ->from(
                $this->resourceConnection->getTableName($sequenceInfo['sequenceTable']),
                ['sequence_value']
            )->where(
                'sequence_value' . ' IN (?)',
                array_column($data, $metadata->getIdentifierField())
            );

        return $connection->fetchCol($select);
    }

    private function getSequenceInfo(string $entityType)
    {
        $this->metadataPool->getMetadata($entityType);

        return $this->sequenceRegistry->retrieve($entityType) ?
            $this->sequenceRegistry->retrieve($entityType)['sequence'] : null;
    }
}