[ 'class' => Index::class, 'columns' => [ 0 => [ 'type' => Index::CUSTOM_COL, 'columnConfig' => [ 'class' => ArrowsColumn::class, ], ], 'id' => [ 'type' => Index::NUMBER_COL, ], 'image' => [ 'type' => Index::PICTURE_COL ], 'title' => [ 'type' => Index::ACTION_COL, 'columnConfig' => [ 'buttonsTemplate' => '{edit}{delete}', ], ], 'categories' => [ 'type' => Index::RELATION_COL, 'columnConfig' => [ 'relationField' => 'title', ], ], 'brand' => [ 'type' => Index::RELATION_COL, 'columnConfig' => [ 'relationField' => 'title', ], ], 'variants' => [ 'type' => Index::CUSTOM_COL, 'columnConfig' => [ 'class' => VariantColumn::class, ], ], 'status' => [ 'type' => Index::STATUS_COL, ], ], 'model' => Product::class, 'hasLanguage' => true, 'enableMassDelete' => true, 'modelPrimaryKey' => 'id', 'massDeletePosition' => 1, ], 'delete' => [ 'class' => Delete::class, ], ]; } public function findModel($id) { $model = Product::find() ->with('languages') ->where([ 'id' => $id ]) ->one(); if ($model !== null) { return $model; } else { throw new NotFoundHttpException('The requested page does not exist.'); } } public function newModel() { return new Product(); } public function actionUpdate($id) { $languages = new Languages(); $product = Product::findOne($id); $product->detachBehavior('translations'); $productLangs = []; $aliases = []; $unsortedProductLangs = ProductLang::find() ->where( [ 'product_id' => $id, ] ) ->indexBy('language_id') ->all(); $unsortedAliases = Alias::find() ->where( [ 'route' => $product->getRoute(), ] ) ->indexBy('language_id') ->all(); /** * @var Variant[] $variants */ $variants = $product->getVariants() ->all(); $optionsHelper = new OptionsHelper(); $optionsHelper->loadOptions($id); $product->optionIds = $optionsHelper->getProductOptions(); foreach ($variants as $variant) { $variant->optionIds = $optionsHelper->getVariantOptions($variant->id); } foreach ($languages->getActive() as $language) { $productLangs[] = $unsortedProductLangs[ $language->id ]; $aliases[] = $unsortedAliases[ $language->id ]; } if (\Yii::$app->request->isPost && \Yii::$app->request->post('Variant')) { $post = \Yii::$app->request->post(); $product->saveImages($post); $variantCount = count($post[ 'Variant' ]); if ($product->load($post) && $product->save()) { $this->updateProductToCategory(); $hasError = false; if ($variantCount > count($variants)) { $toAdd = $variantCount - count($variants); for ($i = 0; $i < $toAdd; $i++) { $variants[] = new Variant(); } } elseif ($variantCount < count($variants)) { $toRemove = count($variants) - $variantCount; $removeArray = []; for ($i = 0; $i < $toRemove; $i++) { $removeArray[] = array_pop($variants); } } Model::loadMultiple($variants, $post); $optionsHelper->setProductOptions($product->optionIds); foreach ($variants as $variant) { /** * @var Variant $variant */ $variant->product_id = $product->id; if (!$variant->save()) { $hasError = true; } $optionsHelper->setVariantOptions($variant->id, $variant->optionIds); } $optionsHelper->save(); if (isset($removeArray)) { foreach ($removeArray as $item) { /** * @var \yii\db\ActiveRecord $item */ $item->delete(); } } Model::loadMultiple($aliases, $post); foreach ($aliases as $alias) { /** * @var Alias $alias */ if (!$alias->save()) { $hasError = true; } } Model::loadMultiple($productLangs, $post); foreach ($productLangs as $key => $productLang) { /** * @var ProductLang $productLang */ if (!$productLang->save()) { $hasError = true; } } } else { $hasError = true; } if (!$hasError) { return $this->redirect('index'); } } list($categoriesData, $categoriesOptions) = $this->getCategories(); return $this->render( 'save', [ 'languages' => $languages, 'product' => $product, 'productLangs' => $productLangs, 'aliases' => $aliases, 'categoriesOptions' => $categoriesOptions, 'categoriesData' => $categoriesData, 'brands' => ArrayHelper::map( Brand::find() ->with('language') ->where( [ 'status' => true, ] ) ->all(), 'id', 'title' ), 'options' => $optionsHelper->getData(), 'variants' => $variants, ] ); } public function actionCreate() { $languages = new Languages(); $product = new Product(); $product->detachBehavior('translations'); $productLangs = []; $aliases = []; foreach ($languages->getActive() as $language) { $productLangs[] = new ProductLang( [ 'language_id' => $language->id, ] ); $aliases[] = new Alias( [ 'language_id' => $language->id, 'entity' => Product::class, ] ); } $optionsHelper = new OptionsHelper(); if (\Yii::$app->request->isPost && \Yii::$app->request->post('Variant')) { $post = \Yii::$app->request->post(); $product->saveImages($post); $variantCount = count($post[ 'Variant' ]); if ($product->load($post) && $product->save()) { $this->updateProductToCategory(); $hasError = false; $variants = []; for ($i = 0; $i < $variantCount; $i++) { $variants[] = new Variant(); } Model::loadMultiple($variants, $post); $optionsHelper->setProductOptions($product->optionIds); foreach ($variants as $variant) { /** * @var Variant $variant */ $variant->product_id = $product->id; if (!$variant->save()) { $hasError = true; } $optionsHelper->setVariantOptions($variant->id, $variant->optionIds); } $optionsHelper->save(); Model::loadMultiple($aliases, $post); foreach ($aliases as $alias) { /** * @var Alias $alias */ $alias->route = $product->getRoute(); if (!$alias->save()) { $hasError = true; } } Model::loadMultiple($productLangs, $post); foreach ($productLangs as $key => $productLang) { /** * @var ProductLang $productLang */ $productLang->product_id = $product->id; if (!$productLang->save()) { $hasError = true; } } } else { $hasError = true; } if (!$hasError) { return $this->redirect('index'); } } list($categoriesData, $categoriesOptions) = $this->getCategories(); return $this->render( 'save', [ 'languages' => $languages, 'product' => $product, 'productLangs' => $productLangs, 'aliases' => $aliases, 'categoriesOptions' => $categoriesOptions, 'categoriesData' => $categoriesData, 'brands' => ArrayHelper::map( Brand::find() ->with('language') ->where( [ 'status' => true, ] ) ->all(), 'id', 'title' ), 'options' => ArrayHelper::map( Option::find() ->with('language') ->all(), 'id', 'title' ), 'variants' => [ ( new Variant() ) ], ] ); } /** * @param $id * * @return string * @throws \yii\web\NotFoundHttpException */ public function actionVariants($id) { $product = Product::findOne($id); if ($product) { return $this->renderPartial( '_variants_table', [ 'models' => $product->getVariants() ->all(), ] ); } else { throw new NotFoundHttpException(); } } public function actionAddVariant($key) { return $this->renderAjax( '_variant', [ 'variant' => ( new Variant() ), 'form' => ( new ActiveForm() ), 'key' => $key, 'options' => [], ] ); } public function deleteModel($id) { $product = Product::findOne($id); if ($product) { $aliases = $product->getAliases() ->all(); foreach ($aliases as $alias) { $alias->delete(); } } else { throw new NotFoundHttpException(); } $product->delete(); } public function actionSortVariant($id, $sort) { $variant = Variant::findOne($id); if ($variant) { $variant->sort = $sort; if ($variant->save()) { return $this->renderPartial( '_variants_table', [ 'models' => Variant::find() ->where( [ 'product_id' => $variant->product_id, ] ) ->all(), ] ); } else { throw new ServerErrorHttpException("Server error variant didn't saved"); } } else { throw new NotFoundHttpException('Category not found'); } } public function actionStatusVariant($id, $status) { $variant = Variant::findOne($id); if ($variant) { $variant->status = $status; if ($variant->save()) { return $this->renderPartial( '_variants_table', [ 'models' => Variant::find() ->where( [ 'product_id' => $variant->product_id, ] ) ->all(), ] ); } else { throw new ServerErrorHttpException("Server error variant didn't saved"); } } else { throw new NotFoundHttpException('Category not found'); } } public function actionUpdateAttribute($id, $field, $value) { $variant = Variant::findOne($id); if ($variant) { $variant->$field = $value; if ($variant->save()) { return $this->renderPartial( '_variants_table', [ 'models' => Variant::find() ->where( [ 'product_id' => $variant->product_id, ] ) ->all(), ] ); } else { throw new ServerErrorHttpException("Server error variant didn't saved"); } } else { throw new NotFoundHttpException('Category not found'); } } protected function getCategories() { $language_id = Language::getCurrent()->id; $flatElements = ( new Query() )->select( [ 'id', 'title', 'parent_id', 'level', ] ) ->from('category') ->leftJoin('category_lang', 'category.id = category_lang.category_id') ->where( [ 'language_id' => $language_id, ] ) ->all(); $categories = $this->buildTree($flatElements); $options = []; $data = []; $this->parseCategoriesData($categories, $data, $options); return [ $data, $options, ]; } protected function parseCategoriesData($categories, &$data, &$options) { foreach ($categories as $category) { $data[ $category[ 'id' ] ] = $category[ 'title' ]; $class = 'l' . ( intval($category[ 'level' ]) + 1 ); if (!empty($category[ 'inc' ])) { if ($category[ 'parent_id' ] !== null) { $options[ $category[ 'id' ] ] = [ 'class' => $class . ' non-leaf', 'data-pup' => $category[ 'parent_id' ], ]; } else { $options[ $category[ 'id' ] ] = [ 'class' => $class . ' non-leaf', ]; } $this->parseCategoriesData($category[ 'inc' ], $data, $options); } else { if ($category[ 'parent_id' ] !== null) { $options[ $category[ 'id' ] ] = [ 'class' => $class, 'data-pup' => $category[ 'parent_id' ], ]; } else { $options[ $category[ 'id' ] ] = [ 'class' => $class, ]; } } } } protected function buildTree(array $items) { $childs = []; foreach ($items as &$item) { $childs[ $item[ 'parent_id' ] ][] = &$item; } unset($item); foreach ($items as &$item) { if (isset($childs[ $item[ 'id' ] ])) { $item[ 'inc' ] = $childs[ $item[ 'id' ] ]; } } return $childs[ null ]; } protected function updateProductToCategory() { $command = \Yii::$app->db->createCommand( "WITH RECURSIVE search_category (id, path ) AS ( SELECT c.id, ARRAY [c.id] FROM category c UNION SELECT c.id, path || c.id FROM category c, search_category sc WHERE c.parent_id = sc.id ) UPDATE product_to_category pc SET category_mp = sc.path FROM ( SELECT distinct on (id) id, path FROM search_category ORDER BY id, array_length (path, 1) DESC) sc WHERE pc.category_id = sc.id" ); $command->execute(); } }