Commit 14cd7eed2849cf5ca2b52e8caaaf957f9ea0d0e3

Authored by Yarik
1 parent 96410438

LanguageBehavior optimized

backend/controllers/ArticlesController.php
... ... @@ -82,10 +82,9 @@
82 82 public function actionCreate()
83 83 {
84 84 $model = new Articles();
85   - $model_langs = $model->generateLangs();
  85 + $model->generateLangs();
86 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 88 if($model->save() && $model->transactionStatus) {
90 89 return $this->redirect([
91 90 'view',
... ... @@ -95,7 +94,7 @@
95 94 }
96 95 return $this->render('create', [
97 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 109 public function actionUpdate($id)
111 110 {
112 111 $model = $this->findModel($id);
113   - $model_langs = $model->generateLangs();
  112 + $model->generateLangs();
114 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 115 if($model->save() && $model->transactionStatus) {
118 116 return $this->redirect([
119 117 'view',
... ... @@ -123,7 +121,7 @@
123 121 }
124 122 return $this->render('update', [
125 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 1 <?php
2 2  
3 3 namespace common\models;
4   -
  4 +
5 5 use common\modules\language\behaviors\TransactionBehavior;
6 6 use common\modules\language\behaviors\LanguageBehavior;
7 7 use common\behaviors\SaveImgBehavior;
... ... @@ -22,26 +22,23 @@
22 22 * @property ArticlesLang $object_lang
23 23 * @property string $ownerKey
24 24 * @property string $langKey
  25 + * @property ArticlesLang[] $model_langs
  26 + * @property bool $transactionStatus
25 27 * @method string getOwnerKey()
26   - * @method void setOwnerKey(string $value)
  28 + * @method void setOwnerKey( string $value )
27 29 * @method string getLangKey()
28   - * @method void setLangKey(string $value)
  30 + * @method void setLangKey( string $value )
29 31 * @method ActiveQuery getLangs()
30 32 * @method ActiveQuery getLang( integer $language_id )
31 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 37 * @method bool getTransactionStatus()
40   - * * End transaction behavior *
  38 + * * End language behavior *
41 39 */
42 40 class Articles extends \yii\db\ActiveRecord
43 41 {
44   - public $imageUpload;
45 42  
46 43 /**
47 44 * @inheritdoc
... ... @@ -58,20 +55,17 @@
58 55 {
59 56 return [
60 57 [
61   - 'class' => SaveImgBehavior::className(),
  58 + 'class' => SaveImgBehavior::className(),
62 59 'fields' => [
63 60 [
64   - 'name' => 'image',
  61 + 'name' => 'image',
65 62 'directory' => 'articles',
66   - ]
  63 + ],
67 64 ],
68 65 ],
69 66 'language' => [
70 67 'class' => LanguageBehavior::className(),
71 68 ],
72   - 'transaction' => [
73   - 'class' => TransactionBehavior::className(),
74   - ],
75 69 ];
76 70 }
77 71  
... ... @@ -93,22 +87,6 @@
93 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 90 [ 'date' ],
113 91 'filter',
114 92 'filter' => function($value) {
... ... @@ -124,23 +102,13 @@
124 102 public function attributeLabels()
125 103 {
126 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 112 public function recalculateRating()
145 113 {
146 114 /**
... ...
common/modules/language/behaviors/LanguageBehavior.php
... ... @@ -6,15 +6,16 @@
6 6 use yii\base\InvalidConfigException;
7 7 use yii\db\ActiveQuery;
8 8 use yii\db\ActiveRecord;
  9 + use yii\db\Transaction;
9 10 use yii\web\Request;
10 11  
11 12 /**
12 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 17 * @property ActiveRecord[] $langs
17   - * @property ActiveRecord $lang
  18 + * @property ActiveRecord $lang
18 19 */
19 20 class LanguageBehavior extends Behavior
20 21 {
... ... @@ -24,11 +25,36 @@
24 25 */
25 26 public $object_lang;
26 27  
  28 + /**
  29 + * @var ActiveRecord[] $model_langs
  30 + */
  31 + public $model_langs = [];
  32 +
27 33 private $_owner_key;
28 34  
29 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 58 * Get $owner primary key to link language model
33 59 * @return string
34 60 */
... ... @@ -129,19 +155,20 @@
129 155 $table_name = $object_lang::getTableSchema()->name;
130 156 $owner = $this->owner;
131 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 162 * Generate language models for $owner for active languages. If $owner not new and language
137 163 * models already inserted, models will be filled with them.
138   - * @return ActiveRecord[]
  164 + * @return void
139 165 */
140 166 public function generateLangs()
141 167 {
142 168 $owner = $this->owner;
143 169 $languages = Language::find()
144 170 ->where([ 'status' => true ])
  171 + ->orderBy([ 'language_id' => SORT_ASC ])
145 172 ->asArray()
146 173 ->column();
147 174 $object_lang = $this->object_lang;
... ... @@ -150,6 +177,7 @@
150 177 if(!$owner->isNewRecord) {
151 178 $langs = $this->getLangs()
152 179 ->andFilterWhere([ 'language_id' => $languages ])
  180 + ->orderBy([ 'language_id' => SORT_ASC ])
153 181 ->all();
154 182 }
155 183 foreach($languages as $language) {
... ... @@ -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 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 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 210 /**
184 211 * Link language models with $owner by setting language model language key to owner key of
185 212 * owner
186   - *
187   - * @param ActiveRecord[] $model_langs
188   - *
189 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 217 $owner = $this->owner;
194 218 if($owner->isNewRecord) {
... ... @@ -196,6 +220,7 @@
196 220 }
197 221 $lang_key = $this->getLangKey();
198 222 $owner_key = $this->getOwnerKey();
  223 + $model_langs = $this->model_langs;
199 224 foreach($model_langs as $model_lang) {
200 225 $model_lang->$lang_key = $owner->$owner_key;
201 226 }
... ... @@ -204,14 +229,12 @@
204 229  
205 230 /**
206 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 232 * @return bool Whether all models are valid
211 233 */
212   - public function saveLangs(array $model_langs)
  234 + public function saveLangs()
213 235 {
214 236 $success = true;
  237 + $model_langs = $this->model_langs;
215 238 foreach($model_langs as $model_lang) {
216 239 if(!$model_lang->save()) {
217 240 $success = false;
... ... @@ -219,4 +242,42 @@
219 242 }
220 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 284 \ No newline at end of file
... ...
common/modules/language/readme.txt
... ... @@ -57,6 +57,8 @@ public function behaviors() {
57 57 * @property {TableLang} $object_lang
58 58 * @property string $ownerKey
59 59 * @property string $langKey
  60 + * @property {TableLang}[] $model_langs
  61 + * @property bool $transactionStatus
60 62 * @method string getOwnerKey()
61 63 * @method void setOwnerKey(string $value)
62 64 * @method string getLangKey()
... ... @@ -67,20 +69,16 @@ public function behaviors() {
67 69 * @method void loadLangs(Request $request, ActiveRecord[] $model_langs)
68 70 * @method bool linkLangs(ActiveRecord[] $model_langs)
69 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 72 * @method bool getTransactionStatus()
75   - * * End transaction behavior *
  73 + * * End language behavior *
76 74 3.2. Убрать language behavior с наследуемых таблиц от {Table} ({TableSearch}...)
77 75 4. Доступные полезные методы:
78 76 {Table}->getLangs() - получить все текущие {TableLang} для {Table} проиндексированные по language_id
79 77 {Table}->getLang($language_id = NULL) - получить {TableLang} для определенного языка (default: текущий язык) для {Table}
80 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 82 5. Добавить поля в форму (к примеру через Bootstrap Tabs).
85 83 В наличии:
86 84 LanguageForm::widget([
... ... @@ -90,7 +88,6 @@ public function behaviors() {
90 88 ]);
91 89 6. Обрабатывать данные в контроллере.
92 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 93 7. Получать данные на публичной части сайта через {Table}->lang.
... ...