These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Aeria\Field\Fields; |
||
4 | |||
5 | use Aeria\Aeria; |
||
6 | use Aeria\Field\FieldError; |
||
7 | use Aeria\Validator\Validator; |
||
8 | use Aeria\Structure\Node; |
||
9 | use Aeria\Field\Interfaces\FieldInterface; |
||
10 | |||
11 | /** |
||
12 | * BaseField is the class that represents every Aeria field. |
||
13 | * |
||
14 | * @category Field |
||
15 | * |
||
16 | * @author Andrea Longo <[email protected]> |
||
17 | * @license https://github.com/caffeinalab/aeria/blob/master/LICENSE MIT license |
||
18 | * |
||
19 | * @see https://github.com/caffeinalab/aeria |
||
20 | */ |
||
21 | class BaseField extends Node implements FieldInterface |
||
22 | { |
||
23 | protected $original_config; |
||
24 | |||
25 | public $is_multiple_field = false; |
||
26 | |||
27 | /** |
||
28 | * Transform the config array; note that this does not operate on |
||
29 | * `$this->config`: this way it can be called from outside. |
||
30 | * |
||
31 | * @param array $config the field's config |
||
32 | * |
||
33 | * @return array the transformed config |
||
34 | */ |
||
35 | public static function transformConfig(array $config) |
||
36 | { |
||
37 | return $config; |
||
38 | } |
||
39 | |||
40 | /** |
||
41 | * Constructs the field. |
||
42 | * |
||
43 | * @param string $parent_key the field's parent key |
||
44 | * @param array $config the field's config |
||
45 | * @param array $sections Aeria's sections config |
||
46 | * @param array $index index for multiple fields |
||
47 | * |
||
48 | * @since Method available since Release 3.0.0 |
||
49 | */ |
||
50 | public function __construct($parent_key, $config, $sections, $index = null) |
||
51 | { |
||
52 | $this->parent_key = $parent_key; |
||
53 | $this->original_config = isset($config['original_config']) ? $config['original_config'] : $config; |
||
54 | |||
55 | unset($config['original_config']); |
||
56 | |||
57 | $this->config = $config; |
||
58 | |||
59 | $this->id = isset($config['id']) |
||
60 | ? $config['id'] |
||
61 | : null; |
||
62 | $this->index = $index; |
||
63 | $this->key = $this->getKey(); |
||
64 | $this->sections = $sections; |
||
65 | } |
||
66 | |||
67 | /** |
||
68 | * Checks whether a field should be child of another. |
||
69 | * |
||
70 | * @param Node $possible_parent the field's possible parent |
||
71 | * |
||
72 | * @return bool whether the field should be child of $possible_parent |
||
73 | * |
||
74 | * @since Method available since Release 3.0.0 |
||
75 | */ |
||
76 | public function shouldBeChildOf(Node $possible_parent) |
||
77 | { |
||
78 | if ($possible_parent->is_multiple_field) { |
||
79 | if (preg_match('/^'.$possible_parent->getKey().'.{1,}/', $this->getKey())) { |
||
0 ignored issues
–
show
|
|||
80 | return true; |
||
81 | } else { |
||
82 | return false; |
||
83 | } |
||
84 | } elseif (get_class($possible_parent) == 'RootNode') { // Check if possible_parent is root |
||
85 | return true; |
||
86 | } else { |
||
87 | return false; |
||
88 | } |
||
89 | } |
||
90 | |||
91 | /** |
||
92 | * Gets the field full key. |
||
93 | * |
||
94 | * @return string the field's key |
||
95 | * |
||
96 | * @since Method available since Release 3.0.0 |
||
97 | */ |
||
98 | public function getKey() |
||
99 | { |
||
100 | return $this->parent_key |
||
101 | .(!is_null($this->index) ? '-'.$this->index : '') |
||
102 | .(!is_null($this->id) ? '-'.$this->id : ''); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Gets the field's value. |
||
107 | * |
||
108 | * @param array $saved_fields the FieldGroup's saved fields |
||
109 | * @param bool $skip_filter whether to skip or not WP's filter |
||
110 | * |
||
111 | * @return mixed the field's value |
||
112 | * |
||
113 | * @since Method available since Release 3.0.0 |
||
114 | */ |
||
115 | public function get(array $saved_fields, bool $skip_filter = false) |
||
116 | { |
||
117 | if (!isset($saved_fields[$this->key])) { |
||
118 | return null; |
||
119 | } |
||
120 | if (!$skip_filter) { |
||
121 | $saved_fields[$this->key] = apply_filters('aeria_get_base', $saved_fields[$this->key], $this->config); |
||
122 | $saved_fields[$this->key] = apply_filters('aeria_get_'.$this->key, $saved_fields[$this->key], $this->config); |
||
123 | } |
||
124 | if (is_array($saved_fields[$this->key])) { |
||
125 | return $saved_fields[$this->key][0]; |
||
126 | } else { |
||
127 | return $saved_fields[$this->key]; |
||
128 | } |
||
129 | } |
||
130 | |||
131 | /** |
||
132 | * Gets the field's value and its errors. |
||
133 | * |
||
134 | * @param array $saved_fields the FieldGroup's saved fields |
||
135 | * @param array $errors the saving errors |
||
136 | * |
||
137 | * @return array the field's config, hydrated with values and errors |
||
138 | * |
||
139 | * @since Method available since Release 3.0.0 |
||
140 | */ |
||
141 | public function getAdmin(array $saved_fields, array $errors) |
||
142 | { |
||
143 | if (isset($errors[$this->key])) { |
||
144 | $result = [ |
||
145 | 'value' => $errors[$this->key]['value'], |
||
146 | 'error' => $errors[$this->key]['message'], |
||
147 | ]; |
||
148 | } else { |
||
149 | $result = [ |
||
150 | 'value' => $this->get($saved_fields, true), |
||
151 | ]; |
||
152 | } |
||
153 | |||
154 | $config = array_merge( |
||
155 | $this->config, |
||
156 | $result |
||
157 | ); |
||
158 | |||
159 | $config = apply_filters('aeria_get_admin_base', $config); |
||
160 | $config = apply_filters('aeria_get_admin_'.$this->id, $config); |
||
161 | $config = apply_filters('aeria_get_admin_'.$this->key, $config); |
||
162 | |||
163 | return $config; |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * Saves the new values to the fields. |
||
168 | * |
||
169 | * @param int $context_ID the context ID. For posts, post's ID |
||
170 | * @param string $context_type the context type. Right now, options|meta |
||
171 | * @param array $saved_fields the saved fields |
||
172 | * @param array $new_values the values we're saving |
||
173 | * @param Validator $validator_service Aeria's validator service |
||
174 | * @param Query $query_service Aeria's query service |
||
175 | * |
||
176 | * @return array the results of the saving |
||
177 | * |
||
178 | * @since Method available since Release 3.0.0 |
||
179 | */ |
||
180 | public function set($context_ID, $context_type, array $saved_fields, array $new_values, $validator_service, $query_service) |
||
181 | { |
||
182 | $value = isset($new_values[$this->key]) ? $new_values[$this->key] : null; |
||
183 | $old = isset($saved_fields[$this->key][0]) ? $saved_fields[$this->key][0] : ''; |
||
184 | $value = apply_filters('aeria_set_'.$this->key, $value, $this->config); |
||
185 | if ($value == $old) { |
||
186 | return ['value' => $value]; |
||
187 | } |
||
188 | if (is_null($value) || $value == '') { |
||
189 | $this->deleteField($context_ID, $context_type, $query_service); |
||
190 | |||
191 | return ['value' => $value]; |
||
192 | } else { |
||
193 | $validators = (isset($this->config['validators'])) ? $this->config['validators'] : ''; |
||
194 | $error = $validator_service->validate($value, $validators); |
||
195 | |||
196 | if (!$error['status']) { |
||
197 | $this->saveField($context_ID, $context_type, $value, $old); |
||
198 | |||
199 | return ['value' => $value]; |
||
200 | } else { |
||
201 | FieldError::make($context_ID) |
||
202 | ->addError($this->key, $error); |
||
203 | |||
204 | return $error; |
||
205 | } |
||
206 | } |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * Saves a single field to the DB. |
||
211 | * |
||
212 | * @param int $context_ID the context ID. For posts, post's ID |
||
213 | * @param string $context_type the context type. Right now, options|meta |
||
214 | * @param mixed $value the new value |
||
215 | * @param mixed $old the old value |
||
216 | * |
||
217 | * @throws Exception if the node context is invalid |
||
218 | * |
||
219 | * @since Method available since Release 3.0.0 |
||
220 | */ |
||
221 | View Code Duplication | private function saveField($context_ID, $context_type, $value, $old) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
222 | { |
||
223 | switch ($context_type) { |
||
224 | case 'options': |
||
225 | update_option($this->key, $value); |
||
226 | break; |
||
227 | case 'meta': |
||
228 | update_post_meta($context_ID, $this->key, $value, $old); |
||
229 | break; |
||
230 | default: |
||
231 | throw new Exception('Node context is not valid.'); |
||
232 | break; |
||
233 | } |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * Deletes a field value. |
||
238 | * |
||
239 | * @param int $context_ID the context ID. For posts, post's ID |
||
240 | * @param string $context_type the context type. Right now, options|meta |
||
241 | * @param Query $query_service Aeria's query service |
||
242 | * |
||
243 | * @throws Exception if the node context is invalid |
||
244 | * |
||
245 | * @since Method available since Release 3.0.0 |
||
246 | */ |
||
247 | View Code Duplication | private function deleteField($context_ID, $context_type, $query_service) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
248 | { |
||
249 | switch ($context_type) { |
||
250 | case 'options': |
||
251 | delete_option($this->key); |
||
252 | break; |
||
253 | case 'meta': |
||
254 | delete_post_meta($context_ID, $this->key); |
||
255 | break; |
||
256 | |||
257 | default: |
||
258 | throw new Exception('Node context is not valid.'); |
||
259 | break; |
||
260 | } |
||
261 | } |
||
262 | } |
||
263 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: