Commit af036678130d7605d53d59b12b79146c02a911cc
1 parent
b569ac34
Image behaviors
Showing
20 changed files
with
898 additions
and
833 deletions
Show diff stats
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, | ... | ... |
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 | ... | ... |
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 | ... | ... |
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 @@ $(".dynamicform_wrapper").on("limitReached", 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 @@ $(".dynamicform_wrapper").on("limitReached", 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