AnonSec Shell
Server IP : 54.36.91.62  /  Your IP : 216.73.217.117
Web Server : Apache
System : Linux webm013.cluster127.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User : coopiak ( 151928)
PHP Version : 8.3.23
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/coopiak/amisdesseniors-fr/sartrouville/components/com_djcatalog2/helpers/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/coopiak/amisdesseniors-fr/sartrouville/components/com_djcatalog2/helpers/cart.php
<?php

/**
 * @package DJ-Catalog2
 * @copyright Copyright (C) DJ-Extensions.com, All rights reserved.
 * @license http://www.gnu.org/licenses GNU/GPL
 * @author url: http://dj-extensions.com
 * @author email contact@dj-extensions.com
 */

use Joomla\Registry\Registry;

defined('_JEXEC') or die('Restricted access');

require_once(JPATH_ROOT . '/components/com_djcatalog2/helpers/price.php');
require_once(JPATH_ROOT . '/components/com_djcatalog2/helpers/quantity.php');
require_once(JPATH_ROOT . '/components/com_djcatalog2/helpers/coupon.php');

class Djcatalog2HelperCart
{
    static $baskets = array();

    protected $_errors = array();

    protected $quantitiesItems = array();

    public $items = array();
    public $quantities = array();
    public $prices = array();

    public $productTypes = array('tangible' => 0, 'virtual' => 0, 'hybrid' => 0, 'subscription' => 0, 'bundle' => 0);

    public $delivery = false;
    public $payment = false;

    public $coupon = false;
    public $coupon_value = 0.0;

    public $product_total = array();
    public $total = array();
    public $sub_totals = array();
    public $product_old_total = array();
    public $attributes = null;
    public $attribute_values = array();
    public $features = null;
    // product features & customisable product features
    public $feature_values = array();
    // Customisable product dimensions
    public $dimension_values = array();
    public $customisations = array();
    public $calculators = array();
    public $discount_value = 0.0;
    public $price_components = array();
    public $shipping_days = 1;
    public $related_accessories = array();
    public $forceRecurring = false;
    public $recurringDate = null;
    /**
     * Weight is being stored in grams
     * @var float
     */
    public $total_weight = 0.0;

    public $gauges_map = [];

    /**
     * @var stdClass
     */
    public $currency;

    /**
     * Dimensions are being stored in meters
     * @var array
     */
    public $total_dimensions = array('length' => 0.0, 'width' => 0.0, 'height' => 0.0);

    protected static $tmpFiles = array();

    /**
     *
     * Retrieves or creates DJCatalog2HelperCart object
     * @param bool $from_storage
     * @param array $cart_items
     * @return DJCatalog2HelperCart
     */

    public static function getInstance($from_storage = true, $cart_items = array())
    {
        $app = JFactory::getApplication();
        $params = Djcatalog2Helper::getParams();

        if ($from_storage) {
            $stored_items = $app->getUserState('com_djcatalog2.cart.items', array());
            if (empty($cart_items) && !empty($stored_items)) {
                $cart_items = $stored_items;
            } else if ($params->get('cart_cookie_enable', 1)) {
                $cookie_val = $app->input->cookie->getString('djc2cart');
                if ($cookie_val != '') {
                    try {
                        $cart_items = json_decode((string)$cookie_val, true);
                    } catch (Exception $e) {
                        $cart_items = array();
                    }
                }
            }
        }

        $db = JFactory::getDBO();
        $user = JFactory::getUser();

        if ($from_storage && $user->id) {
            $query = $db->getQuery(true)->select('*')->from('#__djc2_usercarts')->where('user_id = ' . $user->id);
            $db->setQuery($query);
            $usercart = $db->loadObject();

            if (empty($cart_items) && $usercart) {
                $cart_items = json_decode((string)$usercart->items, true);
            } else {
                if ($usercart) {
                    $query = $db->getQuery(true)->delete('#__djc2_usercarts')->where('user_id=' . $user->id);
                    $db->setQuery($query);
                    $db->execute();
                }

                if ($cart_items) {
                    $query = $db->getQuery(true);
                    $query->insert('#__djc2_usercarts');
                    $query->columns(array('user_id', 'items'));
                    $query->values($user->id . ',' . $db->quote(json_encode($cart_items)));
                    $db->setQuery($query);
                    $db->execute();
                }
            }
        }

        $delivery_id = $app->getUserState('com_djcatalog2.cart.delivery', false);
        $payment_id = $app->getUserState('com_djcatalog2.cart.payment', false);
        $shipping_days = $app->getUserState('com_djcatalog2.cart.shipping_days', false);

        $custom_items = (array)$app->getUserState('com_djcatalog2.cart.custom_items', array());

        //$cart_items = array_merge($cart_items, array_keys($custom_items));
        if (is_array($custom_items) && count($custom_items) > 0) {
            foreach ($custom_items as $csid => $citem) {
                if (empty($citem->_quantity)) continue;
                $cart_items[$csid] = $citem->_quantity;
            }
        }

        $hash = md5(serialize($cart_items) . ':' . $delivery_id . ':' . $payment_id);

        if (isset(self::$baskets[$hash])) {
            return self::$baskets[$hash];
        }

        $basket = new Djcatalog2HelperCart();

        if (!empty($cart_items)) {

            $basket->items = array();
            $basket->quantities = array();

            JModelLegacy::addIncludePath(JPath::clean(JPATH_ROOT . '/components/com_djcatalog2/models'), 'DJCatalog2Model');
            $model = JModelLegacy::getInstance('Items', 'DJCatalog2Model', array('ignore_request' => true));
            $itemModel = JModelLegacy::getInstance('Item', 'DJCatalog2Model', array('ignore_request' => true));

            $state = $model->getState();

            $model->setState('list.start', 0);
            $model->setState('list.limit', 0);

            $juser = JFactory::getUser();
            $user = Djcatalog2Helper::getUserProfile($app->getUserState('com_djcatalog2.checkout.user_id', null));
            if (isset($user->customer_group_id)) {
                $model->setState('filter.customergroup', $user->customer_group_id);
            }

            $model->setState('filter.catalogue', false);
            $model->setState('list.ordering', 'i.name');
            $model->setState('list.direction', 'asc');
            $model->setState('filter.parent', '*');
            $model->setState('filter.state', '3');
            $model->setState('list.fields_visibility', '*');

            $basketIds = array();
            $ids = array();
            foreach ($cart_items as $sid => $qty) {
                $sidParts = self::parseSid($sid);
                if (!$sidParts || empty($sidParts['id'])) {
                    continue;
                }
                $sidParts['qty'] = $qty;
                $basketIds[$sid] = $sidParts;
                $ids[] = $sidParts['id'];
            }
            $model->setState('filter.item_ids', $ids);
            $list = $model->getItems();
            if (count($list) > 0) {
                foreach ($basketIds as $sid => $sidData) {
                    if (isset($list[$sidData['id']])) {
                        $item = clone $list[$sidData['id']];
                        $item->_sid = $sid;
                        $item->_combination_id = $sidData['combination_id'];

                        $type = (!empty($item->product_type)) ? $item->product_type : 'tangible';

                        if ($item->_combination_id > 0) {
                            if ($combination = $itemModel->getCombination($item->_combination_id)) {
                                $item->_combination = $combination;
                                $item->stock = $combination->stock;

                                if (($type == 'tangible' || $type == 'hybrid') && $item->onstock > 0) {
                                    if ($item->onstock == 3) {
                                        $item->onstock = 2;
                                    } else {
                                        $item->onstock = $combination->stock > 0 ? 1 : 0;
                                    }
                                }

                                if ($combination->sku != '') {
                                    $item->sku = $combination->sku;
                                } else if ($item->sku != '') {
                                    $item->sku .= '-CMB-' . $combination->id;
                                } else {
                                    $item->sku = 'ID-' . $item->id . '-CMB-' . $combination->id;
                                }

                                if ($combination->price > 0) {
                                    $item->final_price = $item->price = $combination->price;
                                }
                                if (isset($combination->final_price) && $combination->final_price > 0.0) {
                                    $item->final_price = $item->final_price = $combination->final_price;
                                }

                                if ($combination->length > 0) {
                                    $item->length = $combination->length;
                                }
                                if ($combination->width > 0) {
                                    $item->width = $combination->width;
                                }
                                if ($combination->height > 0) {
                                    $item->height = $combination->height;
                                }
                                if ($combination->weight > 0) {
                                    $item->weight = $combination->weight;
                                }
                            } else {
                                continue;
                            }
                        }

                        if ($item->price_tier_modifier != '0') {
                            $item->_price_tiers = $itemModel->getTierPrices($item->id);
                        } else {
                            $item->_price_tiers = array();
                        }

                        $unit = DJCatalog2HelperQuantity::getUnit($item->unit_id);
                        $item->_unit = $unit->unit;

                        if ($juser->guest) {
                            if ($params->get('price_restrict') == '1' || $item->price_restrict) {
                                $item->final_price = $item->price = $item->special_price = 0.0;
                            }
                        }

                        $basket->items[$sid] = $item;

                        $qty = DJCatalog2HelperQuantity::validateQuantity($sidData['qty'], $unit);
                        $basket->quantities[$sid] = $qty;

                        //Save quantity value
                        $basket->quantitiesItems[$sidData['id']] = $qty;

                        $basket->productTypes[$type]++;

                        if ($type == 'bundle') {
                            $bundle_items = $basket->getBundleItems($item);
                            foreach ($bundle_items as $bundle_item) {
                                $bundle_type = $bundle_item['item']->product_type;
                                $basket->productTypes[$bundle_type]++;
                            }
                        }
                    }
                }
            }

            if ($from_storage) {
                $stored_attributes = $app->getUserState('com_djcatalog2.cart.attributes', array());
                $stored_features = $app->getUserState('com_djcatalog2.cart.features', array());
                $dimension_values = $app->getUserState('com_djcatalog2.cart.dimension_values', array());
                $stored_customisations = $app->getUserState('com_djcatalog2.cart.customisations', array());
                $stored_calculators = $app->getUserState('com_djcatalog2.cart.calculators', array());

                $basket->attribute_values = $stored_attributes;
                $basket->feature_values = $stored_features;
                $basket->dimension_values = $dimension_values;
                $basket->customisations = $stored_customisations;
                $basket->calculators = $stored_calculators;
            }

            $stored_prices = $app->getUserState('com_djcatalog2.cart.prices', array());
            if (!empty($stored_prices)) {
                $basket->prices = $stored_prices;
            }
        }

        if (!empty($custom_items)) {
            $temp = [];
            foreach ($custom_items as $ck => $cv) {
                if (isset($basket->quantities[$ck])) {
                    $cv->_quantity = $basket->quantities[$ck];
                }
                if (isset($cv->_prices)) {
                    unset($cv->_prices);
                }
                $temp[$ck] = $cv;
            }
            $basket->setCustomItems($temp);
        }

        $coupon_id = $app->getUserState('com_djcatalog2.cart.coupon', false);

        if ($shipping_days !== false) {
            $basket->setShippingDays($shipping_days);
        }
        if ($delivery_id !== false) {
            $basket->setDelivery($delivery_id);
        }
        if ($payment_id !== false) {
            $basket->setPayment($payment_id);
        }
        if ($coupon_id !== false) {
            $coupon = Djcatalog2HelperCoupon::getCouponById($coupon_id);
            $basket->setCoupon($coupon, false);
        }

        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();
        Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2CartGetInstance', array(&$basket));

        $basket->recalculate();

        self::$baskets[$hash] = $basket;

        return self::$baskets[$hash];
    }

