forked from terrasoff/yii-flag-behavior
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FlagBehavior.php
122 lines (110 loc) · 2.89 KB
/
FlagBehavior.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
<?php
/**
* Bits data
* @author Tarasov Konstantin
*/
class FlagBehavior extends CBehavior
{
public $errorCode = '500';
/**
* Model's bit field name
* Use type INT|BIGINT for MySQL
* @var string
*/
public $fieldName = 'settings';
/**
* Flags collection,
*
* WARNING!
* Once defined flag's index (bit's order) never change it!.
* @var array
*/
public $flags = array();
/**
* Set specified flag value
* @param string $name
* @param bool $value
* @return int new field value
*/
public function setFlag($name, $value = true) {
$object = $this->getOwner();
$flags = $object->{$this->fieldName};
$flagValue = $this->getFlagValue($name);
// set
if ($value) {
$object->{$this->fieldName} = $flags | $flagValue;
}
// unset
else
{
$object->{$this->fieldName} = $flags & $flagValue
? $flags ^ $flagValue
: $flags ^ $flagValue ^ $flagValue;
}
return $object;
}
/**
* Unset specified flag value
* Could use both clearFlag(User::SETTINGS_ENABLED) or setFlag(User::SETTINGS_ENABLED, false)
* @param $name
* @return int
*/
public function clearFlag($name) {
return $this->setFlag($name, false);
}
/**
* Is specified flag set?
* @param $name
* @return bool
*/
public function hasFlag($name) {
$object = $this->getOwner();
$flag = $this->getFlagValue($name);
return ($object->{$this->fieldName} & $flag) === $flag;
}
/**
* Get flag index (bit's order) in collection
* @param $name
* @return int
* @throws CException
*/
public function getFlagIndex($name) {
if (!isset($this->flags[$name]))
throw new \Exception("Model flag {$name} not found");
return $this->flags[$name];
}
/**
* Get flag value
* @param $name
* @return number
*/
public function getFlagValue($name) {
return pow(2,$this->getFlagIndex($name));
}
/**
* Search by flags
* @param $flags
* @return CActiveRecord
*/
public function scopeFlags($flags) {
/** @var $object CActiveRecord */
$flags = $this->mergeFlags($flags);
$object = $this->getOwner();
$object->getDbCriteria()->mergeWith(array(
'condition'=>$this->fieldName.' & :flag = :flag',
'params' => array(':flag' => $flags),
));
$object->getDbCriteria()->params[':flag'] = $flags;
return $object;
}
/**
* Get combined flags value
* @param $flags
* @return int
*/
private function mergeFlags($flags) {
return (int)array_reduce($flags, function($result, $value) {
return $result = $result | pow(2, $value);
});
}
}