Completed
Push — master ( 38078c...bdabf3 )
by Loban
04:23
created

TranslatedBehavior::eventAfterSave()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1
Metric Value
dl 0
loc 4
rs 10
ccs 3
cts 3
cp 1
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
/**
3
 * @link https://github.com/LAV45/yii2-translated-behavior
4
 * @copyright Copyright (c) 2015 LAV45!
5
 * @author Alexey Loban <[email protected]>
6
 * @license http://opensource.org/licenses/BSD-3-Clause
7
 */
8
9
namespace lav45\translate;
10
11
use yii\db\ActiveRecord;
12
use yii\helpers\ArrayHelper;
13
14
/**
15
 * Class TranslatedBehavior
16
 * @package lav45\translate\TranslatedBehavior
17
 *
18
 * ================ Example use ================
19
 * public function behaviors()
20
 * {
21
 *     return [
22
 *         [
23
 *             'class' => TranslatedBehavior::className(),
24
 *             'translateRelation' => 'postLangs',
25
 *             'translateAttributes' => [
26
 *                 'titleLang' => 'title',
27
 *                 'description',
28
 *             ]
29
 *         ]
30
 *     ];
31
 * }
32
 *
33
 * @property ActiveRecord[] $currentTranslate
34
 * @property array $hasTranslate
35
 * @property ActiveRecord $translation
36
 * @property ActiveRecord $owner
37
 */
