Your IP : 127.0.0.1


Current Path : /home/dev2.destoffenstraat.com/app/Firebear/ImportExport/Model/Source/Platform/
Upload File :
Current File : /home/dev2.destoffenstraat.com/app/Firebear/ImportExport/Model/Source/Platform/Magento.php

<?php
/**
 * @copyright: Copyright © 2017 Firebear Studio. All rights reserved.
 * @author   : Firebear Studio <fbeardev@gmail.com>
 */

namespace Firebear\ImportExport\Model\Source\Platform;

use Firebear\ImportExport\Model\Cache\Type\ImportProduct as ImportProductCache;
use Magento\Catalog\Model\Product\Visibility;
use Firebear\ImportExport\Model\Import\Product;
use Magento\Backend\Model\Session;
use Magento\Catalog\Model\ResourceModel\Eav\Attribute;
use Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceModelFactory;
use Magento\Eav\Model\Entity\Context;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory;
use Magento\Eav\Setup\EavSetupFactory;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\File\Csv;
use Magento\Framework\Filesystem;
use Magento\Framework\Filesystem\File\ReadFactory;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Tax\Model\ClassModelFactory;
use Magento\Bundle\Model\Product\Price as BundlePrice;
use Magento\BundleImportExport\Model\Import\Product\Type\Bundle;
use Magento\ImportExport\Model\Import\Entity\AbstractEntity;
use Symfony\Component\Console\Output\ConsoleOutput;

/**
 * Class Magento
 *
 * @package Firebear\ImportExport\Model\Source\Platform
 */
class Magento extends AbstractPlatform
{
    const PRICE_FIXED = 0;

    protected $separator;

    /**
     * @var \Magento\Framework\App\ProductMetadata
     */
    protected $productMetadata;

