Commit 8b83e9d147ed4059002126163aaed7c775225103

Authored by Administrator
1 parent 423109eb

add variantSku

helpers/CatalogFilterHelper.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace artweb\artbox\ecommerce\helpers;
  4 +
  5 +use artweb\artbox\ecommerce\models\BrandLang;
  6 +use artweb\artbox\ecommerce\models\CategoryLang;
  7 +use artweb\artbox\ecommerce\models\Product;
  8 +use artweb\artbox\ecommerce\models\ProductLang;
  9 +use artweb\artbox\ecommerce\models\ProductVariant;
  10 +use artweb\artbox\ecommerce\models\ProductVariantLang;
  11 +use artweb\artbox\ecommerce\models\TaxGroup;
  12 +use frontend\models\Catalog;
  13 +use yii\base\Object;
  14 +use yii\db\ActiveQuery;
  15 +use yii\helpers\ArrayHelper;
  16 +use yii\elasticsearch\Query;
  17 +
  18 +class CatalogFilterHelper extends Object
  19 +{
  20 +
  21 + public static $optionsList = [];
  22 +
  23 + /**
  24 + * Get TaxGroups
  25 + *
  26 + * @return array
  27 + */
  28 + public static function optionsTemplate()
  29 + {
  30 + if (empty( static::$optionsList )) {
  31 + return static::$optionsList = ArrayHelper::getColumn(
  32 + TaxGroup::find()
  33 + ->joinWith('lang')
  34 + ->where([ 'is_filter' => 'TRUE' ])
  35 + ->all(),
  36 + 'lang.alias'
  37 + );
  38 + } else {
  39 + return static::$optionsList;
  40 + }
  41 +
  42 + }
  43 +
  44 + /**
  45 + * Return custom filter-option link
  46 + *
  47 + * @param array $filter
  48 + * @param string $key
  49 + * @param mixed $value
  50 + * @param bool $remove
  51 + *
  52 + * @return array
  53 + */
  54 + public static function getFilterForOption(array $filter, string $key, $value, bool $remove = false)
  55 + {
  56 +
  57 + $optionsTemplate = self::optionsTemplate();
  58 + array_unshift($optionsTemplate, "special", "brands");
  59 +
  60 + $result = $filter;
  61 +
  62 + if (is_array($value)) {
  63 + foreach ($value as $value_key => $value_items) {
  64 + if (!is_array($value_items)) {
  65 + $value_items = [ $value_items ];
  66 + }
  67 + foreach ($value_items as $value_item) {
  68 + if ($remove && isset( $result[ $key ] ) && ( $i = array_search(
  69 + $value_item,
  70 + $result[ $key ][ $value_key ]
  71 + ) ) !== false
  72 + ) {
  73 + unset( $result[ $key ][ $value_key ][ $i ] );
  74 + if (empty( $result[ $key ][ $value_key ] )) {
  75 + unset( $result[ $key ][ $value_key ] );
  76 + }
  77 + } else {
  78 + if (!isset( $result[ $key ][ $value_key ] ) || array_search(
  79 + $value_item,
  80 + $result[ $key ][ $value_key ]
  81 + ) === false
  82 + ) {
  83 + $result[ $key ][ $value_key ][] = $value_item;
  84 + }
  85 + }
  86 + }
  87 + }
  88 + } else {
  89 + if ($remove && isset( $result[ $key ] ) && ( $i = array_search($value, $result[ $key ]) ) !== false) {
  90 + unset( $result[ $key ][ $i ] );
  91 + if (empty( $result[ $key ] )) {
  92 + unset( $result[ $key ] );
  93 + }
  94 + } else {
  95 + if (!isset( $result[ $key ] ) || array_search($value, $result[ $key ]) === false) {
  96 + $result[ $key ][] = $value;
  97 + }
  98 + }
  99 + }
  100 +
  101 + $filterView = [];
  102 +
  103 + foreach ($optionsTemplate as $optionKey) {
  104 + if (isset( $result[ $optionKey ] )) {
  105 + $filterView[ $optionKey ] = $result[ $optionKey ];
  106 + }
  107 +
  108 + }
  109 +
  110 + return $filterView;
  111 + }
  112 +
  113 +
  114 +
  115 + /**
  116 + * select options for product variants with selected category
  117 + *
  118 + * @param integer $categoryId
  119 + * @param integer $langId
  120 + * @return mixed
  121 + */
  122 + public static function getProductVariantOptions($categoryId,$langId){
  123 +
  124 + $cacheKey = [
  125 + 'OptionsForFilter',
  126 + 'categoryId' => $categoryId,
  127 + 'langId' =>$langId
  128 + ];
  129 + if (!$OptionsForFilter = \Yii::$app->cache->get($cacheKey)) {
  130 + $OptionsForFilter = ( new \yii\db\Query() )->distinct()->select('tax_group_lang.alias')
  131 + ->from('product_variant_option')
  132 + ->innerJoin(
  133 + 'tax_option',
  134 + 'product_variant_option.option_id = tax_option.id'
  135 + )
  136 + ->innerJoin(
  137 + 'tax_group',
  138 + 'tax_group.id = tax_option.tax_group_id'
  139 + )
  140 + ->innerJoin(
  141 + 'tax_group_lang',
  142 + 'tax_group_lang.tax_group_id = tax_group.id'
  143 + )
  144 + ->innerJoin(
  145 + 'tax_group_to_category',
  146 + 'tax_group_to_category.tax_group_id = tax_group.id'
  147 + )
  148 + ->where([
  149 + 'tax_group_lang.language_id' => $langId,
  150 + 'tax_group_to_category.category_id' => $categoryId,
  151 + 'tax_group.is_filter' => true
  152 + ])->all();
  153 + $OptionsForFilter = ArrayHelper::getColumn($OptionsForFilter,'alias');
  154 + \Yii::$app->cache->set($cacheKey, $OptionsForFilter, 3600 * 24);
  155 + }
  156 +
  157 + return $OptionsForFilter;
  158 + }
  159 +
  160 + /**
  161 + * @param array $params
  162 + * @param $categoryId
  163 + * @param $langId
  164 + * @param bool $in_stock
  165 + * @return mixed
  166 + */
  167 + public static function setQueryParams(array $params, $categoryId, $langId,$in_stock=true)
  168 + {
  169 +
  170 + $last_query = null;
  171 + $productVariantOptions = self::getProductVariantOptions($categoryId,$langId);
  172 + $filters = [];
  173 + foreach ($params as $key => $param) {
  174 + switch ($key) {
  175 + case 'special':
  176 + unset($params[$key]);
  177 + self::filterSpecial($param, $filters);
  178 + break;
  179 + case 'brands':
  180 + unset($params[$key]);
  181 + self::filterBrands($param, $filters);
  182 + break;
  183 + case 'prices':
  184 + unset($params[$key]);
  185 + self::filterPrices($param, $filters);
  186 + break;
  187 +
  188 + }
  189 + }
  190 +
  191 + if(!empty($params)){
  192 + self::filterOptions($params, $productVariantOptions, $filters, $langId);
  193 + }
  194 +
  195 +
  196 + $filterQuery = new Query();
  197 + $filterQuery->source('id');
  198 + $filterQuery->from(Catalog::index(), Catalog::type());
  199 + if($in_stock){
  200 + $filterVO['nested']['path'] = 'variants';
  201 + $filterVO['nested']['query']['bool']['must_not'][]['match']['variants.stock'] = 0;
  202 + $filters['bool']['must'][] = $filterVO;
  203 + }
  204 + if($filters){
  205 + $filters['bool']['must'][]['term']['language_id'] = $langId;
  206 + $filterC['nested']['path'] = 'categories';
  207 + $filterC['nested']['query']['bool']['must']['term']['categories.id'] = $categoryId;
  208 + $filters['bool']['must'][] = $filterC;
  209 + $filterQuery->query($filters);
  210 + }
  211 + return $filterQuery;
  212 + }
  213 +
  214 +
  215 +
  216 + /**
  217 + * Tax Option filter
  218 + *
  219 + * @param string[] $params
  220 + * @param string[] $productVariantOptions
  221 + * @param array $filters
  222 + * @param integer $langId
  223 + * @param bool $in_stock
  224 + *
  225 + * @return \yii\db\Query
  226 + */
  227 + private static function filterOptions(array $params,$productVariantOptions, array &$filters, $langId, bool $in_stock = true)
  228 + {
  229 +
  230 +
  231 + $filterVO['nested']['path'] = 'variants';
  232 + foreach ($params as $key=>$param){
  233 + if(in_array($key, $productVariantOptions)){
  234 + unset($params[$key]);
  235 + $filterVO['nested']['query']['bool']['filter'][]['terms']['variants.options.alias'] = $param;
  236 + }
  237 +
  238 + }
  239 +
  240 + if($in_stock){
  241 + $filterVO['nested']['path'] = 'variants';
  242 + $filterVO['nested']['query']['bool']['must_not'][]['match']['variants.stock'] = 0;
  243 + }
  244 +
  245 + $filters['bool']['must'][] = $filterVO;
  246 +
  247 + if(!empty($params)) {
  248 +
  249 + $filterO = [];
  250 +
  251 + foreach ($params as $key=>$param){
  252 +
  253 + $filterO['bool']['filter'][]['terms']['options.alias'] = $param;
  254 +
  255 + }
  256 +
  257 + $filters['bool']['must'][] = $filterO;
  258 + }
  259 +
  260 +
  261 + }
  262 +
  263 +
  264 +
  265 + /**
  266 + * Fill $query with special filters (used in Product)
  267 + *
  268 + * @param array $params
  269 + * @param array $filters
  270 + */
  271 + private static function filterSpecial(array $params, array &$filters)
  272 + {
  273 + /**
  274 + * @var string $key
  275 + */
  276 +
  277 + foreach ($params as $key => $param) {
  278 +
  279 + $filters['bool']['must'][]['term'][$key] = $param;
  280 +
  281 + }
  282 +
  283 + }
  284 +
  285 + /**
  286 + * Fill query with brands filter
  287 + *
  288 + * @param int[] $params
  289 + * @param array $filters
  290 + */
  291 + private static function filterBrands(array $params, array &$filters)
  292 + {
  293 +
  294 +
  295 + $filters['bool']['filter'][]['terms']['brand.alias'] = $params;
  296 +
  297 +
  298 + }
  299 +
  300 + /**
  301 + * Fill query with price limits filter
  302 + *
  303 + * @param array $params
  304 + * @param array $filters
  305 + */
  306 + private static function filterPrices(array $params, array &$filters)
  307 + {
  308 + if (!empty( $params[ 'min' ] ) && $params[ 'min' ] > 0) {
  309 + $filters['bool']['filter']['range']['age']['gte'] = $params[ 'min' ];
  310 + }
  311 + if (!empty( $params[ 'max' ] ) && $params[ 'max' ] > 0) {
  312 + $filters['bool']['filter']['range']['age']['lte'] = $params[ 'max' ];
  313 + }
  314 +
  315 + }
  316 +
  317 +}
