1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace app\models; |
4
|
|
|
|
5
|
|
|
use app\modules\shop\models\ConfigConfigurationModel; |
6
|
|
|
use app\modules\shop\models\Product; |
7
|
|
|
use app\properties\HasProperties; |
8
|
|
|
use app\traits\GetImages; |
9
|
|
|
use app\traits\SortModels; |
10
|
|
|
use devgroup\TagDependencyHelper\ActiveRecordHelper; |
11
|
|
|
use Yii; |
12
|
|
|
use yii\behaviors\AttributeBehavior; |
13
|
|
|
use yii\caching\TagDependency; |
14
|
|
|
use yii\data\ActiveDataProvider; |
15
|
|
|
use yii\db\ActiveQuery; |
16
|
|
|
use yii\db\ActiveRecord; |
17
|
|
|
use yii\db\Expression; |
18
|
|
|
use app\modules\shop\models\Currency; |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* This is the model class for table "property_static_values". |
22
|
|
|
* @property integer $id |
23
|
|
|
* @property integer $property_id |
24
|
|
|
* @property string $name |
25
|
|
|
* @property string $value |
26
|
|
|
* @property string $slug |
27
|
|
|
* @property integer $sort_order |
28
|
|
|
* @property Property $property |
29
|
|
|
* @property integer $dont_filter |
30
|
|
|
*/ |
31
|
|
|
class PropertyStaticValues extends ActiveRecord |
32
|
|
|
{ |
33
|
|
|
use GetImages; |
34
|
|
|
|
35
|
|
|
public static $identity_map_by_property_id = []; |
36
|
|
|
private static $identity_map = []; |
37
|
|
|
|
38
|
|
|
use SortModels; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @inheritdoc |
42
|
|
|
*/ |
43
|
|
|
public function behaviors() |
44
|
|
|
{ |
45
|
|
|
return [ |
46
|
|
|
[ |
47
|
|
|
'class' => AttributeBehavior::className(), |
|
|
|
|
48
|
|
|
'attributes' => [ |
49
|
|
|
\yii\db\ActiveRecord::EVENT_BEFORE_INSERT => 'sort_order', |
50
|
|
|
], |
51
|
|
|
'value' => 0, |
52
|
|
|
], |
53
|
|
|
[ |
54
|
|
|
'class' => ActiveRecordHelper::className(), |
|
|
|
|
55
|
|
|
], |
56
|
|
|
[ |
57
|
|
|
'class' => HasProperties::className(), |
|
|
|
|
58
|
|
|
], |
59
|
|
|
]; |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @inheritdoc |
64
|
|
|
*/ |
65
|
|
|
public static function tableName() |
66
|
|
|
{ |
67
|
|
|
return '{{%property_static_values}}'; |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
/** |
71
|
|
|
* @inheritdoc |
72
|
|
|
*/ |
73
|
|
View Code Duplication |
public function rules() |
74
|
|
|
{ |
75
|
|
|
return [ |
76
|
|
|
[['property_id', 'name', 'value'], 'required'], |
77
|
|
|
[['property_id', 'sort_order', 'dont_filter'], 'integer'], |
78
|
|
|
[['slug'], 'unique'], |
79
|
|
|
[['title_prepend'], 'boolean'], |
80
|
|
|
[['name', 'value', 'slug', 'title_append'], 'string'] |
81
|
|
|
]; |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @inheritdoc |
86
|
|
|
*/ |
87
|
|
|
public function attributeLabels() |
88
|
|
|
{ |
89
|
|
|
return [ |
90
|
|
|
'id' => Yii::t('app', 'ID'), |
91
|
|
|
'property_id' => Yii::t('app', 'Property ID'), |
92
|
|
|
'name' => Yii::t('app', 'Name'), |
93
|
|
|
'value' => Yii::t('app', 'Value'), |
94
|
|
|
'slug' => Yii::t('app', 'Slug'), |
95
|
|
|
'sort_order' => Yii::t('app', 'Sort Order'), |
96
|
|
|
'title_append' => Yii::t('app', 'Title append'), |
97
|
|
|
'title_prepend' => Yii::t('app', 'Prepend title?'), |
98
|
|
|
'dont_filter' => Yii::t('app', 'Don\'t filter (for FilterWidget only)'), |
99
|
|
|
]; |
100
|
|
|
} |
101
|
|
|
|
102
|
|
|
/** |
103
|
|
|
* Search tasks |
104
|
|
|
* @param $params |
105
|
|
|
* @return ActiveDataProvider |
106
|
|
|
*/ |
107
|
|
View Code Duplication |
public function search($params) |
108
|
|
|
{ |
109
|
|
|
$query = static::find()->where(['property_id' => $this->property_id]); |
110
|
|
|
$dataProvider = new ActiveDataProvider( |
111
|
|
|
[ |
112
|
|
|
'query' => $query, |
113
|
|
|
'pagination' => [ |
114
|
|
|
'pageSize' => 10, |
115
|
|
|
], |
116
|
|
|
] |
117
|
|
|
); |
118
|
|
|
if (!($this->load($params))) { |
119
|
|
|
return $dataProvider; |
120
|
|
|
} |
121
|
|
|
$query->andFilterWhere(['id' => $this->id]); |
122
|
|
|
$query->andFilterWhere(['like', 'name', $this->name]); |
123
|
|
|
$query->andFilterWhere(['like', 'value', $this->value]); |
124
|
|
|
$query->andFilterWhere(['like', 'slug', $this->slug]); |
125
|
|
|
return $dataProvider; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
public function getProperty() |
129
|
|
|
{ |
130
|
|
|
return $this->hasOne(Property::className(), ['id' => 'property_id']); |
|
|
|
|
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
/** |
134
|
|
|
* Возвращает Массив! по ID с использованием IdentityMap |
135
|
|
|
* @param int $id |
136
|
|
|
* @return null|PropertyStaticValues |
137
|
|
|
*/ |
138
|
|
View Code Duplication |
public static function findById($id) |
139
|
|
|
{ |
140
|
|
|
if (!isset(static::$identity_map[$id])) { |
141
|
|
|
$cacheKey = "PropertyStaticValue:$id"; |
142
|
|
|
|
143
|
|
|
if (false === $property = Yii::$app->cache->get($cacheKey)) { |
144
|
|
|
if (null !== $property = static::find()->where(['id' => $id])->asArray()->one()) { |
145
|
|
|
Yii::$app->cache->set( |
146
|
|
|
$cacheKey, |
147
|
|
|
$property, |
148
|
|
|
0, |
149
|
|
|
new TagDependency( |
150
|
|
|
[ |
151
|
|
|
'tags' => [ |
152
|
|
|
\devgroup\TagDependencyHelper\ActiveRecordHelper::getObjectTag( |
153
|
|
|
static::className(), |
|
|
|
|
154
|
|
|
$id |
155
|
|
|
), |
156
|
|
|
], |
157
|
|
|
] |
158
|
|
|
) |
159
|
|
|
); |
160
|
|
|
} |
161
|
|
|
} |
162
|
|
|
static::$identity_map[$id] = $property; |
163
|
|
|
} |
164
|
|
|
return static::$identity_map[$id]; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
/** |
168
|
|
|
* Возвращает массив возможных значений свойств по property_id |
169
|
|
|
* Внимание! Это массивы, а не объекты! |
170
|
|
|
* Это сделано для экономии памяти. |
171
|
|
|
* Используется identity_map |
172
|
|
|
* |
173
|
|
|
* @return array |
174
|
|
|
*/ |
175
|
|
|
public static function getValuesForPropertyId($property_id) |
176
|
|
|
{ |
177
|
|
|
if (!isset(static::$identity_map_by_property_id[$property_id])) { |
178
|
|
|
static::$identity_map_by_property_id[$property_id] = static::arrayOfValuesForPropertyId($property_id); |
179
|
|
|
foreach (static::$identity_map_by_property_id[$property_id] as $psv) { |
180
|
|
|
static::$identity_map[$psv['id']] = $psv; |
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
return static::$identity_map_by_property_id[$property_id]; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
public static function getSelectForPropertyId($property_id) |
187
|
|
|
{ |
188
|
|
|
$values = PropertyStaticValues::getValuesForPropertyId($property_id); |
189
|
|
|
$result = []; |
190
|
|
|
foreach ($values as $row) { |
191
|
|
|
$result[$row['id']] = $row['name']; |
192
|
|
|
} |
193
|
|
|
return $result; |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
/** |
197
|
|
|
* @param $property_id |
198
|
|
|
* @param $category_id |
199
|
|
|
* @param $properties |
200
|
|
|
* @return PropertyStaticValues[] |
201
|
|
|
*/ |
202
|
|
|
public static function getValuesForFilter($property_id, $category_id, $properties, $multiple = false, $productsFilteringMode = "") |
203
|
|
|
{ |
204
|
|
|
$priceMin = Yii::$app->request->get('price_min'); |
205
|
|
|
$priceMax = Yii::$app->request->get('price_max'); |
206
|
|
|
$cacheKey = "getValuesForFilter:" . json_encode([$property_id, $category_id, $properties, $priceMin, $priceMax]); |
207
|
|
|
if (false === $allSelections = Yii::$app->cache->get($cacheKey)) { |
208
|
|
|
|
209
|
|
|
switch($productsFilteringMode) { |
210
|
|
|
case ConfigConfigurationModel::FILTER_PARENTS_ONLY: |
211
|
|
|
$joinCondition = 'p.id = {{%product_category}}.object_model_id AND p.active = 1 AND p.parent_id = 0'; |
212
|
|
|
break; |
213
|
|
|
case ConfigConfigurationModel::FILTER_CHILDREN_ONLY: |
214
|
|
|
$joinCondition = 'p.id = {{%product_category}}.object_model_id AND p.active = 1 AND p.parent_id != 0'; |
215
|
|
|
break; |
216
|
|
|
default: |
217
|
|
|
$joinCondition = 'p.id = {{%product_category}}.object_model_id AND p.active = 1'; |
218
|
|
|
break; |
219
|
|
|
} |
220
|
|
|
$product = Yii::$container->get(Product::class); |
221
|
|
|
$objectModel = BaseObject::getForClass(get_class($product)); |
222
|
|
|
$objectId = $objectModel !== null ? $objectModel->id : 0; |
223
|
|
|
$allSelections = static::find() |
224
|
|
|
->asArray(true) |
225
|
|
|
->select([self::tableName() . '.id', self::tableName() . '.name', 'value', self::tableName() . '.slug']) |
226
|
|
|
->innerJoin( |
227
|
|
|
ObjectStaticValues::tableName(), |
228
|
|
|
ObjectStaticValues::tableName() . '.property_static_value_id=' . self::tableName() . '.id' |
229
|
|
|
) |
230
|
|
|
->innerJoin( |
231
|
|
|
'{{%product_category}}', |
232
|
|
|
'{{%product_category}}.object_model_id = ' . ObjectStaticValues::tableName() . '.object_model_id' |
233
|
|
|
) |
234
|
|
|
->innerJoin( |
235
|
|
|
$product::tableName() . ' p', |
236
|
|
|
$joinCondition |
237
|
|
|
) |
238
|
|
|
->where( |
239
|
|
|
[ |
240
|
|
|
self::tableName() . '.property_id' => $property_id, |
241
|
|
|
self::tableName() . '.dont_filter' => 0, |
242
|
|
|
'{{%product_category}}.category_id' => $category_id, |
243
|
|
|
] |
244
|
|
|
) |
245
|
|
|
->orderBy( |
246
|
|
|
[ |
247
|
|
|
self::tableName() . '.sort_order' => SORT_ASC, |
248
|
|
|
self::tableName() . '.name' => SORT_ASC, |
249
|
|
|
] |
250
|
|
|
) |
251
|
|
|
->all(); |
252
|
|
|
/** @var ActiveQuery $query */ |
253
|
|
|
$query = ObjectStaticValues::find() |
254
|
|
|
->distinct(true) |
255
|
|
|
->select(ObjectStaticValues::tableName() . '.object_model_id') |
256
|
|
|
->where(['object_id' => $objectId]); |
257
|
|
|
if (false === empty($properties)) { |
258
|
|
|
foreach ($properties as $propertyId => $propertyStaticValues) { |
259
|
|
|
$subQuery = self::initSubQuery($category_id, $joinCondition); |
260
|
|
|
$subQuery->andWhere(['property_static_value_id' => $propertyStaticValues,]); |
261
|
|
View Code Duplication |
$subQueryOptimisation = Yii::$app->db->cache(function($db) use ($subQuery) { |
262
|
|
|
$ids = implode(', ', $subQuery->createCommand($db)->queryColumn()); |
263
|
|
|
return empty($ids) === true ? '(-1)' : "($ids)"; |
264
|
|
|
}, 86400, new TagDependency([ |
265
|
|
|
'tags' => [ |
266
|
|
|
ActiveRecordHelper::getCommonTag(ObjectStaticValues::className()), |
|
|
|
|
267
|
|
|
] |
268
|
|
|
])); |
269
|
|
|
$query->andWhere(new Expression('`object_model_id` IN ' . $subQueryOptimisation)); |
270
|
|
|
} |
271
|
|
|
} |
272
|
|
|
if (false === empty($priceMin) && false === empty($priceMax)) { |
273
|
|
|
$subQuery = self::initSubQuery($category_id, $joinCondition); |
274
|
|
|
$subQuery |
275
|
|
|
->andWhere('p.price >= (:min_price * currency.convert_nominal / currency.convert_rate)', |
276
|
|
|
[':min_price' => $priceMin]) |
277
|
|
|
->andWhere('p.price <= (:max_price * currency.convert_nominal / currency.convert_rate)', |
278
|
|
|
[':max_price' => $priceMax]) |
279
|
|
|
->leftJoin(Currency::tableName() . ' ON currency.id = p.currency_id'); |
280
|
|
View Code Duplication |
$subQueryOptimisation = Yii::$app->db->cache(function($db) use ($subQuery) { |
281
|
|
|
$ids = implode(', ', $subQuery->createCommand($db)->queryColumn()); |
282
|
|
|
return empty($ids) === true ? '(-1)' : "($ids)"; |
283
|
|
|
}, 86400, new TagDependency([ |
284
|
|
|
'tags' => [ |
285
|
|
|
ActiveRecordHelper::getCommonTag(ObjectStaticValues::className()), |
|
|
|
|
286
|
|
|
] |
287
|
|
|
])); |
288
|
|
|
$query->andWhere(new Expression('`object_model_id` IN ' . $subQueryOptimisation)); |
289
|
|
|
} |
290
|
|
|
$selectedQuery = static::find() |
291
|
|
|
->select(static::tableName() . '.id') |
292
|
|
|
->asArray(true) |
293
|
|
|
->innerJoin( |
294
|
|
|
ObjectStaticValues::tableName(), |
295
|
|
|
ObjectStaticValues::tableName() . '.property_static_value_id = ' . static::tableName() . '.id' |
296
|
|
|
) |
297
|
|
|
->where([ |
298
|
|
|
'property_id' => $property_id, |
299
|
|
|
]) |
300
|
|
|
->andWhere( |
301
|
|
|
new Expression( |
302
|
|
|
ObjectStaticValues::tableName() . '.object_model_id IN (' . $query->createCommand()->getRawSql() . ')' |
303
|
|
|
) |
304
|
|
|
); |
305
|
|
|
if (false == $multiple) { |
|
|
|
|
306
|
|
|
if (isset($properties[$property_id])) { |
307
|
|
|
$selectedQuery->andWhere([self::tableName() . '.id' => $properties[$property_id]]); |
308
|
|
|
} |
309
|
|
|
} else { |
310
|
|
|
unset($properties[$property_id]); |
311
|
|
|
} |
312
|
|
|
$selected = $selectedQuery->column(); |
313
|
|
|
foreach ($allSelections as $index => $selection) { |
314
|
|
|
$allSelections[$index]['active'] = in_array($selection['id'], $selected); |
315
|
|
|
} |
316
|
|
View Code Duplication |
if (null !== $allSelections) { |
317
|
|
|
Yii::$app->cache->set( |
318
|
|
|
$cacheKey, |
319
|
|
|
$allSelections, |
320
|
|
|
0, |
321
|
|
|
new TagDependency( |
322
|
|
|
[ |
323
|
|
|
'tags' => [ |
324
|
|
|
ActiveRecordHelper::getCommonTag(PropertyStaticValues::className()), |
|
|
|
|
325
|
|
|
ActiveRecordHelper::getCommonTag(Property::className()), |
|
|
|
|
326
|
|
|
] |
327
|
|
|
|
328
|
|
|
] |
329
|
|
|
) |
330
|
|
|
); |
331
|
|
|
} |
332
|
|
|
} |
333
|
|
|
return $allSelections; |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
private static function initSubQuery($category_id, $joinCondition) |
337
|
|
|
{ |
338
|
|
|
$product = Yii::$container->get(Product::class); |
339
|
|
|
$subQuery = ObjectStaticValues::find(); |
340
|
|
|
return $subQuery |
341
|
|
|
->select(ObjectStaticValues::tableName() . '.object_model_id') |
342
|
|
|
->innerJoin( |
343
|
|
|
'{{%product_category}}', |
344
|
|
|
'{{%product_category}}.object_model_id = ' . ObjectStaticValues::tableName() . '.object_model_id' |
345
|
|
|
)->innerJoin( |
346
|
|
|
$product::tableName() . ' p', |
347
|
|
|
$joinCondition |
348
|
|
|
)->where( |
349
|
|
|
[ |
350
|
|
|
'category_id' => $category_id, |
351
|
|
|
] |
352
|
|
|
); |
353
|
|
|
} |
354
|
|
|
/** |
355
|
|
|
* Аналогично getValuesForPropertyId |
356
|
|
|
* Но identity_map не используется |
357
|
|
|
* @param int $property_id |
358
|
|
|
* @return array|mixed|\yii\db\ActiveRecord[] |
359
|
|
|
*/ |
360
|
|
|
public static function arrayOfValuesForPropertyId($property_id) |
361
|
|
|
{ |
362
|
|
|
$cacheKey = "ValuesForProperty:$property_id"; |
363
|
|
|
|
364
|
|
|
if (false === $values = Yii::$app->cache->get($cacheKey)) { |
365
|
|
|
$values = static::find()->where(['property_id' => $property_id])->orderBy( |
366
|
|
|
[ |
367
|
|
|
'sort_order' => SORT_ASC, |
368
|
|
|
'name' => SORT_ASC |
369
|
|
|
] |
370
|
|
|
)->asArray()->all(); |
371
|
|
View Code Duplication |
if (null !== $values) { |
372
|
|
|
Yii::$app->cache->set( |
373
|
|
|
$cacheKey, |
374
|
|
|
$values, |
375
|
|
|
0, |
376
|
|
|
new TagDependency( |
377
|
|
|
[ |
378
|
|
|
'tags' => [ |
379
|
|
|
ActiveRecordHelper::getCommonTag(PropertyStaticValues::className()), |
|
|
|
|
380
|
|
|
ActiveRecordHelper::getCommonTag(Property::className()), |
|
|
|
|
381
|
|
|
] |
382
|
|
|
|
383
|
|
|
] |
384
|
|
|
) |
385
|
|
|
); |
386
|
|
|
} |
387
|
|
|
} |
388
|
|
|
return $values; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
public function afterSave($insert, $changedAttributes) |
392
|
|
|
{ |
393
|
|
|
if (null !== $parent = Property::findById($this->property_id)) { |
394
|
|
|
$parent->invalidateModelCache(); |
395
|
|
|
} |
396
|
|
|
parent::afterSave($insert, $changedAttributes); |
397
|
|
|
} |
398
|
|
|
|
399
|
|
|
public function beforeDelete() |
400
|
|
|
{ |
401
|
|
|
if (null !== $parent = Property::findById($this->property_id)) { |
402
|
|
|
$parent->invalidateModelCache(); |
403
|
|
|
} |
404
|
|
|
return parent::beforeDelete(); |
405
|
|
|
} |
406
|
|
|
|
407
|
|
|
public function afterDelete() |
408
|
|
|
{ |
409
|
|
|
ObjectStaticValues::deleteAll(['property_static_value_id' => $this->id]); |
410
|
|
|
parent::afterDelete(); |
411
|
|
|
} |
412
|
|
|
} |
413
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.