/
ExtendedBehavior.php
133 lines (118 loc) · 3.58 KB
/
ExtendedBehavior.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
<?php
namespace mdm\extended;
use Yii;
use yii\db\BaseActiveRecord;
use yii\validators\Validator;
use yii\base\InvalidConfigException;
/**
* Description of ExtendedBehavior
*
* @property \yii\db\BaseActiveRecord $owner
*
* @author Misbahul D Munir (mdmunir) <misbahuldmunir@gmail.com>
*/
class ExtendedBehavior extends \yii\base\Behavior
{
/**
*
* @var \yii\db\BaseActiveRecord
*/
private $_relation;
/**
*
* @var string
*/
public $relationClass;
/**
*
* @var array
*/
public $relationKey;
public function events()
{
return[
BaseActiveRecord::EVENT_AFTER_FIND => 'loadRelation',
BaseActiveRecord::EVENT_AFTER_INSERT => 'afterSave',
BaseActiveRecord::EVENT_AFTER_UPDATE => 'afterSave',
BaseActiveRecord::EVENT_AFTER_DELETE => 'afterDelete'
];
}
public function attach($owner)
{
parent::attach($owner);
$this->loadRelation();
$validators = $owner->validators;
foreach ($this->_relation->rules() as $rule) {
if ($rule instanceof Validator) {
$validators->append($rule);
} elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type
$validator = Validator::createValidator($rule[1], $owner, (array) $rule[0], array_slice($rule, 2));
$validators->append($validator);
} else {
throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
}
}
}
public function canGetProperty($name, $checkVars = true)
{
return $this->_relation->canGetProperty($name, $checkVars) || parent::canGetProperty($name, $checkVars);
}
public function canSetProperty($name, $checkVars = true)
{
return $this->_relation->canSetProperty($name, $checkVars) || parent::canSetProperty($name, $checkVars);
}
public function __get($name)
{
if ($this->_relation->canGetProperty($name)) {
return $this->_relation->$name;
} else {
return parent::__get($name);
}
}
public function __set($name, $value)
{
if ($this->_relation->canGetProperty($name)) {
$this->_relation->$name = $value;
} else {
parent::__set($name, $value);
}
}
public function loadRelation()
{
if ($this->relationKey === null) {
$this->relationKey = [];
foreach ($this->owner->primaryKey() as $name) {
$this->relationKey[$name] = $name;
}
}
/* @var $class \yii\db\BaseActiveRecord */
$class = $this->relationClass;
if ($this->owner->isNewRecord) {
$this->_relation = Yii::createObject($class);
} else {
$conditions = [];
foreach ($this->relationKey as $from => $to) {
$conditions[$to] = $this->owner[$from];
}
if (($this->_relation = $class::findOne($conditions)) === null) {
$conditions['class'] = $class;
$this->_relation = Yii::createObject($conditions);
}
}
}
/**
*
* @param \yii\base\Event $event
*/
public function afterSave($event)
{
foreach ($this->relationKey as $from => $to) {
$this->_relation[$to] = $this->owner[$from];
}
$this->_relation->save();
}
public function afterDelete($event)
{
$this->_relation->delete();
}
}