... ...
helpers/FilterHelper.php
... ... @@ -310,7 +310,8 @@
310 310 */
311 311 private static function filterBrands(array $param, ActiveQuery $query)
312 312 {
313   - $query->andFilterWhere([ Product::tableName() . '.brand_id' => $param ]);
  313 + $query->joinWith('brand');
  314 + $query->andFilterWhere([ 'brand.alias' => $param ]);
314 315 }
315 316  
316 317 /**
... ...
models/Product.php
... ... @@ -40,6 +40,8 @@
40 40 * @property ProductVariant[] $enabledVariants
41 41 * @property string $video
42 42 * @property TaxOption[] $options
  43 + * @property TaxOption[] $filterOptions
  44 + * @property TaxGroup[] $groups
43 45 * @property Brand $brand
44 46 * @property TaxOption[] $filters
45 47 * @property ProductVariant[] $variantsWithFilters
... ... @@ -101,6 +103,7 @@
101 103 */
102 104 class Product extends ActiveRecord
103 105 {
  106 + public $option_id;
104 107  
105 108 public $min;
106 109 public $max;
... ... @@ -366,11 +369,7 @@
366 369 return 0;
367 370 }
368 371 }
369   -
370   - public function getTaxOption()
371   - {
372   -// return $this->getOptions()->innerJoinWith('taxGroup')->where([''])
373   - }
  372 +
