PluginProbe
Booking Calendar / 11.1
Booking Calendar v11.1
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 10.11.2 10.11.3 All 202 releases
booking / includes / ui_settings / class-menu-structure.php

class-menu-structure.php in Booking Calendar 11.1, at includes/ui_settings/class-menu-structure.php

632 lines 25.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Menu Structure in Admin Panel
4 *
5 * @version 1.0
6 * @package Any
7 * @category Plugin Menu Structure - in Admin Panel
8 * @author wpdevelop
9 *
10 * @web-site https://wpbookingcalendar.com/
11 * @email info@wpbookingcalendar.com
12 *
13 * @modified 2025-02-09
14 */
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit; // Exit, if accessed directly.
18 }
19
20 // FixIn: 11.0.0.1.
21
22 /**
23 * Define Settings Page Structure
24 */
25 abstract class WPBC_Menu_Structure {
26
27 /**
28 * Parameters for current page, if this page selected, otherwise its = empty array()
29 *
30 * @var array
31 */
32 protected $current_page_params;
33
34 /**
35 * Tabs array, same for all objects.
36 *
37 * @var array
38 */
39 protected static $nav_tabs;
40
41 /**
42 * Defining Name of parameter in GET request for Navigation TOP and BOTTOM tabs: - $_GET[ 'tab' ] == 'payment' - $_GET[ 'subtab' ] == 'paypal'.
43 *
44 * @var array
45 */
46 protected $tags;
47
48
49 /**
50 * Constructor
51 */
52 public function __construct() {
53
54 self::$nav_tabs = array();
55
56 $this->current_page_params = array();
57
58 $this->tags = array();
59
60 // Defining Name of parameter in GET request - $_GET[ 'tab' ] == 'payment'.
61 $this->tags['tab'] = 'tab';
62
63 // Defining Name of parameter in GET request - $_GET[ 'subtab' ] == 'paypal'.
64 $this->tags['subtab'] = 'subtab';
65
66 // FixIn: 10.14.1.2.
67 // This Hook fire after creation menu in class WPBC_Admin_Menus.
68 add_action( 'wpbc_define_nav_tabs', array( $this, 'wpbc_create_plugin_menu_structure_arr' ), 10, 1 );
69
70 // Such calls requires for ability to use methods, such as $this->is_use_option__in_subtabs_or_tabs('...'), which can be run only after_tabs_defined !
71 // We set here priority 11, to load this function, after 'wpbc_create_plugin_menu_structure_arr', where defined all tabs.
72 add_action( 'wpbc_define_nav_tabs', array( $this, 'after_tabs_defined' ), 11, 1 );
73
74 // Right Vertical Sidebar. // FixIn: 10.14.1.3.
75 add_action( 'wpbc_ui__right_vertical_sidebar_content', array( $this, 'maybe_show_right_sidebar_content' ) );
76
77 // Right Vertical Sidebar - Compact. // FixIn: 10.14.1.3.
78 add_action( 'wpbc_ui__right_vertical_sidebar_compact_content', array( $this, 'maybe_show_right_sidebar_compact_content' ) );
79 }
80
81
82 // -----------------------------------------------------------------------------------------------------------------
83 // Abstract Methods
84 // -----------------------------------------------------------------------------------------------------------------
85
86 /**
87 * Define slug in what menu to show this page. // Parameter relative: $_GET['page'].
88 *
89 * @return string
90 *
91 * Example:
92 *
93 * return 'wpbc-settings';
94 */
95 abstract public function in_page();
96
97 /**
98 * Define Tabs and Subtabs of this Admin Page
99 *
100 * @return array();
101 *
102 * Example:
103 *
104 * $tabs = array();
105 * $tabs[ 'form' ] = array(
106 * 'title' => __('Form','booking') // Title of TAB
107 * , 'hint' => __('Customization of Form Fields', 'booking') // Hint
108 * , 'page_title' =>ucwords( __('Form fields', 'booking') ) // Title of Page
109 * //, 'link' => '' // Can be skiped, then generated link based on Page and Tab tags. Or can be extenral link
110 * //, 'position' => '' // 'left' || 'right' || ''
111 * //, 'css_classes' => '' // CSS class(es)
112 * //, 'icon' => '' // Icon - link to the real PNG img
113 * , 'font_icon' => 'wpbc_icn_draw' // CSS definition of forn Icon
114 * , 'default' => false // Is this tab activated by default or not: true || false.
115 * , 'disabled' => false // Is this tab disbaled: true || false.
116 * , 'hided' => false // Is this tab hided: true || false.
117 * , 'subtabs' => array()
118 *
119 * );
120 * $tabs[ 'upgrade' ] = array(
121 * 'title' => __('Upgrade','booking') // Title of TAB
122 * , 'hint' => __('Upgrade to higher version', 'booking') // Hint
123 * //, 'page_title' => __('Upgrade', 'booking') // Title of Page
124 * , 'link' => 'http://server.com/' // Can be skiped, then generated link based on Page and Tab tags. Or can be extenral link
125 * , 'position' => 'right' // 'left' || 'right' || ''
126 * //, 'css_classes' => '' // CSS class(es)
127 * //, 'icon' => '' // Icon - link to the real PNG img
128 * , 'font_icon' => 'wpbc_icn_auto_graph'// CSS definition of forn Icon
129 * //, 'default' => false // Is this tab activated by default or not: true || false.
130 * //, 'subtabs' => array()
131 *
132 * );
133 *
134 * $subtabs = array();
135 *
136 * $subtabs['fields'] = array(
137 * 'type' => 'subtab' // Required| Possible values: 'subtab' | 'separator' | 'button' | 'goto-link' | 'html'
138 * , 'title' => __('Form','booking') // Title of TAB
139 * , 'page_title' => __('Form Settings', 'booking') // Title of Page
140 * , 'hint' => __('Customization of Form Settings', 'booking') // Hint
141 * , 'link' => '' // link
142 * , 'position' => '' // 'left' || 'right' || ''
143 * , 'css_classes' => '' // CSS class(es)
144 * //, 'icon' => 'https://www.paypalobjects.com/webstatic/icon/pp258.png' // Icon - link to the real PNG img
145 * //, 'font_icon' => 'wpbc_icn_payment' // CSS definition of Font Icon
146 * , 'default' => true // Is this sub tab activated by default or not: true || false.
147 * , 'disabled' => false // Is this sub tab deactivated: true || false.
148 * , 'checkbox' => false // or definition array for specific checkbox: array( 'checked' => true, 'name' => 'feature1_active_status' )
149 * , 'content' => 'content' // Function to load as conten of this TAB
150 * );
151 *
152 * $subtabs['form-separator'] = array(
153 * 'type' => 'separator' // Required| Possible values: 'subtab' | 'separator' | 'button' | 'goto-link' | 'html'
154 * );
155 * $subtabs['form-goto'] = array(
156 * 'type' => 'goto-link' // Required| Possible values: 'subtab' | 'separator' | 'button' | 'goto-link' | 'html'
157 * , 'title' =>ucwords( __('Form fields', 'booking') ) // Title of TAB
158 * , 'hint' => '' // Hint
159 * , 'show_section' => 'id_of_show_section' // ID of HTML element, for scroll to.
160 * );
161 *
162 * ob_start();
163 * ...
164 * $html_element_data = ob_get_clean();
165 *
166 * $subtabs['form-selection'] = array(
167 * 'type' => 'html' // Required| Possible values: 'subtab' | 'separator' | 'button' | 'goto-link' | 'html'
168 * , 'html' => $html_element_data
169 * );
170 *
171 * $subtabs['form-save'] = array(
172 * 'type' => 'button' // Required| Possible values: 'subtab' | 'separator' | 'button' | 'goto-link' | 'html'
173 * , 'title' => __('Save Changes','booking') // Title of TAB
174 * , 'form' => 'wpbc_form' // Required for 'button'! Name of Form to submit
175 * );
176 *
177 * $tabs[ 'form' ][ 'subtabs' ] = $subtabs;
178 *
179 * return $tabs;
180 */
181 abstract public function tabs();
182
183 /**
184 * Show Content of this page - Main function.
185 *
186 * In top of this function have to be checking ubout Update (saving POST request).
187 *
188 * Exmaple:
189 *
190 * // S u b m i t ///////////////////////////////////////////////////////
191 *
192 * $this_submit_form = 'wpbc_emails_toolbar'; // Define form name
193 *
194 * // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
195 * if ( isset( $_POST['is_form_sbmitted_'. $this_submit_form ] ) ) {
196 *
197 * // Check N o n c e
198 * check_admin_referer( 'wpbc_settings_page_' . $this_submit_form ); // Its stop show anything on submiting, if its not refear to the original page
199 *
200 * // Make Update of settings
201 * $edit_field_data = $this->update_wpbc_emails_toolbar( $menu_slug );
202 * }
203 */
204 abstract public function content();
205
206
207 // -----------------------------------------------------------------------------------------------------------------
208 // Right Vertical Sidebar. // FixIn: 10.14.1.3.
209 // -----------------------------------------------------------------------------------------------------------------
210
211 /**
212 * Show content of right sidebar. Overide it in child classes !
213 *
214 * @return void
215 */
216 abstract public function right_sidebar_content();
217
218
219 /**
220 * Helper method to show 'right sidebar' only if it is enabled page!
221 *
222 * @return void
223 */
224 public function maybe_show_right_sidebar_content(){
225
226 if ( ! $this->is_page_activated() ) {
227 return false;
228 }
229
230 $this->right_sidebar_content();
231 }
232
233 /**
234 * Show content of right sidebar - Compact. Overide it in child classes !
235 *
236 * @return void
237 */
238 abstract public function right_sidebar_compact_content();
239
240
241 /**
242 * Helper method to show 'right sidebar' - Compact only if it is enabled page!
243 *
244 * @return void
245 */
246 public function maybe_show_right_sidebar_compact_content(){
247
248 if ( ! $this->is_page_activated() ) {
249 return false;
250 }
251
252 $this->right_sidebar_compact_content();
253 }
254
255 // -----------------------------------------------------------------------------------------------------------------
256 // Methods After 'Tabs' defined. // FixIn: 10.14.1.2.
257 // -----------------------------------------------------------------------------------------------------------------
258
259 /**
260 * We already prepeared all tabs and can use function such as $this->is_page_activated();
261 * // FixIn: 10.14.1.2.
262 *
263 * @return void
264 */
265 public function after_tabs_defined() {
266
267 // This call -> Initiate definition of all parameters for current page.
268 $is_page_activated = $this->is_page_activated();
269
270 if ( $is_page_activated ) {
271 add_filter( 'admin_body_class', array( $this, 'admin_body_class__add_loading_classes' ) );
272 }
273 }
274
275
276 /**
277 * Check if this page have to load in default Full Screen mode,
278 * because of parameter 'is_default_full_screen' => false in ->tabs(...) method.
279 * If yes, then we add css class 'wpbc_admin_full_screen' to the body of the page.
280 * // FixIn: 10.14.1.2.
281 *
282 * @param string $classes - CSS classes.
283 *
284 * @return mixed|string
285 */
286 public function admin_body_class__add_loading_classes( $classes ) {
287
288 // Such method ->is_use_option__in_subtabs_or_tabs(...) can be load only after_tabs_defined !
289 if ( $this->is_use_option__in_subtabs_or_tabs( 'is_default_full_screen' ) ) {
290 $classes .= ' wpbc_admin_full_screen';
291 }
292
293 return $classes;
294 }
295
296
297 // -----------------------------------------------------------------------------------------------------------------
298 // Getters
299 // -----------------------------------------------------------------------------------------------------------------
300
301 public function get_current_page_params() {
302 return $this->current_page_params;
303 }
304
305 public function get_nav_tabs() {
306 return self::$nav_tabs;
307 }
308
309 // -----------------------------------------------------------------------------------------------------------------
310 // Active Page Parameters
311 // -----------------------------------------------------------------------------------------------------------------
312
313 /**
314 * Check if this page selected (active), depend from the GET parameter
315 * If selected, then define Current Page Parameters.
316 *
317 * @return boolean
318 */
319 protected function is_page_activated() {
320
321 $is_page_selected = false;
322
323 $this_page = $this->in_page();
324 $this_page_arr = ( is_array( $this_page ) ) ? $this_page : array( $this_page );
325
326 $request_arr = array();
327 $request_arr['page'] = isset( $_REQUEST['page'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
328 ? sanitize_text_field( wp_unslash( $_REQUEST['page'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
329 : null;
330 $request_arr['tab'] = isset( $_REQUEST[ $this->tags['tab'] ] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
331 ? sanitize_text_field( wp_unslash( $_REQUEST[ $this->tags['tab'] ] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
332 : null;
333 $request_arr['subtab'] = isset( $_REQUEST[ $this->tags['subtab'] ] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
334 ? sanitize_text_field( wp_unslash( $_REQUEST[ $this->tags['subtab'] ] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
335 : null;
336
337 foreach ( $this_page_arr as $this_page ) {
338
339 foreach ( $this->tabs() as $this_tab_tag => $this_tab ) {
340
341 // FixIn: 10.11.3.5.1.
342 $not_skip_type_arr = array( 'tab', 'subtab' );
343
344 if ( ( empty( $this_tab['type'] ) ) || ( in_array( $this_tab['type'], $not_skip_type_arr, true ) ) ) {
345 // Probably it is not the separator, and we have no content here !
346 // Get First Tab Element, which MUST be subtab element, all other tabs, can be links, not really showing content!!!
347 break;
348 }
349 }
350
351 if ( empty( $this_tab ) ) {
352 return $this_page; // this page empty - tabs is empty array, probabaly its was redefined in child CLASS to $tabs = array(); for not ability to open this page.
353 }
354
355 $this_subtab_tag = 0;
356 $this_subtab = array( 'default' => false );
357
358 if ( isset( $this_tab['subtabs'] ) ) {
359 foreach ( $this_tab['subtabs'] as $temp_this_subtab_tag => $temp_this_subtab ) {
360
361 // Get First Subtab element from subtabs array.
362 if ( 'subtab' === $temp_this_subtab['type'] ) {
363 $this_subtab_tag = $temp_this_subtab_tag;
364 $this_subtab = $temp_this_subtab;
365 break;
366 }
367 }
368 }
369
370 if ( ( isset( $request_arr['page'] ) ) && ( $this_page === $request_arr['page'] ) ) { // We are inside of this page. Menu item selected.
371
372 if (
373 ( ! isset( $request_arr['tab'] ) ) // the TAB NOT selected and Default.
374 // && ( ! isset( $request_arr['subtab'] ) ) // the SubTab NOT selected.
375 && ( isset( $this_tab['default'] ) ) && ( $this_tab['default'] ) ) {
376 $is_page_selected = true;
377 }
378
379 if (
380 ( isset( $request_arr['tab'] ) ) // TAB Selected.
381 && ( ! isset( $request_arr['subtab'] ) ) // SubTab NOT selected && ! exist || Default.
382 && ( $request_arr['tab'] === $this_tab_tag ) && ( ( 0 === $this_subtab_tag ) || ( $this_subtab['default'] ) ) ) {
383 $is_page_selected = true;
384 }
385
386 if (
387 ( isset( $request_arr['tab'] ) ) // TAB Selected.
388 && ( isset( $request_arr['subtab'] ) ) // SubTab Selected.
389 && ( $request_arr['tab'] === $this_tab_tag )
390 && ( $request_arr['subtab'] === $this_subtab_tag ) ) {
391 $is_page_selected = true;
392 }
393 }
394
395 // If this page activated, then define Current Page parameters.
396 if ( $is_page_selected ) {
397 $this->define_current_page_parameters( $this_tab_tag, $this_tab, $this_subtab_tag, $this_subtab );
398 }
399
400 if ( $is_page_selected ) {
401 break;
402 }
403 }
404
405 return $is_page_selected;
406 }
407
408
409 /**
410 * Define parameters for current selected page
411 *
412 * @param string $this_tab_tag = 'email'.
413 * @param array $this_tab = [ 'title' => 'Emails', 'font_icon' => 'wpbc_icn_mail_outline', 'subtabs' => [ 'new-admin' => [ 'type' => 'subtab', 'title' => 'New Booking (admin)', ... ], ].
414 * @param string $this_subtab_tag = 'new-admin'.
415 * @param array $this_subtab = [ 'type' => 'subtab', 'title' => 'New Booking (admin)', 'page_title' => 'Emails Settings',... ].
416 *
417 * @return void
418 */
419 protected function define_current_page_parameters( $this_tab_tag, $this_tab, $this_subtab_tag, $this_subtab ) {
420
421 $this->current_page_params = array(
422 'tab' => array_merge( $this_tab, array( 'tag' => $this_tab_tag ) ),
423 'subtab' => array_merge( $this_subtab, array( 'tag' => $this_subtab_tag ) ),
424 );
425 }
426
427
428 /**
429 * Get all SubTabs of current opened page Tab
430 *
431 * @param string $menu_in_page_tag - Optional. Menu Tag, the same as $this->in_page ();.
432 *
433 * @return array
434 */
435 protected function get_all_sub_tabs_of_selected_tab( $menu_in_page_tag = false ) {
436
437 if ( false === $menu_in_page_tag ) {
438
439 $this_page = $this->in_page();
440 $this_page_arr = ( is_array( $this_page ) ) ? $this_page : array( $this_page );
441
442 $menu_in_page_tag = $this_page_arr[0];
443 }
444
445 $all_sub_tabs_of_selected_tab = self::$nav_tabs[ $menu_in_page_tag ][ $this->current_page_params['tab']['tag'] ]['subtabs'];
446
447 return $all_sub_tabs_of_selected_tab;
448 }
449
450
451
452 // -----------------------------------------------------------------------------------------------------------------
453 // T A B s - Define
454 // -----------------------------------------------------------------------------------------------------------------
455
456 /**
457 * Define TABS structure. - General structure of tabs for every plugin menu page.
458 *
459 * Function executed after creation menu in class WPBC_Admin_Menus.
460 */
461 public function wpbc_create_plugin_menu_structure_arr() {
462
463 /**
464 * Array (
465 * [wpbc-resources] => Array ()
466 * [wpbc-settings] => Array
467 * (
468 * [general] => Array
469 * (
470 * [title] => General
471 * [page_title] => General Settings
472 * ...
473 * [subtabs] => Array ()
474 * )
475 * [help] => Array
476 * (
477 * [title] => Help
478 * [page_title] =>
479 * ...
480 * [subtabs] => Array ()
481 * )
482 * [form] => Array
483 * (
484 * [title] => Form
485 * [hint] => Customization of Form Fields
486 * [page_title] => Form Fields
487 * ...
488 * [subtabs] => Array
489 * (
490 * [goto-form] => Array
491 * (
492 * [type] => goto-link
493 * [title] => Booking Form Fields
494 * ...
495 * [content] => content
496 * [update] => update
497 * )
498 *
499 * [goto-content-data] => Array
500 * (
501 * [type] => button
502 * [title] => Save Changes
503 * [form] => wpbc_form
504 * ...
505 * )
506 *
507 * )
508 *
509 * )
510 * [payment] => Array
511 * (
512 * [title] => Payments
513 * [hint] => Customization of Payment
514 * [page_title] => Payment Gateways
515 * ...
516 * [subtabs] => Array
517 * (
518 * [paypal] => Array
519 * (
520 * [type] => subtab
521 * [title] => PayPal
522 * ...
523 * )
524 *
525 * [sage] => Array
526 * (
527 * [type] => subtab
528 * [title] => Sage
529 * ...
530 * )
531 *
532 * )
533 *
534 * )
535 *
536 * )
537 *
538 * )
539 */
540 /**
541 * The self::$nav_tabs =
542 *
543 * WP Left Menu | Top Horiz Menu | Vert Left Menu or top submenu
544 * ? page =wpbc-settings & tab=email & subtab=new-admin
545 *
546 * [
547 * wpbc-settings = [
548 * general = [...]
549 * form = [...]
550 * email = [...,
551 * subtabs = [
552 * new-admin = [
553 * type = "subtab"
554 * , ...
555 */
556
557 $this_page = $this->in_page(); // e.g. 'wpbc-settings'.
558 $this_page_arr = ( is_array( $this_page ) ) ? $this_page : array( $this_page ); // it can be like: [ 'wpbc-settings' ].
559
560 // Menu Structure.
561 foreach ( $this_page_arr as $this_page ) {
562
563 // WP Left Menu.
564 if ( ! isset( self::$nav_tabs[ $this_page ] ) ) {
565 self::$nav_tabs[ $this_page ] = array();
566 }
567
568 // Top Horiz Menu - e.g. [ 'calendar_appearance' ] => [ ... ] ].
569 $local_top_main_menu_arr = $this->tabs();
570
571 // Vert Left Menu - or top submenu.
572 $local_vert_left_menu_arr = array();
573
574 foreach ( $local_top_main_menu_arr as $tab_tag => $tab_array ) {
575
576 if ( isset( $tab_array['subtabs'] ) ) {
577 $local_vert_left_menu_arr[ $tab_tag ] = $tab_array['subtabs']; // Create new Subtabs array.
578
579 unset( $local_top_main_menu_arr[ $tab_tag ]['subtabs'] ); // Detach Subtabs array from Tab array. It's required for do not overwrite subtabs with already exist subtabs in previlosly defined tab.
580 } else {
581 $local_vert_left_menu_arr[ $tab_tag ] = array();
582 }
583 }
584
585 foreach ( $local_top_main_menu_arr as $tab_tag => $tab_array ) {
586
587 if ( ! isset( self::$nav_tabs[ $this_page ][ $tab_tag ] ) ) { // If this tab ( for exmaple "payment") declared previously, then does not do anything.
588 self::$nav_tabs[ $this_page ][ $tab_tag ] = array();
589 }
590
591 foreach ( $local_top_main_menu_arr[ $tab_tag ] as $page_prop_name => $page_prop_value ) {
592 if ( 'subtabs' !== $page_prop_name ) {
593 self::$nav_tabs[ $this_page ][ $tab_tag ][ $page_prop_name ] = $page_prop_value;
594 }
595 }
596
597 if ( ! isset( self::$nav_tabs[ $this_page ][ $tab_tag ]['subtabs'] ) ) {
598 self::$nav_tabs[ $this_page ][ $tab_tag ]['subtabs'] = array();
599 }
600 // Merge subtabs (Ex: PayPal and Sage) and attach to current tab: (Ex: payment).
601 self::$nav_tabs[ $this_page ][ $tab_tag ]['subtabs'] = array_merge( self::$nav_tabs[ $this_page ][ $tab_tag ]['subtabs'], $local_vert_left_menu_arr[ $tab_tag ] );
602
603 }
604 }
605
606 self::$nav_tabs = apply_filters( 'wpbc_plugin_menu_structure_arr', self::$nav_tabs, $this_page );
607 }
608
609
610 /**
611 * Get array of visible TABs
612 * Tabs that do not hided or disbaled
613 *
614 * @param string $menu_in_page_tag - Menu Tag, the same as $this->in_page ();.
615 *
616 * @return type
617 */
618 protected function get_visible_tabs( $menu_in_page_tag ) {
619
620 $visible_tabs = array();
621
622 foreach ( self::$nav_tabs[ $menu_in_page_tag ] as $tab_tag => $tab ) {
623
624 if ( empty( $tab['disabled'] ) && empty( $tab['hided'] ) ) {
625 $visible_tabs[ $tab_tag ] = $tab;
626 }
627 }
628
629 return $visible_tabs;
630 }
631 }
632