PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
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 10.11 All 204 releases
booking / includes / booking_modes_v3 / booking_modes-navigation.php

booking_modes-navigation.php in Booking Calendar 11.8.4, at includes/booking_modes_v3/booking_modes-navigation.php

329 lines 11.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Focused Booking Modes V3 integration adapters.
4 *
5 * @package Booking Calendar
6 * @since 11.8.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Return the selected validated V3 definition with a safe Classic fallback.
15 *
16 * @return array<string,mixed> Selected definition.
17 */
18 function wpbc_booking_modes_v3_get_selected_definition() {
19 $registry = WPBC_Booking_Modes_V3_Compatibility_Registry::get_instance();
20 $definition = $registry->get_compiler_definition( wpbc_booking_modes_get_selected_mode_id() );
21
22 return is_array( $definition ) ? $definition : $registry->get_compiler_definition( 'classic' );
23 }
24
25 /**
26 * Capture original contributor metadata at the shared getter boundary.
27 *
28 * @param array $source_navigation Complete original navigation tree.
29 *
30 * @return array Unmodified source tree for callers that do not render a V3 surface.
31 */
32 function wpbc_booking_modes_v3_capture_navigation_source( $source_navigation ) {
33 WPBC_Booking_Modes_V3_Source_Index::get_instance()->capture( $source_navigation );
34
35 return $source_navigation;
36 }
37
38 /**
39 * Compile only the sidebar tree requested by the vertical renderer.
40 *
41 * @param array $source_navigation Complete original navigation tree.
42 *
43 * @return array Legacy-compatible V3 sidebar tree.
44 */
45 function wpbc_booking_modes_v3_compile_sidebar_navigation( $source_navigation ) {
46 WPBC_Booking_Modes_V3_Source_Index::get_instance()->capture( $source_navigation );
47 $definition = wpbc_booking_modes_v3_get_selected_definition();
48
49 return WPBC_Booking_Modes_V3_Compiler::get_instance()->compile_sidebar(
50 $source_navigation,
51 $definition,
52 WPBC_Booking_Modes_V3_Compiler::get_current_edition_id()
53 );
54 }
55
56 /**
57 * Compile root section metadata for the current V3 sidebar.
58 *
59 * @param array $legacy_roots Legacy root metadata.
60 * @param array $sidebar Already compiled sidebar tree.
61 *
62 * @return array V3 root metadata.
63 */
64 function wpbc_booking_modes_v3_compile_root_navigation( $legacy_roots, $sidebar ) {
65 return WPBC_Booking_Modes_V3_Compiler::get_instance()->compile_roots(
66 $legacy_roots,
67 $sidebar,
68 wpbc_booking_modes_v3_get_selected_definition()
69 );
70 }
71
72 /**
73 * Compile only the horizontal host currently being rendered.
74 *
75 * @param array $source_navigation Source navigation tree.
76 * @param string $active_page Current page slug.
77 * @param string $active_tab Current tab slug.
78 * @param string $active_subtab Current subtab slug.
79 *
80 * @return array Navigation tree with the current horizontal host prepared.
81 */
82 function wpbc_booking_modes_v3_compile_horizontal_navigation( $source_navigation, $active_page, $active_tab, $active_subtab ) {
83 WPBC_Booking_Modes_V3_Source_Index::get_instance()->capture( $source_navigation );
84
85 return WPBC_Booking_Modes_V3_Compiler::get_instance()->compile_horizontal(
86 $source_navigation,
87 wpbc_booking_modes_v3_get_selected_definition(),
88 WPBC_Booking_Modes_V3_Compiler::get_current_edition_id(),
89 $active_page,
90 $active_tab,
91 $active_subtab
92 );
93 }
94
95 /**
96 * Apply V3 page-heading and top-navigation options to the active controller.
97 *
98 * @param array $current_page_params Original controller presentation data.
99 * @param string $page_slug Current registered page slug.
100 * @param string $tab_slug Current registered tab slug.
101 * @param string $subtab_slug Current registered subtab slug.
102 *
103 * @return array Updated presentation data with callbacks and save lifecycle intact.
104 */
105 function wpbc_booking_modes_v3_apply_current_page_options( $current_page_params, $page_slug, $tab_slug, $subtab_slug ) {
106 return WPBC_Booking_Modes_V3_Compiler::get_instance()->apply_page_options(
107 $current_page_params,
108 wpbc_booking_modes_v3_get_selected_definition(),
109 $page_slug,
110 $tab_slug,
111 $subtab_slug
112 );
113 }
114
115 /**
116 * Return canonical IDs whose routes exist in captured source metadata.
117 *
118 * @return array<int,string> Available canonical IDs.
119 */
120 function wpbc_booking_modes_v3_get_available_canonical_page_ids() {
121 $available = array();
122 foreach ( wpbc_booking_modes_get_canonical_pages() as $page_id => $page ) {
123 if ( null !== WPBC_Booking_Modes_V3_Source_Index::get_instance()->get_record( $page ) ) {
124 $available[] = $page_id;
125 }
126 }
127
128 return $available;
129 }
130
131 /**
132 * Apply the selected mode to the already registered native WPBC submenu.
133 *
134 * @return void
135 */
136 function wpbc_booking_modes_v3_filter_wordpress_submenu() {
137 global $submenu;
138
139 if ( ! isset( $submenu['wpbc'] ) || ! is_array( $submenu['wpbc'] ) ) {
140 return;
141 }
142
143 $definition = wpbc_booking_modes_v3_get_selected_definition();
144 $compiled = WPBC_Booking_Modes_V3_Compiler::get_instance()->compile_native(
145 $submenu['wpbc'],
146 $definition,
147 WPBC_Booking_Modes_V3_Compiler::get_current_edition_id()
148 );
149
150 /**
151 * Filter the resolved native submenu using the released hook signature.
152 *
153 * @param array $compiled Native submenu rows.
154 * @param string $mode_id Selected mode ID.
155 * @param array $mode Released-shape mode summary.
156 */
157 $filtered = apply_filters( 'wpbc_booking_modes_resolved_wp_submenu', $compiled, $definition['id'], wpbc_booking_modes_get_mode( $definition['id'] ) );
158 $authorized_submenu = WPBC_Booking_Modes_V3_Compiler::get_instance()->enforce_native_source_constraints(
159 is_array( $filtered ) ? $filtered : $compiled,
160 $compiled
161 );
162 $submenu['wpbc'] = wpbc_booking_modes_v3_add_native_upgrade_action( $authorized_submenu );
163 }
164 add_action( 'admin_menu', 'wpbc_booking_modes_v3_filter_wordpress_submenu', 9999 );
165
166 /**
167 * Check whether the native WordPress submenu should show the Free upgrade action.
168 *
169 * The existing Booking Calendar preference and edition checks remain authoritative,
170 * so this additional navigation surface follows the same visibility contract as
171 * the upgrade action in the Booking Calendar sidebar.
172 *
173 * @since 11.8.0
174 *
175 * @return bool True when the Free upgrade action may be rendered.
176 */
177 function wpbc_booking_modes_v3_should_show_native_upgrade_action() {
178 return function_exists( 'wpbc_is_show_free_upgrade' )
179 && function_exists( 'wpbc_up_link' )
180 && wpbc_is_show_free_upgrade();
181 }
182
183 /**
184 * Append the WPBC-owned Free upgrade action to an authorized native submenu.
185 *
186 * The row is added after source-constraint enforcement because it is a deliberate
187 * Booking Calendar action rather than a page contributed by a navigation source.
188 * Existing registered routes and third-party menu rows cannot be forged through
189 * this helper.
190 *
191 * @since 11.8.0
192 *
193 * @param array $native_submenu Authorized native Booking Calendar submenu rows.
194 *
195 * @return array Native submenu rows, optionally followed by the upgrade action.
196 */
197 function wpbc_booking_modes_v3_add_native_upgrade_action( $native_submenu ) {
198 if ( ! is_array( $native_submenu ) || empty( $native_submenu ) || ! wpbc_booking_modes_v3_should_show_native_upgrade_action() ) {
199 return is_array( $native_submenu ) ? $native_submenu : array();
200 }
201
202 $upgrade_capability = 'read';
203 $has_source_capability = false;
204 foreach ( $native_submenu as $native_submenu_row ) {
205 if ( isset( $native_submenu_row[0] ) && false !== strpos( (string) $native_submenu_row[0], 'wpbc_native_upgrade_menu_label' ) ) {
206 return $native_submenu;
207 }
208 if ( ! $has_source_capability && isset( $native_submenu_row[1] ) && is_string( $native_submenu_row[1] ) && '' !== $native_submenu_row[1] ) {
209 $upgrade_capability = $native_submenu_row[1];
210 $has_source_capability = true;
211 }
212 }
213
214 $native_submenu[] = array(
215 '<span class="wpbc_native_upgrade_menu_label">' . esc_html__( 'Upgrade to Pro', 'booking' ) . '</span>',
216 $upgrade_capability,
217 wpbc_up_link(),
218 );
219
220 return $native_submenu;
221 }
222
223 /**
224 * Enqueue the scoped native-menu upgrade style wherever WordPress renders it.
225 *
226 * @since 11.8.0
227 *
228 * @return void
229 */
230 function wpbc_booking_modes_v3_enqueue_native_upgrade_style() {
231 if ( ! wpbc_booking_modes_v3_should_show_native_upgrade_action() ) {
232 return;
233 }
234
235 wp_enqueue_style(
236 'wpbc-booking-modes-native-menu',
237 trailingslashit( plugins_url( '', __FILE__ ) ) . '_out/booking_modes-native-menu.css',
238 array(),
239 WP_BK_VERSION_NUM
240 );
241 }
242 add_action( 'admin_enqueue_scripts', 'wpbc_booking_modes_v3_enqueue_native_upgrade_style', 20 );
243
244 /**
245 * Hide only a V3-configured native entry while retaining direct registration.
246 *
247 * @param string|false $parent_menu_slug Existing parent slug.
248 * @param string $menu_slug Registered child slug.
249 *
250 * @return string|false Original parent or false for presentation-only hiding.
251 */
252 function wpbc_booking_modes_v3_filter_admin_menu_parent_slug( $parent_menu_slug, $menu_slug ) {
253 $menu_slug = is_scalar( $menu_slug ) ? sanitize_key( (string) $menu_slug ) : '';
254 if ( '' === $menu_slug ) {
255 return $parent_menu_slug;
256 }
257
258 $definition = wpbc_booking_modes_v3_get_selected_definition();
259 $options = isset( $definition['wordpress_menu'][ $menu_slug ] ) ? $definition['wordpress_menu'][ $menu_slug ] : array();
260 $compatibility_menu = WPBC_Booking_Modes_V3_Compatibility_Registry::get_instance()->get_native_menu( $definition['id'] );
261 $compatibility_options = isset( $compatibility_menu[ $menu_slug ] ) ? $compatibility_menu[ $menu_slug ] : array();
262 if ( isset( $options['visible'] ) && false === $options['visible'] ) {
263 return false;
264 }
265 if ( isset( $options['editions'] ) && ! in_array( WPBC_Booking_Modes_V3_Compiler::get_current_edition_id(), $options['editions'], true ) ) {
266 return false;
267 }
268 if ( isset( $compatibility_options['visible'] ) && false === $compatibility_options['visible'] ) {
269 return false;
270 }
271
272 return $parent_menu_slug;
273 }
274 add_filter( 'wpbc_admin_menu_parent_slug', 'wpbc_booking_modes_v3_filter_admin_menu_parent_slug', 10, 2 );
275
276 /**
277 * Preserve the released wpbc-new alias for the selected workflow.
278 *
279 * @return void
280 */
281 function wpbc_booking_modes_v3_redirect_native_add_page() {
282 $context = wpbc_booking_modes_get_context();
283 if ( empty( $context['is_admin'] ) || 'wpbc-new' !== $context['page'] ) {
284 return;
285 }
286
287 $page_id = 'appointment' === wpbc_booking_modes_get_selected_mode_id() ? 'wpbc__add-appointment' : 'wpbc__add-booking';
288 $redirect_url = wpbc_booking_modes_get_canonical_page_url( $page_id );
289 if ( '' !== $redirect_url ) {
290 wp_safe_redirect( $redirect_url );
291 exit;
292 }
293 }
294 add_action( 'admin_init', 'wpbc_booking_modes_v3_redirect_native_add_page', 20 );
295
296 /**
297 * Hide the context-free availability toolbar action in Rentals mode.
298 *
299 * Rental workflows manage availability from their dedicated navigation and do
300 * not need the context-free Block Times shortcut in the booking-list toolbar.
301 * The row action remains available because it has a concrete booking context.
302 *
303 * @since 11.8.0
304 *
305 * @param bool $show_button Existing button visibility.
306 *
307 * @return bool Updated button visibility.
308 */
309 function wpbc_booking_modes_v3_filter_set_unavailable_times_button( $show_button ) {
310 if ( ! $show_button ) {
311 return false;
312 }
313
314 return 'rental' !== wpbc_booking_modes_get_selected_mode_id();
315 }
316 add_filter( 'wpbc_booking_listing_show_set_unavailable_times_button', 'wpbc_booking_modes_v3_filter_set_unavailable_times_button' );
317
318 /**
319 * Preserve the compact listing action label outside Appointments mode.
320 *
321 * @param bool $show_button_text Existing label visibility.
322 *
323 * @return bool Updated label visibility.
324 */
325 function wpbc_booking_modes_v3_filter_set_unavailable_times_button_text( $show_button_text ) {
326 return 'appointment' === wpbc_booking_modes_get_selected_mode_id() ? $show_button_text : false;
327 }
328 add_filter( 'wpbc_booking_listing_show_set_unavailable_times_button_text', 'wpbc_booking_modes_v3_filter_set_unavailable_times_button_text' );
329