374 373  
375 374 /**
376 375 * Get Product name concatenated with Brand name
... ... @@ -472,9 +471,37 @@
472 471 public function getOptions()
473 472 {
474 473 return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ])
475   - ->viaTable('product_option', [ 'product_id' => 'id' ]);
  474 + ->viaTable('product_option', [ 'product_id' => 'id' ]);
  475 +
476 476 }
477   -
  477 +
  478 +
  479 + /**
  480 + * Get TaxOptions query for current Product that will by used in filter
  481 + *
  482 + * @return ActiveQuery
  483 + */
  484 + public function getFilterOptions()
  485 + {
  486 +
  487 + return $this->getOptions()
  488 + ->joinWith(['lang','taxGroup'])
  489 + ->where(['is_filter' => true]);
  490 + }
  491 +
  492 +
  493 + /**
  494 + * Get TaxGroup for current Product
  495 + *
  496 + * @return ActiveQuery
  497 + */
  498 + public function getGroups()
  499 + {
  500 + return $this->hasMany(TaxGroup::className(), [ 'id' => 'tax_group_id' ])
  501 + ->via('options');
  502 + }
  503 +
  504 +
478 505 /**
479 506 * Get TaxOptions query for current Product joined with TaxGroups
480 507 *
... ...
models/ProductFrontendSearch.php
... ... @@ -2,6 +2,7 @@
2 2  
3 3 namespace artweb\artbox\ecommerce\models;
4 4  
  5 + use artweb\artbox\ecommerce\helpers\CatalogFilterHelper;
5 6 use artweb\artbox\ecommerce\helpers\FilterHelper;
6 7 use artweb\artbox\ecommerce\models\Category;
7 8 use artweb\artbox\language\models\Language;
... ... @@ -174,7 +175,19 @@
174 175 );
175 176  
176 177 $lang = Language::getCurrent();
177   - FilterHelper::setQueryParams($query, $params, $category->id, $lang->id);
  178 +
  179 + /**
  180 + * @var $catalog \yii\elasticsearch\Query;
  181 + */
  182 + if($params){
  183 + $catalog = CatalogFilterHelper::setQueryParams($params, $category->id, $lang->id);
  184 + $catalog->limit(9999);
  185 + $catalog->createCommand();
  186 + $result = $catalog->column('id');
  187 + $query->andWhere(['product.id'=>$result]);
  188 + }
  189 +
  190 +
