1 | <?php |
||
2 | /** |
||
3 | * Created by Gorlum 14.11.2018 0:43 |
||
4 | */ |
||
5 | |||
6 | namespace Common; |
||
7 | |||
8 | |||
9 | use Exception; |
||
10 | |||
11 | abstract class AccessLoggedAbstract extends AccessMagic { |
||
12 | const ACCESS_SET = null; |
||
13 | const ACCESS_DELTA_INC = +1; |
||
14 | const ACCESS_DELTA_DEC = -1; |
||
15 | |||
16 | /** |
||
17 | * Starting values of properties |
||
18 | * |
||
19 | * @var array $_startValues |
||
20 | */ |
||
21 | protected $_startValues = []; |
||
22 | /** |
||
23 | * Changed values |
||
24 | * |
||
25 | * @var array $_changes |
||
26 | */ |
||
27 | protected $_changes = []; |
||
28 | /** |
||
29 | * Increment/Decrement results AKA deltas |
||
30 | * |
||
31 | * @var array $_deltas |
||
32 | */ |
||
33 | protected $_deltas = []; |
||
34 | |||
35 | /** |
||
36 | * Current operation: direct store or positive/negative delta which would be applied on next __set() call |
||
37 | * |
||
38 | * @var int|float $_currentOperation |
||
39 | */ |
||
40 | protected $_currentOperation = self::ACCESS_SET; |
||
41 | |||
42 | public function clear() { |
||
43 | parent::clear(); |
||
44 | $this->accept(); |
||
45 | } |
||
46 | |||
47 | /** |
||
48 | * @param string $name |
||
49 | * |
||
50 | * @throws Exception |
||
51 | */ |
||
52 | protected function blockChange($name) { |
||
53 | if (array_key_exists($name, $this->_deltas)) { |
||
54 | throw new Exception(get_called_class() . '::' . $name . ' already INCREMENTED/DECREMENTED - can not CHANGE', ERR_ERROR); |
||
55 | } |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * @param string $name |
||
60 | * |
||
61 | * @throws Exception |
||
62 | */ |
||
63 | protected function blockDelta($name) { |
||
64 | if (array_key_exists($name, $this->_changes)) { |
||
65 | throw new Exception(get_called_class() . '::' . $name . ' already changed - can not use DELTA', ERR_ERROR); |
||
66 | } |
||
67 | } |
||
68 | |||
69 | // /** |
||
70 | // * Stub to pass call down |
||
71 | // * |
||
72 | // * @param string $name |
||
73 | // * @param mixed $value |
||
74 | // */ |
||
75 | // public function __set($name, $value) { |
||
76 | // parent::__set($name, $value); |
||
77 | // } |
||
78 | |||
79 | // /** |
||
80 | // * Stub to pass call down |
||
81 | // * |
||
82 | // * @param string $name |
||
83 | // * |
||
84 | // * @return mixed |
||
85 | // */ |
||
86 | // public function __get($name) { |
||
87 | // return parent::__get($name); |
||
88 | // } |
||
89 | |||
90 | // public function __set($name, $value) { |
||
91 | // if ($this->_currentOperation === self::ACCESS_SET) { |
||
92 | // $this->valueSet($name, $value); |
||
93 | // } else { |
||
94 | // $this->valueDelta($name, $value); |
||
95 | // } |
||
96 | // } |
||
97 | |||
98 | /** |
||
99 | * @param string $name |
||
100 | * @param $value |
||
101 | * |
||
102 | * @throws Exception |
||
103 | */ |
||
104 | abstract protected function valueSet($name, $value); |
||
105 | |||
106 | /** |
||
107 | * @param string $name |
||
108 | * @param mixed $value |
||
109 | * |
||
110 | * @throws Exception |
||
111 | */ |
||
112 | abstract protected function valueDelta($name, $value); |
||
113 | |||
114 | |||
115 | /** |
||
116 | * Mark next set operation as delta increment |
||
117 | * |
||
118 | * @return $this |
||
119 | */ |
||
120 | public function inc() { |
||
121 | $this->_currentOperation = self::ACCESS_DELTA_INC; |
||
122 | |||
123 | return $this; |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Mark next set operation as delta decrement |
||
128 | * |
||
129 | * @return $this |
||
130 | */ |
||
131 | public function dec() { |
||
132 | $this->_currentOperation = self::ACCESS_DELTA_DEC; |
||
133 | |||
134 | return $this; |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * Accepts changes |
||
139 | * |
||
140 | * Makes current values a start one and resets changes/deltas |
||
141 | */ |
||
142 | public function accept() { |
||
143 | $this->_startValues = $this->values; |
||
0 ignored issues
–
show
|
|||
144 | $this->_currentOperation = self::ACCESS_SET; |
||
145 | $this->_changes = []; |
||
146 | $this->_deltas = []; |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Rolls changes back |
||
151 | */ |
||
152 | public function reject() { |
||
153 | $this->values = $this->_startValues; |
||
154 | $this->_currentOperation = self::ACCESS_SET; |
||
155 | $this->_changes = []; |
||
156 | $this->_deltas = []; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Is container was changed? |
||
161 | * |
||
162 | * @return bool |
||
163 | */ |
||
164 | public function isChanged() { |
||
165 | return |
||
166 | ! empty($this->_changes) |
||
167 | || |
||
168 | ! empty($this->_deltas); |
||
169 | } |
||
170 | |||
171 | public function getChanges() { |
||
172 | return $this->_changes; |
||
173 | } |
||
174 | |||
175 | public function getDeltas() { |
||
176 | return $this->_deltas; |
||
177 | } |
||
178 | |||
179 | } |
||
180 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.