Commit 868680ca4ea559127e04f1feb1df9e87d51a2033
1 parent
0ac5c50c
-
Showing
5 changed files
with
257 additions
and
60 deletions
Show diff stats
common/modules/product/CatalogUrlManager.php
| @@ -45,27 +45,7 @@ class CatalogUrlManager implements UrlRuleInterface { | @@ -45,27 +45,7 @@ class CatalogUrlManager implements UrlRuleInterface { | ||
| 45 | if (!empty($paths[2])) { | 45 | if (!empty($paths[2])) { |
| 46 | // Filter | 46 | // Filter |
| 47 | if (strpos($paths[2], 'filter:') === 0) { | 47 | if (strpos($paths[2], 'filter:') === 0) { |
| 48 | - $params['filter'] = []; | ||
| 49 | - $filter_str = substr($paths[2], 7); | ||
| 50 | - $filter_options = explode(';', $filter_str); | ||
| 51 | - foreach ($filter_options as $filter_option) { | ||
| 52 | - if (empty($filter_option)) { | ||
| 53 | - continue; | ||
| 54 | - } | ||
| 55 | - list($filter_key, $filter_option) = explode('=', $filter_option); | ||
| 56 | - if($filter_key == 'prices') { // price-interval section | ||
| 57 | - $prices = explode(':', $filter_option); | ||
| 58 | - $params['filter'][$filter_key] = [ | ||
| 59 | - 'min' => floatval($prices[0]), | ||
| 60 | - 'max' => floatval($prices[1]), | ||
| 61 | - ]; | ||
| 62 | - } elseif (strpos($filter_key, $this->option_prefix) === 0) { // options section | ||
| 63 | - $params['filter']['options'][substr($filter_key, 2)] = explode(',', $filter_option); | ||
| 64 | - } else { // brands and other sections | ||
| 65 | - $params['filter'][$filter_key] = explode(',', $filter_option); | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | - } | 48 | + $this->parseFilter($paths[2], $params); |
| 69 | } elseif (strpos($paths[2], 'word:') === 0) { | 49 | } elseif (strpos($paths[2], 'word:') === 0) { |
| 70 | $params['word'] = substr($paths[2], 5); | 50 | $params['word'] = substr($paths[2], 5); |
| 71 | } | 51 | } |
| @@ -83,8 +63,14 @@ class CatalogUrlManager implements UrlRuleInterface { | @@ -83,8 +63,14 @@ class CatalogUrlManager implements UrlRuleInterface { | ||
| 83 | if (empty($paths[1]) || $paths[1] == 'index') { | 63 | if (empty($paths[1]) || $paths[1] == 'index') { |
| 84 | $route = 'catalog/brands'; | 64 | $route = 'catalog/brands'; |
| 85 | } elseif (($brand = BrandSearch::findByAlias($paths[1]))) { | 65 | } elseif (($brand = BrandSearch::findByAlias($paths[1]))) { |
| 86 | - $route = 'catalog/brands'; | 66 | + $route = 'catalog/brand'; |
| 87 | $params['brand'] = $brand; | 67 | $params['brand'] = $brand; |
| 68 | + if (!empty($paths[2])) { | ||
| 69 | + // Filter | ||
| 70 | + if (strpos($paths[2], 'filter:') === 0) { | ||
| 71 | + $this->parseFilter($paths[2], $params); | ||
| 72 | + } | ||
| 73 | + } | ||
| 88 | } else { | 74 | } else { |
| 89 | // @todo redirect or return FALSE | 75 | // @todo redirect or return FALSE |
| 90 | } | 76 | } |
| @@ -123,40 +109,7 @@ class CatalogUrlManager implements UrlRuleInterface { | @@ -123,40 +109,7 @@ class CatalogUrlManager implements UrlRuleInterface { | ||
| 123 | unset($params['word']); | 109 | unset($params['word']); |
| 124 | } | 110 | } |
| 125 | 111 | ||
| 126 | - $filter = []; | ||
| 127 | - if (!empty($params['filter'])) { | ||
| 128 | - foreach ($params['filter'] as $key => $values) { | ||
| 129 | - switch($key) { | ||
| 130 | - case 'prices': | ||
| 131 | - $filter[] = $key .'='. implode(':', $values); | ||
| 132 | - break; | ||
| 133 | - | ||
| 134 | - case 'options': | ||
| 135 | - foreach($values as $group => &$value_items) { | ||
| 136 | - foreach($value_items as &$value_item) { | ||
| 137 | - $value_item = $this->option_value_encode($value_item); | ||
| 138 | - if (empty($value_item)) { | ||
| 139 | - unset($value_item); | ||
| 140 | - } | ||
| 141 | - } | ||
| 142 | - $filter[] = $this->option_prefix. $group .'='. implode(',', $value_items); | ||
| 143 | - } | ||
| 144 | - break; | ||
| 145 | - | ||
| 146 | - default: | ||
| 147 | - foreach($values as &$value) { | ||
| 148 | - $value = $this->option_value_encode($value); | ||
| 149 | - if (empty($value)) { | ||
| 150 | - unset($value); | ||
| 151 | - } | ||
| 152 | - } | ||
| 153 | - $filter[] = $key .'='. implode(',', $values); | ||
| 154 | - break; | ||
| 155 | - } | ||
| 156 | - } | ||
| 157 | - $url .= 'filter:'. implode(';', $filter); | ||
| 158 | - unset($params['filter']); | ||
| 159 | - } | 112 | + $this->setFilterUrl($params, $url); |
| 160 | 113 | ||
| 161 | if (!empty($params) && ($query = http_build_query($params)) !== '') { | 114 | if (!empty($params) && ($query = http_build_query($params)) !== '') { |
| 162 | $url .= '?' . $query; | 115 | $url .= '?' . $query; |
| @@ -184,7 +137,9 @@ class CatalogUrlManager implements UrlRuleInterface { | @@ -184,7 +137,9 @@ class CatalogUrlManager implements UrlRuleInterface { | ||
| 184 | } else { | 137 | } else { |
| 185 | $brand_alias = is_object($params['brand']) ? $params['brand']->alias : strtolower($params['brand']); | 138 | $brand_alias = is_object($params['brand']) ? $params['brand']->alias : strtolower($params['brand']); |
| 186 | } | 139 | } |
| 187 | - $url = 'brands/'. $brand_alias; | 140 | + $url = 'brands/'. $brand_alias .'/'; |
| 141 | + | ||
| 142 | + $this->setFilterUrl($params, $url); | ||
| 188 | 143 | ||
| 189 | if (!empty($params) && ($query = http_build_query($params)) !== '') { | 144 | if (!empty($params) && ($query = http_build_query($params)) !== '') { |
| 190 | $url .= '?' . $query; | 145 | $url .= '?' . $query; |
| @@ -198,4 +153,64 @@ class CatalogUrlManager implements UrlRuleInterface { | @@ -198,4 +153,64 @@ class CatalogUrlManager implements UrlRuleInterface { | ||
| 198 | private function option_value_encode($value) { | 153 | private function option_value_encode($value) { |
| 199 | return str_replace(array(',', '/'), array('~', '&s;'), $value); | 154 | return str_replace(array(',', '/'), array('~', '&s;'), $value); |
| 200 | } | 155 | } |
| 156 | + | ||
| 157 | + private function setFilterUrl(&$params, &$url) { | ||
| 158 | + $filter = []; | ||
| 159 | + if (!empty($params['filter'])) { | ||
| 160 | + foreach ($params['filter'] as $key => $values) { | ||
| 161 | + switch($key) { | ||
| 162 | + case 'prices': | ||
| 163 | + $filter[] = $key .'='. implode(':', $values); | ||
| 164 | + break; | ||
| 165 | + | ||
| 166 | + case 'options': | ||
| 167 | + foreach($values as $group => &$value_items) { | ||
| 168 | + foreach($value_items as &$value_item) { | ||
| 169 | + $value_item = $this->option_value_encode($value_item); | ||
| 170 | + if (empty($value_item)) { | ||
| 171 | + unset($value_item); | ||
| 172 | + } | ||
| 173 | + } | ||
| 174 | + $filter[] = $this->option_prefix. $group .'='. implode(',', $value_items); | ||
| 175 | + } | ||
| 176 | + break; | ||
| 177 | + | ||
| 178 | + default: | ||
| 179 | + foreach($values as &$value) { | ||
| 180 | + $value = $this->option_value_encode($value); | ||
| 181 | + if (empty($value)) { | ||
| 182 | + unset($value); | ||
| 183 | + } | ||
| 184 | + } | ||
| 185 | + $filter[] = $key .'='. implode(',', $values); | ||
| 186 | + break; | ||
| 187 | + } | ||
| 188 | + } | ||
| 189 | + $url .= 'filter:'. implode(';', $filter); | ||
| 190 | + unset($params['filter']); | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + private function parseFilter($paths, &$params) { | ||
| 195 | + $params['filter'] = []; | ||
| 196 | + $filter_str = substr($paths, 7); | ||
| 197 | + $filter_options = explode(';', $filter_str); | ||
| 198 | + foreach ($filter_options as $filter_option) { | ||
| 199 | + if (empty($filter_option)) { | ||
| 200 | + continue; | ||
| 201 | + } | ||
| 202 | + list($filter_key, $filter_option) = explode('=', $filter_option); | ||
| 203 | + if($filter_key == 'prices') { // price-interval section | ||
| 204 | + $prices = explode(':', $filter_option); | ||
| 205 | + $params['filter'][$filter_key] = [ | ||
| 206 | + 'min' => floatval($prices[0]), | ||
| 207 | + 'max' => floatval($prices[1]), | ||
| 208 | + ]; | ||
| 209 | + } elseif (strpos($filter_key, $this->option_prefix) === 0) { // options section | ||
| 210 | + $params['filter']['options'][substr($filter_key, 2)] = explode(',', $filter_option); | ||
| 211 | + } else { // brands and other sections | ||
| 212 | + $params['filter'][$filter_key] = explode(',', $filter_option); | ||
| 213 | + } | ||
| 214 | + } | ||
| 215 | + } | ||
| 201 | } | 216 | } |
| 202 | \ No newline at end of file | 217 | \ No newline at end of file |
common/modules/product/models/Product.php
| @@ -7,6 +7,7 @@ use common\modules\rubrication\models\TaxOption; | @@ -7,6 +7,7 @@ use common\modules\rubrication\models\TaxOption; | ||
| 7 | use Yii; | 7 | use Yii; |
| 8 | use common\modules\relation\relationBehavior; | 8 | use common\modules\relation\relationBehavior; |
| 9 | use yii\db\ActiveQuery; | 9 | use yii\db\ActiveQuery; |
| 10 | +use yii\db\ActiveRecord; | ||
| 10 | use yii\helpers\Html; | 11 | use yii\helpers\Html; |
| 11 | use yii\web\UploadedFile; | 12 | use yii\web\UploadedFile; |
| 12 | 13 | ||
| @@ -237,6 +238,12 @@ class Product extends \yii\db\ActiveRecord | @@ -237,6 +238,12 @@ class Product extends \yii\db\ActiveRecord | ||
| 237 | } | 238 | } |
| 238 | } | 239 | } |
| 239 | 240 | ||
| 241 | + public function beforeDelete() { | ||
| 242 | + ProductImage::deleteAll(['product_id' => $this->product_id]); | ||
| 243 | + ProductCategory::deleteAll(['product_id' => $this->product_id]); | ||
| 244 | + ProductVariant::deleteAll(['product_id' => $this->product_id]); | ||
| 245 | + } | ||
| 246 | + | ||
| 240 | public function imagesUpload() | 247 | public function imagesUpload() |
| 241 | { | 248 | { |
| 242 | if ($this->validate()) { | 249 | if ($this->validate()) { |
frontend/controllers/CatalogController.php
| @@ -203,9 +203,30 @@ class CatalogController extends \yii\web\Controller | @@ -203,9 +203,30 @@ class CatalogController extends \yii\web\Controller | ||
| 203 | ]); | 203 | ]); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | - public function actionBrand($alias) | 206 | + public function actionBrand($brand) |
| 207 | { | 207 | { |
| 208 | - return 'actionBrand:'. $alias; | 208 | + $filter = Yii::$app->request->get('filter', []); |
| 209 | + | ||
| 210 | + $params = [ | ||
| 211 | + 'brand_id' => $brand->brand_id, | ||
| 212 | + ]; | ||
| 213 | + | ||
| 214 | + if ( !empty($filter['prices']) ) { | ||
| 215 | + $params['prices'] = $filter['prices']; | ||
| 216 | + } | ||
| 217 | + | ||
| 218 | + $productModel = new ProductFrontendSearch(); | ||
| 219 | + $productProvider = $productModel->search(null, $params); | ||
| 220 | + | ||
| 221 | + $priceLimits = $productModel->priceLimits(null, $params); | ||
| 222 | + | ||
| 223 | + return $this->render('brand', [ | ||
| 224 | + 'productModel' => $productModel, | ||
| 225 | + 'productProvider' => $productProvider, | ||
| 226 | + 'brand' => $brand, | ||
| 227 | + 'priceLimits' => $priceLimits, | ||
| 228 | + 'filter' => $filter, | ||
| 229 | + ]); | ||
| 209 | } | 230 | } |
| 210 | 231 | ||
| 211 | } | 232 | } |
| 1 | +<?php | ||
| 2 | +/** @var $this \yii\web\View */ | ||
| 3 | +/** @var $productProvider \yii\data\ActiveDataProvider */ | ||
| 4 | +/** @var $brandProvider \yii\data\ActiveDataProvider */ | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +use yii\helpers\Url; | ||
| 8 | +use yii\widgets\Breadcrumbs; | ||
| 9 | +use yii\web\View; | ||
| 10 | +use common\modules\product\helpers\ProductHelper; | ||
| 11 | + | ||
| 12 | +$this->title = $brand->name; | ||
| 13 | +$this->params['breadcrumbs'][] = ['label' => Yii::t('products', 'Brands'), 'url' => ['catalog/brands']]; | ||
| 14 | +$this->params['breadcrumbs'][] = $brand->name; | ||
| 15 | + | ||
| 16 | +$this->params['seo']['seo_text'] = 'TEST SEO TEXT'; | ||
| 17 | +$this->params['seo']['h1'] = 'TEST H1'; | ||
| 18 | +$this->params['seo']['description'] = 'TEST DESCRIPTION'; | ||
| 19 | +$this->params['seo']['fields']['name'] = 'TEST NAME FROM FIELD'; | ||
| 20 | +$this->params['seo']['key']= 'product_list'; | ||
| 21 | + | ||
| 22 | +$this->registerCssFile (Yii::getAlias('@web/css/ion.rangeSlider.css')); | ||
| 23 | +$this->registerCssFile (Yii::getAlias('@web/css/ion.rangeSlider.skinHTML5.css')); | ||
| 24 | +$this->registerJsFile (Yii::getAlias('@web/js/ion.rangeSlider.js')); | ||
| 25 | +?> | ||
| 26 | + | ||
| 27 | +<script type="text/javascript"> | ||
| 28 | + <?php if ($priceLimits['min'] < $priceLimits['max']) :?> | ||
| 29 | + $(document).ready(function() { | ||
| 30 | + // price rangeslider (filter price slider) | ||
| 31 | + $("#price_interval").ionRangeSlider({ | ||
| 32 | + type: "double", | ||
| 33 | + min: <?= $priceLimits['min']?>, | ||
| 34 | + max: <?= $priceLimits['max']?>, | ||
| 35 | + from: <?= empty($filter['prices']['min']) ? $priceLimits['min'] : $filter['prices']['min']?>, | ||
| 36 | + to: <?= empty($filter['prices']['max']) ? $priceLimits['max'] : $filter['prices']['max']?>, | ||
| 37 | + grid: false, | ||
| 38 | + onFinish: function(e) { | ||
| 39 | + <?php | ||
| 40 | + $filterWhitoutPrice = $filter; | ||
| 41 | + $filterWhitoutPrice['prices'] = [ | ||
| 42 | + 'min' => '{from}', | ||
| 43 | + 'max' => '{to}', | ||
| 44 | + ]; | ||
| 45 | + ?> | ||
| 46 | + var url = "<?= Url::to(['catalog/brands', 'brand' => $brand, 'filter' => $filterWhitoutPrice])?>"; | ||
| 47 | + var from = e.from; | ||
| 48 | + var to = e.to; | ||
| 49 | + document.location = url.replace('{from}', from).replace('{to}', to); | ||
| 50 | + } | ||
| 51 | + }); | ||
| 52 | + }); | ||
| 53 | + <?php endif?> | ||
| 54 | +</script> | ||
| 55 | + | ||
| 56 | +<nav class="bread-crumbs"> | ||
| 57 | + <?= Breadcrumbs::widget ([ | ||
| 58 | + 'links' => $this->params['breadcrumbs'], | ||
| 59 | + ]) | ||
| 60 | + ?> | ||
| 61 | + | ||
| 62 | + | ||
| 63 | + <div class="both"></div> | ||
| 64 | +</nav> | ||
| 65 | + | ||
| 66 | +<div class="loyout"> | ||
| 67 | + <div class="leftbar"> | ||
| 68 | + <div class="filters"> | ||
| 69 | + <ul> | ||
| 70 | + <li class="new"> | ||
| 71 | + <?php | ||
| 72 | + $checked = !empty($filter['special']) && in_array('new', $filter['special']); | ||
| 73 | + $option_url = Url::to(['catalog/brands', 'brand' => $brand, 'filter' => ProductHelper::getFilterForOption($filter, 'special', 'new', $checked)]); | ||
| 74 | + ?> | ||
| 75 | + <input type="checkbox" class="special-option" <?= $checked ? ' checked' : ''?> onchange="document.location='<?= $option_url?>'" /> | ||
| 76 | + <a href="<?= $option_url?>"><?= Yii::t('product', 'New products')?></a> | ||
| 77 | + </li> | ||
| 78 | + <li class="top"> | ||
| 79 | + <?php | ||
| 80 | + $checked = !empty($filter['special']) && in_array('top', $filter['special']); | ||
| 81 | + $option_url = Url::to(['catalog/brands', 'brand' => $brand, 'filter' => ProductHelper::getFilterForOption($filter, 'special', 'top', $checked)]); | ||
| 82 | + ?> | ||
| 83 | + <input type="checkbox" class="special-option" <?= $checked ? ' checked' : ''?> onchange="document.location='<?= $option_url?>'" /> | ||
| 84 | + <a href="<?= $option_url?>"><?= Yii::t('product', 'Top products')?></a> | ||
| 85 | + </li> | ||
| 86 | + <li class="promo"> | ||
| 87 | + <?php | ||
| 88 | + $checked = !empty($filter['special']) && in_array('promo', $filter['special']); | ||
| 89 | + $option_url = Url::to(['catalog/brands', 'brand' => $brand, 'filter' => ProductHelper::getFilterForOption($filter, 'special', 'promo', $checked)]); | ||
| 90 | + ?> | ||
| 91 | + <input type="checkbox" class="special-option" <?= $checked ? ' checked' : ''?> onchange="document.location='<?= $option_url?>'" /> | ||
| 92 | + <a href="<?= $option_url?>"><?= Yii::t('product', 'Promo products')?></a> | ||
| 93 | + </li> | ||
| 94 | + </ul> | ||
| 95 | + </div> | ||
| 96 | + <form action="#" name="filter_catalog_page_form" class="filter-catalog-form"> | ||
| 97 | + <?php if (!empty($filter)) :?> | ||
| 98 | + <div class="filter_accept_bloc"> | ||
| 99 | + <!-- <button type="submit" class="filter_accept_btn">применить</button>--> | ||
| 100 | + <a href="<?= Url::to(['catalog/brands', 'brand' => $brand])?>" class="_form_checkbox_reset">сбросить фильтры</a> | ||
| 101 | + </div> | ||
| 102 | + <?php endif?> | ||
| 103 | + | ||
| 104 | + <?php if ($priceLimits['min'] < $priceLimits['max']) :?> | ||
| 105 | + <div class="cost_box filters"> | ||
| 106 | + <div class="begin">Цена</div> | ||
| 107 | + <div class="price_filter first_price_li"> | ||
| 108 | + <div class="price_slider"> | ||
| 109 | + <input type="text" id="price_interval" name="price_interval" value="" /> | ||
| 110 | + </div> | ||
| 111 | + </div> | ||
| 112 | + </div> | ||
| 113 | + <?php endif?> | ||
| 114 | + </form> | ||
| 115 | + </div> | ||
| 116 | + | ||
| 117 | + <div class="content"> | ||
| 118 | + <h1><?= $brand->name ?></h1> | ||
| 119 | + <div class="sort_menu"> | ||
| 120 | + | ||
| 121 | + <div class="sort_block"> | ||
| 122 | + <span>Сортировка:</span> | ||
| 123 | + <?= \yii\widgets\LinkSorter::widget([ | ||
| 124 | + 'sort' => $productProvider->sort, | ||
| 125 | + 'attributes' => [ | ||
| 126 | + 'name', | ||
| 127 | + 'price', | ||
| 128 | + ] | ||
| 129 | + ]); | ||
| 130 | + ?> | ||
| 131 | + </div> | ||
| 132 | + </div> | ||
| 133 | + <div class="products pn"> | ||
| 134 | + <ul> | ||
| 135 | + <?php foreach($productProvider->models as $product) :?> | ||
| 136 | + <?php require(__DIR__ .'/product_item.php')?> | ||
| 137 | + <?php endforeach?> | ||
| 138 | + </ul> | ||
| 139 | + <div class="both"></div> | ||
| 140 | + </div> | ||
| 141 | + <?php if ($productProvider->totalCount > $productProvider->pagination->pageSize) :?> | ||
| 142 | + <?= \yii\widgets\LinkPager::widget([ | ||
| 143 | + 'pagination' => $productProvider->pagination, | ||
| 144 | + 'options' => ['class' => 'pagination pull-right'], | ||
| 145 | + 'registerLinkTags' => true, | ||
| 146 | + ]); | ||
| 147 | + ?> | ||
| 148 | + <?php endif?> | ||
| 149 | + <div class="both"></div> | ||
| 150 | + </div> | ||
| 151 | + <div class="both"></div> | ||
| 152 | + | ||
| 153 | + <?= \common\modules\product\widgets\lastProducts::widget()?> | ||
| 154 | +</div> | ||
| 0 | \ No newline at end of file | 155 | \ No newline at end of file |
frontend/widgets/Rubrics.php
| @@ -32,7 +32,7 @@ class Rubrics extends Widget { | @@ -32,7 +32,7 @@ class Rubrics extends Widget { | ||
| 32 | $items = []; | 32 | $items = []; |
| 33 | 33 | ||
| 34 | if (empty($this->categories)) { | 34 | if (empty($this->categories)) { |
| 35 | - $this->categories = Category::find ()->all(); | 35 | + $this->categories = Category::find ()->orderBy('category_id', SORT_ASC)->all(); |
| 36 | } | 36 | } |
| 37 | foreach ($this->categories as $category) { | 37 | foreach ($this->categories as $category) { |
| 38 | if (!empty($this->includes) && !in_array($category->category_id, $this->includes)) { | 38 | if (!empty($this->includes) && !in_array($category->category_id, $this->includes)) { |