Completed
Push — master ( bd2d7d...616bb2 )
by Loban
40:11
created

TranslatedBehavior::getTranslation()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4

Importance

Changes 11
Bugs 2 Features 2
Metric Value
c 11
b 2
f 2
dl 0
loc 18
ccs 10
cts 10
cp 1
rs 9.2
cc 4
eloc 10
nc 6
nop 1
crap 4
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
     * Returns the translation model for the specified language.
69
     * @param string|null $language
70
     * @return ActiveRecord
71
     */
72 8
    public function getTranslation($language = null)
73
    {
74 8
        $language = $language ?: $this->language;
75 8
76 8
        $translations = $this->getTranslateRelations();
77 8
        if (isset($translations[$language])) {
78
            return $translations[$language];
79 5
        }
80 5
81 5
        $attributes = isset($translations[$this->sourceLanguage]) ?
82
            ArrayHelper::toArray($translations[$this->sourceLanguage]) : [];
83
84
        $translations[$language] = $this->createTranslation($language, $attributes);
85
86
        $this->setTranslateRelations($translations);
87 8
88
        return $translations[$language];
89 8
    }
90 8
91 1
    /**
92 1
     * @return ActiveRecord[]
93 1
     */
94 8
    protected function getTranslateRelations()
95
    {
96
        $records = $this->owner->getRelatedRecords();
97
        if (!isset($records['currentTranslate']) && isset($records[$this->translateRelation])) {
98
            $translations = ArrayHelper::index($this->owner->{$this->translateRelation}, $this->languageAttribute);
99
            $this->setTranslateRelations($translations);
100 6
        }
101
        return $this->owner['currentTranslate'];
102 6
    }
103 6
104
    /**
105
     * @param ActiveRecord[] $models
106
     */
107
    protected function setTranslateRelations($models)
108
    {
109
        $this->owner->populateRelation('currentTranslate', $models);
110 5
    }
111
112 5
    /**
113
     * @param string $language
114 5
     * @param array $attributes
115 5
     * @return ActiveRecord
116 2
     */
117 2
    protected function createTranslation($language, $attributes = [])
118 2
    {
119 2
        $class = $this->getRelation()->modelClass;
120 5
        /** @var ActiveRecord $model */
121 5
        $model = new $class();
122
        $attributes[$this->languageAttribute] = $language;
123
        $model->setAttributes($attributes, false);
124
        return $model;
125
    }
126
127 9
    /**
128
     * @return \yii\db\ActiveQuery
129 9
     */
130
    protected function getRelation()
131
    {
132
        return $this->owner->getRelation($this->translateRelation);
133
    }
134
135 11
    /**
136
     * @inheritdoc
137 11
     */
138 9
    public function canGetProperty($name, $checkVars = true)
139 11
    {
140
        return $this->isAttribute($name) ||
141
        parent::canGetProperty($name, $checkVars) ||
142
        (is_object($this->getTranslation()) && $this->getTranslation()->canGetProperty($name, $checkVars));
143
    }
144
145 7
    /**
146
     * @inheritdoc
147 7
     */
148 5
    public function canSetProperty($name, $checkVars = true)
149 7
    {
150
        return $this->isAttribute($name) ||
151
        parent::canSetProperty($name, $checkVars) ||
152
        (is_object($this->getTranslation()) && $this->getTranslation()->canSetProperty($name, $checkVars));
153
    }
154
155 11
    /**
156
     * @inheritdoc
157 11
     */
158 11
    public function __get($name)
159 9
    {
160
        $getter = 'get' . $name;
161 4
        if (method_exists($this, $getter)) {
162 3
            return $this->$getter();
163 3
        } else {
164 4
            if ($this->isAttribute($name)) {
165
                $name = $this->getAttributeName($name);
166
            }
167
            return $this->getTranslation()[$name];
168
        }
169
    }
170
171 12
    /**
172
     * @inheritdoc
173 12
     */
174 12
    public function __set($name, $value)
175 12
    {
176 12
        $setter = 'set' . $name;
177 5
        if (method_exists($this, $setter)) {
178 3
            $this->$setter($value);
179 3
        } else {
180 5
            if ($this->isAttribute($name)) {
181
                $name = $this->getAttributeName($name);
182 12
            }
183
            $this->getTranslation()[$name] = $value;
184
        }
185
    }
186
187
    /**
188
     * Returns a value indicating whether a method is defined.
189
     *
190
     * The default implementation is a call to php function `method_exists()`.
191
     * You may override this method when you implemented the php magic method `__call()`.
192 6
     * @param string $name the method name
193
     * @return boolean whether the method is defined
194 6
     */
195
    public function hasMethod($name)
196
    {
197
        return parent::hasMethod($name) || $this->getTranslation()->hasMethod($name);
198
    }
199
200
    /**
201
     * Calls the named method which is not a class method.
202
     *
203
     * Do not call this method directly as it is a PHP magic method that
204
     * will be implicitly called when an unknown method is being invoked.
205
     * @param string $name the method name
206 1
     * @param array $params method parameters
207
     * @return mixed the method return value
208 1
     */
209
    public function __call($name, $params)
210
    {
211
        return call_user_func_array([$this->getTranslation(), $name], $params);
212
    }
213
214 1
    /**
215
     * @return bool
216 1
     */
217
    public function isTranslated()
218
    {
219
        return $this->isSourceLanguage() === false && $this->getTranslation()->getIsNewRecord() === false;
220
    }
221
222
    /**
223 3
     * This read only relations designed for method $this->hasTranslate()
224
     * @return \yii\db\ActiveQuery
225 3
     */
226 3
    public function getHasTranslate()
227 3
    {
228
        $relations = $this->getRelation();
229
        $select = array_keys($relations->link);
230 3
        $select[] = $this->languageAttribute;
231 3
232 3
        return $relations
233
            ->select($select)
234
            ->indexBy($this->languageAttribute)
235
            ->asArray();
236
    }
237
238 8
    /**
239
     * @return \yii\db\ActiveQuery
240 8
     */
241 8
    public function getCurrentTranslate()
242
    {
243 8
        $langList = [$this->language, $this->sourceLanguage];
244 8
        $langList = array_keys(array_flip($langList));
245 8
246
        return $this->getRelation()
247
            ->where([$this->languageAttribute => $langList])
248
            ->indexBy($this->languageAttribute);
249
    }
250
}
251