Completed
Push — master ( 616bb2...27a38b )
by Loban
36:26 queued 33:59
created

TranslatedBehavior::isTranslated()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

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