Your IP : 216.73.216.86


Current Path : /var/www/homesaver/www/bitrix/modules/sprint.migration/lib/exchange/
Upload File :
Current File : /var/www/homesaver/www/bitrix/modules/sprint.migration/lib/exchange/iblockelementsimport.php

<?php

namespace Sprint\Migration\Exchange;

use Sprint\Migration\AbstractExchange;
use Sprint\Migration\Exceptions\HelperException;
use Sprint\Migration\Exceptions\RestartException;
use Sprint\Migration\Locale;
use XMLReader;

class IblockElementsImport extends AbstractExchange
{
    protected $converter;

    /**
     * @param callable $converter
     *
     * @throws HelperException
     * @throws RestartException
     */
    public function execute(callable $converter)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();

        $this->converter = $converter;

        $params = $this->exchangeEntity->getRestartParams();

        if (!isset($params['total'])) {
            if (!is_file($this->file)) {
                throw new HelperException(
                    Locale::getMessage('ERR_EXCHANGE_FILE_NOT_FOUND', ['#FILE#' => $this->file])
                );
            }

            $reader = new XMLReader();
            $reader->open($this->getExchangeFile());
            $params['total'] = 0;
            $params['offset'] = 0;
            $exchangeVersion = 0;

            $iblockUid = '';

            while ($reader->read()) {
                if ($this->isOpenTag($reader, 'items')) {
                    $exchangeVersion = (int)$reader->getAttribute('exchangeVersion');
                    $iblockUid = $reader->getAttribute('iblockUid');
                }
                if ($this->isOpenTag($reader, 'item')) {
                    $params['total']++;
                }
            }
            $reader->close();

            if (!$exchangeVersion || $exchangeVersion < self::EXCHANGE_VERSION) {
                throw new HelperException(
                    Locale::getMessage('ERR_EXCHANGE_VERSION', ['#NAME#' => $this->getExchangeFile()])
                );
            }

            $params['iblock_id'] = $iblockExchange->getIblockIdByUid($iblockUid);
        }

        $reader = new XMLReader();
        $reader->open($this->getExchangeFile());
        $index = 0;

        while ($reader->read()) {
            if ($this->isOpenTag($reader, 'item')) {
                $collect = ($index >= $params['offset'] && $index < $params['offset'] + $this->getLimit());
                $restart = ($index >= $params['offset'] + $this->getLimit());
                $finish = ($index >= $params['total'] - 1);

                if ($collect) {
                    $this->collectItem($reader, $params['iblock_id']);
                }

                if ($finish || $restart) {
                    $this->outProgress('', ($index + 1), $params['total']);
                }

                if ($restart) {
                    $params['offset'] = $index;
                    $this->exchangeEntity->setRestartParams($params);
                    $this->restart();
                }
                $index++;
            }
        }