    /**
     * Magento constructor.
     * @param ScopeConfigInterface $scopeConfig
     * @param Filesystem $filesystem
     * @param ReadFactory $readFactory
     * @param Csv $csvProcessor
     * @param ClassModelFactory $taxFactory
     * @param Visibility $visibility
     * @param CollectionFactory $attributeSetCollectionFactory
     * @param Product $importProduct
     * @param Context $context
     * @param EavSetupFactory $eavSetupFactory
     * @param StoreManagerInterface $storeManager
     * @param Attribute $attributeFactory
     * @param ResourceModelFactory $resourceFactory
     * @param Session $session
     * @param CacheInterface $cache
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        Filesystem $filesystem,
        ReadFactory $readFactory,
        Csv $csvProcessor,
        ClassModelFactory $taxFactory,
        Visibility $visibility,
        CollectionFactory $attributeSetCollectionFactory,
        Product $importProduct,
        Context $context,
        EavSetupFactory $eavSetupFactory,
        StoreManagerInterface $storeManager,
        Attribute $attributeFactory,
        ResourceModelFactory $resourceFactory,
        Session $session,
        CacheInterface $cache,
        ConsoleOutput $output
    ) {
        parent::__construct(
            $scopeConfig,
            $filesystem,
            $readFactory,
            $csvProcessor,
            $taxFactory,
            $visibility,
            $attributeSetCollectionFactory,
            $importProduct,
            $context,
            $eavSetupFactory,
            $storeManager,
            $attributeFactory,
            $resourceFactory,
            $session,
            $cache,
            $output
        );

        $this->unsetColumns = [
            '_group_price_website',
            '_group_price_customer_group',
            '_group_price_price'
        ];
    }

    /**
     * Prepare Rows
     *
     * @param $rowData
     *
     * @return mixed
     */
    public function prepareRow($rowData)
    {
        /*tax phase*/
        if (isset($rowData['tax_class_id'])) {
            $rowData['tax_class_name'] = $this->getTaxClassName($rowData['tax_class_id']);
            unset($rowData['tax_class_id']);
        }

        /*visibility phase*/
        if (isset($rowData['visibility'])) {
            $rowData['visibility'] = $this->getVisibilityText($rowData['visibility']);
        }

        $attrList = ['gift_message_available', 'shipment_type', 'page_layout'];
        foreach ($attrList as $item) {
            if (isset($rowData[$item])) {
                $rowData[$item] = $this->getAttrValues($item, $rowData[$item]);
            }
        }

        if ($rowData['product_type'] == 'bundle') {
            $fields = ['price_type', 'weight_type', 'sku_type'];
            foreach ($fields as $field) {
                if (isset($rowData[$field])) {
                    if ($rowData[$field] == BundlePrice::PRICE_TYPE_DYNAMIC) {
                        $rowData[$field] = Bundle::VALUE_DYNAMIC;
                    } else {
                        $rowData[$field] = Bundle::VALUE_FIXED;
                    }
                }
            }
        }

        if ($rowData['product_type'] == 'configurable') {
            if (!empty($rowData['_super_products_sku']) &&
                !empty($rowData['_super_attribute_code']) &&
                !empty($rowData['_super_attribute_option'])
            ) {
                $newArray = [];
                $configuration = [];
                if (!empty($rowData['configurable_variations'])) {
                    $configuration = explode('|', $rowData['configurable_variations']);
                }

                $superSku = explode($this->separator, $rowData['_super_products_sku']);
                $superAttr = explode($this->separator, $rowData['_super_attribute_code']);
                $superOption = explode($this->separator, $rowData['_super_attribute_option']);

                if (count($superSku) == 1) {
                    foreach ($superSku as $skuSuper) {
                        if (count($superAttr) == count($superOption)) {
                            foreach ($superAttr as $key => $attribute) {
                                $newArray[$skuSuper][] = $superAttr[$key] . "=" . $superOption[$key];
                            }
                        }
                    }
                } elseif (count($superSku) > 1) {
                    foreach ($superSku as $key => $skuSuper) {
                        $newArray[$skuSuper][] = $superAttr[$key] . "=" . $superOption[$key];
                    }
                }

                $configurationPart = '';
                foreach ($newArray as $key => $array) {
                    $configurationPart = '';
                    $configurationPart .= 'sku=' . $key;
                    foreach ($array as $arrayItem) {
                        $configurationPart .= $this->separator . $arrayItem;
                    }
                    $configuration[] = $configurationPart;
                }

                if (!empty($configuration)) {
                    $rowData['configurable_variations'] = implode('|', $configuration);
                    unset($rowData['_super_products_sku']);
                    unset($rowData['_super_attribute_code']);
                    unset($rowData['_super_attribute_option']);
                }
            }
        }

        $rowData = $this->changeTierPrices($rowData);
        if (isset($rowData['_attribute_set'])) {
            $rowData['_attribute_set'] = $this->getAttributeSetName($rowData['_attribute_set']);
        }
        if (isset($rowData['_root_category'])) {
            if (isset($rowData['categories'])) {
                $rowData['categories'] = $rowData['_root_category'] . "/" . $rowData['categories'];
            } else {
                $rowData['categories'] = $rowData['_root_category'];
            }
        }

        if (isset($rowData['price']) && !$rowData['price']) {
            $rowData['price'] = 0;
        }

        /*bundle phase*/
        if (isset($rowData['bundle_configurations']) && isset($rowData['bundle_values'])) {
            if ($rowData['bundle_configurations']) {
                $bundleConfigurations = explode(',', $rowData['bundle_configurations']);
                foreach ($bundleConfigurations as $bundleConfigData) {
                    $bundleConfigData = explode('=', $bundleConfigData);
                    $rowData[$bundleConfigData[0]] = $bundleConfigData[1];
                }
            } else {
                $rowData['bundle_price_type'] = '';
                $rowData['bundle_sku_type'] = '';
                $rowData['bundle_price_view'] = '';
                $rowData['bundle_weight_type'] = '';
            }
        }

        $rowData = $this->unsetColumns($rowData, $this->unsetColumns);
        $rowData['custom_options'] = $this->formatCustomOptions($rowData);
        $array = [
            '_custom_option_title',
            '_custom_option_type',
            '_custom_option_is_required',
            '_custom_option_sku',
            '_custom_option_price',
            '_custom_option_row_title',
            '_custom_option_store',
            '_custom_option_max_characters',
            '_custom_option_sort_order',
            '_custom_option_row_price',
            '_custom_option_row_sku',
            '_custom_option_row_sort'
        ];

        foreach ($array as $field) {
            if (isset($rowData[$field])) {
                unset($rowData[$field]);
            }
        }
        if (isset($rowData['_store'])) {
            $rowData['store_view_code'] = $rowData['_store'];
        } else {
            $rowData['store_view_code'] = '';
        }

        return $rowData;
    }

