Basket.php 9.83 KB
<?php
    
    namespace artbox\order\models;
    
    use artbox\catalog\models\Variant;
    use yii\base\Component;
    use yii\db\ActiveQuery;
    use yii\helpers\Json;
    use yii\web\Cookie;
    use yii\web\NotFoundHttpException;
    
   
    
    /**
     * Class Basket to work with basket
     */
    class Basket extends Component
    {
        /**
         * Session object
         *
         * @var \yii\web\Session
         */
        protected $session;
        public $config = [
          'count_all' => false,
        ];
        
        /**
         * Basket constructor.
         * Check for basket variable in session and set it to empty array if not exist.
         *
         * @param array $config
         */
        public function __construct(array $config = [])
        {
            $this->session = \Yii::$app->session;
            if (!$this->session->has('basket')) {
                $this->session->set('basket', []);
            } elseif (!empty($this->session->get('basket'))) {
                $cookies = \Yii::$app->response->cookies;
                $cookies->add(
                    new Cookie(
                        [
                            'name'  => 'basket',
                            'value' => Json::encode($this->session->get('basket')),
                        ]
                    )
                );
            }
            parent::__construct($config);
        }
        
        /**
         * Increment variant with $variant_id count by 1
         *
         * @param int $variant_id
         * @param int $count
         */
        public function add(int $variant_id, int $count)
        {
            $data = $this->getData();
            if (array_key_exists($variant_id, $data)) {
                if ($data[ $variant_id ][ 'count' ] <= 0) {
                    $data[ $variant_id ][ 'count' ] = $count;
                } else {
                    $data[ $variant_id ][ 'count' ] += $count;
                }
            } else {
                if ($this->findModel($variant_id)) {
                    $data[ $variant_id ] = [
                        'count' => $count,
                    ];
                }
            }
            if ($data[ $variant_id ][ 'count' ] <= 0) {
                unset($data[ $variant_id ]);
            }
            $this->setData($data);
        }
        
        /**
         * Set variant with $variant_id to $count
         *
         * @param int $variant_id
         * @param int $count
         */
        public function set(int $variant_id, int $count)
        {
            $data = $this->getData();
            if (array_key_exists($variant_id, $data)) {
                $data[ $variant_id ][ 'count' ] = $count;
                if ($data[ $variant_id ][ 'count' ] <= 0) {
                    unset($data[ $variant_id ]);
                }
            } elseif ($count > 0) {
                if ($this->findModel($variant_id)) {
                    $data[ $variant_id ] = [
                        'count' => $count,
                    ];
                }
            }
            $this->setData($data);
        }
        
        /**
         * Delete product variant with $variant_id from basket
         *
         * @param int $variant_id
         */
        public function delete(int $variant_id)
        {
            $this->set($variant_id, 0);
        }
        
        /**
         * Get basket data
         *
         * @return array
         */
        public function getData(): array
        {
            return $this->session->get('basket');
        }
        
        /**
         * Get basket item with $variant_id. Returns false if item not in basket.
         *
         * @param int $variant_id
         *
         * @return bool|array
         */
        public function getItem(int $variant_id)
        {
            $data = $this->getData();
            if (!empty($data[ $variant_id ])) {
                return $data[ $variant_id ];
            } else {
                return false;
            }
        }
        
        /**
         * Set basket data
         *
         * @param array $data
         */
        public function setData(array $data)
        {
            $this->session->set('basket', $data);
            $cookies = \Yii::$app->response->cookies;
            if (empty($data)) {
                $cookies->remove('basket');
            } else {
                $cookies->add(
                    new Cookie(
                        [
                            'name'  => 'basket',
                            'value' => Json::encode($data),
                        ]
                    )
                );
            }
        }
        
        /**
         * Get count of variants in basket
         *
         * @return int
         */
        public function getCount(): int
        {
            $data = $this->getData();
            if ($this->config['count_all']){
                $all_data = 0;
                foreach($data as $item){
                    $all_data +=$item['count'];
                }
                return $all_data;
            }
            return count($data);
        }
        
        
        /**
         * Get sum of variants in basket
         *
         * @return float
         */
        public function getSum(): float
        {
            $data = $this->getData();
            $models = $this->findModels(array_keys($data));
            $sum = 0;
            foreach ($models as $model) {
                $sum += $model->price * $data[ $model->id ][ 'count' ];
            }
            return $sum;
        }
        
        /**
         * Find Variant by $variant_id
         *
         * @param int $variant_id
         *
         * @return Variant
         * @throws \yii\web\NotFoundHttpException
         */
        public function findModel(int $variant_id): Variant
        {
            /**
             * @var Variant $model
             */
            $model = Variant::find()
                            ->where([ 'variant.id' => $variant_id ])//                            ->andWhere(
                //                                [
                //                                    '>',
                //                                    'variant.stock',
                //                                    0,
                //                                ]
                //                            )
                            ->joinWith('lang')
                            ->one();
            if (empty($model)) {
                throw new NotFoundHttpException(\Yii::t('app', 'Product not found'));
            } else {
                return $model;
            }
        }
        
        /**
         * Find all Variants filtered by $variant_ids
         *
         * @param array $variant_ids
         *
         * @return Variant[]
         */
        public function findModels(array $variant_ids)
        {
            if (empty($variant_ids)) {
                return [];
            }
            return Variant::find()
                          ->where([ 'variant.id' => $variant_ids ])
                          ->joinWith('lang')
                          ->joinWith(
                              [
                                  'product' => function ($query) {
                                      /**
                                       * @var \yii\db\ActiveQuery $query
                                       */
                                      $query->with(
                                          [
                                              'lang',
                                              'image',
                                          ]
                                      );
                                  },
                              ]
                          )
                          ->with(
                              'image'
                          )
                          ->indexBy('id')
                          ->all();
        }
    
        public function findModelsWithOptions(array $variant_ids)
        {
            if (empty($variant_ids)) {
                return [];
            }
            return Variant::find()
                          ->where([ 'variant.id' => $variant_ids ])
                          ->joinWith(
                              [
                                  'variantOptionExcls' => function (ActiveQuery $query) {
                                      $query->with(
                                          [
                                              'group',
                                              'lang',
                                          ]
                                      );
                                  },
                              ]
                          )
                          ->joinWith('lang')
                          ->joinWith(
                              [
                                  'product' => function ($query) {
                                      /**
                                       * @var \yii\db\ActiveQuery $query
                                       */
                                      $query->with(
                                          [
                                              'lang',
                                              'image',
                                              'category.lang',
                                              'brand.lang',
                                          ]
                                      );
                                  },
                              ]
                          )
                          ->with(
                              'image'
                          )
                          ->indexBy('id')
                          ->all();
        }
        
        /**
         * Clear basket
         */
        public function clear()
        {
            $this->setData([]);
        }
    }