Your IP : 216.73.216.43


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

use Amasty\ImportCore\Api\Behavior\BehaviorResultInterface;
use Amasty\ImportCore\Api\Config\Profile\EntitiesConfigInterface;
use Amasty\ImportCore\Api\Config\ProfileConfigInterface;
use Amasty\ImportCore\Import\Config\RelationConfigProvider;
use Amasty\ImportCore\Import\Source\SourceDataStructure;

class BehaviorApplier
{
    public const SYNC_BEHAVIORS_TO_SKIP = [
        'delete',
        'delete_direct'
    ];

    /**
     * @var BehaviorProvider
     */
    private $behaviorProvider;

    /**
     * @var RelationConfigProvider
     */
    private $relationConfigProvider;

    /**
     * @var SynchronizationProcessor
     */
    private $synchronizationProcessor;

    /**
     * @var array
     */
    private $behaviorResults = [];

    public function __construct(
        BehaviorProvider $behaviorProvider,
        RelationConfigProvider $relationConfigProvider,
        SynchronizationProcessor $synchronizationProcessor
    ) {
        $this->behaviorProvider = $behaviorProvider;
        $this->relationConfigProvider = $relationConfigProvider;
        $this->synchronizationProcessor = $synchronizationProcessor;
    }

    public function apply(array &$data, ProfileConfigInterface $profileConfig): array
    {
        $this->behaviorResults = [];
        $profileEntitiesConfig = $profileConfig->getEntitiesConfig();

        $behavior = $this->behaviorProvider->getBehavior(
            $profileEntitiesConfig->getEntityCode(),
            $profileEntitiesConfig->getBehavior()
        );
        $result = $behavior->execute($data, $profileConfig->getEntityIdentifier());
        $this->behaviorResults[$profileEntitiesConfig->getEntityCode()] = $result;

        if ($result->getAffectedIds()) {
            $this->executeSubEntities($profileEntitiesConfig, $data, $result->getAffectedIds());
            $this->processBehaviorResults($profileEntitiesConfig);
        }

        return $this->behaviorResults;
    }

    private function executeSubEntities(
        EntitiesConfigInterface $entitiesConfig,
        array &$data,
        array $parentIds
    ): void {
        foreach ($data as $index => &$row) {
            if (!isset($row[SourceDataStructure::SUB_ENTITIES_DATA_KEY])) {
                continue;
            }
            $rowSubEntities = &$row[SourceDataStructure::SUB_ENTITIES_DATA_KEY];

            foreach ($entitiesConfig->getSubEntitiesConfig() as $subEntityConfig) {
                if (!isset($rowSubEntities[$subEntityConfig->getEntityCode()])) {
                    continue;
                }
                $parentEntityCode = $entitiesConfig->getEntityCode();
                $childEntityCode = $subEntityConfig->getEntityCode();

                $this->updateRelationFields(
                    $parentEntityCode,
                    $childEntityCode,
                    $rowSubEntities,
                    $parentIds,
                    $index
                );
                $this->synchronizationProcessor->setOrigIds(
                    $childEntityCode,
                    $rowSubEntities[$childEntityCode]
                );

                $behavior = $this->behaviorProvider->getBehavior(
                    $childEntityCode,
                    $subEntityConfig->getBehavior(),
                    true
                );
                $subEntityResult = $behavior->execute($rowSubEntities[$childEntityCode]);

                if (isset($this->behaviorResults[$childEntityCode])) {
                    $subEntityResult->merge($this->behaviorResults[$childEntityCode]);
                }
                $this->behaviorResults[$childEntityCode] = $subEntityResult;

                if (!in_array($entitiesConfig->getBehavior(), self::SYNC_BEHAVIORS_TO_SKIP)) {
                    $this->synchronizationProcessor->processSynchronizations(
                        $row,
                        $childEntityCode,
                        $this->behaviorResults
                    );
                }

                if (!empty($subEntityConfig->getSubEntitiesConfig())) {
                    $this->executeSubEntities(
                        $subEntityConfig,
                        $rowSubEntities[$childEntityCode],
                        $subEntityResult->getAffectedIds()
                    );
                }
            }
        }
    }

    private function updateRelationFields(
        string $parentEntityCode,
        string $childEntityCode,
        array &$rowSubEntities,
        array $parentIds,
        int $index
    ): void {
        $relationConfig = $this->relationConfigProvider->getExact(
            $parentEntityCode,
            $childEntityCode
        );
        // TODO: replace isSkipRelationFieldsUpdate() method to behavior's getAffectedIds() with autoincrement field
        if ($relationConfig && !$relationConfig->isSkipRelationFieldsUpdate()) {
            $childFieldName = $relationConfig->getChildFieldName();
            if ($childFieldName) {
                foreach ($rowSubEntities[$childEntityCode] as &$entityRow) {
                    if (isset($parentIds[$index])) {
                        $entityRow[$childFieldName] = $parentIds[$index];
                        $this->synchronizationProcessor->adjustSubEntityOrigId(
                            $childEntityCode,
                            $entityRow,
                            $childFieldName,
                            $parentIds[$index]
                        );
                    }
                }
            }
        }
    }

    private function processBehaviorResults(EntitiesConfigInterface $entitiesConfig): void
    {
        $mainEntityCode = $entitiesConfig->getEntityCode();
        if (count($this->behaviorResults[$mainEntityCode]->getAffectedIds()) > 0) {
            return;
        }

        $mainEntityResult = $this->behaviorResults[$mainEntityCode];
        foreach ($entitiesConfig->getSubEntitiesConfig() as $subEntityConfig) {
            $this->processSubEntitiesResult($mainEntityResult, $subEntityConfig);
        }
    }

    private function processSubEntitiesResult(
        BehaviorResultInterface $mainEntityResult,
        EntitiesConfigInterface $entitiesConfig
    ): void {
        $subEntityCode = $entitiesConfig->getEntityCode();

        if (!isset($this->behaviorResults[$subEntityCode])) {
            foreach ($entitiesConfig->getSubEntitiesConfig() as $subEntityConfig) {
                $this->processSubEntitiesResult($mainEntityResult, $subEntityConfig);
            }

            return;
        }

        $subEntityResult = $this->behaviorResults[$subEntityCode];
        if (count($subEntityResult->getAffectedIds()) > 0) {
            $mainEntityResult->setNewIds(
                array_merge($mainEntityResult->getNewIds(), $subEntityResult->getNewIds())
            );
            $mainEntityResult->setUpdatedIds(
                array_merge($mainEntityResult->getUpdatedIds(), $subEntityResult->getUpdatedIds())
            );
            $mainEntityResult->setDeletedIds(
                array_merge($mainEntityResult->getDeletedIds(), $subEntityResult->getDeletedIds())
            );

            return;
        }

        foreach ($entitiesConfig->getSubEntitiesConfig() as $subEntityConfig) {
            $this->processSubEntitiesResult($mainEntityResult, $subEntityConfig);
        }
    }
}