ProductHelper.php 8.37 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 common\modules\product\models\BrandName;
use common\modules\product\models\CategoryName;
use yii\base\Object;
use Yii;

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;

    const PRODUCT_VARIANT_TYPE_COLOR = 1;
    const PRODUCT_VARIANT_TYPE_SIZE = 2;

    public static function getCategories() {
        return Category::find()->getTree(); // with('categoryName')->
    }

    public static function getBrands() {
        return Brand::find(); // ->with('brandName')
    }

    /*
     * 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() .'.product_id' => $last_products])->andWhere(['!=', ProductVariant::tableName() .'.stock', 0])->all();
        }
        return array_reverse($last_products);
    }

    public static function getSpecialProducts($type, $count, $sort = null) {
        switch($type) {
            case 'top':
                $data = ['is_top' => true];
                break;
            case 'new':
                $data = ['is_new' => true];
                break;
            case 'promo':
                $data = ['akciya' => true];
                break;
        }
        return Product::find()->joinWith('variants')->where($data)->andWhere(['!=', ProductVariant::tableName() .'.stock', 0])/*->orderBy($sort)*/->all();
    }

    public static function getSimilarProducts($product, $count = 10) {
        if (!is_object($product)) {
            $product = Product::find()->where(['product_id'=>$product])->with('enabledVariants')->one();
        }

        if (!$product->properties) {
            return [];
        }
        $product_categories = [];
        foreach ($product->categories as $category) {
            $product_categories[] = $category->category_id;
        }
        $query = Product::find()
            ->select('product.product_id')
            ->innerJoinWith('variant')
            ->joinWith('category')
            ->where(['!=', 'product_variant.stock', 0])
            ->andWhere(['product_category.category_id' => $product_categories]);
//        $query->andWhere(['>=', 'product_variant.price', $product->enabledVariant->price * 0.7]);
//        $query->andWhere(['<=', 'product_variant.price', $product->enabledVariant->price * 1.3]);
        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.product_id');
            $query->andWhere(['to'. $group->tax_group_id .'.option_id' => $where]);
        }
        $query->andWhere(['!=', 'product.product_id', $product->product_id]);
        $query->groupBy('product.product_id');
        $query->limit($count);
        $products = $query->asArray()->all();
        foreach ($products as &$_product) {
            $_product = Product::findOne($_product['product_id']);
        }
        return $products;
    }



    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', BrandName::tableName() .'.value', $keyword]);
                $query->orFilterWhere(['ilike', CategoryName::tableName() .'.value', $keyword]);
                $query->orFilterWhere(['ilike', ProductVariant::tableName() .'.sku', $keyword]);
            }
        }

        foreach($params as $key => $param){

            switch ($key) {
                case 'special':
                    foreach($param as $key => $value) {
                        $query->orFilterWhere([Product::tableName() .'.'. $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:
                    $query->andWhere(
                        Product::tableName() . '.product_id IN (SELECT product_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) . '\'))'
                    );
            }

        }

    }

    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.product_id)']);

        return $query;
    }
}