ProductHelper.php 13.9 KB
<?php
    
    namespace common\modules\product\helpers;
    
    use common\modules\product\models\Brand;
    use common\modules\product\models\Category;
    use common\modules\product\models\Product;
    use common\modules\product\models\ProductVariant;
    use yii\base\Object;
    use Yii;
    use yii\db\ActiveQuery;
    
    class ProductHelper extends Object
    {
        
        const PRODUCT_TAX_GROUP_ID_TARGET = 20;
        const PRODUCT_TAX_GROUP_ID_YEAR = 21;
        const PRODUCT_TAX_GROUP_ID_SEX = 22;
        
        public static function getCategories()
        {
            return Category::find()
                           ->getTree(null, 'lang');
        }
        
        public static function getBrands()
        {
            return Brand::find();
        }
        
        /*
         * Return custom filter-option link
         * @var array $filter
         * @var array $options
         * @return array
         */
        public static function getFilterForOption($filter, $key, $value, $remove = false)
        {
            $result = $filter;
            if (is_array($value)) {
                foreach ($value as $value_key => $value_items) {
                    if (!is_array($value_items)) {
                        $value_items = [ $value_items ];
                    }
                    foreach ($value_items as $value_item) {
                        if ($remove && isset( $result[ $key ] ) && ( $i = array_search(
                                $value_item,
                                $result[ $key ][ $value_key ]
                            ) ) !== false
                        ) {
                            unset( $result[ $key ][ $value_key ][ $i ] );
                            if (empty( $result[ $key ][ $value_key ] )) {
                                unset( $result[ $key ][ $value_key ] );
                            }
                        } else {
                            if (!isset( $result[ $key ][ $value_key ] ) || array_search(
                                    $value_item,
                                    $result[ $key ][ $value_key ]
                                ) === false
                            ) {
                                $result[ $key ][ $value_key ][] = $value_item;
                            }
                        }
                    }
                }
            } else {
                if ($remove && isset( $result[ $key ] ) && ( $i = array_search($value, $result[ $key ]) ) !== false) {
                    unset( $result[ $key ][ $i ] );
                    if (empty( $result[ $key ] )) {
                        unset( $result[ $key ] );
                    }
                } else {
                    if (!isset( $result[ $key ] ) || array_search($value, $result[ $key ]) === false) {
                        $result[ $key ][] = $value;
                    }
                }
            }
            return $result;
        }
        
        public static function addLastProsucts($product_id)
        {
            $last_products = self::getLastProducts();
            if (!in_array($product_id, $last_products)) {
                $last_products[] = intval($product_id);
                if (count($last_products) > 16) {
                    array_shift($last_products);
                }
                Yii::$app->session->set('last_products', $last_products);
            }
        }
        
        public static function getLastProducts($as_object = false)
        {
            $last_products = Yii::$app->session->get('last_products', []);
            if ($as_object) {
                $last_products = Product::find()
                                        ->joinWith([ 'variant' ])
                                        ->where([ Product::tableName() . '.id' => $last_products ])
                                        ->andWhere(
                                            [
                                                '!=',
                                                ProductVariant::tableName() . '.stock',
                                                0,
                                            ]
                                        )
                                        ->all();
            }
            return array_reverse($last_products);
        }
        
        public static function getSpecialProducts($type, $count, $sort = null)
        {
            $data = [];
            switch ($type) {
                case 'top':
                    $data = [ 'is_top' => true ];
                    break;
                case 'new':
                    $data = [ 'is_new' => true ];
                    break;
                case 'promo':
                    $data = [ 'is_discount' => true ];
                    break;
            }
            return Product::find()
                          ->with('lang')
                          ->joinWith('variants.lang')
                          ->where($data)
                          ->andWhere(
                              [
                                  '!=',
                                  ProductVariant::tableName() . '.stock',
                                  0,
                              ]
                          )
                          ->limit($count)
                          ->all();
        }
        
        /**
         * @param Product $product
         * @param int     $count
         *
         * @return array|\yii\db\ActiveRecord[]
         */
        public static function getSimilarProducts($product, $count = 10)
        {
            if (!is_object($product)) {
                $product = Product::find()
                                  ->where([ 'id' => $product ])
                                  ->with('enabledVariants')
                                  ->one();
            }
            
            if (!$product->properties) {
                return [];
            }
            $product_categories = [];
            foreach ($product->categories as $category) {
                $product_categories[] = $category->id;
            }
            $query = Product::find()
                            ->select('product.id')
                            ->innerJoinWith('variant')
                            ->joinWith('category')
                            ->where(
                                [
                                    '!=',
                                    'product_variant.stock',
                                    0,
                                ]
                            )
                            ->andWhere([ 'product_category.category_id' => $product_categories ]);
            foreach ($product->properties as $group) {
                $where = [];
                foreach ($group->options as $option) {
                    $where[] = $option->tax_option_id;
                }
                if (!$where) {
                    continue;
                }
                $query->innerJoin(
                    'product_option to' . $group->tax_group_id,
                    'to' . $group->tax_group_id . '.product_id = product.id'
                );
                $query->andWhere([ 'to' . $group->tax_group_id . '.option_id' => $where ]);
            }
            $query->andWhere(
                [
                    '!=',
                    'product.id',
                    $product->id,
                ]
            );
            $query->groupBy('product.id');
            $query->limit($count);
            $products = $query->asArray()
                              ->all();
            foreach ($products as &$_product) {
                $_product = Product::findOne($_product[ 'id' ]);
            }
            return $products;
        }
        
        /**
         * @todo Refactor
         *
         * @param ActiveQuery $query
         * @param             $params
         * @param bool        $setPriceLimits
         */
        public static function setQueryParams(&$query, $params, $setPriceLimits = true)
        {
            if (!empty( $params[ 'keywords' ] )) {
                if (!is_array($params[ 'keywords' ])) {
                    $params[ 'keywords' ] = [ $params[ 'keywords' ] ];
                }
                foreach ($params[ 'keywords' ] as $keyword) {
                    $query->orFilterWhere(
                        [
                            'ilike',
                            Product::tableName() . '.name',
                            $keyword,
                        ]
                    );
                    $query->orFilterWhere(
                        [
                            'ilike',
                            Brand::tableName() . '.name',
                            $keyword,
                        ]
                    );
                    $query->orFilterWhere(
                        [
                            'ilike',
                            Category::tableName() . '.name',
                            $keyword,
                        ]
                    );
                    $query->orFilterWhere(
                        [
                            'ilike',
                            ProductVariant::tableName() . '.sku',
                            $keyword,
                        ]
                    );
                }
            }
            
            foreach ($params as $key => $param) {
                
                switch ($key) {
                    case 'special':
                        foreach ($param as $inner_key => $value) {
                            $query->orFilterWhere([ Product::tableName() . '.' . $inner_key => $value ]);
                        }
                        break;
                    case 'brands':
                        $query->andFilterWhere([ Product::tableName() . '.brand_id' => $param ]);
                        break;
                    case 'keywords':
                        break;
                    case 'prices':
                        if ($param[ 'min' ] > 0) {
                            $query->andWhere(
                                [
                                    '>=',
                                    ProductVariant::tableName() . '.price',
                                    $param[ 'min' ],
                                ]
                            );
                        }
                        if ($param[ 'max' ] > 0) {
                            $query->andWhere(
                                [
                                    '<=',
                                    ProductVariant::tableName() . '.price',
                                    $param[ 'max' ],
                                ]
                            );
                        }
                        break;
                    default:
                        /**
                         * @todo Refactor this
                         */
                        $query->andWhere(
                            Product::tableName() . '.id IN (       
                        SELECT DISTINCT products
                            FROM (
                                SELECT id AS products
                                FROM product_option
                                    INNER JOIN tax_option ON tax_option.tax_option_id = product_option.option_id
                                    INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id
                                WHERE tax_group.alias LIKE \'' . $key . '\' AND tax_option.alias IN (\'' . implode(
                                '\',\'',
                                $param
                            ) . '\') OR product_id IN (
                                  (SELECT product_id AS products
                                FROM product_variant_option
                                    INNER JOIN product_variant ON product_variant_option.product_variant_id = product_variant.id
                                    INNER JOIN tax_option ON tax_option.tax_option_id = product_variant_option.option_id
                                    INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id
                         WHERE tax_group.alias LIKE \'' . $key . '\' AND tax_option.alias IN (\'' . implode(
                                '\',\'',
                                $param
                            ) . '\'))
                                ) 
                                ) AS table_name      
                        )'
                        );
                        break;
                }
                
            }
            
        }
        
        /**
         * @param null|Category $category
         * @param array         $params
         * @param array         $excludeKeys
         *
         * @return ActiveQuery
         */
        public static function productCountQuery($category = null, $params, $excludeKeys = [])
        {
            $p = [];
            foreach ($params as $key => $param) {
                if (in_array($key, $excludeKeys)) {
                    $p[ $key ] = $param;
                }
            }
            /** @var ActiveQuery $query */
            if (!empty( $category )) {
                $query = $category->getProducts();
            } else {
                $query = Product::find();
            }
            ProductHelper::setQueryParams($query, $params);
            $query->select([ 'COUNT(product.id)' ]);
            
            return $query;
        }
        
        public static function addLastCategory($category_id)
        {
            \Yii::$app->session->set('last_category_id', $category_id);
        }
        
        public static function getLastCategory()
        {
            return \Yii::$app->session->get('last_category_id');
        }
    }