    public function getTotal()
    {
        return $this->total;
    }

    public function getProductTotal()
    {
        return $this->product_total;
    }

    public function getProductOldTotal()
    {
        return $this->product_old_total;
    }

    public function getSubTotals()
    {
        return $this->total;
    }

    public function getItems()
    {
        return $this->items;
    }

    public function getTotalWeight()
    {
        return $this->total_weight;
    }

    public function getTotalDimensions()
    {
        return $this->total_dimensions;
    }

    public function getGaugesMap()
    {
        return $this->gauges_map;
    }

    public function getCurrencyCode()
    {
        if ($this->currency) {
            return $this->currency->currency;
        }

        $params = JComponentHelper::getParams('com_djcatalog2');
        return strtoupper($params->get('cart_currency', ''));
    }

    public function getCurrencyID()
    {
        if ($this->currency) {
            return $this->currency->id;
        }
        return 0;
    }

    public function removeItem($sid, $lazy = false)
    {

        foreach ($this->items as $k => $v) {
            if ($v->_sid == $sid) {
                unset($this->items[$k]);
            }
        }

        if (isset($this->quantities[$sid])) {
            unset($this->quantities[$sid]);
        }

        if (isset($this->prices[$sid])) {
            unset($this->prices[$sid]);
        }

        if (isset($this->attribute_values[$sid])) {
            unset($this->attribute_values[$sid]);
        }

        if (isset($this->feature_values[$sid])) {
            unset($this->feature_values[$sid]);
        }

        if (isset($this->customisations[$sid])) {
            unset($this->customisations[$sid]);
        }

        $app = JFactory::getApplication();
        $custom_items = (array)$app->getUserState('com_djcatalog2.cart.custom_items', array());
        if (isset($custom_items[$sid])) {
            unset($custom_items[$sid]);
            $app->setUserState('com_djcatalog2.cart.custom_items', $custom_items);
        }

        if (!$lazy) {
            $this->recalculate();
        }

        return true;
    }

    public function addItem($item, $combination_id = 0, $features = [], $customisations = [], $dimensions = [], $configurable = [], $quantity = 1, $lazy = false, $calculator = [])
    {
        $params = Djcatalog2Helper::getParams();

        if (is_scalar($item) && (int)$item > 0) {

            JModelLegacy::addIncludePath(JPath::clean(JPATH_ROOT . '/components/com_djcatalog2/models'), 'DJCatalog2Model');

            $itemModel = JModelLegacy::getInstance('Item', 'DJCatalog2Model', array('ignore_request' => true));

            $item = $itemModel->getItem($item);

            if (!empty($item)) {
                $type = (!empty($item->product_type)) ? $item->product_type : 'tangible';

                if ($combination_id > 0) {
                    if ($combination = $itemModel->getCombination($combination_id)) {
                        $item->_combination = $combination;
                        $item->stock = $combination->stock;

                        if (($type == 'tangible' || $type == 'hybrid') && $item->onstock > 0) {
                            if ($item->onstock == 3) {
                                $item->onstock = 2;
                            } else {
                                $item->onstock = $combination->stock > 0 ? 1 : 0;
                            }
                        }

                        if ($combination->sku != '') {
                            $item->sku = $combination->sku;
                        } else if ($item->sku != '') {
                            $item->sku .= '-CMB-' . $combination->id;
                        } else {
                            $item->sku = 'ID-' . $item->id . '-CMB-' . $combination->id;
                        }

                        if ($combination->price > 0) {
                            $item->final_price = $item->price = $combination->price;
                        }
                        if (isset($combination->final_price) && $combination->final_price > 0.0) {
                            $item->final_price = $item->final_price = $combination->final_price;
                        }

                        if ($combination->length > 0) {
                            $item->length = $combination->length;
                        }
                        if ($combination->width > 0) {
                            $item->width = $combination->width;
                        }
                        if ($combination->height > 0) {
                            $item->height = $combination->height;
                        }
                        if ($combination->weight > 0) {
                            $item->weight = $combination->weight;
                        }
                    }
                }

                if ($item->price_tier_modifier != '0') {
                    $item->_price_tiers = $itemModel->getTierPrices($item->id);
                } else {
                    $item->_price_tiers = array();
                }

                $unit = DJCatalog2HelperQuantity::getUnit($item->unit_id);
                $item->_unit = $unit->unit;

                if (JFactory::getUser()->guest) {
                    if ($params->get('price_restrict') == '1' || $item->price_restrict) {
                        $item->final_price = $item->price = $item->special_price = 0.0;
                    }
                }


            }
        }

        if (!is_object($item) || $item->available != 1) {
            $this->recalculate();
            return false;
        }

        // if a product has combinations and a combination has not been specified,
        // then product cannot be added to cart
        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
        $query->select('id')->from('#__djc2_items_combinations')->where('item_id=' . (int)$item->id);
        $db->setQuery($query);
        $possibleCombinations = $db->loadColumn();

        if (count($possibleCombinations) && !$combination_id) {
            $this->recalculate();
            return false;
        } else if ($combination_id && !in_array($combination_id, $possibleCombinations)) {
            $this->recalculate();
            return false;
        }

        //$item_id = $item->id;


        $sid = static::getSid($item->id, $combination_id, $features, $customisations, $dimensions, $configurable, null, $calculator);
        foreach ($this->items as $k => $v) {
            if (isset($v->_sid) && $v->_sid == $sid) {
                unset($this->items[$k]);
            }
        }

        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();
        Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2CartAddItem', array(&$item, $sid));

        $this->items[$sid] = clone $item;
        $this->items[$sid]->_sid = $sid;
        $this->items[$sid]->_combination_id = $combination_id;



        $this->calculators[$sid] = $calculator;

        if (isset($this->quantities[$sid])) {
            $quantity += (($unit->is_int) ? (int)$this->quantities[$sid] : floatval($this->quantities[$sid]) + 0);
        }

        $quantity = DJCatalog2HelperQuantity::validateQuantity($quantity, $unit);

        if ($this->validateStock($item, $quantity) == false) {
            $this->setError(JText::_('COM_DJCATALOG2_ADD_CART_ERROR_QUANTITY'));
            return false;
        }

        $this->quantities[$sid] = $quantity;


        if (!$lazy) {
            $this->recalculate();
        }

        return true;
    }

    public function getItem($item_id, $combination_id = 0, $features = [], $customisations = [], $dimensions = [], $configurable = [])
    {
        $sid = static::getSid($item_id, $combination_id, $features, $customisations, $dimensions, $configurable);
        return $this->getItemBySid($sid);
    }

    public function getItemBySid($sid)
    {
        if (!$sid || !isset($this->items[$sid])) {
            return false;
        }

        return $this->items[$sid];
    }

    public static function getSid($item_id, $combination_id = 0, $features = array(), $customisations = array(), $dimensions = array(), $configurable = array(), $suffix = null, $calculator = [])
    {


        $parts = array($item_id, $combination_id);

        $hash = $item_id . '|' . $combination_id;

        if (!empty($features) && is_array($features)) {
            $hash .= '|' . serialize($features);
        } else {
            $hash .= '|-';
        }

        if (!empty($customisations) && is_array($customisations)) {
            $hash .= '|' . serialize($customisations);
        } else {
            $hash .= '|-';
        }

        if (!empty($dimensions) && is_array($dimensions)) {
            $hash .= '|' . serialize($dimensions);
        } else {
            $hash .= '|-';
        }

        if (!empty($configurable) && is_array($configurable)) {
            $hash .= '|' . serialize($configurable);
        } else {
            $hash .= '|-';
        }

        if (!empty($calculator) && is_array($calculator)) {
            $hash .= '|' . serialize($calculator);
        } else {
            $hash .= '|-';
        }


        if (!is_null($suffix)) {
            $hash .= $suffix;
        }


        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();
        Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2CartGetSID', array(&$parts));

        $parts[] = md5($hash);

        return implode('.', $parts);
        //return $item_id.'.'.$combination_id;
    }

