Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/job-board.corals.io/Corals/modules/Ecommerce/Jobs/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/job-board.corals.io/Corals/modules/Ecommerce/Jobs/HandleProductsImportFile.php
<?php


namespace Corals\Modules\Ecommerce\Jobs;


use Corals\Modules\Ecommerce\Http\Requests\{ProductRequest, SKURequest};
use Corals\Modules\Ecommerce\Models\{Attribute, Brand, Category, Product, SKU};
use Corals\Modules\Ecommerce\Services\{ProductService};
use Corals\Modules\Ecommerce\Traits\ImportTrait;
use Corals\Modules\Marketplace\Services\SKUService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\{InteractsWithQueue, SerializesModels};
use Illuminate\Support\{Arr, Str};
use League\Csv\{Exception as CSVException};

class HandleProductsImportFile implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels, ImportTrait;

    protected $importFilePath;

    /**
     * @var Collection
     */
    protected $categories;

    /**
     * @var Collection
     */
    protected $brands;
    /**
     * @var Collection
     */
    protected $attributes;
    /**
     * @var array
     */
    protected $importHeaders;
    protected $user;
    protected $images_root;
    protected $clearExistingImages;

    /**
     * HandleProductsImportFile constructor.
     * @param $importFilePath
     * @param $images_root
     * @param $clearExistingImages
     * @param $user
     */
    public function __construct($importFilePath, $images_root, $clearExistingImages, $user)
    {
        $this->user = $user;
        $this->importFilePath = $importFilePath;
        $this->clearExistingImages = $clearExistingImages;
        $this->images_root = $images_root;
        $this->importHeaders = array_keys(trans('Ecommerce::import.product-headers'));
    }


    /**
     * @throws CSVException
     */
    public function handle()
    {
        $this->doImport();
    }

    /**
     * @param $record
     * @throws \Exception
     */
    protected function handleImportRecord($record)
    {
        $record = array_map('trim', $record);

        //prepare product data
        $productData = $productRequestData = $this->getProductData($record);

        $productRequestData['variation_options'] = array_keys(data_get($productRequestData, 'variation_options', []));
        $productRequestData['global_options'] = array_keys(data_get($productRequestData, 'global_options', []));
        unset($productRequestData['shippable']);

        //validate record
        $this->validateRecord($productRequestData);

        //check if product/sku exist
        $skuCode = data_get($record, 'SKU');

        $skuModel = SKU::query()
            ->where('code', $skuCode)
            ->first();

        $productCode = data_get($record, 'Parent SKU');

        if ($productCode) {
            $productModel = Product::query()
                ->where('product_code', $productCode)
                ->first();
        } elseif ($skuModel) {
            $productModel = $skuModel->product;
        }

        $productRequest = new ProductRequest();

        $productRequest->replace($productRequestData);

        $productService = new ProductService();

        if (isset($productModel) && $productModel) {
            $productModel = $productService->update($productRequest, $productModel);
        } else {
            $productModel = $productService->store($productRequest, Product::class);
        }

        $this->handleProductImages($record, $productModel);

        if ($productData['type'] === 'variable') {
            $productData['product_id'] = $productModel->id;
            $skuData = $this->getSKUData($productData);
            $skuService = new SKUService();
            $skuRequest = new SKURequest();
            $skuRequest->replace($skuData);

            if ($skuModel) {
                $skuModel = $skuService->update($skuRequest, $skuModel);
            } else {
                $skuModel = $skuService->store($skuRequest, SKU::class);
            }
            $featuredImage = data_get($record, 'Featured Image');

            if ($featuredImage) {
                $this->addMediaFromFile(
                    $skuModel,
                    $featuredImage,
                    $skuModel->mediaCollectionName,
                    "sku_{$skuModel->id}");
            }
        }

        unset($skuModel);
        unset($productModel);
    }

    /**
     * @param $record
     * @return array
     */
    protected function handleProductCategories($record): array
    {
        $importCategories = array_filter(explode('|', data_get($record, 'Categories', [])));

        $productCategories = [];

        foreach ($importCategories as $categoryName) {
            $categoryName = trim($categoryName);

            if (empty($categoryName)) {
                continue;
            }

            $categoryFound = $this->categories->where('name', $categoryName)->first();

            if (!$categoryFound) {
                $categoryFound = $this->categories->where('slug', Str::slug($categoryName))->first();
            }

            if ($categoryFound) {
                $productCategories[] = $categoryFound->id;
            } else {
                $newCategory = Category::query()->create([
                    'name' => $categoryName,
                    'slug' => Str::slug($categoryName),
                ]);

                $this->categories->push($newCategory);

                $productCategories[] = $newCategory->id;
            }
        }

        return $productCategories;
    }

    /**
     * @param $record
     * @return int|null
     */
    protected function handleProductBrand($record)
    {
        $brandName = data_get($record, 'Brand Name');

        $brandId = null;

        if ($brandName) {
            $brandFound = $this->brands->where('name', $brandName)->first();

            if (!$brandFound) {
                $brandFound = $this->categories->where('slug', $brandName)->first();
            }

            if (!$brandFound) {
                $newBrand = Brand::query()->create([
                    'name' => $brandName,
                    'slug' => Str::slug($brandName),
                ]);

                $this->brands->push($newBrand);
                $brandFound = $newBrand;
            }

            $brandId = $brandFound->id;
        }

        return $brandId;
    }

    /**
     * @param $record
     * @param $productModel
     */
    protected function handleProductImages($record, $productModel)
    {
        if ($this->clearExistingImages) {
            $productModel->clearMediaCollection($productModel->galleryMediaCollection);
        }

        $featuredImage = data_get($record, 'Featured Image');

        if ($featuredImage) {
            $media = $this->addMediaFromFile(
                $productModel,
                $featuredImage,
                $productModel->galleryMediaCollection,
                "product_{$productModel->id}", false, ['featured' => true]);

            if ($media && !$this->clearExistingImages) {
                $gallery = $productModel->getMedia($productModel->galleryMediaCollection);

                foreach ($gallery as $item) {
                    if ($item->id != $media->id) {
                        $item->forgetCustomProperty('featured');
                        $item->save();
                    }
                }
            }
        }

        $images = array_filter(explode('|', data_get($record, 'Images')));

        foreach ($images as $image) {
            if ($featuredImage == $image) {
                continue;
            }
            $this->addMediaFromFile(
                $productModel,
                $image,
                $productModel->galleryMediaCollection,
                "product_{$productModel->id}", false);
        }
    }

    protected function loadEcommerceCategories()
    {
        $this->categories = Category::query()->get();
    }

    protected function loadEcommerceBrands()
    {
        $this->brands = Brand::query()->get();
    }

    protected function loadEcommerceAttributes()
    {
        $this->attributes = Attribute::with(['options'])->get();
    }

    /**
     * @param $record
     * @param string $column
     * @return array
     * @throws \Exception
     */
    protected function handleVariationOptions($record, string $column)
    {
        $attributes = array_filter(explode('|', data_get($record, $column)));

        $isGlobal = $column !== 'Attributes';

        $variationOptions = [];

        foreach ($attributes as $attribute) {
            if (!$isGlobal) {
                [$code, $value] = explode(':', $attribute);

                $value = trim($value);
            } else {
                $code = $attribute;
            }


            $attributeModel = $this->attributes->where('code', trim($code))->first();

            if (!$attributeModel) {
                throw new \Exception("Attribute $code not found");
            }

            if (empty($value) && $attributeModel->required) {
                throw new \Exception("Attribute $attribute value is empty");
            }

            if ($isGlobal) {
                $variationOptions[$attributeModel->id] = 1;
                continue;
            }

            if ($attributeModel->options->isNotEmpty()) {
                if ($attributeModel->type == 'multi_values') {
                    $variationOptions[$attributeModel->id] = ['multi' => []];

                    $values = array_filter(explode('+', $value));

                    foreach ($values as $value) {
                        $option = $this->getAttributeOption($attributeModel, $value);
                        $variationOptions[$attributeModel->id]['multi'][] = [$option->id => $value];
                    }
                } else {
                    $option = $this->getAttributeOption($attributeModel, $value);
                    $variationOptions[$attributeModel->id] = [$option->id => $value];
                }
            } else {
                $variationOptions[$attributeModel->id] = $value;
            }
        }
        return $variationOptions;
    }

    /**.
     * @param $attributeModel
     * @param $value
     * @return mixed
     * @throws \Exception
     */
    protected function getAttributeOption($attributeModel, $value)
    {
        $option = $attributeModel->options->where('option_value', $value)->first();

        if (!$option) {
            throw new \Exception("Attribute {$attributeModel->code} $value option not found");
        }

        return $option;
    }

    /**
     * @param $record
     * @return array
     */
    protected function getShippingDetails($record): array
    {
        return array_filter([
            'shipping_option' => 'calculate_rates',
            'enabled' => data_get($record, 'Shippable') == 1 ? 1 : 0,
            'width' => data_get($record, 'Width'),
            'height' => data_get($record, 'Height'),
            'length' => data_get($record, 'Length'),
            'weight' => data_get($record, 'Weight'),
        ]);
    }

    /**
     * @param $record
     * @return array
     * @throws \Exception
     */
    protected function getProductData($record)
    {
        $productCategories = $this->handleProductCategories($record);

        $brandId = $this->handleProductBrand($record);

        $variationOptions = $this->handleVariationOptions($record, 'Attributes');

        $globalOptions = $this->handleVariationOptions($record, 'Global Attributes');

        return array_filter([
            'name' => data_get($record, 'Name'),
            'caption' => data_get($record, 'Caption'),
            'product_code' => data_get($record, 'Parent SKU') ?: null,
            'type' => data_get($record, 'Type'),
            'status' => data_get($record, 'Status'),
            'code' => data_get($record, 'SKU'),
            'regular_price' => data_get($record, 'Regular Price'),
            'sale_price' => data_get($record, 'Sale Price'),
            'allowed_quantity' => '0',
            'categories' => $productCategories,
            'description' => data_get($record, 'Description'),
            'global_options' => $globalOptions,
            'variation_options' => $variationOptions,
            'shipping' => $this->getShippingDetails($record),
            'shippable' => data_get($record, 'Shippable'),
            'inventory' => data_get($record, 'Inventory'),
            'inventory_value' => data_get($record, 'Inventory Value'),
            'brand_id' => $brandId
        ]);
    }

    /**
     * @param array $productData
     * @return array
     */
    protected function getSKUData(array $productData)
    {
        $skuData = Arr::only($productData, [
            'regular_price',
            'sale_price',
            'allowed_quantity',
            'code',
            'status',
            'inventory',
            'inventory_value',
            'shipping',
            'product_id',
        ]);

        foreach ($productData['variation_options'] as $optionId => $option) {
            if (is_array($option)) {
                $key = key($option);
                if ($key == 'multi') {
                    foreach ($option[$key] as $multiOption) {
                        $skuData['options'][$optionId][] = key($multiOption);
                    }
                } else {
                    $skuData['options'][$optionId] = $key;
                }
            } else {
                $skuData['options'][$optionId] = $option;
            }
        }

        return $skuData;
    }

    protected function initHandler()
    {
        $this->loadEcommerceCategories();
        $this->loadEcommerceBrands();
        $this->loadEcommerceAttributes();
    }

    protected function getValidationRules($data, $model): array
    {
        return [
            'name' => 'required|max:191',
            'caption' => 'required',
            'status' => 'required|in:active,inactive',
            'type' => 'required|in:simple,variable',
            'inventory' => 'required_if:type,simple',
            'inventory_value' => 'required_if:inventory,finite,bucket',
            'regular_price' => 'required_if:type,simple',
            'code' => 'required_if:type,simple',
            'product_code' => 'required_if:type,variable',
            'shipping.width' => 'required_if:shippable,1',
            'shipping.height' => 'required_if:shippable,1',
            'shipping.length' => 'required_if:shippable,1',
            'shipping.weight' => 'required_if:shippable,1',
            'variation_options' => [
                'required_if:type,variable',
                function ($attribute, $value, $fail) use ($data) {
                    $global_options = data_get($data, 'global_options', []);

                    if (array_intersect($value, $global_options)) {
                        $fail($attribute . ' should be unique with global attributes');
                    }
                }
            ],
            'categories' => 'required',
        ];
    }
}

Spamworldpro Mini