    /**
     * @param $rowData
     * @return mixed
     */
    public function prepareColumns($rowData)
    {
        /*tax phase*/
        foreach ($this->unsetColumns as $field) {
            if (in_array($field, $rowData)) {
                $key = array_search($field, $rowData);
                unset($rowData[$key]);
            }
        }
        if (in_array('tax_class_id', $rowData)) {
            $key = array_search('tax_class_id', $rowData);
            $rowData[$key] = 'tax_class_name';
        }

        if (in_array('reward_update_notification', $rowData)) {
            $key = array_search('reward_update_notification', $rowData);
            unset($rowData[$key]);
        }
        if (in_array('reward_warning_notification', $rowData)) {
            $key = array_search('reward_warning_notification', $rowData);
            unset($rowData[$key]);
        }

        if (in_array('_root_category', $rowData) || in_array('_category', $rowData)) {
            $key = array_search('_root_category', $rowData);
            if ($key !== false) {
                $rowData[$key] = 'categories';
            }
            $keySecond = array_search('_category', $rowData);

            if ($keySecond !== false) {
                if ($key !== false) {
                    unset($rowData[$keySecond]);
                } else {
                    $rowData[$keySecond] = 'categories';
                }
            }
        }

        return $rowData;
    }

    /**
     * Unset unnecessary columns
     *
     * @param $data
     * @param $columnNames
     *
     * @return mixed
     */
    public function unsetColumns($data, $columnNames)
    {
        foreach ($columnNames as $column) {
            unset($data[$column]);
        }

        return $data;
    }

    /**
     * Get tax class name
     *
     * @param $taxId
     *
     * @return mixed|string
     */
    public function getTaxClassName($taxId)
    {
        if (!is_numeric($taxId)) {
            return '';
        }
        $taxInfo = $this->taxFactory->create()->load($taxId);

        if ($taxInfo->getClassName()) {
            return $taxInfo->getClassName();
        }

        return '';
    }

    /**
     * Get tax visibility label
     *
     * @param $visibilityId
     *
     * @return string
     */
    public function getVisibilityText($visibilityId)
    {
        if (!$visibilityId) {
            return '';
        }
        $optionText = $this->visibility->getOptionText($visibilityId);

        return $optionText
            ? (string)$optionText
            : (string)$this->visibility->getOptionText(
                Visibility::VISIBILITY_NOT_VISIBLE
            );
    }

    public function getAttrValues($name, $value)
    {
        if (!strlen($value)) {
            return '';
        }

        $newValue = '';
        $collection = $this->attributeFactory->getCollection()->addFieldToFilter('attribute_code', $name);
        if ($collection->getSize()) {
            $item = $collection->getFirstItem();
            if ($item->getFrontendInput() == 'boolean') {
                if ($value == 0) {
                    $newValue = __('No');
                } else {
                    $newValue = __('Yes');
                }
            } else {
                foreach ($item->getOptions() as $option) {
                    $optValue = $option->getValue();
                    if ($optValue instanceof \Magento\Framework\Phrase) {
                        $optValue = $optValue->__toString();
                    };
                    if ($value instanceof \Magento\Framework\Phrase) {
                        $value = $value->__toString();
                    };
                    if ($optValue == $value) {
                        $newValue = $option->getLabel();
                    }
                }
            }
        }

        return $newValue;
    }

    /**
     * Get Attribute Set Name
     *
     * @param $setName
     *
     * @return mixed
     */
    public function getAttributeSetName($setName)
    {
        $attributeSetCollection = $this->attributeSetCollectionFactory->create();
        $attributeSetName =
            $attributeSetCollection->addFieldToFilter('attribute_set_name', $setName)->getFirstItem();
        if ($attributeSetName->getId()) {
            return $setName;
        }

        return $this->attributeSetCollectionFactory->create()->getFirstItem()->getAttributeSetName();
    }