    public static function parseSid($sid)
    {
        $parts = explode('.', $sid, 3);
        if (count($parts) < 2) {
            return false;
        }

        $hash = '';
        if (count($parts) > 2) {
            if (isset($parts[2])) {
                $hash = $parts[2];
            }
        }

        $retVal = array(
            'id' => $parts[0],
            'combination_id' => $parts[1],
            'hash' => $hash,
        );

        return $retVal;
    }

    public function getCombinationAttributes($item, $format = 'array')
    {

        if (empty($item->_combination) || empty($item->_combination->fields)) {
            return $format == 'array' ? array() : '';
        }

        $data = Joomla\Utilities\ArrayHelper::fromObject($item->_combination);
        $fields = array_values($data['fields']);

        if ($format == 'string' || $format == 'string_values') {
            $pairs = array();
            foreach ($fields as $field) {
                $pairs[] = $format == 'string_values' ? $field['field_value'] : $field['field_name'] . ': ' . $field['field_value'];
            }
            return implode(', ', $pairs);
        }

        return ($format == 'array') ? $fields : json_encode($fields);
    }

    public function getItemAttributes($item, $translate = false, $format = 'array')
    {


        if (!$item || !isset($this->items[$item->_sid])) {
            return false;
        }

        if (!isset($this->attribute_values[$item->_sid]) && !isset($this->calculators[$item->_sid])) {
            return $format == 'array' ? array() : '';
        }

        $attributes = $this->attribute_values[$item->_sid];
        if ($translate) {
            $fields = $this->getAttributes();
            foreach ($fields as $key => $field) {
                $value = '';

                if (isset($attributes[$field->id])) {
                    $value = $attributes[$field->id];
                }

                if (!empty($value)) {
                    switch ($field->type) {
                        case 'text':
                        case 'textarea':
                        case 'calendar':
                        {
                            $attributes[$field->id] = $value;
                            break;
                        }
                        case 'select':
                        case 'radio':
                        case 'checkbox':
                        {
                            $selected = (is_array($value)) ? $value : array($value);
                            $values = array();
                            foreach ($field->optionlist as $option) {
                                if (in_array($option->id, $selected)) {
                                    $values[] = $option->value;
                                }
                            }

                            $attributes[$field->id] = implode(', ', $values);
                            break;
                        }
                    }
                }
            }
            $calculator = CalculatorHelper::getInstance($item->calculator_id);
            $calculatorData = $this->calculators[$item->_sid];


            foreach ($calculator->fields as $calculatorField) {
                if(isset($calculatorData[$calculatorField->name])) {
                    switch ($calculatorField->type) {
                        case 'checkbox':

                            foreach ($calculatorField->options as $option) {
                                if($option->price == $calculatorData[$calculatorField->name]) {
                                    $attributes[$calculatorField->name] = $option->text;
                                }
                            }
                            break;
                        default:
                            $attributes[$calculatorField->name] = $calculatorData[$calculatorField->name];
                            break;
                    }
                }
            }




            if ($format == 'json') {

                $output = array();
                foreach ($attributes as $key => $attribute) {
                    if (isset($fields[$key])) {

                    }else {
                        $output[$key] = $attribute;
                    }
                }
                $attributes = json_encode($output);

            } else if ($format == 'list') {
                $output = array();
                foreach ($attributes as $key => $attribute) {
                    if (isset($fields[$key])) {
                        $output[] = array('field_name' => $fields[$key]->name, 'field_value' => $attribute);
                    }
                }
                $attributes = $output;
            }
        }




        return $attributes;
    }

    public function addCustomisations($customisations, $item)
    {
        if (count($customisations) < 1 /*|| empty($item)*/) {
            return false;
        }

        $app = JFactory::getApplication();

        JModelLegacy::addIncludePath(JPATH_BASE . '/components/com_djcatalog2/models', 'DJCatalog2Model');
        $itemModel = JModelLegacy::getInstance('Item', 'Djcatalog2Model', array('ignore_request' => true));

        $individualCustoms = (!empty($item)) ? $itemModel->getCustomisations($item->id) : array();
        $commonCustoms = $itemModel->getCustomisations(0);

        $availCustoms = array_merge($individualCustoms, $commonCustoms);

        if (count($availCustoms) < 1) {
            return false;
        }

        $cartCustoms = array();
        $itemCustoms = array();

        $formData = array(
            'customisation' => array()
        );

        foreach ($availCustoms as $availCustom) {
            foreach ($customisations as $custom) {
                if ($custom['id'] == $availCustom->_cid) {

                    $formData['customisation'][] = $availCustom->_cid;

                    $customisation = array(
                        'id' => $availCustom->customisation_id,
                        'name' => $availCustom->name,
                        'type' => $availCustom->type,
                        'price' => $availCustom->price,
                        'tax_rule_id' => $availCustom->tax_rule_id,
                        'price_modifier' => $availCustom->price_modifier,
                        'required' => $availCustom->required,
                        'min_quantity' => $availCustom->min_quantity,
                        'max_quantity' => $availCustom->max_quantity,
                        'item_id' => (!empty($item) && $availCustom->type != 'c') ? $item->id : 0
                    );

                    $customisation = Joomla\Utilities\ArrayHelper::toObject($customisation);
                    $customisation->data = array();

                    foreach ($availCustom->input_params as $ik => $inputParam) {
                        $input = Joomla\Utilities\ArrayHelper::toObject($inputParam);

                        if (isset($custom['data'][$ik])) {
                            $value = $custom['data'][$ik];
                            if ($inputParam['type'] == 'checkbox' || $inputParam['type'] == 'radio') {
                                $optionParamVal = array();
                                foreach ($inputParam['options'] as $optionParamKey => $optionParam) {
                                    $selected = false;
                                    if (is_array($value)) {
                                        if (in_array($optionParamKey, $value)) {
                                            $optionParamVal[] = $optionParam['option_label'];
                                            $selected = true;
                                        }
                                    } else {
                                        if ($value == $optionParamKey) {
                                            $optionParamVal[] = $optionParam['option_label'];
                                            $selected = true;
                                        }
                                    }
                                    if ($selected && floatval(trim((string)$optionParam['option_price'])) > 0) {
                                        $customisation->price += floatval(trim((string)$optionParam['option_price']));
                                    }
                                }
                                $value = implode(', ', $optionParamVal);
                            }

                            $customisation->data[$ik] = array(
                                'id' => $ik,
                                'name' => $input->label,
                                'type' => $input->type,
                                'value' => $value
                            );

                            $formData['customValues-' . $availCustom->_cid . '[' . $ik . ']'] = $custom['data'][$ik];
                        }
                    }

                    if ($availCustom->type == 'c') {
                        $cartCustoms[] = $customisation;
                    } else {
                        $itemCustoms[] = $customisation;
                    }
                }
            }
        }

        $this->customisations[$item->_sid] = (count($itemCustoms) > 0) ? $itemCustoms : null;
        $this->customisations[0] = (count($cartCustoms) > 0) ? $cartCustoms : null;

        $app->setUserState('com_djcatalog2.recent_customisation', $formData);

        $this->saveToStorage();

        return true;
    }

    public function getCustomisations($sid)
    {
        if (isset($this->customisations[$sid])) {
            return $this->customisations[$sid];
        }
        return array();
    }

    public function getCalculatorData($sid)
    {
        if (isset($this->calculators[$sid])) {
            return $this->calculators[$sid];
        }
        return array();
    }

    public function getCustomisationData($customisation, $format = 'json')
    {
        if (empty($customisation) || empty($customisation->data)) {
            return '';
        }


        $data = array();
        foreach ($customisation->data as $k => $custom) {

            $cData = new stdClass();
            $cData->name = $custom['name'];
            $cData->type = $custom['type'];
            $cData->value = trim((string)$custom['value']);

            if ($cData->value == '') {
                $data[] = $cData;
                continue;
            }

            if ($cData->type == 'file') {
                $fData = json_decode((string)$cData->value);
                if (empty($fData) || !is_array($fData)) {
                    continue;
                }

                foreach ($fData as $file) {
                    if (!isset(static::$tmpFiles[$file->id])) {
                        $upFile = self::prepareCustomisationFile($file);

                        static::$tmpFiles[$file->id] = $upFile;
                    }
                    $cData->value = static::$tmpFiles[$file->id];
                }
            }

            $data[] = $cData;
        }

        return ($format == 'json') ? json_encode($data) : '';
    }

    protected static function prepareCustomisationFile($file)
    {
        $app = JFactory::getApplication();
        $uploaded = $app->getUserState('com_djcatalog2.customisation_files', array());

        if (is_array($uploaded) && array_key_exists($file->id, $uploaded)) {
            if (JFile::exists(JPath::clean($uploaded[$file->id]->fullpath))) {
                return $uploaded[$file->id];
            }
        }

        $source = JPath::clean(JPATH_ROOT . '/media/djcatalog2/tmp/' . $file->fullname);
        //$destination = JPath::clean( DJCATATTFOLDER.'/customisation' );
        $destination = JPath::clean(JPATH_ROOT . '/media/djcatalog2/files/customisation');

        if (!JFolder::exists($destination)) {
            JFolder::create($destination, 0755);
        }

        $ext = JFile::getExt($file->fullname);
        $newName = $file->caption . '.' . $file->id . '.' . $ext;
        $newName = \Joomla\String\StringHelper::strtolower(DJCatalog2FileHelper::createFileName($newName, $destination));
        $newPath = $destination . '/' . $newName;

        if (JFile::copy($source, $newPath)) {
            $file->file_id = md5($file->id . ':' . $file->caption . ':' . $file->fullname);
            $file->fullname = $newName;
            $file->url = 'media/djcatalog2/files/customisation/' . $newName;
            $file->size = filesize($newPath);
            $file->path = 'media/djcatalog2/files/customisation';
            $file->fullpath = $file->path . '/' . $file->fullname;

            $uploaded[$file->id] = $file;
            $app->setUserState('com_djcatalog2.customisation_files', $uploaded);

            return $file;
        }

        if (isset($uploaded[$file->id])) {
            unset($uploaded[$file->id]);
        }

        $app->setUserState('com_djcatalog2.customisation_files', $uploaded);

        return false;
    }