178 191 return $query;
179 192 }
180 193  
... ... @@ -194,21 +207,27 @@
194 207 $query = Product::find();
195 208 }
196 209  
  210 +
  211 +
197 212 $query->select(['MAX('.ProductVariant::tableName() . '.price) as max', 'MIN('.ProductVariant::tableName() . '.price) as min']);
198 213 $query->joinWith('variant');
199   -
  214 +
200 215 // Price filter fix
201 216 unset( $params[ 'prices' ] );
202   -
203 217 $lang = Language::getCurrent();
204   - FilterHelper::setQueryParams($query, $params, $category->id, $lang->id);
205   - $query->andWhere(
206   - [
207   - '>=',
208   - ProductVariant::tableName() . '.stock',
209   - 1,
210   - ]
211   - );
  218 +
  219 + /**
  220 + * @var $catalog \yii\elasticsearch\Query;
  221 + */
  222 + if($params){
  223 + $catalog = CatalogFilterHelper::setQueryParams($params, $category->id, $lang->id);
  224 + $catalog->limit(9999);
  225 + $catalog->createCommand();
  226 + $result = $catalog->column('id');
  227 + $query->andWhere(['product.id'=>$result]);
  228 + }
  229 +
  230 +
212 231 return $query->one();
213 232 }
214 233 }
215 234 \ No newline at end of file
... ...
models/ProductVariant.php
... ... @@ -24,6 +24,8 @@
24 24 * @property integer $product_unit_id
25 25 * @property string $fullname
26 26 * @property TaxOption[] $options
  27 + * @property TaxGroup[] $groups
  28 + * @property TaxOption[] $filterOptions
27 29 * @property ProductUnit $productUnit
28 30 * @property Product $product
29 31 * @property Category[] $categories
... ... @@ -71,7 +73,7 @@
71 73 {
72 74  
73 75 public $customOption = [];
74   -
  76 +
75 77 /**
76 78 * @var int[] $options
77 79 */
... ... @@ -280,7 +282,30 @@
280 282 return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ])
281 283 ->viaTable('product_variant_option', [ 'product_variant_id' => 'id' ]);
282 284 }
283   -
  285 +
  286 + /**
  287 + * Get TaxGroup for current Product
  288 + *
  289 + * @return ActiveQuery
  290 + */
  291 + public function getGroups()
  292 + {
  293 + return $this->hasMany(TaxGroup::className(), [ 'id' => 'tax_group_id' ])
  294 + ->via('options');
  295 + }
  296 +
  297 + /**
  298 + * Get TaxOptions query for current ProductVariant that will by used in filter
  299 + *
  300 + * @return ActiveQuery
  301 + */
  302 + public function getFilterOptions()
  303 + {
  304 + return $this->getOptions()
  305 + ->joinWith(['lang','taxGroup'])
  306 + ->where(['is_filter' => true]);
  307 + }
  308 +
284 309 /**
285 310 * Get one variant's option whith needed conditions, or random if condition is empty
286 311 *
... ... @@ -332,7 +357,7 @@
332 357 {
333 358 $this->options = $values;
334 359 }
335   -
  360 +
336 361 /**
337 362 * Get all TaxGroups for current ProductVariant filled with $customOptions that satisfy current ProductVariant
338 363 *
... ... @@ -446,7 +471,7 @@
446 471 }
447 472 }
448 473 }
449   -
  474 +
450 475 /**
451 476 * @return string
452 477 */
... ...