PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.13
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.13
1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 1.7.0.9 All 211 releases
← All changes | includes/utilities/class-charitable-data-processor.php +212 -41 1.6.8 → 1.8.13 View file →
@@ -4,13 +4,13 @@
4 4 * and sanitizing and normalizing that data, depending on its data type and
5 5 * the type of data (text, checkbox, etc.).
6 6 *
7 7 * @package Charitable/Classes/Charitable_Data_Processor
8 - * @author Eric Daams
9 - * @copyright Copyright (c) 2019, Studio 164a
8 + * @author David Bisset
9 + * @copyright Copyright (c) 2023, WP Charitable LLC
10 10 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
11 11 * @since 1.5.9
12 - * @version 1.5.9
12 + * @version 1.6.55
13 13 */
14 14
15 15 // Exit if accessed directly.
16 16 if ( ! defined( 'ABSPATH' ) ) {
@@ -19,13 +19,18 @@
19 19
20 20
21 21 if ( ! class_exists( 'Charitable_Data_Processor' ) ) :
22 22
23 + /**
24 + * Data processor class.
25 + *
26 + * @since 1.5.9
27 + */
23 28 class Charitable_Data_Processor {
24 29 /**
25 30 * The raw input data.
26 31 *
27 - * @since 1.2.0
32 + * @since 1.5.9
28 33 *
29 34 * @var array
30 35 */
31 36 protected $data;
@@ -32,9 +37,9 @@
32 37
33 38 /**
34 39 * The map of fields.
35 40 *
36 - * @since 1.2.0
41 + * @since 1.5.9
37 42 *
38 43 * @var array
39 44 */
40 45 protected $fields;
@@ -39,13 +44,22 @@
39 44 */
40 45 protected $fields;
41 46
42 47 /**
48 + * An array of valid options for specific fields.
49 + *
50 + * @since 1.6.51
51 + *
52 + * @var array
53 + */
54 + protected $options;
55 +
56 + /**
43 57 * This is the output data. It has the same structure
44 58 * as the map of fields, but has the sanitized &
45 59 * normalized values from the input data.
46 60 *
47 - * @since 1.2.0
61 + * @since 1.5.9
48 62 *
49 63 * @var array
50 64 */
51 65 protected $output;
@@ -50,8 +64,17 @@
50 64 */
51 65 protected $output;
52 66
53 67 /**
68 + * Whether the data is invalid.
69 + *
70 + * @since 1.5.9
71 + *
72 + * @var boolean
73 + */
74 + protected $invalid;
75 +
76 + /**
54 77 * Instantiate the formatter with a dataset and array of fields.
55 78 *
56 79 * @since 1.5.9
57 80 *
@@ -57,11 +80,12 @@
57 80 *
58 81 * @param array $data The raw input data.
59 82 * @param array $fields The map of fields.
60 83 */
61 - public function __construct( $data, $fields ) {
84 + public function __construct( $data, $fields, $options = array() ) {
62 85 $this->data = $data;
63 86 $this->fields = $fields;
87 + $this->options = $options;
64 88 $this->output = array();
65 89 $this->invalid = false;
66 90
67 91 $this->process_data( $this->fields );
@@ -169,8 +193,9 @@
169 193 * @since 1.5.9
170 194 *
171 195 * @param array $functions Stack of functions, in order of priority, with $args
172 196 * passed as the value of the function.
197 + * @param mixed $default The default value to return if none of the functions exist.
173 198 * @return mixed|null
174 199 */
175 200 protected function apply_function_to_field( $functions, $default = '' ) {
176 201 foreach ( $functions as $function => $args ) {
@@ -193,39 +218,36 @@
193 218 * @return mixed|null The set value of the field, or NULL if the
194 219 * field was not contained in the data.
195 220 */
196 221 protected function process_field( $key, $type, $data_type = false ) {
222 + $sanitized_key = str_replace( '-', '_', $key );
223 + $sanitized_type = str_replace( '-', '_', $type );
224 + $sanitized_data_type = str_replace( '-', '_', $data_type );
225 + $field_options = isset( $this->options[ $key ] ) ? $this->options[ $key ] : null;
226 +
197 227 /* Retrieve the value. */
198 - $value = $this->apply_function_to_field( array(
199 - 'process_' . $key => array( $type, $data_type ),
200 - 'process_' . $data_type => array( $key, $type ),
201 - 'process_' . $type => array( $key, $data_type ),
202 - 'process_generic_field' => array( $key ),
203 - ) );
228 + $value = $this->apply_function_to_field(
229 + array(
230 + 'process_' . $sanitized_key => array( $type, $data_type ),
231 + 'process_' . $sanitized_data_type => array( $key, $type ),
232 + 'process_' . $sanitized_type => array( $key, $data_type ),
233 + 'process_generic_field' => array( $key ),
234 + )
235 + );
204 236
205 237 /* Return the value after it is sanitized. */
206 - return $this->apply_function_to_field( array(
207 - 'sanitize_' . $key => array( $value, $type, $data_type ),
208 - 'sanitize_' . $data_type => array( $value, $key, $type ),
209 - 'sanitize_' . $type => array( $value, $key, $data_type ),
210 - ), $value );
238 + return $this->apply_function_to_field(
239 + array(
240 + 'sanitize_' . $sanitized_key => array( $value, $type, $data_type, $field_options ),
241 + 'sanitize_' . $sanitized_data_type => array( $value, $key, $type, $field_options ),
242 + 'sanitize_' . $sanitized_type => array( $value, $key, $data_type, $field_options ),
243 + 'sanitize_generic_field' => array( $value, $key, $field_options ),
244 + ),
245 + $value
246 + );
211 247 }
212 248
213 249 /**
214 - * Process a generic field. i.e. One that hasn't been processed
215 - * by any of the other processors.
216 - *
217 - * @since 1.5.9
218 - *
219 - * @param string $key The field key.
220 - * @return mixed|null The set value of the field, or NULL if the
221 - * field was not contained in the data.
222 - */
223 - public function process_generic_field( $key ) {
224 - return array_key_exists( $key, $this->data ) ? $this->data[ $key ] : null;
225 - }
226 -
227 - /**
228 250 * Process a checkbox field.
229 251 *
230 252 * @since 1.5.9
231 253 *
@@ -241,9 +263,9 @@
241 263 * Process a picture field.
242 264 *
243 265 * @since 1.5.9
244 266 *
245 - * @param string $key
267 + * @param string $key The key of the picture field.
246 268 * @return int|false
247 269 */
248 270 protected function process_picture( $key ) {
249 271 $value = array_key_exists( $key, $this->data ) ? $this->data[ $key ] : '';
@@ -267,16 +289,30 @@
267 289 return $value;
268 290 }
269 291
270 292 /**
293 + * Process a generic field. i.e. One that hasn't been processed
294 + * by any of the other processors.
295 + *
296 + * @since 1.5.9
297 + *
298 + * @param string $key The field key.
299 + * @return mixed|null The set value of the field, or NULL if the
300 + * field was not contained in the data.
301 + */
302 + public function process_generic_field( $key ) {
303 + return isset( $this->data[ $key ] ) ? $this->data[ $key ] : null;
304 + }
305 +
306 + /**
271 307 * Sanitize a number.
272 308 *
273 309 * @since 1.5.9
274 310 *
275 - * @param string|int The number to be sanitized.
311 + * @param string|int $value The number to be sanitized.
276 312 * @return int
277 313 */
278 - protected function sanitize_number( $value ) {
314 + public static function sanitize_number( $value ) {
279 315 return intval( $value );
280 316 }
281 317
282 318 /**
@@ -281,23 +317,158 @@
281 317
282 318 /**
283 319 * Sanitize a value received from a datepicker.
284 320 *
285 - * @since 1.5.9
321 + * When decline_months is on, the JS datepicker sends yy-mm-dd (e.g. 2026-2-1).
322 + * We normalize to Y-m-d (e.g. 2026-02-01) so MySQL and PHP never interpret
323 + * the string as d-m-y (e.g. January 2 instead of February 1).
286 324 *
325 + * @since 1.5.9
326 + * @version 1.8.9.2
327 + *
287 328 * @param string $value The datepicker value.
288 329 * @return string|int If a date was chosen, returns the date in YYYY-MM-DD format.
289 330 * Otherwise, returns 0.
290 331 */
291 - protected function sanitize_datepicker( $value ) {
332 + public static function sanitize_datepicker( $value ) {
292 333 if ( empty( $value ) ) {
293 334 return 0;
294 335 }
295 336
296 - return charitable_sanitize_date( $value, 'Y-m-d' );
337 + if ( ! charitable()->registry()->get( 'i18n' )->decline_months() ) {
338 + $value = charitable_sanitize_date( $value, 'Y-m-d' );
339 + if ( false === $value ) {
340 + $value = 0;
341 + }
342 + } else {
343 + // Normalize to canonical Y-m-d so MySQL/PHP never interpret as d-m-y.
344 + $value = trim( $value );
345 + $dt = DateTime::createFromFormat( 'Y-m-d', $value );
346 + if ( ! $dt ) {
347 + $dt = DateTime::createFromFormat( 'Y-n-j', $value );
348 + }
349 + if ( $dt ) {
350 + $value = $dt->format( 'Y-m-d' );
351 + } else {
352 + $value = 0;
353 + }
354 + }
355 +
356 + return $value;
297 357 }
298 358
299 359 /**
360 + * Sanitize editor fields.
361 + *
362 + * @since 1.6.51
363 + *
364 + * @param mixed $value The submitted value.
365 + * @return string
366 + */
367 + public static function sanitize_editor( $value ) {
368 + return wp_kses_post( $value );
369 + }
370 +
371 + /**
372 + * Sanitize textarea.
373 + *
374 + * @since 1.6.51
375 + *
376 + * @param mixed $value The submitted value.
377 + * @return string
378 + */
379 + public static function sanitize_textarea( $value ) {
380 + return sanitize_textarea_field( $value );
381 + }
382 +
383 + /**
384 + * Sanitize submitted email.
385 + *
386 + * @since 1.6.51
387 + *
388 + * @param mixed $value The submitted value.
389 + * @return string
390 + */
391 + public static function sanitize_email( $value ) {
392 + return sanitize_email( $value );
393 + }
394 +
395 + /**
396 + * Escape a submitted url.
397 + *
398 + * @since 1.6.51
399 + *
400 + * @param mixed $value The submitted value.
401 + * @return string
402 + */
403 + public static function sanitize_url( $value ) {
404 + return esc_url_raw( $value );
405 + }
406 +
407 + /**
408 + * Fallback sanitization, using sanitize_text_field.
409 + *
410 + * @since 1.6.51
411 + *
412 + * @param mixed $value The submitted value.
413 + * @return string
414 + */
415 + public static function sanitize_text( $value ) {
416 + return sanitize_text_field( $value );
417 + }
418 +
419 + /**
420 + * Sanitize multi-checkbox fields.
421 + *
422 + * @since 1.6.51
423 + *
424 + * @param mixed $value The submitted value.
425 + * @param string $key The field key.
426 + * @param string $data_type The type of data.
427 + * @param null|array $options The options for the field.
428 + * @return string|array
429 + */
430 + public static function sanitize_multi_checkbox( $value, $key, $data_type, $options = null ) {
431 + /* Multi-checkbox should return an empty string or an array. */
432 + if ( ! is_array( $value ) ) {
433 + return '';
434 + }
435 +
436 + if ( is_null( $options ) ) {
437 + return $value;
438 + }
439 +
440 + /* Check against a specific set of options that are valid for this field. */
441 + foreach ( $value as $i => $option ) {
442 + /* If the selected option is not valid, remove it. */
443 + if ( ! in_array( $option, $options ) ) {
444 + unset( $value[ $i ] );
445 + }
446 + }
447 +
448 + return $value;
449 + }
450 +
451 + /**
452 + * Fallback sanitization.
453 + *
454 + * @since 1.6.51
455 + *
456 + * @param mixed $value The submitted value.
457 + * @param string $key The field key.
458 + * @param null|array $options The options for the field.
459 + * @return string
460 + */
461 + public static function sanitize_generic_field( $value, $key, $options = null ) {
462 + /* Check against a specific set of options that are valid for this field. */
463 + if ( is_array( $options ) ) {
464 + $value = in_array( $value, $options ) ? $value : '';
465 + }
466 +
467 + return $value;
468 + }
469 +
470 + /**
300 471 * Returns true if a file was found for the picture in the $_FILES array.
301 472 *
302 473 * @since 1.5.9
303 474 *
@@ -304,9 +475,9 @@
304 475 * @param string $key The picture file key.
305 476 * @return boolean
306 477 */
307 478 protected function picture_file_exists( $key ) {
308 - return isset( $_FILES ) && isset( $_FILES[ $key ] );
479 + return isset( $_FILES ) && isset( $_FILES[ $key ] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
309 480 }
310 481
311 482 /**
312 483 * Uploads a file and attaches it to the given post.
@@ -332,11 +503,11 @@
332 503 *
333 504 * @since 1.0.0
334 505 *
335 506 * @param string $file_key Reference to a single element of `$_FILES`. Call the
336 - * function once for each uploaded file.
507 + * function once for each uploaded file.
337 508 * @param array $overrides Optional. An associative array of names=>values to
338 - * override default variables. Default false.
509 + * override default variables. Default false.
339 510 * @return array
340 511 */
341 512 protected function get_file_overrides( $file_key, $overrides = array() ) {
342 513 $allowed_mimes = array(