    public function updateQuantity($sid, $quantity, $attributes = null, $append = false)
    {
        if ($this->parseSid($sid) == false) {
            $sid = static::getSid($sid);
        }

        $sidParts = static::parseSid($sid);
        $hadErrors = false;

        if (!isset($this->quantities[$sid])) {
            //if (!$this->addItem($sid, 0, $quantity)) {
            if (!$this->addItem($sidParts[0], 0, [], [], $quantity)) {
                $hadErrors = true;
            }
        } else {
            $item = $this->getItemBySid($sid);
            $newQty = ($append) ? $this->quantities[$sid] + $quantity : $quantity;

            if ($this->validateStock($item, $newQty) == false) {
                if ($this->validateStock($item, $quantity) == false) {
                    $this->setError(JText::sprintf('COM_DJCATALOG2_UPDATE_CART_ERROR_QUANTITY', $item->name, floatval($quantity), floatval($item->stock)));
                    $hadErrors = true;
                } else {
                    $this->quantities[$sid] = $quantity;
                }
            } else {
                $this->quantities[$sid] = $newQty;
            }
        }

        if (is_array($attributes) && count($attributes) > 0) {
            $attributes = $this->validateAttributes($attributes);
            $this->attribute_values[$sid] = $attributes;
        }

        if ($hadErrors) {
            return false;
        }

        $this->recalculate();

        return true;
    }

    public function validateAttributes($attributes)
    {
        $fields = $this->getAttributes();
        foreach ($attributes as $key => $attribute) {
            if (!isset($fields[$key])) {
                unset($attributes[$key]);
                continue;
            }

            if (is_array($attribute)) {
                if (isset($fields[$key]->optionlist) && count($fields[$key]->optionlist)) {
                    foreach ($attribute as $opt_key => $option) {
                        $exist = false;
                        foreach ($fields[$key]->optionlist as $field_option) {
                            if ($field_option->id == $option) {
                                $exist = true;
                                break;
                            }
                        }
                        if (!$exist) {
                            unset($attribute[$opt_key]);
                        }
                    }
                } else {
                    unset($attributes[$key]);
                }

                if (count($attribute) < 1) {
                    unset($attributes[$key]);
                }
            } else {
                if (isset($fields[$key]->optionlist) && count($fields[$key]->optionlist)) {
                    $exist = false;
                    foreach ($fields[$key]->optionlist as $field_option) {
                        if ($field_option->id == $attribute) {
                            $exist = true;
                            break;
                        }
                    }
                    if (!$exist) {
                        unset($attributes[$key]);
                    }
                }
            }
        }

        return $attributes;
    }

    public function addFeatures($sid, $item, $features)
    {
        $attributes = $this->getFeatures();

        foreach ($features as $id => $feature) {
            if (!isset($attributes[$id])) continue;
            $attribute = $attributes[$id];
            if (!is_array($attribute->optionlist) || empty($attribute->optionlist)) continue;

            $key = '_ef_' . $attribute->alias;
            if (!isset($item->$key)) continue;
            if (!is_array($item->$key) || empty($item->$key)) continue;

            foreach ($attribute->optionlist as $option) {
                if ($feature != $option->id) continue;

                if (isset($item->$key[$option->id])) {

                    if (!isset($this->feature_values[$sid])) {
                        $this->feature_values[$sid] = array();
                    }
                    if (!isset($this->feature_values[$sid][$id])) {
                        $this->feature_values[$sid][$id] = array();
                    }

                    $this->feature_values[$sid][$id][] = $option->id;
                }
            }
        }


        $this->recalculate();
    }

    public function addDimensions($sid, $item, $dimensions)
    {
        if (empty($item->config_dimensions) /*|| trim((string)$item->config_dimensions) == ''*/) {
            return true;
        }

        if (is_array($dimensions) == false || empty($dimensions)) {
            return false;
        }

        $itemDims = is_string($item->config_dimensions) ? json_decode((string)$item->config_dimensions, true) : (array)$item->config_dimensions;

        foreach ($itemDims as $dim) {
            if (!isset($dimensions[$dim])) {
                return false;
            }
            if (trim((string)$dimensions[$dim]) === '') {
                return false;
            }
            if ($item->config_dimensions_unit != '') {
                $dimensions[$dim] .= ' [' . $item->config_dimensions_unit . ']';
            }
        }

        $this->dimension_values[$sid] = $dimensions;

        $this->recalculate();

        return true;
    }

    public function addConfigurable($sid, $item, $features)
    {
        if (empty($item->config_conditions) /*|| trim((string)$item->config_conditions) == ''*/) {
            return true;
        }

        if (is_array($features) == false || empty($features)) {
            return false;
        }

        $itemCond = is_string($item->config_conditions) ? json_decode((string)$item->config_conditions, true) : (array)$item->config_conditions;
        $choicePath = [];

        foreach ($itemCond as $field_id => $cond) {
            if (!isset($features[$field_id])) {
                return false;
            }
            if (trim((string)$features[$field_id]) === '') {
                return false;
            }

            foreach ($cond['options'] as $oidx => $option) {
                if ($option['id'] != $features[$field_id]) continue;

                $valid = false;
                if (empty($option['dependancies'])) {
                    $valid = true;
                } else {
                    $valid_deps = 0;
                    foreach ($option['dependancies'] as $dep) {
                        if (!isset($choicePath[$dep['id']])) {
                            return false;
                        }

                        $val = $choicePath[$dep['id']];

                        switch ($dep['operator']) {
                            case 'eq' :
                            {
                                if (!is_array($dep['match_ids']) || empty($dep['match_ids'])) {
                                    $valid_deps++;
                                } else if (in_array($val['id'], $dep['match_ids'])) {
                                    $valid_deps++;
                                }
                                break;
                            }
                            case 'not' :
                            {
                                if (!is_array($dep['match_ids']) || empty($dep['match_ids'])) {
                                    $valid_deps++;
                                } else if (!in_array($val['id'], $dep['match_ids'])) {
                                    $valid_deps++;
                                }
                                break;
                            }
                            case 'lt' :
                            {
                                if (strlen($dep['match']) > 0) {
                                    if (floatval($val['value']) < floatval($dep['match'])) {
                                        $valid_deps++;
                                    }
                                }
                                break;
                            }
                            case 'lte' :
                            {
                                if (strlen($dep['match']) > 0) {
                                    if (floatval($val['value']) <= floatval($dep['match'])) {
                                        $valid_deps++;
                                    }
                                }
                                break;
                            }
                            case 'gt' :
                            {
                                if (strlen($dep['match']) > 0) {
                                    if (floatval($val['value']) > floatval($dep['match'])) {
                                        $valid_deps++;
                                    }
                                }
                                break;
                            }
                            case 'gte' :
                            {
                                if (strlen($dep['match']) > 0) {
                                    if (floatval($val['value']) >= floatval($dep['match'])) {
                                        $valid_deps++;
                                    }
                                }
                                break;
                            }
                            case 'contains' :
                            {
                                if (strlen($dep['match']) > 0) {
                                    if (strstr($val['value'], $dep['match']) !== false) {
                                        $valid_deps++;
                                    }
                                }
                                break;
                            }
                        }
                    }

                    $valid = (bool)(count($option['dependancies']) == $valid_deps);
                }

                if ($valid) {
                    $choicePath[$field_id] = $option;
                }
            }
        }

        $addOnPrice = $item->final_price;
        foreach ($choicePath as $field_id => $option) {
            if ($option['price'] > 0.0) {
                if ($option['price_mod'] == 'add') {
                    $addOnPrice += $option['price'];
                } else if ($option['price_mod'] == 'multiply') {
                    $addOnPrice *= $option['price'];
                }
            }
        }

        $item->price = $item->final_price = $this->items[$sid]->price = $this->items[$sid]->final_price = floatval($addOnPrice);
        $this->prices[$sid] = $item->price;

        $this->feature_values[$sid] = array();
        foreach ($choicePath as $id => $choice) {
            if (!isset($this->feature_values[$sid][$id])) {
                $this->feature_values[$sid][$id] = array();
            }

            $this->feature_values[$sid][$id][] = $choice['id'];
        }

        $this->recalculate();
        return true;
    }

    public function getItemFeatures($item, $translate = false, $format = 'array')
    {
        if (!$item || !isset($this->items[$item->_sid])) {
            return false;
        }

        if (!isset($this->feature_values[$item->_sid])) {
            return $format == 'array' ? array() : '';
        }

        $attributes = $this->feature_values[$item->_sid];

        if ($translate) {
            $fields = $this->getFeatures();
            foreach ($fields as $key => $field) {
                $value = '';

                if (isset($attributes[$field->id])) {
                    $value = $attributes[$field->id];
                }

                if (!empty($value)) {
                    $selected = (is_array($value)) ? $value : array($value);
                    $values = array();
                    foreach ($field->optionlist as $option) {
                        if (in_array($option->id, $selected)) {
                            $values[] = $option->value;
                        }
                    }

                    $attributes[$field->id] = implode(', ', $values);
                }
            }

            if ($format == 'json') {
                $output = array();
                foreach ($attributes as $key => $attribute) {
                    if (isset($fields[$key])) {
                        $output[$fields[$key]->name] = $attribute;
                    }
                }
                if (!empty($this->dimension_values[$item->_sid])) {
                    foreach ($this->dimension_values[$item->_sid] as $dim => $value) {
                        $output[$dim] = $value;
                    }
                }
                $attributes = json_encode($output);
            } else if ($format == 'list') {
                $output = array();
                foreach ($attributes as $key => $attribute) {
                    if (isset($fields[$key])) {
                        $obj = new stdClass();
                        $obj->field_name = $fields[$key]->name;
                        $obj->field_value = $attribute;
                        $output[] = $obj;
                    }
                }
                if (!empty($this->dimension_values[$item->_sid])) {
                    foreach ($this->dimension_values[$item->_sid] as $dim => $value) {
                        $obj = new stdClass();
                        $obj->field_name = JText::_('COM_DJCATALOG2_' . $dim);
                        $obj->field_value = $value;
                        $output[] = $obj;
                    }
                }
                $attributes = $output;
            }
        }

        return $attributes;
    }

