Blame view

common/modules/language/behaviors/LanguageBehavior.php 9.26 KB
d55d2fe0   Yarik   Multilanguage
1
2
3
4
  <?php
      namespace common\modules\language\behaviors;
      
      use common\modules\language\models\Language;
d55d2fe0   Yarik   Multilanguage
5
6
7
8
      use yii\base\Behavior;
      use yii\base\InvalidConfigException;
      use yii\db\ActiveQuery;
      use yii\db\ActiveRecord;
14cd7eed   Yarik   LanguageBehavior ...
9
      use yii\db\Transaction;
d55d2fe0   Yarik   Multilanguage
10
11
12
13
      use yii\web\Request;
      
      /**
       * Class LanguageBehavior
14cd7eed   Yarik   LanguageBehavior ...
14
15
16
       * @property ActiveRecord   $owner
       * @property string         $ownerKey
       * @property string         $langKey
d55d2fe0   Yarik   Multilanguage
17
       * @property ActiveRecord[] $langs
14cd7eed   Yarik   LanguageBehavior ...
18
       * @property ActiveRecord   $lang
d55d2fe0   Yarik   Multilanguage
19
20
21
22
23
       */
      class LanguageBehavior extends Behavior
      {
          
          /**
8af13427   Yarik   For leha commit.
24
           * @var ActiveRecord $objectLang Empty language model for $owner
d55d2fe0   Yarik   Multilanguage
25
           */
8af13427   Yarik   For leha commit.
26
          public $objectLang;
d55d2fe0   Yarik   Multilanguage
27
          
14cd7eed   Yarik   LanguageBehavior ...
28
          /**
8af13427   Yarik   For leha commit.
29
           * @var ActiveRecord[] $modelLangs
14cd7eed   Yarik   LanguageBehavior ...
30
           */
8af13427   Yarik   For leha commit.
31
          public $modelLangs = [];
14cd7eed   Yarik   LanguageBehavior ...
32
          
8af13427   Yarik   For leha commit.
33
          private $ownerKey;
d55d2fe0   Yarik   Multilanguage
34
          
8af13427   Yarik   For leha commit.
35
          private $langKey;
d55d2fe0   Yarik   Multilanguage
36
37
          
          /**
8af13427   Yarik   For leha commit.
38
           * @var Transaction $transaction
14cd7eed   Yarik   LanguageBehavior ...
39
           */
8af13427   Yarik   For leha commit.
40
          private $transaction;
14cd7eed   Yarik   LanguageBehavior ...
41
42
          
          /**
8af13427   Yarik   For leha commit.
43
           * @var bool $transactionStatus
14cd7eed   Yarik   LanguageBehavior ...
44
           */
8af13427   Yarik   For leha commit.
45
          private $transactionStatus = false;
14cd7eed   Yarik   LanguageBehavior ...
46
47
48
49
50
51
52
53
54
55
56
57
          
          public function events()
          {
              return [
                  ActiveRecord::EVENT_BEFORE_INSERT => 'beforeSave',
                  ActiveRecord::EVENT_BEFORE_UPDATE => 'beforeSave',
                  ActiveRecord::EVENT_AFTER_INSERT  => 'afterSave',
                  ActiveRecord::EVENT_AFTER_UPDATE  => 'afterSave',
              ];
          }
          
          /**
d55d2fe0   Yarik   Multilanguage
58
59
60
61
62
           * Get $owner primary key to link language model
           * @return string
           */
          public function getOwnerKey():string
          {
8af13427   Yarik   For leha commit.
63
64
              if(!empty( $this->ownerKey )) {
                  return $this->ownerKey;
d55d2fe0   Yarik   Multilanguage
65
66
67
68
69
70
71
72
73
74
75
76
              } else {
                  return $this->owner->primaryKey()[ 0 ];
              }
          }
          
          /**
           * Set which attribute to use as $owner primary key to link language model
           *
           * @param string $value
           */
          public function setOwnerKey(string $value)
          {
8af13427   Yarik   For leha commit.
77
              $this->ownerKey = $value;
d55d2fe0   Yarik   Multilanguage
78
79
80
81
82
83
84
85
          }
          
          /**
           * Get language model attribute that is used as foreign key to $owner
           * @return string
           */
          public function getLangKey():string
          {
8af13427   Yarik   For leha commit.
86
87
              if(!empty( $this->langKey )) {
                  return $this->langKey;
d55d2fe0   Yarik   Multilanguage
88
89
90
91
92
93
94
95
96
97
98
99
100
              } else {
                  $owner = $this->owner;
                  return $owner::getTableSchema()->name . '_id';
              }
          }
          
          /**
           * Set which attribute to use as language model foreign key to $owner
           *
           * @param $value
           */
          public function setLangKey(string $value)
          {
8af13427   Yarik   For leha commit.
101
              $this->langKey = $value;
d55d2fe0   Yarik   Multilanguage
102
103
104
105
106
107
108
109
110
111
112
          }
          
          /**
           * Additional checks to attach this behavior
           *
           * @param ActiveRecord $owner
           *
           * @throws InvalidConfigException
           */
          public function attach($owner)
          {
8af13427   Yarik   For leha commit.
113
114
115
              if(empty( $this->objectLang )) {
                  $this->objectLang = $owner::className() . 'Lang';
              } elseif(!is_string($this->objectLang)) {
d55d2fe0   Yarik   Multilanguage
116
117
118
                  throw new InvalidConfigException('Object lang must be fully classified namespaced classname');
              }
              try {
8af13427   Yarik   For leha commit.
119
                  $this->objectLang = \Yii::createObject($this->objectLang);
d55d2fe0   Yarik   Multilanguage
120
121
122
              } catch(\ReflectionException $exception) {
                  throw new InvalidConfigException('Object lang must be fully classified namespaced classname');
              }
8af13427   Yarik   For leha commit.
123
              if(( !$owner instanceof ActiveRecord ) || ( !$this->objectLang instanceof ActiveRecord )) {
d55d2fe0   Yarik   Multilanguage
124
125
126
127
128
129
130
131
132
133
134
                  throw new InvalidConfigException('Object lang must be fully classified namespaced classname');
              }
              parent::attach($owner);
          }
          
          /**
           * Get query to get all language models for $owner indexed by language_id
           * @return ActiveQuery
           */
          public function getLangs()
          {
8af13427   Yarik   For leha commit.
135
              $objectLang = $this->objectLang;
d55d2fe0   Yarik   Multilanguage
136
              $owner = $this->owner;
8af13427   Yarik   For leha commit.
137
              return $owner->hasMany($objectLang::className(), [ $this->getLangKey() => $this->getOwnerKey() ])
d55d2fe0   Yarik   Multilanguage
138
139
140
141
142
143
144
145
146
147
148
149
150
151
                           ->indexBy('language_id');
          }
          
          /**
           * Get query to get language model for $owner for language_id, default to
           * Language::getCurrent()
           *
           * @param int $language_id
           *
           * @return ActiveQuery
           */
          public function getLang(int $language_id = NULL)
          {
              if(empty( $language_id )) {
8af13427   Yarik   For leha commit.
152
                  $language_id = Language::getCurrent()->id;
d55d2fe0   Yarik   Multilanguage
153
              }
8af13427   Yarik   For leha commit.
154
155
              $objectLang = $this->objectLang;
              $table_name = $objectLang::getTableSchema()->name;
d55d2fe0   Yarik   Multilanguage
156
              $owner = $this->owner;
8af13427   Yarik   For leha commit.
157
              return $owner->hasOne($objectLang::className(), [ $this->getLangKey() => $this->getOwnerKey() ])
14cd7eed   Yarik   LanguageBehavior ...
158
                           ->where([ $table_name . '.language_id' => $language_id ]);
d55d2fe0   Yarik   Multilanguage
159
160
161
162
163
          }
          
          /**
           * Generate language models for $owner for active languages. If $owner not new and language
           * models already inserted, models will be filled with them.
14cd7eed   Yarik   LanguageBehavior ...
164
           * @return void
d55d2fe0   Yarik   Multilanguage
165
166
167
168
169
170
           */
          public function generateLangs()
          {
              $owner = $this->owner;
              $languages = Language::find()
                                   ->where([ 'status' => true ])
8af13427   Yarik   For leha commit.
171
                                   ->orderBy([ 'id' => SORT_ASC ])
d55d2fe0   Yarik   Multilanguage
172
173
                                   ->asArray()
                                   ->column();
8af13427   Yarik   For leha commit.
174
              $objectLang = $this->objectLang;
d55d2fe0   Yarik   Multilanguage
175
176
177
178
179
              $owner_key = $this->getOwnerKey();
              $langs = [];
              if(!$owner->isNewRecord) {
                  $langs = $this->getLangs()
                                ->andFilterWhere([ 'language_id' => $languages ])
14cd7eed   Yarik   LanguageBehavior ...
180
                                ->orderBy([ 'language_id' => SORT_ASC ])
d55d2fe0   Yarik   Multilanguage
181
182
183
184
185
                                ->all();
              }
              foreach($languages as $language) {
                  if(!array_key_exists($language, $langs)) {
                      $langs[ $language ] = \Yii::createObject([
8af13427   Yarik   For leha commit.
186
                          'class'             => $objectLang::className(),
d55d2fe0   Yarik   Multilanguage
187
188
189
190
191
                          'language_id'       => $language,
                          $this->getLangKey() => ( $owner->isNewRecord ? NULL : $owner->$owner_key ),
                      ]);
                  }
              }
8af13427   Yarik   For leha commit.
192
              $this->modelLangs = $langs;
d55d2fe0   Yarik   Multilanguage
193
194
195
196
197
          }
          
          /**
           * Load language models with post data.
           *
14cd7eed   Yarik   LanguageBehavior ...
198
           * @param Request $request
d55d2fe0   Yarik   Multilanguage
199
           */
14cd7eed   Yarik   LanguageBehavior ...
200
          public function loadLangs(Request $request)
d55d2fe0   Yarik   Multilanguage
201
          {
8af13427   Yarik   For leha commit.
202
203
204
205
              foreach($request->post($this->objectLang->formName(), []) as $lang => $value) {
                  if(!empty( $this->modelLangs[ $lang ] )) {
                      $this->modelLangs[ $lang ]->attributes = $value;
                      $this->modelLangs[ $lang ]->language_id = $lang;
d55d2fe0   Yarik   Multilanguage
206
207
208
209
210
211
212
                  }
              }
          }
          
          /**
           * Link language models with $owner by setting language model language key to owner key of
           * owner
d55d2fe0   Yarik   Multilanguage
213
214
           * @return bool If $owner is new record then return false else true
           */
14cd7eed   Yarik   LanguageBehavior ...
215
          public function linkLangs()
d55d2fe0   Yarik   Multilanguage
216
217
          {
              $owner = $this->owner;
5c2eb7c8   Yarik   Big commit almost...
218
219
220
              //            if($owner->isNewRecord) {
              //                return false;
              //            }
d55d2fe0   Yarik   Multilanguage
221
222
              $lang_key = $this->getLangKey();
              $owner_key = $this->getOwnerKey();
8af13427   Yarik   For leha commit.
223
224
              $modelLangs = $this->modelLangs;
              foreach($modelLangs as $model_lang) {
d55d2fe0   Yarik   Multilanguage
225
226
227
228
229
230
231
                  $model_lang->$lang_key = $owner->$owner_key;
              }
              return true;
          }
          
          /**
           * Try to save all language models to the db. Validation function is run for all models.
d55d2fe0   Yarik   Multilanguage
232
233
           * @return bool Whether all models are valid
           */
14cd7eed   Yarik   LanguageBehavior ...
234
          public function saveLangs()
d55d2fe0   Yarik   Multilanguage
235
236
          {
              $success = true;
8af13427   Yarik   For leha commit.
237
238
              $modelLangs = $this->modelLangs;
              foreach($modelLangs as $model_lang) {
18d6bf69   Yarik   Import browser be...
239
                  if($model_lang->save() === false) {
2e91abdd   Yarik   Import browser be...
240
                      $success = false;
d55d2fe0   Yarik   Multilanguage
241
242
243
244
                  }
              }
              return $success;
          }
14cd7eed   Yarik   LanguageBehavior ...
245
246
247
248
249
250
251
252
          
          public function beforeSave($event)
          {
              /**
               * @var ActiveRecord $owner
               */
              $owner = $this->owner;
              $db = $owner::getDb();
8af13427   Yarik   For leha commit.
253
              $this->transaction = $db->beginTransaction();
5c2eb7c8   Yarik   Big commit almost...
254
255
              if($owner->hasAttribute('remote_id') && empty( $owner->remote_id )) {
                  $owner->remote_id = strval(microtime(true) * 10000);
72a992f5   Yarik   Import browser v1.0
256
              }
14cd7eed   Yarik   LanguageBehavior ...
257
258
259
260
          }
          
          public function afterSave($event)
          {
8af13427   Yarik   For leha commit.
261
              if(!empty( $this->modelLangs )) {
14cd7eed   Yarik   LanguageBehavior ...
262
                  if($this->linkLangs() && $this->saveLangs()) {
8af13427   Yarik   For leha commit.
263
264
                      $this->transaction->commit();
                      $this->transactionStatus = true;
14cd7eed   Yarik   LanguageBehavior ...
265
                  } else {
8af13427   Yarik   For leha commit.
266
267
                      $this->transaction->rollBack();
                      $this->transactionStatus = false;
14cd7eed   Yarik   LanguageBehavior ...
268
269
                  }
              } else {
8af13427   Yarik   For leha commit.
270
271
                  $this->transaction->commit();
                  $this->transactionStatus = true;
14cd7eed   Yarik   LanguageBehavior ...
272
              }
14cd7eed   Yarik   LanguageBehavior ...
273
274
275
276
277
278
279
          }
          
          /**
           * @return bool
           */
          public function getTransactionStatus():bool
          {
8af13427   Yarik   For leha commit.
280
              return $this->transactionStatus;
14cd7eed   Yarik   LanguageBehavior ...
281
          }
d55d2fe0   Yarik   Multilanguage
282
      }