PluginProbe
Booktics – Appointment Booking Calendar for Service Businesses / 1.0.27
Booktics – Appointment Booking Calendar for Service Businesses v1.0.27
1.0.29 1.0.28 1.0.27 1.0.26 1.0.25 1.0.24 1.0.23 1.0.22 1.0.21 1.0.20 1.0.19 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.2 1.0.3 All 31 releases
← All changes | base/abstracts/user-model.php +31 -10 1.0.3 → 1.0.27 View file →
@@ -6,8 +6,10 @@
6 6 */
7 7
8 8 namespace Booktics\Abstracts;
9 9
10 +if ( ! defined( 'ABSPATH' ) ) exit;
11 +
10 12 use JsonSerializable;
11 13 use WP_User_Query;
12 14
13 15 abstract class User_Model implements JsonSerializable {
@@ -301,17 +303,16 @@
301 303 * @return boolean
302 304 */
303 305 public function delete(): bool {
304 306 $user = get_userdata( $this->id );
305 -
307 +
306 308 if ( ! $user ) {
307 309 return false;
308 310 }
309 311
310 - if ( count( $user->roles ) == 1 && in_array( $this->role, $user->roles ) ) {
312 + if ( count( $user->roles ) == 1 && in_array( $this->role, $user->roles ) ) {
311 313 return wp_delete_user( $this->id );
312 314 }
313 -
314 315 $user->remove_role( $this->role );
315 316
316 317 return true;
317 318 }
@@ -415,8 +416,9 @@
415 416 $relation = 'OR';
416 417 }
417 418 }
418 419 if ( ! empty( $meta_query ) ) {
420 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Meta query is necessary for filtering users by meta fields
419 421 $args['meta_query'] = [
420 422 'relation' => $relation,
421 423 ...$meta_query
422 424 ];
@@ -539,17 +541,17 @@
539 541 }
540 542
541 543 $value = $this->$key ?? $this->fillable[ $key ];
542 544
543 - // Unserialize if necessary
545 + // Unserialize if necessary (object instantiation disallowed — see helper).
544 546 if ( is_string( $value ) && $this->is_serialized( $value ) ) {
545 - $value = maybe_unserialize( $value );
547 + $value = \booktics_safe_maybe_unserialize( $value );
546 548 }
547 549
548 550 // Normalize value to default type
549 551 if ( gettype( $value ) !== gettype( $default ) ) {
550 552 if ( gettype( $default ) === 'array' && is_string( $value ) && $this->is_serialized( $value ) ) {
551 - $value = maybe_unserialize( $value );
553 + $value = \booktics_safe_maybe_unserialize( $value );
552 554 } elseif ( gettype( $default ) === 'array' ) {
553 555 $value = $default;
554 556 }
555 557 }
@@ -554,9 +556,9 @@
554 556 }
555 557 }
556 558
557 559 // Cast specific keys to objects
558 - if ( $key == 'schedule' ) {
560 + if ( 'schedule' == $key ) {
559 561 $value = (object) $value;
560 562 }
561 563
562 564 // Cast specific keys to boolean
@@ -561,14 +563,15 @@
561 563
562 564 // Cast specific keys to boolean
563 565 if ( in_array( $key, [
564 566 'enable_custom_schedule',
565 - 'enable_custom_holiday'
567 + 'enable_custom_holiday',
568 + 'enable_custom_availability',
566 569 ] ) ) {
567 570 $value = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
568 571 }
569 572
570 - if ( $key == 'user_registered' ) {
573 + if ( 'user_registered' == $key ) {
571 574 $value = $default;
572 575 }
573 576
574 577 $data[ $key ] = $value ?? $default;
@@ -586,9 +589,11 @@
586 589 *
587 590 * @return bool True if data is serialized, false otherwise
588 591 */
589 592 function is_serialized( $data ) {
590 - return is_string( $data ) && @unserialize( $data ) !== false;
593 + // Structural check only (WordPress core) — never calls unserialize(), so it
594 + // cannot trigger PHP Object Injection on attacker-controlled user meta.
595 + return is_string( $data ) && \is_serialized( $data );
591 596 }
592 597
593 598 /**
594 599 * Specify data which should be serialized to JSON.
@@ -596,6 +601,22 @@
596 601 * @return array
597 602 */
598 603 public function jsonSerialize(): array {
599 604 return $this->to_array();
605 + }
606 +
607 + /**
608 + * Get the first user matching the current filters.
609 + *
610 + * @param array $args
611 + * @return self|null
612 + */
613 + public function first(array $args = []): ?self {
614 + $args['number'] = 1;
615 + $args['paged'] = 1;
616 + $result = $this->all($args);
617 + if (!empty($result['items'][0])) {
618 + return $this->hydrate($result['items'][0]['ID'], $result['items'][0]);
619 + }
620 + return null;
600 621 }
601 622 }