!C99Shell v. 2.5 [PHP 8 Update] [24.05.2025]!

Software: Apache. PHP/8.1.30 

uname -a: Linux server1.tuhinhossain.com 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC
2025 x86_64
 

uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root)  

Safe-mode: OFF (not secure)

/home/picotech/domains/ecom1.picotech.app/public_html_ecom1/app/Services/Import/   drwxr-xr-x
Free 26.57 GB of 117.98 GB (22.52%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Self remove    Logout    


Viewing file:     ProductImportService.php (40.12 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php

/**
 * @package ProductImportService Handler
 * @author TechVillage <support@techvill.org>
 * @contributor Md Abdur Rahaman Zihad <[zihad.techvill@gmail.com]>
 * @created 19-11-2022
 */

namespace App\Services\Import;

use 
App\Enums\ProductStatus;
use 
App\Enums\ProductType;
use 
App\Models\Attribute;
use 
App\Models\AttributeValue;
use 
App\Models\Product;
use 
App\Models\ProductMeta;
use 
App\Services\Import\Dependencies\Category;
use 
App\Services\Import\Dependencies\CrossSell;
use 
App\Services\Import\Dependencies\TagDependency;
use 
App\Services\Import\Dependencies\Upsell;
use 
Illuminate\Http\Request;

class 
ProductImportService extends ImportService
{

    protected 
$fieldMap = [
        
"ID" => "id",
        
"Type" => "type",
        
"SKU" => "sku",
        
"Name" => "name",
        
"Title" => "name",
        
"Published" => "published",
        
"Is featured?" => "featured",
        
"Short description" => "summary",
        
"Description" => "description",
        
"Date sale price starts" => "sale_from",
        
"Date sale price ends" => "sale_to",
        
"Tax class" => "meta_tax_classes",
        
"In stock?" => "meta_stock_status",
        
"Low stock amount" => "meta_stock_threshold",
        
"Stock" => "total_stocks",
        
"Backorders allowed?" => "meta_backorder",
        
"weight" => "meta_weight",
        
"length" => "metadimensionlength",
        
"width" => "metadimensionwidth",
        
"height" => "metadimensionheight",
        
"Allow customer reviews?" => "meta_allow_review",
        
"Purchase note" => "meta_purchase_note",
        
"Sale price" => "sale_price",
        
"Regular price" => "regular_price",
        
"Shipping class" => "meta_shipping_class",
        
"Images" => "meta_image",
        
"Parent" => "parent_id",
        
"Upsells" => "upsells",
        
"Cross-sells" => "cross_sells",
        
"Categories" => "categories",
        
"Tags" => "tags",
        
'attributename' => 'attributetitle',
        
'attributevalue' => 'attributevalue',
        
'attributevisible' => 'attributevisibility',
        
'attributeglobal' => 'attributevariation',
        
'attributedefault' => 'attributedefault',
        
'downloadid' => 'downloadableid',
        
'downloadname' => 'downloadablename',
        
'downloadurl' => 'downloadableurl',
        
'Sold individually?' => 'meta_individual_sale',
        
'Download limit' => 'meta_download_limit',
        
'Allow customer reviews?' => 'meta_enable_reviews',
        
'externalurl' => 'metaexternalproducturl',
        
'buttontext' => 'metaexternalproducttext',
        
"Grouped products" => "meta_grouped_products"
    
];

    protected 
$importableFields = [];

    protected 
$meta = [];

    protected 
$categoryService;

    protected 
$tagService;

    protected 
$upsellService;

    protected 
$crossSellService;

    
/**
     * Contains insertable product_categories table data
     * @var array
     */
    
protected $categories  = [];
    
/**
     * Contains insertable product_tags table data
     *
     * @var array
     */
    
protected $tags  = [];

    
/**
     * Remembers product's group
     *
     * @var array
     */
    
protected $groupedProducts = [];

    protected 
$parentProducts = [];

    protected 
$variationProducts = [];

    protected 
$parentIds = [];

    protected 
$codeBindings = [];

    protected 
$skus = [];

    protected 
$slugs = [];

    protected 
$upsells = [];

    protected 
$crossSells = [];

    protected 
$skuBindings = [];

    protected 
$parentProductIds = [];

    protected 
$stored = [];

    public 
$totalUploaded 0;

    public 
$totalSkipped 0;

    public 
$totalVariations 0;

    protected 
$idFootPrints = [];

    protected 
$arrayableFields = ['attribute' => true'downloadable' => true'meta_dimension' => true'meta_external_product' => true];

    public function 
__construct(Request $request)
    {
        
parent::__construct($request);
        
$this->categoryService = new Category;
        
$this->tagService = new TagDependency;

        
$this->upsellService = new Upsell;

        
$this->crossSellService = new CrossSell;
    }

    
/**
     * Process step 1 of import steps
     * @return self
     */
    
public function importerStep1()
    {
        if (
$this->loadFile('csv') === false) {
            return 
false;
        }

        
$this->fieldMapUpdate();

        
$this->setSession('product-file'$this->getFilePath());

        
$headers $this->getDataHeaders();

        
$relations $this->fieldMap;

        
$fieldMap $this->mappingHeaders();

        
$step 2;

        
$exampleData $this->readFirstColumn();

        if (
count($exampleData) <= 1) {
            
$this->setError(__('Something went wrong, please try again.'));

            return 
false;
        }

        
$this->setResponse(view($this->getViewAndRoute('admin.epz.import.product'), compact('headers''fieldMap''relations''exampleData''step')));

        return 
$exampleData $this false;
    }

    
/**
     * Process second step of product import from wordress
     *
     * @return self
     */
    
public function importerStep2()
    {
        
// check if the data file has loaded
        
if ($this->loadSessionFile('product-file') === false) {
            return 
false;
        }

        
$columns $this->getColumns();
        
// check if the columns mapping failed
        
if ($columns === false) {
            return 
false;
        }
        
// Process the import data
        
$this->processImportableData($columns'processBatchStore');

        
// Store upsell and cross-sell data
        
$this->storeUpsellCrossSell();

        
// Clear cache for attribute
        
Attribute::forgetCache();
        
Attribute::forgetCache('attribute_values');

        
// Set user response for the next step
        
$this->setResponse(view($this->getViewAndRoute('admin.epz.import.product'), [
            
'step' => 3,
            
'products' => $this->totalUploaded,
            
'variations' => $this->totalVariations,
            
'skipped' => $this->totalSkipped
        
]));
        return 
$this;
    }

    
/**
     * Process products in batches
     *
     * @return void
     */
    
protected function processBatchStore($body)
    {
        
$filtered $this->applyFilters($body'attachCode''splitProduct');

        
// handle dependencies of the products
        
$this->dependencyHandler($filtered);

        
// store parent products first
        
$this->storeParentProducts();

        
// store variations
        
$this->storeChildProducts();

        
// reset the container for next batch of products
        
$this->resetForNextBatch();
    }

    
/**
     * Reset the class properties for next batch of products
     * @return void
     */
    
protected function resetForNextBatch()
    {
        
$newSkus array_values($this->skuBindings);

        
$newSkus array_flip($newSkus);

        
$this->skus array_merge($this->skus$newSkus);

        
$this->parentProducts = [];

        
$this->variationProducts = [];

        
$this->meta = [];
    }

    
/**
     * Stores parent products
     * @return void
     */
    
protected function storeParentProducts()
    {
        
$allInfo $this->parentProducts;
        
// pick only the data which are fillable for the model
        
$parentProducts $this->sortFillableData($allInfo);

        foreach (
$parentProducts as $key => $product) {
            
$product $this->storeSingleProduct($product);

            if (
false == $product) {
                
$this->totalSkipped++;
                continue;
            }

            
$product['upsell'] = $allInfo[$key]['upsells'] ?? '';
            
$product['cross_sell'] = $allInfo[$key]['cross_sells'] ?? '';

            
$this->totalUploaded++;
            
$this->storeRelatedInformation($product);
        }
    }

    
/**
     * Store variation/child products
     * @return void
     */
    
protected function storeChildProducts()
    {
        
$products $this->sortFillableData($this->variationProducts);

        foreach (
$products as $product) {
            
$parentId $this->getParentProductId($product['parent_id']);
            
// check if the product id is found
            
if (false == $parentId) {
                continue;
            }

            
$this->totalVariations++;

            
$product['parent_id'] = $parentId;

            
$product $this->storeSingleProduct($product);

            if (
false == $product) {
                continue;
            }

            
$this->storeRelatedInformation($product);
        }
    }

    
/**
     * Store product related data
     * @return void
     */
    
protected function storeRelatedInformation($product)
    {
        
$this->storeMetadata($product);

        
$this->storeCategories($product);

        
$this->storeTags($product);

        
$this->manageUpsellCrossSell($product);
    }

    
/**
     * Stores meta data
     *
     * @param Product $product
     *
     * @return bool
     */
    
protected function storeMetadata($product)
    {
        
$this->attachGroupedProductToMeta($product);

        
$meta = isset($this->meta[$product->code]) ? $this->meta[$product->code] : false;

        if (
false == $meta) {
            return 
false;
        }

        
$storableMeta = [];

        
$productId $product->id;
        try {
            foreach (
$meta as $metaName => $metaValue) {
                
$storableMeta[] = [
                    
'product_id' => $productId,
                    
'key' => $metaName,
                    
'value' => is_array($metaValue) ? json_encode($metaValue) : $metaValue,
                    
'type' => gettype($metaValue)
                ];
            }

            
ProductMeta::upsert($storableMeta, ['product_id''key'], ['value''type']);

            return 
true;
        } catch (
\Throwable $th) {
            return 
false;
        }
    }

    
/**
     * Organize upsale and cross sell data
     *
     * @param Product $product
     *
     * @return void
     */
    
private function manageUpsellCrossSell($product)
    {
        
$this->upsells[] = [$product->id => $product->upsell];

        
$this->crossSells[] = [$product->id => $product->cross_sell];
    }

    
/**
     * Store upsell and cross sell
     *
     * @param Product $product
     *
     * @return void
     */
    
private function storeUpsellCrossSell()
    {
        
$this->upsellService->process($this->upsells);

        
$this->crossSellService->process($this->crossSells);
    }

    
/**
     * Attach grouped products to the product meta
     *
     * @param Product $product
     *
     * @return void
     */
    
public function attachGroupedProductToMeta($product)
    {
        
$grouped $this->groupedProducts[$product->code] ?? [];

        if (
count($grouped) == 0) {
            return;
        }

        
$foreignProducts $localProducts = [];

        foreach (
$grouped as $sku) {
            if (isset(
$this->stored[$sku])) {
                
array_push($localProducts$this->stored[$sku]);
            } else {
                
array_push($foreignProducts$sku);
            }
        }

        if (
count($foreignProducts) > 0) {
            
$foreignProductsIds optional(Product::select('id')->where(function ($query) use ($foreignProducts) {
                
$query->whereIn('sku'$foreignProducts);
            })->
orWhere(function ($query) use ($foreignProducts) {
                
$query->whereIn('slug'$foreignProducts);
            })->
get())->pluck('id')->toArray();
        }

        if (isset(
$foreignProductsIds) && is_array($foreignProductsIds)) {
            
$localProducts array_merge($localProducts$foreignProductsIds);
        }

        if (!isset(
$this->meta[$product->code])) {
            
$this->meta[$product->code] = [];
        }

        
// push grouped products to meta data
        
$this->meta[$product->code]['meta_grouped_products'] = $localProducts;
    }

    
/**
     * Stores related categories
     *
     * @return boolean
     */
    
protected function storeCategories($product)
    {
        
$categories = isset($this->categories[$product->code]) ? $this->categories[$product->code] : false;

        if (
false == $categories) {
            return 
false;
        }

        return 
$product->category()->sync($categories);
    }

    
/**
     * Stores related tags
     *
     * @return boolean
     */
    
protected function storeTags($product)
    {
        
$tags = isset($this->tags[$product->code]) ? $this->tags[$product->code] : false;

        if (
false === $tags) {
            return 
false;
        }

        return 
$product->tags()->sync($tags);
    }

    
/**
     * Get parent id from sku
     * @param string $parentId SKU of parent
     * @param bool|integer
     */
    
protected function getParentProductId($parentId)
    {
        if (
str_starts_with($parentId'id:')) {
            
$parentId = isset($this->idFootPrints[$parentId]) ? $this->idFootPrints[$parentId] : $parentId;
        } else {
            
$parentId $this->getUpdatedSku($parentId);
        }

        return isset(
$this->stored[$parentId]) ? $this->stored[$parentId] : false;
    }

    
/**
     * Get the updated sku of given sku
     * @param string $sku
     * @return string
     */
    
protected function getUpdatedSku($code)
    {
        return isset(
$this->skuBindings[$code]) ? $this->skuBindings[$code] : $code;
    }

    
/**
     * Detach all the data from product array which are not fillable
     * @param array $products
     * @return array
     */
    
protected function sortFillableData($products)
    {
        
$fillable Product::getFillableData();

        
$fillable array_flip($fillable);

        for (
$i 0$i count($products); $i++) {
            
$product array_intersect_key($products[$i], $fillable);
            foreach (
$product as $key => $value) {
                if (
$value == '') {
                    
$product[$key] = null;
                }
            }
            
$products[$i] = $product;
        }
        return 
$products;
    }

    
/**
     * Stores single product
     * @param array $product Product data array
     * @return bool/Model
     */
    
protected function storeSingleProduct($product)
    {
        try {
            
$product Product::create($product);
            
$this->stored[$product->code] = $product->id;
            if (
$product->sku) {
                
$this->stored[$product->sku] = $product->id;
            }
            return 
$product;
        } catch (
\Throwable $th) {
            return 
false;
        }
    }

    
/**
     * Handles product dependencies
     * @return void
     */
    
protected function dependencyHandler(&$data)
    {
        foreach (
$data as $key => $product) {
            
// Handle Categories
            
$categories $this->handleCategory($product);

            
$this->categories[$data[$key]['code']] = $categories;
            unset(
$data[$key]['categories']);

            
// Handle tags
            
$tags $this->handleTags($product);
            
$this->tags[$data[$key]['code']] = $tags;
            unset(
$data[$key]['tags']);
        }
    }

    
/**
     * Generates array of category id
     *
     * @return array
     */
    
protected function handleCategory($data)
    {
        
$category $this->categoryService->process($data['categories'] ?? null);

        unset(
$data['categories']);

        return 
$category;
    }

    
/**
     * Generates array of tags id
     *
     * @return array
     */
    
public function handleTags($data)
    {
        
$tags $this->tagService->process($data['tags'] ?? '');

        unset(
$data['tags']);

        return 
$tags;
    }

    protected function 
filterVendorId($data)
    {
        
$data['vendor_id'] = null;
        return 
$data;
    }
    
/**
     * Filters featured column
     *
     * @return array
     */
    
protected function filterFeatured($data)
    {
        
$data['featured'] = isset($data['featured']) && $data['featured'] == now() : null;
        return 
$data;
    }

    
/**
     * Filters status column
     *
     * @return array
     */
    
protected function filterStatus($data)
    {
        if (
$this->hasParentId($data)) {
            
$data['status'] = ProductStatus::$Published;
        } else {
            
$data['status'] = isset($data['published']) && $data['published'] == ProductStatus::$Published ProductStatus::$Draft;
        }
        return 
$data;
    }

    protected function 
filterIdFootprint($data)
    {
        if (isset(
$data['id'])) {
            
$this->idFootPrints['id:' $data['id']] =  $data['code'];
            unset(
$data['id']);
        }
        return 
$data;
    }

    
/**
     * Splits the product list into parent and variation lists
     * Also create a parent child dependency array
     * @param array $data
     * @return array
     */
    
protected function splitProduct($data)
    {
        if (
$this->hasParentId($data)) {
            
// dependent
            
$this->variationProducts[] = $data;
            
$this->parentIds[$data['code']] = $data['parent_id'];
        } else {
            
// independent
            
$this->parentProducts[] = $data;
            
$data['parent_id'] = null;
        }

        return 
$data;
    }

    
/**
     * Attaches Unique data
     *
     * @return array
     */
    
protected function attachCode($data)
    {
        
$data['code'] = $data['code'] ?? \Str::random(5) . uniqid();
        return 
$data;
    }

    
/**
     * Filters product type
     *
     * @param array $data
     *
     * @return array
     */
    
protected function filterType($data)
    {
        
$typeArray array_map("trim"explode(","$data['type'] ?? ''));

        
$replacables = [
            
'variable' => ProductType::$Variable,
            
'variation' => ProductType::$Variation,
            
'grouped' => ProductType::$Grouped,
            
'external' => ProductType::$External,
        ];

        
// Attach meta types
        
$typeMeta = [];

        if (
in_array('downloadable'$typeArray)) {
            
$typeMeta['meta_downloadable'] = true;
        }

        if (
in_array('virtual'$typeArray)) {
            
$typeMeta['meta_virtual'] = true;
        }

        
$this->meta[$data['code']] = $typeMeta;

        
$data['type'] = ProductType::$Simple;

        foreach (
$replacables as $current => $replacement) {
            if (
in_array($current$typeArray)) {
                
$data['type'] = $replacement;
                break;
            }
        }

        return 
$data;
    }

    public function 
filterStocks($data)
    {
        if (!isset(
$data['total_stocks']) || empty($data['total_stocks'])) {
            
$data['total_stocks'] = 0;
        }

        return 
$data;
    }

    
/**
     * Filters product name
     * @param array $data
     * @return array
     */
    
protected function filterName($data)
    {
        if (!isset(
$data['name']) || trim($data['name']) == '') {
            
$data['name'] = 'Untitled Product';
        }
        return 
$data;
    }

    
/**
     * Handles sku and slug
     */
    
protected function filterSkuAndSlug($data)
    {
        if (!
$this->hasParentId($data)) {
            if (!
$this->hasSlug($data)) {
                
$data['slug'] = \Str::slug($data['name']);
            }

            
$slug $data['slug'];

            
$this->prefetchSlugs($slug);

            
$slug $this->generateSlug($slug);

            
$data['slug'] = $slug;
        }

        if (
$this->hasSku($data)) {

            
$sku $this->generateSku($data['sku']);

            if (
$sku <> $data['sku']) {
                
$this->skuBindings[$data['sku']] = $sku;
            }

            
$data['sku'] = $sku;
        }

        return 
$data;
    }

    
/**
     * Checks if the product has parent id
     */
    
protected function hasParentId($product)
    {
        return isset(
$product['parent_id']) && (trim($product['parent_id']) <> '' || $product['parent_id'] <> null);
    }

    
/**
     * Checks if the product has either sku or slug
     */
    
private function hasSkuOrSlug($product)
    {
        return 
$this->hasSku($product) || $this->hasSlug($product);
    }

    
/**
     * Checks if the product data has SKU
     * @return bool
     */
    
private function hasSku($product)
    {
        return isset(
$product['sku']) && (trim($product['sku']) == '' || $product['sku'] <> null);
    }

    
/**
     * Check if the product data has slug
     * @return bool
     */
    
private function hasSlug($product)
    {
        return isset(
$product['slug']) && (trim($product['slug']) == '' || $product['slug'] <> null);
    }

    
/**
     * Generates unique SKU
     * @param string $sku
     * @return string
     */
    
protected function generateSku($sku)
    {
        
$sku \Str::slug($sku);
        
$counter 1;
        
$ext '';
        do {
            
$newSku $sku $ext;
            
$ext '-' $counter;
        } while (isset(
$this->skus[$newSku]) && $counter++);

        return 
$newSku;
    }

    
/**
     * Generates unique slug
     * @param string $slug
     * @return string
     */
    
protected function generateSlug($slug)
    {
        
$slug \Str::slug($slug);
        
$counter 1;
        
$ext '';
        do {
            
$newSlug $slug $ext;
            
$ext '-' $counter;
        } while (isset(
$this->slugs[$newSlug]) && $counter++);

        return 
$newSlug;
    }

    
/**
     * Prefetch product slugs and skus to compare
     */
    
private function prefetchSlugs($slug)
    {
        
$products Product::whereLike('slug'$slug)->orWhereLike('sku'$slug)->get();

        
$products->map(function ($product) {
            if (
$product->slug && !isset($this->slugs[$product->slug])) {
                
$this->slugs[$product->slug] = 1;
            }
            if (
$product->sku && !isset($this->skus[$product->sku])) {
                
$this->skus[$product->sku] = 1;
            }
        });
    }

    
/**
     * Check if the product's meta exists
     *
     * @param string $code Products unique code
     *
     * @return bool
     */
    
protected function metaExists($code)
    {
        return isset(
$this->meta[$code]);
    }

    
/**
     * Filter Date
     *
     * @param array $data
     * @return array $data
     */
    
protected function filterDate($data)
    {
        
$dates = ['sale_from''sale_to''available_from''available_to'];

        foreach (
$dates as $date) {
            if (isset(
$data[$date]) && !empty($data[$date])) {
                
$data[$date] = DbDateFormat($data[$date]);
            }
        }

        return 
$data;
    }

    
/**
     * Clean meta information from product data
     * Inject meta data into product data
     * Filter meta data
     *
     * This is a long method which can be splitted into separate method
     *
     * @param array $data
     *
     * @return array
     */
    
protected function filterMeta($data)
    {
        
$meta = [];
        
$stockStatus $data['meta_stock_status'] ?? 0;
        
$meta['meta_stock_status'] = $stockStatus == 'In Stock' : ($stockStatus == 'backorder' 'On Backorder' 'Out Of Stock');
        unset(
$data['meta_stock_status']);

        
$meta['meta_stock_threshold'] = isset($data['meta_stock_threshold']) ? $data['meta_stock_threshold'] : '';
        unset(
$data['meta_stock_threshold']);

        
$meta['meta_image'] = isset($data['meta_image']) ? array_filter(array_map("trim"explode(","$data['meta_image']))) : '';
        unset(
$data['meta_image']);

        
$meta['meta_enable_reviews'] = isset($data['meta_enable_reviews']) ? $data['meta_enable_reviews'] : '';
        unset(
$data['meta_enable_reviews']);

        
$meta['meta_tax_classes'] = isset($data['meta_tax_classes']) ? $data['meta_tax_classes'] : '';
        unset(
$data['meta_tax_classes']);

        
$meta['meta_backorder'] = isset($data['meta_backorder']) ? $data['meta_backorder'] : '';
        unset(
$data['meta_backorder']);

        
$meta['meta_cash_on_delivery'] = isset($data['meta_cash_on_delivery']) ? $data['meta_cash_on_delivery'] : '';
        unset(
$data['meta_cash_on_delivery']);

        
$meta['meta_weight'] = isset($data['meta_weight']) ? $data['meta_weight'] : '';
        unset(
$data['meta_weight']);

        
$meta['meta_dimension'] = isset($data['meta_dimension']) ? $data['meta_dimension'] : '';
        unset(
$data['meta_dimension']);

        
$meta['meta_purchase_note'] = isset($data['meta_purchase_note']) ? $data['meta_purchase_note'] : '';
        unset(
$data['meta_purchase_note']);

        
$meta['meta_external_product'] = $data['meta_external_product'] ?? '';

        
$meta['meta_individual_sale'] = $data['meta_individual_sale'] ?? 0;
        unset(
$data['meta_individual_sale']);

        
$meta['meta_download_limit'] = $data['meta_download_limit'] ?? 0;
        unset(
$data['meta_download_limit']);

        if (
isActive("B2B")) {
            
$meta['meta_enable_b2b'] = $data['meta_enable_b2b'] ?? 0;
            unset(
$data['meta_enable_b2b']);
        }

        
// Inject meta data into product data
        // check if the product already has metadata
        // else create a blank meta data array
        // then insert new array
        
if (!isset($this->meta[$data['code']])) {
            
$this->meta[$data['code']] = [];
        }
        
$this->meta[$data['code']] = array_merge($this->meta[$data['code']], $meta);
        return 
$data;
    }

    
/**
     * Filter attribute
     */
    
protected function filterAttribute($data)
    {
        if (!
$this->hasParentId($data)) {
            
$attributes =  $this->getAttributesFromProduct($data);
            if (
$attributes) {
                
$this->meta[$data['code']]['attributes'] = $attributes;
            }
        } else {
            
$attributes $this->getAttributeMetaFromProduct($data);
            if (
$attributes) {
                
$meta array_merge($this->meta[$data['code']], $attributes);
                
$this->meta[$data['code']] = $meta;
            }
        }
        unset(
$data['attribute']);

        return 
$data;
    }

    
/**
     * filter B2B data
     *
     * @param $data
     * @return void
     */
    
protected function filterB2B($data)
    {
        if (
isActive('B2B')) {
            
$b2bData $this->b2bDataFormat($data['bb'] ?? []);
            unset(
$data['bb']);
            
// check if it has downloadable data
            
if (count($b2bData) == 0) {
                return 
$data;
            }
            
// check if product already has meta data
            // else create blank meta data array
            
if (!isset($this->meta[$data['code']])) {
                
$this->meta[$data['code']] = [];
            }
            
// push downloadable data to meta array
            
$this->meta[$data['code']]['meta_b2b_data'] = $b2bData;
        }

        return 
$data;
    }

    
/**
     * b2b data format
     *
     * @param $data
     * @return array
     */
    
protected function b2bDataFormat($data)
    {
        if (!
is_array($data)) {
            return [];
        }

        
$formatted = array();

        foreach (
$data as $index => $item) {
            if (isset(
$item['min']) && $item['min'] != '' || isset($item['max']) && $item['max'] != '' || isset($item['price']) && $item['price'] != '') {
                
$formatted[] = [
                    
'min_qty' => $item['min'] ?? '',
                    
'max_qty' => $item['max'] ?? '',
                    
'price' => $item['price'] ?? '',
                ];
            }
        }

        return 
$formatted;
    }

    
/**
     * Filter downloadable data of the product
     *
     * @param array $data
     *
     * @return array
     */
    
protected function filterDownloadables($data)
    {
        
$downloadables $this->trimDownloadableData($data['downloadable'] ?? []);
        unset(
$data['downloadable']);
        
// check if it has downloadable data
        
if (count($downloadables) == 0) {
            return 
$data;
        }
        
// check if product already has meta data
        // else create blank meta data array
        
if (!isset($this->meta[$data['code']])) {
            
$this->meta[$data['code']] = [];
        }
        
// push downloadable data to meta array
        
$this->meta[$data['code']]['meta_downloadable_files'] = array_values($downloadables);
        return 
$data;
    }

    
/**
     * Filter grouped product data
     *
     * @param array $data
     *
     * @return array
     */
    
public function filterGroupedProducts($product)
    {
        
$groupedProducts $product['meta_grouped_products'] ?? [];
        if (!
is_array($groupedProducts)) {
            
$groupedProducts array_filter(array_map("trim"explode(","$groupedProducts)));
        }
        unset(
$product['meta_grouped_products']);
        
// Return if the products doesn't have any grouped product
        
if (count($groupedProducts) == 0) {
            return 
$product;
        }

        
// Get the latest skus references
        
$groupedProducts array_map(function ($sku) {
            return 
$this->getUpdatedSku($sku);
        }, 
$groupedProducts);

        
// push downloadable data to meta array
        
$this->groupedProducts[$product['code']] = $groupedProducts;

        return 
$product;
    }

    
/**
     * Trim downloadable files data
     *
     * @param array $data
     *
     * @return array
     */
    
private function trimDownloadableData($data)
    {
        if (!
is_array($data)) {
            return [];
        }
        
$trimmed = array();
        foreach (
$data as $index => $item) {
            if (!isset(
$item['url']) || trim($item['url']) == '') {
                continue;
            }
            if (!isset(
$item['name']) || trim($item['name']) == '') {
                
$item['name'] = 'File-' $index;
            }
            
array_push($trimmed$item);
        }
        return 
$trimmed;
    }

    
/**
     * Extracts attribute meta from product
     * @param array $product
     * @return array;
     */
    
private function getAttributeMetaFromProduct($product)
    {
        
$attributes = [];

        if (!isset(
$product['attribute'])) {
            return 
false;
        }

        foreach (
$product['attribute'] as $attribute) {

            
$attribute miniCollection($attributetrue);
            
$slug \Str::slug($attribute->title);

            if (
$attribute->variation != 1) {
                
$attributes['attribute_' $slug] = $attribute->value;
                continue;
            }
            
$aValue Attribute::where('name'$attribute->title)
                ->
leftJoin('attribute_values''attributes.id''=''attribute_values.attribute_id')
                ->
where('attribute_values.value'$attribute->value)
                ->
selectRaw('attributes.id as id, attribute_values.id as vid')
                ->
first();

            
$attributes['attribute_' $slug] = $aValue $aValue->vid '';
        }

        return 
$attributes;
    }

    
/**
     * Extracts attribute from product
     * @param array $product
     * @return bool|array;
     */
    
private function getAttributesFromProduct($product)
    {
        
$attributes = [];
        if (!isset(
$product['attribute'])) {
            return 
false;
        }

        foreach (
$product['attribute'] as $index => $attribute) {
            
$attribute miniCollection($attributetrue);

            if (!
$attribute->title) {
                continue;
            }

            
$attribute->value array_map('trim'explode(","$attribute->value));

            if (
$attribute->variation == 1) {
                
$fetchAttribute =  Attribute::updateOrCreate(['name' => $attribute->title]);
                
$attribute->value $this->getAttributeValue($fetchAttribute->id$attribute->value);
                
$attribute->attributeId $fetchAttribute->id;
            }

            
$slug \Str::slug($attribute->title);

            
$attribute $this->checkAttributeValidity([
                
'name' => $attribute->title,
                
'position' => $index,
                
'key' => $slug,
                
'value' => $attribute->value ?? [],
                
'variation' => $attribute->variation,
                
'visibility' => $attribute->visibility,
                
'attribute_id' => $attribute->attributeId
            
]);

            if (
$attribute) {
                
$attributes[$slug] = $attribute;
            }
        }

        return 
$attributes;
    }

    
/**
     * Checks if the attribute data is complete and usable
     *
     * @param array $attribute
     *
     * @return bool|array
     */
    
protected function checkAttributeValidity($attribute)
    {
        if (!isset(
$attribute['name']) || !isset($attribute['value']) || !isset($attribute['key'])) {
            return 
false;
        }
        return 
$attribute;
    }

    private function 
getAttributeFromSlug($name)
    {
        return 
Attribute::select('id''name')->whereName($name)->first();
    }

    
/**
     * Store attribute values and returns their id
     *
     * @param int $attribute
     * @param array $values
     *
     * @return array
     */
    
private function getAttributeValue($attribute$values)
    {
        
$attributeValues = [];
        
// Prepare insertable attribute values
        
foreach ($values as $value) {
            
$attributeValues[] = [
                
'attribute_id' => $attribute,
                
'value' => $value,
                
'order_by' => 0,
            ];
        }
        
// Insert or update attribute values
        
AttributeValue::upsert($attributeValues, ['attribute_id''value'], []);

        
$attributeValues AttributeValue::select('id')
            ->
whereIn('value'$values)
            ->
where('attribute_id'$attribute)
            ->
get();

        return !
is_null($attributeValues) && count($attributeValues) > $attributeValues->pluck('id')->toArray() : [];
    }

    
/**
     * Headers for the expected field
     *
     * @return Closure
     */
    
private function mappingHeaders()
    {
        return function (
$field) {
            
$index $field;

            
$field \Str::slug($field);

            if (
preg_match('/\b\d+\b/'$field$matches)) {
                
$index $matches[0];
            }

            
$data = [
                
"id" => __("ID"),
                
"name" => __("Name"),
                
"type" => __("Type"),
                
"sku" => __("SKU"),
                
"description" => __("Description"),
                
"summary" => __("Summary"),
                
"parent_id" => __("Parent"),
                
"featured" => __("Featured"),
                
"published" => __("Published"),
                
__("Price") => [
                    
"regular_price" => __("Regular Price"),
                    
"sale_price" => __("Sale Price"),
                ],
                
__("Date") => [
                    
"available_from" => __("Available From"),
                    
"available_to" => __("Available To"),
                    
"sale_from" => __("Sale From"),
                    
"sale_to" => __("Sale To")
                ],
                
__("Dimentions") => [
                    
"meta_weight" => __("Weight"),
                    
"meta_dimension:height" => __("Height"),
                    
"meta_dimension:length" => __("Length"),
                    
"meta_dimension:width" => __("Width")
                ],
                
__("External Product") => [
                    
"meta_external_product:text" => __("Button Text"),
                    
"meta_external_product:url" => __("Product URL"),
                ],
                
"meta_grouped_products" => __("Grouped Products"),
                
"categories" => __("Categories"),
                
"tags" => __("Tags"),
                
"meta_backorder" => __("Allow Backorder"),
                
"meta_image" => __("Images"),
                
"upsells" => __("Upsells"),
                
__("Stock") => [
                    
"manage_stocks" => __("Manage Stock?"),
                    
"total_stocks" => __("Total Stock"),
                    
"meta_stock_status" => __("Stock Status"),
                    
"meta_stock_threshold" => __("Stock Threshold"),
                ],
                
"cross_sells" => __("Cross Sells"),
                
"meta_enable_reviews" => __("Enable Review"),
                
"meta_purchase_note" => __("Purchase Note"),
                
"meta_shipping_class" => __("Shipping Class"),
                
"meta_cash_on_delivery" => __("Cash On Delivery"),
                
"meta_tax_classes" => __("Tax Class"),
                
"meta_individual_sale" => __("Sold Individually"),
                
__("Attributes") => [
                    
"attribute:title." $index => __("Attribute Title"),
                    
"attribute:value." $index => __("Attribute Value"),
                    
"attribute:visibility." $index => __("Attribute Visible"),
                    
"attribute:variation." $index => __("Attribute For Variation"),
                    
"attribute:default." $index => __("Attribute Default")
                ],
                
__("Downloadable") => [
                    
"downloadable:id." $index => __("Download ID"),
                    
"downloadable:name." $index => __("Download Name"),
                    
"downloadable:url." $index => __("Download Url"),
                ],
                
"meta_download_limit" => __("Download Limit"),
                
"meta_" $field => __("Meta Informations")
            ];

            if (
isActive("B2B")) {

                
$data array_merge($data, ['meta_enable_b2b' => __('Is B2B?'),__("B2B") => [
                    
"bb:min." $index => __("B2B Min(qty)"),
                    
"bb:max." $index => __("B2B Max(qty)"),
                    
"bb:price." $index => __("B2B Price"),
                ]]);
            }
            return 
$data;
        };
    }

    
/**
     * Process fetched to into column => data associative array
     *
     * @param array $columns [] Default
     * @param array $rowData
     *
     * @return array|bool
     */
    
protected function assignDataToColumns($columns = [], $rowData)
    {
        if (!
is_array($rowData)) {
            return 
false;
        }

        foreach (
$columns as $name => $index) {
            
// Extract the arrayable column name from the provided name
            
$arrayableName strtok($name":");
            
// Check if the arrayable column has attribute name attached
            
if ($attribute strtok(".")) {
                
// Check if the attribute has Index
                
if ($aIndex strtok("")) {
                    
// Attach the arrayable data in a indexed manner
                    
$columns[$arrayableName][$aIndex][$attribute] = $rowData[$index] ?? null;
                } else {
                    
// If index number not found the use attribute as array keys
                    
$columns[$arrayableName][$attribute] = $rowData[$index] ?? null;
                }
                
// Unset the actual column
                
unset($columns[$name]);
            } else {
                
$columns[$name] = $rowData[$index] ?? null;
            }
        }
        return 
$columns;
    }

    
/**
     * Explodes column name and returns the arrayable name;
     * @param string $name
     * @return string
     */
    
protected function getArrayableName($name)
    {
        
$name explode(":"$name);
        return 
$name[0];
    }

    public function 
getViewAndRoute(string $name)
    {
        return 
$name;
    }

    public function 
fieldMapUpdate()
    {
        if (
isActive("B2B")) {
            
$this->fieldMap array_merge($this->fieldMap, ['Is B2B?' => 'meta_enable_b2b','bbmin' => 'bbmin''bbmax' => 'bbmax''bbprice' => 'bbprice']);
        }
    }
}

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ ok ]

:: Make Dir ::
 
[ ok ]
:: Make File ::
 
[ ok ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.006 ]--