38
class TranslatedBehavior extends BaseTranslatedBehavior
39
{
40
    /**
41
     * @var string the translations relation name
42
     */
43
    public $translateRelation;
44
    /**
45
     * @var string the translations model language attribute name
46
     */
47
    public $languageAttribute = 'lang_id';
48
49
    /**
50
     * @inheritdoc
51
     */
52 12
    public function events()
53
    {
54
        $beforeDelete = function () {
55 1
            $this->owner->unlinkAll($this->translateRelation, true);
56 12
        };
57 12
        $afterSave = function () {
58 3
            $this->owner->link('currentTranslate', $this->getTranslation());
59 12
        };
60
        return [
61 12
            ActiveRecord::EVENT_BEFORE_DELETE => $beforeDelete,
62 12
            ActiveRecord::EVENT_AFTER_INSERT => $afterSave,
63 12
            ActiveRecord::EVENT_AFTER_UPDATE => $afterSave,
64 12
        ];
65
    }
66
67
    /**
68
     * @return ActiveRecord[]
69
     */
70 8
    protected function getTranslateRelations()
71
    {
72 8
        $records = $this->owner->getRelatedRecords();
73 8
        if (!isset($records['currentTranslate']) && isset($records[$this->translateRelation])) {
74 1
            $translations = ArrayHelper::index($this->owner->{$this->translateRelation}, $this->languageAttribute);
75 1
            $this->setTranslateRelations($translations);
76 1
        }
77 8
        return $this->owner['currentTranslate'];
78
    }
79
80
    /**
81
     * @param ActiveRecord[] $models
82
     */
83 6
    protected function setTranslateRelations($models)
84
    {
85 6
        $this->owner->populateRelation('currentTranslate', $models);
86 6
    }
87
88
    /**
89
     * @return \yii\db\ActiveQuery
90
     */
91 9
    protected function getRelation()
92
    {
93 9
        return $this->owner->getRelation($this->translateRelation);
94
    }
95
96
    /**
97
     * Returns the translation model for the specified language.
98
     * @param string|null $language
99
     * @return ActiveRecord
100
     */
101 8
    public function getTranslation($language = null)
102
    {
103 8
        $language = $language ?: $this->language;
104 8
        $translations = $this->getTranslateRelations();
105 8
        if (isset($translations[$language])) {
106 8
            return $translations[$language];
107
        }
108 5
        $translations[$language] = $this->createTranslation($language, $translations);
109 5
        $this->setTranslateRelations($translations);
110 5
        return $translations[$language];
111
    }
112
113
    /**
114
     * @param string $language
115
     * @param ActiveRecord[]|array $translations
116
     * @return ActiveRecord
117
     */
118 5
    protected function createTranslation($language, $translations)
119
    {
120 5
        $class = $this->getRelation()->modelClass;
121
        /** @var ActiveRecord $model */
122 5
        $model = new $class();
123 5
        if (isset($translations[$this->sourceLanguage])) {
124 2
            $attributes = $translations[$this->sourceLanguage] instanceof ActiveRecord ?
125 2
                $translations[$this->sourceLanguage]->attributes : $translations[$this->sourceLanguage];
126 2
            $model->setAttributes((array) $attributes, false);
127 2
        }
128 5
        $model->setAttribute($this->languageAttribute, $language);
129 5
        return $model;
130
    }
131
132
    /**
133
     * @inheritdoc
134
     */
135 11
    public function canGetProperty($name, $checkVars = true)
136
    {
137 11
        return $this->isAttribute($name) ||
138 9
        parent::canGetProperty($name, $checkVars) ||
139 11
        (is_object($this->getTranslation()) && $this->getTranslation()->canGetProperty($name, $checkVars));
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145 7
    public function canSetProperty($name, $checkVars = true)
146
    {
147 7
        return $this->isAttribute($name) ||
148 5
        parent::canSetProperty($name, $checkVars) ||
149 7
        (is_object($this->getTranslation()) && $this->getTranslation()->canSetProperty($name, $checkVars));
150
    }
151
152
    /**
153
     * @inheritdoc
154
     */
155 11
    public function __get($name)
156
    {
157 11
        $getter = 'get' . $name;
158 11
        if (method_exists($this, $getter)) {
159 9
            return $this->$getter();
160
        } else {
161 4
            if ($this->isAttribute($name)) {
162 3
                $name = $this->normalizeAttributeName($name);
163 3
            }
164 4
            return $this->getTranslation()[$name];
165
        }
166
    }
167
168
    /**
169
     * @inheritdoc
170
     */
171 12
    public function __set($name, $value)
172
    {
173 12
        $setter = 'set' . $name;
174 12
        if (method_exists($this, $setter)) {
175 12
            $this->$setter($value);
176 12
        } else {
177 5
            if ($this->isAttribute($name)) {
178 3
                $name = $this->normalizeAttributeName($name);
179 3
            }
180 5
            $this->getTranslation()[$name] = $value;
181
        }
182 12
    }
183
184
    /**
185
     * Returns a value indicating whether a method is defined.
186
     *
187
     * The default implementation is a call to php function `method_exists()`.
188
     * You may override this method when you implemented the php magic method `__call()`.
189
     * @param string $name the method name
190
     * @return boolean whether the method is defined
191
     */
192 6
    public function hasMethod($name)
193
    {
194 6
        return parent::hasMethod($name) || $this->getTranslation()->hasMethod($name);
195
    }
196
197
    /**
198
     * Calls the named method which is not a class method.
199
     *
200
     * Do not call this method directly as it is a PHP magic method that
201
     * will be implicitly called when an unknown method is being invoked.
202
     * @param string $name the method name
203
     * @param array $params method parameters
204
     * @return mixed the method return value
205
     */
206 1
    public function __call($name, $params)
207
    {
208 1
        return call_user_func_array([$this->getTranslation(), $name], $params);
209
    }
210
211
    /**
212
     * @return bool
213
     */
214 1
    public function isTranslated()
215
    {
216 1
        return $this->isSourceLanguage() === false && $this->getTranslation()->getIsNewRecord() === false;
217
    }
218
219
    /**
220
     * This read only relations designed for method $this->hasTranslate()
221
     * @return \yii\db\ActiveQuery
222
     */
223 3
    public function getHasTranslate()
224
    {
225 3
        $relations = $this->getRelation();
226 3
        $select = array_keys($relations->link);
227 3
        $select[] = $this->languageAttribute;
228
229
        return $relations
230 3
            ->select($select)
231 3
            ->indexBy($this->languageAttribute)
232 3
            ->asArray();
233
    }
234
235
    /**
236
     * @return \yii\db\ActiveQuery
237
     */
238 8
    public function getCurrentTranslate()
239
    {
240 8
        $langList = [$this->language, $this->sourceLanguage];
241 8
        $langList = array_keys(array_flip($langList));
242
243 8
        return $this->getRelation()
244 8
            ->where([$this->languageAttribute => $langList])
245 8
            ->indexBy($this->languageAttribute);
246
    }
247
}
248