Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like BackendProductController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use BackendProductController, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 33 | class BackendProductController extends BackendController |
||
| 34 | { |
||
| 35 | const EVENT_BACKEND_PRODUCT_EDIT = 'backend-product-edit'; |
||
| 36 | const EVENT_BACKEND_PRODUCT_EDIT_SAVE = 'backend-product-edit-save'; |
||
| 37 | const EVENT_BACKEND_PRODUCT_EDIT_FORM = 'backend-product-edit-form'; |
||
| 38 | const EVENT_BACKEND_PRODUCT_AFTER_SAVE = 'backend-product-after-save'; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @inheritdoc |
||
| 42 | * @return array |
||
|
|
|||
| 43 | */ |
||
| 44 | public function behaviors() |
||
| 45 | { |
||
| 46 | return [ |
||
| 47 | 'access' => [ |
||
| 48 | 'class' => AccessControl::className(), |
||
| 49 | 'rules' => [ |
||
| 50 | [ |
||
| 51 | 'allow' => true, |
||
| 52 | 'roles' => ['product manage'], |
||
| 53 | ], |
||
| 54 | ], |
||
| 55 | ], |
||
| 56 | ]; |
||
| 57 | } |
||
| 58 | |||
| 59 | /** |
||
| 60 | * @inheritdoc |
||
| 61 | * @return array |
||
| 62 | */ |
||
| 63 | public function actions() |
||
| 64 | { |
||
| 65 | return [ |
||
| 66 | 'getTree' => [ |
||
| 67 | 'class' => AdjacencyFullTreeDataAction::className(), |
||
| 68 | 'class_name' => Category::className(), |
||
| 69 | 'model_label_attribute' => 'name', |
||
| 70 | ], |
||
| 71 | 'getCatTree' => [ |
||
| 72 | 'class' => 'app\backend\actions\JSSelectableTreeGetTree', |
||
| 73 | 'modelName' => 'app\modules\shop\models\Category', |
||
| 74 | 'label_attribute' => 'name', |
||
| 75 | 'vary_by_type_attribute' => null, |
||
| 76 | ], |
||
| 77 | 'addImage' => [ |
||
| 78 | 'class' => AddImageAction::className(), |
||
| 79 | ], |
||
| 80 | 'upload' => [ |
||
| 81 | 'class' => UploadAction::className(), |
||
| 82 | 'upload' => 'theme/resources/product-images', |
||
| 83 | ], |
||
| 84 | 'remove' => [ |
||
| 85 | 'class' => RemoveAction::className(), |
||
| 86 | 'uploadDir' => 'theme/resources/product-images', |
||
| 87 | ], |
||
| 88 | 'save-info' => [ |
||
| 89 | 'class' => SaveInfoAction::className(), |
||
| 90 | ], |
||
| 91 | 'update-editable' => [ |
||
| 92 | 'class' => UpdateEditable::className(), |
||
| 93 | 'modelName' => Product::className(), |
||
| 94 | 'allowedAttributes' => [ |
||
| 95 | View Code Duplication | 'currency_id' => function (Product $model, $attribute) { |
|
| 96 | if ($model === null || $model->currency === null || $model->currency_id === 0) { |
||
| 97 | return null; |
||
| 98 | } |
||
| 99 | return \yii\helpers\Html::tag( |
||
| 100 | 'div', |
||
| 101 | $model->currency->name, |
||
| 102 | ['class' => $model->currency->name] |
||
| 103 | ); |
||
| 104 | }, |
||
| 105 | 'price', |
||
| 106 | 'old_price', |
||
| 107 | View Code Duplication | 'active' => function (Product $model) { |
|
| 108 | if ($model === null || $model->active === null) { |
||
| 109 | return null; |
||
| 110 | } |
||
| 111 | if ($model->active === 1) { |
||
| 112 | $label_class = 'label-success'; |
||
| 113 | $value = 'Active'; |
||
| 114 | } else { |
||
| 115 | $value = 'Inactive'; |
||
| 116 | $label_class = 'label-default'; |
||
| 117 | } |
||
| 118 | return \yii\helpers\Html::tag( |
||
| 119 | 'span', |
||
| 120 | Yii::t('app', $value), |
||
| 121 | ['class' => "label $label_class"] |
||
| 122 | ); |
||
| 123 | }, |
||
| 124 | ], |
||
| 125 | ], |
||
| 126 | 'property-handler' => [ |
||
| 127 | 'class' => PropertyHandler::className(), |
||
| 128 | 'modelName' => Product::className() |
||
| 129 | ] |
||
| 130 | ]; |
||
| 131 | } |
||
| 132 | |||
| 133 | /** |
||
| 134 | * @return string |
||
| 135 | * @throws ServerErrorHttpException |
||
| 136 | */ |
||
| 137 | public function actionIndex() |
||
| 138 | { |
||
| 139 | $searchModel = new Product(); |
||
| 140 | $params = Yii::$app->request->get(); |
||
| 141 | /** @var ActiveDataProvider $dataProvider */ |
||
| 142 | $dataProvider = $searchModel->search($params); |
||
| 143 | if (null !== $catId = Yii::$app->request->get('parent_id')) { |
||
| 144 | $dataProvider->query->leftJoin( |
||
| 145 | Object::getForClass(Product::className())->categories_table_name . ' cp', |
||
| 146 | 'cp.object_model_id=product.id' |
||
| 147 | )->andWhere('product.parent_id=0 AND cp.category_id=:cur', [':cur' => $catId]); |
||
| 148 | } |
||
| 149 | return $this->render( |
||
| 150 | 'index', |
||
| 151 | [ |
||
| 152 | 'dataProvider' => $dataProvider, |
||
| 153 | 'searchModel' => $searchModel, |
||
| 154 | ] |
||
| 155 | ); |
||
| 156 | } |
||
| 157 | |||
| 158 | /** |
||
| 159 | * @param null $id |
||
| 160 | * @return string|\yii\web\Response |
||
| 161 | * @throws NotFoundHttpException |
||
| 162 | * @throws ServerErrorHttpException |
||
| 163 | * @throws \Exception |
||
| 164 | * @throws \yii\base\InvalidRouteException |
||
| 165 | */ |
||
| 166 | public function actionEdit($id = null) |
||
| 167 | { |
||
| 168 | /* |
||
| 169 | * @todo Продумать механизм сохранения изображений для нового продукта. |
||
| 170 | * Сейчас для нового продукта скрывается форма добавления изображений. |
||
| 171 | */ |
||
| 172 | if (null === $object = Object::getForClass(Product::className())) { |
||
| 173 | throw new ServerErrorHttpException; |
||
| 174 | } |
||
| 175 | |||
| 176 | /** @var null|Product|HasProperties|\devgroup\TagDependencyHelper\ActiveRecordHelper $model */ |
||
| 177 | $model = null; |
||
| 178 | $parent = null; |
||
| 179 | if (null === $id) { |
||
| 180 | $model = new Product(); |
||
| 181 | $model->loadDefaultValues(); |
||
| 182 | $parent_id = Yii::$app->request->get('owner_id', 0); |
||
| 183 | View Code Duplication | if (0 !== intval($parent_id) && null !== Product::findById($parent_id)) { |
|
| 184 | $model->parent_id = $parent_id; |
||
| 185 | } |
||
| 186 | $model->measure_id = $this->module->defaultMeasureId; |
||
| 187 | } else { |
||
| 188 | $model = Product::findById($id, null); |
||
| 189 | View Code Duplication | if ((null !== $model) && ($model->parent_id > 0)) { |
|
| 190 | $parent = Product::findById($model->parent_id, null); |
||
| 191 | } |
||
| 192 | } |
||
| 193 | |||
| 194 | if (null === $model) { |
||
| 195 | throw new NotFoundHttpException(); |
||
| 196 | } |
||
| 197 | |||
| 198 | $model->loadRelatedProductsArray(); |
||
| 199 | |||
| 200 | $event = new BackendEntityEditEvent($model); |
||
| 201 | $this->trigger(self::EVENT_BACKEND_PRODUCT_EDIT, $event); |
||
| 202 | |||
| 203 | $post = \Yii::$app->request->post(); |
||
| 204 | |||
| 205 | if ($event->isValid && $model->load($post)) { |
||
| 206 | $saveStateEvent = new BackendEntityEditEvent($model); |
||
| 207 | $this->trigger(self::EVENT_BACKEND_PRODUCT_EDIT_SAVE, $saveStateEvent); |
||
| 208 | |||
| 209 | if ($model->validate()) { |
||
| 210 | if (isset($post['GeneratePropertyValue'])) { |
||
| 211 | $generateValues = $post['GeneratePropertyValue']; |
||
| 212 | } else { |
||
| 213 | $generateValues = []; |
||
| 214 | } |
||
| 215 | if (isset($post['PropertyGroup'])) { |
||
| 216 | $model->option_generate = Json::encode( |
||
| 217 | [ |
||
| 218 | 'group' => $post['PropertyGroup']['id'], |
||
| 219 | 'values' => $generateValues |
||
| 220 | ] |
||
| 221 | ); |
||
| 222 | } else { |
||
| 223 | $model->option_generate = ''; |
||
| 224 | } |
||
| 225 | |||
| 226 | $save_result = $model->save(); |
||
| 227 | $model->saveProperties($post); |
||
| 228 | $model->saveRelatedProducts(); |
||
| 229 | |||
| 230 | View Code Duplication | if (null !== $view_object = ViewObject::getByModel($model, true)) { |
|
| 231 | if ($view_object->load($post, 'ViewObject')) { |
||
| 232 | if ($view_object->view_id <= 0) { |
||
| 233 | $view_object->delete(); |
||
| 234 | } else { |
||
| 235 | $view_object->save(); |
||
| 236 | } |
||
| 237 | } |
||
| 238 | } |
||
| 239 | |||
| 240 | if ($save_result) { |
||
| 241 | $modelAfterSaveEvent = new BackendEntityEditEvent($model); |
||
| 242 | $this->trigger(self::EVENT_BACKEND_PRODUCT_AFTER_SAVE, $modelAfterSaveEvent); |
||
| 243 | |||
| 244 | $categories = isset($post['Product']['categories']) ? $post['Product']['categories'] : []; |
||
| 245 | |||
| 246 | $model->saveCategoriesBindings($categories); |
||
| 247 | |||
| 248 | $this->runAction('save-info', ['model_id'=>$model->id]); |
||
| 249 | $model->invalidateTags(); |
||
| 250 | |||
| 251 | |||
| 252 | $action = Yii::$app->request->post('action', 'save'); |
||
| 253 | if (Yii::$app->request->post(HasProperties::FIELD_ADD_PROPERTY_GROUP) |
||
| 254 | || Yii::$app->request->post(HasProperties::FIELD_REMOVE_PROPERTY_GROUP)) { |
||
| 255 | $action = 'save'; |
||
| 256 | } |
||
| 257 | $returnUrl = Yii::$app->request->get('returnUrl', ['index']); |
||
| 258 | switch ($action) { |
||
| 259 | case 'next': |
||
| 260 | return $this->redirect( |
||
| 261 | [ |
||
| 262 | 'edit', |
||
| 263 | 'returnUrl' => $returnUrl, |
||
| 264 | 'parent_id' => Yii::$app->request->get('parent_id', null) |
||
| 265 | ] |
||
| 266 | ); |
||
| 267 | case 'back': |
||
| 268 | return $this->redirect($returnUrl); |
||
| 269 | default: |
||
| 270 | return $this->redirect( |
||
| 271 | Url::toRoute([ |
||
| 272 | 'edit', |
||
| 273 | 'id' => $model->id, |
||
| 274 | 'returnUrl' => $returnUrl, |
||
| 275 | 'parent_id' => $model->main_category_id |
||
| 276 | ]) |
||
| 277 | ); |
||
| 278 | } |
||
| 279 | } else { |
||
| 280 | Yii::$app->session->setFlash('error', Yii::t('app', 'Cannot save data')); |
||
| 281 | } |
||
| 282 | } else { |
||
| 283 | Yii::$app->session->setFlash('error', Yii::t('app', 'Cannot save data')); |
||
| 284 | } |
||
| 285 | } |
||
| 286 | |||
| 287 | $items = ArrayHelper::map( |
||
| 288 | Category::find()->all(), |
||
| 289 | 'id', |
||
| 290 | 'name' |
||
| 291 | ); |
||
| 292 | |||
| 293 | |||
| 294 | return $this->render( |
||
| 295 | 'product-form', |
||
| 296 | [ |
||
| 297 | 'object' => $object, |
||
| 298 | 'model' => $model, |
||
| 299 | 'items' => $items, |
||
| 300 | 'selected' => $model->getCategoryIds(), |
||
| 301 | 'parent' => $parent, |
||
| 302 | ] |
||
| 303 | ); |
||
| 304 | } |
||
| 305 | |||
| 306 | /** |
||
| 307 | * @param $id |
||
| 308 | * @throws NotFoundHttpException |
||
| 309 | * @throws \yii\db\Exception |
||
| 310 | */ |
||
| 311 | public function actionGenerate($id) |
||
| 312 | { |
||
| 313 | $post = \Yii::$app->request->post(); |
||
| 314 | if (!isset($post['GeneratePropertyValue'])) { |
||
| 315 | throw new NotFoundHttpException(); |
||
| 316 | } |
||
| 317 | $parent = Product::findById($id, null); |
||
| 318 | if ($parent === null) { |
||
| 319 | throw new NotFoundHttpException(); |
||
| 320 | } |
||
| 321 | |||
| 322 | $object = Object::getForClass(Product::className()); |
||
| 323 | $catIds = (new Query())->select('category_id')->from([$object->categories_table_name])->where( |
||
| 324 | 'object_model_id = :id', |
||
| 325 | [':id' => $id] |
||
| 326 | )->orderBy(['sort_order' => SORT_ASC, 'id' => SORT_ASC])->column(); |
||
| 327 | |||
| 328 | |||
| 329 | if (isset($post['GeneratePropertyValue'])) { |
||
| 330 | $generateValues = $post['GeneratePropertyValue']; |
||
| 331 | $post[HasProperties::FIELD_ADD_PROPERTY_GROUP]['Product'] = $post['PropertyGroup']['id']; |
||
| 332 | } else { |
||
| 333 | $generateValues = []; |
||
| 334 | } |
||
| 335 | $parent->option_generate = Json::encode( |
||
| 336 | [ |
||
| 337 | 'group' => $post['PropertyGroup']['id'], |
||
| 338 | 'values' => $generateValues |
||
| 339 | ] |
||
| 340 | ); |
||
| 341 | $parent->save(); |
||
| 342 | |||
| 343 | $postProperty = []; |
||
| 344 | foreach ($post['GeneratePropertyValue'] as $key_property => $values) { |
||
| 345 | $inner = []; |
||
| 346 | foreach ($values as $key_value => $trash) { |
||
| 347 | $inner[] = [$key_property => $key_value]; |
||
| 348 | } |
||
| 349 | $postProperty[] = $inner; |
||
| 350 | } |
||
| 351 | |||
| 352 | $optionProperty = self::generateOptions($postProperty); |
||
| 353 | |||
| 354 | foreach ($optionProperty as $option) { |
||
| 355 | /** @var Product|HasProperties $model */ |
||
| 356 | $model = new Product; |
||
| 357 | $model->load($post); |
||
| 358 | |||
| 359 | $model->parent_id = $parent->id; |
||
| 360 | $nameAppend = []; |
||
| 361 | $slugAppend = []; |
||
| 362 | $tempPost = []; |
||
| 363 | |||
| 364 | // @todo something |
||
| 365 | foreach ($option as $optionValue) { |
||
| 366 | $valueModels = []; |
||
| 367 | foreach ($optionValue as $propertyKey => $propertyValue) { |
||
| 368 | if (false === in_array($propertyKey, $valueModels)) { |
||
| 369 | /** @var $propertyStaticValues PropertyStaticValues */ |
||
| 370 | $propertyStaticValues = PropertyStaticValues::findOne($propertyValue); |
||
| 371 | $key = $propertyStaticValues->property->key; |
||
| 372 | $tempPost[$key] = $propertyValue; |
||
| 373 | $valueModels[] = $propertyKey; |
||
| 374 | $nameAppend[] = $propertyStaticValues->name; |
||
| 375 | $slugAppend[] = $propertyStaticValues->id; |
||
| 376 | } |
||
| 377 | } |
||
| 378 | } |
||
| 379 | $model->measure_id = $parent->measure_id; |
||
| 380 | $model->name = $parent->name . ' (' . implode(', ', $nameAppend) . ')'; |
||
| 381 | $model->slug = $parent->slug . '-' . implode('-', $slugAppend); |
||
| 382 | $save_model = $model->save(); |
||
| 383 | if ($save_model) { |
||
| 384 | foreach (array_keys($parent->propertyGroups) as $key) { |
||
| 385 | $opg = new ObjectPropertyGroup(); |
||
| 386 | $opg->attributes = [ |
||
| 387 | 'object_id' => $parent->object->id, |
||
| 388 | 'object_model_id' => $model->id, |
||
| 389 | 'property_group_id' => $key, |
||
| 390 | ]; |
||
| 391 | $opg->save(); |
||
| 392 | } |
||
| 393 | $newValues = array_merge($parent->abstractModel->attributes, $tempPost); |
||
| 394 | $model->saveProperties([ |
||
| 395 | 'Properties_Product_' . $model->id => $newValues, |
||
| 396 | ]); |
||
| 397 | $add = []; |
||
| 398 | foreach ($catIds as $value) { |
||
| 399 | $add[] = [ |
||
| 400 | $value, |
||
| 401 | $model->id |
||
| 402 | ]; |
||
| 403 | } |
||
| 404 | View Code Duplication | if (!empty($add)) { |
|
| 405 | Yii::$app->db->createCommand()->batchInsert( |
||
| 406 | $object->categories_table_name, |
||
| 407 | ['category_id', 'object_model_id'], |
||
| 408 | $add |
||
| 409 | )->execute(); |
||
| 410 | } |
||
| 411 | |||
| 412 | $params = $parent->images; |
||
| 413 | View Code Duplication | if (!empty($params)) { |
|
| 414 | $rows = []; |
||
| 415 | foreach ($params as $param) { |
||
| 416 | $rows[] = [ |
||
| 417 | $param['object_id'], |
||
| 418 | $model->id, |
||
| 419 | $param['filename'], |
||
| 420 | $param['image_title'], |
||
| 421 | $param['image_alt'], |
||
| 422 | $param['sort_order'], |
||
| 423 | ]; |
||
| 424 | } |
||
| 425 | |||
| 426 | Yii::$app->db->createCommand()->batchInsert( |
||
| 427 | Image::tableName(), |
||
| 428 | [ |
||
| 429 | 'object_id', |
||
| 430 | 'object_model_id', |
||
| 431 | 'filename', |
||
| 432 | 'image_title', |
||
| 433 | 'image_alt', |
||
| 434 | 'sort_order', |
||
| 435 | ], |
||
| 436 | $rows |
||
| 437 | )->execute(); |
||
| 438 | |||
| 439 | } |
||
| 440 | } |
||
| 441 | } |
||
| 442 | } |
||
| 443 | |||
| 444 | /** |
||
| 445 | * Clone product action. |
||
| 446 | * @param integer $id |
||
| 447 | * @throws \yii\web\NotFoundHttpException |
||
| 448 | */ |
||
| 449 | public function actionClone($id, $returnUrl = ['index']) |
||
| 450 | { |
||
| 451 | /** @var Product|HasProperties $model */ |
||
| 452 | $model = Product::findOne($id); |
||
| 453 | if ($model === null) { |
||
| 454 | throw new NotFoundHttpException; |
||
| 455 | } |
||
| 456 | |||
| 457 | /** @var Product|HasProperties $newModel */ |
||
| 458 | $newModel = new Product; |
||
| 459 | $newModel->setAttributes($model->attributes, false); |
||
| 460 | $time = time(); |
||
| 461 | $newModel->name .= ' (copy ' . date('Y-m-d h:i:s', $time) . ')'; |
||
| 462 | $newModel->slug .= '-copy-' . date('Ymdhis', $time); |
||
| 463 | $newModel->id = null; |
||
| 464 | View Code Duplication | if ($newModel->validate() === false) { |
|
| 465 | $newModel->slug = substr(uniqid() . "-" . $model->slug, 0, 80); |
||
| 466 | } |
||
| 467 | if ($newModel->save()) { |
||
| 468 | $object = Object::getForClass(get_class($newModel)); |
||
| 469 | // save categories |
||
| 470 | $categoriesTableName = Object::getForClass(Product::className())->categories_table_name; |
||
| 471 | $query = new Query(); |
||
| 472 | $params = $query->select(['category_id', 'sort_order'])->from($categoriesTableName)->where( |
||
| 473 | ['object_model_id' => $model->id] |
||
| 474 | )->all(); |
||
| 475 | if (!empty($params)) { |
||
| 476 | $rows = []; |
||
| 477 | foreach ($params as $param) { |
||
| 478 | $rows[] = [ |
||
| 479 | $param['category_id'], |
||
| 480 | $newModel->id, |
||
| 481 | $param['sort_order'], |
||
| 482 | ]; |
||
| 483 | } |
||
| 484 | Yii::$app->db->createCommand()->batchInsert( |
||
| 485 | $categoriesTableName, |
||
| 486 | [ |
||
| 487 | 'category_id', |
||
| 488 | 'object_model_id', |
||
| 489 | 'sort_order' |
||
| 490 | ], |
||
| 491 | $rows |
||
| 492 | )->execute(); |
||
| 493 | } |
||
| 494 | |||
| 495 | // save images bindings |
||
| 496 | $params = $query->select( |
||
| 497 | ['object_id', 'filename', 'image_title', 'image_alt', 'sort_order'] |
||
| 498 | )->from(Image::tableName())->where( |
||
| 499 | [ |
||
| 500 | 'object_id' => $object->id, |
||
| 501 | 'object_model_id' => $model->id |
||
| 502 | ] |
||
| 503 | )->all(); |
||
| 504 | View Code Duplication | if (!empty($params)) { |
|
| 505 | $rows = []; |
||
| 506 | foreach ($params as $param) { |
||
| 507 | $rows[] = [ |
||
| 508 | $param['object_id'], |
||
| 509 | $newModel->id, |
||
| 510 | $param['filename'], |
||
| 511 | $param['image_title'], |
||
| 512 | $param['image_alt'], |
||
| 513 | $param['sort_order'], |
||
| 514 | ]; |
||
| 515 | } |
||
| 516 | Yii::$app->db->createCommand()->batchInsert( |
||
| 517 | Image::tableName(), |
||
| 518 | [ |
||
| 519 | 'object_id', |
||
| 520 | 'object_model_id', |
||
| 521 | 'filename', |
||
| 522 | 'image_title', |
||
| 523 | 'image_alt', |
||
| 524 | 'sort_order', |
||
| 525 | ], |
||
| 526 | $rows |
||
| 527 | )->execute(); |
||
| 528 | } |
||
| 529 | $newModelProps = []; |
||
| 530 | View Code Duplication | foreach (array_keys($model->propertyGroups) as $key) { |
|
| 531 | $opg = new ObjectPropertyGroup(); |
||
| 532 | $opg->attributes = [ |
||
| 533 | 'object_id' => $object->id, |
||
| 534 | 'object_model_id' => $newModel->id, |
||
| 535 | 'property_group_id' => $key, |
||
| 536 | ]; |
||
| 537 | $opg->save(); |
||
| 538 | $props = Property::getForGroupId($key); |
||
| 539 | foreach ($props as $prop) { |
||
| 540 | $propValues = $model->getPropertyValuesByPropertyId($prop->id); |
||
| 541 | if ($propValues !== null) { |
||
| 542 | foreach ($propValues->values as $val) { |
||
| 543 | $valueToSave = ArrayHelper::getValue($val, 'psv_id', $val['value']); |
||
| 544 | $newModelProps[$prop->key][] = $valueToSave; |
||
| 545 | } |
||
| 546 | } |
||
| 547 | } |
||
| 548 | } |
||
| 549 | $newModel->saveProperties( |
||
| 550 | [ |
||
| 551 | 'Properties_Product_' . $newModel->id => $newModelProps, |
||
| 552 | ] |
||
| 553 | ); |
||
| 554 | Yii::$app->session->setFlash('success', Yii::t('app', 'Product has been cloned successfully.')); |
||
| 555 | $this->redirect(['edit', 'id' => $newModel->id, 'returnUrl' => $returnUrl]); |
||
| 556 | } |
||
| 557 | } |
||
| 558 | |||
| 559 | /** |
||
| 560 | * @param $id |
||
| 561 | * @return \yii\web\Response |
||
| 562 | * @throws NotFoundHttpException |
||
| 563 | * @throws \Exception |
||
| 564 | */ |
||
| 565 | public function actionDelete($id) |
||
| 566 | { |
||
| 567 | /** @var Product $model */ |
||
| 568 | if (null === $model = Product::findOne($id)) { |
||
| 569 | throw new NotFoundHttpException; |
||
| 570 | } |
||
| 571 | |||
| 572 | if (Yii::$app->request->get('returnUrl') !== null) { |
||
| 573 | $redirect = Yii::$app->request->get('returnUrl'); |
||
| 574 | } elseif ($model->parent_id == 0) { |
||
| 575 | $redirect = Url::toRoute(['index']); |
||
| 576 | } else { |
||
| 577 | $redirect = Url::toRoute(['edit', 'id' => $model->parent_id]); |
||
| 578 | } |
||
| 579 | |||
| 580 | if (!$model->delete()) { |
||
| 581 | Yii::$app->session->setFlash('info', Yii::t('app', 'The object is placed in the cart')); |
||
| 582 | } else { |
||
| 583 | Yii::$app->session->setFlash('info', Yii::t('app', 'Object has been removed')); |
||
| 584 | } |
||
| 585 | |||
| 586 | return $this->redirect($redirect); |
||
| 587 | } |
||
| 588 | |||
| 589 | /** |
||
| 590 | * @param $parent_id |
||
| 591 | * @return \yii\web\Response |
||
| 592 | * @throws \Exception |
||
| 593 | */ |
||
| 594 | public function actionRemoveAll($parent_id) |
||
| 595 | { |
||
| 596 | $items = Yii::$app->request->post('items', []); |
||
| 597 | if (!empty($items)) { |
||
| 598 | $items = Product::find()->where(['in', 'id', $items])->all(); |
||
| 599 | foreach ($items as $item) { |
||
| 600 | $item->delete(); |
||
| 601 | } |
||
| 602 | } |
||
| 603 | |||
| 604 | return $this->redirect(['index', 'parent_id' => $parent_id]); |
||
| 605 | } |
||
| 606 | |||
| 607 | /** |
||
| 608 | * @param $tableName |
||
| 609 | * @param $ids |
||
| 610 | * @param string $field |
||
| 611 | * @return bool |
||
| 612 | * @throws \yii\db\Exception |
||
| 613 | */ |
||
| 614 | View Code Duplication | public static function sortModels($tableName, $ids, $field = 'sort_order') |
|
| 615 | { |
||
| 616 | $priorities = []; |
||
| 617 | $start = 0; |
||
| 618 | $ids_sorted = $ids; |
||
| 619 | sort($ids_sorted); |
||
| 620 | foreach ($ids as $id) { |
||
| 621 | $priorities[$id] = $ids_sorted[$start++]; |
||
| 622 | } |
||
| 623 | $sql = "UPDATE " . $tableName . " SET $field = " . self::generateCase($priorities) . " WHERE id IN(" . implode( |
||
| 624 | ', ', |
||
| 625 | $ids |
||
| 626 | ) . ")"; |
||
| 627 | |||
| 628 | return Yii::$app->db->createCommand( |
||
| 629 | $sql |
||
| 630 | )->execute() > 0; |
||
| 631 | |||
| 632 | } |
||
| 633 | |||
| 634 | /** |
||
| 635 | * Рекурсивный генератор свойств для создания комплектаций. |
||
| 636 | * @param array $array Трехмерный массив вида: |
||
| 637 | * [[['{property1}' => '{value1}']], [['{property1}' => '{value2}']], [['{property2}' => '{value1}']], [['{property2}' => '{value1}']]] |
||
| 638 | * @param array $result Используется для передачи результатов внутри рекурсии |
||
| 639 | * @param integer $count Счетчик внутри рекурсии |
||
| 640 | * @return array |
||
| 641 | */ |
||
| 642 | public static function generateOptions($array, $result = [], $count = 0) |
||
| 643 | { |
||
| 644 | if (empty($result)) { |
||
| 645 | foreach ($array[$count] as $value) { |
||
| 646 | $result[] = [$value]; |
||
| 647 | } |
||
| 648 | $count++; |
||
| 649 | $arResult = self::generateOptions($array, $result, $count); |
||
| 650 | } else { |
||
| 651 | if (isset($array[$count])) { |
||
| 652 | $nextResult = []; |
||
| 653 | foreach ($array[$count] as $value) { |
||
| 654 | foreach ($result as $resValue) { |
||
| 655 | $nextResult[] = array_merge($resValue, [$value]); |
||
| 656 | } |
||
| 657 | } |
||
| 658 | $count++; |
||
| 659 | $arResult = self::generateOptions($array, $nextResult, $count); |
||
| 660 | } else { |
||
| 661 | return $result; |
||
| 662 | } |
||
| 663 | } |
||
| 664 | return $arResult; |
||
| 665 | } |
||
| 666 | |||
| 667 | /** |
||
| 668 | * @param $priorities |
||
| 669 | * @return string |
||
| 670 | */ |
||
| 671 | View Code Duplication | private static function generateCase($priorities) |
|
| 672 | { |
||
| 673 | $result = 'CASE `id`'; |
||
| 674 | foreach ($priorities as $k => $v) { |
||
| 675 | $result .= ' when "' . $k . '" then "' . $v . '"'; |
||
| 676 | } |
||
| 677 | return $result . ' END'; |
||
| 678 | } |
||
| 679 | |||
| 680 | /** |
||
| 681 | * @return array |
||
| 682 | */ |
||
| 683 | public function actionAjaxRelatedProduct() |
||
| 705 | } |
This check looks for the generic type
arrayas a return type and suggests a more specific type. This type is inferred from the actual code.