    public function setDelivery($delivery_id)
    {
        if ($delivery_id == 0) {
            $this->delivery = false;
            return false;
        }
        $db = JFactory::getDbo();
        $db->setQuery('select * from #__djc2_delivery_methods where id =' . (int)$delivery_id . ' and published=1');
        $delivery = $db->loadObject();
        if (!$delivery) {
            $this->delivery = false;
            $this->recalculate();
            $this->saveToStorage();
            throw new Exception(JText::_('COM_DJCATALOG2_DELIVERY_METHOD_IS_INVALID'), 500);
        }

        $params = new Registry();
        $params->loadString($delivery->params, 'JSON');
        $delivery->params = $params;

        if ($this->shipping_days > 1) {
            $delivery->days = $this->shipping_days;
        }


        JPluginHelper::importPlugin('djcatalog2delivery');
        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();
        Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2SetDeliveryMethod', array('com_djcatalog2.cart.set_delivery', &$this, &$delivery));

        $this->delivery = $delivery;

        // No needed to recalculate at this point. Used to cause issues with the price rules
        //$this->recalculate();

        return $this->delivery;
    }

    public function setPayment($payment_id)
    {
        if ($payment_id == 0) {
            $this->payment = false;
            return false;
        }
        $db = JFactory::getDbo();
        $db->setQuery('select * from #__djc2_payment_methods where id =' . (int)$payment_id . ' and published=1');
        $payment = $db->loadObject();
        if (!$payment) {
            $this->payment = false;
            $this->recalculate();
            $this->saveToStorage();
            throw new Exception(JText::_('COM_DJCATALOG2_PAYMENT_METHOD_IS_INVALID'), 500);
        }

        if ($this->delivery) {
            $db->setQuery('select delivery_id from #__djc2_deliveries_payments where payment_id=' . (int)$payment_id);
            $validDeliveries = $db->loadColumn();
            if (!empty($validDeliveries) && !in_array((int)$this->delivery->id, $validDeliveries)) {
                $this->payment = false;
                $this->recalculate();
                $this->saveToStorage();
                throw new Exception(JText::_('COM_DJCATALOG2_PAYMENT_METHOD_IS_INVALID'), 500);
            }
        }

        $params = new Registry();
        $params->loadString($payment->params, 'JSON');
        $payment->params = $params;

        JPluginHelper::importPlugin('djcatalog2payment');
        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();
        Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2SetPaymentMethod', array('com_djcatalog2.cart.set_payment', &$this, &$payment));

        $this->payment = $payment;

        // No needed to recalculate at this point. Used to cause issues with the price rules
        //$this->recalculate();

        return $this->payment;
    }

    public function setCoupon(&$coupon, $check = true)
    {

        if ($this->coupon) {
            $coupon->setError(JText::_('COM_DJCATALOG2_COUPON_ALREADY_APPLIED'));
            return false;
        }

        // check basic and assign product restrictions
        if ($check && (!$coupon->checkRestrictions() || !$coupon->checkProductRestriction())) {
            return false;
        }

        // restrictions are met, apply the coupon
        $this->coupon = $coupon;

        // recalculate the cart prices
        $this->recalculate();
        // save cart state to storage
        $this->saveToStorage();

        return true;
    }

    public function removeCoupon()
    {

        if (!$this->coupon) return false;

        $coupon = $this->coupon;
        $this->coupon = false;
        $this->subscription = null;

        // recalculate the cart prices
        $this->recalculate();

        // save cart state to storage
        $this->saveToStorage();

        return $coupon;
    }

