CatalogController.php 8.55 KB
<?php

namespace frontend\controllers;

use common\modules\product\models\Brand;
use common\modules\product\models\Category;
use common\modules\product\models\CategorySearch;
use common\modules\product\models\Product;
use common\modules\product\models\ProductCategory;
use common\modules\product\models\ProductOption;
use common\modules\product\models\ProductSearch;
use common\modules\product\models\ProductVariant;
use common\modules\rubrication\models\TaxGroup;
use common\modules\rubrication\models\TaxOption;
use yii\data\ActiveDataProvider;
use yii\data\Pagination;
use yii\data\Sort;
use yii\db\ActiveQuery;
use yii\web\HttpException;

class CatalogController extends \yii\web\Controller
{
    public function actionSearch() {

    }

    public function actionCategory($alias)
    {
        $category = CategorySearch::findByAlias($alias);
        if (empty($category->category_id)) {
            throw new HttpException(404 ,'Page not found');
        }
        if ($category->depth < 2) {
            return $this->render(
                'categories',
                [
                    'category' => $category
                ]
            );
        } else {
            $per_page = 24;

            $sort = new Sort([
                'attributes' => [
                    'name' => [
                        'asc' => ['name' => SORT_ASC],
                        'desc' => ['name' => SORT_DESC],
                        'default' => SORT_DESC,
                        'label' => 'имени',
                    ],
                    'price' => [
                        'asc' => [ProductVariant::tableName() .'.price' => SORT_ASC],
                        'desc' => [ProductVariant::tableName() .'.price' => SORT_DESC],
                        'default' => SORT_DESC,
                        'label' => 'цене',
                    ],
                ],
            ]);
            /** @var ActiveQuery $query */
            $query = $category->getRelations('product_categories')
                ->joinWith([
                    'variants'
                ]);
            $all_count = $query->count();

            $brandsQuery = Brand::find()
                ->innerJoinWith('products')
                ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id')
                ->where([
                    ProductCategory::tableName() .'.category_id' => $category->category_id
                ])
                ->groupBy(Brand::tableName() .'.brand_id');
            $brands = $brandsQuery->all();
            $brands_count = $brandsQuery->count();

            $optionsQuery = TaxOption::find()
                ->select([
                    TaxOption::tableName() .'.*',
                    'COUNT('. ProductOption::tableName() .'.product_id) AS _items_count'
                ])
                ->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id')
                ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id')
                ->where([
                    ProductCategory::tableName() .'.category_id' => $category->category_id
                ])
                ->groupBy(TaxOption::tableName() .'.tax_option_id');
            $all_options = [];
            foreach($optionsQuery->all() as $_option) {
                $all_options[] = $_option;
            }

            $priceQuery = clone $query;
            $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price');
            $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price');

            // Prices
            if (($price_interval = \Yii::$app->request->get('price_interval')) != false) {
                $price_interval = explode(';', $price_interval);
                $price_interval = [
                    floatval($price_interval[0]),
                    floatval($price_interval[1]),
                ];
                if ($price_interval[0] > 0) {
                    $query->andWhere(['>=', ProductVariant::tableName() .'.price', $price_interval[0]]);
                    $priceMinCurr = $price_interval[0];
                }
                if ($price_interval[1] > 0) {
                    $query->andWhere(['<=', ProductVariant::tableName() .'.price', $price_interval[1]]);
                    $priceMaxCurr = $price_interval[1];
                }
            }

            $groups = [];
            foreach($category->getTaxGroups()->all() as $_group) {
                $groups[$_group->tax_group_id] = $_group;
            }
            foreach ($all_options as $option) {
                $groups[$option->tax_group_id]->_options[] = $option;
            }
            foreach($groups as $i => $group) {
                if (empty($group->_options))
                    unset($groups[$i]);
            }

            // Options
            if (($options = \Yii::$app->request->get('option')) != false) {
//                $query->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.product_id='. Product::tableName() .'.product_id');
//                $query->innerJoin(TaxOption::tableName(), TaxOption::tableName() .'.tax_option_id='. ProductOption::tableName() .'.option_id');
                foreach($options as $group_alias => $options_alias) {
                    if (!is_array($options_alias)) {
                        $options_alias = [$options_alias];
                    }
                    foreach($options_alias as &$option_alias) {
                        $option_alias = "'". $option_alias ."'";
                    }
                    $group = TaxGroup::find()->where(['like', 'alias', $group_alias])->one();
                    if (!$group) {
                        continue;
                    }
                    $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 WHERE tax_option.alias IN ('. implode(',', $options_alias) .'))');
                }
            }

            if (($_brands = \Yii::$app->request->get('brand')) != false && is_array($_brands) && count($_brands) > 0) {
                $_brands = Brand::find()->where(['in', 'alias', $_brands])->all();
                $bids = [];
                foreach ($_brands as $brand) {
                    $bids[] = $brand->brand_id;
                }
                if (count($bids)) {
                    $query->andWhere([Product::tableName() .'.brand_id' => $bids]);
                }
            }

            $count = $query->count();

            $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]);
            $query->offset($pages->offset)
                ->orderBy($sort->orders)
                ->limit($pages->limit);
            $products = $query->all();

            return $this->render(
                'products',
                [
                    'category' => $category,
                    'products' => $products,
                    'all_count' => $all_count,
                    'product_count' => $count,
                    'sort' => $sort,
                    'pages' => $pages,
                    'per_page' => $per_page,
                    'priceMin' => $priceMin,
                    'priceMax' => $priceMax,
                    'priceMinCurr' => $priceMinCurr,
                    'priceMaxCurr' => $priceMaxCurr,
                    'brands' => $brands,
                    'brands_count' => $brands_count,
                    'groups' => $groups,
                    'options' => $options,
                ]
            );
        }
    }

    public function actionProduct($alias)
    {
        $product = ProductSearch::findByAlias($alias);
        if (empty($product->product_id)) {
            throw new HttpException(404 ,'Page not found');
        }
        $groups = [];
        foreach($product->category->getTaxGroups()->all() as $_group) {
            $groups[$_group->tax_group_id] = $_group;
        }
        foreach ($product->options as $option) {
            $groups[$option->tax_group_id]->_options[] = $option;
        }
        foreach($groups as $i => $group) {
            if (empty($group->_options))
                unset($groups[$i]);
        }

        return $this->render('product', [
            'product' => $product,
            'properties' => $groups,
        ]);
    }

    public function actionBrands()
    {
        return 'actionBrands';
    }

    public function actionBrand($alias)
    {
        return 'actionBrand:'. $alias;
    }

}