PluginProbe
Booking Calendar / 11.8
Booking Calendar v11.8
11.9 11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 All 205 releases
booking / includes / booking_modes_v3 / class-wpbc-booking-modes-v3-context.php

class-wpbc-booking-modes-v3-context.php in Booking Calendar 11.8, at includes/booking_modes_v3/class-wpbc-booking-modes-v3-context.php

139 lines 4.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Request and owner context for Booking Modes V3.
4 *
5 * @package Booking Calendar
6 * @since 11.8.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Resolve immutable request context once without performing navigation work.
15 */
16 final class WPBC_Booking_Modes_V3_Context {
17
18 /** @var WPBC_Booking_Modes_V3_Context|null */
19 private static $instance = null;
20
21 /** @var array<string,mixed>|null */
22 private $context = null;
23
24 /** @var int */
25 private $build_count = 0;
26
27 /**
28 * Prevent direct construction.
29 */
30 private function __construct() {}
31
32 /**
33 * Return the shared request instance.
34 *
35 * @return WPBC_Booking_Modes_V3_Context Context instance.
36 */
37 public static function get_instance() {
38 if ( null === self::$instance ) {
39 self::$instance = new self();
40 }
41
42 return self::$instance;
43 }
44
45 /**
46 * Return normalized request, actor, owner, and multisite context.
47 *
48 * @return array<string,mixed> Cached context values.
49 */
50 public function get_context() {
51 if ( null !== $this->context ) {
52 return $this->context;
53 }
54
55 ++$this->build_count;
56 $real_user_id = get_current_user_id();
57 $owner_user_id = function_exists( 'wpbc_get_current_user_id' ) ? absint( wpbc_get_current_user_id() ) : absint( $real_user_id );
58 $is_multiuser = class_exists( 'wpdev_bk_multiuser' );
59 $is_ajax = function_exists( 'wp_doing_ajax' ) ? wp_doing_ajax() : ( defined( 'DOING_AJAX' ) && DOING_AJAX );
60 $page = $this->get_request_key( 'page' );
61 $context = array(
62 'feature_enabled' => true,
63 'is_admin' => is_admin(),
64 'is_ajax' => (bool) $is_ajax,
65 'is_wpbc_page' => 0 === strpos( $page, 'wpbc' ),
66 'page' => $page,
67 'tab' => $this->get_request_key( 'tab' ),
68 'subtab' => $this->get_request_key( 'subtab' ),
69 'real_user_id' => absint( $real_user_id ),
70 'owner_user_id' => $owner_user_id,
71 'site_id' => function_exists( 'get_current_blog_id' ) ? absint( get_current_blog_id() ) : 0,
72 'is_multiuser' => $is_multiuser,
73 'is_simulated_login' => $is_multiuser && $owner_user_id > 0 && $owner_user_id !== absint( $real_user_id ),
74 'is_real_booking_super_admin' => $is_multiuser ? (bool) apply_bk_filter( 'is_user_super_admin', $real_user_id ) : current_user_can( 'activate_plugins' ),
75 'is_owner_booking_super_admin' => $is_multiuser ? (bool) apply_bk_filter( 'is_user_super_admin', $owner_user_id ) : current_user_can( 'activate_plugins' ),
76 );
77
78 /**
79 * Filter the cached Booking Modes request and owner context.
80 *
81 * This released hook remains presentation-only and cannot grant access.
82 *
83 * @param array $context Normalized V3 request context.
84 */
85 $filtered_context = apply_filters( 'wpbc_booking_modes_context', $context );
86 $this->context = $this->normalize_context( $filtered_context, $context );
87
88 return $this->context;
89 }
90
91 /**
92 * Return the number of request-context builds.
93 *
94 * @return int Build count.
95 */
96 public function get_build_count() {
97 return $this->build_count;
98 }
99
100 /**
101 * Read a scalar presentation request key.
102 *
103 * @param string $request_key Request parameter name.
104 *
105 * @return string Sanitized request value.
106 */
107 private function get_request_key( $request_key ) {
108 if ( ! isset( $_REQUEST[ $request_key ] ) || ! is_scalar( $_REQUEST[ $request_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
109 return '';
110 }
111
112 return sanitize_key( wp_unslash( $_REQUEST[ $request_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
113 }
114
115 /**
116 * Normalize a filtered context while retaining extension metadata.
117 *
118 * @param mixed $filtered_context Filter result.
119 * @param array $default_context Source-confirmed defaults.
120 *
121 * @return array<string,mixed> Safe context.
122 */
123 private function normalize_context( $filtered_context, $default_context ) {
124 $context = is_array( $filtered_context ) ? wp_parse_args( $filtered_context, $default_context ) : $default_context;
125
126 foreach ( array( 'page', 'tab', 'subtab' ) as $key ) {
127 $context[ $key ] = is_scalar( $context[ $key ] ) ? sanitize_key( (string) $context[ $key ] ) : '';
128 }
129 foreach ( array( 'real_user_id', 'owner_user_id', 'site_id' ) as $key ) {
130 $context[ $key ] = is_scalar( $context[ $key ] ) ? absint( $context[ $key ] ) : 0;
131 }
132 foreach ( array( 'feature_enabled', 'is_admin', 'is_ajax', 'is_wpbc_page', 'is_multiuser', 'is_simulated_login', 'is_real_booking_super_admin', 'is_owner_booking_super_admin' ) as $key ) {
133 $context[ $key ] = (bool) $context[ $key ];
134 }
135
136 return $context;
137 }
138 }
139