    public function recalculate()
    {
        $params = Djcatalog2Helper::getParams();
        $user = JFactory::getUser();

        $sub_totals = array();
        $product_sub_totals = array();
        $product_sub_old_totals = array();

        $total = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
        $product_total = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
        $product_old_total = array('net' => 0, 'tax' => 0, 'gross' => 0.0);

        $tax_already_incl = (bool)($params->get('price_including_tax', 1) == 1);

        if ($this->coupon) {
            $this->coupon->resetValue();
        }
        $this->price_components = array();

        // prepare data for tier discount rules
        // i - indvidual, a - all, c - same category, p - same producer
        $tierRules = array('a' => 0, 'i' => array(), 'c' => array(), 'p' => array());
        foreach ($this->items as $k => &$item) {


            if (empty($item->id) || empty($item->_sid)) {
                unset($this->items[$k]);
                continue;
            }
            $item->_quantity = (isset($this->quantities[$item->_sid])) ? $this->quantities[$item->_sid] : 1;
            $item->final_price = (isset($this->prices[$item->_sid])) ? $this->prices[$item->_sid] : $item->final_price;

            if (!$item->tax_rule_id) {
                $item->tax_rule_id = 0;
            }

            $tierRules['a'] += (int)$item->_quantity;
            if (!isset($tierRules['i'][$item->id])) {
                $tierRules['i'][$item->id] = 0;
            }
            $tierRules['i'][$item->id] += (int)$item->_quantity;

            if (!isset($tierRules['c'][$item->cat_id])) {
                $tierRules['c'][$item->cat_id] = 0;
            }
            $tierRules['c'][$item->cat_id] += (int)$item->_quantity;

            if (!isset($tierRules['p'][$item->producer_id])) {
                $tierRules['p'][$item->producer_id] = 0;
            }
            $tierRules['p'][$item->producer_id] += (int)$item->_quantity;

            $this->applyCalculator($item);

        }

        if (isset($item->force_recurring) && $item->force_recurring) {
            $this->forceRecurring = true;
            $this->recurringDate = date("Y-m-d", strtotime('now + ' . $item->expiration));
        }

        unset($item);

        // apply tier discounts
        $this->applyTierPrices($tierRules);

        // apply cart rules before calculating the sub total
        Djcatalog2HelperPrice::applyRulesBeforeInit($this, $this->items);

        $this->total_weight = 0.0;
        $this->gauges_map = [];

        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();

        foreach ($this->items as $k => &$item) {
            Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2CartFetchPrice', array(&$item, &$this));

            $finalPrice = $item->final_price;
            $basePrice = $item->price;

            if ($this->coupon) {
                $finalPrice = $this->coupon->getPrice($finalPrice, $item->id, $item->_quantity);
            }

            $item->_prices = (isset($item->_prices)) ? $item->_prices : Djcatalog2HelperPrice::getCartPrices($finalPrice, $basePrice, $item->tax_rule_id, false, $item->_quantity, $params);
        }
        unset($item);

        // apply cart rules before calculating the sub total
        Djcatalog2HelperPrice::applyRulesAfterInit($this, $this->items);

        foreach ($this->items as $k => &$item) {
            //if($this->coupon) {
            if (!isset($product_sub_old_totals[$item->tax_rule_id])) {
                $product_sub_old_totals[$item->tax_rule_id] = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
            }

            if (!isset($item->_old_prices)) {
                $item->_old_prices = Djcatalog2HelperPrice::getCartPrices($item->final_price, $item->price, $item->tax_rule_id, false, $item->_quantity, $params);
            }

            $product_sub_old_totals[$item->tax_rule_id]['net'] += ($item->_old_prices['total']['net']);
            $product_sub_old_totals[$item->tax_rule_id]['gross'] += ($item->_old_prices['total']['gross']);
            $product_sub_old_totals[$item->tax_rule_id]['tax'] += ($item->_old_prices['total']['tax']);
            //}
            if ($this->coupon) {
                $diffPrice = array(
                    'net' => $item->_prices['total']['net'] - $item->_old_prices['total']['net'],
                    'tax' => $item->_prices['total']['tax'] - $item->_old_prices['total']['tax'],
                    'gross' => $item->_prices['total']['gross'] - $item->_old_prices['total']['gross']
                );
                $this->addPriceComponent($this->coupon, $diffPrice, 'coupon');
            }

            if (!isset($sub_totals[$item->tax_rule_id])) {
                $sub_totals[$item->tax_rule_id] = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
            }

            $sub_totals[$item->tax_rule_id]['net'] += ($item->_prices['total']['net']);
            $sub_totals[$item->tax_rule_id]['gross'] += ($item->_prices['total']['gross']);
            $sub_totals[$item->tax_rule_id]['tax'] += ($item->_prices['total']['tax']);

            $this->total_weight += DJCatalog2HelperQuantity::convertWeigthUnit(($item->weight * $item->_quantity), $item->weight_unit, 'G');

            $this->total_dimensions['length'] += DJCatalog2HelperQuantity::convertDimensionUnit(($item->length * $item->_quantity), $item->dimensions_unit, 'M');
            $this->total_dimensions['width'] += DJCatalog2HelperQuantity::convertDimensionUnit(($item->width * $item->_quantity), $item->dimensions_unit, 'M');
            $this->total_dimensions['height'] += DJCatalog2HelperQuantity::convertDimensionUnit(($item->height * $item->_quantity), $item->dimensions_unit, 'M');

            if (isset($item->gauge_id)) {
                if (!isset($this->gauges_map[$item->gauge_id])) {
                    $this->gauges_map[$item->gauge_id] = [];
                }
                $this->gauges_map[$item->gauge_id][] = $item->id;
            }
        }
        unset($item);

        if (!empty($this->customisations)) {

            foreach ($this->customisations as $sid => &$customOptions) {
                if (!is_array($customOptions)) {
                    continue;
                }
                foreach ($customOptions as &$customOption) {
                    $customOption->_quantity = 1;

                    if ($customOption->price_modifier == 'm') {
                        if ($sid == 0) {
                            $customOption->_quantity = 0;
                            foreach ($this->quantities as $qty) {
                                $customOption->_quantity += $qty;
                            }
                        } else {
                            if (isset($this->quantities[$sid])) {
                                $customOption->_quantity = $this->quantities[$sid];
                            }
                        }
                    }

                    if (!$customOption->tax_rule_id) {
                        $customOption->tax_rule_id = 0;
                    }

                    $customOption->_prices = Djcatalog2HelperPrice::getCartPrices($customOption->price, $customOption->price, $customOption->tax_rule_id, false, $customOption->_quantity, $params);

                    if (!isset($sub_totals[$customOption->tax_rule_id])) {
                        $sub_totals[$customOption->tax_rule_id] = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
                    }

                    $sub_totals[$customOption->tax_rule_id]['net'] += ($customOption->_prices['total']['net']);
                    $sub_totals[$customOption->tax_rule_id]['gross'] += ($customOption->_prices['total']['gross']);
                    $sub_totals[$customOption->tax_rule_id]['tax'] += ($customOption->_prices['total']['tax']);
                }
                unset($customOption);
            }
            unset($customOptions);
        }

        //if($this->coupon) {
        foreach ($product_sub_old_totals as $tax_rule_id => $sub_total) {
            if ($tax_already_incl) {
                //$sub_total['gross'] = Djcatalog2HelperPrice::applyCartPriceRules($this, $sub_total['gross'], true, 'total_items');
                $product_sub_old_totals[$tax_rule_id]['tax'] = Djcatalog2HelperPrice::calculate($sub_total['gross'], 'T', $tax_rule_id);
                $product_sub_old_totals[$tax_rule_id]['net'] = $sub_total['gross'] - $sub_total['tax'];
            } else {
                //$sub_total['net'] = Djcatalog2HelperPrice::applyCartPriceRules($this, $sub_total['net'], true, 'total_items');
                $product_sub_old_totals[$tax_rule_id]['tax'] = Djcatalog2HelperPrice::calculate($sub_total['net'], 'T', $tax_rule_id);
                $product_sub_old_totals[$tax_rule_id]['gross'] = $sub_total['net'] + $sub_total['tax'];
            }

            $product_old_total ['net'] += $product_sub_old_totals[$tax_rule_id]['net'];
            $product_old_total ['tax'] += $product_sub_old_totals[$tax_rule_id]['tax'];
            $product_old_total ['gross'] += $product_sub_old_totals[$tax_rule_id]['gross'];
        }
        //}

        foreach ($sub_totals as $tax_rule_id => $sub_total) {
            $sub_total = Djcatalog2HelperPrice::applyCartPriceRules($this, $sub_totals[$tax_rule_id], true, 'total_items');
            $sub_totals[$tax_rule_id] = $sub_total;

            if ($tax_already_incl) {
                $sub_totals[$tax_rule_id]['tax'] = Djcatalog2HelperPrice::calculate($sub_total['gross'], 'T', $tax_rule_id);
                $sub_totals[$tax_rule_id]['net'] = $sub_totals[$tax_rule_id]['gross'] - $sub_totals[$tax_rule_id]['tax'];
            } else {
                $sub_totals[$tax_rule_id]['tax'] = Djcatalog2HelperPrice::calculate($sub_total['net'], 'T', $tax_rule_id);
                $sub_totals[$tax_rule_id]['gross'] = $sub_totals[$tax_rule_id]['net'] + $sub_totals[$tax_rule_id]['tax'];
            }

            $product_total ['net'] += $sub_totals[$tax_rule_id]['net'];
            $product_total ['tax'] += $sub_totals[$tax_rule_id]['tax'];
            $product_total ['gross'] += $sub_totals[$tax_rule_id]['gross'];
        }

        $product_sub_totals = $sub_totals;


        if (!empty($this->delivery)) {
            $this->delivery->_quantity = 1;

            $fee = 0;
            if ($this->delivery->additional_fee > 0) {
                if ($tax_already_incl) {
                    $fee = round(($this->delivery->additional_fee * $product_total ['gross']) / 100, 2);
                } else {
                    $fee = round(($this->delivery->additional_fee * $product_total ['net']) / 100, 2);
                }
            }
            $deliveryPrice = $this->delivery->price + $fee;

            $deliveryPrice = ($this->delivery->free_amount > 0 && $this->delivery->free_amount <= $product_total ['gross']) ? 0.0 : $deliveryPrice;
            $deliveryPrice = $deliveryPrice * $this->shipping_days;
            $deliveryPrice = Djcatalog2HelperPrice::applyPriceRules($deliveryPrice, true, 'delivery', $this->delivery, 'delivery');

            $this->delivery->_prices = Djcatalog2HelperPrice::getCartPrices($deliveryPrice, $deliveryPrice, $this->delivery->tax_rule_id, false, $this->delivery->_quantity, $params);

            if (!$this->delivery->tax_rule_id) {
                $this->delivery->tax_rule_id = 0;
            }
            if (!isset($sub_totals[$this->delivery->tax_rule_id])) {
                $sub_totals[$this->delivery->tax_rule_id] = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
            }

            $sub_totals[$this->delivery->tax_rule_id]['net'] += ($this->delivery->_prices['total']['net']);
            $sub_totals[$this->delivery->tax_rule_id]['gross'] += ($this->delivery->_prices['total']['gross']);
            $sub_totals[$this->delivery->tax_rule_id]['tax'] += ($this->delivery->_prices['total']['tax']);
        }

        if (!empty($this->payment)) {
            $this->payment->_quantity = 1;

            $fee = 0;
            if ($this->payment->additional_fee > 0) {
                if ($tax_already_incl) {
                    $fee = round(($this->payment->additional_fee * $product_total ['gross']) / 100, 2);
                } else {
                    $fee = round(($this->payment->additional_fee * $product_total ['net']) / 100, 2);
                }
            }
            $paymentPrice = $this->payment->price + $fee;

            $paymentPrice = ($this->payment->free_amount > 0 && $this->payment->free_amount <= $product_total ['gross']) ? 0.0 : $paymentPrice;
            $paymentPrice = Djcatalog2HelperPrice::applyPriceRules($paymentPrice, true, 'payment', $this->payment, 'payment');

            $this->payment->_prices = Djcatalog2HelperPrice::getCartPrices($paymentPrice, $paymentPrice, $this->payment->tax_rule_id, false, $this->payment->_quantity, $params);
            if (!$this->payment->tax_rule_id) {
                $this->payment->tax_rule_id = 0;
            }
            if (!isset($sub_totals[$this->payment->tax_rule_id])) {
                $sub_totals[$this->payment->tax_rule_id] = array('net' => 0, 'tax' => 0, 'gross' => 0.0);
            }

            $sub_totals[$this->payment->tax_rule_id]['net'] += ($this->payment->_prices['total']['net']);
            $sub_totals[$this->payment->tax_rule_id]['gross'] += ($this->payment->_prices['total']['gross']);
            $sub_totals[$this->payment->tax_rule_id]['tax'] += ($this->payment->_prices['total']['tax']);
        }

        foreach ($sub_totals as $tax_rule_id => $sub_total) {
            $sub_total = Djcatalog2HelperPrice::applyCartPriceRules($this, $sub_totals[$tax_rule_id], true, 'grand_total');
            $sub_totals[$tax_rule_id] = $sub_total;

            if ($tax_already_incl) {

                //$sub_totals[$tax_rule_id]['gross'] = $sub_total['gross'] = Djcatalog2HelperPrice::applyCartPriceRules($this, $sub_totals[$tax_rule_id]['gross'], true, 'grand_total');

                $sub_totals[$tax_rule_id]['gross'] = $sub_total['gross'];
                $sub_totals[$tax_rule_id]['tax'] = Djcatalog2HelperPrice::calculate($sub_total['gross'], 'T', $tax_rule_id);
                $sub_totals[$tax_rule_id]['net'] = $sub_totals[$tax_rule_id]['gross'] - $sub_totals[$tax_rule_id]['tax'];
            } else {
                $sub_totals[$tax_rule_id]['net'] = $sub_total['net'];
                $sub_totals[$tax_rule_id]['tax'] = Djcatalog2HelperPrice::calculate($sub_total['net'], 'T', $tax_rule_id);
                $sub_totals[$tax_rule_id]['gross'] = $sub_totals[$tax_rule_id]['net'] + $sub_totals[$tax_rule_id]['tax'];
            }

            $total ['net'] += $sub_totals[$tax_rule_id]['net'];
            $total ['tax'] += $sub_totals[$tax_rule_id]['tax'];
            $total ['gross'] += $sub_totals[$tax_rule_id]['gross'];
        }

        $this->product_old_total = $product_old_total;
        $this->product_total = $product_total;
        $this->sub_totals = $sub_totals;

        $this->total = $total;

        $user_currency_id = JFactory::getApplication()->getUserState('com_djcatalog2.checkout.currency');
        $default_currency = Djcatalog2HelperPrice::getCurrencyDefault();
        $user_currency = Djcatalog2HelperPrice::getCurrencyById($user_currency_id);

        $this->currency = ((!empty($user_currency)) ? $user_currency : ((!empty($default_currency)) ? $default_currency : false));

        return true;
    }

