Commit 6fa713cab9dd74a8008022c7b7703bb1099e8b30
1 parent
7450652a
Catalog v 1.2
Showing
20 changed files
with
1165 additions
and
454 deletions
Show diff stats
.gitignore
common/components/artboxtree/ArtboxTreeBehavior.php
@@ -102,6 +102,7 @@ class ArtboxTreeBehavior extends Behavior { | @@ -102,6 +102,7 @@ class ArtboxTreeBehavior extends Behavior { | ||
102 | return $this->buildTree($query->all(), $this->owner->getAttribute($this->keyNameId)); | 102 | return $this->buildTree($query->all(), $this->owner->getAttribute($this->keyNameId)); |
103 | } | 103 | } |
104 | 104 | ||
105 | + // @todo Check algorytm | ||
105 | public function buildTree(array $data, $parentId = 0) { | 106 | public function buildTree(array $data, $parentId = 0) { |
106 | $result = []; | 107 | $result = []; |
107 | foreach ($data as $key => $element) { | 108 | foreach ($data as $key => $element) { |
common/config/main.php
@@ -116,7 +116,7 @@ return [ | @@ -116,7 +116,7 @@ return [ | ||
116 | 'entity2' => [ | 116 | 'entity2' => [ |
117 | 'model' => '\common\modules\rubrication\models\TaxOption', | 117 | 'model' => '\common\modules\rubrication\models\TaxOption', |
118 | 'label' => 'Option', | 118 | 'label' => 'Option', |
119 | - 'listField' => 'ValueeRenderFlash', | 119 | + 'listField' => 'ValueRenderFlash', |
120 | 'key' => 'tax_option_id', | 120 | 'key' => 'tax_option_id', |
121 | 'linked_key' => 'option_id', | 121 | 'linked_key' => 'option_id', |
122 | ], | 122 | ], |
common/models/ProductVariant.php deleted
1 | -<?php | ||
2 | - | ||
3 | -namespace common\models; | ||
4 | - | ||
5 | -use Yii; | ||
6 | - | ||
7 | -/** | ||
8 | - * This is the model class for table "product_variant". | ||
9 | - * | ||
10 | - * @property integer $product_variant_id | ||
11 | - * @property integer $product_id | ||
12 | - * @property string $name | ||
13 | - * @property string $sku | ||
14 | - * @property double $price | ||
15 | - * @property double $price_old | ||
16 | - * @property double $stock | ||
17 | - * @property integer $product_unit_id | ||
18 | - * | ||
19 | - * @property OrderItems[] $orderItems | ||
20 | - * @property ProductUnit $productUnit | ||
21 | - */ | ||
22 | -class ProductVariant extends \yii\db\ActiveRecord | ||
23 | -{ | ||
24 | - /** | ||
25 | - * @inheritdoc | ||
26 | - */ | ||
27 | - public static function tableName() | ||
28 | - { | ||
29 | - return 'product_variant'; | ||
30 | - } | ||
31 | - | ||
32 | - /** | ||
33 | - * @inheritdoc | ||
34 | - */ | ||
35 | - public function rules() | ||
36 | - { | ||
37 | - return [ | ||
38 | - [['product_id', 'sku'], 'required'], | ||
39 | - [['product_id', 'product_unit_id'], 'integer'], | ||
40 | - [['price', 'price_old', 'stock'], 'number'], | ||
41 | - [['name', 'sku'], 'string', 'max' => 255], | ||
42 | - [['product_unit_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductUnit::className(), 'targetAttribute' => ['product_unit_id' => 'product_unit_id']], | ||
43 | - ]; | ||
44 | - } | ||
45 | - | ||
46 | - /** | ||
47 | - * @inheritdoc | ||
48 | - */ | ||
49 | - public function attributeLabels() | ||
50 | - { | ||
51 | - return [ | ||
52 | - 'product_variant_id' => Yii::t('app', 'Product Variant ID'), | ||
53 | - 'product_id' => Yii::t('app', 'Product ID'), | ||
54 | - 'name' => Yii::t('app', 'Name'), | ||
55 | - 'sku' => Yii::t('app', 'Sku'), | ||
56 | - 'price' => Yii::t('app', 'Price'), | ||
57 | - 'price_old' => Yii::t('app', 'Price Old'), | ||
58 | - 'stock' => Yii::t('app', 'Stock'), | ||
59 | - 'product_unit_id' => Yii::t('app', 'Product Unit ID'), | ||
60 | - ]; | ||
61 | - } | ||
62 | - | ||
63 | - /** | ||
64 | - * @return \yii\db\ActiveQuery | ||
65 | - */ | ||
66 | - public function getOrderItems() | ||
67 | - { | ||
68 | - return $this->hasMany(OrderItems::className(), ['item_id' => 'product_variant_id']); | ||
69 | - } | ||
70 | - | ||
71 | - /** | ||
72 | - * @return \yii\db\ActiveQuery | ||
73 | - */ | ||
74 | - public function getProductUnit() | ||
75 | - { | ||
76 | - return $this->hasOne(ProductUnit::className(), ['product_unit_id' => 'product_unit_id']); | ||
77 | - } | ||
78 | -} |
1 | +<?php | ||
2 | + | ||
3 | +namespace common\modules\product; | ||
4 | + | ||
5 | +use common\modules\product\models\Brand; | ||
6 | +use common\modules\product\models\CategorySearch; | ||
7 | +use common\modules\product\models\ProductSearch; | ||
8 | +use common\modules\rubrication\models\TaxOption; | ||
9 | +use Yii; | ||
10 | +use yii\helpers\Url; | ||
11 | +use yii\web\UrlRuleInterface; | ||
12 | + | ||
13 | +class CatalogUrlManager implements UrlRuleInterface { | ||
14 | + public $route_map = []; | ||
15 | + | ||
16 | + public $option_prefix = 'o:'; | ||
17 | + /** | ||
18 | + * Parses the given request and returns the corresponding route and parameters. | ||
19 | + * @param \yii\web\UrlManager $manager the URL manager | ||
20 | + * @param \yii\web\Request $request the request component | ||
21 | + * @return array|boolean the parsing result. The route and the parameters are returned as an array. | ||
22 | + * If false, it means this rule cannot be used to parse this path info. | ||
23 | + */ | ||
24 | + public function parseRequest($manager, $request) | ||
25 | + { | ||
26 | + $pathInfo = $request->getPathInfo(); | ||
27 | + $paths = explode('/', $pathInfo); | ||
28 | + | ||
29 | + if (!array_key_exists($paths[0], $this->route_map)) { | ||
30 | + return false; | ||
31 | + } | ||
32 | + | ||
33 | + $params = []; | ||
34 | + if ($paths[0] == 'catalog') { | ||
35 | + $route = 'catalog/category'; | ||
36 | + // Category | ||
37 | + if (!empty($paths[1])) { | ||
38 | + $category = CategorySearch::findByAlias($paths[1]); | ||
39 | + if (empty($category)) { | ||
40 | + http_redirect(Url::to(['/'])); | ||
41 | + } | ||
42 | + $params['category'] = $category; | ||
43 | + } | ||
44 | + // Filter | ||
45 | + if (!empty($paths[2])) { | ||
46 | + if (strpos($paths[2], 'filter:') === 0) { | ||
47 | + $params['filter'] = []; | ||
48 | + $filter_str = substr($paths[2], 7); | ||
49 | + $filter_options = explode(';', $filter_str); | ||
50 | + foreach ($filter_options as $filter_option) { | ||
51 | + if (empty($filter_option)) { | ||
52 | + continue; | ||
53 | + } | ||
54 | + list($filter_key, $filter_option) = explode('=', $filter_option); | ||
55 | + if($filter_key == 'prices') { // price-interval section | ||
56 | + $prices = explode(':', $filter_option); | ||
57 | + $params['filter'][$filter_key] = [ | ||
58 | + 'min' => floatval($prices[0]), | ||
59 | + 'max' => floatval($prices[1]), | ||
60 | + ]; | ||
61 | + } elseif (strpos($filter_key, $this->option_prefix) === 0) { // options section | ||
62 | + $params['filter']['options'][substr($filter_key, 2)] = explode(',', $filter_option); | ||
63 | + } else { // brands and other sections | ||
64 | + $params['filter'][$filter_key] = explode(',', $filter_option); | ||
65 | + } | ||
66 | + | ||
67 | + } | ||
68 | + } | ||
69 | + } | ||
70 | + } elseif ($paths[0] == 'product') { | ||
71 | + $product = ProductSearch::findByAlias($paths[1]); | ||
72 | + if (empty($product->product_id)) { | ||
73 | + throw new HttpException(404 ,'Page not found'); | ||
74 | + } | ||
75 | + $route = 'catalog/product'; | ||
76 | + $params = [ | ||
77 | + 'product' => $product, | ||
78 | + ]; | ||
79 | + } elseif ($paths[0] == 'brand') { | ||
80 | + | ||
81 | + } | ||
82 | + | ||
83 | + return [$route, $params]; | ||
84 | + } | ||
85 | + /** | ||
86 | + * Creates a URL according to the given route and parameters. | ||
87 | + * @param \yii\web\UrlManager $manager the URL manager | ||
88 | + * @param string $route the route. It should not have slashes at the beginning or the end. | ||
89 | + * @param array $params the parameters | ||
90 | + * @return string|boolean the created URL, or false if this rule cannot be used for creating this URL. | ||
91 | + */ | ||
92 | + public function createUrl($manager, $route, $params) | ||
93 | + { | ||
94 | + if (!in_array($route, $this->route_map)) { | ||
95 | + return false; | ||
96 | + } | ||
97 | + | ||
98 | + switch($route) { | ||
99 | + case 'catalog/category': | ||
100 | + if (!empty($params['category'])) { | ||
101 | + $category_alias = is_object($params['category']) ? $params['category']->alias : strtolower($params['category']); | ||
102 | + } | ||
103 | + $url = 'catalog/'. $category_alias .'/'; | ||
104 | + | ||
105 | + $filter = []; | ||
106 | + if (!empty($params['filter'])) { | ||
107 | + foreach ($params['filter'] as $key => $values) { | ||
108 | + switch($key) { | ||
109 | + case 'prices': | ||
110 | + $filter[] = $key .'='. implode(':', $values); | ||
111 | + break; | ||
112 | + | ||
113 | + case 'options': | ||
114 | + foreach($values as $group => &$value_items) { | ||
115 | + foreach($value_items as &$value_item) { | ||
116 | + $value_item = $this->option_value_encode($value_item); | ||
117 | + if (empty($value_item)) { | ||
118 | + unset($value_item); | ||
119 | + } | ||
120 | + } | ||
121 | + $filter[] = $this->option_prefix. $group .'='. implode(',', $value_items); | ||
122 | + } | ||
123 | + break; | ||
124 | + | ||
125 | + default: | ||
126 | + foreach($values as &$value) { | ||
127 | + $value = $this->option_value_encode($value); | ||
128 | + if (empty($value)) { | ||
129 | + unset($value); | ||
130 | + } | ||
131 | + } | ||
132 | + $filter[] = $key .'='. implode(',', $values); | ||
133 | + break; | ||
134 | + } | ||
135 | + } | ||
136 | + $url .= 'filter:'. implode(';', $filter); | ||
137 | + } | ||
138 | + return $url; | ||
139 | + break; | ||
140 | + | ||
141 | + case 'catalog/product': | ||
142 | + if (!empty($params['product'])) { | ||
143 | + $product_alias = is_object($params['product']) ? $params['product']->alias : strtolower($params['product']); | ||
144 | + } | ||
145 | + $url = 'product/'. $product_alias; | ||
146 | + return $url; | ||
147 | + break; | ||
148 | + } | ||
149 | + } | ||
150 | + | ||
151 | + private function option_value_encode($value) { | ||
152 | + return str_replace(array(',', '/'), array('~', '&s;'), $value); | ||
153 | + } | ||
154 | +} | ||
0 | \ No newline at end of file | 155 | \ No newline at end of file |
common/modules/product/helpers/ProductHelper.php
@@ -14,4 +14,45 @@ class ProductHelper extends Object { | @@ -14,4 +14,45 @@ class ProductHelper extends Object { | ||
14 | public static function getBrands() { | 14 | public static function getBrands() { |
15 | return Brand::find()->with('brandName'); | 15 | return Brand::find()->with('brandName'); |
16 | } | 16 | } |
17 | + | ||
18 | + /* | ||
19 | + * Return custom filter-option link | ||
20 | + * @var array $filter | ||
21 | + * @var array $options | ||
22 | + * @return array | ||
23 | + */ | ||
24 | + public static function getFilterForOption($filter, $key, $value, $remove = false) { | ||
25 | + $result = $filter; | ||
26 | + if (is_array($value)) { | ||
27 | + foreach($value as $value_key => $value_items) { | ||
28 | + if (!is_array($value_items)) { | ||
29 | + $value_items = [$value_items]; | ||
30 | + } | ||
31 | + foreach($value_items as $value_item) { | ||
32 | + if ($remove && isset($result[$key]) && ($i = array_search($value_item, $result[$key][$value_key])) !== FALSE) { | ||
33 | + unset($result[$key][$value_key][$i]); | ||
34 | + if (empty($result[$key][$value_key])) { | ||
35 | + unset($result[$key][$value_key]); | ||
36 | + } | ||
37 | + } else { | ||
38 | + if (!isset($result[$key][$value_key]) || array_search($value_item, $result[$key][$value_key]) === FALSE) { | ||
39 | + $result[$key][$value_key][] = $value_item; | ||
40 | + } | ||
41 | + } | ||
42 | + } | ||
43 | + } | ||
44 | + } else { | ||
45 | + if ($remove && isset($result[$key]) && ($i = array_search($value, $result[$key])) !== FALSE) { | ||
46 | + unset($result[$key][$i]); | ||
47 | + if (empty($result[$key])) { | ||
48 | + unset($result[$key]); | ||
49 | + } | ||
50 | + } else { | ||
51 | + if (!isset($result[$key]) || array_search($value, $result[$key]) === FALSE) { | ||
52 | + $result[$key][] = $value; | ||
53 | + } | ||
54 | + } | ||
55 | + } | ||
56 | + return $result; | ||
57 | + } | ||
17 | } | 58 | } |
18 | \ No newline at end of file | 59 | \ No newline at end of file |
common/modules/product/models/BrandSearch.php
@@ -72,4 +72,40 @@ class BrandSearch extends Brand | @@ -72,4 +72,40 @@ class BrandSearch extends Brand | ||
72 | 72 | ||
73 | return $dataProvider; | 73 | return $dataProvider; |
74 | } | 74 | } |
75 | + | ||
76 | + public function getBrands($category, $params) { | ||
77 | + $query = Brand::find() | ||
78 | + ->select([ | ||
79 | + Brand::tableName() .'.*', | ||
80 | + 'COUNT('. ProductCategory::tableName() .'.product_id) AS _items_count' | ||
81 | + ]) | ||
82 | + ->innerJoin(Product::tableName(), Product::tableName() .'.brand_id='. Brand::tableName() .'.brand_id') | ||
83 | + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id') | ||
84 | + | ||
85 | + ->with('brandName') | ||
86 | + ->where([ | ||
87 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
88 | + ]) | ||
89 | + ->groupBy(Brand::tableName() .'.brand_id'); | ||
90 | + if (isset($params['options'])) { | ||
91 | + unset($params['options']); | ||
92 | + } | ||
93 | + if (!empty($params['prices'])) { | ||
94 | + if ($params['prices']['min'] > 0 || $params['prices']['max'] > 0) { | ||
95 | + $query->innerJoin(ProductVariant::tableName(), ProductVariant::tableName() .'.product_id='. Product::tableName() .'.product_id'); | ||
96 | + } | ||
97 | + if ($params['prices']['min'] > 0) { | ||
98 | + $query->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); | ||
99 | + } | ||
100 | + if ($params['prices']['max'] > 0) { | ||
101 | + $query->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); | ||
102 | + } | ||
103 | + } | ||
104 | + | ||
105 | + $dataProvider = new ActiveDataProvider([ | ||
106 | + 'query' => $query, | ||
107 | + ]); | ||
108 | + | ||
109 | + return $dataProvider; | ||
110 | + } | ||
75 | } | 111 | } |
common/modules/product/widgets/views/submenu.php
1 | <div class="menu_item"> | 1 | <div class="menu_item"> |
2 | - <?= \yii\helpers\Html::a($rootCategory->categoryName->value, ['catalog/category', 'alias' => $rootCategory->alias], ['class' => 'submenu_button '. $rootClass])?> | 2 | + <?= \yii\helpers\Html::a($rootCategory->categoryName->value, ['catalog/category', 'category' => $rootCategory], ['class' => 'submenu_button '. $rootClass])?> |
3 | <div class="submenu"> | 3 | <div class="submenu"> |
4 | <ul class="categories"> | 4 | <ul class="categories"> |
5 | <li class="sub_cat"><span>Популярные категории</span> | 5 | <li class="sub_cat"><span>Популярные категории</span> |
@@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
7 | <div class="sub_cat_content"> | 7 | <div class="sub_cat_content"> |
8 | <div class="content_items"> | 8 | <div class="content_items"> |
9 | <?php foreach($populary as $_item) :?> | 9 | <?php foreach($populary as $_item) :?> |
10 | - <div class="content_item"><a href="<?= \yii\helpers\Url::to(['catalog/category', 'alias' => $_item->alias])?>"> | 10 | + <div class="content_item"><a href="<?= \yii\helpers\Url::to(['catalog/category', 'category' => $_item])?>"> |
11 | <div valign="top" class="picture"> | 11 | <div valign="top" class="picture"> |
12 | <?php if (empty($_item->image)) :?> | 12 | <?php if (empty($_item->image)) :?> |
13 | <img valign="top" src="/images/no_photo.png"> | 13 | <img valign="top" src="/images/no_photo.png"> |
@@ -29,7 +29,7 @@ | @@ -29,7 +29,7 @@ | ||
29 | <div class="sub_cat_content"> | 29 | <div class="sub_cat_content"> |
30 | <div class="content_items"> | 30 | <div class="content_items"> |
31 | <?php foreach($item['children'] as $_item) :?> | 31 | <?php foreach($item['children'] as $_item) :?> |
32 | - <div class="content_item"><a href="<?= \yii\helpers\Url::to(['/catalog/category', 'alias' => $_item['item']->alias])?>"> | 32 | + <div class="content_item"><a href="<?= \yii\helpers\Url::to(['catalog/category', 'category' => $_item['item']])?>"> |
33 | <div valign="top" class="picture"> | 33 | <div valign="top" class="picture"> |
34 | <?php if (empty($_item['item']->image)) :?> | 34 | <?php if (empty($_item['item']->image)) :?> |
35 | <img valign="top" src="/images/no_photo.png"> | 35 | <img valign="top" src="/images/no_photo.png"> |
common/modules/rubrication/models/TaxGroup.php
@@ -15,6 +15,7 @@ use Yii; | @@ -15,6 +15,7 @@ use Yii; | ||
15 | * @property string $module | 15 | * @property string $module |
16 | * @property boolean $hierarchical | 16 | * @property boolean $hierarchical |
17 | * @property string $settings | 17 | * @property string $settings |
18 | + * @property boolean is_filter | ||
18 | * | 19 | * |
19 | * @property TaxGroupToGroup[] $taxGroupToGroups | 20 | * @property TaxGroupToGroup[] $taxGroupToGroups |
20 | * @property TaxGroupToGroup[] $taxGroupToGroups0 | 21 | * @property TaxGroupToGroup[] $taxGroupToGroups0 |
@@ -81,6 +82,7 @@ class TaxGroup extends \yii\db\ActiveRecord | @@ -81,6 +82,7 @@ class TaxGroup extends \yii\db\ActiveRecord | ||
81 | 'module' => 'Module', | 82 | 'module' => 'Module', |
82 | 'hierarchical' => 'Hierarchical', | 83 | 'hierarchical' => 'Hierarchical', |
83 | // 'settings' => 'Settings', | 84 | // 'settings' => 'Settings', |
85 | + 'is_filter' => 'Use in filter', | ||
84 | ]; | 86 | ]; |
85 | } | 87 | } |
86 | 88 |
frontend/config/main.php
@@ -47,11 +47,20 @@ return [ | @@ -47,11 +47,20 @@ return [ | ||
47 | 'enablePrettyUrl' => true, | 47 | 'enablePrettyUrl' => true, |
48 | 'showScriptName' => false, | 48 | 'showScriptName' => false, |
49 | 'rules' => [ | 49 | 'rules' => [ |
50 | -// 'catalog' => 'catalog/category', | ||
51 | - 'catalog/<alias:[A-Za-z0-9_-]+>' => 'catalog/category', | ||
52 | - 'product/<alias:[A-Za-z0-9_-]+>' => 'catalog/product', | ||
53 | - 'brand' => 'catalog/brands', | ||
54 | - 'brand/<alias:[A-Za-z0-9_-]+>' => 'catalog/brand', | 50 | + [ |
51 | + 'class' => '\common\modules\product\CatalogUrlManager', | ||
52 | + 'route_map' => [ | ||
53 | + 'catalog' => 'catalog/category', | ||
54 | + 'product' => 'catalog/product', | ||
55 | + 'brand' => 'catalog/brand', | ||
56 | + ] | ||
57 | + ], | ||
58 | +//// 'catalog' => 'catalog/category', | ||
59 | +// 'catalog/<alias:[A-Za-z0-9_-]+>' => 'catalog/category', | ||
60 | +// 'catalog/<alias:[A-Za-z0-9_-]+>/<filter>' => 'catalog/category', | ||
61 | +// 'product/<alias:[A-Za-z0-9_-]+>' => 'catalog/product', | ||
62 | +// 'brand' => 'catalog/brands', | ||
63 | +// 'brand/<alias:[A-Za-z0-9_-]+>' => 'catalog/brand', | ||
55 | ] | 64 | ] |
56 | ] | 65 | ] |
57 | 66 |
1 | +<?php | ||
2 | + | ||
3 | +namespace frontend\controllers; | ||
4 | + | ||
5 | +use common\modules\product\models\Brand; | ||
6 | +use common\modules\product\models\Category; | ||
7 | +use common\modules\product\models\CategorySearch; | ||
8 | +use common\modules\product\models\Product; | ||
9 | +use common\modules\product\models\ProductCategory; | ||
10 | +use common\modules\product\models\ProductOption; | ||
11 | +use common\modules\product\models\ProductSearch; | ||
12 | +use common\modules\product\models\ProductVariant; | ||
13 | +use common\modules\rubrication\models\TaxGroup; | ||
14 | +use common\modules\rubrication\models\TaxOption; | ||
15 | +use common\modules\rubrication\models\TaxValueString; | ||
16 | +use yii\data\ActiveDataProvider; | ||
17 | +use yii\data\Pagination; | ||
18 | +use yii\data\Sort; | ||
19 | +use yii\db\ActiveQuery; | ||
20 | +use yii\web\HttpException; | ||
21 | + | ||
22 | +class CatalogController extends \yii\web\Controller | ||
23 | +{ | ||
24 | + public function actionSearch() { | ||
25 | + | ||
26 | + } | ||
27 | + | ||
28 | + public function actionCategory($alias) | ||
29 | + { | ||
30 | + $category = CategorySearch::findByAlias($alias); | ||
31 | + if (empty($category->category_id)) { | ||
32 | + throw new HttpException(404 ,'Page not found'); | ||
33 | + } | ||
34 | + if ($category->depth < 2) { | ||
35 | + return $this->render( | ||
36 | + 'categories', | ||
37 | + [ | ||
38 | + 'category' => $category | ||
39 | + ] | ||
40 | + ); | ||
41 | + } else { | ||
42 | + $per_page = 24; | ||
43 | + | ||
44 | + $sort = new Sort([ | ||
45 | + 'attributes' => [ | ||
46 | + 'name' => [ | ||
47 | + 'asc' => ['name' => SORT_ASC], | ||
48 | + 'desc' => ['name' => SORT_DESC], | ||
49 | + 'default' => SORT_DESC, | ||
50 | + 'label' => 'имени', | ||
51 | + ], | ||
52 | + 'price' => [ | ||
53 | + 'asc' => [ProductVariant::tableName() .'.price' => SORT_ASC], | ||
54 | + 'desc' => [ProductVariant::tableName() .'.price' => SORT_DESC], | ||
55 | + 'default' => SORT_DESC, | ||
56 | + 'label' => 'цене', | ||
57 | + ], | ||
58 | + ], | ||
59 | + ]); | ||
60 | + /** @var ActiveQuery $query */ | ||
61 | + $query = $category->getRelations('product_categories') | ||
62 | + ->joinWith([ | ||
63 | + 'variants' | ||
64 | + ]); | ||
65 | + $all_count = $query->count(); | ||
66 | + | ||
67 | + $brandsQuery = Brand::find() | ||
68 | + ->innerJoinWith('brandName') | ||
69 | + ->innerJoinWith('products') | ||
70 | + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id') | ||
71 | + ->where([ | ||
72 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
73 | + ]) | ||
74 | + ->groupBy(Brand::tableName() .'.brand_id'); | ||
75 | + $brands = $brandsQuery->all(); | ||
76 | + $brands_count = count($brands); // $brandsQuery->count(); | ||
77 | + | ||
78 | + $optionsQuery = TaxOption::find() | ||
79 | + ->select([ | ||
80 | + TaxOption::tableName() .'.*', | ||
81 | + 'COUNT('. ProductOption::tableName() .'.product_id) AS _items_count' | ||
82 | + ]) | ||
83 | + ->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id') | ||
84 | + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id') | ||
85 | + ->innerJoinWith('group') | ||
86 | + ->where([ | ||
87 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
88 | + ]) | ||
89 | + ->groupBy(TaxOption::tableName() .'.tax_option_id'); | ||
90 | + $all_options = []; | ||
91 | + foreach($optionsQuery->all() as $_option) { | ||
92 | + $all_options[] = $_option; | ||
93 | + } | ||
94 | + | ||
95 | + $priceQuery = clone $query; | ||
96 | + $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price'); | ||
97 | + $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price'); | ||
98 | + | ||
99 | + // Prices | ||
100 | + if (($price_interval = \Yii::$app->request->get('price_interval')) != false) { | ||
101 | + $price_interval = explode(';', $price_interval); | ||
102 | + $price_interval = [ | ||
103 | + floatval($price_interval[0]), | ||
104 | + floatval($price_interval[1]), | ||
105 | + ]; | ||
106 | + if ($price_interval[0] > 0) { | ||
107 | + $query->andWhere(['>=', ProductVariant::tableName() .'.price', $price_interval[0]]); | ||
108 | + $priceMinCurr = $price_interval[0]; | ||
109 | + } | ||
110 | + if ($price_interval[1] > 0) { | ||
111 | + $query->andWhere(['<=', ProductVariant::tableName() .'.price', $price_interval[1]]); | ||
112 | + $priceMaxCurr = $price_interval[1]; | ||
113 | + } | ||
114 | + } | ||
115 | + | ||
116 | + $groups = []; | ||
117 | + foreach($category->getTaxGroups()->all() as $_group) { | ||
118 | + $groups[$_group->tax_group_id] = $_group; | ||
119 | + } | ||
120 | + foreach ($all_options as $option) { | ||
121 | + $groups[$option->tax_group_id]->_options[] = $option; | ||
122 | + } | ||
123 | + foreach($groups as $i => $group) { | ||
124 | + if (empty($group->_options)) | ||
125 | + unset($groups[$i]); | ||
126 | + } | ||
127 | + | ||
128 | + // Options | ||
129 | + if (($options = \Yii::$app->request->get('option')) != false) { | ||
130 | +// $query->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.product_id='. Product::tableName() .'.product_id'); | ||
131 | +// $query->innerJoin(TaxOption::tableName(), TaxOption::tableName() .'.tax_option_id='. ProductOption::tableName() .'.option_id'); | ||
132 | + foreach($options as $group_alias => $options_alias) { | ||
133 | + if (!is_array($options_alias)) { | ||
134 | + $options_alias = [$options_alias]; | ||
135 | + } | ||
136 | + foreach($options_alias as &$option_alias) { | ||
137 | + $option_alias = "'". $option_alias ."'"; | ||
138 | + } | ||
139 | + /*$group = TaxGroup::find()->where(['like', 'alias', $group_alias])->one(); | ||
140 | + if (!$group) { | ||
141 | + continue; | ||
142 | + }*/ | ||
143 | + } | ||
144 | + $query->andWhere( | ||
145 | + 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) .'))' | ||
146 | + ); | ||
147 | + } | ||
148 | + | ||
149 | + if (($_brands = \Yii::$app->request->get('brand')) != false && is_array($_brands) && count($_brands) > 0) { | ||
150 | + $_brands = Brand::find()->where(['in', 'alias', $_brands])->all(); | ||
151 | + $bids = []; | ||
152 | + foreach ($_brands as $brand) { | ||
153 | + $bids[] = $brand->brand_id; | ||
154 | + } | ||
155 | + if (count($bids)) { | ||
156 | + $query->andWhere([Product::tableName() .'.brand_id' => $bids]); | ||
157 | + } | ||
158 | + } | ||
159 | + | ||
160 | + $query->with('variant'); | ||
161 | + $query->with('brand'); | ||
162 | + $query->with('categories'); | ||
163 | + $query->with('image'); | ||
164 | + | ||
165 | + $count = $query->count(); | ||
166 | + $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]); | ||
167 | + $query->offset($pages->offset) | ||
168 | + ->orderBy($sort->orders) | ||
169 | + ->limit($pages->limit); | ||
170 | + | ||
171 | + $products = $query->all(); | ||
172 | + | ||
173 | + return $this->render( | ||
174 | + 'products', | ||
175 | + [ | ||
176 | + 'category' => $category, | ||
177 | + 'products' => $products, | ||
178 | + 'all_count' => $all_count, | ||
179 | + 'product_count' => $count, | ||
180 | + 'sort' => $sort, | ||
181 | + 'pages' => $pages, | ||
182 | + 'per_page' => $per_page, | ||
183 | + 'priceMin' => $priceMin, | ||
184 | + 'priceMax' => $priceMax, | ||
185 | + 'priceMinCurr' => $priceMinCurr, | ||
186 | + 'priceMaxCurr' => $priceMaxCurr, | ||
187 | + '_brands' => $_brands, | ||
188 | + 'brands' => $brands, | ||
189 | + 'brands_count' => $brands_count, | ||
190 | + 'groups' => $groups, | ||
191 | + 'options' => $options, | ||
192 | + ] | ||
193 | + ); | ||
194 | + } | ||
195 | + } | ||
196 | + | ||
197 | + public function actionProduct($alias) | ||
198 | + { | ||
199 | + $product = ProductSearch::findByAlias($alias); | ||
200 | + if (empty($product->product_id)) { | ||
201 | + throw new HttpException(404 ,'Page not found'); | ||
202 | + } | ||
203 | + $groups = []; | ||
204 | + foreach($product->category->getTaxGroups()->all() as $_group) { | ||
205 | + $groups[$_group->tax_group_id] = $_group; | ||
206 | + } | ||
207 | + foreach ($product->options as $option) { | ||
208 | + $groups[$option->tax_group_id]->_options[] = $option; | ||
209 | + } | ||
210 | + foreach($groups as $i => $group) { | ||
211 | + if (empty($group->_options)) | ||
212 | + unset($groups[$i]); | ||
213 | + } | ||
214 | + | ||
215 | + return $this->render('product', [ | ||
216 | + 'product' => $product, | ||
217 | + 'properties' => $groups, | ||
218 | + ]); | ||
219 | + } | ||
220 | + | ||
221 | + public function actionBrands() | ||
222 | + { | ||
223 | + return 'actionBrands'; | ||
224 | + } | ||
225 | + | ||
226 | + public function actionBrand($alias) | ||
227 | + { | ||
228 | + return 'actionBrand:'. $alias; | ||
229 | + } | ||
230 | + | ||
231 | +} |
frontend/controllers/CatalogController.php
@@ -2,7 +2,12 @@ | @@ -2,7 +2,12 @@ | ||
2 | 2 | ||
3 | namespace frontend\controllers; | 3 | namespace frontend\controllers; |
4 | 4 | ||
5 | +use common\modules\product\Filter; | ||
6 | +use common\modules\rubrication\models\TaxOptionSearch; | ||
7 | +use frontend\models\ProductFrontendSearch; | ||
8 | +use Yii; | ||
5 | use common\modules\product\models\Brand; | 9 | use common\modules\product\models\Brand; |
10 | +use common\modules\product\models\BrandSearch; | ||
6 | use common\modules\product\models\Category; | 11 | use common\modules\product\models\Category; |
7 | use common\modules\product\models\CategorySearch; | 12 | use common\modules\product\models\CategorySearch; |
8 | use common\modules\product\models\Product; | 13 | use common\modules\product\models\Product; |
@@ -25,9 +30,12 @@ class CatalogController extends \yii\web\Controller | @@ -25,9 +30,12 @@ class CatalogController extends \yii\web\Controller | ||
25 | 30 | ||
26 | } | 31 | } |
27 | 32 | ||
28 | - public function actionCategory($alias) | 33 | + public function actionCategory() |
29 | { | 34 | { |
30 | - $category = CategorySearch::findByAlias($alias); | 35 | + /** @var Category $category */ |
36 | + $category = Yii::$app->request->get('category'); | ||
37 | + $filter = Yii::$app->request->get('filter', []); | ||
38 | + | ||
31 | if (empty($category->category_id)) { | 39 | if (empty($category->category_id)) { |
32 | throw new HttpException(404 ,'Page not found'); | 40 | throw new HttpException(404 ,'Page not found'); |
33 | } | 41 | } |
@@ -39,85 +47,51 @@ class CatalogController extends \yii\web\Controller | @@ -39,85 +47,51 @@ class CatalogController extends \yii\web\Controller | ||
39 | ] | 47 | ] |
40 | ); | 48 | ); |
41 | } else { | 49 | } else { |
42 | - $per_page = 24; | ||
43 | - | ||
44 | - $sort = new Sort([ | ||
45 | - 'attributes' => [ | ||
46 | - 'name' => [ | ||
47 | - 'asc' => ['name' => SORT_ASC], | ||
48 | - 'desc' => ['name' => SORT_DESC], | ||
49 | - 'default' => SORT_DESC, | ||
50 | - 'label' => 'имени', | ||
51 | - ], | ||
52 | - 'price' => [ | ||
53 | - 'asc' => [ProductVariant::tableName() .'.price' => SORT_ASC], | ||
54 | - 'desc' => [ProductVariant::tableName() .'.price' => SORT_DESC], | ||
55 | - 'default' => SORT_DESC, | ||
56 | - 'label' => 'цене', | ||
57 | - ], | ||
58 | - ], | ||
59 | - ]); | ||
60 | - /** @var ActiveQuery $query */ | ||
61 | - $query = $category->getRelations('product_categories') | ||
62 | - ->joinWith([ | ||
63 | - 'variants' | ||
64 | - ]); | ||
65 | - $all_count = $query->count(); | ||
66 | - | ||
67 | - $brandsQuery = Brand::find() | ||
68 | - ->innerJoinWith('brandName') | ||
69 | - ->innerJoinWith('products') | ||
70 | - ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id') | ||
71 | - ->where([ | ||
72 | - ProductCategory::tableName() .'.category_id' => $category->category_id | ||
73 | - ]) | ||
74 | - ->groupBy(Brand::tableName() .'.brand_id'); | ||
75 | - $brands = $brandsQuery->all(); | ||
76 | - $brands_count = count($brands); // $brandsQuery->count(); | ||
77 | - | ||
78 | - $optionsQuery = TaxOption::find() | ||
79 | - ->select([ | ||
80 | - TaxOption::tableName() .'.*', | ||
81 | - 'COUNT('. ProductOption::tableName() .'.product_id) AS _items_count' | ||
82 | - ]) | ||
83 | - ->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id') | ||
84 | - ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id') | ||
85 | - ->innerJoinWith('group') | ||
86 | - ->where([ | ||
87 | - ProductCategory::tableName() .'.category_id' => $category->category_id | ||
88 | - ]) | ||
89 | - ->groupBy(TaxOption::tableName() .'.tax_option_id'); | ||
90 | - $all_options = []; | ||
91 | - foreach($optionsQuery->all() as $_option) { | ||
92 | - $all_options[] = $_option; | ||
93 | - } | 50 | + $params = []; |
94 | 51 | ||
95 | - $priceQuery = clone $query; | ||
96 | - $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price'); | ||
97 | - $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price'); | ||
98 | - | ||
99 | - // Prices | ||
100 | - if (($price_interval = \Yii::$app->request->get('price_interval')) != false) { | ||
101 | - $price_interval = explode(';', $price_interval); | ||
102 | - $price_interval = [ | ||
103 | - floatval($price_interval[0]), | ||
104 | - floatval($price_interval[1]), | ||
105 | - ]; | ||
106 | - if ($price_interval[0] > 0) { | ||
107 | - $query->andWhere(['>=', ProductVariant::tableName() .'.price', $price_interval[0]]); | ||
108 | - $priceMinCurr = $price_interval[0]; | 52 | + if ( !empty($filter['brands']) ) { |
53 | + $brands = Brand::find()->select('brand_id')->where(['in', 'alias', $filter['brands']])->all(); | ||
54 | + $params['brands'] = []; | ||
55 | + foreach ($brands as $brand) { | ||
56 | + $params['brands'][] = $brand->brand_id; | ||
109 | } | 57 | } |
110 | - if ($price_interval[1] > 0) { | ||
111 | - $query->andWhere(['<=', ProductVariant::tableName() .'.price', $price_interval[1]]); | ||
112 | - $priceMaxCurr = $price_interval[1]; | 58 | + } |
59 | + | ||
60 | + if ( !empty($filter['options']) ) { | ||
61 | + $params['options'] = $filter['options']; | ||
62 | + /*$optionQuery = TaxOption::find(); | ||
63 | + $optionQuery->select('tax_option_id'); | ||
64 | + $optionQuery->innerJoinWith('group'); | ||
65 | + foreach ($filter['options'] as $option_key => $option_values) { | ||
66 | + $optionQuery->orWhere([ | ||
67 | + 'tax_group_id' => $option_key, | ||
68 | + 'alias' => $filter['options'] | ||
69 | + ]); | ||
113 | } | 70 | } |
71 | + $options = ->where(['in', 'alias', $filter['options']])->all(); | ||
72 | + $params['options'] = []; | ||
73 | + foreach ($options as $option) { | ||
74 | + $params['options'][] = $option->tax_option_id; | ||
75 | + }*/ | ||
114 | } | 76 | } |
115 | 77 | ||
116 | - $groups = []; | ||
117 | - foreach($category->getTaxGroups()->all() as $_group) { | ||
118 | - $groups[$_group->tax_group_id] = $_group; | 78 | + if ( !empty($filter['prices']) ) { |
79 | + $params['prices'] = $filter['prices']; | ||
119 | } | 80 | } |
120 | - foreach ($all_options as $option) { | 81 | + |
82 | + $productModel = new ProductFrontendSearch(); | ||
83 | + $productProvider = $productModel->search($category, $params); | ||
84 | + | ||
85 | + $brandModel = new BrandSearch(); | ||
86 | + $brandProvider = $brandModel->getBrands($category, $params); | ||
87 | + | ||
88 | + $optionsProvider = $productModel->optionsForCategory($category, $params); | ||
89 | + $groups = []; | ||
90 | + foreach ($optionsProvider->models as $option) { | ||
91 | + if (!isset($groups[$option->tax_group_id])) { | ||
92 | + $groups[$option->tax_group_id] = $option->taxGroup; | ||
93 | + $groups[$option->tax_group_id]->_options = []; | ||
94 | + } | ||
121 | $groups[$option->tax_group_id]->_options[] = $option; | 95 | $groups[$option->tax_group_id]->_options[] = $option; |
122 | } | 96 | } |
123 | foreach($groups as $i => $group) { | 97 | foreach($groups as $i => $group) { |
@@ -125,78 +99,29 @@ class CatalogController extends \yii\web\Controller | @@ -125,78 +99,29 @@ class CatalogController extends \yii\web\Controller | ||
125 | unset($groups[$i]); | 99 | unset($groups[$i]); |
126 | } | 100 | } |
127 | 101 | ||
128 | - // Options | ||
129 | - if (($options = \Yii::$app->request->get('option')) != false) { | ||
130 | -// $query->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.product_id='. Product::tableName() .'.product_id'); | ||
131 | -// $query->innerJoin(TaxOption::tableName(), TaxOption::tableName() .'.tax_option_id='. ProductOption::tableName() .'.option_id'); | ||
132 | - foreach($options as $group_alias => $options_alias) { | ||
133 | - if (!is_array($options_alias)) { | ||
134 | - $options_alias = [$options_alias]; | ||
135 | - } | ||
136 | - foreach($options_alias as &$option_alias) { | ||
137 | - $option_alias = "'". $option_alias ."'"; | ||
138 | - } | ||
139 | - /*$group = TaxGroup::find()->where(['like', 'alias', $group_alias])->one(); | ||
140 | - if (!$group) { | ||
141 | - continue; | ||
142 | - }*/ | ||
143 | - } | ||
144 | - $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) .'))'); | ||
145 | - } | ||
146 | - | ||
147 | - if (($_brands = \Yii::$app->request->get('brand')) != false && is_array($_brands) && count($_brands) > 0) { | ||
148 | - $_brands = Brand::find()->where(['in', 'alias', $_brands])->all(); | ||
149 | - $bids = []; | ||
150 | - foreach ($_brands as $brand) { | ||
151 | - $bids[] = $brand->brand_id; | ||
152 | - } | ||
153 | - if (count($bids)) { | ||
154 | - $query->andWhere([Product::tableName() .'.brand_id' => $bids]); | ||
155 | - } | ||
156 | - } | ||
157 | - | ||
158 | - $query->with('variant'); | ||
159 | - $query->with('brand'); | ||
160 | - $query->with('categories'); | ||
161 | - $query->with('image'); | ||
162 | - | ||
163 | - $count = $query->count(); | ||
164 | - $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]); | ||
165 | - $query->offset($pages->offset) | ||
166 | - ->orderBy($sort->orders) | ||
167 | - ->limit($pages->limit); | ||
168 | - | ||
169 | - $products = $query->all(); | 102 | + $priceLimits = $productModel->priceLimits($category, $params); |
170 | 103 | ||
171 | return $this->render( | 104 | return $this->render( |
172 | 'products', | 105 | 'products', |
173 | [ | 106 | [ |
174 | - 'category' => $category, | ||
175 | - 'products' => $products, | ||
176 | - 'all_count' => $all_count, | ||
177 | - 'product_count' => $count, | ||
178 | - 'sort' => $sort, | ||
179 | - 'pages' => $pages, | ||
180 | - 'per_page' => $per_page, | ||
181 | - 'priceMin' => $priceMin, | ||
182 | - 'priceMax' => $priceMax, | ||
183 | - 'priceMinCurr' => $priceMinCurr, | ||
184 | - 'priceMaxCurr' => $priceMaxCurr, | ||
185 | - 'brands' => $brands, | ||
186 | - 'brands_count' => $brands_count, | ||
187 | - 'groups' => $groups, | ||
188 | - 'options' => $options, | 107 | + 'category' => $category, |
108 | + 'brandModel' => $brandModel, | ||
109 | + 'brandProvider' => $brandProvider, | ||
110 | + 'filter' => $filter, | ||
111 | + 'productModel' => $productModel, | ||
112 | + 'productProvider' => $productProvider, | ||
113 | + 'optionsProvider' => $optionsProvider, | ||
114 | + 'groups' => $groups, | ||
115 | + 'priceLimits' => $priceLimits, | ||
189 | ] | 116 | ] |
190 | ); | 117 | ); |
191 | } | 118 | } |
192 | } | 119 | } |
193 | 120 | ||
194 | - public function actionProduct($alias) | 121 | + public function actionProduct() |
195 | { | 122 | { |
196 | - $product = ProductSearch::findByAlias($alias); | ||
197 | - if (empty($product->product_id)) { | ||
198 | - throw new HttpException(404 ,'Page not found'); | ||
199 | - } | 123 | + $product = Yii::$app->request->get('product'); |
124 | + | ||
200 | $groups = []; | 125 | $groups = []; |
201 | foreach($product->category->getTaxGroups()->all() as $_group) { | 126 | foreach($product->category->getTaxGroups()->all() as $_group) { |
202 | $groups[$_group->tax_group_id] = $_group; | 127 | $groups[$_group->tax_group_id] = $_group; |
1 | +<?php | ||
2 | + | ||
3 | +namespace frontend\models; | ||
4 | + | ||
5 | +use common\modules\product\models\Brand; | ||
6 | +use common\modules\product\models\ProductCategory; | ||
7 | +use common\modules\product\models\ProductOption; | ||
8 | +use common\modules\rubrication\models\TaxGroup; | ||
9 | +use common\modules\rubrication\models\TaxOption; | ||
10 | +use Yii; | ||
11 | +use yii\base\Model; | ||
12 | +use yii\data\ActiveDataProvider; | ||
13 | +use yii\db\ActiveQuery; | ||
14 | +use yii\db\ActiveRecord; | ||
15 | +use yii\web\NotFoundHttpException; | ||
16 | +use common\modules\product\models\Product; | ||
17 | +use common\modules\product\models\ProductVariant; | ||
18 | + | ||
19 | +class ProductFrontendSearch extends Product { | ||
20 | + /** | ||
21 | + * @inheritdoc | ||
22 | + */ | ||
23 | + public function rules() | ||
24 | + { | ||
25 | + return [ | ||
26 | + [['price_interval', 'brands'], 'safe'], | ||
27 | + ]; | ||
28 | + } | ||
29 | + | ||
30 | + /** | ||
31 | + * @inheritdoc | ||
32 | + */ | ||
33 | + public function scenarios() | ||
34 | + { | ||
35 | + // bypass scenarios() implementation in the parent class | ||
36 | + return Model::scenarios(); | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * Creates data provider instance with search query applied for frontend | ||
41 | + * | ||
42 | + * @param array $params | ||
43 | + * | ||
44 | + * @return ActiveDataProvider | ||
45 | + */ | ||
46 | + public function search($category, $params) { | ||
47 | + /** @var ActiveQuery $query */ | ||
48 | + $query = $category->getRelations('product_categories'); | ||
49 | + | ||
50 | + $query->joinWith('variant'); | ||
51 | + $query->joinWith('brand'); | ||
52 | + $query->joinWith('categories'); | ||
53 | + $query->joinWith('image'); | ||
54 | + | ||
55 | + $dataProvider = new ActiveDataProvider([ | ||
56 | + 'query' => $query, | ||
57 | + 'pagination' => [ | ||
58 | + 'pageSize' => 24, | ||
59 | + ], | ||
60 | + 'sort' => [ | ||
61 | + 'attributes' => [ | ||
62 | + 'name' => [ | ||
63 | + 'asc' => ['name' => SORT_ASC], | ||
64 | + 'desc' => ['name' => SORT_DESC], | ||
65 | + 'default' => SORT_DESC, | ||
66 | + 'label' => 'имени', | ||
67 | + ], | ||
68 | + 'price' => [ | ||
69 | + 'asc' => [ProductVariant::tableName() .'.price' => SORT_ASC], | ||
70 | + 'desc' => [ProductVariant::tableName() .'.price' => SORT_DESC], | ||
71 | + 'default' => SORT_DESC, | ||
72 | + 'label' => 'цене', | ||
73 | + ], | ||
74 | + ], | ||
75 | + ] | ||
76 | + ]); | ||
77 | + | ||
78 | + if (!$this->validate()) { | ||
79 | + return $dataProvider; | ||
80 | + } | ||
81 | + | ||
82 | + $this->_setParams($query, $params); | ||
83 | + | ||
84 | + return $dataProvider; | ||
85 | + } | ||
86 | + | ||
87 | + public function optionsForCategory($category, $params) { | ||
88 | + $query = TaxOption::find() | ||
89 | + ->select([ | ||
90 | + TaxOption::tableName() .'.*', | ||
91 | + 'COUNT('. ProductOption::tableName() .'.product_id) AS _items_count' | ||
92 | + ]) | ||
93 | + ->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id') | ||
94 | + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id') | ||
95 | + ->innerJoin(TaxGroup::tableName(), TaxGroup::tableName() .'.tax_group_id='. TaxOption::tableName() .'.tax_group_id') | ||
96 | + ->where([ | ||
97 | + TaxGroup::tableName() .'.is_filter' => true, | ||
98 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
99 | + ]) | ||
100 | + ->groupBy(TaxOption::tableName() .'.tax_option_id'); | ||
101 | + | ||
102 | + if (!empty($params['prices'])) { | ||
103 | + if ($params['prices']['min'] > 0 || $params['prices']['max'] > 0) { | ||
104 | + $query->innerJoin(ProductVariant::tableName(), ProductVariant::tableName() .'.product_id='. ProductCategory::tableName() .'.product_id'); | ||
105 | + } | ||
106 | + if ($params['prices']['min'] > 0) { | ||
107 | + $query->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); | ||
108 | + } | ||
109 | + if ($params['prices']['max'] > 0) { | ||
110 | + $query->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); | ||
111 | + } | ||
112 | + } | ||
113 | + if (!empty($params['brands'])) { | ||
114 | + $query->innerJoin(Product::tableName(), Product::tableName() .'.product_id='. ProductCategory::tableName() .'.product_id'); | ||
115 | + $query->andWhere([Product::tableName() .'.brand_id' => $params['brands']]); | ||
116 | + } | ||
117 | + | ||
118 | + $dataProvider = new ActiveDataProvider([ | ||
119 | + 'query' => $query, | ||
120 | + ]); | ||
121 | + | ||
122 | + return $dataProvider; | ||
123 | + } | ||
124 | + | ||
125 | + public function priceLimits($category, $params) { | ||
126 | + /** @var ActiveQuery $query */ | ||
127 | + $query = $category->getRelations('product_categories'); | ||
128 | + $query->joinWith('variant'); | ||
129 | + | ||
130 | + $this->_setParams($query, $params, false); | ||
131 | + | ||
132 | +// $query->select([ | ||
133 | +// 'MIN('. ProductVariant::tableName() .'.price) AS priceMIN', | ||
134 | +// 'MAX('. ProductVariant::tableName() .'.price) AS priceMAX', | ||
135 | +// ]); | ||
136 | + | ||
137 | + return [ | ||
138 | + 'min' => $query->min(ProductVariant::tableName() .'.price'), | ||
139 | + 'max' => $query->max(ProductVariant::tableName() .'.price'), | ||
140 | + ]; | ||
141 | + } | ||
142 | + | ||
143 | + protected function _setParams(&$query, $params, $setPriceLimits = true) { | ||
144 | + if (!empty($params['brands'])) { | ||
145 | + $query->andFilterWhere([Product::tableName() .'.brand_id' => $params['brands']]); | ||
146 | + } | ||
147 | + if (!empty($params['options'])) { | ||
148 | + foreach ($params['options'] as $group => $options) { | ||
149 | + foreach ($options as &$option) { | ||
150 | + $option = "'$option'"; | ||
151 | + } | ||
152 | + $query->andWhere( | ||
153 | + 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 \''. $group .'\' AND tax_option.alias IN (' . implode(',', $options) . '))' | ||
154 | + ); | ||
155 | + } | ||
156 | + } | ||
157 | + if ($setPriceLimits && !empty($params['prices'])) { | ||
158 | + if ($params['prices']['min'] > 0) { | ||
159 | + $query->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); | ||
160 | + } | ||
161 | + if ($params['prices']['max'] > 0) { | ||
162 | + $query->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); | ||
163 | + } | ||
164 | + } | ||
165 | + } | ||
166 | +} | ||
0 | \ No newline at end of file | 167 | \ No newline at end of file |
frontend/views/catalog/categories.php
@@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
4 | 4 | ||
5 | $this->title = $category->name; | 5 | $this->title = $category->name; |
6 | foreach($category->getParents()->all() as $parent) { | 6 | foreach($category->getParents()->all() as $parent) { |
7 | - $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]]; | 7 | + $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'category' => $parent]]; |
8 | } | 8 | } |
9 | $this->params['breadcrumbs'][] = $this->title; | 9 | $this->params['breadcrumbs'][] = $this->title; |
10 | ?> | 10 | ?> |
@@ -31,7 +31,7 @@ $this->params['breadcrumbs'][] = $this->title; | @@ -31,7 +31,7 @@ $this->params['breadcrumbs'][] = $this->title; | ||
31 | <div class="cat_li_sub_ul"> | 31 | <div class="cat_li_sub_ul"> |
32 | <ul> | 32 | <ul> |
33 | <?php foreach($category['children'] as $_category) :?> | 33 | <?php foreach($category['children'] as $_category) :?> |
34 | - <li><a href="<?= \yii\helpers\Url::to(['catalog/category', 'alias' => $_category['item']->alias])?>"><?= $_category['item']->name?><!-- (18)--></a></li> | 34 | + <li><a href="<?= \yii\helpers\Url::to(['catalog/category', 'category' => $_category['item']])?>"><?= $_category['item']->name?><!-- (18)--></a></li> |
35 | <?php endforeach?> | 35 | <?php endforeach?> |
36 | </ul> | 36 | </ul> |
37 | </div> | 37 | </div> |
frontend/views/catalog/product.php
@@ -4,9 +4,9 @@ | @@ -4,9 +4,9 @@ | ||
4 | 4 | ||
5 | $this->title = $product->name; | 5 | $this->title = $product->name; |
6 | foreach($product->category->getParents()->all() as $parent) { | 6 | foreach($product->category->getParents()->all() as $parent) { |
7 | - $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]]; | 7 | + $this->params['breadcrumbs'][] = ['label' => $parent->categoryName->value, 'url' => ['catalog/category', 'category' => $parent]]; |
8 | } | 8 | } |
9 | -$this->params['breadcrumbs'][] = ['label' => $product->category->name, 'url' => ['catalog/category', 'alias' => $product->category->alias]]; | 9 | +$this->params['breadcrumbs'][] = ['label' => $product->category->categoryName->value, 'url' => ['catalog/category', 'category' => $product->category]]; |
10 | $this->params['breadcrumbs'][] = $product->name .' #'. $product->variant->sku; | 10 | $this->params['breadcrumbs'][] = $product->name .' #'. $product->variant->sku; |
11 | ?> | 11 | ?> |
12 | <h1 class="open_card_item_title"><?= $product->name .' '. $product->variant->name?></h1> | 12 | <h1 class="open_card_item_title"><?= $product->name .' '. $product->variant->name?></h1> |
frontend/views/catalog/product_item.php
@@ -5,7 +5,7 @@ | @@ -5,7 +5,7 @@ | ||
5 | <div class="item" data-id="<?= $product->product_id?>"> | 5 | <div class="item" data-id="<?= $product->product_id?>"> |
6 | <!--<div class="new">АКЦИЯ</div> | 6 | <!--<div class="new">АКЦИЯ</div> |
7 | <div class="top">Toп</div>--> | 7 | <div class="top">Toп</div>--> |
8 | - <a href="<?= \yii\helpers\Url::to(['catalog/product', 'alias' => $product->alias])?>" class="item_link"> | 8 | + <a href="<?= \yii\helpers\Url::to(['catalog/product', 'product' => $product])?>" class="item_link"> |
9 | <div class="pic"> | 9 | <div class="pic"> |
10 | <?php if (empty($product->image)) :?> | 10 | <?php if (empty($product->image)) :?> |
11 | <img src="/images/no_photo.png"> | 11 | <img src="/images/no_photo.png"> |
1 | +<?php | ||
2 | +/** @var $this \yii\web\View */ | ||
3 | +/** @var $dataProvider \yii\data\ActiveDataProvider */ | ||
4 | + | ||
5 | +$this->title = $category->categoryName->value; | ||
6 | +foreach($category->getParents()->all() as $parent) { | ||
7 | + $this->params['breadcrumbs'][] = ['label' => $parent->categoryName->value, 'url' => ['catalog/category', 'alias' => $parent->alias]]; | ||
8 | +} | ||
9 | +$this->params['breadcrumbs'][] = $category->categoryName->value; | ||
10 | +?> | ||
11 | +<script type="text/javascript"> | ||
12 | + $(document).ready(function() { | ||
13 | + // price rangeslider (filter price slider) | ||
14 | + $("#price_interval").ionRangeSlider({ | ||
15 | + type: "double", | ||
16 | + min: <?= $priceMin?>, | ||
17 | + max: <?= $priceMax?>, | ||
18 | + from: <?= $priceMinCurr?>, | ||
19 | + to: <?= $priceMaxCurr?>, | ||
20 | + grid: false | ||
21 | + }); | ||
22 | + }); | ||
23 | +</script> | ||
24 | +<div class="w_960"> | ||
25 | + <!-- side bar with all filters --> | ||
26 | + <div class="cat_p_filter_bar"> | ||
27 | + <div class="title">ФИЛЬТРЫ</div> | ||
28 | + <div class="filter_list"> | ||
29 | + <form action="#" name="filter_catalog_page_form"> | ||
30 | + <ul> | ||
31 | + <li>Цена: | ||
32 | + <div class="arrow"><img src="/images/head_up.png" alt=""></i></div> | ||
33 | + <div class="price_filter first_price_li"> | ||
34 | + <div class="price_slider"> | ||
35 | + <input type="text" id="price_interval" name="price_interval" value="" /> | ||
36 | + </div> | ||
37 | + <!--<div class="checkbox"> | ||
38 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
39 | + <a href="#">Акции</a> | ||
40 | + </div> | ||
41 | + <div class="checkbox"> | ||
42 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
43 | + <a href="#">Товар в наличии</a> | ||
44 | + </div> | ||
45 | + <div class="checkbox"> | ||
46 | + <label><input type="checkbox" name="venecia" value="0" /></label> | ||
47 | + <a href="#">Хит продаж</a> | ||
48 | + </div>--> | ||
49 | + </div> | ||
50 | + </li> | ||
51 | + | ||
52 | + <?php if ($brands_count) :?> | ||
53 | + <li>Бренд | ||
54 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
55 | + <div class="price_filter<?= !empty($_brands)?' active-field':''?>"> | ||
56 | + <?php foreach($brands as $brand) :?> | ||
57 | + <div class="checkbox"> | ||
58 | + <label><input type="checkbox" name="brand[]" value="<?= $brand->alias?>"<?= isset($_GET['brand']) && in_array($brand->alias, $_GET['brand']) ? ' checked' : ''?> /></label> | ||
59 | + <a href="#<?php /*= \yii\helpers\Url::to(['brand', 'alias' => $brand->alias])*/?>"><?= $brand->name?><!-- (<?php /*= $brand->getProducts()->count()*/?>)--></a> | ||
60 | + </div> | ||
61 | + <?php endforeach?> | ||
62 | + <!--<div class="checkbox see_all"> | ||
63 | + <i class="fa fa-plus-circle"></i> | ||
64 | + <a href="#">посмотреть все</a> | ||
65 | + </div>--> | ||
66 | + </div> | ||
67 | + </li> | ||
68 | + <?php endif?> | ||
69 | + | ||
70 | + <?php if (!empty($groups)) :?> | ||
71 | + <div class="title_2">ПОДБОР ПО ПАРАМЕТРАМ</div> | ||
72 | + | ||
73 | + <?php foreach($groups as $group) :?> | ||
74 | + <li><?= $group->name?> | ||
75 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
76 | + <div class="price_filter<?= isset($options[$group->alias])?' active-field':''?>"> | ||
77 | + <?php foreach($group->_options as $option) :?> | ||
78 | + <div class="checkbox"> | ||
79 | + <label><input type="checkbox" name="option[<?= $group->alias?>][]" value="<?= $option->alias?>"<?= (isset($options[$group->alias]) && in_array($option->alias, $options[$group->alias])) ? ' checked' : ''?> /></label> | ||
80 | + <a href="#"><?= $option->ValueRenderHTML?> (<?= $option->_items_count?>)</a> | ||
81 | + </div> | ||
82 | + <?php endforeach?> | ||
83 | + </div> | ||
84 | + </li> | ||
85 | + <?php endforeach?> | ||
86 | + <?php endif?> | ||
87 | + | ||
88 | + </ul> | ||
89 | + | ||
90 | + <div class="filter_accept_bloc"> | ||
91 | + <button type="submit" class="filter_accept_btn">применить</button> | ||
92 | + <a href="#" class="form_checkbox_reset">сбросить фильтры</a> | ||
93 | + </div> | ||
94 | + </form> | ||
95 | + <!--<div class="product_list"> | ||
96 | + <h2 class="title">КАТАЛОГ ТОВАРОВ</h2> | ||
97 | + <ul> | ||
98 | + <li>Битумная черепица | ||
99 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
100 | + <div class="price_filter"> | ||
101 | + <a href="#">RUUKI</a> | ||
102 | + <a href="#">Venecia</a> | ||
103 | + </div> | ||
104 | + </li> | ||
105 | + | ||
106 | + <li>Комплектация кровли | ||
107 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
108 | + <div class="price_filter"> | ||
109 | + <a href="#">RUUKI</a> | ||
110 | + <a href="#">Venecia</a> | ||
111 | + </div> | ||
112 | + </li> | ||
113 | + | ||
114 | + <li>Водосточные системы | ||
115 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
116 | + <div class="price_filter"> | ||
117 | + <a href="#">RUUKI</a> | ||
118 | + <a href="#">Venecia</a> | ||
119 | + </div> | ||
120 | + </li> | ||
121 | + | ||
122 | + <li>Чердачные лестницы | ||
123 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
124 | + <div class="price_filter"> | ||
125 | + <a href="#">RUUKI</a> | ||
126 | + <a href="#">Venecia</a> | ||
127 | + </div> | ||
128 | + </li> | ||
129 | + | ||
130 | + <li>Мансардные окна | ||
131 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
132 | + <div class="price_filter"> | ||
133 | + <a href="#">RUUKI</a> | ||
134 | + <a href="#">Venecia</a> | ||
135 | + </div> | ||
136 | + </li> | ||
137 | + | ||
138 | + <li>Металлочерепица | ||
139 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
140 | + <div class="price_filter"> | ||
141 | + <a href="#">RUUKI</a> | ||
142 | + <a href="#">Venecia</a> | ||
143 | + </div> | ||
144 | + </li> | ||
145 | + | ||
146 | + <li>Плоская кровля | ||
147 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
148 | + <div class="price_filter"> | ||
149 | + <a href="#">RUUKI</a> | ||
150 | + <a href="#">Venecia</a> | ||
151 | + </div> | ||
152 | + </li> | ||
153 | + | ||
154 | + <li>Профнастил | ||
155 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
156 | + <div class="price_filter"> | ||
157 | + <a href="#">RUUKI</a> | ||
158 | + <a href="#">Venecia</a> | ||
159 | + </div> | ||
160 | + </li> | ||
161 | + | ||
162 | + <li>Ондулин | ||
163 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
164 | + <div class="price_filter"> | ||
165 | + <a href="#">RUUKI</a> | ||
166 | + <a href="#">Venecia</a> | ||
167 | + </div> | ||
168 | + </li> | ||
169 | + | ||
170 | + <li>OSB плиты | ||
171 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
172 | + <div class="price_filter"> | ||
173 | + <a href="#">RUUKI</a> | ||
174 | + <a href="#">Venecia</a> | ||
175 | + </div> | ||
176 | + </li> | ||
177 | + | ||
178 | + </ul> | ||
179 | + </div>--> | ||
180 | + </div> | ||
181 | + | ||
182 | + | ||
183 | + </div> | ||
184 | + | ||
185 | + <!-- catalog list with all item cards --> | ||
186 | + <div class="cat_p_catalog_list"> | ||
187 | + <div class="title"><?= $category->categoryName->value?> <span>(<?= $all_count?>)</span></div> | ||
188 | + | ||
189 | + <?php if (empty($products)) :?> | ||
190 | + <h2>По данному запросу товары не найдены.</h2><br> | ||
191 | + <p>Показать <a href="<?= \yii\helpers\Url::to(['catalog/category', 'alias' => $category->alias])?>">все товары из категории "<?= $category->categoryName->value?>"</a></p> | ||
192 | + <?php else :?> | ||
193 | + <!-- sort menu --> | ||
194 | + <div class="sort_menu"> | ||
195 | + | ||
196 | + <div class="sort_price"> | ||
197 | + <span>Сортировка:</span> | ||
198 | + <?= \yii\widgets\LinkSorter::widget([ | ||
199 | + 'sort' => $sort, | ||
200 | + 'attributes' => [ | ||
201 | + 'name', | ||
202 | + 'price', | ||
203 | + ] | ||
204 | + ]); | ||
205 | + ?> | ||
206 | + <!-- | ||
207 | + <select name="sort_price" id="" class="sort_price_select"> | ||
208 | + <option value="price">по цене</option> | ||
209 | + <option value="popular">новые</option> | ||
210 | + <option value="sale">по акции</option> | ||
211 | + </select> | ||
212 | + <i class="fa fa-angle-down"></i>--> | ||
213 | + </div> | ||
214 | + | ||
215 | + <div class="show"> | ||
216 | + <!--<span>Показывать по:</span> | ||
217 | + <ul> | ||
218 | + <li><a class="active" href="#">24</a></li> | ||
219 | + <li><a href="#">48</a></li> | ||
220 | + <li><a href="#">96</a></li> | ||
221 | + </ul>--> | ||
222 | + </div> | ||
223 | + | ||
224 | + <div class="show_pages"> | ||
225 | + <?php if ($pages->totalCount > $pages->pageSize) :?> | ||
226 | + <span>Страница:</span> | ||
227 | + <?= \yii\widgets\LinkPager::widget([ | ||
228 | + 'pagination' => $pages, | ||
229 | + 'options' => ['class' => 'pagination pull-right'], | ||
230 | + ]); | ||
231 | + ?> | ||
232 | + <!--<i class="fa fa-caret-right"></i>--> | ||
233 | + <?php endif?> | ||
234 | + </div> | ||
235 | + | ||
236 | + </div> | ||
237 | + | ||
238 | + | ||
239 | + <div class="cat_p_item_card_list"> | ||
240 | + <div class="novelty"> | ||
241 | + <div class="content"> | ||
242 | + <div class="novelty_cont"> | ||
243 | + <?php foreach($products as $product) :?> | ||
244 | + <?php require(__DIR__ .'/product_item.php')?> | ||
245 | + <?php endforeach?> | ||
246 | + </div> | ||
247 | + | ||
248 | + <?php if ($pages->totalCount > $pages->pageSize) :?> | ||
249 | + <!-- LOAD MORE BUTTON --> | ||
250 | + <!--button class="load_more_btn">Загрузить еще <?= $per_page?> товара</button--> | ||
251 | + | ||
252 | + <div class="show_pages"> | ||
253 | + Страница: | ||
254 | + <?= \yii\widgets\LinkPager::widget([ | ||
255 | + 'pagination' => $pages, | ||
256 | + 'options' => ['class' => 'pagination pull-right'], | ||
257 | + ]); | ||
258 | + ?> | ||
259 | + <!--<i class="fa fa-caret-right"></i>--> | ||
260 | + </div> | ||
261 | + <?php endif?> | ||
262 | + <hr> | ||
263 | + | ||
264 | + <?php if(!empty($category->description)) :?> | ||
265 | + <div class="description"> | ||
266 | + <?= $category->description?> | ||
267 | + | ||
268 | + <div class="empty_padding_400"></div> | ||
269 | + </div> | ||
270 | + <?php endif?> | ||
271 | + </div> | ||
272 | + </div> | ||
273 | + </div> | ||
274 | + | ||
275 | + <?php endif?> | ||
276 | + </div> | ||
277 | +</div> | ||
278 | + |
frontend/views/catalog/products.php
1 | <?php | 1 | <?php |
2 | /** @var $this \yii\web\View */ | 2 | /** @var $this \yii\web\View */ |
3 | -/** @var $dataProvider \yii\data\ActiveDataProvider */ | 3 | +/** @var $productProvider \yii\data\ActiveDataProvider */ |
4 | +/** @var $brandProvider \yii\data\ActiveDataProvider */ | ||
5 | + | ||
6 | +use yii\helpers\Url; | ||
7 | +use common\modules\product\helpers\ProductHelper; | ||
4 | 8 | ||
5 | $this->title = $category->categoryName->value; | 9 | $this->title = $category->categoryName->value; |
6 | foreach($category->getParents()->all() as $parent) { | 10 | foreach($category->getParents()->all() as $parent) { |
7 | - $this->params['breadcrumbs'][] = ['label' => $parent->categoryName->value, 'url' => ['catalog/category', 'alias' => $parent->alias]]; | 11 | + $this->params['breadcrumbs'][] = ['label' => $parent->categoryName->value, 'url' => ['catalog/category', 'category' => $parent]]; |
8 | } | 12 | } |
9 | $this->params['breadcrumbs'][] = $category->categoryName->value; | 13 | $this->params['breadcrumbs'][] = $category->categoryName->value; |
10 | ?> | 14 | ?> |
11 | <script type="text/javascript"> | 15 | <script type="text/javascript"> |
16 | +<?php if ($priceLimits['min'] < $priceLimits['max']) :?> | ||
12 | $(document).ready(function() { | 17 | $(document).ready(function() { |
13 | // price rangeslider (filter price slider) | 18 | // price rangeslider (filter price slider) |
14 | $("#price_interval").ionRangeSlider({ | 19 | $("#price_interval").ionRangeSlider({ |
15 | type: "double", | 20 | type: "double", |
16 | - min: <?= $priceMin?>, | ||
17 | - max: <?= $priceMax?>, | ||
18 | - from: <?= $priceMinCurr?>, | ||
19 | - to: <?= $priceMaxCurr?>, | ||
20 | - grid: false | 21 | + min: <?= $priceLimits['min']?>, |
22 | + max: <?= $priceLimits['max']?>, | ||
23 | + from: <?= empty($filter['prices']['min']) ? $priceLimits['min'] : $filter['prices']['min']?>, | ||
24 | + to: <?= empty($filter['prices']['max']) ? $priceLimits['max'] : $filter['prices']['max']?>, | ||
25 | + grid: false, | ||
26 | + onFinish: function(e) { | ||
27 | +<?php | ||
28 | +$filterWhitoutPrice = $filter; | ||
29 | +$filterWhitoutPrice['prices'] = [ | ||
30 | + 'min' => '{from}', | ||
31 | + 'max' => '{to}', | ||
32 | +]; | ||
33 | +?> | ||
34 | + var url = "<?= Url::to(['catalog/category', 'category' => $category, 'filter' => $filterWhitoutPrice])?>"; | ||
35 | + var from = e.from; | ||
36 | + var to = e.to; | ||
37 | + document.location = url.replace('{from}', from).replace('{to}', to); | ||
38 | + } | ||
39 | + }); | ||
40 | + }); | ||
41 | +<?php endif?> | ||
42 | +<?php /* | ||
43 | + $(document).ready(function() { | ||
44 | + $('form.filter-catalog-form').each(function() { | ||
45 | + var form = $(this); | ||
46 | + form.submit(function(e) { | ||
47 | + e.preventDefault(); | ||
48 | + var brands = ''; | ||
49 | + // Get brands values | ||
50 | + $('input[type=checkbox].brands-option:checked', form).each(function() { | ||
51 | + var filter_value = $(this).val().replace(',', '~').replace('/', '&s;'); | ||
52 | + if (brands) { | ||
53 | + brands += ','+ filter_value; | ||
54 | + } else { | ||
55 | + brands = filter_value; | ||
56 | + } | ||
57 | + }); | ||
58 | + // Formate query and redirect | ||
59 | + var filter = ''; | ||
60 | + if (brands) { | ||
61 | + filter += 'brands='+ brands; | ||
62 | + } | ||
63 | + filter += ';'; | ||
64 | + | ||
65 | + if (filter) { | ||
66 | + var request = '<?= Url::toRoute(['catalog/category/filter', 'alias' => $category->alias, 'filter' => '+ filter .'])?>'; | ||
67 | + window.location.href = request; | ||
68 | + } | ||
69 | + }); | ||
21 | }); | 70 | }); |
22 | }); | 71 | }); |
72 | +*/?> | ||
23 | </script> | 73 | </script> |
24 | <div class="w_960"> | 74 | <div class="w_960"> |
25 | <!-- side bar with all filters --> | 75 | <!-- side bar with all filters --> |
26 | <div class="cat_p_filter_bar"> | 76 | <div class="cat_p_filter_bar"> |
27 | <div class="title">ФИЛЬТРЫ</div> | 77 | <div class="title">ФИЛЬТРЫ</div> |
28 | <div class="filter_list"> | 78 | <div class="filter_list"> |
29 | - <form action="#" name="filter_catalog_page_form"> | 79 | + <form action="#" name="filter_catalog_page_form" class="filter-catalog-form"> |
80 | + <?php if (!empty($filter)) :?> | ||
81 | + <div class="filter_accept_bloc"> | ||
82 | + <!-- <button type="submit" class="filter_accept_btn">применить</button>--> | ||
83 | + <a href="<?= Url::to(['catalog/category', 'category' => $category])?>" class="_form_checkbox_reset">сбросить фильтры</a> | ||
84 | + </div> | ||
85 | + <?php endif?> | ||
30 | <ul> | 86 | <ul> |
87 | + <?php if ($priceLimits['min'] < $priceLimits['max']) :?> | ||
31 | <li>Цена: | 88 | <li>Цена: |
32 | <div class="arrow"><img src="/images/head_up.png" alt=""></i></div> | 89 | <div class="arrow"><img src="/images/head_up.png" alt=""></i></div> |
33 | <div class="price_filter first_price_li"> | 90 | <div class="price_filter first_price_li"> |
34 | <div class="price_slider"> | 91 | <div class="price_slider"> |
35 | <input type="text" id="price_interval" name="price_interval" value="" /> | 92 | <input type="text" id="price_interval" name="price_interval" value="" /> |
36 | </div> | 93 | </div> |
37 | - <!--<div class="checkbox"> | ||
38 | - <label><input type="checkbox" name="venecia" value="0" /></label> | ||
39 | - <a href="#">Акции</a> | ||
40 | - </div> | ||
41 | - <div class="checkbox"> | ||
42 | - <label><input type="checkbox" name="venecia" value="0" /></label> | ||
43 | - <a href="#">Товар в наличии</a> | ||
44 | - </div> | ||
45 | - <div class="checkbox"> | ||
46 | - <label><input type="checkbox" name="venecia" value="0" /></label> | ||
47 | - <a href="#">Хит продаж</a> | ||
48 | - </div>--> | ||
49 | </div> | 94 | </div> |
50 | </li> | 95 | </li> |
96 | + <?php endif?> | ||
51 | 97 | ||
52 | - <?php if ($brands_count) :?> | ||
53 | - <li>Бренд | ||
54 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
55 | - <div class="price_filter"> | ||
56 | - <?php foreach($brands as $brand) :?> | ||
57 | - <div class="checkbox"> | ||
58 | - <label><input type="checkbox" name="brand[]" value="<?= $brand->alias?>"<?= isset($_GET['brand']) && in_array($brand->alias, $_GET['brand']) ? ' checked' : ''?> /></label> | ||
59 | - <a href="#<?php /*= \yii\helpers\Url::to(['brand', 'alias' => $brand->alias])*/?>"><?= $brand->name?><!-- (<?php /*= $brand->getProducts()->count()*/?>)--></a> | 98 | + <?php if ($brandProvider->totalCount > 0) :?> |
99 | + <li>Бренд | ||
100 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
101 | + <div class="price_filter<?= !empty($filter['brands'])?' active-field':''?>"> | ||
102 | + <?php foreach($brandProvider->models as $brand) : | ||
103 | + $checked = !empty($filter['brands']) && in_array($brand->alias, $filter['brands']); | ||
104 | + $option_url = Url::to(['catalog/category', 'category' => $category, 'filter' => ProductHelper::getFilterForOption($filter, 'brands', $brand->alias, $checked)]); | ||
105 | + ?> | ||
106 | + <div class="checkbox"> | ||
107 | + <label><input type="checkbox" class="brands-option" <?php /*name="brands[]" value="<?= $brand->alias?>"*/?><?= $checked ? ' checked' : ''?> onchange="document.location='<?= $option_url?>'" /></label> | ||
108 | + <a href="<?= $option_url?>"><?= $brand->name?> (<?= $brand->getProducts()->count()?>)</a> | ||
109 | + </div> | ||
110 | + <?php endforeach?> | ||
60 | </div> | 111 | </div> |
61 | - <?php endforeach?> | ||
62 | - <!--<div class="checkbox see_all"> | ||
63 | - <i class="fa fa-plus-circle"></i> | ||
64 | - <a href="#">посмотреть все</a> | ||
65 | - </div>--> | ||
66 | - </div> | ||
67 | - </li> | 112 | + </li> |
68 | <?php endif?> | 113 | <?php endif?> |
69 | 114 | ||
70 | <?php if (!empty($groups)) :?> | 115 | <?php if (!empty($groups)) :?> |
71 | - <div class="title_2">ПОДБОР ПО ПАРАМЕТРАМ</div> | 116 | + <div class="title_2">ПОДБОР ПО ПАРАМЕТРАМ</div> |
72 | 117 | ||
73 | <?php foreach($groups as $group) :?> | 118 | <?php foreach($groups as $group) :?> |
74 | - <li><?= $group->name?> | ||
75 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
76 | - <div class="price_filter"> | ||
77 | - <?php foreach($group->_options as $option) :?> | ||
78 | - <div class="checkbox"> | ||
79 | - <label><input type="checkbox" name="option[<?= $group->alias?>][]" value="<?= $option->alias?>"<?= (isset($options[$group->alias]) && in_array($option->alias, $options[$group->alias])) ? ' checked' : ''?> /></label> | ||
80 | - <a href="#"><?= $option->ValueRenderHTML?> (<?= $option->_items_count?>)</a> | 119 | + <li><?= $group->name?> |
120 | + <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
121 | + <div class="price_filter<?= isset($filter['options'][$group->alias])?' active-field':''?>"> | ||
122 | + <?php foreach($group->_options as $option) : | ||
123 | + $checked = (isset($filter['options'][$group->alias]) && in_array($option->alias, $filter['options'][$group->alias])); | ||
124 | + $option_url = Url::to(['catalog/category', 'category' => $category, 'filter' => ProductHelper::getFilterForOption($filter, 'options', [$option->group->alias => [$option->alias]], $checked)]); | ||
125 | + ?> | ||
126 | + <div class="checkbox"> | ||
127 | + <label><input type="checkbox" class="features-option" onchange="document.location='<?= $option_url?>'" <?php /* name="option[<?= $group->alias?>][]"value="<?= $option->alias?>"*/?><?= $checked ? ' checked' : ''?> /></label> | ||
128 | + <a href="<?= $option_url?>"><?= $option->ValueRenderHTML?> (<?= $option->_items_count?>)</a> | ||
129 | + </div> | ||
130 | + <?php endforeach?> | ||
81 | </div> | 131 | </div> |
82 | - <?php endforeach?> | ||
83 | - </div> | ||
84 | - </li> | 132 | + </li> |
85 | <?php endforeach?> | 133 | <?php endforeach?> |
86 | <?php endif?> | 134 | <?php endif?> |
87 | - | ||
88 | </ul> | 135 | </ul> |
89 | - | ||
90 | - <div class="filter_accept_bloc"> | ||
91 | - <button type="submit" class="filter_accept_btn">применить</button> | ||
92 | - <a href="#" class="form_checkbox_reset">сбросить фильтры</a> | ||
93 | - </div> | ||
94 | </form> | 136 | </form> |
95 | - <!--<div class="product_list"> | ||
96 | - <h2 class="title">КАТАЛОГ ТОВАРОВ</h2> | ||
97 | - <ul> | ||
98 | - <li>Битумная черепица | ||
99 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
100 | - <div class="price_filter"> | ||
101 | - <a href="#">RUUKI</a> | ||
102 | - <a href="#">Venecia</a> | ||
103 | - </div> | ||
104 | - </li> | ||
105 | - | ||
106 | - <li>Комплектация кровли | ||
107 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
108 | - <div class="price_filter"> | ||
109 | - <a href="#">RUUKI</a> | ||
110 | - <a href="#">Venecia</a> | ||
111 | - </div> | ||
112 | - </li> | ||
113 | - | ||
114 | - <li>Водосточные системы | ||
115 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
116 | - <div class="price_filter"> | ||
117 | - <a href="#">RUUKI</a> | ||
118 | - <a href="#">Venecia</a> | ||
119 | - </div> | ||
120 | - </li> | ||
121 | - | ||
122 | - <li>Чердачные лестницы | ||
123 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
124 | - <div class="price_filter"> | ||
125 | - <a href="#">RUUKI</a> | ||
126 | - <a href="#">Venecia</a> | ||
127 | - </div> | ||
128 | - </li> | ||
129 | - | ||
130 | - <li>Мансардные окна | ||
131 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
132 | - <div class="price_filter"> | ||
133 | - <a href="#">RUUKI</a> | ||
134 | - <a href="#">Venecia</a> | ||
135 | - </div> | ||
136 | - </li> | ||
137 | - | ||
138 | - <li>Металлочерепица | ||
139 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
140 | - <div class="price_filter"> | ||
141 | - <a href="#">RUUKI</a> | ||
142 | - <a href="#">Venecia</a> | ||
143 | - </div> | ||
144 | - </li> | ||
145 | - | ||
146 | - <li>Плоская кровля | ||
147 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
148 | - <div class="price_filter"> | ||
149 | - <a href="#">RUUKI</a> | ||
150 | - <a href="#">Venecia</a> | ||
151 | - </div> | ||
152 | - </li> | ||
153 | - | ||
154 | - <li>Профнастил | ||
155 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
156 | - <div class="price_filter"> | ||
157 | - <a href="#">RUUKI</a> | ||
158 | - <a href="#">Venecia</a> | ||
159 | - </div> | ||
160 | - </li> | ||
161 | - | ||
162 | - <li>Ондулин | ||
163 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
164 | - <div class="price_filter"> | ||
165 | - <a href="#">RUUKI</a> | ||
166 | - <a href="#">Venecia</a> | ||
167 | - </div> | ||
168 | - </li> | ||
169 | - | ||
170 | - <li>OSB плиты | ||
171 | - <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | ||
172 | - <div class="price_filter"> | ||
173 | - <a href="#">RUUKI</a> | ||
174 | - <a href="#">Venecia</a> | ||
175 | - </div> | ||
176 | - </li> | ||
177 | - | ||
178 | - </ul> | ||
179 | - </div>--> | ||
180 | </div> | 137 | </div> |
181 | - | ||
182 | - | ||
183 | </div> | 138 | </div> |
184 | 139 | ||
185 | <!-- catalog list with all item cards --> | 140 | <!-- catalog list with all item cards --> |
186 | <div class="cat_p_catalog_list"> | 141 | <div class="cat_p_catalog_list"> |
187 | - <div class="title"><?= $category->categoryName->value?> <span>(<?= $all_count?>)</span></div> | 142 | + <div class="title"><?= $category->categoryName->value?> <span>(<?= $productProvider->totalCount?>)</span></div> |
188 | 143 | ||
189 | - <?php if (empty($products)) :?> | 144 | + <?php if (!$productProvider->count) :?> |
190 | <h2>По данному запросу товары не найдены.</h2><br> | 145 | <h2>По данному запросу товары не найдены.</h2><br> |
191 | - <p>Показать <a href="<?= \yii\helpers\Url::to(['catalog/category', 'alias' => $category->alias])?>">все товары из категории "<?= $category->categoryName->value?>"</a></p> | 146 | + <p>Показать <a href="<?= Url::to(['catalog/category', 'category' => $category])?>">все товары из категории "<?= $category->categoryName->value?>"</a></p> |
192 | <?php else :?> | 147 | <?php else :?> |
193 | - <!-- sort menu --> | ||
194 | - <div class="sort_menu"> | ||
195 | - | ||
196 | - <div class="sort_price"> | ||
197 | - <span>Сортировка:</span> | ||
198 | - <?= \yii\widgets\LinkSorter::widget([ | ||
199 | - 'sort' => $sort, | ||
200 | - 'attributes' => [ | ||
201 | - 'name', | ||
202 | - 'price', | ||
203 | - ] | ||
204 | - ]); | ||
205 | - ?> | ||
206 | - <!-- | ||
207 | - <select name="sort_price" id="" class="sort_price_select"> | ||
208 | - <option value="price">по цене</option> | ||
209 | - <option value="popular">новые</option> | ||
210 | - <option value="sale">по акции</option> | ||
211 | - </select> | ||
212 | - <i class="fa fa-angle-down"></i>--> | ||
213 | - </div> | 148 | + <!-- sort menu --> |
149 | + <div class="sort_menu"> | ||
150 | + | ||
151 | + <div class="sort_price"> | ||
152 | + <span>Сортировка:</span> | ||
153 | + <?= \yii\widgets\LinkSorter::widget([ | ||
154 | + 'sort' => $productProvider->sort, | ||
155 | + 'attributes' => [ | ||
156 | + 'name', | ||
157 | + 'price', | ||
158 | + ] | ||
159 | + ]); | ||
160 | + ?> | ||
161 | + <!-- | ||
162 | + <select name="sort_price" id="" class="sort_price_select"> | ||
163 | + <option value="price">по цене</option> | ||
164 | + <option value="popular">новые</option> | ||
165 | + <option value="sale">по акции</option> | ||
166 | + </select> | ||
167 | + <i class="fa fa-angle-down"></i>--> | ||
168 | + </div> | ||
214 | 169 | ||
215 | - <div class="show"> | ||
216 | - <!--<span>Показывать по:</span> | ||
217 | - <ul> | ||
218 | - <li><a class="active" href="#">24</a></li> | ||
219 | - <li><a href="#">48</a></li> | ||
220 | - <li><a href="#">96</a></li> | ||
221 | - </ul>--> | ||
222 | - </div> | 170 | + <div class="show"> |
171 | + <!--<span>Показывать по:</span> | ||
172 | + <ul> | ||
173 | + <li><a class="active" href="#">24</a></li> | ||
174 | + <li><a href="#">48</a></li> | ||
175 | + <li><a href="#">96</a></li> | ||
176 | + </ul>--> | ||
177 | + </div> | ||
223 | 178 | ||
224 | - <div class="show_pages"> | ||
225 | - <?php if ($pages->totalCount > $pages->pageSize) :?> | ||
226 | - <span>Страница:</span> | ||
227 | - <?= \yii\widgets\LinkPager::widget([ | ||
228 | - 'pagination' => $pages, | ||
229 | - 'options' => ['class' => 'pagination pull-right'], | ||
230 | - ]); | ||
231 | - ?> | ||
232 | - <!--<i class="fa fa-caret-right"></i>--> | 179 | + <?php if ($productProvider->totalCount > $productProvider->pagination->pageSize) :?> |
180 | + <div class="show_pages"> | ||
181 | + Страница: | ||
182 | + <?= \yii\widgets\LinkPager::widget([ | ||
183 | + 'pagination' => $productProvider->pagination, | ||
184 | + 'options' => ['class' => 'pagination pull-right'], | ||
185 | + ]); | ||
186 | + ?> | ||
187 | + <!--<i class="fa fa-caret-right"></i>--> | ||
188 | + </div> | ||
233 | <?php endif?> | 189 | <?php endif?> |
234 | - </div> | ||
235 | - | ||
236 | - </div> | ||
237 | - | ||
238 | 190 | ||
239 | - <div class="cat_p_item_card_list"> | ||
240 | - <div class="novelty"> | ||
241 | - <div class="content"> | ||
242 | - <div class="novelty_cont"> | ||
243 | - <?php foreach($products as $product) :?> | ||
244 | - <?php require(__DIR__ .'/product_item.php')?> | ||
245 | - <?php endforeach?> | ||
246 | - </div> | 191 | + </div> |
247 | 192 | ||
248 | - <?php if ($pages->totalCount > $pages->pageSize) :?> | ||
249 | - <!-- LOAD MORE BUTTON --> | ||
250 | - <!--button class="load_more_btn">Загрузить еще <?= $per_page?> товара</button--> | 193 | + <div class="cat_p_item_card_list"> |
194 | + <div class="novelty"> | ||
195 | + <div class="content"> | ||
196 | + <div class="novelty_cont"> | ||
197 | + <?php foreach($productProvider->models as $product) :?> | ||
198 | + <?php require(__DIR__ .'/product_item.php')?> | ||
199 | + <?php endforeach?> | ||
200 | + </div> | ||
251 | 201 | ||
252 | - <div class="show_pages"> | ||
253 | - Страница: | ||
254 | - <?= \yii\widgets\LinkPager::widget([ | ||
255 | - 'pagination' => $pages, | ||
256 | - 'options' => ['class' => 'pagination pull-right'], | ||
257 | - ]); | ||
258 | - ?> | ||
259 | - <!--<i class="fa fa-caret-right"></i>--> | ||
260 | - </div> | ||
261 | - <?php endif?> | ||
262 | - <hr> | 202 | + <?php if ($productProvider->totalCount > $productProvider->pagination->pageSize) :?> |
203 | + <!-- LOAD MORE BUTTON --> | ||
204 | + <!--button class="load_more_btn">Загрузить еще <?= $productProvider->pagination->pageSize?> товара</button--> | ||
205 | + | ||
206 | + <div class="show_pages"> | ||
207 | + Страница: | ||
208 | + <?= \yii\widgets\LinkPager::widget([ | ||
209 | + 'pagination' => $productProvider->pagination, | ||
210 | + 'options' => ['class' => 'pagination pull-right'], | ||
211 | + ]); | ||
212 | + ?> | ||
213 | + <!--<i class="fa fa-caret-right"></i>--> | ||
214 | + </div> | ||
215 | + <?php endif ?> | ||
216 | + <hr> | ||
263 | 217 | ||
264 | - <?php if(!empty($category->description)) :?> | ||
265 | - <div class="description"> | ||
266 | - <?= $category->description?> | 218 | + <?php if(!empty($category->description)) :?> |
219 | + <div class="description"> | ||
220 | + <?= $category->description?> | ||
267 | 221 | ||
268 | - <div class="empty_padding_400"></div> | 222 | + <div class="empty_padding_400"></div> |
223 | + </div> | ||
224 | + <?php endif?> | ||
269 | </div> | 225 | </div> |
270 | - <?php endif?> | ||
271 | </div> | 226 | </div> |
272 | </div> | 227 | </div> |
273 | - </div> | ||
274 | 228 | ||
275 | <?php endif?> | 229 | <?php endif?> |
276 | </div> | 230 | </div> |
277 | -</div> | ||
278 | - | 231 | +</div> |
279 | \ No newline at end of file | 232 | \ No newline at end of file |
frontend/web/css/concat_all.css
@@ -104,6 +104,9 @@ | @@ -104,6 +104,9 @@ | ||
104 | .cat_p_filter_bar .filter_list .price_filter a { | 104 | .cat_p_filter_bar .filter_list .price_filter a { |
105 | color: #6aa033; | 105 | color: #6aa033; |
106 | } | 106 | } |
107 | +.cat_p_filter_bar .filter_list .price_filter.active-field { | ||
108 | + display: block; | ||
109 | +} | ||
107 | 110 | ||
108 | .cat_p_filter_bar .filter_list .first_price_li { | 111 | .cat_p_filter_bar .filter_list .first_price_li { |
109 | padding-top: 30px; | 112 | padding-top: 30px; |
frontend/web/js/my_scripts.js
@@ -2,16 +2,6 @@ $(document).ready(function(){ | @@ -2,16 +2,6 @@ $(document).ready(function(){ | ||
2 | // ion tabs | 2 | // ion tabs |
3 | $.ionTabs("#tabs_1"); | 3 | $.ionTabs("#tabs_1"); |
4 | 4 | ||
5 | - // price rangeslider (filter price slider) | ||
6 | - $("#example_id").ionRangeSlider({ | ||
7 | - type: "double", | ||
8 | - min: 0, | ||
9 | - max: 500, | ||
10 | - from: 50, | ||
11 | - to: 450, | ||
12 | - grid: false | ||
13 | - }); | ||
14 | - | ||
15 | // ion checkradio init | 5 | // ion checkradio init |
16 | $("input[type='radio'], input[type='checkbox']").ionCheckRadio(); | 6 | $("input[type='radio'], input[type='checkbox']").ionCheckRadio(); |
17 | 7 |