Commit af036678130d7605d53d59b12b79146c02a911cc

Authored by Yarik
1 parent b569ac34

Image behaviors

backend/controllers/ProjectController.php
@@ -92,16 +92,7 @@ @@ -92,16 +92,7 @@
92 $model->generateLangs(); 92 $model->generateLangs();
93 if($model->load(Yii::$app->request->post())) { 93 if($model->load(Yii::$app->request->post())) {
94 $model->loadLangs(\Yii::$app->request); 94 $model->loadLangs(\Yii::$app->request);
95 - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');  
96 if($model->save() && $model->transactionStatus) { 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 return $this->redirect([ 96 return $this->redirect([
106 'view', 97 'view',
107 'id' => $model->project_id, 98 'id' => $model->project_id,
@@ -128,16 +119,7 @@ @@ -128,16 +119,7 @@
128 $model->generateLangs(); 119 $model->generateLangs();
129 if($model->load(Yii::$app->request->post())) { 120 if($model->load(Yii::$app->request->post())) {
130 $model->loadLangs(\Yii::$app->request); 121 $model->loadLangs(\Yii::$app->request);
131 - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');  
132 if($model->save() && $model->transactionStatus) { 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 return $this->redirect([ 123 return $this->redirect([
142 'view', 124 'view',
143 'id' => $model->project_id, 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 \ No newline at end of file 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 \ No newline at end of file 117 \ No newline at end of file
common/behaviors/SaveImgBehavior.php
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 use yii\base\ModelEvent; 6 use yii\base\ModelEvent;
7 use yii\db\ActiveRecord; 7 use yii\db\ActiveRecord;
8 use yii\web\UploadedFile; 8 use yii\web\UploadedFile;
  9 +
9 /** 10 /**
10 * Class Save Image Behavior 11 * Class Save Image Behavior
11 * @property ActiveRecord $owner 12 * @property ActiveRecord $owner
@@ -15,6 +16,7 @@ @@ -15,6 +16,7 @@
15 { 16 {
16 17
17 public $fields; 18 public $fields;
  19 +
18 public $is_language = false; 20 public $is_language = false;
19 21
20 public function events() 22 public function events()
@@ -24,25 +26,26 @@ @@ -24,25 +26,26 @@
24 ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave', 26 ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
25 ]; 27 ];
26 } 28 }
27 - 29 +
28 /** 30 /**
29 * @param ModelEvent $event 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 $name = $field_name; 37 $name = $field_name;
35 if($this->is_language) { 38 if($this->is_language) {
36 - $name = '['.$this->owner->language_id.']'.$name; 39 + $name = '[' . $this->owner->language_id . ']' . $name;
37 } 40 }
38 - 41 +
39 $image = UploadedFile::getInstance($this->owner, $name); 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 $this->owner->$field_name = $this->owner->getOldAttribute($field_name); 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 if(!is_dir($imgDir)) { 49 if(!is_dir($imgDir)) {
47 mkdir($imgDir, 0755, true); 50 mkdir($imgDir, 0755, true);
48 } 51 }
@@ -50,28 +53,43 @@ @@ -50,28 +53,43 @@
50 $baseName = $image->baseName; 53 $baseName = $image->baseName;
51 54
52 $iteration = 0; 55 $iteration = 0;
53 - $file_name = $imgDir.$baseName.'.'.$image->extension; 56 + $file_name = $imgDir . $baseName . '.' . $image->extension;
54 while(file_exists($file_name)) { 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 $image->saveAs($file_name); 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 \ No newline at end of file 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 \ No newline at end of file 120 \ No newline at end of file
common/models/Articles.php
1 <?php 1 <?php
2 2
3 namespace common\models; 3 namespace common\models;
4 -  
5 - use common\modules\language\behaviors\TransactionBehavior; 4 +
6 use common\modules\language\behaviors\LanguageBehavior; 5 use common\modules\language\behaviors\LanguageBehavior;
7 use common\behaviors\SaveImgBehavior; 6 use common\behaviors\SaveImgBehavior;
8 use common\modules\comment\models\CommentModel; 7 use common\modules\comment\models\CommentModel;
@@ -36,8 +35,14 @@ @@ -36,8 +35,14 @@
36 * @method bool saveLangs() 35 * @method bool saveLangs()
37 * @method bool getTransactionStatus() 36 * @method bool getTransactionStatus()
38 * * End language behavior * 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,6 +2,8 @@
2 2
3 namespace common\models; 3 namespace common\models;
4 4
  5 + use common\behaviors\MultipleImgBehavior;
  6 + use common\behaviors\SaveMultipleFileBehavior;
5 use common\modules\language\behaviors\LanguageBehavior; 7 use common\modules\language\behaviors\LanguageBehavior;
6 use common\modules\product\models\ProductVariant; 8 use common\modules\product\models\ProductVariant;
7 use Yii; 9 use Yii;
@@ -11,13 +13,9 @@ @@ -11,13 +13,9 @@
11 13
12 /** 14 /**
13 * This is the model class for table "project". 15 * This is the model class for table "project".
14 - *  
15 * @todo Refactor 16 * @todo Refactor
16 - *  
17 * @property integer $project_id 17 * @property integer $project_id
18 * @property integer $date_add 18 * @property integer $date_add
19 - * @property ProjectImage[] $images  
20 - * @property ProjectImage $image  
21 * @property array $imagesConfig 19 * @property array $imagesConfig
22 * @property ProductVariant[] $variants 20 * @property ProductVariant[] $variants
23 * @property ProductToProject[] $productToProject 21 * @property ProductToProject[] $productToProject
@@ -41,6 +39,14 @@ @@ -41,6 +39,14 @@
41 * @method bool saveLangs() 39 * @method bool saveLangs()
42 * @method bool getTransactionStatus() 40 * @method bool getTransactionStatus()
43 * * End language behavior * 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 class Project extends ActiveRecord 51 class Project extends ActiveRecord
46 { 52 {
@@ -61,9 +67,31 @@ @@ -61,9 +67,31 @@
61 public function behaviors() 67 public function behaviors()
62 { 68 {
63 return [ 69 return [
64 - 'language' => [ 70 + 'language' => [
65 'class' => LanguageBehavior::className(), 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,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 public function getProductToProject() 143 public function getProductToProject()
184 { 144 {
185 return $this->hasMany(ProductToProject::className(), [ 145 return $this->hasMany(ProductToProject::className(), [
common/modules/product/controllers/ManageController.php
@@ -8,7 +8,6 @@ @@ -8,7 +8,6 @@
8 use common\modules\product\models\Export; 8 use common\modules\product\models\Export;
9 use common\modules\product\models\Import; 9 use common\modules\product\models\Import;
10 use common\modules\product\models\ProductImage; 10 use common\modules\product\models\ProductImage;
11 - use common\modules\product\models\ProductVariant;  
12 use Yii; 11 use Yii;
13 use common\modules\product\models\Product; 12 use common\modules\product\models\Product;
14 use common\modules\product\models\ProductSearch; 13 use common\modules\product\models\ProductSearch;
@@ -38,22 +37,6 @@ @@ -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 * Lists all Product models. 41 * Lists all Product models.
59 * @return mixed 42 * @return mixed
@@ -92,36 +75,11 @@ @@ -92,36 +75,11 @@
92 { 75 {
93 $model = new Product(); 76 $model = new Product();
94 $model->generateLangs(); 77 $model->generateLangs();
95 -  
96 $product_spec = new ProductSpec(); 78 $product_spec = new ProductSpec();
97 $product_spec->generateLangs(); 79 $product_spec->generateLangs();
98 -  
99 if($model->load(Yii::$app->request->post())) { 80 if($model->load(Yii::$app->request->post())) {
100 $model->loadLangs(\Yii::$app->request); 81 $model->loadLangs(\Yii::$app->request);
101 - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');  
102 - $model->certificateUpload = UploadedFile::getInstances($model, 'certificateUpload');  
103 -  
104 if($model->save() && $model->transactionStatus) { 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 if($product_spec->load(Yii::$app->request->post())) { 83 if($product_spec->load(Yii::$app->request->post())) {
126 $product_spec->loadLangs(\Yii::$app->request); 84 $product_spec->loadLangs(\Yii::$app->request);
127 $product_spec->product_id = $model->product_id; 85 $product_spec->product_id = $model->product_id;
@@ -168,26 +126,7 @@ @@ -168,26 +126,7 @@
168 $product_spec->generateLangs(); 126 $product_spec->generateLangs();
169 if($model->load(Yii::$app->request->post())) { 127 if($model->load(Yii::$app->request->post())) {
170 $model->loadLangs(\Yii::$app->request); 128 $model->loadLangs(\Yii::$app->request);
171 - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');  
172 - $model->certificateUpload = UploadedFile::getInstances($model, 'certificateUpload');  
173 if($model->save() && $model->transactionStatus) { 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 if($product_spec->load(Yii::$app->request->post())) { 130 if($product_spec->load(Yii::$app->request->post())) {
192 $product_spec->loadLangs(\Yii::$app->request); 131 $product_spec->loadLangs(\Yii::$app->request);
193 $product_spec->techSpecFile = UploadedFile::getInstance($product_spec, 'techSpecFile'); 132 $product_spec->techSpecFile = UploadedFile::getInstance($product_spec, 'techSpecFile');
@@ -225,7 +164,6 @@ @@ -225,7 +164,6 @@
225 { 164 {
226 $this->findModel($id) 165 $this->findModel($id)
227 ->delete(); 166 ->delete();
228 -  
229 return $this->redirect([ 'index' ]); 167 return $this->redirect([ 'index' ]);
230 } 168 }
231 169
common/modules/product/controllers/VariantController.php
@@ -9,11 +9,9 @@ @@ -9,11 +9,9 @@
9 use common\modules\product\models\ProductVariantListSearch; 9 use common\modules\product\models\ProductVariantListSearch;
10 use common\modules\product\models\Stock; 10 use common\modules\product\models\Stock;
11 use Yii; 11 use Yii;
12 - use yii\helpers\ArrayHelper;  
13 use yii\web\Controller; 12 use yii\web\Controller;
14 use yii\web\NotFoundHttpException; 13 use yii\web\NotFoundHttpException;
15 use yii\filters\VerbFilter; 14 use yii\filters\VerbFilter;
16 - use yii\web\UploadedFile;  
17 15
18 /** 16 /**
19 * ManageController implements the CRUD actions for ProductVariant model. 17 * ManageController implements the CRUD actions for ProductVariant model.
@@ -83,30 +81,7 @@ @@ -83,30 +81,7 @@
83 $model->generateLangs(); 81 $model->generateLangs();
84 if($model->load(Yii::$app->request->post())) { 82 if($model->load(Yii::$app->request->post())) {
85 $model->loadLangs(\Yii::$app->request); 83 $model->loadLangs(\Yii::$app->request);
86 - $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload');  
87 if($model->save() && $model->transactionStatus) { 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 $ProductStocks = Yii::$app->request->post('ProductStock'); 85 $ProductStocks = Yii::$app->request->post('ProductStock');
111 $total_quantity = 0; 86 $total_quantity = 0;
112 if(!empty( $ProductStocks ) && is_array($ProductStocks)) { 87 if(!empty( $ProductStocks ) && is_array($ProductStocks)) {
@@ -187,28 +162,6 @@ @@ -187,28 +162,6 @@
187 if($model->load(Yii::$app->request->post())) { 162 if($model->load(Yii::$app->request->post())) {
188 $model->loadLangs(\Yii::$app->request); 163 $model->loadLangs(\Yii::$app->request);
189 if($model->save() && $model->transactionStatus) { 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 $ProductStocks = Yii::$app->request->post('ProductStock'); 165 $ProductStocks = Yii::$app->request->post('ProductStock');
213 $total_quantity = 0; 166 $total_quantity = 0;
214 if(!empty( $ProductStocks ) && is_array($ProductStocks)) { 167 if(!empty( $ProductStocks ) && is_array($ProductStocks)) {
common/modules/product/models/Export.php
@@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
50 * @var Product[] $products 50 * @var Product[] $products
51 */ 51 */
52 $products = Product::find() 52 $products = Product::find()
53 - ->with('variantsWithFilters', 'brand.lang', 'categories.lang', 'filters') 53 + ->with('variantsWithFilters', 'brand.lang', 'categories.lang', 'filters', 'images')
54 ->joinWith('lang', true, 'INNER JOIN') 54 ->joinWith('lang', true, 'INNER JOIN')
55 ->limit($limit) 55 ->limit($limit)
56 ->offset($from) 56 ->offset($from)
@@ -71,6 +71,9 @@ @@ -71,6 +71,9 @@
71 } 71 }
72 72
73 $fotos = []; 73 $fotos = [];
  74 + foreach($product->images as $image) {
  75 + $fotos[] = $image->image;
  76 + }
74 77
75 $categories = []; 78 $categories = [];
76 foreach($product->categories as $value) { 79 foreach($product->categories as $value) {
@@ -80,20 +83,20 @@ @@ -80,20 +83,20 @@
80 $categories = implode(',', $categories); 83 $categories = implode(',', $categories);
81 84
82 $list = [ 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 $to_write = array_merge($list, $mods); 101 $to_write = array_merge($list, $mods);
99 fputcsv($handle, $to_write, ';'); 102 fputcsv($handle, $to_write, ';');
common/modules/product/models/Import.php
@@ -316,6 +316,10 @@ @@ -316,6 +316,10 @@
316 { 316 {
317 if(!empty( $fotos )) { 317 if(!empty( $fotos )) {
318 foreach($fotos as $foto) { 318 foreach($fotos as $foto) {
  319 +
  320 + if(empty($foto)){
  321 + continue;
  322 + }
319 $source_image = Yii::getAlias('@uploadDir') . '/product_images/' . urlencode($foto); 323 $source_image = Yii::getAlias('@uploadDir') . '/product_images/' . urlencode($foto);
320 if(file_exists($source_image)) { 324 if(file_exists($source_image)) {
321 if(( $productImage = ProductImage::find() 325 if(( $productImage = ProductImage::find()
@@ -410,7 +414,6 @@ @@ -410,7 +414,6 @@
410 $_productVariant->save(false); 414 $_productVariant->save(false);
411 415
412 $MOD_ARRAY[] = $_productVariant->product_variant_id; 416 $MOD_ARRAY[] = $_productVariant->product_variant_id;
413 -  
414 $this->saveFotos([ $mod_image ], $product_id, $_productVariant->product_variant_id); 417 $this->saveFotos([ $mod_image ], $product_id, $_productVariant->product_variant_id);
415 } 418 }
416 } 419 }
@@ -444,6 +447,8 @@ @@ -444,6 +447,8 @@
444 447
445 while(( empty( $limit ) || $j++ < $limit ) && ( $data = fgetcsv($handle, 10000, ";") ) !== false) { 448 while(( empty( $limit ) || $j++ < $limit ) && ( $data = fgetcsv($handle, 10000, ";") ) !== false) {
446 try { 449 try {
  450 +
  451 +
447 foreach($data as &$value) { 452 foreach($data as &$value) {
448 if(!$is_utf) { 453 if(!$is_utf) {
449 $value = iconv('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value); 454 $value = iconv('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value);
@@ -528,7 +533,6 @@ @@ -528,7 +533,6 @@
528 533
529 $options = []; 534 $options = [];
530 if(!empty ( $filters )) { 535 if(!empty ( $filters )) {
531 -  
532 $options = $this->saveFilters($filters, 0, $categories); 536 $options = $this->saveFilters($filters, 0, $categories);
533 } 537 }
534 $parsed_name = $this->parseName($product_name); 538 $parsed_name = $this->parseName($product_name);
common/modules/product/models/Product.php
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 2
3 namespace common\modules\product\models; 3 namespace common\modules\product\models;
4 4
  5 + use common\behaviors\MultipleImgBehavior;
  6 + use common\behaviors\SaveMultipleFileBehavior;
5 use common\models\ProductCertificate; 7 use common\models\ProductCertificate;
6 use common\models\ProductSpec; 8 use common\models\ProductSpec;
7 use common\models\ProductToRating; 9 use common\models\ProductToRating;
@@ -24,8 +26,6 @@ @@ -24,8 +26,6 @@
24 * @property Category[] $categories 26 * @property Category[] $categories
25 * @property ProductVariant[] $variants 27 * @property ProductVariant[] $variants
26 * @property ProductVariant $variant 28 * @property ProductVariant $variant
27 - * @property ProductImage $image  
28 - * @property ProductImage[] $images  
29 * @property boolean $is_top 29 * @property boolean $is_top
30 * @property boolean $is_new 30 * @property boolean $is_new
31 * @property boolean $akciya 31 * @property boolean $akciya
@@ -39,25 +39,33 @@ @@ -39,25 +39,33 @@
39 * @property ProductSpec $productSpec 39 * @property ProductSpec $productSpec
40 * @property ProductCertificate[] $productCertificates 40 * @property ProductCertificate[] $productCertificates
41 * * From language behavior * 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 * @method string getOwnerKey() 49 * @method string getOwnerKey()
50 - * @method void setOwnerKey(string $value) 50 + * @method void setOwnerKey( string $value )
51 * @method string getLangKey() 51 * @method string getLangKey()
52 - * @method void setLangKey(string $value) 52 + * @method void setLangKey( string $value )
53 * @method ActiveQuery getLangs() 53 * @method ActiveQuery getLangs()
54 * @method ActiveQuery getLang( integer $language_id ) 54 * @method ActiveQuery getLang( integer $language_id )
55 * @method ProductLang[] generateLangs() 55 * @method ProductLang[] generateLangs()
56 - * @method void loadLangs(Request $request) 56 + * @method void loadLangs( Request $request )
57 * @method bool linkLangs() 57 * @method bool linkLangs()
58 * @method bool saveLangs() 58 * @method bool saveLangs()
59 * @method bool getTransactionStatus() 59 * @method bool getTransactionStatus()
60 * * End language behavior * 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 class Product extends \yii\db\ActiveRecord 70 class Product extends \yii\db\ActiveRecord
63 { 71 {
@@ -65,8 +73,7 @@ @@ -65,8 +73,7 @@
65 /** @var array $_variants */ 73 /** @var array $_variants */
66 public $_variants = []; 74 public $_variants = [];
67 75
68 - /** @var array $_images */  
69 - public $imagesUpload = ''; 76 + public $imagesUpload = [];
70 77
71 public $certificateUpload = []; 78 public $certificateUpload = [];
72 79
@@ -76,10 +83,42 @@ @@ -76,10 +83,42 @@
76 public function behaviors() 83 public function behaviors()
77 { 84 {
78 return [ 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 'class' => FilterBehavior::className(), 119 'class' => FilterBehavior::className(),
81 ], 120 ],
82 - 'language' => [ 121 + 'language' => [
83 'class' => LanguageBehavior::className(), 122 'class' => LanguageBehavior::className(),
84 ], 123 ],
85 ]; 124 ];
@@ -159,33 +198,6 @@ @@ -159,33 +198,6 @@
159 { 198 {
160 return $this->hasOne(Brand::className(), [ 'brand_id' => 'brand_id' ]); 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 * @return \yii\db\ActiveQuery 203 * @return \yii\db\ActiveQuery
@@ -247,18 +259,15 @@ @@ -247,18 +259,15 @@
247 return empty( $this->brand ) ? $this->lang->name : $this->brand->lang->name . ' ' . $this->lang->name; 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 public function getCategories() 265 public function getCategories()
251 { 266 {
252 return $this->hasMany(Category::className(), [ 'category_id' => 'category_id' ]) 267 return $this->hasMany(Category::className(), [ 'category_id' => 'category_id' ])
253 ->viaTable('product_category', [ 'product_id' => 'product_id' ]); 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 public function getCategoriesNames() 271 public function getCategoriesNames()
263 { 272 {
264 $result = []; 273 $result = [];
@@ -347,135 +356,51 @@ @@ -347,135 +356,51 @@
347 ->where([ 'product_id' => $this->product_id ]) 356 ->where([ 'product_id' => $this->product_id ])
348 ->sum('quantity'); 357 ->sum('quantity');
349 } 358 }
350 - 359 +
351 public function afterSave($insert, $changedAttributes) 360 public function afterSave($insert, $changedAttributes)
352 { 361 {
353 parent::afterSave($insert, $changedAttributes); 362 parent::afterSave($insert, $changedAttributes);
354 -  
355 - if(!empty($this->categories)){ 363 +
  364 + if(!empty( $this->categories )) {
356 $categories = Category::findAll($this->categories); 365 $categories = Category::findAll($this->categories);
357 $this->unlinkAll('categories', true); 366 $this->unlinkAll('categories', true);
358 - foreach($categories as $category){ 367 + foreach($categories as $category) {
359 $this->link('categories', $category); 368 $this->link('categories', $category);
360 } 369 }
361 } 370 }
362 -  
363 - if(!empty($this->options)){ 371 +
  372 + if(!empty( $this->options )) {
364 $options = TaxOption::findAll($this->options); 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 $this->link('options', $option); 376 $this->link('options', $option);
368 } 377 }
369 } 378 }
370 -  
371 -  
372 - if (!empty($this->_variants)) { 379 +
  380 + if(!empty( $this->_variants )) {
373 $todel = []; 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 return; 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 } else { 392 } else {
385 $model = new ProductVariant(); 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 $model->product_id = $this->product_id; 397 $model->product_id = $this->product_id;
390 $model->save(); 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 public function recalculateRating() 406 public function recalculateRating()
common/modules/product/models/ProductImage.php
1 <?php 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 <?php 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 $query->andFilterWhere([ 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,6 +2,8 @@
2 2
3 namespace common\modules\product\models; 3 namespace common\modules\product\models;
4 4
  5 + use common\behaviors\MultipleImgBehavior;
  6 + use common\behaviors\SaveMultipleFileBehavior;
5 use common\modules\language\behaviors\LanguageBehavior; 7 use common\modules\language\behaviors\LanguageBehavior;
6 use common\modules\rubrication\models\TaxGroup; 8 use common\modules\rubrication\models\TaxGroup;
7 use common\modules\rubrication\models\TaxOption; 9 use common\modules\rubrication\models\TaxOption;
@@ -22,8 +24,6 @@ @@ -22,8 +24,6 @@
22 * @property double $price_old 24 * @property double $price_old
23 * @property double $stock 25 * @property double $stock
24 * @property integer $product_unit_id 26 * @property integer $product_unit_id
25 - * @property ProductImage $image  
26 - * @property array $images  
27 * @property TaxOption[] $options 27 * @property TaxOption[] $options
28 * @property ProductUnit $productUnit 28 * @property ProductUnit $productUnit
29 * @property Product $product 29 * @property Product $product
@@ -47,6 +47,14 @@ @@ -47,6 +47,14 @@
47 * @method bool saveLangs() 47 * @method bool saveLangs()
48 * @method bool getTransactionStatus() 48 * @method bool getTransactionStatus()
49 * * End language behavior * 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 class ProductVariant extends ActiveRecord 59 class ProductVariant extends ActiveRecord
52 { 60 {
@@ -58,7 +66,7 @@ @@ -58,7 +66,7 @@
58 private $_options; 66 private $_options;
59 67
60 /** @var array $_images */ 68 /** @var array $_images */
61 - public $imagesUpload = ''; 69 + public $imagesUpload = [];
62 70
63 /** 71 /**
64 * @inheritdoc 72 * @inheritdoc
@@ -71,9 +79,32 @@ @@ -71,9 +79,32 @@
71 public function behaviors() 79 public function behaviors()
72 { 80 {
73 return [ 81 return [
74 - 'language' => [ 82 + 'language' => [
75 'class' => LanguageBehavior::className(), 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,7 +146,6 @@
115 [ 146 [
116 [ 147 [
117 'options', 148 'options',
118 - 'imagesUpload',  
119 ], 149 ],
120 'safe', 150 'safe',
121 ], 151 ],
@@ -204,70 +234,11 @@ @@ -204,70 +234,11 @@
204 ->joinWith('lang', true, 'INNER JOIN'); 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 public function getFullname() 237 public function getFullname()
226 { 238 {
227 return empty( $this->product ) ? NULL : ( $this->product->lang->name . ( empty( $this->lang->name ) ? '' : ' ' . $this->lang->name ) ); 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 public function setOptions($values) 242 public function setOptions($values)
272 { 243 {
273 $this->_options = $values; 244 $this->_options = $values;
@@ -348,7 +319,6 @@ @@ -348,7 +319,6 @@
348 319
349 if(!empty( $this->stocks )) { 320 if(!empty( $this->stocks )) {
350 ProductStock::deleteAll([ 'product_variant_id' => $this->product_variant_id ]); 321 ProductStock::deleteAll([ 'product_variant_id' => $this->product_variant_id ]);
351 - $values = [];  
352 foreach($this->stocks as $id => $quantity) { 322 foreach($this->stocks as $id => $quantity) {
353 $productStock = ProductStock::find() 323 $productStock = ProductStock::find()
354 ->where([ 324 ->where([
@@ -362,24 +332,4 @@ @@ -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 <?php 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 <div class="product-index"> 19 <div class="product-index">
18 - 20 +
19 <h1><?= Html::encode($this->title) ?></h1> 21 <h1><?= Html::encode($this->title) ?></h1>
20 - 22 +
21 <p> 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 </p> 25 </p>
24 <?= GridView::widget([ 26 <?= GridView::widget([
25 'dataProvider' => $dataProvider, 27 'dataProvider' => $dataProvider,
26 - 'filterModel' => $searchModel,  
27 - 'columns' => [  
28 - ['class' => 'yii\grid\SerialColumn'], 28 + 'filterModel' => $searchModel,
  29 + 'columns' => [
29 'product_id', 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 return Html::a('<span class="glyphicon glyphicon-th-list"></span>', $url, [ 111 return Html::a('<span class="glyphicon glyphicon-th-list"></span>', $url, [
107 'title' => Yii::t('product', 'Variants'), 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 case 'items': 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 break; 124 break;
117 case 'is_top': 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 break; 130 break;
120 case 'is_new': 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 break; 136 break;
123 case 'akciya': 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 break; 142 break;
126 case 'view': 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 break; 148 break;
129 case 'update': 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 break; 154 break;
132 case 'delete': 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 break; 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,13 +53,12 @@ $(&quot;.dynamicform_wrapper&quot;).on(&quot;limitReached&quot;, function(e, item) {
53 ->textarea(); ?> 53 ->textarea(); ?>
54 <?= $form->field($model, 'price_old') 54 <?= $form->field($model, 'price_old')
55 ->textarea(); ?> 55 ->textarea(); ?>
56 - <?= $form->field($model, 'image') 56 + <?= $form->field($model, 'imagesUpload[]')
57 ->widget(\kartik\file\FileInput::className(), [ 57 ->widget(\kartik\file\FileInput::className(), [
58 - 'model' => $model,  
59 - 'attribute' => 'image', 58 + 'language' => 'ru',
60 'options' => [ 59 'options' => [
61 'accept' => 'image/*', 60 'accept' => 'image/*',
62 - 'multiple' => false, 61 + 'multiple' => true,
63 ], 62 ],
64 'pluginOptions' => [ 63 'pluginOptions' => [
65 'allowedFileExtensions' => [ 64 'allowedFileExtensions' => [
@@ -67,10 +66,13 @@ $(&quot;.dynamicform_wrapper&quot;).on(&quot;limitReached&quot;, function(e, item) { @@ -67,10 +66,13 @@ $(&quot;.dynamicform_wrapper&quot;).on(&quot;limitReached&quot;, function(e, item) {
67 'gif', 66 'gif',
68 'png', 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 'showUpload' => false, 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