[ 'class' => SaveMultipleFileBehavior::className(), 'name' => 'imagesUpload', 'directory' => 'products', 'column' => 'image', 'links' => [ 'product_id' => 'id', ], 'model' => ProductImage::className(), ], 'multipleImage' => [ 'class' => MultipleImgBehavior::className(), 'links' => [ 'product_id' => 'id', ], 'conditions' => [ 'product_variant_id' => null, ], 'model' => ProductImage::className(), 'config' => [ 'caption' => 'image', 'delete_action' => '/product/manage/delete-image', 'id' => 'product_image_id', ], ], 'language' => [ 'class' => LanguageBehavior::className(), ], ]; } /** * @inheritdoc */ public static function tableName() { return 'product'; } /** * @inheritdoc */ public function rules() { return [ [ [ 'brand_id' ], 'integer', ], [ [ 'categories', 'variants', 'options', 'imagesUpload', ], 'safe', ], [ [ 'video', ], 'safe', ], [ [ 'is_top', 'is_new', 'is_discount', ], 'boolean', ], ]; } /** * @inheritdoc */ public function attributeLabels() { return [ 'id' => Yii::t('product', 'ID'), 'brand_id' => Yii::t('product', 'Brand'), 'categories' => Yii::t('product', 'Categories'), // relation behavior field 'category' => Yii::t('product', 'Category'), // relation behavior field 'image' => Yii::t('product', 'Image'), 'images' => Yii::t('product', 'Images'), 'video' => Yii::t('product', 'Video embeded'), 'variants' => Yii::t('product', 'Variants'), 'is_top' => Yii::t('product', 'Is top'), 'is_new' => Yii::t('product', 'Is new'), 'is_discount' => Yii::t('product', 'Is promo'), ]; } /** * @return \yii\db\ActiveQuery */ public function getBrand() { return $this->hasOne(Brand::className(), [ 'id' => 'brand_id' ]); } /** * @return \yii\db\ActiveQuery */ public function getVariant() { return $this->hasOne(ProductVariant::className(), [ 'product_id' => 'id' ]); } /** * @return \yii\db\ActiveQuery */ public function getEnabledVariant() { return $this->hasOne(ProductVariant::className(), [ 'product_id' => 'id' ]) ->andOnCondition( [ '!=', ProductVariant::tableName() . '.stock', 0, ] ); } public function getVariantPrice() { return $this->variant->price; } public function getEnabledVariantPrice() { return $this->enabledVariants[ 0 ]->price; } /** * @return \yii\db\ActiveQuery */ public function getVariants() { return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ]); } public function getEnabledVariants() { return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ]) ->andOnCondition( [ '!=', ProductVariant::tableName() . '.stock', 0, ] ) ->joinWith('image'); } public function setVariants($variants) { $this->variants = $variants; } public function getFullname() { return empty( $this->brand ) ? $this->lang->title : $this->brand->lang->title . ' ' . $this->lang->title; } /** * @return ActiveQuery */ public function getCategories() { return $this->hasMany(Category::className(), [ 'id' => 'category_id' ]) ->viaTable('product_category', [ 'product_id' => 'id' ]); } public function getCategoriesNames() { $result = []; foreach ($this->categories as $category) { $result[] = $category->lang->title; } return $result; } public function getVariantsWithFilters() { return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ]) ->joinWith('lang', true, 'INNER JOIN') ->with( [ 'filters', 'image', ] ); } public function getVariantsFilter() { return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ]) ->joinWith('lang') ->joinWith( [ 'options variant_options' => function ($query) { /** * @var ActiveQuery $query */ $query->joinWith([ 'langs variant_options_lang' ]) ->andWhere( [ 'variant_options_lang.language_id' => Language::getCurrent()->id ] ) ->joinWith( [ 'taxGroup variant_options_group' => function ($subquery) { /** * @var ActiveQuery $subquery */ $subquery->joinWith([ 'langs variant_options_group_lang' ]) ->andWhere( [ 'variant_options_group_lang.language_id' => Language::getCurrent( )->id, ] ); }, ] ); }, ] ); } /** * @return ActiveQuery */ public function getCategory() { return $this->hasOne(Category::className(), [ 'id' => 'category_id' ]) ->viaTable('product_category', [ 'product_id' => 'id' ]); } public function getOptions() { return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ]) ->viaTable('product_option', [ 'product_id' => 'id' ]); } /** * @return TaxGroup[] */ public function getProperties() { $groups = $options = []; foreach ($this->getOptions() ->with('lang') ->all() as $option) { /** * @var TaxOption $option */ $options[ $option->tax_group_id ][] = $option; } foreach (TaxGroup::find() ->where([ 'id' => array_keys($options) ]) ->with('lang') ->all() as $group) { /** * @var TaxGroup $group */ if (!empty( $options[ $group->id ] )) { $group->options = $options[ $group->id ]; $groups[] = $group; } } return $groups; } public function getActiveProperties($category_id) { $groups = $options = []; foreach ($this->options as $option) { $options[ $option->tax_group_id ][] = $option; } /** * @var TaxGroup[] $taxGroups */ $taxGroups = TaxGroup::find() ->joinWith('categories') ->where( [ 'tax_group.id' => array_keys($options), 'tax_group.display' => true, 'category.id' => $category_id, ] ) ->all(); foreach ($taxGroups as $group) { if (!empty( $options[ $group->id ] )) { $group->options = $options[ $group->id ]; $groups[] = $group; } } return $groups; } public function getStocks() { return $this->hasMany(Stock::className(), [ 'id' => 'product_id' ]) ->via('variants'); } public function getProductStocks() { return $this->hasMany(ProductStock::className(), [ 'product_variant_id' => 'id' ]) ->via('variants'); } public function getQuantity() { return $this->getProductStocks() ->sum('quantity'); } public function afterSave($insert, $changedAttributes) { parent::afterSave($insert, $changedAttributes); if (!empty( $this->categories )) { $categories = Category::findAll($this->categories); $this->unlinkAll('categories', true); foreach ($categories as $category) { $this->link('categories', $category); } } if (!empty( $this->options )) { $options = TaxOption::findAll($this->options); $this->unlinkAll('options', true); foreach ($options as $option) { $this->link('options', $option); } } if (!empty( $this->variants )) { $todel = []; foreach ($this->variants ? : [] as $_variant) { /** * @var ProductVariant $_variant */ $todel[ $_variant->id ] = $_variant->id; } foreach ($this->variants as $_variant) { if (!is_array($_variant)) { return; } if (!empty( $_variant[ 'id' ] )) { unset( $todel[ $_variant[ 'id' ] ] ); $model = ProductVariant::findOne($_variant[ 'id' ]); } else { $model = new ProductVariant(); } $_variant[ 'product_id' ] = $this->id; $model->load([ 'ProductVariant' => $_variant ]); $model->product_id = $this->id; $model->save(); } if (!empty( $todel )) { ProductVariant::deleteAll([ 'id' => $todel ]); } } } public function recalculateRating() { /** * @var ProductToRating $averageRating */ $average = $this->getComments() ->joinWith('rating') ->select([ 'average' => 'avg(artbox_comment_rating.value)::float' ]) ->scalar(); if (!$average) { $average = 0; } $averageRating = $this->averageRating; if (!empty( $averageRating )) { $averageRating->value = $average; } else { $averageRating = new ProductToRating( [ 'product_id' => $this->id, 'value' => $average, ] ); } if ($averageRating->save()) { return true; } else { return false; } } public function getComments() { return $this->hasMany(CommentModel::className(), [ 'entity_id' => 'id' ]) ->where( [ 'artbox_comment.entity' => self::className(), 'artbox_comment.status' => CommentModel::STATUS_ACTIVE, 'artbox_comment.artbox_comment_pid' => null, ] ); } public function getAverageRating() { return $this->hasOne(ProductToRating::className(), [ 'product_id' => 'id' ]); } public function getTaxGroupsByLevel($level) { $categories = ArrayHelper::getColumn($this->categories, 'id'); return TaxGroup::find() ->distinct() ->innerJoin( 'tax_group_to_category', 'tax_group_to_category.tax_group_id = tax_group.id' ) ->andWhere([ 'tax_group_to_category.category_id' => $categories ]) ->andWhere([ 'level' => $level ]); } public function setCategories($values) { $this->categories = $values; } public function setOptions($values) { $this->options = $values; } public function getFilters() { return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ]) ->viaTable('product_option', [ 'product_id' => 'id' ]) ->joinWith('taxGroup.lang', true, 'INNER JOIN') ->joinWith('lang', true, 'INNER JOIN'); } }