    public function formatCustomOptions($data)
    {

        $str = "";
        if (isset($data['_custom_option_title']) && $data['_custom_option_title']) {
            $titles = $this->divideData($data['_custom_option_title']);
            $requirds = $this->divideData($data['_custom_option_is_required']);
            foreach ($requirds as $key => $requird) {
                if (!strlen($requird)) {
                    $requirds[$key] = 0;
                }
            }
            $types = $this->divideData($data['_custom_option_type']);
            $skus = $this->divideData($data['_custom_option_sku']);

            $prices = $this->divideData($data['_custom_option_price']);
            $rowTitles = array_unique($this->divideData($data['_custom_option_row_title']));
            for ($i = 0; $i <= count($prices); $i++) {
                if (!isset($skus[$i]) || (isset($skus[$i]) && empty($skus[$i]))) {
                    $skus[$i] = $data['sku'];
                }
            }
            foreach ($prices as $key => $price) {
                if (empty($price) || $price == 0) {
                    if (count($prices) > 1) {
                        array_splice($prices, $key, 1);
                    } else {
                        unset($prices[$key]);
                    }
                    if (isset($titles[$key])) {
                        if (count($titles) > 1) {
                            array_splice($titles, $key, 1);
                        } else {
                            unset($titles[$key]);
                        }
                    }
                    if (isset($requirds[$key])) {
                        if (count($requirds) > 1) {
                            array_splice($requirds, $key, 1);
                        } else {
                            unset($requirds[$key]);
                        }
                    }
                    if (isset($types[$key])) {
                        if (count($types) > 1) {
                            array_splice($types, $key, 1);
                        } else {
                            unset($types[$key]);
                        }
                    }
                    if (isset($skus[$key])) {
                        if (count($skus) > 1) {
                            array_splice($skus, $key, 1);
                        } else {
                            unset($skus[$key]);
                        }
                    }
                    if (isset($rowTitles[$key])) {
                        if (count($rowTitles) > 1) {
                            array_splice($rowTitles, $key, 1);
                        } else {
                            unset($rowTitles[$key]);
                        }
                    }
                }
            }
            if (count($prices) > 0) {
                $bigData = [
                    ['name' => 'name', 'array' => $titles, 'count' => count($titles)],
                    ['name' => 'type', 'array' => $types, 'count' => count($types)],
                    ['name' => 'required', 'array' => $requirds, 'count' => count($requirds)],
                    ['name' => 'sku', 'array' => $skus, 'count' => count($skus)],
                    ['name' => 'price', 'array' => $prices, 'count' => count($prices)],
                    ['name' => 'option_title', 'array' => $rowTitles, 'count' => count($rowTitles)]
                ];

                list($bigData, $max) = $this->getMax($bigData);
                for ($i = 0; $i < $max; $i++) {
                    $text = 0;
                    foreach ($bigData as $field) {
                        if (strlen($field['array'][$i])) {
                            $text++;
                            if ($field['name'] != 'name') {
                                $str .= ",";
                            }
                            $str .= $field['name'] . "=" . $field['array'][$i];
                            if ($field['name'] == 'price') {
                                $str .= ",price_type=fixed";
                            }
                        }
                    }

                    if ($i < $max - 1 && $text) {
                        $str .= "|";
                    }
                }
            }
        }
        return $str;
    }

    /**
     * @param $source
     * @param $maxDataSize
     * @param $bunchSize
     * @param $dataSourceModel
     * @param $parameters
     * @param $entityTypeCode
     * @param $behavior
     * @param $processedRowsCount
     * @param $separator
     * @param Product $model
     *
     * @return $this
     */
    public function saveValidatedBunches(
        $source,
        $maxDataSize,
        $bunchSize,
        $dataSourceModel,
        $parameters,
        $entityTypeCode,
        $behavior,
        $processedRowsCount,
        $separator,
        Product $model
    ) {
        $currentDataSize = 0;
        $bunchRows = [];
        $prevData = [];
        $startNewBunch = false;
        $nextRowBackup = [];
        $repeatStore = 0;
        $source->rewind();
        $dataSourceModel->cleanBunches();
        $file = null;
        $jobId = null;

        if (isset($parameters['file'])) {
            $file = $parameters['file'];
        }
        if (isset($parameters['job_id'])) {
            $jobId = $parameters['job_id'];
        }
        $repeats = 0;
        $end = 0;
        while ($source->valid() || $bunchRows) {
            if ($startNewBunch || !$source->valid()) {
                $dataSourceModel->saveBunches(
                    $entityTypeCode,
                    $behavior,
                    $jobId,
                    $file,
                    $bunchRows
                );
                $bunchRows = $nextRowBackup;
                $currentDataSize = strlen($model->getJsonHelper()->jsonEncode($bunchRows));
                $startNewBunch = false;
                $nextRowBackup = [];
            }
            if ($source->valid()) {
                try {
                    $rowData = $source->current();
                    $isCached = $parameters['cache_products'] ?? false;
                    if ($isCached) {
                        $isRowDataInCache = $this->isRowDataInCache($model, $rowData);
                        if ($isRowDataInCache) {
                            $source->next();
                            continue;
                        }
                    }
                    $invalidAttr = [];
                    foreach ($rowData as $attrName => $element) {
                        if (!mb_check_encoding($element, 'UTF-8')) {
                            unset($rowData[$attrName]);
                            $invalidAttr[] = $attrName;
                        }
                    }
                    if (!empty($invalidAttr)) {
                        $model->addRowError(
                            AbstractEntity::ERROR_CODE_ILLEGAL_CHARACTERS,
                            $processedRowsCount,
                            \implode(',', $invalidAttr)
                        );
                    }
                } catch (\InvalidArgumentException $e) {
                    $model->addRowError($e->getMessage(), $processedRowsCount);
                    $processedRowsCount++;
                    $source->next();
                    continue;
                }
                if (empty($rowData['sku'])
                    || (isset($prevData['sku']) && $prevData['sku'] == $rowData['sku']) && !$end) {
                    if (!empty($rowData['_store']) && $rowData['_store'] != $prevData['_store']) {
                        $repeatStore = 1;
                        $repeats++;
                    } else {
                        $prevData = $this->mergeData($rowData, $prevData, $separator);
                        $source->next();
                        $repeats++;
                        if ($source->valid()) {
                            continue;
                        } else {
                            $end = 1;
                        }
                    }
                }

                $rowData = $model->customFieldsMapping($rowData);

                if (!empty($prevData) && $repeats > 0) {
                    if ($model->isExist($prevData['sku'])) {
                        continue;
                    }
                    $this->separator = $separator;
                    $prevData = $this->prepareRow($prevData);
                    $processedRowsCount++;
                    $rowSize = strlen($model->getJsonHelper()->jsonEncode($prevData));
                    $isBunchSizeExceeded = $bunchSize > 0 && count($bunchRows) >= $bunchSize;
                    if ($currentDataSize + $rowSize >= $maxDataSize || $isBunchSizeExceeded) {
                        $startNewBunch = true;
                        $nextRowBackup = [$processedRowsCount => $prevData];
                    } else {
                        $bunchRows[$processedRowsCount] = $prevData;
                        $currentDataSize += $rowSize;
                    }
                }
                if ($repeatStore) {
                    $prevData = array_merge($prevData, $this->deleteEmpty($rowData));
                    $repeatStore = 0;
                } else {
                    $prevData = $rowData;
                }
                if (!$end) {
                    $repeats = 1;
                    $key = $source->key();
                }
                $source->next();
                if (!$source->valid() && $end == 0) {
                    $source->rewind();
                    $source->seek($key);
                    $end = 1;
                }
            }
        }
        $this->setProcessedRowsCount($processedRowsCount);
        if (empty($processedRowsCount)) {
            $errorMessage = __('This file is empty. Please try another one.');
            $model->addLogWriteln($errorMessage, null, 'warning');
        }
        $this->saveRowDataInBuffCache($model);
        return $this;
    }

