ProductController.php 14 KB
<?php
    
    namespace artbox\catalog\controllers;

    use artbox\catalog\models\Category;
    use artbox\catalog\models\ProductOptionCompl;
    use artbox\catalog\models\ProductOptionExcl;
    use artbox\catalog\models\ProductOptionGroupCompl;
    use artbox\catalog\models\ProductOptionGroupExcl;
    use artbox\catalog\models\ProductToImage;
    use Yii;
    use artbox\catalog\models\Product;
    use artbox\catalog\models\ProductSearch;
    use yii\filters\AccessControl;
    use yii\helpers\ArrayHelper;
    use yii\web\Controller;
    use yii\web\NotFoundHttpException;
    use yii\filters\VerbFilter;
    use yii\web\Response;
    
    /**
     * ProductController implements the CRUD actions for Product model.
     */
    class ProductController extends Controller
    {
        /**
         * @inheritdoc
         */
        public function getViewPath()
        {
            return '@artbox/catalog/views/product';
        }
    
        /**
         * @inheritdoc
         */
        public function behaviors()
        {
            return [
                'access' => [
                    'class' => AccessControl::className(),
                    'rules' => [
                        [
                            'actions' => [
                                'login',
                                'error',
                            ],
                            'allow'   => true,
                        ],
                        [
                            'allow' => true,
                            'roles' => [ '@' ],
                        ],
                    ],
                ],
                'verbs'  => [
                    'class'   => VerbFilter::className(),
                    'actions' => [
                        'delete'          => [ 'POST' ],
                        'delete-multiple' => [ 'POST' ],
                    ],
                ],
            ];
        }
    
        /**
         * Lists all Product models.
         *
         * @return mixed
         */
        public function actionIndex()
        {
            $searchModel = new ProductSearch();
            $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    
            return $this->render(
                'index',
                [
                    'searchModel'  => $searchModel,
                    'dataProvider' => $dataProvider,
                ]
            );
        }
    
        /**
         * Displays a single Product model.
         *
         * @param integer $id
         *
         * @return mixed
         */
        public function actionView($id)
        {
            return $this->render(
                'view',
                [
                    'model' => $this->findModel($id),
                ]
            );
        }
    
        /**
         * Creates a new Product model.
         * If creation is successful, the browser will be redirected to the 'view' page.
         *
         * @return mixed
         */
        public function actionCreate()
        {
            $model = new Product();
            $model->generateLangs();
            $groups_compl = [];
            $groups_excl = [];
            $model->categoryIds = [];
    
            $model->recommendIds = [];
            
            $model->loadMask(\Yii::$app->request);
    
            if ($model->loadWithLangs(\Yii::$app->request) && $model->saveWithLangs()) {
                $categories = Category::find()
                                      ->where([ 'id' => \Yii::$app->request->post('categoryIds') ])
                                      ->all();
        
                $model->linkMany('categories', $categories);
    
                $products = Product::find()
                                   ->where([ 'id' => \Yii::$app->request->post('recommendIds') ])
                                   ->all();
    
                $model->linkMany('recommendedProducts', $products);
    
                $model->saveImages(\Yii::$app->request->post());
                
                return $this->redirect(
                    [
                        'view',
                        'id' => $model->id,
                    ]
                );
            }
            return $this->render(
                'create',
                [
                    'model'        => $model,
                    'modelLangs'   => $model->modelLangs,
                    'groups_compl' => $groups_compl,
                    'groups_excl'  => $groups_excl,
                ]
            );
        }
    
        /**
         * Updates an existing Product model.
         * If update is successful, the browser will be redirected to the 'view' page.
         *
         * @param integer $id
         *
         * @return mixed
         */
        public function actionUpdate($id)
        {
            $model = $this->findModel($id);
            $model->generateLangs();
    
            $model->categoryIds = ArrayHelper::map(
                $model->categories,
                'id',
                'lang.title'
            );
    
            $model->recommendIds = ArrayHelper::map(
                $model->recommendedProducts,
                'id',
                'lang.title'
            );
            
            $groups_compl = [];
            $groups_excl = [];
            if (!empty($model->categories)) {
                $groups_compl = ProductOptionGroupCompl::find()
                                                       ->innerJoin(
                                                           'product_option_group_compl_to_category',
                                                           'product_option_group_compl_to_category.product_option_group_compl_id = product_option_group_compl.id'
                                                       )
                                                       ->where(
                                                           [
                                                               'product_option_group_compl_to_category.category_id' => ArrayHelper::getColumn(
                                                                   $model->categories,
                                                                   'id'
                                                               ),
                                                           ]
                                                       )
                                                       ->with('options.lang')
                                                       ->all();
                $groups_excl = ProductOptionGroupExcl::find()
                                                     ->innerJoin(
                                                         'product_option_group_excl_to_category',
                                                         'product_option_group_excl_to_category.product_option_group_excl_id = product_option_group_excl.id'
                                                     )
                                                     ->where(
                                                         [
                                                             'product_option_group_excl_to_category.category_id' => ArrayHelper::getColumn(
                                                                 $model->categories,
                                                                 'id'
                                                             ),
                                                         ]
                                                     )
                                                     ->with('options.lang')
                                                     ->all();
            }
    
            $model->loadMask(\Yii::$app->request);
            
            if ($model->loadWithLangs(\Yii::$app->request) && $model->saveWithLangs()) {
                $categories = Category::find()
                                      ->where([ 'id' => \Yii::$app->request->post('categoryIds') ])
                                      ->all();
    
                $model->linkMany('categories', $categories);
                $products = Product::find()
                                   ->where([ 'id' => \Yii::$app->request->post('recommendIds') ])
                                   ->all();
    
                $model->linkMany('recommendedProducts', $products);
//                if (!empty(\Yii::$app->request->post('Product')[ 'productOptionCompls' ])) {
//                    $options = ProductOptionCompl::findAll($model->productOptionCompls);
//                    $model->linkMany('productOptionCompls', $options);
//                } else {
//                    $model->unlinkAll('productOptionCompls', true);
//                }
//                if (!empty(\Yii::$app->request->post('Product')[ 'productOptionExcls' ])) {
//                    $options = ProductOptionExcl::findAll($model->productOptionExcls);
//                    $model->linkMany('productOptionExcls', $options);
//                } else {
//                    $model->unlinkAll('productOptionExcls', true);
//                }
    
                $model->saveImages(\Yii::$app->request->post());
                
                return $this->redirect(
                    [
                        'view',
                        'id' => $model->id,
                    ]
                );
            }
            return $this->render(
                'update',
                [
                    'model'        => $model,
                    'modelLangs'   => $model->modelLangs,
                    'groups_compl' => $groups_compl,
                    'groups_excl'  => $groups_excl,
                ]
            );
        }
    
        /**
         * Deletes an existing Product model.
         * If deletion is successful, the browser will be redirected to the 'index' page.
         *
         * @param integer $id
         *
         * @return mixed
         */
        public function actionDelete($id)
        {
            $this->findModel($id)
                 ->delete();
    
            return $this->redirect([ 'index' ]);
        }
    
        public function actionDeleteMultiple($ids)
        {
            $response = \Yii::$app->response;
            $response->format = $response::FORMAT_JSON;
            $ids = explode(',', $ids);
            if (!empty($ids)) {
                if (Product::deleteAll(
                    [
                        'id' => $ids,
                    ]
                )
                ) {
                    return [
                        'success' => true,
                    ];
                }
            }
            return [
                'failed' => true,
            ];
        }
        
        /**
         * Finds the Product model based on its primary key value.
         * If the model is not found, a 404 HTTP exception will be thrown.
         *
         * @param integer $id
         *
         * @return Product the loaded model
         * @throws NotFoundHttpException if the model cannot be found
         */
        protected function findModel($id)
        {
            if (( $model = Product::find()
                                  ->with('categories.lang')
                                  ->where([ 'id' => $id ])
                                  ->one() ) !== null
            ) {
                return $model;
            } else {
                throw new NotFoundHttpException('The requested page does not exist.');
            }
        }
    
        protected function saveImages(Product $model)
        {
            $model->unlinkAll('images', true);
    
            if (!empty(\Yii::$app->request->post('images'))) {
                if (is_array(\Yii::$app->request->post('images'))) {
                    foreach (\Yii::$app->request->post('images') as $image_id) {
                        $m = new ProductToImage();
                        $m->image_id = $image_id;
                        $m->product_id = $model->id;
                        $m->save();
                    }
                } else {
                    $m = new ProductToImage();
                    $m->image_id = \Yii::$app->request->post('images');
                    $m->product_id = $model->id;
                    $m->save();
                }
            }
        }
    
        /**
         * @param string   $q
         * @param int|null $id
         *
         * @return array
         */
        public function actionList(string $q = null, int $id = null)
        {
            \Yii::$app->response->format = Response::FORMAT_JSON;
            $out = [
                'results' => [
                    'id'   => '',
                    'text' => '',
                ],
            ];
            if (!is_null($q)) {
                $out[ 'results' ] = Product::find()
                                           ->joinWith('lang')
                                           ->select(
                                               [
                                                   'product.id as id',
                                                   'product_lang.title as text',
                                               ]
                                           )
                                           ->where(
                                               [
                                                   'like',
                                                   'product_lang.title',
                                                   $q,
                                               ]
                                           )
                                           ->andFilterWhere(
                                               [
                                                   '!=',
                                                   'product.id',
                                                   $id,
                                               ]
                                           )
                                           ->limit(20)
                                           ->asArray()
                                           ->all();
            }
            return $out;
        }
    }