    public function saveToStorage()
    {
        $app = JFactory::getApplication();
        $params = Djcatalog2Helper::getParams();
        $db = JFactory::getDbo();
        $user = JFactory::getUser();

        $app->setUserState('com_djcatalog2.cart.prices', $this->prices);
        $app->setUserState('com_djcatalog2.cart.items', $this->quantities);
        $app->setUserState('com_djcatalog2.cart.attributes', $this->attribute_values);
        $app->setUserState('com_djcatalog2.cart.features', $this->feature_values);
        $app->setUserState('com_djcatalog2.cart.dimension_values', $this->dimension_values);

        if ($user->id) {
            $query = $db->getQuery(true)->select('id')->from('#__djc2_usercarts')->where('user_id=' . $user->id);
            $db->setQuery($query);
            $exists = $db->loadResult();

            if ($exists) {
                $query = $db->getQuery(true)->delete('#__djc2_usercarts')->where('user_id=' . $user->id);
                $db->setQuery($query);
                $db->execute();
            }

            if (count($this->quantities) > 0) {
                $query = $db->getQuery(true);
                $query->insert('#__djc2_usercarts');
                $query->columns(array('user_id', 'items'));
                $query->values($user->id . ',' . $db->quote(json_encode($this->quantities)));
                $db->setQuery($query);
                $db->execute();
            }
        }
        if (!empty($this->delivery)) {
            $app->setUserState('com_djcatalog2.cart.delivery', $this->delivery->id);
        } else {
            $app->setUserState('com_djcatalog2.cart.delivery', null);
        }

        if ($this->shipping_days > 1) {
            $app->setUserState('com_djcatalog2.cart.shipping_days', $this->shipping_days);
        }

        if (!empty($this->payment)) {
            $app->setUserState('com_djcatalog2.cart.payment', $this->payment->id);
        } else {
            $app->setUserState('com_djcatalog2.cart.payment', null);
        }

        $app->setUserState('com_djcatalog2.cart.coupon', @$this->coupon->id);

        $app->setUserState('com_djcatalog2.cart.customisations', $this->customisations);
        $app->setUserState('com_djcatalog2.cart.calculators', $this->calculators);

        if ($params->get('cart_cookie_enable', 1)) {
            $cookie_val = json_encode($this->quantities);
            $cookie_time = (int)$params->get('cart_cookie_time', 2419200);
            $app->input->cookie->set('djc2cart', $cookie_val, (time() + $cookie_time), $app->get('cookie_path', '/'), $app->get('cookie_domain', ''));
        } else if ($app->input->cookie->getString('djc2cart') != '') {
            $app->input->cookie->set('djc2cart', '', (time() - 3600), $app->get('cookie_path', '/'), $app->get('cookie_domain', ''));
        }

        return true;
    }

    public function clear()
    {
        $app = JFactory::getApplication();

        $this->items = array();
        $this->quantities = array();
        $this->prices = array();
        $this->total = array();
        $this->sub_totals = array();
        $this->product_total = array();
        $this->delivery = false;
        $this->payment = false;
        $this->attribute_values = array();
        $this->feature_values = array();
        $this->customisations = array();

        $app->setUserState('com_djcatalog2.cart.prices', null);
        $app->setUserState('com_djcatalog2.cart.items', null);
        $app->setUserState('com_djcatalog2.cart.attributes', null);
        $app->setUserState('com_djcatalog2.cart.features', null);
        $app->setUserState('com_djcatalog2.cart.dimension_values', null);
        $app->setUserState('com_djcatalog2.cart.delivery', null);
        $app->setUserState('com_djcatalog2.cart.payment', null);
        $app->setUserState('com_djcatalog2.cart.coupon', null);
        $app->setUserState('com_djcatalog2.cart.customisations', null);
        $app->setUserState('com_djcatalog2.cart.calculators', null);
        $app->setUserState('com_djcatalog2.recent_customisation', null);
        $app->setUserState('com_djcatalog2.customisation_files', null);
        $app->setUserState('com_djcatalog2.cart.shipping_days', null);
        $app->setUserState('com_djcatalog2.cart.custom_items', null);

        $app->input->cookie->set('djc2cart', '', (time() - 3600), $app->get('cookie_path', '/'), $app->get('cookie_domain', ''));

        $db = JFactory::getDbo();
        $user = JFactory::getUser();

        if ($user->id) {
            $query = $db->getQuery(true)->delete('#__djc2_usercarts')->where('user_id=' . $user->id);
            $db->setQuery($query);
            $db->execute();
        }
    }

    public function getAttributes()
    {
        if (is_null($this->attributes)) {
            $db = JFactory::getDbo();

            $query = $db->getQuery(true);
            $query->select('f.*');
            $query->from('#__djc2_cart_extra_fields AS f');
            $query->where('f.published=1');
            $query->order('f.ordering ASC');

            $db->setQuery($query);
            $attributes = $db->loadObjectList('id');

            if (count($attributes) > 0) {
                $query = $db->getQuery(true);
                $query->select('o.*');
                $query->from('#__djc2_cart_extra_fields_options AS o');
                $query->order('o.id ASC');

                $db->setQuery($query);
                $options = $db->loadObjectList();

                foreach ($options as $k => $v) {
                    if (isset($attributes[$v->field_id])) {
                        if (!isset($attributes[$v->field_id]->optionlist)) {
                            $attributes[$v->field_id]->optionlist = array();
                        }
                        $attributes[$v->field_id]->optionlist[] = $v;
                    }
                }
            }

            $this->attributes = $attributes;
        }

        return $this->attributes;
    }

    public function getFeatures()
    {
        if (is_null($this->features)) {
            $db = JFactory::getDbo();

            $query = $db->getQuery(true);
            $query->select('f.*');
            $query->from('#__djc2_items_extra_fields AS f');
            $query->where('f.published=1 AND f.cart_variant = 2');
            $query->order('f.ordering ASC');

            $db->setQuery($query);
            $attributes = $db->loadObjectList('id');

            if (count($attributes) > 0) {
                $query = $db->getQuery(true);
                $query->select('o.*');
                $query->from('#__djc2_items_extra_fields_options AS o');
                $query->order('o.id ASC');

                $db->setQuery($query);
                $options = $db->loadObjectList();

                foreach ($options as $k => $v) {
                    if (isset($attributes[$v->field_id])) {
                        if (!isset($attributes[$v->field_id]->optionlist)) {
                            $attributes[$v->field_id]->optionlist = array();
                        }
                        $attributes[$v->field_id]->optionlist[] = $v;
                    }
                }
            }

            $this->features = $attributes;
        }

        return $this->features;
    }

    protected function applyTierPrices($rules)
    {
        foreach ($this->items as $k => &$item) {
            if ($item->price_tier_modifier != '0' && count($item->_price_tiers)) {
                if (isset($item->_tier_applied)) {
                    continue;
                }
                $item->_tier_applied = true;

                $quantity = $item->_quantity;

                switch ($item->price_tier_break) {
                    case 'i':
                    {
                        if (isset($rules['i'][$item->id]) && $rules['i'][$item->id] > 0) {
                            $quantity = $rules['i'][$item->id];
                        }
                        break;
                    }
                    case 'c':
                    {
                        if ($item->cat_id && isset($rules['c'][$item->cat_id]) && $rules['c'][$item->cat_id] > 0) {
                            $quantity = $rules['c'][$item->cat_id];
                        }
                        break;
                    }
                    case 'p':
                    {
                        if ($item->producer_id && isset($rules['p'][$item->producer_id]) && $rules['p'][$item->producer_id] > 0) {
                            $quantity = $rules['p'][$item->producer_id];
                        }
                        break;
                    }
                    case 'a':
                    {
                        if ($rules['a'] > 0) {
                            $quantity = $rules['a'];
                        }
                        break;
                    }
                }

                $discounts = Djcatalog2HelperPrice::getTierDiscounts($item->final_price, $item->_price_tiers, $item->price_tier_modifier, $quantity);
                $item->final_price = $discounts['price'];


            }
        }
        unset($item);
    }

    public function addPriceComponent($rule, $value, $type = 'rule')
    {
        if (!is_array($this->price_components)) {
            $this->price_components = array();
        }

        $id = $type . ':' . $rule->id;
        $name = '';

        if ($type == 'rule') {
            $name = $rule->name;
        } else if ($type == 'coupon') {
            $name = ($rule->description != '') ? $rule->description : $rule->code;
        }

        $operation = ($type == 'rule') ? $rule->operation : 'sub';


        if (!isset($this->price_components[$id])) {
            $component = array(
                'name' => $name,
                'value' => array('net' => 0.0000, 'tax' => 0.0000, 'gross' => 0.0000),
                'rule' => $rule,
                'type' => $type,
                'operation' => $operation,
                'calc_type' => $rule->type
            );
            $this->price_components[$id] = (object)$component;
        }

        foreach ($this->price_components[$id]->value as $k => $v) {
            $this->price_components[$id]->value[$k] += $value[$k];
        }
    }

    public function getPriceComponents($ruleId = null)
    {
        return is_null($ruleId) ? $this->price_components : (isset($this->price_components[$ruleId]) ? $this->price_components[$ruleId] : false);
    }

    public function getShippingDays($items)
    {
        $shipping_days = array();
        foreach ($items as $item) {
            $days = ($item->shipping_days > 0) ? $item->shipping_days : 1;
            $shipping_days[$days][] = $item;
        }

        ksort($shipping_days);
        return $shipping_days;
    }

    public function setShippingDays($shipping_days)
    {
        if ($shipping_days > 0)
            $this->shipping_days = $shipping_days;
    }

    // Return array with all items in cart ids
    private function getItemsIds()
    {
        $items = self::getItems();
        $ids = array();

        if (count($items)) {
            foreach ($items as $item)
                $ids[] = $item->id;
        }


        return $ids;
    }


