Completed
Push — master ( 27a38b...3364e5 )
by Loban
02:07
created

TranslatedBehavior::eventBeforeDelete()   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

Importance

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