Your IP : 216.73.217.13


Current Path : /var/www/magento.test.indacotrentino.com/www/app/code/Amasty/ImportCore/Import/Behavior/
Upload File :
Current File : /var/www/magento.test.indacotrentino.com/www/app/code/Amasty/ImportCore/Import/Behavior/Model.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\Behavior;

use Amasty\ImportCore\Api\Behavior\BehaviorResultInterfaceFactory;
use Amasty\ImportCore\Import\Utils\DuplicateFieldChecker;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Model\AbstractModelFactory;
use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Model\ResourceModel\Db\AbstractDb;
use Magento\Framework\ObjectManagerInterface;

abstract class Model
{
    /**
     * @var AbstractModelFactory|null
     */
    protected $modelFactory = null;

    /**
     * @var mixed
     */
    protected $repository = null;

    /**
     * @var string|null
     */
    protected $idFieldName = null;

    /**
     * @var mixed
     */
    protected $deleteCallback = null;

    /**
     * @var mixed
     */
    protected $saveCallback = null;

    /**
     * @var mixed
     */
    protected $loadCallback = null;

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

    /**
     * @var null|AbstractDb
     */
    private $insertResourceModel;

    /**
     * @var BehaviorResultInterfaceFactory
     */
    protected $resultFactory;

    /**
     * @var DuplicateFieldChecker
     */
    private $duplicateFieldChecker;

    public function __construct(
        ObjectManagerInterface $objectManager,
        BehaviorResultInterfaceFactory $behaviorResultFactory,
        DuplicateFieldChecker $duplicateFieldChecker,
        array $config
    ) {
        $this->config = $config;
        $this->modelFactory = $objectManager->get($config['modelFactory']);
        if (!method_exists($this->modelFactory, 'create')) {
            throw new \LogicException($config['modelFactory'] . ' is not a valid factory class');
        }

        if (!empty($config['insertResourceModel'])) {
            $this->insertResourceModel = $objectManager->create($config['insertResourceModel']);
        }

        if (!empty($config['repository']['class'])
            && $repositoryClass = $config['repository']['class']
        ) {
            $this->repository = $objectManager->get($repositoryClass);
        }
        $this->resultFactory = $behaviorResultFactory;
        $this->duplicateFieldChecker = $duplicateFieldChecker;
    }

    public function getIdFieldName(): string
    {
        if ($this->idFieldName === null) {
            /** @var AbstractModel $modelPrototype */
            $modelPrototype = $this->modelFactory->create();
            $this->idFieldName = $modelPrototype->getIdFieldName();
        }

        return $this->idFieldName;
    }

    private function initDelete()
    {
        if ($this->repository) {
            $deleteMethod = $this->config['repository']['deleteMethod'];
            if (method_exists($this->repository, $deleteMethod)) {
                $this->deleteCallback = [$this->repository, $deleteMethod];
            } else {
                throw new \LogicException(
                    'Repository "' . get_class($this->repository) . '" has no method "' . $deleteMethod . '"'
                );
            }
        } else {
            $this->deleteCallback = function (AbstractModel $model) {
                return $model->delete();
            };
        }
    }

    public function delete(AbstractModel $model)
    {
        if (!$this->deleteCallback) {
            $this->initDelete();
        }
        // phpcs:ignore Magento2.Functions.DiscouragedFunction
        return call_user_func($this->deleteCallback, $model);
    }

    private function initLoad()
    {
        if ($this->repository) {
            $loadMethod = $this->config['repository']['loadMethod'];
            if (method_exists($this->repository, $loadMethod)) {
                $this->loadCallback = [$this->repository, $loadMethod];
            } else {
                throw new \LogicException(
                    'Repository "' . get_class($this->repository) . '" has no method "' . $loadMethod . '"'
                );
            }
        } else {
            $this->loadCallback = function (int $id) {
                /** @var AbstractModel $model */
                $model = $this->modelFactory->create();

                return $model->load($id);
            };
        }
    }

    /**
     * @param int $id
     * @return AbstractModel|null Always returns null when entity is not found
     */
    public function load(int $id)
    {
        if (!$this->loadCallback) {
            $this->initLoad();
        }

        try {
            // phpcs:ignore Magento2.Functions.DiscouragedFunction
            $model = call_user_func($this->loadCallback, $id);
            if (!$model->getId()) {
                return null;
            }

            return $model;
        } catch (NoSuchEntityException $e) {
            return null;
        }
    }

    private function initSave()
    {
        if ($this->repository) {
            $saveMethod = $this->config['repository']['saveMethod'];
            if (method_exists($this->repository, $saveMethod)) {
                $this->saveCallback = [$this->repository, $saveMethod];
            } else {
                throw new \LogicException(
                    'Repository "' . get_class($this->repository) . '" has no method "' . $saveMethod . '"'
                );
            }
        } else {
            $this->saveCallback = function (AbstractModel $model) {
                return $model->save();
            };
        }
    }

    public function save(AbstractModel $model)
    {
        if (!$this->saveCallback) {
            $this->initSave();
        }
        // phpcs:ignore Magento2.Functions.DiscouragedFunction
        return call_user_func($this->saveCallback, $model);
    }

    public function createWithInsertResourceModel(array $row)
    {
        if (!$this->insertResourceModel) {
            return null;
        }
        /** @var AbstractModel $model */
        $insertModel = $this->modelFactory->create();
        $insertModel->setId($row[$this->getIdFieldName()]);
        $this->insertResourceModel->save($insertModel);

        return $this->load((int)$row[$this->getIdFieldName()]);
    }

    protected function updateDataIdFields(array &$data, string $customIdentifier): void
    {
        /** @var AbstractDb $resource */
        $resource = $this->modelFactory->create()->getResource();
        $connection = $resource->getConnection();
        $mainTable = $resource->getMainTable();
        $idFieldName = $this->getIdFieldName();

        $newEntityIdsSelect = $connection->select()
            ->from($mainTable, [$customIdentifier, $idFieldName])
            ->where($customIdentifier . ' IN (?)', array_column($data, $customIdentifier));
        $newEntityIds = $connection->fetchPairs($newEntityIdsSelect);

        $existingEntityIdsSelect = $connection->select()
            ->from($mainTable, [$customIdentifier, $idFieldName])
            ->where($idFieldName . ' IN (?)', array_column($data, $idFieldName));
        $existingEntityIds = $connection->fetchPairs($existingEntityIdsSelect);

        foreach ($data as &$row) {
            $currentEntityId = $row[$idFieldName] ?? 0;
            if (in_array($currentEntityId, $existingEntityIds)
                && ($newEntityIds[$currentEntityId] ?? 0) != ($existingEntityIds[$currentEntityId] ?? 0)
            ) {
                unset($row[$idFieldName]);
            }

            $newEntityId = $newEntityIds[$row[$customIdentifier]] ?? null;
            if (!empty($row[$customIdentifier]) && $newEntityId) {
                $row[$idFieldName] = $newEntityId;
            }

            $existingId = $this->duplicateFieldChecker->getDuplicateRowId($mainTable, $row);
            if ($existingId) {
                $row[$idFieldName] = $existingId;
            }
        }
    }
}