ProductFrontendSearch.php 5.53 KB
<?php
    
    namespace artweb\artbox\ecommerce\models;
    
    use artweb\artbox\ecommerce\helpers\FilterHelper;
    use artweb\artbox\ecommerce\models\Category;
    use yii\base\Model;
    use yii\data\ActiveDataProvider;
    use yii\data\ArrayDataProvider;
    use yii\db\ActiveQuery;
    
    use artweb\artbox\ecommerce\models\Product;
    use artweb\artbox\ecommerce\models\ProductVariant;
    
    class ProductFrontendSearch extends Product
    {
        
        public $price_interval;
        public $brands;
        
        public function behaviors()
        {
            $behaviors = parent::behaviors();
            
            if (isset( $behaviors[ 'language' ] )) {
                unset( $behaviors[ 'language' ] );
            }
            return $behaviors;
        }
        
        /**
         * @inheritdoc
         */
        public function rules()
        {
            return [
                [
                    [
                        'price_interval',
                        'brands',
                    ],
                    'safe',
                ],
            ];
        }
        
        /**
         * @inheritdoc
         */
        public function scenarios()
        {
            // bypass scenarios() implementation in the parent class
            return Model::scenarios();
        }
        
        /**
         * Creates data provider instance with search query applied for frontend
         *
         * @param array $params
         *
         * @return ArrayDataProvider
         */
        public function search($category = null, $params = [], $in_stock = true)
        {
            
            $dataProvider = new ArrayDataProvider(
                [
                    'allModels'  => $this->getSearchQuery($category, $params, $in_stock)
                                         ->all(),
                    'pagination' => [
                        'pageSize' => 10,
                    ],
                    'sort'       => [
                        'attributes' => [
                            'name_asc'  => [
                                'asc'     => [ 'name' => SORT_ASC ],
                                'desc'    => [ 'name' => SORT_ASC ],
                                'default' => SORT_ASC,
                                'label'   => 'имени от А до Я',
                            ],
                            'name_desc' => [
                                'asc'     => [ 'name' => SORT_DESC ],
                                'desc'    => [ 'name' => SORT_DESC ],
                                'default' => SORT_DESC,
                                'label'   => 'имени от Я до А',
                            ],
                            'price'     => [
                                'asc'     => [ 'price' => SORT_ASC ],
                                'desc'    => [ 'price' => SORT_DESC ],
                                'default' => SORT_DESC,
                                'label'   => 'по цене',
                            ],
                        ],
                    ],
                ]
            );
            
            return $dataProvider;
        }
        
        public function getSearchQuery($category = null, $params = [], $in_stock = true)
        {
            
            if (!empty( $category )) {
                /** @var ActiveQuery $query */
                /**@var Category $category * */
                $query = $category->getProducts();
                
            } else {
                $query = Product::find();
            }
            
            $query->select([ 'product.*' ]);
            $query->joinWith(
                [
                    'lang',
                    'brand.lang',
                    'options',
                ]
            )
                  ->innerJoinWith(
                      [
                          'enabledVariants' => function ($query) {
                              /**
                               * @var ActiveQuery $query
                               */
                              $query->joinWith('lang')
                                    ->with('images');
                          },
                      ]
                  );
            
            $query->groupBy(
                [
                    'product.id',
                    'product_variant.price',
                ]
            );
            
            FilterHelper::setQueryParams($query, $params);
            if ($in_stock) {
                $query->andWhere(
                    [
                        '>=',
                        ProductVariant::tableName() . '.stock',
                        1,
                    ]
                );
            }
            
            return $query;
        }
        
        /**
         * @param Category|null $category
         *
         * @return array
         */
        
        public function priceLimits($category = null)
        {
            if (!empty( $category )) {
                /** @var ActiveQuery $query */
                $query = $category->getProducts();
            } else {
                $query = Product::find();
            }
            $query->joinWith('variant');
            
            return [
                'min' => $query->min(ProductVariant::tableName() . '.price'),
                'max' => $query->max(ProductVariant::tableName() . '.price'),
            ];
        }
    }