PluginProbe
Booking Calendar / 11.9
Booking Calendar v11.9
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 / page-setup-wizard / setup-overview / class-wpbc-setup-wizard-setup-overview-actions.php

class-wpbc-setup-wizard-setup-overview-actions.php in Booking Calendar 11.9, at includes/page-setup-wizard/setup-overview/class-wpbc-setup-wizard-setup-overview-actions.php

175 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * State-changing actions launched from the completed Setup overview.
4 *
5 * @package Booking Calendar
6 */
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit;
10 }
11
12 /**
13 * Handle nonce-protected wizard reopening and restart operations.
14 */
15 final class WPBC_Setup_Wizard_Setup_Overview_Actions {
16
17 /** Authenticated WordPress action used to reopen an allow-listed wizard step. */
18 const ACTION_REOPEN_STEP = 'wpbc_setup_wizard_overview_reopen_step';
19
20 /** Authenticated WordPress action used to restart wizard navigation. */
21 const ACTION_RESTART = 'wpbc_setup_wizard_overview_restart';
22
23 /** Shared nonce action for completed-overview mutations. */
24 const NONCE_ACTION = 'wpbc_setup_wizard_overview_action';
25
26 /** Request field carrying the completed-overview nonce. */
27 const NONCE_NAME = 'wpbc_setup_wizard_overview_nonce';
28
29 /**
30 * Register authenticated WordPress action endpoints.
31 *
32 * @return void
33 */
34 public static function register() {
35 add_action( 'admin_post_' . self::ACTION_REOPEN_STEP, array( __CLASS__, 'reopen_step' ) );
36 add_action( 'admin_post_' . self::ACTION_RESTART, array( __CLASS__, 'restart' ) );
37 }
38
39 /**
40 * Reopen one explicitly allow-listed earlier step from a completed overview.
41 *
42 * @return void
43 */
44 public static function reopen_step() {
45 self::authorize_request();
46
47 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by authorize_request().
48 $target_step_id = isset( $_POST['target_step_id'] ) && is_scalar( $_POST['target_step_id'] ) ? sanitize_key( wp_unslash( $_POST['target_step_id'] ) ) : '';
49 $allowed_steps = array( 'customer_journey' );
50 if ( ! in_array( $target_step_id, $allowed_steps, true ) ) {
51 self::redirect_with_notice( 'error' );
52 }
53
54 $draft_store = self::create_draft_store();
55 $checkpoint = $draft_store->load();
56 if ( 'completed' !== $checkpoint['status'] ) {
57 self::redirect_to_setup_page();
58 }
59
60 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by authorize_request().
61 $expected_revision = isset( $_POST['expected_revision'] ) && is_scalar( $_POST['expected_revision'] ) ? absint( wp_unslash( $_POST['expected_revision'] ) ) : -1;
62 $result = $draft_store->navigate_to_step( $target_step_id, $checkpoint['current_step'], $expected_revision );
63 if ( is_wp_error( $result ) ) {
64 self::redirect_with_notice( self::is_stale_error( $result ) ? 'stale' : 'error' );
65 }
66
67 self::redirect_to_setup_page();
68 }
69
70 /**
71 * Start a fresh wizard navigation pass without rolling back live settings.
72 *
73 * @return void
74 */
75 public static function restart() {
76 self::authorize_request();
77
78 $draft_store = self::create_draft_store();
79 $checkpoint = $draft_store->load();
80 if ( 'completed' !== $checkpoint['status'] ) {
81 self::redirect_to_setup_page();
82 }
83
84 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified by authorize_request().
85 $expected_revision = isset( $_POST['expected_revision'] ) && is_scalar( $_POST['expected_revision'] ) ? absint( wp_unslash( $_POST['expected_revision'] ) ) : -1;
86 $result = $draft_store->restart( $expected_revision );
87 if ( is_wp_error( $result ) ) {
88 self::redirect_with_notice( self::is_stale_error( $result ) ? 'stale' : 'error' );
89 }
90
91 self::redirect_to_setup_page();
92 }
93
94 /**
95 * Enforce login capability and the shared overview nonce.
96 *
97 * @return void
98 */
99 private static function authorize_request() {
100 if ( ! WPBC_Setup_Wizard_Access::current_user_can_access() ) {
101 wp_die(
102 esc_html__( 'You are not allowed to change this Setup Wizard.', 'booking' ),
103 esc_html__( 'Access denied', 'booking' ),
104 array( 'response' => 403 )
105 );
106 }
107
108 $request_method = isset( $_SERVER['REQUEST_METHOD'] ) && is_scalar( $_SERVER['REQUEST_METHOD'] )
109 ? strtoupper( sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) )
110 : '';
111 if ( 'POST' !== $request_method ) {
112 wp_die(
113 esc_html__( 'This Setup Wizard action requires a form submission.', 'booking' ),
114 esc_html__( 'Invalid request method', 'booking' ),
115 array( 'response' => 405 )
116 );
117 }
118
119 check_admin_referer( self::NONCE_ACTION, self::NONCE_NAME );
120 }
121
122 /**
123 * Create the owner/site-scoped checkpoint store used by overview actions.
124 *
125 * @return WPBC_Setup_Wizard_Draft_Store Checkpoint store.
126 */
127 private static function create_draft_store() {
128 $module_registry = new WPBC_Setup_Wizard_Step_Module_Registry();
129 $step_registry = new WPBC_Setup_Wizard_Step_Registry( $module_registry );
130 $step_data = new WPBC_Setup_Wizard_Step_Data( $module_registry );
131
132 return new WPBC_Setup_Wizard_Draft_Store( $step_registry, new WPBC_Setup_Wizard_Draft_Validator( $step_data ) );
133 }
134
135 /**
136 * Determine whether an operation failed because the client checkpoint was stale.
137 *
138 * @param WP_Error $error Setup Wizard operation error.
139 *
140 * @return bool True for a stale revision or stale step error.
141 */
142 private static function is_stale_error( WP_Error $error ) {
143 return 0 === strpos( (string) $error->get_error_code(), 'wpbc_setup_wizard_stale_' );
144 }
145
146 /**
147 * Redirect to the canonical Setup Wizard menu URL and stop execution.
148 *
149 * @return void
150 */
151 private static function redirect_to_setup_page() {
152 wp_safe_redirect( wpbc_get_setup_wizard_page_url() );
153 exit;
154 }
155
156 /**
157 * Redirect a bounded error code to the completed overview.
158 *
159 * @param string $notice_code Allow-listed presentation notice code.
160 *
161 * @return void
162 */
163 private static function redirect_with_notice( $notice_code ) {
164 $notice_code = in_array( $notice_code, array( 'stale', 'error' ), true ) ? $notice_code : 'error';
165 wp_safe_redirect(
166 add_query_arg(
167 'wpbc_setup_overview_notice',
168 $notice_code,
169 wpbc_get_setup_wizard_page_url()
170 )
171 );
172 exit;
173 }
174 }
175