1
|
|
|
<?php |
2
|
|
|
namespace omgdef\multilingual; |
3
|
|
|
|
4
|
|
|
use Yii; |
5
|
|
|
use yii\base\Behavior; |
6
|
|
|
use yii\base\UnknownPropertyException; |
7
|
|
|
use yii\base\InvalidConfigException; |
8
|
|
|
use yii\db\ActiveQuery; |
9
|
|
|
use yii\db\ActiveRecord; |
10
|
|
|
use yii\helpers\Inflector; |
11
|
|
|
use yii\validators\Validator; |
12
|
|
|
|
13
|
|
|
class MultilingualBehavior extends Behavior |
14
|
|
|
{ |
15
|
|
|
/** |
16
|
|
|
* Multilingual attributes |
17
|
|
|
* @var array |
18
|
|
|
*/ |
19
|
|
|
public $attributes; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Available languages |
23
|
|
|
* It can be a simple array: array('fr', 'en') or an associative array: array('fr' => 'Français', 'en' => 'English') |
24
|
|
|
* For associative arrays, only the keys will be used. |
25
|
|
|
* @var array |
26
|
|
|
*/ |
27
|
|
|
public $languages; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @var string the default language. |
31
|
|
|
* Example: 'en'. |
32
|
|
|
*/ |
33
|
|
|
public $defaultLanguage; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* @var string the name of the translation table |
37
|
|
|
*/ |
38
|
|
|
public $tableName; |
39
|
|
|
|
40
|
|
|
/** |
41
|
|
|
* @var string the name of translation model class. |
42
|
|
|
*/ |
43
|
|
|
public $langClassName; |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @var string the name of the foreign key field of the translation table related to base model table. |
47
|
|
|
*/ |
48
|
|
|
public $langForeignKey; |
49
|
|
|
|
50
|
|
|
/** |
51
|
|
|
* @var string the prefix of the localized attributes in the lang table. Here to avoid collisions in queries. |
52
|
|
|
* In the translation table, the columns corresponding to the localized attributes have to be name like this: 'l_[name of the attribute]' |
53
|
|
|
* and the id column (primary key) like this : 'l_id' |
54
|
|
|
* Default to ''. |
55
|
|
|
*/ |
56
|
|
|
public $localizedPrefix = ''; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @var string the name of the lang field of the translation table. Default to 'language'. |
60
|
|
|
*/ |
61
|
|
|
public $languageField = 'language'; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* @var boolean if this property is set to true required validators will be applied to all translation models. |
65
|
|
|
* Default to false. |
66
|
|
|
*/ |
67
|
|
|
public $requireTranslations = false; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* @var boolean whether to force deletion of the associated translations when a base model is deleted. |
71
|
|
|
* Not needed if using foreign key with 'on delete cascade'. |
72
|
|
|
* Default to true. |
73
|
|
|
*/ |
74
|
|
|
public $forceDelete = true; |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* @var boolean whether to dynamically create translation model class. |
78
|
|
|
* If true, the translation model class will be generated on runtime with the use of the eval() function so no additional php file is needed. |
79
|
|
|
* See {@link createLangClass()} |
80
|
|
|
* Default to true. |
81
|
|
|
*/ |
82
|
|
|
public $dynamicLangClass = true; |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @var boolean whether to abridge the language ID. |
86
|
|
|
* Default to true. |
87
|
|
|
*/ |
88
|
|
|
public $abridge = true; |
89
|
|
|
|
90
|
|
|
/** |
91
|
|
|
* @var string the name of the primary key field of the base model. Defaults to first value of Model::primaryKey. |
92
|
|
|
*/ |
93
|
|
|
public $ownerPrimaryKey; |
94
|
|
|
|
95
|
|
|
/** |
96
|
|
|
* @var boolean whether to check for existing translations on insert |
97
|
|
|
* Default to false |
98
|
|
|
*/ |
99
|
|
|
public $checkOnInsert = false; |
100
|
|
|
|
101
|
|
|
private $currentLanguage; |
102
|
|
|
private $ownerClassName; |
103
|
|
|
private $langClassShortName; |
104
|
|
|
private $ownerClassShortName; |
105
|
|
|
private $langAttributes = []; |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* @var array excluded validators |
109
|
|
|
*/ |
110
|
|
|
private $excludedValidators = ['unique']; |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* @inheritdoc |
114
|
|
|
*/ |
115
|
9 |
|
public function events() |
116
|
|
|
{ |
117
|
|
|
return [ |
118
|
9 |
|
ActiveRecord::EVENT_AFTER_FIND => 'afterFind', |
119
|
9 |
|
ActiveRecord::EVENT_AFTER_UPDATE => 'afterUpdate', |
120
|
9 |
|
ActiveRecord::EVENT_AFTER_INSERT => 'afterInsert', |
121
|
9 |
|
ActiveRecord::EVENT_AFTER_DELETE => 'afterDelete', |
122
|
9 |
|
ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate', |
123
|
|
|
]; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* @inheritdoc |
128
|
|
|
*/ |
129
|
9 |
|
public function attach($owner) |
130
|
|
|
{ |
131
|
|
|
/** @var ActiveRecord $owner */ |
132
|
|
|
parent::attach($owner); |
133
|
|
|
|
134
|
|
View Code Duplication |
if (empty($this->languages) || !is_array($this->languages)) { |
135
|
|
|
throw new InvalidConfigException('Please specify array of available languages for the ' . get_class($this) . ' in the ' |
136
|
|
|
. get_class($this->owner) . ' or in the application parameters', 101); |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
if (array_values($this->languages) !== $this->languages) { //associative array |
140
|
|
|
$this->languages = array_keys($this->languages); |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
$this->languages = array_unique(array_map(function ($language) { |
144
|
|
|
return $this->getLanguageBaseName($language); |
145
|
|
|
}, $this->languages)); |
146
|
|
|
|
147
|
9 |
|
if (!$this->defaultLanguage) { |
148
|
|
|
$this->defaultLanguage = isset(Yii::$app->params['defaultLanguage']) && Yii::$app->params['defaultLanguage'] ? |
149
|
|
|
Yii::$app->params['defaultLanguage'] : Yii::$app->language; |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
$this->defaultLanguage = $this->getLanguageBaseName($this->defaultLanguage); |
153
|
|
|
|
154
|
9 |
|
if (!$this->currentLanguage) { |
155
|
|
|
$this->currentLanguage = $this->getLanguageBaseName(Yii::$app->language); |
156
|
|
|
} |
157
|
|
|
|
158
|
|
View Code Duplication |
if (empty($this->attributes) || !is_array($this->attributes)) { |
159
|
|
|
throw new InvalidConfigException('Please specify multilingual attributes for the ' . get_class($this) . ' in the ' |
160
|
|
|
. get_class($this->owner), 103); |
161
|
|
|
} |
162
|
|
|
|
163
|
9 |
|
if (!$this->langClassName) { |
164
|
|
|
$this->langClassName = get_class($this->owner) . 'Lang'; |
165
|
|
|
} |
166
|
|
|
|
167
|
|
|
$this->langClassShortName = $this->getShortClassName($this->langClassName); |
168
|
|
|
$this->ownerClassName = get_class($this->owner); |
169
|
|
|
$this->ownerClassShortName = $this->getShortClassName($this->ownerClassName); |
170
|
|
|
|
171
|
|
|
/** @var ActiveRecord $className */ |
172
|
9 |
|
$className = $this->ownerClassName; |
173
|
9 |
|
if (!isset($this->ownerPrimaryKey)) { |
174
|
|
|
$this->ownerPrimaryKey = $className::primaryKey()[0]; |
175
|
|
|
} |
176
|
|
|
|
177
|
9 |
|
if (!isset($this->langForeignKey)) { |
178
|
|
|
throw new InvalidConfigException('Please specify langForeignKey for the ' . get_class($this) . ' in the ' |
179
|
|
|
. get_class($this->owner), 105); |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
$rules = $owner->rules(); |
183
|
|
|
$validators = $owner->getValidators(); |
184
|
|
|
|
185
|
|
|
foreach ($rules as $rule) { |
186
|
|
|
if (in_array($rule[1], $this->excludedValidators)) |
187
|
|
|
continue; |
188
|
|
|
|
189
|
|
|
$rule_attributes = is_array($rule[0]) ? $rule[0] : [$rule[0]]; |
190
|
|
|
$attributes = array_intersect($this->attributes, $rule_attributes); |
191
|
|
|
|
192
|
|
|
if (empty($attributes)) |
193
|
|
|
continue; |
194
|
|
|
|
195
|
|
|
$rule_attributes = []; |
196
|
|
|
foreach ($attributes as $key => $attribute) { |
197
|
|
|
foreach ($this->languages as $language) |
198
|
|
|
if ($language != $this->defaultLanguage) |
199
|
|
|
$rule_attributes[] = $this->getAttributeName($attribute, $language); |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
if (isset($rule['skipOnEmpty']) && !$rule['skipOnEmpty']) |
203
|
|
|
$rule['skipOnEmpty'] = !$this->requireTranslations; |
204
|
|
|
|
205
|
|
|
$params = array_slice($rule, 2); |
206
|
|
|
|
207
|
|
|
if ($rule[1] !== 'required' || $this->requireTranslations) { |
208
|
|
|
$validators[] = Validator::createValidator($rule[1], $owner, $rule_attributes, $params); |
209
|
8 |
|
} elseif ($rule[1] === 'required') { |
210
|
|
|
$validators[] = Validator::createValidator('safe', $owner, $rule_attributes, $params); |
211
|
8 |
|
} |
212
|
|
|
} |
213
|
|
|
|
214
|
9 |
|
if ($this->dynamicLangClass) { |
215
|
|
|
$this->createLangClass(); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
$translation = new $this->langClassName; |
219
|
9 |
View Code Duplication |
foreach ($this->languages as $lang) { |
220
|
|
|
foreach ($this->attributes as $attribute) { |
221
|
|
|
$attributeName = $this->localizedPrefix . $attribute; |
222
|
|
|
$this->setLangAttribute($this->getAttributeName($attribute, $lang), $translation->{$attributeName}); |
223
|
|
|
if ($lang == $this->defaultLanguage) { |
224
|
|
|
$this->setLangAttribute($attribute, $translation->{$attributeName}); |
225
|
|
|
} |
226
|
|
|
} |
227
|
|
|
} |
228
|
|
|
} |
229
|
|
|
|
230
|
9 |
|
public function createLangClass() |
231
|
|
|
{ |
232
|
|
|
if (!class_exists($this->langClassName, false)) { |
233
|
|
|
$namespace = substr($this->langClassName, 0, strrpos($this->langClassName, '\\')); |
234
|
|
|
eval(' |
235
|
|
|
namespace ' . $namespace . '; |
236
|
|
|
use yii\db\ActiveRecord; |
237
|
|
|
class ' . $this->langClassShortName . ' extends ActiveRecord |
238
|
|
|
{ |
239
|
|
|
public static function tableName() |
240
|
|
|
{ |
241
|
|
|
return \'' . $this->tableName . '\'; |
242
|
|
|
} |
243
|
|
|
}'); |
244
|
|
|
} |
245
|
9 |
|
} |
246
|
|
|
|
247
|
|
|
/** |
248
|
|
|
* Relation to model translations |
249
|
|
|
* @return ActiveQuery |
250
|
|
|
*/ |
251
|
|
|
public function getTranslations() |
252
|
|
|
{ |
253
|
|
|
return $this->owner->hasMany($this->langClassName, [$this->langForeignKey => $this->ownerPrimaryKey]); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
/** |
257
|
|
|
* Relation to model translation |
258
|
|
|
* @param $language |
259
|
|
|
* @return ActiveQuery |
260
|
|
|
*/ |
261
|
5 |
|
public function getTranslation($language = null) |
262
|
|
|
{ |
263
|
|
|
$language = $language ?: $this->getCurrentLanguage(); |
264
|
5 |
|
return $this->owner->hasOne($this->langClassName, [$this->langForeignKey => $this->ownerPrimaryKey]) |
265
|
|
|
->where([$this->languageField => $language]); |
266
|
5 |
|
} |
267
|
|
|
|
268
|
|
|
/** |
269
|
|
|
* Handle 'beforeValidate' event of the owner. |
270
|
|
|
*/ |
271
|
10 |
|
public function beforeValidate() |
272
|
|
|
{ |
273
|
10 |
|
foreach ($this->attributes as $attribute) { |
274
|
|
|
$this->setLangAttribute($this->getAttributeName($attribute, $this->defaultLanguage), $this->getLangAttribute($attribute)); |
275
|
|
|
} |
276
|
10 |
|
} |
277
|
|
|
|
278
|
|
|
/** |
279
|
|
|
* Handle 'afterFind' event of the owner. |
280
|
|
|
*/ |
281
|
8 |
|
public function afterFind() |
282
|
|
|
{ |
283
|
|
|
/** @var ActiveRecord $owner */ |
284
|
8 |
|
$owner = $this->owner; |
285
|
|
|
|
286
|
|
|
if ($owner->isRelationPopulated('translations') && $related = $owner->getRelatedRecords()['translations']) { |
287
|
|
|
$translations = $this->indexByLanguage($related); |
288
|
4 |
|
foreach ($this->languages as $lang) { |
289
|
|
|
foreach ($this->attributes as $attribute) { |
290
|
|
View Code Duplication |
foreach ($translations as $translation) { |
291
|
|
|
if ($this->getLanguageBaseName($translation->{$this->languageField}) == $lang) { |
292
|
|
|
$attributeName = $this->localizedPrefix . $attribute; |
293
|
|
|
$this->setLangAttribute($this->getAttributeName($attribute, $lang), $translation->{$attributeName}); |
294
|
|
|
|
295
|
|
|
if ($lang == $this->defaultLanguage) { |
296
|
|
|
$this->setLangAttribute($attribute, $translation->{$attributeName}); |
297
|
|
|
} |
298
|
|
|
} |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
} |
302
|
|
|
} else { |
303
|
|
|
if (!$owner->isRelationPopulated('translation')) { |
304
|
|
|
$owner->translation; |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
$translation = $owner->getRelatedRecords()['translation']; |
308
|
5 |
|
if ($translation) { |
309
|
4 |
|
foreach ($this->attributes as $attribute) { |
310
|
|
|
$attribute_name = $this->localizedPrefix . $attribute; |
311
|
|
|
$owner->setLangAttribute($attribute, $translation->$attribute_name); |
312
|
|
|
} |
313
|
|
|
} |
314
|
4 |
|
} |
315
|
|
|
|
316
|
8 |
|
foreach ($this->attributes as $attribute) { |
317
|
|
|
if ($owner->hasAttribute($attribute) && $this->getLangAttribute($attribute)) { |
318
|
|
|
$owner->setAttribute($attribute, $this->getLangAttribute($attribute)); |
319
|
|
|
} |
320
|
|
|
} |
321
|
8 |
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Handle 'afterInsert' event of the owner. |
325
|
|
|
*/ |
326
|
4 |
View Code Duplication |
public function afterInsert() |
|
|
|
|
327
|
|
|
{ |
328
|
4 |
|
$translations = []; |
329
|
4 |
|
if ($this->checkOnInsert) |
330
|
|
|
{ |
331
|
|
|
$translations = $this->indexByLanguage($this->owner->getRelatedRecords()['translations']); |
332
|
|
|
} |
333
|
|
|
$this->saveTranslations($translations); |
334
|
4 |
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Handle 'afterUpdate' event of the owner. |
338
|
|
|
*/ |
339
|
5 |
View Code Duplication |
public function afterUpdate() |
|
|
|
|
340
|
|
|
{ |
341
|
|
|
/** @var ActiveRecord $owner */ |
342
|
5 |
|
$owner = $this->owner; |
343
|
|
|
|
344
|
|
|
if ($owner->isRelationPopulated('translations')) { |
345
|
|
|
$translations = $this->indexByLanguage($owner->getRelatedRecords()['translations']); |
346
|
|
|
$this->saveTranslations($translations); |
347
|
|
|
} |
348
|
5 |
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Handle 'afterDelete' event of the owner. |
352
|
|
|
*/ |
353
|
2 |
|
public function afterDelete() |
354
|
|
|
{ |
355
|
2 |
|
if ($this->forceDelete) { |
356
|
|
|
/** @var ActiveRecord $owner */ |
357
|
2 |
|
$owner = $this->owner; |
358
|
|
|
$owner->unlinkAll('translations', true); |
359
|
|
|
} |
360
|
2 |
|
} |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* @param array $translations |
364
|
|
|
*/ |
365
|
7 |
|
private function saveTranslations($translations = []) |
366
|
|
|
{ |
367
|
|
|
/** @var ActiveRecord $owner */ |
368
|
7 |
|
$owner = $this->owner; |
369
|
|
|
|
370
|
7 |
|
foreach ($this->languages as $lang) { |
371
|
|
|
$defaultLanguage = $lang == $this->defaultLanguage; |
372
|
|
|
|
373
|
|
|
if (!isset($translations[$lang])) { |
374
|
|
|
/** @var ActiveRecord $translation */ |
375
|
|
|
$translation = new $this->langClassName; |
376
|
|
|
$translation->{$this->languageField} = $lang; |
377
|
|
|
$translation->{$this->langForeignKey} = $owner->getAttribute($this->ownerPrimaryKey); |
378
|
|
|
} else { |
379
|
|
|
$translation = $translations[$lang]; |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
$save = false; |
383
|
|
|
foreach ($this->attributes as $attribute) { |
384
|
|
|
$value = $defaultLanguage ? $owner->$attribute : $this->getLangAttribute($this->getAttributeName($attribute, $lang)); |
385
|
|
|
|
386
|
|
|
if ($value !== null) { |
387
|
|
|
$field = $this->localizedPrefix . $attribute; |
388
|
|
|
$translation->$field = $value; |
389
|
|
|
$save = true; |
390
|
|
|
} |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
if ($translation->isNewRecord && !$save) |
394
|
3 |
|
continue; |
395
|
|
|
|
396
|
|
|
$translation->save(); |
397
|
|
|
} |
398
|
7 |
|
} |
399
|
|
|
|
400
|
|
|
/** |
401
|
|
|
* @inheritdoc |
402
|
|
|
*/ |
403
|
3 |
|
public function canGetProperty($name, $checkVars = true) |
404
|
|
|
{ |
405
|
|
|
return method_exists($this, 'get' . $name) || $checkVars && property_exists($this, $name) |
406
|
3 |
|
|| $this->hasLangAttribute($name); |
407
|
3 |
|
} |
408
|
|
|
|
409
|
|
|
/** |
410
|
|
|
* @inheritdoc |
411
|
|
|
*/ |
412
|
|
|
public function canSetProperty($name, $checkVars = true) |
413
|
|
|
{ |
414
|
|
|
return $this->hasLangAttribute($name); |
415
|
|
|
} |
416
|
|
|
|
417
|
|
|
/** |
418
|
|
|
* @inheritdoc |
419
|
|
|
*/ |
420
|
|
|
public function __get($name) |
421
|
|
|
{ |
422
|
|
|
try { |
423
|
|
|
return parent::__get($name); |
424
|
|
|
} catch (UnknownPropertyException $e) { |
425
|
|
|
if ($this->hasLangAttribute($name)) return $this->getLangAttribute($name); |
426
|
|
|
// @codeCoverageIgnoreStart |
427
|
|
|
else throw $e; |
428
|
|
|
// @codeCoverageIgnoreEnd |
429
|
|
|
} |
430
|
|
|
} |
431
|
|
|
|
432
|
|
|
/** |
433
|
|
|
* @inheritdoc |
434
|
|
|
*/ |
435
|
|
|
public function __set($name, $value) |
436
|
|
|
{ |
437
|
|
|
try { |
438
|
|
|
parent::__set($name, $value); |
439
|
|
|
} catch (UnknownPropertyException $e) { |
440
|
|
|
if ($this->hasLangAttribute($name)) $this->setLangAttribute($name, $value); |
441
|
|
|
// @codeCoverageIgnoreStart |
442
|
|
|
else throw $e; |
443
|
|
|
// @codeCoverageIgnoreEnd |
444
|
|
|
} |
445
|
|
|
} |
446
|
|
|
|
447
|
|
|
/** |
448
|
|
|
* @inheritdoc |
449
|
|
|
* @codeCoverageIgnore |
450
|
|
|
*/ |
451
|
|
|
public function __isset($name) |
452
|
|
|
{ |
453
|
|
|
if (!parent::__isset($name)) { |
454
|
|
|
return $this->hasLangAttribute($name); |
455
|
|
|
} else { |
456
|
|
|
return true; |
457
|
|
|
} |
458
|
|
|
} |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Whether an attribute exists |
462
|
|
|
* @param string $name the name of the attribute |
463
|
|
|
* @return boolean |
464
|
|
|
*/ |
465
|
|
|
public function hasLangAttribute($name) |
466
|
|
|
{ |
467
|
|
|
return array_key_exists($name, $this->langAttributes); |
468
|
|
|
} |
469
|
|
|
|
470
|
|
|
/** |
471
|
|
|
* @param string $name the name of the attribute |
472
|
|
|
* @return string the attribute value |
473
|
|
|
*/ |
474
|
|
|
public function getLangAttribute($name) |
475
|
|
|
{ |
476
|
|
|
return $this->hasLangAttribute($name) ? $this->langAttributes[$name] : null; |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
/** |
480
|
|
|
* @param string $name the name of the attribute |
481
|
|
|
* @param string $value the value of the attribute |
482
|
|
|
*/ |
483
|
|
|
public function setLangAttribute($name, $value) |
484
|
|
|
{ |
485
|
|
|
$this->langAttributes[$name] = $value; |
486
|
|
|
} |
487
|
|
|
|
488
|
|
|
/** |
489
|
|
|
* @param $records |
490
|
|
|
* @return array |
491
|
|
|
*/ |
492
|
1 |
|
protected function indexByLanguage($records) |
493
|
|
|
{ |
494
|
1 |
|
$sorted = array(); |
495
|
|
|
foreach ($records as $record) { |
496
|
|
|
$sorted[$record->{$this->languageField}] = $record; |
497
|
|
|
} |
498
|
1 |
|
unset($records); |
499
|
1 |
|
return $sorted; |
500
|
|
|
} |
501
|
|
|
|
502
|
|
|
/** |
503
|
|
|
* @param $language |
504
|
|
|
* @return string |
505
|
|
|
*/ |
506
|
|
|
protected function getLanguageBaseName($language) |
507
|
|
|
{ |
508
|
|
|
return $this->abridge ? substr($language, 0, 2) : $language; |
509
|
|
|
} |
510
|
|
|
|
511
|
|
|
/** |
512
|
|
|
* @param string $className |
513
|
|
|
* @return string |
514
|
|
|
*/ |
515
|
|
|
private function getShortClassName($className) |
516
|
|
|
{ |
517
|
|
|
return substr($className, strrpos($className, '\\') + 1); |
518
|
|
|
} |
519
|
|
|
|
520
|
|
|
/** |
521
|
|
|
* @return mixed|string |
522
|
|
|
*/ |
523
|
5 |
|
public function getCurrentLanguage() |
524
|
|
|
{ |
525
|
5 |
|
return $this->currentLanguage; |
526
|
|
|
} |
527
|
|
|
|
528
|
|
|
/** |
529
|
|
|
* @param $attribute |
530
|
|
|
* @param $language |
531
|
|
|
* @return string |
532
|
|
|
*/ |
533
|
|
|
protected function getAttributeName($attribute, $language) |
534
|
|
|
{ |
535
|
|
|
$language = $this->abridge ? $language : Inflector::camel2id(Inflector::id2camel($language), "_"); |
536
|
|
|
return $attribute . "_" . $language; |
537
|
|
|
} |
538
|
|
|
} |
539
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.