Commit 14cd7eed2849cf5ca2b52e8caaaf957f9ea0d0e3

Authored by Yarik
1 parent 96410438

LanguageBehavior optimized

backend/controllers/ArticlesController.php
@@ -82,10 +82,9 @@ @@ -82,10 +82,9 @@
82 public function actionCreate() 82 public function actionCreate()
83 { 83 {
84 $model = new Articles(); 84 $model = new Articles();
85 - $model_langs = $model->generateLangs(); 85 + $model->generateLangs();
86 if($model->load(Yii::$app->request->post())) { 86 if($model->load(Yii::$app->request->post())) {
87 - $model->loadLangs(\Yii::$app->request, $model_langs);  
88 - $model->model_langs = $model_langs; 87 + $model->loadLangs(\Yii::$app->request);
89 if($model->save() && $model->transactionStatus) { 88 if($model->save() && $model->transactionStatus) {
90 return $this->redirect([ 89 return $this->redirect([
91 'view', 90 'view',
@@ -95,7 +94,7 @@ @@ -95,7 +94,7 @@
95 } 94 }
96 return $this->render('create', [ 95 return $this->render('create', [
97 'model' => $model, 96 'model' => $model,
98 - 'model_langs' => $model_langs, 97 + 'model_langs' => $model->model_langs,
99 ]); 98 ]);
100 } 99 }
101 100
@@ -110,10 +109,9 @@ @@ -110,10 +109,9 @@
110 public function actionUpdate($id) 109 public function actionUpdate($id)
111 { 110 {
112 $model = $this->findModel($id); 111 $model = $this->findModel($id);
113 - $model_langs = $model->generateLangs(); 112 + $model->generateLangs();
114 if($model->load(Yii::$app->request->post())) { 113 if($model->load(Yii::$app->request->post())) {
115 - $model->loadLangs(\Yii::$app->request, $model_langs);  
116 - $model->model_langs = $model_langs; 114 + $model->loadLangs(\Yii::$app->request);
117 if($model->save() && $model->transactionStatus) { 115 if($model->save() && $model->transactionStatus) {
118 return $this->redirect([ 116 return $this->redirect([
119 'view', 117 'view',
@@ -123,7 +121,7 @@ @@ -123,7 +121,7 @@
123 } 121 }
124 return $this->render('update', [ 122 return $this->render('update', [
125 'model' => $model, 123 'model' => $model,
126 - 'model_langs' => $model_langs, 124 + 'model_langs' => $model->model_langs,
127 ]); 125 ]);
128 } 126 }
129 127
common/models/Articles.php
1 <?php 1 <?php
2 2
3 namespace common\models; 3 namespace common\models;
4 - 4 +
5 use common\modules\language\behaviors\TransactionBehavior; 5 use common\modules\language\behaviors\TransactionBehavior;
6 use common\modules\language\behaviors\LanguageBehavior; 6 use common\modules\language\behaviors\LanguageBehavior;
7 use common\behaviors\SaveImgBehavior; 7 use common\behaviors\SaveImgBehavior;
@@ -22,26 +22,23 @@ @@ -22,26 +22,23 @@
22 * @property ArticlesLang $object_lang 22 * @property ArticlesLang $object_lang
23 * @property string $ownerKey 23 * @property string $ownerKey
24 * @property string $langKey 24 * @property string $langKey
  25 + * @property ArticlesLang[] $model_langs
  26 + * @property bool $transactionStatus
25 * @method string getOwnerKey() 27 * @method string getOwnerKey()
26 - * @method void setOwnerKey(string $value) 28 + * @method void setOwnerKey( string $value )
27 * @method string getLangKey() 29 * @method string getLangKey()
28 - * @method void setLangKey(string $value) 30 + * @method void setLangKey( string $value )
29 * @method ActiveQuery getLangs() 31 * @method ActiveQuery getLangs()
30 * @method ActiveQuery getLang( integer $language_id ) 32 * @method ActiveQuery getLang( integer $language_id )
31 * @method ArticlesLang[] generateLangs() 33 * @method ArticlesLang[] generateLangs()
32 - * @method void loadLangs(Request $request, ActiveRecord[] $model_langs)  
33 - * @method bool linkLangs(ActiveRecord[] $model_langs)  
34 - * @method bool saveLangs(ActiveRecord[] $model_langs)  
35 - * * End language behavior *  
36 - * * From transaction behavior *  
37 - * @property ArticlesLang[] $model_langs  
38 - * @property bool $transactionStatus 34 + * @method void loadLangs( Request $request )
  35 + * @method bool linkLangs()
  36 + * @method bool saveLangs()
39 * @method bool getTransactionStatus() 37 * @method bool getTransactionStatus()
40 - * * End transaction behavior * 38 + * * End language behavior *
41 */ 39 */
42 class Articles extends \yii\db\ActiveRecord 40 class Articles extends \yii\db\ActiveRecord
43 { 41 {
44 - public $imageUpload;  
45 42
46 /** 43 /**
47 * @inheritdoc 44 * @inheritdoc
@@ -58,20 +55,17 @@ @@ -58,20 +55,17 @@
58 { 55 {
59 return [ 56 return [
60 [ 57 [
61 - 'class' => SaveImgBehavior::className(), 58 + 'class' => SaveImgBehavior::className(),
62 'fields' => [ 59 'fields' => [
63 [ 60 [
64 - 'name' => 'image', 61 + 'name' => 'image',
65 'directory' => 'articles', 62 'directory' => 'articles',
66 - ] 63 + ],
67 ], 64 ],
68 ], 65 ],
69 'language' => [ 66 'language' => [
70 'class' => LanguageBehavior::className(), 67 'class' => LanguageBehavior::className(),
71 ], 68 ],
72 - 'transaction' => [  
73 - 'class' => TransactionBehavior::className(),  
74 - ],  
75 ]; 69 ];
76 } 70 }
77 71
@@ -93,22 +87,6 @@ @@ -93,22 +87,6 @@
93 'safe', 87 'safe',
94 ], 88 ],
95 [ 89 [
96 - [  
97 - 'image',  
98 - ],  
99 - 'string',  
100 - 'max' => 255,  
101 - ],  
102 - [  
103 - [ 'imageUpload' ],  
104 - 'safe',  
105 - ],  
106 - [  
107 - [ 'imageUpload' ],  
108 - 'file',  
109 - 'extensions' => 'jpg, gif, png',  
110 - ],  
111 - [  
112 [ 'date' ], 90 [ 'date' ],
113 'filter', 91 'filter',
114 'filter' => function($value) { 92 'filter' => function($value) {
@@ -124,23 +102,13 @@ @@ -124,23 +102,13 @@
124 public function attributeLabels() 102 public function attributeLabels()
125 { 103 {
126 return [ 104 return [
127 - 'id' => Yii::t('app', 'ID'),  
128 - 'date' => Yii::t('app', 'Date'),  
129 - 'image' => Yii::t('app', 'Image'),  
130 - 'imageUrl' => Yii::t('app', 'Image'), 105 + 'id' => Yii::t('app', 'ID'),
  106 + 'date' => Yii::t('app', 'Date'),
  107 + 'image' => Yii::t('app', 'Image'),
  108 + 'imageUrl' => Yii::t('app', 'Image'),
131 ]; 109 ];
132 } 110 }
133 111
134 - public function getImageFile()  
135 - {  
136 - return empty( $this->image ) ? NULL : Yii::getAlias('@imagesDir/articles/' . $this->image);  
137 - }  
138 -  
139 - public function getImageUrl()  
140 - {  
141 - return empty( $this->image ) ? NULL : Yii::getAlias('@imagesUrl/articles/' . $this->image);  
142 - }  
143 -  
144 public function recalculateRating() 112 public function recalculateRating()
145 { 113 {
146 /** 114 /**
common/modules/language/behaviors/LanguageBehavior.php
@@ -6,15 +6,16 @@ @@ -6,15 +6,16 @@
6 use yii\base\InvalidConfigException; 6 use yii\base\InvalidConfigException;
7 use yii\db\ActiveQuery; 7 use yii\db\ActiveQuery;
8 use yii\db\ActiveRecord; 8 use yii\db\ActiveRecord;
  9 + use yii\db\Transaction;
9 use yii\web\Request; 10 use yii\web\Request;
10 11
11 /** 12 /**
12 * Class LanguageBehavior 13 * Class LanguageBehavior
13 - * @property ActiveRecord $owner  
14 - * @property string $ownerKey  
15 - * @property string $langKey 14 + * @property ActiveRecord $owner
  15 + * @property string $ownerKey
  16 + * @property string $langKey
16 * @property ActiveRecord[] $langs 17 * @property ActiveRecord[] $langs
17 - * @property ActiveRecord $lang 18 + * @property ActiveRecord $lang
18 */ 19 */
19 class LanguageBehavior extends Behavior 20 class LanguageBehavior extends Behavior
20 { 21 {
@@ -24,11 +25,36 @@ @@ -24,11 +25,36 @@
24 */ 25 */
25 public $object_lang; 26 public $object_lang;
26 27
  28 + /**
  29 + * @var ActiveRecord[] $model_langs
  30 + */
  31 + public $model_langs = [];
  32 +
27 private $_owner_key; 33 private $_owner_key;
28 34
29 private $_lang_key; 35 private $_lang_key;
30 36
31 /** 37 /**
  38 + * @var Transaction $_transaction
  39 + */
  40 + private $_transaction;
  41 +
  42 + /**
  43 + * @var bool $_transaction_status
  44 + */
  45 + private $_transaction_status = false;
  46 +
  47 + public function events()
  48 + {
  49 + return [
  50 + ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
  51 + ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeSave',
  52 + ActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
  53 + ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
  54 + ];
  55 + }
  56 +
  57 + /**
32 * Get $owner primary key to link language model 58 * Get $owner primary key to link language model
33 * @return string 59 * @return string
34 */ 60 */
@@ -129,19 +155,20 @@ @@ -129,19 +155,20 @@
129 $table_name = $object_lang::getTableSchema()->name; 155 $table_name = $object_lang::getTableSchema()->name;
130 $owner = $this->owner; 156 $owner = $this->owner;
131 return $owner->hasOne($object_lang::className(), [ $this->getLangKey() => $this->getOwnerKey() ]) 157 return $owner->hasOne($object_lang::className(), [ $this->getLangKey() => $this->getOwnerKey() ])
132 - ->where([ $table_name.'.language_id' => $language_id ]); 158 + ->where([ $table_name . '.language_id' => $language_id ]);
133 } 159 }
134 160
135 /** 161 /**
136 * Generate language models for $owner for active languages. If $owner not new and language 162 * Generate language models for $owner for active languages. If $owner not new and language
137 * models already inserted, models will be filled with them. 163 * models already inserted, models will be filled with them.
138 - * @return ActiveRecord[] 164 + * @return void
139 */ 165 */
140 public function generateLangs() 166 public function generateLangs()
141 { 167 {
142 $owner = $this->owner; 168 $owner = $this->owner;
143 $languages = Language::find() 169 $languages = Language::find()
144 ->where([ 'status' => true ]) 170 ->where([ 'status' => true ])
  171 + ->orderBy([ 'language_id' => SORT_ASC ])
145 ->asArray() 172 ->asArray()
146 ->column(); 173 ->column();
147 $object_lang = $this->object_lang; 174 $object_lang = $this->object_lang;
@@ -150,6 +177,7 @@ @@ -150,6 +177,7 @@
150 if(!$owner->isNewRecord) { 177 if(!$owner->isNewRecord) {
151 $langs = $this->getLangs() 178 $langs = $this->getLangs()
152 ->andFilterWhere([ 'language_id' => $languages ]) 179 ->andFilterWhere([ 'language_id' => $languages ])
  180 + ->orderBy([ 'language_id' => SORT_ASC ])
153 ->all(); 181 ->all();
154 } 182 }
155 foreach($languages as $language) { 183 foreach($languages as $language) {
@@ -161,21 +189,20 @@ @@ -161,21 +189,20 @@
161 ]); 189 ]);
162 } 190 }
163 } 191 }
164 - return $langs; 192 + $this->model_langs = $langs;
165 } 193 }
166 194
167 /** 195 /**
168 * Load language models with post data. 196 * Load language models with post data.
169 * 197 *
170 - * @param Request $request  
171 - * @param ActiveRecord[] $model_langs 198 + * @param Request $request
172 */ 199 */
173 - public function loadLangs(Request $request, array $model_langs) 200 + public function loadLangs(Request $request)
174 { 201 {
175 foreach($request->post($this->object_lang->formName(), []) as $lang => $value) { 202 foreach($request->post($this->object_lang->formName(), []) as $lang => $value) {
176 - if(!empty( $model_langs[ $lang ] )) {  
177 - $model_langs[ $lang ]->attributes = $value;  
178 - $model_langs[ $lang ]->language_id = $lang; 203 + if(!empty( $this->model_langs[ $lang ] )) {
  204 + $this->model_langs[ $lang ]->attributes = $value;
  205 + $this->model_langs[ $lang ]->language_id = $lang;
179 } 206 }
180 } 207 }
181 } 208 }
@@ -183,12 +210,9 @@ @@ -183,12 +210,9 @@
183 /** 210 /**
184 * Link language models with $owner by setting language model language key to owner key of 211 * Link language models with $owner by setting language model language key to owner key of
185 * owner 212 * owner
186 - *  
187 - * @param ActiveRecord[] $model_langs  
188 - *  
189 * @return bool If $owner is new record then return false else true 213 * @return bool If $owner is new record then return false else true
190 */ 214 */
191 - public function linkLangs(array $model_langs) 215 + public function linkLangs()
192 { 216 {
193 $owner = $this->owner; 217 $owner = $this->owner;
194 if($owner->isNewRecord) { 218 if($owner->isNewRecord) {
@@ -196,6 +220,7 @@ @@ -196,6 +220,7 @@
196 } 220 }
197 $lang_key = $this->getLangKey(); 221 $lang_key = $this->getLangKey();
198 $owner_key = $this->getOwnerKey(); 222 $owner_key = $this->getOwnerKey();
  223 + $model_langs = $this->model_langs;
199 foreach($model_langs as $model_lang) { 224 foreach($model_langs as $model_lang) {
200 $model_lang->$lang_key = $owner->$owner_key; 225 $model_lang->$lang_key = $owner->$owner_key;
201 } 226 }
@@ -204,14 +229,12 @@ @@ -204,14 +229,12 @@
204 229
205 /** 230 /**
206 * Try to save all language models to the db. Validation function is run for all models. 231 * Try to save all language models to the db. Validation function is run for all models.
207 - *  
208 - * @param ActiveRecord[] $model_langs  
209 - *  
210 * @return bool Whether all models are valid 232 * @return bool Whether all models are valid
211 */ 233 */
212 - public function saveLangs(array $model_langs) 234 + public function saveLangs()
213 { 235 {
214 $success = true; 236 $success = true;
  237 + $model_langs = $this->model_langs;
215 foreach($model_langs as $model_lang) { 238 foreach($model_langs as $model_lang) {
216 if(!$model_lang->save()) { 239 if(!$model_lang->save()) {
217 $success = false; 240 $success = false;
@@ -219,4 +242,42 @@ @@ -219,4 +242,42 @@
219 } 242 }
220 return $success; 243 return $success;
221 } 244 }
  245 +
  246 + public function beforeSave($event)
  247 + {
  248 + /**
  249 + * @var ActiveRecord $owner
  250 + */
  251 + $owner = $this->owner;
  252 + $db = $owner::getDb();
  253 + $this->_transaction = $db->beginTransaction();
  254 + }
  255 +
  256 + public function afterSave($event)
  257 + {
  258 + /**
  259 + * @var ActiveRecord $owner
  260 + */
  261 + $owner = $this->owner;
  262 + if(!empty( $this->model_langs )) {
  263 + if($this->linkLangs() && $this->saveLangs()) {
  264 + $this->_transaction->commit();
  265 + $this->_transaction_status = true;
  266 + } else {
  267 + $this->_transaction->rollBack();
  268 + $this->_transaction_status = false;
  269 + }
  270 + } else {
  271 + $this->_transaction->commit();
  272 + $this->_transaction_status = true;
  273 + }
  274 + }
  275 +
  276 + /**
  277 + * @return bool
  278 + */
  279 + public function getTransactionStatus():bool
  280 + {
  281 + return $this->_transaction_status;
  282 + }
222 } 283 }
223 \ No newline at end of file 284 \ No newline at end of file
common/modules/language/readme.txt
@@ -57,6 +57,8 @@ public function behaviors() { @@ -57,6 +57,8 @@ public function behaviors() {
57 * @property {TableLang} $object_lang 57 * @property {TableLang} $object_lang
58 * @property string $ownerKey 58 * @property string $ownerKey
59 * @property string $langKey 59 * @property string $langKey
  60 + * @property {TableLang}[] $model_langs
  61 + * @property bool $transactionStatus
60 * @method string getOwnerKey() 62 * @method string getOwnerKey()
61 * @method void setOwnerKey(string $value) 63 * @method void setOwnerKey(string $value)
62 * @method string getLangKey() 64 * @method string getLangKey()
@@ -67,20 +69,16 @@ public function behaviors() { @@ -67,20 +69,16 @@ public function behaviors() {
67 * @method void loadLangs(Request $request, ActiveRecord[] $model_langs) 69 * @method void loadLangs(Request $request, ActiveRecord[] $model_langs)
68 * @method bool linkLangs(ActiveRecord[] $model_langs) 70 * @method bool linkLangs(ActiveRecord[] $model_langs)
69 * @method bool saveLangs(ActiveRecord[] $model_langs) 71 * @method bool saveLangs(ActiveRecord[] $model_langs)
70 - * * End language behavior *  
71 - * * From transaction behavior *  
72 - * @property {TableLang}[] $model_langs  
73 - * @property bool $transactionStatus  
74 * @method bool getTransactionStatus() 72 * @method bool getTransactionStatus()
75 - * * End transaction behavior * 73 + * * End language behavior *
76 3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...) 74 3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...)
77 4. Доступные полезные методы: 75 4. Доступные полезные методы:
78 {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id 76 {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id
79 {Table}->getLang($language_id = NULL) - получить {TableLang} для определенного языка (default: текущий язык) для {Table} 77 {Table}->getLang($language_id = NULL) - получить {TableLang} для определенного языка (default: текущий язык) для {Table}
80 {Table}->generateLangs() - получить массив {TableLang} под каждый язык, включая существующие записи, для {Table} 78 {Table}->generateLangs() - получить массив {TableLang} под каждый язык, включая существующие записи, для {Table}
81 - {Table}->loadLangs($request, $model_langs) - заполнить массив {TableLang} данными с POST  
82 - {Table}->linkLangs($model_langs) - связать каждый элемент массива {TableLang} с текущей {Table}  
83 - {Table}->saveLangs($model_langs) - провалидировать и сохранить каждый элемент массива {TableLang} 79 + {Table}->loadLangs($request) - заполнить массив {TableLang} данными с POST
  80 + {Table}->linkLangs() - связать каждый элемент массива {TableLang} с текущей {Table}
  81 + {Table}->saveLangs() - провалидировать и сохранить каждый элемент массива {TableLang}
84 5. Добавить поля в форму (к примеру через Bootstrap Tabs). 82 5. Добавить поля в форму (к примеру через Bootstrap Tabs).
85 В наличии: 83 В наличии:
86 LanguageForm::widget([ 84 LanguageForm::widget([
@@ -90,7 +88,6 @@ public function behaviors() { @@ -90,7 +88,6 @@ public function behaviors() {
90 ]); 88 ]);
91 6. Обрабатывать данные в контроллере. 89 6. Обрабатывать данные в контроллере.
92 1. После создания/поиска {Table} создаем/находим языковые модели {Table}->generateLangs() 90 1. После создания/поиска {Table} создаем/находим языковые модели {Table}->generateLangs()
93 - 2. При POST запросе загружаем данные в языковые модели {Table}->loadLangs(Request $request, {TableLangs[]} $model_langs)  
94 - 3. Передаем в свойство model_langs модели {Table} массив {TableLang[]}: $model->model_langs = $model_langs  
95 - 4. После сохранения, если транзанкция успешна, то свойство {Table}->transactionStatus будет true, иначе возникла ошибка в какой то модели. 91 + 2. При POST запросе загружаем данные в языковые модели {Table}->loadLangs(Request $request)
  92 + 3. После сохранения, если транзанкция успешна, то свойство {Table}->transactionStatus будет true, иначе возникла ошибка в какой то модели.
96 7. Получать данные на публичной части сайта через {Table}->lang. 93 7. Получать данные на публичной части сайта через {Table}->lang.