This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
1 | <?php |
||||||
2 | /** |
||||||
3 | * REST API Setting Options controller |
||||||
4 | * |
||||||
5 | * Handles requests to the /settings and /settings/$setting_id endpoints. |
||||||
6 | * |
||||||
7 | * @package GetPaid |
||||||
8 | * @subpackage REST API |
||||||
9 | * @since 2.0.0 |
||||||
10 | */ |
||||||
11 | |||||||
12 | defined( 'ABSPATH' ) || exit; |
||||||
13 | |||||||
14 | /** |
||||||
15 | * GetPaid REST Setting controller class. |
||||||
16 | * |
||||||
17 | * @package Invoicing |
||||||
18 | */ |
||||||
19 | class GetPaid_REST_Settings_Controller extends GetPaid_REST_Controller { |
||||||
20 | |||||||
21 | /** |
||||||
22 | * An array of available settings. |
||||||
23 | * |
||||||
24 | * @var string |
||||||
25 | */ |
||||||
26 | protected $settings; |
||||||
27 | |||||||
28 | /** |
||||||
29 | * Route base. |
||||||
30 | * |
||||||
31 | * @var string |
||||||
32 | */ |
||||||
33 | protected $rest_base = 'settings'; |
||||||
34 | |||||||
35 | /** |
||||||
36 | * Registers the routes for the objects of the controller. |
||||||
37 | * |
||||||
38 | * @since 2.0.0 |
||||||
39 | * |
||||||
40 | * @see register_rest_route() |
||||||
41 | */ |
||||||
42 | public function register_namespace_routes( $namespace ) { |
||||||
43 | |||||||
44 | // List all registered tabs. |
||||||
45 | register_rest_route( |
||||||
46 | $namespace, |
||||||
47 | $this->rest_base, |
||||||
48 | array( |
||||||
49 | array( |
||||||
50 | 'methods' => WP_REST_Server::READABLE, |
||||||
51 | 'callback' => array( $this, 'get_tabs' ), |
||||||
52 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||||||
53 | ), |
||||||
54 | 'schema' => '__return_empty_array', |
||||||
55 | ) |
||||||
56 | ); |
||||||
57 | |||||||
58 | // View/Update a single setting. |
||||||
59 | register_rest_route( |
||||||
60 | $namespace, |
||||||
61 | $this->rest_base . '/setting/(?P<id>[\w-]+)', |
||||||
62 | array( |
||||||
63 | 'args' => array( |
||||||
64 | 'id' => array( |
||||||
65 | 'description' => __( 'Unique identifier for the setting.', 'invoicing' ), |
||||||
66 | 'type' => 'string', |
||||||
67 | 'required' => true, |
||||||
68 | ), |
||||||
69 | ), |
||||||
70 | array( |
||||||
71 | 'methods' => WP_REST_Server::READABLE, |
||||||
72 | 'callback' => array( $this, 'get_item' ), |
||||||
73 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||||||
74 | ), |
||||||
75 | array( |
||||||
76 | 'methods' => WP_REST_Server::EDITABLE, |
||||||
77 | 'callback' => array( $this, 'update_item' ), |
||||||
78 | 'permission_callback' => array( $this, 'update_items_permissions_check' ), |
||||||
79 | 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
||||||
80 | ), |
||||||
81 | 'schema' => array( $this, 'get_public_item_schema' ), |
||||||
82 | ) |
||||||
83 | ); |
||||||
84 | |||||||
85 | // List registered sections for a given tab. |
||||||
86 | register_rest_route( |
||||||
87 | $namespace, |
||||||
88 | $this->rest_base . '/(?P<tab>[\w-]+)', |
||||||
89 | array( |
||||||
90 | 'args' => array( |
||||||
91 | 'tab' => array( |
||||||
92 | 'description' => __( 'Unique identifier for the tab whose sections should be retrieved.', 'invoicing' ), |
||||||
93 | 'type' => 'string', |
||||||
94 | 'required' => true, |
||||||
95 | 'enum' => array_keys( wpinv_get_settings_tabs() ), |
||||||
96 | ), |
||||||
97 | ), |
||||||
98 | array( |
||||||
99 | 'methods' => WP_REST_Server::READABLE, |
||||||
100 | 'callback' => array( $this, 'get_sections' ), |
||||||
101 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||||||
102 | ), |
||||||
103 | 'schema' => '__return_empty_array', |
||||||
104 | ) |
||||||
105 | ); |
||||||
106 | |||||||
107 | // List all registered settings for a given tab. |
||||||
108 | register_rest_route( |
||||||
109 | $namespace, |
||||||
110 | $this->rest_base . '/(?P<tab>[\w-]+)/(?P<section>[\w-]+)', |
||||||
111 | array( |
||||||
112 | 'args' => array( |
||||||
113 | 'tab' => array( |
||||||
114 | 'description' => __( 'Unique identifier for the tab whose settings should be retrieved.', 'invoicing' ), |
||||||
115 | 'type' => 'string', |
||||||
116 | 'required' => true, |
||||||
117 | 'enum' => array_keys( wpinv_get_settings_tabs() ), |
||||||
118 | ), |
||||||
119 | 'section' => array( |
||||||
120 | 'description' => __( 'The section in the tab whose settings should be retrieved.', 'invoicing' ), |
||||||
121 | 'type' => 'string', |
||||||
122 | 'required' => true, |
||||||
123 | ), |
||||||
124 | ), |
||||||
125 | array( |
||||||
126 | 'methods' => WP_REST_Server::READABLE, |
||||||
127 | 'callback' => array( $this, 'get_items' ), |
||||||
128 | 'permission_callback' => array( $this, 'get_items_permissions_check' ), |
||||||
129 | ), |
||||||
130 | 'schema' => array( $this, 'get_public_item_schema' ), |
||||||
131 | ) |
||||||
132 | ); |
||||||
133 | |||||||
134 | register_rest_route( |
||||||
135 | $namespace, |
||||||
136 | '/' . $this->rest_base . '/batch', |
||||||
137 | array( |
||||||
138 | 'args' => array( |
||||||
139 | 'id' => array( |
||||||
140 | 'description' => __( 'Setting ID.', 'invoicing' ), |
||||||
141 | 'type' => 'string', |
||||||
142 | ), |
||||||
143 | ), |
||||||
144 | array( |
||||||
145 | 'methods' => WP_REST_Server::EDITABLE, |
||||||
146 | 'callback' => array( $this, 'batch_items' ), |
||||||
147 | 'permission_callback' => array( $this, 'batch_items_permissions_check' ), |
||||||
148 | 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), |
||||||
149 | ), |
||||||
150 | 'schema' => array( $this, 'get_public_batch_schema' ), |
||||||
151 | ) |
||||||
152 | ); |
||||||
153 | |||||||
154 | } |
||||||
155 | |||||||
156 | /** |
||||||
157 | * Return all settings. |
||||||
158 | * |
||||||
159 | * @since 2.0.0 |
||||||
160 | * @param WP_REST_Request $request Request data. |
||||||
161 | * @return WP_Error|WP_REST_Response |
||||||
162 | */ |
||||||
163 | public function get_items( $request ) { |
||||||
164 | |||||||
165 | $settings = $this->get_settings(); |
||||||
166 | |||||||
167 | if ( ! isset( $settings[ $request['tab'] ] ) ) { |
||||||
168 | return new WP_Error( 'rest_invalid_tab', __( 'Invalid tab.', 'invoicing' ), array( 'status' => 400 ) ); |
||||||
169 | } |
||||||
170 | |||||||
171 | if ( ! isset( $settings[ $request['tab'] ][ $request['section'] ] ) ) { |
||||||
172 | return new WP_Error( 'rest_invalid_section', __( 'Invalid section.', 'invoicing' ), array( 'status' => 400 ) ); |
||||||
173 | } |
||||||
174 | |||||||
175 | $settings = $settings[ $request['tab'] ][ $request['section'] ]; |
||||||
176 | $prepared = array(); |
||||||
177 | |||||||
178 | foreach ( $settings as $setting ) { |
||||||
179 | |||||||
180 | $setting = $this->sanitize_setting( $setting ); |
||||||
181 | $setting_data = $this->prepare_item_for_response( $setting, $request ); |
||||||
182 | $setting_data = $this->prepare_response_for_collection( $setting_data ); |
||||||
183 | |||||||
184 | if ( $this->is_setting_type_valid( $setting['type'] ) ) { |
||||||
185 | $prepared[] = $setting_data; |
||||||
186 | } |
||||||
187 | } |
||||||
188 | |||||||
189 | return rest_ensure_response( $prepared ); |
||||||
190 | } |
||||||
191 | |||||||
192 | /** |
||||||
193 | * Return a single setting. |
||||||
194 | * |
||||||
195 | * @since 2.0.0 |
||||||
196 | * @param WP_REST_Request $request Request data. |
||||||
197 | * @return WP_Error|WP_REST_Response |
||||||
198 | */ |
||||||
199 | public function get_item( $request ) { |
||||||
200 | $setting = $this->get_setting( $request['id'] ); |
||||||
201 | |||||||
202 | if ( is_wp_error( $setting ) ) { |
||||||
203 | return $setting; |
||||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||||
204 | } |
||||||
205 | |||||||
206 | $setting = $this->sanitize_setting( $setting ); |
||||||
0 ignored issues
–
show
It seems like
$setting can also be of type WP_Error ; however, parameter $setting of GetPaid_REST_Settings_Co...ler::sanitize_setting() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
207 | $response = $this->prepare_item_for_response( $setting, $request ); |
||||||
208 | return rest_ensure_response( $response ); |
||||||
209 | } |
||||||
210 | |||||||
211 | /** |
||||||
212 | * Update a single setting. |
||||||
213 | * |
||||||
214 | * @since 2.0.0 |
||||||
215 | * @param WP_REST_Request $request Request data. |
||||||
216 | * @return WP_Error|WP_REST_Response |
||||||
217 | */ |
||||||
218 | public function update_item( $request ) { |
||||||
219 | $setting = $this->get_setting( $request['id'] ); |
||||||
220 | |||||||
221 | if ( is_wp_error( $setting ) ) { |
||||||
222 | return $setting; |
||||||
0 ignored issues
–
show
|
|||||||
223 | } |
||||||
224 | |||||||
225 | if ( is_callable( array( $this, 'validate_setting_' . $setting['type'] . '_field' ) ) ) { |
||||||
226 | $value = $this->{'validate_setting_' . $setting['type'] . '_field'}( $request['value'], $setting ); |
||||||
227 | } else { |
||||||
228 | $value = $this->validate_setting_text_field( $request['value'], $setting ); |
||||||
0 ignored issues
–
show
The call to
GetPaid_REST_Settings_Co...te_setting_text_field() has too many arguments starting with $setting .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||||
229 | } |
||||||
230 | |||||||
231 | if ( is_wp_error( $value ) ) { |
||||||
232 | return $value; |
||||||
233 | } |
||||||
234 | |||||||
235 | wpinv_update_option( $request['id'], $value ); |
||||||
236 | $setting['value'] = $value; |
||||||
237 | $setting = $this->sanitize_setting( $setting ); |
||||||
0 ignored issues
–
show
It seems like
$setting can also be of type WP_Error ; however, parameter $setting of GetPaid_REST_Settings_Co...ler::sanitize_setting() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
238 | $response = $this->prepare_item_for_response( $setting, $request ); |
||||||
239 | |||||||
240 | return rest_ensure_response( $response ); |
||||||
241 | } |
||||||
242 | |||||||
243 | /** |
||||||
244 | * Makes sure the current user has access to READ the settings APIs. |
||||||
245 | * |
||||||
246 | * @since 2.0.0 |
||||||
247 | * @param WP_REST_Request $request Full data about the request. |
||||||
248 | * @return WP_Error|boolean |
||||||
249 | */ |
||||||
250 | public function get_items_permissions_check( $request ) { |
||||||
251 | if ( ! wpinv_current_user_can_manage_invoicing() ) { |
||||||
252 | return new WP_Error( 'rest_cannot_view', __( 'Sorry, you cannot list resources.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) ); |
||||||
253 | } |
||||||
254 | |||||||
255 | return true; |
||||||
256 | } |
||||||
257 | |||||||
258 | /** |
||||||
259 | * Makes sure the current user has access to WRITE the settings APIs. |
||||||
260 | * |
||||||
261 | * @since 2.0.0 |
||||||
262 | * @param WP_REST_Request $request Full data about the request. |
||||||
263 | * @return WP_Error|boolean |
||||||
264 | */ |
||||||
265 | public function update_items_permissions_check( $request ) { |
||||||
266 | if ( ! wpinv_current_user_can_manage_invoicing() ) { |
||||||
267 | return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) ); |
||||||
268 | } |
||||||
269 | |||||||
270 | return true; |
||||||
271 | } |
||||||
272 | |||||||
273 | /** |
||||||
274 | * Check if a given request has access batch create, update and delete items. |
||||||
275 | * |
||||||
276 | * @param WP_REST_Request $request Full details about the request. |
||||||
277 | * |
||||||
278 | * @return boolean|WP_Error |
||||||
279 | */ |
||||||
280 | public function batch_items_permissions_check( $request ) { |
||||||
281 | return wpinv_current_user_can_manage_invoicing() ? true : new WP_Error( 'rest_cannot_batch', __( 'Sorry, you are not allowed to batch manipulate this resource.', 'invoicing' ), array( 'status' => rest_authorization_required_code() ) ); |
||||||
282 | } |
||||||
283 | |||||||
284 | /** |
||||||
285 | * Prepare links for the request. |
||||||
286 | * |
||||||
287 | * @param string $setting_id Setting ID. |
||||||
288 | * @return array Links for the given setting. |
||||||
289 | */ |
||||||
290 | protected function prepare_links( $setting_id ) { |
||||||
291 | |||||||
292 | $links = array( |
||||||
293 | 'self' => array( |
||||||
294 | 'href' => rest_url( sprintf( '/%s/%s/setting/%s', $this->namespace, $this->rest_base, $setting_id ) ), |
||||||
295 | ), |
||||||
296 | 'collection' => array( |
||||||
297 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), |
||||||
298 | ), |
||||||
299 | ); |
||||||
300 | |||||||
301 | return $links; |
||||||
302 | } |
||||||
303 | |||||||
304 | /** |
||||||
305 | * Prepare a settings object for serialization. |
||||||
306 | * |
||||||
307 | * @since 2.0.0 |
||||||
308 | * @param array $item Setting object. |
||||||
309 | * @param WP_REST_Request $request Request object. |
||||||
310 | * @return WP_REST_Response $response Response data. |
||||||
311 | */ |
||||||
312 | public function prepare_item_for_response( $item, $request ) { |
||||||
313 | $context = empty( $request['context'] ) ? 'view' : $request['context']; |
||||||
314 | $data = $this->add_additional_fields_to_object( $item, $request ); |
||||||
315 | $data = $this->filter_response_by_context( $data, $context ); |
||||||
316 | |||||||
317 | $response = rest_ensure_response( $data ); |
||||||
318 | |||||||
319 | $response->add_links( $this->prepare_links( $item['id'] ) ); |
||||||
320 | |||||||
321 | return $response; |
||||||
322 | } |
||||||
323 | |||||||
324 | /** |
||||||
325 | * Filters out bad values from the settings array/filter so we |
||||||
326 | * only return known values via the API. |
||||||
327 | * |
||||||
328 | * @since 2.0.0 |
||||||
329 | * @param array $setting Setting. |
||||||
330 | * @return array |
||||||
331 | */ |
||||||
332 | public function filter_setting( $setting ) { |
||||||
333 | return array_intersect_key( |
||||||
334 | $setting, |
||||||
335 | array_flip( array_filter( array_keys( $setting ), array( $this, 'allowed_setting_keys' ) ) ) |
||||||
336 | ); |
||||||
337 | } |
||||||
338 | |||||||
339 | /** |
||||||
340 | * Callback for allowed keys for each setting response. |
||||||
341 | * |
||||||
342 | * @param string $key Key to check. |
||||||
343 | * @return boolean |
||||||
344 | */ |
||||||
345 | public function allowed_setting_keys( $key ) { |
||||||
346 | return in_array( $key, array_keys( $this->setting_defaults() ), true ); |
||||||
347 | } |
||||||
348 | |||||||
349 | /** |
||||||
350 | * Returns default options for a setting. null means the field is required. |
||||||
351 | * |
||||||
352 | * @since 2.0.0 |
||||||
353 | * @return array |
||||||
354 | */ |
||||||
355 | protected function setting_defaults() { |
||||||
356 | return array( |
||||||
357 | 'id' => null, |
||||||
358 | 'name' => null, |
||||||
359 | 'desc' => '', |
||||||
360 | 'options' => array(), |
||||||
361 | 'std' => false, |
||||||
362 | 'value' => false, |
||||||
363 | 'placeholder' => '', |
||||||
364 | 'readonly' => false, |
||||||
365 | 'faux' => false, |
||||||
366 | 'section' => 'main', |
||||||
367 | 'tab' => 'general', |
||||||
368 | 'type' => 'text', |
||||||
369 | ); |
||||||
370 | } |
||||||
371 | |||||||
372 | /** |
||||||
373 | * Sanitizes a setting's field. |
||||||
374 | * |
||||||
375 | * @param array $setting The setting to sanitize. |
||||||
376 | * @return array |
||||||
377 | */ |
||||||
378 | public function sanitize_setting( $setting ) { |
||||||
379 | |||||||
380 | $setting = wp_parse_args( $setting, $this->setting_defaults() ); |
||||||
381 | $setting['value'] = wpinv_get_option( $setting['id'], $setting['std'] ); |
||||||
382 | return $this->filter_setting( $setting ); |
||||||
383 | |||||||
384 | } |
||||||
385 | |||||||
386 | /** |
||||||
387 | * Get setting data. |
||||||
388 | * |
||||||
389 | * @since 2.0.0 |
||||||
390 | * @param string $setting_id Setting ID. |
||||||
391 | * @return array|WP_Error |
||||||
392 | */ |
||||||
393 | public function get_setting( $setting_id ) { |
||||||
394 | |||||||
395 | if ( empty( $setting_id ) ) { |
||||||
396 | return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'invoicing' ), array( 'status' => 404 ) ); |
||||||
397 | } |
||||||
398 | |||||||
399 | $settings = $this->get_settings(); |
||||||
400 | |||||||
401 | foreach ( $settings as $tabs ) { |
||||||
402 | |||||||
403 | foreach ( $tabs as $sections ) { |
||||||
404 | |||||||
405 | if ( isset( $sections[ $setting_id ] ) ) { |
||||||
406 | if ( ! $this->is_setting_type_valid( $sections[ $setting_id ]['type'] ) ) { |
||||||
407 | return new WP_Error( 'rest_setting_setting_type_invalid', __( 'Invalid setting type.', 'invoicing' ), array( 'status' => 404 ) ); |
||||||
408 | } |
||||||
409 | |||||||
410 | return $sections[ $setting_id ]; |
||||||
411 | } |
||||||
412 | } |
||||||
413 | } |
||||||
414 | |||||||
415 | return new WP_Error( 'rest_setting_setting_invalid', __( 'Invalid setting.', 'invoicing' ), array( 'status' => 404 ) ); |
||||||
416 | } |
||||||
417 | |||||||
418 | /** |
||||||
419 | * Get all tabs. |
||||||
420 | * |
||||||
421 | * @param WP_REST_Request $request Request data. |
||||||
422 | * @return array |
||||||
423 | */ |
||||||
424 | public function get_tabs( $request ) { |
||||||
425 | $tabs = wpinv_get_settings_tabs(); |
||||||
426 | $prepared = array(); |
||||||
427 | |||||||
428 | foreach ( $tabs as $id => $tab ) { |
||||||
429 | |||||||
430 | $_request = $request; |
||||||
431 | $_request['tab'] = sanitize_title( $id ); |
||||||
432 | $data = array( |
||||||
433 | 'id' => sanitize_title( $id ), |
||||||
434 | 'label' => sanitize_text_field( $tab ), |
||||||
435 | 'sections' => $this->get_sections( $_request ), |
||||||
436 | ); |
||||||
437 | |||||||
438 | $data = $this->add_additional_fields_to_object( $data, $request ); |
||||||
439 | $response = rest_ensure_response( $data ); |
||||||
440 | |||||||
441 | if ( ! is_wp_error( $response ) ) { |
||||||
442 | $links = array( |
||||||
443 | 'sections' => array( |
||||||
444 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $id ) ), |
||||||
445 | ), |
||||||
446 | 'collection' => array( |
||||||
447 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), |
||||||
448 | ), |
||||||
449 | ); |
||||||
450 | $response->add_links( $links ); |
||||||
451 | $response = $this->prepare_response_for_collection( $response ); |
||||||
452 | } |
||||||
453 | |||||||
454 | $prepared[] = $response; |
||||||
455 | |||||||
456 | } |
||||||
457 | |||||||
458 | return rest_ensure_response( $prepared ); |
||||||
0 ignored issues
–
show
|
|||||||
459 | } |
||||||
460 | |||||||
461 | /** |
||||||
462 | * Get all sections. |
||||||
463 | * |
||||||
464 | * @param WP_REST_Request $request Request data. |
||||||
465 | * @return array |
||||||
466 | */ |
||||||
467 | public function get_sections( $request ) { |
||||||
468 | |||||||
469 | $tab = sanitize_title( $request['tab'] ); |
||||||
470 | $sections = wpinv_get_settings_tab_sections( $tab ); |
||||||
471 | $prepared = array(); |
||||||
472 | |||||||
473 | foreach ( $sections as $id => $section ) { |
||||||
474 | |||||||
475 | $data = array( |
||||||
476 | 'id' => sanitize_title( $id ), |
||||||
477 | 'label' => sanitize_text_field( $section ), |
||||||
478 | ); |
||||||
479 | |||||||
480 | $data = $this->add_additional_fields_to_object( $data, $request ); |
||||||
481 | $response = rest_ensure_response( $data ); |
||||||
482 | |||||||
483 | if ( ! is_wp_error( $response ) ) { |
||||||
484 | $links = array( |
||||||
485 | 'settings' => array( |
||||||
486 | 'href' => rest_url( sprintf( '/%s/%s/%s/%s', $this->namespace, $this->rest_base, $tab, $id ) ), |
||||||
487 | ), |
||||||
488 | 'collection' => array( |
||||||
489 | 'href' => rest_url( sprintf( '/%s/%s/%s', $this->namespace, $this->rest_base, $tab ) ), |
||||||
490 | ), |
||||||
491 | 'tabs' => array( |
||||||
492 | 'href' => rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ), |
||||||
493 | ), |
||||||
494 | ); |
||||||
495 | $response->add_links( $links ); |
||||||
496 | $response = $this->prepare_response_for_collection( $response ); |
||||||
497 | } |
||||||
498 | |||||||
499 | $prepared[] = $response; |
||||||
500 | |||||||
501 | } |
||||||
502 | |||||||
503 | return rest_ensure_response( $prepared ); |
||||||
0 ignored issues
–
show
|
|||||||
504 | } |
||||||
505 | |||||||
506 | /** |
||||||
507 | * Get all settings. |
||||||
508 | * |
||||||
509 | * @return array |
||||||
510 | */ |
||||||
511 | public function get_settings() { |
||||||
512 | |||||||
513 | if ( empty( $this->settings ) ) { |
||||||
514 | $this->settings = wpinv_get_registered_settings(); |
||||||
0 ignored issues
–
show
It seems like
wpinv_get_registered_settings() of type array is incompatible with the declared type string of property $settings .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||||
515 | } |
||||||
516 | |||||||
517 | return $this->settings; |
||||||
0 ignored issues
–
show
|
|||||||
518 | |||||||
519 | } |
||||||
520 | |||||||
521 | /** |
||||||
522 | * Boolean for if a setting type is a valid supported setting type. |
||||||
523 | * |
||||||
524 | * @since 2.0.0 |
||||||
525 | * @param string $type Type. |
||||||
526 | * @return bool |
||||||
527 | */ |
||||||
528 | public function is_setting_type_valid( $type ) { |
||||||
529 | |||||||
530 | return in_array( |
||||||
531 | $type, |
||||||
532 | array( |
||||||
533 | 'text', // Validates with validate_setting_text_field. |
||||||
534 | 'email', // Validates with validate_setting_text_field. |
||||||
535 | 'number', // Validates with validate_setting_text_field. |
||||||
536 | 'color', // Validates with validate_setting_text_field. |
||||||
537 | 'password', // Validates with validate_setting_text_field. |
||||||
538 | 'textarea', // Validates with validate_setting_textarea_field. |
||||||
539 | 'select', // Validates with validate_setting_select_field. |
||||||
540 | 'multiselect', // Validates with validate_setting_multiselect_field. |
||||||
541 | 'radio', // Validates with validate_setting_radio_field (-> validate_setting_select_field). |
||||||
542 | 'checkbox', // Validates with validate_setting_checkbox_field. |
||||||
543 | 'header', // Validates with validate_setting_text_field. |
||||||
544 | ) |
||||||
545 | ); |
||||||
546 | |||||||
547 | } |
||||||
548 | |||||||
549 | /** |
||||||
550 | * Get the settings schema, conforming to JSON Schema. |
||||||
551 | * |
||||||
552 | * @return array |
||||||
553 | */ |
||||||
554 | public function get_item_schema() { |
||||||
555 | |||||||
556 | // Maybe retrieve the schema from cache. |
||||||
557 | if ( ! empty( $this->schema ) ) { |
||||||
558 | return $this->add_additional_fields_schema( $this->schema ); |
||||||
559 | } |
||||||
560 | |||||||
561 | $schema = array( |
||||||
562 | '$schema' => 'http://json-schema.org/draft-04/schema#', |
||||||
563 | 'title' => 'setting', |
||||||
564 | 'type' => 'object', |
||||||
565 | 'properties' => array( |
||||||
566 | 'id' => array( |
||||||
567 | 'description' => __( 'A unique identifier for the setting.', 'invoicing' ), |
||||||
568 | 'type' => 'string', |
||||||
569 | 'arg_options' => array( |
||||||
570 | 'sanitize_callback' => 'sanitize_title', |
||||||
571 | ), |
||||||
572 | 'context' => array( 'view', 'edit' ), |
||||||
573 | 'readonly' => true, |
||||||
574 | ), |
||||||
575 | 'tab' => array( |
||||||
576 | 'description' => __( 'An identifier for the tab this setting belongs to.', 'invoicing' ), |
||||||
577 | 'type' => 'string', |
||||||
578 | 'arg_options' => array( |
||||||
579 | 'sanitize_callback' => 'sanitize_title', |
||||||
580 | ), |
||||||
581 | 'context' => array( 'view', 'edit' ), |
||||||
582 | 'readonly' => true, |
||||||
583 | ), |
||||||
584 | 'section' => array( |
||||||
585 | 'description' => __( 'An identifier for the section this setting belongs to.', 'invoicing' ), |
||||||
586 | 'type' => 'string', |
||||||
587 | 'arg_options' => array( |
||||||
588 | 'sanitize_callback' => 'sanitize_title', |
||||||
589 | ), |
||||||
590 | 'context' => array( 'view', 'edit' ), |
||||||
591 | 'readonly' => true, |
||||||
592 | ), |
||||||
593 | 'name' => array( |
||||||
594 | 'description' => __( 'A human readable label for the setting used in interfaces.', 'invoicing' ), |
||||||
595 | 'type' => 'string', |
||||||
596 | 'arg_options' => array( |
||||||
597 | 'sanitize_callback' => 'sanitize_text_field', |
||||||
598 | ), |
||||||
599 | 'context' => array( 'view', 'edit' ), |
||||||
600 | 'readonly' => true, |
||||||
601 | ), |
||||||
602 | 'desc' => array( |
||||||
603 | 'description' => __( 'A human readable description for the setting used in interfaces.', 'invoicing' ), |
||||||
604 | 'type' => 'string', |
||||||
605 | 'context' => array( 'view', 'edit' ), |
||||||
606 | 'readonly' => true, |
||||||
607 | ), |
||||||
608 | 'value' => array( |
||||||
609 | 'description' => __( 'The current value of this setting.', 'invoicing' ), |
||||||
610 | 'type' => 'mixed', |
||||||
611 | 'context' => array( 'view', 'edit' ), |
||||||
612 | ), |
||||||
613 | 'default' => array( |
||||||
614 | 'description' => __( 'Default value for the setting.', 'invoicing' ), |
||||||
615 | 'type' => 'mixed', |
||||||
616 | 'context' => array( 'view', 'edit' ), |
||||||
617 | 'readonly' => true, |
||||||
618 | ), |
||||||
619 | 'placeholder' => array( |
||||||
620 | 'description' => __( 'Placeholder text to be displayed in text inputs.', 'invoicing' ), |
||||||
621 | 'type' => 'string', |
||||||
622 | 'arg_options' => array( |
||||||
623 | 'sanitize_callback' => 'sanitize_text_field', |
||||||
624 | ), |
||||||
625 | 'context' => array( 'view', 'edit' ), |
||||||
626 | 'readonly' => true, |
||||||
627 | ), |
||||||
628 | 'type' => array( |
||||||
629 | 'description' => __( 'Type of setting.', 'invoicing' ), |
||||||
630 | 'type' => 'string', |
||||||
631 | 'arg_options' => array( |
||||||
632 | 'sanitize_callback' => 'sanitize_text_field', |
||||||
633 | ), |
||||||
634 | 'context' => array( 'view', 'edit' ), |
||||||
635 | 'enum' => array( 'text', 'email', 'number', 'color', 'password', 'textarea', 'select', 'multiselect', 'radio', 'image_width', 'checkbox', 'raw_html' ), |
||||||
636 | 'readonly' => true, |
||||||
637 | ), |
||||||
638 | 'options' => array( |
||||||
639 | 'description' => __( 'Array of options (key value pairs) for inputs such as select, multiselect, and radio buttons.', 'invoicing' ), |
||||||
640 | 'type' => 'object', |
||||||
641 | 'context' => array( 'view', 'edit' ), |
||||||
642 | 'readonly' => true, |
||||||
643 | ), |
||||||
644 | 'readonly' => array( |
||||||
645 | 'description' => __( 'Whether or not this setting is readonly', 'invoicing' ), |
||||||
646 | 'type' => 'string', |
||||||
647 | 'context' => array( 'view' ), |
||||||
648 | 'readonly' => true, |
||||||
649 | ), |
||||||
650 | 'faux' => array( |
||||||
651 | 'description' => __( 'Whether or not this setting is readonly/faux', 'invoicing' ), |
||||||
652 | 'type' => 'string', |
||||||
653 | 'context' => array( 'view' ), |
||||||
654 | 'readonly' => true, |
||||||
655 | ), |
||||||
656 | ), |
||||||
657 | ); |
||||||
658 | |||||||
659 | // Filters the settings schema for the REST API. |
||||||
660 | $schema = apply_filters( 'getpaid_rest_settings_schema', $schema ); |
||||||
661 | |||||||
662 | // Cache the settings schema. |
||||||
663 | $this->schema = $schema; |
||||||
664 | |||||||
665 | return $this->add_additional_fields_schema( $this->schema ); |
||||||
666 | |||||||
667 | } |
||||||
668 | |||||||
669 | /** |
||||||
670 | * Validate a text value for a text based setting. |
||||||
671 | * |
||||||
672 | * @since 2.0.0 |
||||||
673 | * @param string $value Value. |
||||||
674 | * @param array $setting Setting. |
||||||
675 | * @return string |
||||||
676 | */ |
||||||
677 | public function validate_setting_text_field( $value ) { |
||||||
678 | $value = is_null( $value ) ? '' : $value; |
||||||
0 ignored issues
–
show
|
|||||||
679 | return wp_kses_post( trim( stripslashes( $value ) ) ); |
||||||
680 | } |
||||||
681 | |||||||
682 | /** |
||||||
683 | * Validate select based settings. |
||||||
684 | * |
||||||
685 | * @since 2.0.0 |
||||||
686 | * @param string $value Value. |
||||||
687 | * @param array $setting Setting. |
||||||
688 | * @return string|WP_Error |
||||||
689 | */ |
||||||
690 | public function validate_setting_select_field( $value, $setting ) { |
||||||
691 | if ( array_key_exists( $value, $setting['options'] ) ) { |
||||||
692 | return $value; |
||||||
693 | } else { |
||||||
694 | return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'invoicing' ), array( 'status' => 400 ) ); |
||||||
695 | } |
||||||
696 | } |
||||||
697 | |||||||
698 | /** |
||||||
699 | * Validate multiselect based settings. |
||||||
700 | * |
||||||
701 | * @since 2.0.0 |
||||||
702 | * @param array $values Values. |
||||||
703 | * @param array $setting Setting. |
||||||
704 | * @return array|WP_Error |
||||||
705 | */ |
||||||
706 | public function validate_setting_multiselect_field( $values, $setting ) { |
||||||
707 | if ( empty( $values ) ) { |
||||||
708 | return array(); |
||||||
709 | } |
||||||
710 | |||||||
711 | if ( ! is_array( $values ) ) { |
||||||
0 ignored issues
–
show
|
|||||||
712 | return new WP_Error( 'rest_setting_value_invalid', __( 'An invalid setting value was passed.', 'invoicing' ), array( 'status' => 400 ) ); |
||||||
713 | } |
||||||
714 | |||||||
715 | $final_values = array(); |
||||||
716 | foreach ( $values as $value ) { |
||||||
717 | if ( array_key_exists( $value, $setting['options'] ) ) { |
||||||
718 | $final_values[] = $value; |
||||||
719 | } |
||||||
720 | } |
||||||
721 | |||||||
722 | return $final_values; |
||||||
723 | } |
||||||
724 | |||||||
725 | /** |
||||||
726 | * Validate radio based settings. |
||||||
727 | * |
||||||
728 | * @since 2.0.0 |
||||||
729 | * @param string $value Value. |
||||||
730 | * @param array $setting Setting. |
||||||
731 | * @return string|WP_Error |
||||||
732 | */ |
||||||
733 | public function validate_setting_radio_field( $value, $setting ) { |
||||||
734 | return $this->validate_setting_select_field( $value, $setting ); |
||||||
735 | } |
||||||
736 | |||||||
737 | /** |
||||||
738 | * Validate checkbox based settings. |
||||||
739 | * |
||||||
740 | * @since 2.0.0 |
||||||
741 | * @param string $value Value. |
||||||
742 | * @return int |
||||||
743 | */ |
||||||
744 | public function validate_setting_checkbox_field( $value ) { |
||||||
745 | return (int) ! empty( $value ); |
||||||
746 | } |
||||||
747 | |||||||
748 | /** |
||||||
749 | * Validate textarea based settings. |
||||||
750 | * |
||||||
751 | * @since 2.0.0 |
||||||
752 | * @param string $value Value. |
||||||
753 | * @return string |
||||||
754 | */ |
||||||
755 | public function validate_setting_textarea_field( $value ) { |
||||||
756 | $value = is_null( $value ) ? '' : $value; |
||||||
0 ignored issues
–
show
|
|||||||
757 | return wp_kses( |
||||||
758 | trim( stripslashes( $value ) ), |
||||||
759 | array_merge( |
||||||
760 | array( |
||||||
761 | 'iframe' => array( |
||||||
762 | 'src' => true, |
||||||
763 | 'style' => true, |
||||||
764 | 'id' => true, |
||||||
765 | 'class' => true, |
||||||
766 | ), |
||||||
767 | ), |
||||||
768 | wp_kses_allowed_html( 'post' ) |
||||||
769 | ) |
||||||
770 | ); |
||||||
771 | } |
||||||
772 | |||||||
773 | } |
||||||
774 |