    // Get related items by Items Model
    private function fetchRelatedAccessories($ids)
    {
        if (!count($ids)) return array();

        $db = JFactory::getDbo();
        $query = $db->getQuery(true);

        $query->select($db->quoteName('related_item'))
            ->from($db->quoteName('#__djc2_items_related_accessories'))
            ->where($db->quoteName('item_id') . ' IN (' . implode(',', $ids) . ')');

        $params = Djcatalog2Helper::getParams();
        $accessories_limit = $params->get('cart_related_accessories_limit', 0);

        if (intval($accessories_limit))
            $query->setLimit($accessories_limit);

        $db->setQuery($query);

        $results = $db->loadColumn();

        if (empty($results)) return array();

        JModelLegacy::addIncludePath(JPATH_BASE . '/components/com_djcatalog2/models', 'DJCatalog2Model');
        $model = JModelLegacy::getInstance('Items', 'Djcatalog2Model', array('ignore_request' => true));

        $ids = array_unique($results);
        $model->setState('filter.item_ids', $ids);
        return $model->getItems();
    }


    public function getRelatedAccessoriess()
    {
        if (empty($this->related_accessories)) {
            $items_ids = $this->getItemsIds();
            $this->related_accessories = $this->fetchRelatedAccessories($items_ids);
        }

        return $this->related_accessories;
    }

    public function validateStock($item, $quantity)
    {
        $juser = JFactory::getUser();
        $params = Djcatalog2Helper::getParams();
        $salesman = $juser->authorise('djcatalog2.salesman', 'com_djcatalog2') || $juser->authorise('core.admin', 'com_djcatalog2');

        if ($salesman || $params->get('cart_query_enabled', 1)) {
            return true;
        }

        if (!$item->onstock || $quantity == 0.0000) {
            return false;
        } else if ($item->product_type == 'tangible' || $item->product_type == 'hybrid') {
            if ($quantity > $item->stock && $item->onstock < 2) {
                return false;
            }
        } else if ($item->product_type == 'bundle') {
            $bundleStock = $this->getBundleStock($item);
            if ($quantity > $bundleStock && $item->onstock < 2) {
                return false;
            }
        }

        return true;
    }

    protected function setCustomItems($items)
    {
        foreach ($items as $sid => $item) {
            $this->items[$sid] = $item;
            $this->quantities[$sid] = $item->_quantity;
        }
    }

    public function addCustomItem($item, $quantity = 1, $hashSuffix = null)
    {
        $app = JFactory::getApplication();

        $sid = static::getSid($item->id, 0, [], [], [], [], $hashSuffix);

        $dispatcher = Joomla\CMS\Factory::getApplication()->getDispatcher();
        Joomla\CMS\Factory::getApplication()->triggerEvent('onDJC2CartAddItem', array(&$item, $sid));

        $custom_items = (array)$app->getUserState('com_djcatalog2.cart.custom_items', array());

        $item->_sid = $sid;
        $item->_quantity = $quantity;
        $this->items[$sid] = $item;
        $this->quantities[$sid] = $quantity;

        $custom_items[$sid] = $item;

        $app->setUserState('com_djcatalog2.cart.custom_items', $custom_items);

        $this->recalculate();
        $this->saveToStorage();
    }

    public function removeCustomItem($item)
    {
    }

    public function getBundleItems($item)
    {
        $params = JComponentHelper::getParams('com_djcatalog2');

        if (!empty($item->bundle_items)) {

            if (is_array($item->bundle_items)) {
                if (isset($item->bundle_items->prices)) {
                    unset($item->bundle_items->prices);
                }
            }

            if (!is_array($item->bundle_items)) {
                $item->bundle_items = json_decode((string)$item->bundle_items, true);
                foreach ($item->bundle_items as $k => $v) {
                    if ((float)$v['quantity'] == 0.0 || trim((string)$v['sku'] == '')) {
                        unset($item->bundle_items[$k]);
                        continue;
                    }
                }
                $item->bundle_items = array_values($item->bundle_items);
            }
        } else {
            return false;
        }

        // sum of prices of all items in the bundle
        $bundle_total = 0.0;

        foreach ($item->bundle_items as $k => $v) {
            $bundle_item = $this->getItemBySKU($v['sku']);
            if (!empty($bundle_item)) {
                if (trim((string)$v['price']) != '' && $v['price'] > 0.0) {
                    $bundle_item->final_price = $v['price'];
                }
                $bundle_total += $bundle_item->final_price * $v['quantity'];

                //$prices = Djcatalog2HelperPrice::getCartPrices($bundle_item->final_price, $bundle_item->final_price, $bundle_item->tax_rule_id, false,  $v['quantity'], $params);
                //$bundle_item->prices = $prices;

                $item->bundle_items[$k]['item'] = $bundle_item;
            } else {
                unset($item->bundle_items[$k]);
            }
        }

        $item->bundle_items = array_values($item->bundle_items);

        // another pass for price calculation
        foreach ($item->bundle_items as $k => $v) {
            $old_price = $v['item']->final_price;

            // new price, according to bundle's final price (usually discounted)
            if (trim((string)$v['price']) == '' || $v['price'] == 0.0) {
                // price share of the calculated total price of the bundle
                $price_share = round($old_price / $bundle_total, 4);

                $item->bundle_items[$k]['item']->final_price = round($price_share * $item->final_price, 4);
            }

            $finalPrice = $item->bundle_items[$k]['item']->final_price;
            if ($this->coupon) {
                $finalPrice = $this->coupon->getPrice($finalPrice, $item->id, $v['quantity']);
            }

            //$prices = Djcatalog2HelperPrice::getCartPrices($item->bundle_items[$k]['item']->final_price, $old_price, $v['item']->tax_rule_id, false,  $v['quantity'], $params);
            $prices = Djcatalog2HelperPrice::getCartPrices($finalPrice, $old_price, $v['item']->tax_rule_id, false, $v['quantity'], $params);
            $item->bundle_items[$k]['item']->prices = $prices;
        }

        //JFactory::getApplication()->enqueueMessage('<pre>' . print_r($item->bundle_items, true) .'</pre>');

        if (count($item->bundle_items) < 1) return false;

        return $item->bundle_items;
    }

    public function getBundleStock($item)
    {
        $bundle_items = $this->getBundleItems($item);
        if ($bundle_items == false) return 0;

        $bundle_stock = $item->stock;
        foreach ($item->bundle_items as $k => $v) {

            // ignore always on stock in specific bundle products
            if ($v['onstock'] == 3 || ($v['onstock'] == 2 && $v['combination_id'] == 0)) {
                continue;
            }

            $stock = round(($v['stock'] / $v['quantity']), 2);
            $bundle_stock = min($stock, $bundle_stock);
        }

        return $bundle_stock < 0 ? 0 : (float)$bundle_stock;
    }

    public function getItemBySKU($sku)
    {
        JModelLegacy::addIncludePath(JPath::clean(JPATH_ROOT . '/components/com_djcatalog2/models'), 'DJCatalog2Model');
        $itemModel = JModelLegacy::getInstance('Item', 'DJCatalog2Model', array('ignore_request' => true));

        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from('#__djc2_items_combinations');
        $query->where('sku = ' . $db->quote($sku));
        $db->setQuery($query, 0, 1);
        $resultObj = $db->loadObject();

        $combination_id = (empty($resultObj)) ? 0 : $resultObj->id;

        $query = $db->getQuery(true);
        if ($combination_id > 0) {
            $item_id = $resultObj->item_id;
        } else {
            $query->select('id');
            $query->from('#__djc2_items');
            $query->where('sku = ' . $db->quote($sku));
            $db->setQuery($query, 0, 1);
            $item_id = $db->loadResult();
        }

        if (!$item_id) return false;

        $item = $itemModel->getItem($item_id);

        if (empty($item)) return false;

        $combination = null;
        if ($combination_id > 0) {
            if ($combination = $itemModel->getCombination($combination_id)) {
                $item->_combination = $combination;
            }
        }


        $unit = DJCatalog2HelperQuantity::getUnit($item->unit_id);
        $item->_unit = $unit->unit;

        $return = [
            'id' => $item->id,
            'combination_id' => (!empty($item->_combination)) ? $item->_combination->id : 0,
            'sku' => $sku,
            'final_price' => (!empty($item->_combination) && $item->_combination->price > 0.0) ? $item->_combination->price : $item->final_price,
            'name' => $item->name,
            'unit' => $item->_unit,
            'tax_rule_id' => $item->tax_rule_id,
            'stock' => (!empty($item->_combination)) ? $item->_combination->stock : $item->stock,
            'onstock' => $item->onstock,
            'product_type' => $item->product_type,
            '_combination' => $combination
        ];

        $return = (object)($return);

        return $return;

    }

    public function getError($i = null, $toString = true)
    {
        // Find the error
        if ($i === null) {
            // Default, return the last message
            $error = end($this->_errors);
        } elseif (!array_key_exists($i, $this->_errors)) {
            // If $i has been specified but does not exist, return false
            return false;
        } else {
            $error = $this->_errors[$i];
        }

        // Check if only the string is requested
        if ($error instanceof Exception && $toString) {
            return $error->getMessage();
        }

        return $error;
    }

    public function getErrors()
    {
        return $this->_errors;
    }

    public function setError($error)
    {
        $this->_errors[] = $error;
    }

    private function applyCalculator(&$item)
    {
        if (isset($this->calculators[$item->_sid]) && !empty($this->calculators[$item->_sid])) {
            $calculatorData = $this->calculators[$item->_sid];
            $calculator = CalculatorHelper::getInstance($item->calculator_id);
            $calculatorData += [
                'price' => $item->final_price
            ];

            $item->final_price = $calculator->applyPattern($item, $calculatorData);
            $item->price = $calculator->applyPattern($item, $calculatorData);
        }
    }

}

Anon7 - 2022
AnonSec Team