Commit af036678130d7605d53d59b12b79146c02a911cc

Authored by Yarik
1 parent b569ac34

Image behaviors

backend/controllers/ProjectController.php
... ... @@ -92,16 +92,7 @@
92 92 $model->generateLangs();
93 93 if($model->load(Yii::$app->request->post())) {
94 94 $model->loadLangs(\Yii::$app->request);
95   - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');
96 95 if($model->save() && $model->transactionStatus) {
97   - if($model->imagesUpload && ( ( $images = $model->imagesUpload() ) !== false )) {
98   - foreach($images as $image) {
99   - $imageModel = new ProjectImage();
100   - $imageModel->project_id = $model->project_id;
101   - $imageModel->image = $image;
102   - $imageModel->save();
103   - }
104   - }
105 96 return $this->redirect([
106 97 'view',
107 98 'id' => $model->project_id,
... ... @@ -128,16 +119,7 @@
128 119 $model->generateLangs();
129 120 if($model->load(Yii::$app->request->post())) {
130 121 $model->loadLangs(\Yii::$app->request);
131   - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');
132 122 if($model->save() && $model->transactionStatus) {
133   - if($model->imagesUpload && ( ( $images = $model->imagesUpload() ) !== false )) {
134   - foreach($images as $image) {
135   - $imageModel = new ProjectImage();
136   - $imageModel->project_id = $model->project_id;
137   - $imageModel->image = $image;
138   - $imageModel->save();
139   - }
140   - }
141 123 return $this->redirect([
142 124 'view',
143 125 'id' => $model->project_id,
... ...
common/behaviors/ImageBehavior.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace common\behaviors;
  4 +
  5 + use yii\base\Behavior;
  6 + use yii\base\Event;
  7 + use yii\db\ActiveRecord;
  8 +
  9 + /**
  10 + * Class ImageBehavior
  11 + * @package common\behaviors
  12 + */
  13 + class ImageBehavior extends Behavior
  14 + {
  15 +
  16 + /**
  17 + * @var string column where file name is stored
  18 + */
  19 + public $link;
  20 +
  21 + /**
  22 + * @var string directory name
  23 + */
  24 + public $directory;
  25 +
  26 + /**
  27 + * @inheritdoc
  28 + */
  29 + public function events()
  30 + {
  31 + return [
  32 + ActiveRecord::EVENT_BEFORE_DELETE => 'beforeDelete',
  33 + ];
  34 + }
  35 +
  36 + /**
  37 + * @param Event $event
  38 + */
  39 + public function beforeDelete($event)
  40 + {
  41 + $file = $this->getImageFile();
  42 + if(file_exists($file)) {
  43 + unlink($file);
  44 + }
  45 + }
  46 +
  47 + /**
  48 + * Get image file path
  49 + *
  50 + * @return null|string
  51 + */
  52 + public function getImageFile()
  53 + {
  54 + $link = $this->link;
  55 + return empty( $this->owner->$link ) ? NULL : \Yii::getAlias('@storage/' . $this->directory . '/' . $this->owner->$link);
  56 + }
  57 +
  58 + /**
  59 + * Get image file url
  60 + *
  61 + * @return null|string
  62 + */
  63 + public function getImageUrl()
  64 + {
  65 + $link = $this->link;
  66 + return empty( $this->owner->$link ) ? NULL : '/storage/' . $this->directory . '/' . $this->owner->$link;
  67 + }
  68 + }
0 69 \ No newline at end of file
... ...
common/behaviors/MultipleImgBehavior.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace common\behaviors;
  4 +
  5 + use common\components\artboximage\ArtboxImageHelper;
  6 + use yii\base\Behavior;
  7 + use yii\db\ActiveRecord;
  8 + use yii\helpers\Url;
  9 +
  10 + /**
  11 + * Class MultipleImgBehavior
  12 + * @todo Write validation
  13 + * @property ActiveRecord $owner
  14 + * @property ActiveRecord $image
  15 + * @property ActiveRecord[] $images
  16 + * @package common\behaviors
  17 + */
  18 + class MultipleImgBehavior extends Behavior
  19 + {
  20 +
  21 + /**
  22 + * key - $model foreign key, value - $owner link key (usual ID)
  23 + * @var array
  24 + */
  25 + public $links = [];
  26 +
  27 + /**
  28 + * Full namespaced image model
  29 + * @var string
  30 + */
  31 + public $model;
  32 +
  33 + /**
  34 + * Image config array:
  35 + * 'caption' - $model caption attribute
  36 + * 'delete_action' - url to image delete action, will be passed as first argument to
  37 + * Url::to();
  38 + * 'id' - $model primary key
  39 + * @var array
  40 + */
  41 + public $config = [];
  42 +
  43 + /**
  44 + * One image query
  45 + *
  46 + * @return \yii\db\ActiveQuery
  47 + */
  48 + public function getImage()
  49 + {
  50 + /**
  51 + * @var ActiveRecord $owner
  52 + */
  53 + $owner = $this->owner;
  54 + return $owner->hasOne($this->model, $this->links);
  55 + }
  56 +
  57 + /**
  58 + * All images query
  59 + *
  60 + * @return \yii\db\ActiveQuery
  61 + */
  62 + public function getImages()
  63 + {
  64 + /**
  65 + * @var ActiveRecord $owner
  66 + */
  67 + $owner = $this->owner;
  68 + return $owner->hasMany($this->model, $this->links);
  69 + }
  70 +
  71 + /**
  72 + * Get images config array for FileInput
  73 + *
  74 + * @return array
  75 + */
  76 + public function getImagesConfig()
  77 + {
  78 + $op = [];
  79 + $images = $this->getImages()->all();
  80 + $config = $this->config;
  81 + if(!isset( $config[ 'id' ] )) {
  82 + return $op;
  83 + }
  84 + foreach($images as $image) {
  85 + $op[] = [
  86 + 'caption' => ( isset( $config[ 'caption' ] ) ) ? $image->{$config[ 'caption' ]} : '',
  87 + 'url' => ( isset( $config[ 'delete_action' ] ) ) ? Url::to([
  88 + $config[ 'delete_action' ],
  89 + 'id' => $image->{$config[ 'id' ]},
  90 + ]) : '',
  91 + 'key' => $image->{$config[ 'id' ]},
  92 + 'extra' => [
  93 + 'id' => $image->{$config[ 'id' ]},
  94 + ],
  95 + ];
  96 + }
  97 + return $op;
  98 + }
  99 +
  100 + /**
  101 + * Get images HTML
  102 + *
  103 + * @param string $preset
  104 + *
  105 + * @return array
  106 + */
  107 + public function getImagesHTML($preset = 'admin_thumb')
  108 + {
  109 + $op = [];
  110 + $images = $this->getImages()->all();
  111 + foreach($images as $image) {
  112 + $op[] = ArtboxImageHelper::getImage($image->imageUrl, $preset);
  113 + }
  114 + return $op;
  115 + }
  116 + }
0 117 \ No newline at end of file
... ...
common/behaviors/SaveImgBehavior.php
... ... @@ -6,6 +6,7 @@
6 6 use yii\base\ModelEvent;
7 7 use yii\db\ActiveRecord;
8 8 use yii\web\UploadedFile;
  9 +
9 10 /**
10 11 * Class Save Image Behavior
11 12 * @property ActiveRecord $owner
... ... @@ -15,6 +16,7 @@
15 16 {
16 17  
17 18 public $fields;
  19 +
18 20 public $is_language = false;
19 21  
20 22 public function events()
... ... @@ -24,25 +26,26 @@
24 26 ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
25 27 ];
26 28 }
27   -
  29 +
28 30 /**
29 31 * @param ModelEvent $event
30 32 */
31   - public function beforeSave($event) {
32   - foreach($this->fields as $field){
33   - $field_name = $field['name'];
  33 + public function beforeSave($event)
  34 + {
  35 + foreach($this->fields as $field) {
  36 + $field_name = $field[ 'name' ];
34 37 $name = $field_name;
35 38 if($this->is_language) {
36   - $name = '['.$this->owner->language_id.']'.$name;
  39 + $name = '[' . $this->owner->language_id . ']' . $name;
37 40 }
38   -
  41 +
39 42 $image = UploadedFile::getInstance($this->owner, $name);
40 43  
41   - if(empty($image) && $event->name == ActiveRecord::EVENT_BEFORE_UPDATE) {
  44 + if(empty( $image ) && $event->name == ActiveRecord::EVENT_BEFORE_UPDATE) {
42 45 $this->owner->$field_name = $this->owner->getOldAttribute($field_name);
43   - } elseif(!empty($image)) {
44   - $imgDir = \Yii::getAlias('@storage/'.$field['directory'].'/');
45   -
  46 + } elseif(!empty( $image )) {
  47 + $imgDir = \Yii::getAlias('@storage/' . $field[ 'directory' ] . '/');
  48 +
46 49 if(!is_dir($imgDir)) {
47 50 mkdir($imgDir, 0755, true);
48 51 }
... ... @@ -50,28 +53,43 @@
50 53 $baseName = $image->baseName;
51 54  
52 55 $iteration = 0;
53   - $file_name = $imgDir.$baseName.'.'.$image->extension;
  56 + $file_name = $imgDir . $baseName . '.' . $image->extension;
54 57 while(file_exists($file_name)) {
55   - $baseName = $image->baseName.'_'.++$iteration;
56   - $file_name = $imgDir.$baseName.'.'.$image->extension;
  58 + $baseName = $image->baseName . '_' . ++$iteration;
  59 + $file_name = $imgDir . $baseName . '.' . $image->extension;
57 60 }
58   - unset($iteration);
  61 + unset( $iteration );
59 62  
60   - $this->owner->$field_name = $baseName.'.'.$image->extension;
  63 + $this->owner->$field_name = $baseName . '.' . $image->extension;
61 64  
62 65 $image->saveAs($file_name);
63 66 }
64 67 }
65 68 }
66   -
67   - public function getImageFile($image = 'image') {
68   - return empty($this->owner->$image) ? null : '/storage/'.$this->fields[0]['directory'].'/'. $this->owner->$image;
69   - }
70 69  
71   - public function getImageUrl($image = 'image') {
72   - return empty($this->owner->$image) ? null : '/storage/'.$this->fields[0]['directory'].'/'. $this->owner->$image;
  70 + /**
  71 + * @param int $field
  72 + *
  73 + * @return null|string
  74 + */
  75 + public function getImageFile($field = 0)
  76 + {
  77 + $fieldset = $this->fields[ $field ];
  78 + $name = $fieldset[ 'name' ];
  79 + $directory = $fieldset[ 'directory' ];
  80 + return empty( $this->owner->$name ) ? NULL : '/storage/' . $directory . '/' . $this->owner->$name;
73 81 }
74 82  
75   -
76   -
  83 + /**
  84 + * @param int $field
  85 + *
  86 + * @return null|string
  87 + */
  88 + public function getImageUrl($field = 0)
  89 + {
  90 + $fieldset = $this->fields[ $field ];
  91 + $name = $fieldset[ 'name' ];
  92 + $directory = $fieldset[ 'directory' ];
  93 + return empty( $this->owner->$name ) ? NULL : '/storage/' . $directory . '/' . $this->owner->$name;
  94 + }
77 95 }
78 96 \ No newline at end of file
... ...
common/behaviors/SaveMultipleFileBehavior.php 0 → 100644
  1 +<?php
  2 +
  3 + namespace common\behaviors;
  4 +
  5 + use yii\base\Behavior;
  6 + use yii\base\Event;
  7 + use yii\db\ActiveRecord;
  8 + use yii\web\UploadedFile;
  9 +
  10 + /**
  11 + * Class SaveMultipleFileBehavior
  12 + *
  13 + * @todo Write validators
  14 + *
  15 + * @package common\behaviors
  16 + */
  17 + class SaveMultipleFileBehavior extends Behavior
  18 + {
  19 +
  20 + /**
  21 + * $owner attribute to write files
  22 + * @var string
  23 + */
  24 + public $name;
  25 +
  26 + /**
  27 + * Directory to store files
  28 + * @var string
  29 + */
  30 + public $directory;
  31 +
  32 + /**
  33 + * Column in $model where to store filename
  34 + * @var string
  35 + */
  36 + public $column;
  37 +
  38 + /**
  39 + * key - owner link attribute (usual ID), value - $model link attribute
  40 + * @var array
  41 + */
  42 + public $links = [];
  43 +
  44 + /**
  45 + * Full namespaced classname of file table
  46 + * @var string
  47 + */
  48 + public $model;
  49 +
  50 + public function events()
  51 + {
  52 + return [
  53 + ActiveRecord::EVENT_AFTER_UPDATE => 'downloadFiles',
  54 + ActiveRecord::EVENT_AFTER_INSERT => 'downloadFiles',
  55 + ];
  56 + }
  57 +
  58 + /**
  59 + * Save files to file table
  60 + *
  61 + * @param Event $event
  62 + */
  63 + public function downloadFiles($event)
  64 + {
  65 + /**
  66 + * @var ActiveRecord $owner
  67 + */
  68 + $owner = $this->owner;
  69 + $name = $this->name;
  70 + $owner->$name = UploadedFile::getInstances($owner, $name);
  71 + if(!empty( $files = $this->filesUpload() )) {
  72 + $model = $this->model;
  73 + $links = $this->links;
  74 + $column = $this->column;
  75 + foreach($files as $file) {
  76 + /**
  77 + * @var ActiveRecord $fileModel
  78 + */
  79 + $fileModel = new $model();
  80 + foreach($links as $link_owner => $link) {
  81 + $fileModel->$link = $owner->$link_owner;
  82 + }
  83 + $fileModel->$column = $file;
  84 + $fileModel->save();
  85 + }
  86 + }
  87 + $this->detach();
  88 + }
  89 +
  90 + /**
  91 + * Save files to file system
  92 + *
  93 + * @return array
  94 + */
  95 + private function filesUpload()
  96 + {
  97 + $owner = $this->owner;
  98 + $name = $this->name;
  99 + $directory = $this->directory;
  100 + $fileDir = \Yii::getAlias('@storage/' . $directory . '/');
  101 + if(!is_dir($fileDir)) {
  102 + mkdir($fileDir, 0755, true);
  103 + }
  104 + $files = [];
  105 + /**
  106 + * @var UploadedFile $file
  107 + */
  108 + foreach($owner->$name as $file) {
  109 + $fileName = $file->baseName . '.' . $file->extension;
  110 + $i = 0;
  111 + while(file_exists(\Yii::getAlias($fileDir . $fileName))) {
  112 + $fileName = $file->baseName . '_' . ++$i . '.' . $file->extension;
  113 + }
  114 + $file->saveAs($fileDir . $fileName);
  115 + $files[] = $fileName;
  116 + }
  117 + return $files;
  118 + }
  119 + }
0 120 \ No newline at end of file
... ...
common/models/Articles.php
1 1 <?php
2 2  
3 3 namespace common\models;
4   -
5   - use common\modules\language\behaviors\TransactionBehavior;
  4 +
6 5 use common\modules\language\behaviors\LanguageBehavior;
7 6 use common\behaviors\SaveImgBehavior;
8 7 use common\modules\comment\models\CommentModel;
... ... @@ -36,8 +35,14 @@
36 35 * @method bool saveLangs()
37 36 * @method bool getTransactionStatus()
38 37 * * End language behavior *
  38 + * * From SaveImgBehavior
  39 + * @property string|null imageFile
  40 + * @property string|null imageUrl
  41 + * @method string|null getImageFile( int $field )
  42 + * @method string|null getImageUrl( int $field )
  43 + * * End SaveImgBehavior
39 44 */
40   - class Articles extends \yii\db\ActiveRecord
  45 + class Articles extends ActiveRecord
41 46 {
42 47  
43 48 /**
... ...
common/models/Project.php
... ... @@ -2,6 +2,8 @@
2 2  
3 3 namespace common\models;
4 4  
  5 + use common\behaviors\MultipleImgBehavior;
  6 + use common\behaviors\SaveMultipleFileBehavior;
5 7 use common\modules\language\behaviors\LanguageBehavior;
6 8 use common\modules\product\models\ProductVariant;
7 9 use Yii;
... ... @@ -11,13 +13,9 @@
11 13  
12 14 /**
13 15 * This is the model class for table "project".
14   - *
15 16 * @todo Refactor
16   - *
17 17 * @property integer $project_id
18 18 * @property integer $date_add
19   - * @property ProjectImage[] $images
20   - * @property ProjectImage $image
21 19 * @property array $imagesConfig
22 20 * @property ProductVariant[] $variants
23 21 * @property ProductToProject[] $productToProject
... ... @@ -41,6 +39,14 @@
41 39 * @method bool saveLangs()
42 40 * @method bool getTransactionStatus()
43 41 * * End language behavior *
  42 + * * From multipleImage behavior
  43 + * @property ProjectImage $image
  44 + * @property ProjectImage[] $images
  45 + * @method ActiveQuery getImage()
  46 + * @method ActiveQuery getImages()
  47 + * @method array getImagesConfig()
  48 + * @method array getImagesHTML( string $preset )
  49 + * * End multipleImage behavior
44 50 */
45 51 class Project extends ActiveRecord
46 52 {
... ... @@ -61,9 +67,31 @@
61 67 public function behaviors()
62 68 {
63 69 return [
64   - 'language' => [
  70 + 'language' => [
65 71 'class' => LanguageBehavior::className(),
66 72 ],
  73 + 'images' => [
  74 + 'class' => SaveMultipleFileBehavior::className(),
  75 + 'name' => 'imagesUpload',
  76 + 'directory' => 'projects',
  77 + 'column' => 'image',
  78 + 'links' => [
  79 + 'project_id' => 'project_id',
  80 + ],
  81 + 'model' => ProjectImage::className(),
  82 + ],
  83 + 'multipleImage' => [
  84 + 'class' => MultipleImgBehavior::className(),
  85 + 'links' => [
  86 + 'project_id' => 'project_id',
  87 + ],
  88 + 'model' => ProjectImage::className(),
  89 + 'config' => [
  90 + 'caption' => 'image',
  91 + 'delete_action' => '/project/delimg',
  92 + 'id' => 'project_image_id',
  93 + ],
  94 + ],
67 95 ];
68 96 }
69 97  
... ... @@ -112,74 +140,6 @@
112 140 ];
113 141 }
114 142  
115   - public function getImages()
116   - {
117   - return $this->hasMany(ProjectImage::className(), [ 'project_id' => 'project_id' ]);
118   - }
119   -
120   - public function getImage()
121   - {
122   - return $this->hasOne(ProjectImage::className(), [ 'project_id' => 'project_id' ]);
123   - }
124   -
125   - public function getImagesHTML()
126   - {
127   - $op = [];
128   - if($this->images) {
129   - foreach($this->images as $image) {
130   - $op[] = \common\components\artboximage\ArtboxImageHelper::getImage($image->imageUrl, 'admin_thumb');
131   - }
132   - }
133   - return $op;
134   - }
135   -
136   - public function getImagesConfig()
137   - {
138   - $op = [];
139   - if($this->images) {
140   - foreach($this->images as $image) {
141   - $op[] = [
142   - 'caption' => $image->image,
143   - 'width' => '120px',
144   - 'url' => \yii\helpers\Url::to([
145   - '/project/delimg',
146   - 'id' => $image->project_image_id,
147   - ]),
148   - 'key' => $image->project_image_id,
149   - 'extra' => [
150   - 'id' => $image->project_image_id,
151   - ],
152   - ];
153   - }
154   - }
155   - return $op;
156   - }
157   -
158   - public function imagesUpload()
159   - {
160   - if($this->validate()) {
161   - $images = [];
162   - foreach($this->imagesUpload as $image) {
163   - $imageName = $image->baseName . '.' . $image->extension;
164   - $i = 0;
165   - while(file_exists(\Yii::getAlias('@storage/projects/' . $imageName))) {
166   - $i++;
167   - $imageName = $image->baseName . '_' . $i . '.' . $image->extension;
168   - }
169   - $imgDir = \Yii::getAlias('@storage/projects/');
170   - if(!is_dir($imgDir)) {
171   - mkdir($imgDir, 0755, true);
172   - }
173   -
174   - $image->saveAs($imgDir . $imageName);
175   - $images[] = $imageName;
176   - }
177   - return $images;
178   - } else {
179   - return false;
180   - }
181   - }
182   -
183 143 public function getProductToProject()
184 144 {
185 145 return $this->hasMany(ProductToProject::className(), [
... ...
common/modules/product/controllers/ManageController.php
... ... @@ -8,7 +8,6 @@
8 8 use common\modules\product\models\Export;
9 9 use common\modules\product\models\Import;
10 10 use common\modules\product\models\ProductImage;
11   - use common\modules\product\models\ProductVariant;
12 11 use Yii;
13 12 use common\modules\product\models\Product;
14 13 use common\modules\product\models\ProductSearch;
... ... @@ -38,22 +37,6 @@
38 37 ];
39 38 }
40 39  
41   - public function actionDev()
42   - {
43   - foreach(ProductVariant::find()
44   - ->where([
45   - '>',
46   - 'price_old',
47   - 0,
48   - ])
49   - ->all() as $item) {
50   - if($item->price >= $item->price_old || $item->price == 0) {
51   - print $item->price . ' | ' . $item->price_old . "<br>\n";
52   - }
53   - }
54   - print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~';
55   - }
56   -
57 40 /**
58 41 * Lists all Product models.
59 42 * @return mixed
... ... @@ -92,36 +75,11 @@
92 75 {
93 76 $model = new Product();
94 77 $model->generateLangs();
95   -
96 78 $product_spec = new ProductSpec();
97 79 $product_spec->generateLangs();
98   -
99 80 if($model->load(Yii::$app->request->post())) {
100 81 $model->loadLangs(\Yii::$app->request);
101   - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');
102   - $model->certificateUpload = UploadedFile::getInstances($model, 'certificateUpload');
103   -
104 82 if($model->save() && $model->transactionStatus) {
105   -
106   - if(!empty( $model->imagesUpload ) && ( ( $images = $model->imagesUpload() ) !== false )) {
107   - foreach($images as $image) {
108   - $imageModel = new ProductImage();
109   - $imageModel->product_id = $model->product_id;
110   - $imageModel->image = $image;
111   - $imageModel->save();
112   - }
113   - }
114   -
115   - if(!empty( $model->certificateUpload ) && ( ( $certificates = $model->certificateUpload() ) !== false )) {
116   - foreach($certificates as $certificate) {
117   - $certificateModel = new ProductCertificate([
118   - 'product_id' => $model->product_id,
119   - 'link' => $certificate,
120   - ]);
121   - $certificateModel->save(false);
122   - }
123   - }
124   -
125 83 if($product_spec->load(Yii::$app->request->post())) {
126 84 $product_spec->loadLangs(\Yii::$app->request);
127 85 $product_spec->product_id = $model->product_id;
... ... @@ -168,26 +126,7 @@
168 126 $product_spec->generateLangs();
169 127 if($model->load(Yii::$app->request->post())) {
170 128 $model->loadLangs(\Yii::$app->request);
171   - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');
172   - $model->certificateUpload = UploadedFile::getInstances($model, 'certificateUpload');
173 129 if($model->save() && $model->transactionStatus) {
174   - if(!empty( $model->imagesUpload ) && ( ( $images = $model->imagesUpload() ) !== false )) {
175   - foreach($images as $image) {
176   - $imageModel = new ProductImage();
177   - $imageModel->product_id = $model->product_id;
178   - $imageModel->image = $image;
179   - $imageModel->save();
180   - }
181   - }
182   - if(!empty( $model->certificateUpload ) && ( ( $certificates = $model->certificateUpload() ) !== false )) {
183   - foreach($certificates as $certificate) {
184   - $certificateModel = new ProductCertificate([
185   - 'product_id' => $model->product_id,
186   - 'link' => $certificate,
187   - ]);
188   - $certificateModel->save(false);
189   - }
190   - }
191 130 if($product_spec->load(Yii::$app->request->post())) {
192 131 $product_spec->loadLangs(\Yii::$app->request);
193 132 $product_spec->techSpecFile = UploadedFile::getInstance($product_spec, 'techSpecFile');
... ... @@ -225,7 +164,6 @@
225 164 {
226 165 $this->findModel($id)
227 166 ->delete();
228   -
229 167 return $this->redirect([ 'index' ]);
230 168 }
231 169  
... ...
common/modules/product/controllers/VariantController.php
... ... @@ -9,11 +9,9 @@
9 9 use common\modules\product\models\ProductVariantListSearch;
10 10 use common\modules\product\models\Stock;
11 11 use Yii;
12   - use yii\helpers\ArrayHelper;
13 12 use yii\web\Controller;
14 13 use yii\web\NotFoundHttpException;
15 14 use yii\filters\VerbFilter;
16   - use yii\web\UploadedFile;
17 15  
18 16 /**
19 17 * ManageController implements the CRUD actions for ProductVariant model.
... ... @@ -83,30 +81,7 @@
83 81 $model->generateLangs();
84 82 if($model->load(Yii::$app->request->post())) {
85 83 $model->loadLangs(\Yii::$app->request);
86   - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');
87 84 if($model->save() && $model->transactionStatus) {
88   - if(( $image = UploadedFile::getInstance($model, 'image') )) {
89   - $imageModel = ProductImage::find()
90   - ->where([ 'product_variant_id' => $model->product_variant_id ])
91   - ->one();
92   - if($imageModel instanceof ProductImage) {
93   - $imageModel->product_id = $model->product_id;
94   - $imageModel->product_variant_id = $model->product_variant_id;
95   - $imageModel->image = $image->name;
96   - $imageModel->save();
97   - } else {
98   - $imageModel = new ProductImage();
99   - $imageModel->product_id = $model->product_id;
100   - $imageModel->product_variant_id = $model->product_variant_id;
101   - $imageModel->image = $image->name;
102   - $imageModel->save();
103   - }
104   - $imgDir = Yii::getAlias('@storage/products/');
105   - if(!is_dir($imgDir)) {
106   - mkdir($imgDir, 0755, true);
107   - }
108   - $image->saveAs(Yii::getAlias('@storage/products/' . $image->name));
109   - }
110 85 $ProductStocks = Yii::$app->request->post('ProductStock');
111 86 $total_quantity = 0;
112 87 if(!empty( $ProductStocks ) && is_array($ProductStocks)) {
... ... @@ -187,28 +162,6 @@
187 162 if($model->load(Yii::$app->request->post())) {
188 163 $model->loadLangs(\Yii::$app->request);
189 164 if($model->save() && $model->transactionStatus) {
190   - if(( $image = UploadedFile::getInstance($model, 'image') )) {
191   - $imageModel = ProductImage::find()
192   - ->where([ 'product_variant_id' => $model->product_variant_id ])
193   - ->one();
194   - if($imageModel instanceof ProductImage) {
195   - $imageModel->product_id = $model->product_id;
196   - $imageModel->product_variant_id = $model->product_variant_id;
197   - $imageModel->image = $image->name;
198   - $imageModel->save();
199   - } else {
200   - $imageModel = new ProductImage();
201   - $imageModel->product_id = $model->product_id;
202   - $imageModel->product_variant_id = $model->product_variant_id;
203   - $imageModel->image = $image->name;
204   - $imageModel->save();
205   - }
206   - $imgDir = Yii::getAlias('@storage/products/');
207   - if(!is_dir($imgDir)) {
208   - mkdir($imgDir, 0755, true);
209   - }
210   - $image->saveAs(Yii::getAlias('@storage/products/' . $image->name));
211   - }
212 165 $ProductStocks = Yii::$app->request->post('ProductStock');
213 166 $total_quantity = 0;
214 167 if(!empty( $ProductStocks ) && is_array($ProductStocks)) {
... ...
common/modules/product/models/Export.php
... ... @@ -50,7 +50,7 @@
50 50 * @var Product[] $products
51 51 */
52 52 $products = Product::find()
53   - ->with('variantsWithFilters', 'brand.lang', 'categories.lang', 'filters')
  53 + ->with('variantsWithFilters', 'brand.lang', 'categories.lang', 'filters', 'images')
54 54 ->joinWith('lang', true, 'INNER JOIN')
55 55 ->limit($limit)
56 56 ->offset($from)
... ... @@ -71,6 +71,9 @@
71 71 }
72 72  
73 73 $fotos = [];
  74 + foreach($product->images as $image) {
  75 + $fotos[] = $image->image;
  76 + }
74 77  
75 78 $categories = [];
76 79 foreach($product->categories as $value) {
... ... @@ -80,20 +83,20 @@
80 83 $categories = implode(',', $categories);
81 84  
82 85 $list = [
83   - $categories,
84   - ( ( !empty( $product->brand ) ) ? $product->brand->lang->name.$this->generateID($product->brand->remote_id) : '' ),
85   - $product->lang->name.$this->generateID($product->remote_id),
86   - '',
87   - ( ( !empty( $product->lang->description ) ) ? $product->lang->description : '' ),
88   - $filterString,
89   - ( !empty( $product->variant ) ) ? $product->variant->price_old : '',
90   - ( !empty( $product->variant ) ) ? $product->variant->price : '',
91   - intval($product->akciya),
92   - '',
93   - intval($product->is_new),
94   - intval($product->is_top),
95   - $product->video,
96   - implode(',', $fotos),
  86 + $categories, //A - категории через запятую Название(remote_id)
  87 + ( ( !empty( $product->brand ) ) ? $product->brand->lang->name.$this->generateID($product->brand->remote_id) : '' ), //B - бренд Название(remote_id)
  88 + $product->lang->name.$this->generateID($product->remote_id), //C - название товара Название(remote_id)
  89 + ( ( !empty( $product->lang->description ) ) ? $product->lang->description : '' ), //D - описание товара Описание(remote_id)
  90 + $filterString, //E - характеристики товара. Структура: [Группа1(remote_id):Характеристика11(remote_id),Характеристика12(remote_id)]*[Группа2(remote_id):Характеристика21(remote_id),Характеристика22(remote_id)]
  91 + ( !empty( $product->variant ) ) ? $product->variant->price_old : '', //F - страрая цена
  92 + ( !empty( $product->variant ) ) ? $product->variant->price : '', //G - новая цена
  93 + intval($product->akciya), //H - товар акционный (1/0)
  94 + '', //I - пустой
  95 + intval($product->is_new), //J - товар новинка
  96 + intval($product->is_top), //K - товар в топе
  97 + $product->video, //L - ссылка на видео (iframe)
  98 + implode(',', $fotos), //M - название файлов через запятую, картинки должны хранится в /storage/sync/product_images
  99 + // Все последующие модификации: SKU(remote_id)=[Группа1(remote_id):Характеристика11(remote_id),Характеристика12(remote_id)]*[Группа2(remote_id):Характеристика21(remote_id),Характеристика22(remote_id)]=Название=Изображение=Остаток
97 100 ];
98 101 $to_write = array_merge($list, $mods);
99 102 fputcsv($handle, $to_write, ';');
... ...
common/modules/product/models/Import.php
... ... @@ -316,6 +316,10 @@
316 316 {
317 317 if(!empty( $fotos )) {
318 318 foreach($fotos as $foto) {
  319 +
  320 + if(empty($foto)){
  321 + continue;
  322 + }
319 323 $source_image = Yii::getAlias('@uploadDir') . '/product_images/' . urlencode($foto);
320 324 if(file_exists($source_image)) {
321 325 if(( $productImage = ProductImage::find()
... ... @@ -410,7 +414,6 @@
410 414 $_productVariant->save(false);
411 415  
412 416 $MOD_ARRAY[] = $_productVariant->product_variant_id;
413   -
414 417 $this->saveFotos([ $mod_image ], $product_id, $_productVariant->product_variant_id);
415 418 }
416 419 }
... ... @@ -444,6 +447,8 @@
444 447  
445 448 while(( empty( $limit ) || $j++ < $limit ) && ( $data = fgetcsv($handle, 10000, ";") ) !== false) {
446 449 try {
  450 +
  451 +
447 452 foreach($data as &$value) {
448 453 if(!$is_utf) {
449 454 $value = iconv('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);
... ... @@ -528,7 +533,6 @@
528 533  
529 534 $options = [];
530 535 if(!empty ( $filters )) {
531   -
532 536 $options = $this->saveFilters($filters, 0, $categories);
533 537 }
534 538 $parsed_name = $this->parseName($product_name);
... ...
common/modules/product/models/Product.php
... ... @@ -2,6 +2,8 @@
2 2  
3 3 namespace common\modules\product\models;
4 4  
  5 + use common\behaviors\MultipleImgBehavior;
  6 + use common\behaviors\SaveMultipleFileBehavior;
5 7 use common\models\ProductCertificate;
6 8 use common\models\ProductSpec;
7 9 use common\models\ProductToRating;
... ... @@ -24,8 +26,6 @@
24 26 * @property Category[] $categories
25 27 * @property ProductVariant[] $variants
26 28 * @property ProductVariant $variant
27   - * @property ProductImage $image
28   - * @property ProductImage[] $images
29 29 * @property boolean $is_top
30 30 * @property boolean $is_new
31 31 * @property boolean $akciya
... ... @@ -39,25 +39,33 @@
39 39 * @property ProductSpec $productSpec
40 40 * @property ProductCertificate[] $productCertificates
41 41 * * From language behavior *
42   - * @property ProductLang $lang
43   - * @property ProductLang[] $langs
44   - * @property ProductLang $object_lang
45   - * @property string $ownerKey
46   - * @property string $langKey
47   - * @property ProductLang[] $model_langs
48   - * @property bool $transactionStatus
  42 + * @property ProductLang $lang
  43 + * @property ProductLang[] $langs
  44 + * @property ProductLang $object_lang
  45 + * @property string $ownerKey
  46 + * @property string $langKey
  47 + * @property ProductLang[] $model_langs
  48 + * @property bool $transactionStatus
49 49 * @method string getOwnerKey()
50   - * @method void setOwnerKey(string $value)
  50 + * @method void setOwnerKey( string $value )
51 51 * @method string getLangKey()
52   - * @method void setLangKey(string $value)
  52 + * @method void setLangKey( string $value )
53 53 * @method ActiveQuery getLangs()
54 54 * @method ActiveQuery getLang( integer $language_id )
55 55 * @method ProductLang[] generateLangs()
56   - * @method void loadLangs(Request $request)
  56 + * @method void loadLangs( Request $request )
57 57 * @method bool linkLangs()
58 58 * @method bool saveLangs()
59 59 * @method bool getTransactionStatus()
60 60 * * End language behavior *
  61 + * * From multipleImage behavior
  62 + * @property ProductImage $image
  63 + * @property ProductImage[] $images
  64 + * @method ActiveQuery getImage()
  65 + * @method ActiveQuery getImages()
  66 + * @method array getImagesConfig()
  67 + * @method array getImagesHTML( string $preset )
  68 + * * End multipleImage behavior
61 69 */
62 70 class Product extends \yii\db\ActiveRecord
63 71 {
... ... @@ -65,8 +73,7 @@
65 73 /** @var array $_variants */
66 74 public $_variants = [];
67 75  
68   - /** @var array $_images */
69   - public $imagesUpload = '';
  76 + public $imagesUpload = [];
70 77  
71 78 public $certificateUpload = [];
72 79  
... ... @@ -76,10 +83,42 @@
76 83 public function behaviors()
77 84 {
78 85 return [
  86 + 'images' => [
  87 + 'class' => SaveMultipleFileBehavior::className(),
  88 + 'name' => 'imagesUpload',
  89 + 'directory' => 'products',
  90 + 'column' => 'image',
  91 + 'links' => [
  92 + 'product_id' => 'product_id',
  93 + ],
  94 + 'model' => ProductImage::className(),
  95 + ],
  96 + 'certificates' => [
  97 + 'class' => SaveMultipleFileBehavior::className(),
  98 + 'name' => 'certificateUpload',
  99 + 'directory' => 'certificates',
  100 + 'column' => 'link',
  101 + 'links' => [
  102 + 'product_id' => 'product_id',
  103 + ],
  104 + 'model' => ProductCertificate::className(),
  105 + ],
  106 + 'multipleImage' => [
  107 + 'class' => MultipleImgBehavior::className(),
  108 + 'links' => [
  109 + 'product_id' => 'product_id',
  110 + ],
  111 + 'model' => ProductImage::className(),
  112 + 'config' => [
  113 + 'caption' => 'image',
  114 + 'delete_action' => '/product/manage/delimg',
  115 + 'id' => 'product_image_id',
  116 + ],
  117 + ],
79 118 [
80 119 'class' => FilterBehavior::className(),
81 120 ],
82   - 'language' => [
  121 + 'language' => [
83 122 'class' => LanguageBehavior::className(),
84 123 ],
85 124 ];
... ... @@ -159,33 +198,6 @@
159 198 {
160 199 return $this->hasOne(Brand::className(), [ 'brand_id' => 'brand_id' ]);
161 200 }
162   -
163   - /**
164   - * @return \yii\db\ActiveQuery
165   - */
166   - public function getImage()
167   - {
168   - return $this->hasOne(ProductImage::className(), [ 'product_id' => 'product_id' ]);
169   - }
170   -
171   - /**
172   - * fetch stored image url
173   - * @return string
174   - */
175   - public function getImageUrl()
176   - {
177   - $image = empty( $this->variant ) ? NULL : $this->variant->image;
178   - return !empty( $image ) ? $image->imageUrl : '/images/no_photo.png';
179   - }
180   -
181   - /**
182   - * @return \yii\db\ActiveQuery
183   - */
184   - public function getImages()
185   - {
186   - return $this->hasMany(ProductImage::className(), [ 'product_id' => 'product_id' ])
187   - ->where([ 'product_variant_id' => NULL ]);
188   - }
189 201  
190 202 /**
191 203 * @return \yii\db\ActiveQuery
... ... @@ -247,18 +259,15 @@
247 259 return empty( $this->brand ) ? $this->lang->name : $this->brand->lang->name . ' ' . $this->lang->name;
248 260 }
249 261  
  262 + /**
  263 + * @return ActiveQuery
  264 + */
250 265 public function getCategories()
251 266 {
252 267 return $this->hasMany(Category::className(), [ 'category_id' => 'category_id' ])
253 268 ->viaTable('product_category', [ 'product_id' => 'product_id' ]);
254 269 }
255 270  
256   - public function getCategoriesWithName()
257   - {
258   - return $this->hasMany(Category::className(), [ 'category_id' => 'category_id' ])
259   - ->viaTable('product_category', [ 'product_id' => 'product_id' ]);
260   - }
261   -
262 271 public function getCategoriesNames()
263 272 {
264 273 $result = [];
... ... @@ -347,135 +356,51 @@
347 356 ->where([ 'product_id' => $this->product_id ])
348 357 ->sum('quantity');
349 358 }
350   -
  359 +
351 360 public function afterSave($insert, $changedAttributes)
352 361 {
353 362 parent::afterSave($insert, $changedAttributes);
354   -
355   - if(!empty($this->categories)){
  363 +
  364 + if(!empty( $this->categories )) {
356 365 $categories = Category::findAll($this->categories);
357 366 $this->unlinkAll('categories', true);
358   - foreach($categories as $category){
  367 + foreach($categories as $category) {
359 368 $this->link('categories', $category);
360 369 }
361 370 }
362   -
363   - if(!empty($this->options)){
  371 +
  372 + if(!empty( $this->options )) {
364 373 $options = TaxOption::findAll($this->options);
365   - $this->unlinkAll('options',true);
366   - foreach($options as $option){
  374 + $this->unlinkAll('options', true);
  375 + foreach($options as $option) {
367 376 $this->link('options', $option);
368 377 }
369 378 }
370   -
371   -
372   - if (!empty($this->_variants)) {
  379 +
  380 + if(!empty( $this->_variants )) {
373 381 $todel = [];
374   - foreach ($this->variants ?: [] as $_variant) {
375   - $todel[$_variant->product_variant_id] = $_variant->product_variant_id;
  382 + foreach($this->variants ? : [] as $_variant) {
  383 + $todel[ $_variant->product_variant_id ] = $_variant->product_variant_id;
376 384 }
377   - foreach ($this->_variants as $_variant) {
378   - if (!is_array($_variant)) {
  385 + foreach($this->_variants as $_variant) {
  386 + if(!is_array($_variant)) {
379 387 return;
380 388 }
381   - if (!empty($_variant['product_variant_id'])) {
382   - unset($todel[$_variant['product_variant_id']]);
383   - $model = ProductVariant::findOne($_variant['product_variant_id']);
  389 + if(!empty( $_variant[ 'product_variant_id' ] )) {
  390 + unset( $todel[ $_variant[ 'product_variant_id' ] ] );
  391 + $model = ProductVariant::findOne($_variant[ 'product_variant_id' ]);
384 392 } else {
385 393 $model = new ProductVariant();
386 394 }
387   - $_variant['product_id'] = $this->product_id;
388   - $model->load(['ProductVariant' => $_variant]);
  395 + $_variant[ 'product_id' ] = $this->product_id;
  396 + $model->load([ 'ProductVariant' => $_variant ]);
389 397 $model->product_id = $this->product_id;
390 398 $model->save();
391 399 }
392   - if (!empty($todel)) {
393   - ProductVariant::deleteAll(['product_variant_id' => $todel]);
394   - }
395   - }
396   - }
397   -
398   - public function imagesUpload()
399   - {
400   - if($this->validate()) {
401   - $images = [];
402   - foreach($this->imagesUpload as $image) {
403   - $imageName = $image->baseName . '.' . $image->extension;
404   - $i = 0;
405   - while(file_exists(Yii::getAlias('@imagesDir/products/' . $imageName))) {
406   - $i++;
407   - $imageName = $image->baseName . '_' . $i . '.' . $image->extension;
408   - }
409   - $imgDir = Yii::getAlias('@imagesDir/products/');
410   - if(!is_dir($imgDir)) {
411   - mkdir($imgDir, 0755, true);
412   - }
413   -
414   - $image->saveAs($imgDir . $imageName);
415   - $images[] = $imageName;
416   - }
417   - return $images;
418   - } else {
419   - return false;
420   - }
421   - }
422   -
423   - public function certificateUpload()
424   - {
425   - if($this->validate()) {
426   - $certificates = [];
427   - foreach($this->certificateUpload as $certificate) {
428   - $certificateName = $certificate->baseName . '.' . $certificate->extension;
429   - $i = 0;
430   - while(file_exists(Yii::getAlias('@storage/certificates/' . $this->product_id . '/' . $certificateName))) {
431   - $i++;
432   - $certificateName = $certificate->baseName . '_' . $i . '.' . $certificate->extension;
433   - }
434   - $certificateDir = Yii::getAlias('@storage/certificates/' . $this->product_id . '/');
435   - if(!is_dir($certificateDir)) {
436   - mkdir($certificateDir, 0755, true);
437   - }
438   -
439   - $certificate->saveAs($certificateDir . $certificateName);
440   - $certificates[] = $certificateName;
441   - }
442   - return $certificates;
443   - } else {
444   - return false;
445   - }
446   - }
447   -
448   - public function getImagesHTML()
449   - {
450   - $op = [];
451   - if($this->images) {
452   - foreach($this->images as $image) {
453   - $op[] = \common\components\artboximage\ArtboxImageHelper::getImage($image->imageUrl, 'admin_thumb');
454   - }
455   - }
456   - return $op;
457   - }
458   -
459   - public function getImagesConfig()
460   - {
461   - $op = [];
462   - if($this->images) {
463   - foreach($this->images as $image) {
464   - $op[] = [
465   - 'caption' => $image->image,
466   - 'width' => '120px',
467   - 'url' => \yii\helpers\Url::to([
468   - '/product/manage/delimg',
469   - 'id' => $image->product_image_id,
470   - ]),
471   - 'key' => $image->product_image_id,
472   - 'extra' => [
473   - 'id' => $image->product_image_id,
474   - ],
475   - ];
  400 + if(!empty( $todel )) {
  401 + ProductVariant::deleteAll([ 'product_variant_id' => $todel ]);
476 402 }
477 403 }
478   - return $op;
479 404 }
480 405  
481 406 public function recalculateRating()
... ...
common/modules/product/models/ProductImage.php
1 1 <?php
2   -
3   -namespace common\modules\product\models;
4   -
5   -use Yii;
6   -use yii\web\UploadedFile;
7   -
8   -/**
9   - * This is the model class for table "product_image".
10   - *
11   - * @property integer $product_image_id
12   - * @property integer $product_id
13   - * @property integer $product_variant_id
14   - * @property string $image
15   - * @property string $alt
16   - * @property string $title
17   - * @property Product $product
18   - * @property ProductVariant $productVariant
19   - */
20   -class ProductImage extends \yii\db\ActiveRecord
21   -{
22   - public $imageUpload;
  2 +
  3 + namespace common\modules\product\models;
  4 +
  5 + use common\behaviors\ImageBehavior;
  6 + use Yii;
  7 +
23 8 /**
24   - * @inheritdoc
  9 + * This is the model class for table "product_image".
  10 + * @property integer $product_image_id
  11 + * @property integer $product_id
  12 + * @property integer $product_variant_id
  13 + * @property string $image
  14 + * @property string $alt
  15 + * @property string $title
  16 + * @property Product $product
  17 + * @property ProductVariant $productVariant
25 18 */
26   - public static function tableName()
  19 + class ProductImage extends \yii\db\ActiveRecord
27 20 {
28   - return 'product_image';
29   - }
30   -
31   - /**
32   - * @inheritdoc
33   - */
34   - public function rules()
35   - {
36   - return [
37   - [['product_id'], 'required'],
38   - [['product_image_id', 'product_id', 'product_variant_id'], 'integer'],
39   - [['alt', 'title', 'image'], 'string', 'max' => 255],
40   - [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']],
41   - [['product_variant_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductVariant::className(), 'targetAttribute' => ['product_variant_id' => 'product_variant_id']],
42   - [['imageUpload'], 'safe'],
43   - [['imageUpload'], 'file', 'extensions' => 'jpg, gif, png'],
44   - ];
45   - }
46   -
47   - /**
48   - * @inheritdoc
49   - */
50   - public function attributeLabels()
51   - {
52   - return [
53   - 'product_image_id' => Yii::t('product', 'Product Image ID'),
54   - 'product_id' => Yii::t('product', 'Product ID'),
55   - 'product_variant_id' => Yii::t('product', 'Product Variant ID'),
56   - 'product' => Yii::t('product', 'Product'),
57   - 'product_variant' => Yii::t('product', 'Product Variant'),
58   - 'image' => Yii::t('product', 'Image'),
59   - 'alt' => Yii::t('product', 'Alt'),
60   - 'title' => Yii::t('product', 'Title'),
61   - ];
62   - }
63   -
64   - /**
65   - * @return \yii\db\ActiveQuery
66   - */
67   - public function getProduct()
68   - {
69   - $return = $this->hasOne(Product::className(), ['product_id' => 'product_id']);
70   - if (empty($return)) {
71   - $return = $this->productVariant->product_id;
  21 +
  22 + /**
  23 + * @inheritdoc
  24 + */
  25 + public static function tableName()
  26 + {
  27 + return 'product_image';
72 28 }
73   - return $return;
74   - }
75   -
76   - /**
77   - * @return \yii\db\ActiveQuery
78   - */
79   - public function getProductVariant()
80   - {
81   - return $this->hasOne(Product::className(), ['product_variant_id' => 'product_variant_id']);
82   - }
83   -
84   - /**
85   - * fetch stored image file name with complete path
86   - * @return string
87   - */
88   - public function getImageFile()
89   - {
90   - return isset($this->image) ? '/storage/products/' . $this->image : null;
91   - }
92   -
93   - /**
94   - * fetch stored image url
95   - * @return string
96   - */
97   - public function getImageUrl()
98   - {
99   - // return a default image placeholder if your source image is not found
100   - return isset($this->image) ? '/storage/products/'. $this->image : '/storage/no_photo.png';
101   - }
102   -
103   - /**
104   - * Process upload of image
105   - *
106   - * @return mixed the uploaded image instance
107   - */
108   - public function uploadImage() {
109   - // get the uploaded file instance. for multiple file uploads
110   - // the following data will return an array (you may need to use
111   - // getInstances method)
112   - $image = UploadedFile::getInstance($this, 'imageUpload');
113   -
114   - // if no image was uploaded abort the upload
115   - if (empty($image)) {
116   - return false;
  29 +
  30 + public function behaviors()
  31 + {
  32 + return [
  33 + [
  34 + 'class' => ImageBehavior::className(),
  35 + 'link' => 'image',
  36 + 'directory' => 'products',
  37 + ],
  38 + ];
117 39 }
118   -
119   - // store the source file name
120   - $this->filename = $image->name;
121   - $ext = end((explode(".", $image->name)));
122   -
123   - // generate a unique file name
124   - $this->image = Yii::$app->security->generateRandomString().".{$ext}";
125   -
126   - // the uploaded image instance
127   - return $image;
128   - }
129   -
130   - /**
131   - * Process deletion of image
132   - *
133   - * @return boolean the status of deletion
134   - */
135   - public function deleteImage() {
136   - $file = $this->getImageFile();
137   -
138   - // check if file exists on server
139   - if (empty($file) || !file_exists($file)) {
140   - return false;
  40 +
  41 + /**
  42 + * @inheritdoc
  43 + */
  44 + public function rules()
  45 + {
  46 + return [
  47 + [
  48 + [ 'product_id' ],
  49 + 'required',
  50 + ],
  51 + [
  52 + [
  53 + 'product_image_id',
  54 + 'product_id',
  55 + 'product_variant_id',
  56 + ],
  57 + 'integer',
  58 + ],
  59 + [
  60 + [
  61 + 'alt',
  62 + 'title',
  63 + 'image',
  64 + ],
  65 + 'string',
  66 + 'max' => 255,
  67 + ],
  68 + [
  69 + [ 'product_id' ],
  70 + 'exist',
  71 + 'skipOnError' => true,
  72 + 'targetClass' => Product::className(),
  73 + 'targetAttribute' => [ 'product_id' => 'product_id' ],
  74 + ],
  75 + [
  76 + [ 'product_variant_id' ],
  77 + 'exist',
  78 + 'skipOnError' => true,
  79 + 'targetClass' => ProductVariant::className(),
  80 + 'targetAttribute' => [ 'product_variant_id' => 'product_variant_id' ],
  81 + ],
  82 + ];
  83 + }
  84 +
  85 + /**
  86 + * @inheritdoc
  87 + */
  88 + public function attributeLabels()
  89 + {
  90 + return [
  91 + 'product_image_id' => Yii::t('product', 'Product Image ID'),
  92 + 'product_id' => Yii::t('product', 'Product ID'),
  93 + 'product_variant_id' => Yii::t('product', 'Product Variant ID'),
  94 + 'product' => Yii::t('product', 'Product'),
  95 + 'product_variant' => Yii::t('product', 'Product Variant'),
  96 + 'image' => Yii::t('product', 'Image'),
  97 + 'alt' => Yii::t('product', 'Alt'),
  98 + 'title' => Yii::t('product', 'Title'),
  99 + ];
  100 + }
  101 +
  102 + /**
  103 + * @return \yii\db\ActiveQuery
  104 + */
  105 + public function getProduct()
  106 + {
  107 + $return = $this->hasOne(Product::className(), [ 'product_id' => 'product_id' ]);
  108 + if(empty( $return )) {
  109 + $return = $this->productVariant->product_id;
  110 + }
  111 + return $return;
141 112 }
142   -
143   - // check if uploaded file can be deleted on server
144   - if (!unlink($file)) {
145   - return false;
  113 +
  114 + /**
  115 + * @return \yii\db\ActiveQuery
  116 + */
  117 + public function getProductVariant()
  118 + {
  119 + return $this->hasOne(Product::className(), [ 'product_variant_id' => 'product_variant_id' ]);
146 120 }
147   -
148   - // if deletion successful, reset your file attributes
149   - $this->image = null;
150   - $this->filename = null;
151   -
152   - return true;
153 121 }
154   -}
... ...
common/modules/product/models/ProductSearch.php
1 1 <?php
2   -
3   -namespace common\modules\product\models;
4   -
5   -use yii\base\Model;
6   -use yii\data\ActiveDataProvider;
7   -
8   -/**
9   - * ProductSearch represents the model behind the search form about `common\modules\product\models\Product`.
10   - */
11   -class ProductSearch extends Product
12   -{
13   - public $brand_name;
14   - public $brand_id;
15   - public $category_id;
16   - public $category_name;
17   - public $variant_sku;
18   -
19   - public function behaviors()
20   - {
21   - $behaviors = parent::behaviors();
22   - if(isset($behaviors['language'])) {
23   - unset($behaviors['language']);
24   - }
25   - return $behaviors;
26   - }
27 2  
28   - /**
29   - * @inheritdoc
30   - */
31   - public function rules()
32   - {
33   - return [
34   - [['brand_name', 'brand_id', 'category_id', 'category_name', 'variant_sku'], 'safe'],
35   - [['brand_id', 'product_id'], 'integer'],
36   - [['is_top', 'is_new', 'akciya'], 'boolean'],
37   - ];
38   - }
  3 + namespace common\modules\product\models;
  4 +
  5 + use yii\base\Model;
  6 + use yii\data\ActiveDataProvider;
  7 + use yii\db\ActiveQuery;
39 8  
40 9 /**
41   - * @inheritdoc
42   - */
43   - public function scenarios()
44   - {
45   - // bypass scenarios() implementation in the parent class
46   - return Model::scenarios();
47   - }
48   -
49   - /**
50   - * Creates data provider instance with search query applied
51   - *
52   - * @param array $params
53   - *
54   - * @return ActiveDataProvider
  10 + * ProductSearch represents the model behind the search form about
  11 + * `common\modules\product\models\Product`.
55 12 */
56   - public function search($params)
  13 + class ProductSearch extends Product
57 14 {
58   -
59   - $query = Product::find();
60   -
61   -// $query->joinWith(['brand', 'categories', 'variant']);
62   -
63   - $query->groupBy(['product.product_id']);
64   -
65   - $dataProvider = new ActiveDataProvider([
66   - 'query' => $query,
67   - ]);
68   -
69   - if ( !($this->load($params) && $this->validate()) ) {
70   - return $dataProvider;
  15 +
  16 + public $brand_id;
  17 +
  18 + public $category_id;
  19 +
  20 + public $variant_sku;
  21 +
  22 + public function behaviors()
  23 + {
  24 + $behaviors = parent::behaviors();
  25 + if(isset( $behaviors[ 'language' ] )) {
  26 + unset( $behaviors[ 'language' ] );
  27 + }
  28 + return $behaviors;
71 29 }
72   -
73   -// $dataProvider->setSort([
74   -// 'attributes' => [
75   -// 'brand_name' => [
76   -// 'asc' => ['brand.name' => SORT_ASC],
77   -// 'desc' => ['brand.name' => SORT_DESC],
78   -// 'default' => SORT_DESC,
79   -// 'label' => 'Brand name',
80   -// ],
81   -// 'category_name',
82   -// 'variant_sku',
83   -// ]
84   -// ]);
85   -
86   - if (isset($this->is_top)) {
87   - $query->andFilterWhere([
88   - 'is_top' => (bool)$this->is_top,
89   - ]);
  30 +
  31 + /**
  32 + * @inheritdoc
  33 + */
  34 + public function rules()
  35 + {
  36 + return [
  37 + [
  38 + [ 'variant_sku' ],
  39 + 'safe',
  40 + ],
  41 + [
  42 + [
  43 + 'brand_id',
  44 + 'product_id',
  45 + 'category_id',
  46 + 'brand_id',
  47 + ],
  48 + 'integer',
  49 + ],
  50 + [
  51 + [
  52 + 'is_top',
  53 + 'is_new',
  54 + 'akciya',
  55 + ],
  56 + 'boolean',
  57 + ],
  58 + ];
90 59 }
91   - if (isset($this->is_new)) {
92   - $query->andFilterWhere([
93   - 'is_new' => (bool)$this->is_new,
94   - ]);
  60 +
  61 + /**
  62 + * @inheritdoc
  63 + */
  64 + public function scenarios()
  65 + {
  66 + // bypass scenarios() implementation in the parent class
  67 + return Model::scenarios();
95 68 }
96   - if (isset($this->akciya)) {
  69 +
  70 + /**
  71 + * Creates data provider instance with search query applied
  72 + *
  73 + * @param array $params
  74 + *
  75 + * @return ActiveDataProvider
  76 + */
  77 + public function search($params)
  78 + {
  79 +
  80 + $query = Product::find();
  81 +
  82 + $query->joinWith([
  83 + 'categories',
  84 + /*'variant'*/
  85 + ])
  86 + ->joinWith([
  87 + 'brand' => function($query) {
  88 + /**
  89 + * @var ActiveQuery $query
  90 + */
  91 + $query->joinWith('lang');
  92 + },
  93 + ]);
  94 +
  95 + $query->groupBy([ 'product.product_id' ]);
  96 +
  97 + $dataProvider = new ActiveDataProvider([
  98 + 'query' => $query,
  99 + ]);
  100 +
  101 + if(!( $this->load($params) && $this->validate() )) {
  102 + return $dataProvider;
  103 + }
  104 +
  105 + $dataProvider->setSort([
  106 + 'attributes' => [
  107 + 'brand_id' => [
  108 + 'asc' => [ 'brand_lang.name' => SORT_ASC ],
  109 + 'desc' => [ 'brand_lang.name' => SORT_DESC ],
  110 + 'default' => SORT_DESC,
  111 + 'label' => 'Brand name',
  112 + ],
  113 + ],
  114 + ]);
  115 +
  116 + if(isset( $this->is_top )) {
  117 + $query->andFilterWhere([
  118 + 'is_top' => (bool) $this->is_top,
  119 + ]);
  120 + }
  121 + if(isset( $this->is_new )) {
  122 + $query->andFilterWhere([
  123 + 'is_new' => (bool) $this->is_new,
  124 + ]);
  125 + }
  126 + if(isset( $this->akciya )) {
  127 + $query->andFilterWhere([
  128 + 'akciya' => (bool) $this->akciya,
  129 + ]);
  130 + }
97 131 $query->andFilterWhere([
98   - 'akciya' => (bool)$this->akciya,
  132 + 'product.brand_id' => $this->brand_id,
  133 + 'product.product_id' => $this->product_id,
  134 + 'product_category.category_id' => $this->category_id,
99 135 ]);
  136 +
  137 + // $query->andFilterWhere(['ilike', 'brand.name', $this->brand_name]);
  138 + // $query->andFilterWhere(['ilike', 'product_variant.sku', $this->variant_sku]);
  139 +
  140 + return $dataProvider;
100 141 }
101   - $query->andFilterWhere([
102   - 'product.brand_id' => $this->brand_id,
103   - 'product.product_id' => $this->product_id,
104   -// 'product_category.category_id' => $this->category_id
105   - ]);
106   -
107   -// $query->andFilterWhere(['ilike', 'brand.name', $this->brand_name]);
108   -// $query->andFilterWhere(['ilike', 'category.name', $this->category_name]);
109   -// $query->andFilterWhere(['ilike', 'product_variant.sku', $this->variant_sku]);
110   -
111   - return $dataProvider;
112 142 }
113   -}
... ...
common/modules/product/models/ProductVariant.php
... ... @@ -2,6 +2,8 @@
2 2  
3 3 namespace common\modules\product\models;
4 4  
  5 + use common\behaviors\MultipleImgBehavior;
  6 + use common\behaviors\SaveMultipleFileBehavior;
5 7 use common\modules\language\behaviors\LanguageBehavior;
6 8 use common\modules\rubrication\models\TaxGroup;
7 9 use common\modules\rubrication\models\TaxOption;
... ... @@ -22,8 +24,6 @@
22 24 * @property double $price_old
23 25 * @property double $stock
24 26 * @property integer $product_unit_id
25   - * @property ProductImage $image
26   - * @property array $images
27 27 * @property TaxOption[] $options
28 28 * @property ProductUnit $productUnit
29 29 * @property Product $product
... ... @@ -47,6 +47,14 @@
47 47 * @method bool saveLangs()
48 48 * @method bool getTransactionStatus()
49 49 * * End language behavior *
  50 + * * From multipleImage behavior
  51 + * @property ProductImage $image
  52 + * @property ProductImage[] $images
  53 + * @method ActiveQuery getImage()
  54 + * @method ActiveQuery getImages()
  55 + * @method array getImagesConfig()
  56 + * @method array getImagesHTML( string $preset )
  57 + * * End multipleImage behavior
50 58 */
51 59 class ProductVariant extends ActiveRecord
52 60 {
... ... @@ -58,7 +66,7 @@
58 66 private $_options;
59 67  
60 68 /** @var array $_images */
61   - public $imagesUpload = '';
  69 + public $imagesUpload = [];
62 70  
63 71 /**
64 72 * @inheritdoc
... ... @@ -71,9 +79,32 @@
71 79 public function behaviors()
72 80 {
73 81 return [
74   - 'language' => [
  82 + 'language' => [
75 83 'class' => LanguageBehavior::className(),
76 84 ],
  85 + 'images' => [
  86 + 'class' => SaveMultipleFileBehavior::className(),
  87 + 'name' => 'imagesUpload',
  88 + 'directory' => 'products',
  89 + 'column' => 'image',
  90 + 'links' => [
  91 + 'product_id' => 'product_id',
  92 + 'product_variant_id' => 'product_variant_id',
  93 + ],
  94 + 'model' => ProductImage::className(),
  95 + ],
  96 + 'multipleImage' => [
  97 + 'class' => MultipleImgBehavior::className(),
  98 + 'links' => [
  99 + 'product_variant_id' => 'product_variant_id',
  100 + ],
  101 + 'model' => ProductImage::className(),
  102 + 'config' => [
  103 + 'caption' => 'image',
  104 + 'delete_action' => '/product/variant/delimg',
  105 + 'id' => 'product_image_id',
  106 + ],
  107 + ],
77 108 ];
78 109 }
79 110  
... ... @@ -115,7 +146,6 @@
115 146 [
116 147 [
117 148 'options',
118   - 'imagesUpload',
119 149 ],
120 150 'safe',
121 151 ],
... ... @@ -204,70 +234,11 @@
204 234 ->joinWith('lang', true, 'INNER JOIN');
205 235 }
206 236  
207   - /**
208   - * @return \yii\db\ActiveQuery
209   - */
210   - public function getImage()
211   - {
212   - return $this->hasOne(ProductImage::className(), [ 'product_variant_id' => 'product_variant_id' ]);
213   - }
214   -
215   - /**
216   - * fetch stored image url
217   - * @return string
218   - */
219   - public function getImageUrl()
220   - {
221   - // return a default image placeholder if your source image is not found
222   - return !empty( $this->image ) ? $this->image->imageUrl : '/images/no_photo.png';
223   - }
224   -
225 237 public function getFullname()
226 238 {
227 239 return empty( $this->product ) ? NULL : ( $this->product->lang->name . ( empty( $this->lang->name ) ? '' : ' ' . $this->lang->name ) );
228 240 }
229 241  
230   - public function getImagesHTML()
231   - {
232   - $op = [];
233   - if($this->images) {
234   - foreach($this->images as $image) {
235   - $op[] = \common\components\artboximage\ArtboxImageHelper::getImage($image->imageUrl, 'admin_thumb');
236   - }
237   - }
238   - return $op;
239   - }
240   -
241   - public function getImagesConfig()
242   - {
243   - $op = [];
244   - if($this->images) {
245   - foreach($this->images as $image) {
246   - $op[] = [
247   - 'caption' => $image->image,
248   - 'width' => '120px',
249   - 'url' => \yii\helpers\Url::to([
250   - '/product/manage/delimg',
251   - 'id' => $image->product_image_id,
252   - ]),
253   - 'key' => $image->product_image_id,
254   - 'extra' => [
255   - 'id' => $image->product_image_id,
256   - ],
257   - ];
258   - }
259   - }
260   - return $op;
261   - }
262   -
263   - /**
264   - * @return \yii\db\ActiveQuery
265   - */
266   - public function getImages()
267   - {
268   - return $this->hasMany(ProductImage::className(), [ 'product_variant_id' => 'product_variant_id' ]);
269   - }
270   -
271 242 public function setOptions($values)
272 243 {
273 244 $this->_options = $values;
... ... @@ -348,7 +319,6 @@
348 319  
349 320 if(!empty( $this->stocks )) {
350 321 ProductStock::deleteAll([ 'product_variant_id' => $this->product_variant_id ]);
351   - $values = [];
352 322 foreach($this->stocks as $id => $quantity) {
353 323 $productStock = ProductStock::find()
354 324 ->where([
... ... @@ -362,24 +332,4 @@
362 332 }
363 333 }
364 334  
365   - public function imagesUpload()
366   - {
367   - if($this->validate()) {
368   - $images = [];
369   - foreach($this->imagesUpload as $image) {
370   - $imageName = $image->baseName . '.' . $image->extension;
371   - $i = 0;
372   - while(file_exists(Yii::getAlias('@imagesDir/products/' . $imageName))) {
373   - $i++;
374   - $imageName = $image->baseName . '_' . $i . '.' . $image->extension;
375   - }
376   -
377   - $image->saveAs(Yii::getAlias('@imagesDir/products/' . $imageName));
378   - $images[] = $imageName;
379   - }
380   - return $images;
381   - } else {
382   - return false;
383   - }
384   - }
385 335 }
... ...
common/modules/product/views/manage/export-process.php 100644 → 100755
common/modules/product/views/manage/export.php 100644 → 100755
common/modules/product/views/manage/index.php
1 1 <?php
2   -
3   -use yii\helpers\Html;
4   -use yii\grid\GridView;
5   -use yii\helpers\ArrayHelper;
6   -use kartik\select2\Select2;
7   -use common\components\artboxtree\ArtboxTreeHelper;
8   -use common\modules\product\helpers\ProductHelper;
9   -
10   -/* @var $this yii\web\View */
11   -/* @var $searchModel common\modules\product\models\ProductSearch */
12   -/* @var $dataProvider yii\data\ActiveDataProvider */
13   -
14   -$this->title = Yii::t('product', 'Products');
15   -$this->params['breadcrumbs'][] = $this->title;
  2 +
  3 + use common\modules\product\models\Brand;
  4 + use common\modules\product\models\Category;
  5 + use common\modules\product\models\Product;
  6 + use yii\helpers\Html;
  7 + use yii\grid\GridView;
  8 + use kartik\select2\Select2;
  9 + use common\components\artboxtree\ArtboxTreeHelper;
  10 + use common\modules\product\helpers\ProductHelper;
  11 +
  12 + /* @var $this yii\web\View */
  13 + /* @var $searchModel common\modules\product\models\ProductSearch */
  14 + /* @var $dataProvider yii\data\ActiveDataProvider */
  15 +
  16 + $this->title = Yii::t('product', 'Products');
  17 + $this->params[ 'breadcrumbs' ][] = $this->title;
16 18 ?>
17 19 <div class="product-index">
18   -
  20 +
19 21 <h1><?= Html::encode($this->title) ?></h1>
20   -
  22 +
21 23 <p>
22   - <?= Html::a(Yii::t('product', 'Create Product'), ['create'], ['class' => 'btn btn-success']) ?>
  24 + <?= Html::a(Yii::t('product', 'Create Product'), [ 'create' ], [ 'class' => 'btn btn-success' ]) ?>
23 25 </p>
24 26 <?= GridView::widget([
25 27 'dataProvider' => $dataProvider,
26   - 'filterModel' => $searchModel,
27   - 'columns' => [
28   - ['class' => 'yii\grid\SerialColumn'],
  28 + 'filterModel' => $searchModel,
  29 + 'columns' => [
29 30 'product_id',
30   -// [
31   -// 'label' => Yii::t('product', 'Brand'),
32   -// 'attribute' => 'brand_name',
33   -// 'value' => 'brand.name',
34   -// 'format' => 'raw',
35   -// 'filter' => Select2::widget([
36   -// 'model' => $searchModel,
37   -// 'attribute' => 'brand_id',
38   -// 'data' => ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'),
39   -// 'language' => 'ru',
40   -// 'options' => [
41   -// 'placeholder' => Yii::t('product', 'Select brand'),
42   -// 'multiple' => false,
43   -// ],
44   -// 'pluginOptions' => [
45   -// 'allowClear' => true
46   -// ],
47   -// ])
48   -// ],
49   -// [
50   -// 'label' => Yii::t('product', 'Category'),
51   -// 'attribute' => 'category_name',
52   -// 'value' => function($model) {
53   -// $categories = [];
54   -// foreach ($model->categories as $category) {
55   -// $categories[] = $category->name;
56   -// }
57   -// return implode(", ", $categories);
58   -// },
59   -// 'format' => 'raw',
60   -// 'filter' => Select2::widget([
61   -// 'model' => $searchModel,
62   -// 'attribute' => 'category_id',
63   -// 'data' => ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'),
64   -// 'language' => 'ru',
65   -// 'options' => [
66   -// 'placeholder' => Yii::t('product', 'Select category'),
67   -// 'multiple' => false,
68   -// ],
69   -// 'pluginOptions' => [
70   -// 'allowClear' => true
71   -// ],
72   -// ])
73   -// ],
74   -// [
75   -// 'label' => Yii::t('product', 'SKU'),
76   -// 'attribute' => 'variant_sku',
77   -// 'value' => 'variant.sku',
78   -// ],
79   -// 'variant.price',
80   -// 'variant.price_old',
81   -// [
82   -// 'label' => Yii::t('product', 'Stock'),
83   -// 'attribute' => 'variant_stock',
84   -// 'value' => 'variant.stock_caption',
85   -// ],
86 31 [
87   - 'class' => 'yii\grid\ActionColumn',
88   - 'template' => '{items} {view} |{is_top} {is_new} {akciya} | {update} {delete}',
89   - 'buttons' => [
90   - 'is_top' => function ($url, $model) {
91   - return Html::a('<span class="glyphicon glyphicon-star' . ($model->is_top ? '' : '-empty') . '"></span>', $url, [
92   - 'title' => Yii::t('product', ($model->is_top ? 'Set not is top' : 'Set is top')),
  32 + 'label' => Yii::t('product', 'Brand'),
  33 + 'attribute' => 'brand_id',
  34 + 'value' => 'brand.lang.name',
  35 + 'filter' => Select2::widget([
  36 + 'model' => $searchModel,
  37 + 'attribute' => 'brand_id',
  38 + 'data' => Brand::find()->joinWith('lang')->select(['brand_lang.name', 'brand.brand_id'])->asArray()->indexBy('brand_id')->column(),
  39 + 'language' => 'ru',
  40 + 'options' => [
  41 + 'placeholder' => Yii::t('product', 'Select brand'),
  42 + 'multiple' => false,
  43 + ],
  44 + 'pluginOptions' => [
  45 + 'allowClear' => true,
  46 + ],
  47 + ]),
  48 + ],
  49 + [
  50 + 'label' => Yii::t('product', 'Category'),
  51 + 'attribute' => 'category_id',
  52 + 'value' => function($model) {
  53 + /**
  54 + * @var Product $model
  55 + */
  56 + $categories = [];
  57 + foreach($model->getCategories()->with('lang')->all() as $category) {
  58 + /**
  59 + * @var Category $category
  60 + */
  61 + $categories[] = $category->lang->name;
  62 + }
  63 + return implode(", ", $categories);
  64 + },
  65 + 'filter' => Select2::widget([
  66 + 'model' => $searchModel,
  67 + 'attribute' => 'category_id',
  68 + 'data' => ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'lang.name'),
  69 + 'language' => 'ru',
  70 + 'options' => [
  71 + 'placeholder' => Yii::t('product', 'Select category'),
  72 + 'multiple' => false,
  73 + ],
  74 + 'pluginOptions' => [
  75 + 'allowClear' => true,
  76 + ],
  77 + ]),
  78 + ],
  79 + // [
  80 + // 'label' => Yii::t('product', 'SKU'),
  81 + // 'attribute' => 'variant_sku',
  82 + // 'value' => 'variant.sku',
  83 + // ],
  84 + // 'variant.price',
  85 + // 'variant.price_old',
  86 + // [
  87 + // 'label' => Yii::t('product', 'Stock'),
  88 + // 'attribute' => 'variant_stock',
  89 + // 'value' => 'variant.stock_caption',
  90 + // ],
  91 + [
  92 + 'class' => 'yii\grid\ActionColumn',
  93 + 'template' => '{items} {view} |{is_top} {is_new} {akciya} | {update} {delete}',
  94 + 'buttons' => [
  95 + 'is_top' => function($url, $model) {
  96 + return Html::a('<span class="glyphicon glyphicon-star' . ( $model->is_top ? '' : '-empty' ) . '"></span>', $url, [
  97 + 'title' => Yii::t('product', ( $model->is_top ? 'Set not is top' : 'Set is top' )),
93 98 ]);
94 99 },
95   - 'is_new' => function ($url, $model) {
96   - return Html::a('<span class="glyphicon glyphicon-heart' . ($model->is_new ? '' : '-empty') . '"></span>', $url, [
97   - 'title' => Yii::t('product', ($model->is_new ? 'Set not is new' : 'Set is new')),
  100 + 'is_new' => function($url, $model) {
  101 + return Html::a('<span class="glyphicon glyphicon-heart' . ( $model->is_new ? '' : '-empty' ) . '"></span>', $url, [
  102 + 'title' => Yii::t('product', ( $model->is_new ? 'Set not is new' : 'Set is new' )),
98 103 ]);
99 104 },
100   - 'akciya' => function ($url, $model) {
101   - return Html::a('<span class="glyphicon glyphicon-tag' . ($model->akciya ? 's' : '') . '"></span>', $url, [
102   - 'title' => Yii::t('product', ($model->akciya ? 'Set not is promotion' : 'Set is promotion')),
  105 + 'akciya' => function($url, $model) {
  106 + return Html::a('<span class="glyphicon glyphicon-tag' . ( $model->akciya ? 's' : '' ) . '"></span>', $url, [
  107 + 'title' => Yii::t('product', ( $model->akciya ? 'Set not is promotion' : 'Set is promotion' )),
103 108 ]);
104 109 },
105   - 'items' => function ($url, $model) {
  110 + 'items' => function($url, $model) {
106 111 return Html::a('<span class="glyphicon glyphicon-th-list"></span>', $url, [
107 112 'title' => Yii::t('product', 'Variants'),
108 113 ]);
109 114 },
110   -
  115 +
111 116 ],
112   - 'urlCreator' => function ($action, $model, $key, $index) {
113   - switch ($action) {
  117 + 'urlCreator' => function($action, $model, $key, $index) {
  118 + switch($action) {
114 119 case 'items':
115   - return \yii\helpers\Url::to(['/product/variant', 'product_id' => $model->product_id]);
  120 + return \yii\helpers\Url::to([
  121 + '/product/variant',
  122 + 'product_id' => $model->product_id,
  123 + ]);
116 124 break;
117 125 case 'is_top':
118   - return \yii\helpers\Url::to(['manage/is_top', 'id' => $model->product_id]);
  126 + return \yii\helpers\Url::to([
  127 + 'manage/is_top',
  128 + 'id' => $model->product_id,
  129 + ]);
119 130 break;
120 131 case 'is_new':
121   - return \yii\helpers\Url::to(['manage/is_new', 'id' => $model->product_id]);
  132 + return \yii\helpers\Url::to([
  133 + 'manage/is_new',
  134 + 'id' => $model->product_id,
  135 + ]);
122 136 break;
123 137 case 'akciya':
124   - return \yii\helpers\Url::to(['manage/akciya', 'id' => $model->product_id]);
  138 + return \yii\helpers\Url::to([
  139 + 'manage/akciya',
  140 + 'id' => $model->product_id,
  141 + ]);
125 142 break;
126 143 case 'view':
127   - return \yii\helpers\Url::to(['manage/view', 'id' => $model->product_id]);
  144 + return \yii\helpers\Url::to([
  145 + 'manage/view',
  146 + 'id' => $model->product_id,
  147 + ]);
128 148 break;
129 149 case 'update':
130   - return \yii\helpers\Url::to(['manage/update', 'id' => $model->product_id]);
  150 + return \yii\helpers\Url::to([
  151 + 'manage/update',
  152 + 'id' => $model->product_id,
  153 + ]);
131 154 break;
132 155 case 'delete':
133   - return \yii\helpers\Url::to(['manage/delete', 'id' => $model->product_id]);
  156 + return \yii\helpers\Url::to([
  157 + 'manage/delete',
  158 + 'id' => $model->product_id,
  159 + ]);
134 160 break;
135 161 }
136   - }
  162 + },
137 163 ],
138 164 ],
139 165 ]); ?>
... ...
common/modules/product/views/variant/_form.php
... ... @@ -53,13 +53,12 @@ $(&quot;.dynamicform_wrapper&quot;).on(&quot;limitReached&quot;, function(e, item) {
53 53 ->textarea(); ?>
54 54 <?= $form->field($model, 'price_old')
55 55 ->textarea(); ?>
56   - <?= $form->field($model, 'image')
  56 + <?= $form->field($model, 'imagesUpload[]')
57 57 ->widget(\kartik\file\FileInput::className(), [
58   - 'model' => $model,
59   - 'attribute' => 'image',
  58 + 'language' => 'ru',
60 59 'options' => [
61 60 'accept' => 'image/*',
62   - 'multiple' => false,
  61 + 'multiple' => true,
63 62 ],
64 63 'pluginOptions' => [
65 64 'allowedFileExtensions' => [
... ... @@ -67,10 +66,13 @@ $(&quot;.dynamicform_wrapper&quot;).on(&quot;limitReached&quot;, function(e, item) {
67 66 'gif',
68 67 'png',
69 68 ],
70   - 'initialPreview' => $model->imageUrl ? \common\components\artboximage\ArtboxImageHelper::getImage($model->imageUrl, 'products') : '',
71   - 'overwriteInitial' => true,
72   - 'showRemove' => true,
  69 + 'initialPreview' => !empty( $model->imagesHTML ) ? $model->imagesHTML : [],
  70 + 'initialPreviewConfig' => $model->imagesConfig,
  71 + 'overwriteInitial' => false,
  72 + 'showRemove' => false,
73 73 'showUpload' => false,
  74 + 'uploadAsync' => !empty( $model->product_variant_id ),
  75 + 'previewFileType' => 'image',
74 76 ],
75 77 ]); ?>
76 78  
... ...
console/migrations/m161011_104931_create_stock_lang_table.php 100644 → 100755