    protected function getMax($array)
    {
        $max = 0;
        foreach ($array as $field) {
            if ($field['count'] > $max) {
                $max = $field['count'];
            }
        }
        foreach ($array as $key => $field) {
            $counts = count($field['array']);
            if ($counts < $max) {
                $diff = $max - $counts;
                $end = end($field['array']);

                for ($i = $counts - 1; $i <= $diff; $i++) {
                    $array[$key]['array'][$i] = $end;
                }
            }
        }

        return [$array, $max];
    }

    /**
     * @param $str
     * @return array
     */
    protected function divideData($str)
    {
        $array = [];
        if (strpos($str, $this->separator) !== false) {
            $array = explode($this->separator, $str);
        } else {
            $array = [$str];
        }

        return $array;
    }

    /**
     * @param $rowData
     * @param $maps
     * @return mixed
     */
    public function afterColumns($rowData, $maps)
    {
        return $rowData;
    }

    protected function changeTierPrices($rowData)
    {
        if (!empty($rowData['_tier_price_price'])) {
            $website = explode($this->separator, $rowData["_tier_price_website"]);
            $group = explode($this->separator, $rowData["_tier_price_customer_group"]);
            $qty = explode($this->separator, $rowData["_tier_price_qty"]);
            $price = explode($this->separator, $rowData["_tier_price_price"]);
            $txt = '';
            foreach ($price as $key => $tier) {
                if (strpos($this->importProduct->productMetadata->getVersion(), '2.2') !== false) {
                    $txt .= $group[$key] . $this->separator . $qty[$key] . $this->separator . $tier .
                        $this->separator . '' . $this->separator . $website[$key];
                } else {
                    $txt .= $group[$key] . $this->separator . $qty[$key]. $this->separator . $tier  .
                        $this->separator . self::PRICE_FIXED .$this->separator .$website[$key];
                }
                if (next($price)) {
                    $txt .= "|";
                }
            }

            $rowData['tier_prices'] = $txt;
            unset($rowData["_tier_price_website"]);
            unset($rowData["_tier_price_customer_group"]);
            unset($rowData['_tier_price_qty']);
            unset($rowData['_tier_price_price']);
        }

        return $rowData;
    }
}