        $reader->close();
        unset($params['offset']);
        unset($params['total']);
        unset($params['iblock_id']);
        $this->exchangeEntity->setRestartParams($params);
    }

    /**
     * @param XMLReader $reader
     * @param           $iblockId
     */
    protected function collectItem(XMLReader $reader, $iblockId)
    {
        $fields = [];
        $props = [];

        if ($this->isOpenTag($reader, 'item')) {
            do {
                $reader->read();

                $field = $this->collectField($reader, 'field');
                if ($field) {
                    $fields[] = $field;
                }

                $prop = $this->collectField($reader, 'property');
                if ($prop) {
                    $props[] = $prop;
                }
            } while (!$this->isCloseTag($reader, 'item'));

            $convertedItem = $this->convertItem(
                [
                    'iblock_id'  => $iblockId,
                    'fields'     => $fields,
                    'properties' => $props,
                ]
            );

            if ($convertedItem) {
                call_user_func($this->converter, $convertedItem);
            }
        }
    }

    /**
     * @param $item
     *
     * @return array|bool
     */
    protected function convertItem($item)
    {
        if (empty($item['iblock_id'])) {
            return false;
        }

        $convertedFields = [];
        foreach ($item['fields'] as $field) {
            $method = $this->getConvertFieldMethod($item['iblock_id'], $field['name']);
            if (method_exists($this, $method)) {
                $convertedFields[$field['name']] = $this->$method($item['iblock_id'], $field);
            }
        }

        $convertedProperties = [];
        foreach ($item['properties'] as $prop) {
            $method = $this->getConvertPropertyMethod($item['iblock_id'], $prop['name']);
            if (method_exists($this, $method)) {
                $convertedProperties[$prop['name']] = $this->$method($item['iblock_id'], $prop);
            }
        }

        return [
            'iblock_id'  => $item['iblock_id'],
            'fields'     => $convertedFields,
            'properties' => $convertedProperties,
        ];
    }

    /**
     * @param $iblockId
     * @param $code
     *
     * @return string
     */
    protected function getConvertFieldMethod($iblockId, $code)
    {
        if (in_array($code, ['PREVIEW_PICTURE', 'DETAIL_PICTURE'])) {
            return 'convertFieldF';
        } elseif ($code == 'IBLOCK_SECTION') {
            return 'convertFieldIblockSection';
        } else {
            return 'convertFieldS';
        }
    }

    /**
     * @param $iblockId
     * @param $field
     *
     * @return mixed
     */
    protected function convertFieldS($iblockId, $field)
    {
        return $this->makeFieldValue($field['value'][0]);
    }

    /**
     * @param $iblockId
     * @param $field
     *
     * @throws HelperException
     * @return array
     */
    protected function convertFieldIblockSection($iblockId, $field)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();

        $value = [];
        foreach ($field['value'] as $val) {
            $val['value'] = $iblockExchange->getSectionIdByUniqName($iblockId, $val['value']);
            $value[] = $this->makeFieldValue($val);
        }

        return $value;
    }

    /**
     * @param $iblockId
     * @param $field
     *
     * @return array|bool|null
     */
    protected function convertFieldF($iblockId, $field)
    {
        return $this->makeFileValue($field['value'][0]);
    }

    protected function getConvertPropertyMethod($iblockId, $code)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();
        $type = $iblockExchange->getPropertyType($iblockId, $code);

        if (in_array($type, ['L', 'F', 'G', 'E'])) {
            return 'convertProperty' . ucfirst($type);
        } else {
            return 'convertPropertyS';
        }
    }

    protected function convertPropertyS($iblockId, $prop)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();
        $isMultiple = $iblockExchange->isPropertyMultiple($iblockId, $prop['name']);
        $res = [];
        foreach ($prop['value'] as $val) {
            $res[] = $this->makePropertyValue($val);
        }

        return ($isMultiple) ? $res : $res[0];
    }

    protected function convertPropertyG($iblockId, $prop)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();
        $isMultiple = $iblockExchange->isPropertyMultiple($iblockId, $prop['name']);
        $linkIblockId = $iblockExchange->getPropertyLinkIblockId($iblockId, $prop['name']);

        $res = [];
        if ($linkIblockId) {
            foreach ($prop['value'] as $val) {
                $val['value'] = $iblockExchange->getSectionIdByUniqName($linkIblockId, $val['value']);
                $res[] = $this->makePropertyValue($val);
            }
        }

        return ($isMultiple) ? $res : $res[0];
    }

    protected function convertPropertyE($iblockId, $prop)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();
        $isMultiple = $iblockExchange->isPropertyMultiple($iblockId, $prop['name']);
        $linkIblockId = $iblockExchange->getPropertyLinkIblockId($iblockId, $prop['name']);

        $res = [];
        if ($linkIblockId) {
            foreach ($prop['value'] as $val) {
                $val['value'] = $iblockExchange->getElementIdByUniqName($linkIblockId, $val['value']);
                $res[] = $this->makePropertyValue($val);
            }
        }

        return ($isMultiple) ? $res : $res[0];
    }

    protected function convertPropertyF($iblockId, $prop)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();
        $isMultiple = $iblockExchange->isPropertyMultiple($iblockId, $prop['name']);
        $res = [];
        foreach ($prop['value'] as $val) {
            $res[] = $this->makeFileValue($val);
        }
        return ($isMultiple) ? $res : $res[0];
    }

    protected function convertPropertyL($iblockId, $prop)
    {
        $iblockExchange = $this->getHelperManager()->IblockExchange();
        $isMultiple = $iblockExchange->isPropertyMultiple($iblockId, $prop['name']);
        $res = [];
        foreach ($prop['value'] as $val) {
            $val['value'] = $iblockExchange->getPropertyEnumIdByXmlId(
                $iblockId,
                $prop['name'],
                $val['value']
            );

            $res[] = $this->makePropertyValue($val);
        }
        return ($isMultiple) ? $res : $res[0];
    }

    protected function makeFieldValue($val)
    {
        return $val['value'];
    }

    protected function makePropertyValue($val)
    {
        $result = [
            'VALUE' => $val['value'],
        ];

        if (!empty($val['description'])) {
            $result['DESCRIPTION'] = $val['description'];
        }

        return $result;
    }
}