TranslationBehavior::__set()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/**
4
 * @link https://github.com/rkit/translation-behavior-yii2
5
 * @copyright Copyright (c) 2018 Igor Romanov
6
 * @license [MIT](http://opensource.org/licenses/MIT)
7
 */
8
9
namespace rkit\translation\behavior;
10
11
use yii\base\{Behavior, InvalidConfigException}; // phpcs:ignore
12
use yii\db\ActiveRecord;
13
14
class TranslationBehavior extends Behavior
15
{
16
    /**
17
     * @var string The name of the has-one relation.
18
     */
19
    public $relationOne = 'translation';
20
    /**
21
     * @var string The name of the has-many relation.
22
     */
23
    public $relationMany = 'translations';
24
    /**
25
     * @var string The language attribute name
26
     */
27
    public $languageAttribute = 'language';
28
    /**
29
     * @var int|string The default language.
30
     */
31
    public $defaultLanguage = null;
32
    /**
33
     * @var string[] The attributes for translation.
34
     */
35
    public $attributes = null;
36
37
    /**
38
     * @inheritdoc
39
     */
40
    public function events()
41
    {
42
        return [
43
            ActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
44
            ActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
45
        ];
46
    }
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public function init()
52
    {
53
        if ($this->attributes === null) {
54
            throw new InvalidConfigException('The "attributes" property must be set.');
55
        }
56
57
        $this->attributes[] = $this->languageAttribute;
58
    }
59
60
    /**
61
     * @inheritdoc
62
     */
63
    public function afterSave()
64
    {
65
        $translations = $this->owner->{$this->relationMany};
66
        $this->owner->unlinkAll($this->relationMany, true);
67
68
        foreach ($translations as $translation) {
69
            $this->owner->link($this->relationMany, $translation);
70
        }
71
    }
72
73
    /**
74
     * @inheritdoc
75
     */
76
    public function canGetProperty($name, $checkVars = true)
77
    {
78
        return in_array($name, $this->attributes) ?: parent::canGetProperty($name, $checkVars);
79
    }
80
81
    /**
82
     * @inheritdoc
83
     */
84
    public function canSetProperty($name, $checkVars = true)
85
    {
86
        return in_array($name, $this->attributes) ?: parent::canSetProperty($name, $checkVars);
87
    }
88
89
    /**
90
     * @inheritdoc
91
     */
92
    public function __get($name)
93
    {
94
        return $this->translate()->getAttribute($name);
95
    }
96
97
    /**
98
     * @inheritdoc
99
     */
100
    public function __set($name, $value)
101
    {
102
        $translation = $this->translate();
103
        $translation->setAttribute($name, $value);
104
    }
105
106
    public function loadTranslations($data)
107
    {
108
        $this->owner->populateRelation($this->relationMany, []);
109
110
        foreach ($data as $language => $items) {
111
            foreach ($items as $attribute => $translation) {
112
                $this->owner->translate($language)->$attribute = $translation;
113
            }
114
        }
115
116
        return true;
117
    }
118
119
    /**
120
     * Returns the translation model for the specified language.
121
     * 
122
     * @param string|int|null $language
123
     * @return ActiveRecord
124
     */
125
    public function translate($language = null)
126
    {
127
        if ($this->owner->isRelationPopulated($this->relationOne) && $this->owner->{$this->relationOne}) {
128
            return $this->owner->{$this->relationOne};
129
        }
130
131
        $translations = $this->owner->{$this->relationMany};
132
133
        if ($language !== null) {
134
            foreach ($translations as $translation) {
135
                if ($translation->getAttribute($this->languageAttribute) === $language) {
136
                    return $translation;
137
                }
138
            }
139
        }
140
141
        $language = $language === null ? $this->defaultLanguage : $language;
142
143
        $translation = $this->createTranslation($language);
144
145
        $translations[] = $translation;
146
        $this->owner->populateRelation($this->relationMany, $translations);
147
148
        return $translation;
149
    }
150
151
    private function createTranslation($language)
152
    {
153
        $translationClass = $this->owner->getRelation($this->relationMany)->modelClass;
154
155
        $translation = new $translationClass();
156
        $translation->setAttribute($this->languageAttribute, $language);
157
158
        return $translation;
159
    }
160
}
161