PluginProbe
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder / 1.5
Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder v1.5
3.6.0 3.5.0 trunk 1.0.10 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.6.1 1.0.7 1.0.8 1.0.9 1.1 1.1.1 1.2 1.3 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5 1.5.1 All 110 releases
buttonizer-multifunctional-button / freemius / includes / managers / class-fs-admin-menu-manager.php

class-fs-admin-menu-manager.php in Buttonizer – Floating Menus, Sticky Buttons, & Popup Builder 1.5, at freemius/includes/managers/class-fs-admin-menu-manager.php

957 lines 23.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.1.3
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 class FS_Admin_Menu_Manager {
14
15 #region Properties
16
17 /**
18 * @since 1.2.2
19 *
20 * @var string
21 */
22 protected $_module_unique_affix;
23
24 /**
25 * @since 1.2.2
26 *
27 * @var number
28 */
29 protected $_module_id;
30
31 /**
32 * @since 1.2.2
33 *
34 * @var string
35 */
36 protected $_module_type;
37
38 /**
39 * @since 1.0.6
40 *
41 * @var string
42 */
43 private $_menu_slug;
44 /**
45 * @since 1.1.3
46 *
47 * @var string
48 */
49 private $_parent_slug;
50 /**
51 * @since 1.1.3
52 *
53 * @var string
54 */
55 private $_parent_type;
56 /**
57 * @since 1.1.3
58 *
59 * @var string
60 */
61 private $_type;
62 /**
63 * @since 1.1.3
64 *
65 * @var bool
66 */
67 private $_is_top_level;
68 /**
69 * @since 1.1.3
70 *
71 * @var bool
72 */
73 private $_is_override_exact;
74 /**
75 * @since 1.1.3
76 *
77 * @var array<string,bool>
78 */
79 private $_default_submenu_items;
80 /**
81 * @since 1.1.3
82 *
83 * @var string
84 */
85 private $_first_time_path;
86 /**
87 * @since 1.2.2
88 *
89 * @var bool
90 */
91 private $_menu_exists;
92 /**
93 * @since 2.0.0
94 *
95 * @var bool
96 */
97 private $_network_menu_exists;
98
99 #endregion Properties
100
101 /**
102 * @var FS_Logger
103 */
104 protected $_logger;
105
106 #region Singleton
107
108 /**
109 * @var FS_Admin_Menu_Manager[]
110 */
111 private static $_instances = array();
112
113 /**
114 * @param number $module_id
115 * @param string $module_type
116 * @param string $module_unique_affix
117 *
118 * @return FS_Admin_Menu_Manager
119 */
120 static function instance( $module_id, $module_type, $module_unique_affix ) {
121 $key = 'm_' . $module_id;
122
123 if ( ! isset( self::$_instances[ $key ] ) ) {
124 self::$_instances[ $key ] = new FS_Admin_Menu_Manager( $module_id, $module_type, $module_unique_affix );
125 }
126
127 return self::$_instances[ $key ];
128 }
129
130 protected function __construct( $module_id, $module_type, $module_unique_affix ) {
131 $this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_admin_menu', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
132
133 $this->_module_id = $module_id;
134 $this->_module_type = $module_type;
135 $this->_module_unique_affix = $module_unique_affix;
136 }
137
138 #endregion Singleton
139
140 #region Helpers
141
142 private function get_option( &$options, $key, $default = false ) {
143 return ! empty( $options[ $key ] ) ? $options[ $key ] : $default;
144 }
145
146 private function get_bool_option( &$options, $key, $default = false ) {
147 return isset( $options[ $key ] ) && is_bool( $options[ $key ] ) ? $options[ $key ] : $default;
148 }
149
150 #endregion Helpers
151
152 /**
153 * @param array $menu
154 * @param bool $is_addon
155 */
156 function init( $menu, $is_addon = false ) {
157 $this->_menu_exists = ( isset( $menu['slug'] ) && ! empty( $menu['slug'] ) );
158 $this->_network_menu_exists = ( ! empty( $menu['network'] ) && true === $menu['network'] );
159
160 $this->_menu_slug = ( $this->_menu_exists ? $menu['slug'] : $this->_module_unique_affix );
161
162 $this->_default_submenu_items = array();
163 // @deprecated
164 $this->_type = 'page';
165 $this->_is_top_level = true;
166 $this->_is_override_exact = false;
167 $this->_parent_slug = false;
168 // @deprecated
169 $this->_parent_type = 'page';
170
171 if ( isset( $menu ) ) {
172 if ( ! $is_addon ) {
173 $this->_default_submenu_items = array(
174 'contact' => $this->get_bool_option( $menu, 'contact', true ),
175 'support' => $this->get_bool_option( $menu, 'support', true ),
176 'affiliation' => $this->get_bool_option( $menu, 'affiliation', true ),
177 'account' => $this->get_bool_option( $menu, 'account', true ),
178 'pricing' => $this->get_bool_option( $menu, 'pricing', true ),
179 'addons' => $this->get_bool_option( $menu, 'addons', true ),
180 );
181
182 // @deprecated
183 $this->_type = $this->get_option( $menu, 'type', 'page' );
184
185 $this->_first_time_path = $this->get_option( $menu, 'first-path', false );
186 if ( ! empty( $this->_first_time_path ) && is_string( $this->_first_time_path ) ) {
187 $this->_first_time_path = admin_url( $this->_first_time_path, 'admin' );
188 }
189 }
190
191 $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' );
192
193 if ( isset( $menu['parent'] ) ) {
194 $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' );
195 // @deprecated
196 $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' );
197
198 // If parent's slug is different, then it's NOT a top level menu item.
199 $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug );
200 } else {
201 /**
202 * If no parent then top level if:
203 * - Has custom admin menu ('page')
204 * - CPT menu type ('cpt')
205 */
206 // $this->_is_top_level = in_array( $this->_type, array(
207 // 'cpt',
208 // 'page'
209 // ) );
210 }
211 }
212 }
213
214 /**
215 * Check if top level menu.
216 *
217 * @author Vova Feldman (@svovaf)
218 * @since 1.1.3
219 *
220 * @return bool False if submenu item.
221 */
222 function is_top_level() {
223 return $this->_is_top_level;
224 }
225
226 /**
227 * Check if the page should be override on exact URL match.
228 *
229 * @author Vova Feldman (@svovaf)
230 * @since 1.1.3
231 *
232 * @return bool False if submenu item.
233 */
234 function is_override_exact() {
235 return $this->_is_override_exact;
236 }
237
238
239 /**
240 * Get the path of the page the user should be forwarded to after first activation.
241 *
242 * @author Vova Feldman (@svovaf)
243 * @since 1.1.3
244 *
245 * @return string
246 */
247 function get_first_time_path() {
248 return $this->_first_time_path;
249 }
250
251 /**
252 * Check if plugin's menu item is part of a custom top level menu.
253 *
254 * @author Vova Feldman (@svovaf)
255 * @since 1.1.3
256 *
257 * @return bool
258 */
259 function has_custom_parent() {
260 return ! $this->_is_top_level && is_string( $this->_parent_slug );
261 }
262
263 /**
264 * @author Leo Fajardo (@leorw)
265 * @since 1.2.2
266 *
267 * @return bool
268 */
269 function has_menu() {
270 return $this->_menu_exists;
271 }
272
273 /**
274 * @author Vova Feldman (@svovaf)
275 * @since 2.0.0
276 *
277 * @return bool
278 */
279 function has_network_menu() {
280 return $this->_network_menu_exists;
281 }
282
283 /**
284 * @author Vova Feldman (@svovaf)
285 * @since 1.1.3
286 *
287 * @param string $id
288 * @param bool $default
289 * @param bool $ignore_menu_existence Since 1.2.2.7 If true, check if the submenu item visible even if there's no parent menu.
290 *
291 * @return bool
292 */
293 function is_submenu_item_visible( $id, $default = true, $ignore_menu_existence = false ) {
294 if ( ! $ignore_menu_existence && ! $this->has_menu() ) {
295 return false;
296 }
297
298 return fs_apply_filter(
299 $this->_module_unique_affix,
300 'is_submenu_visible',
301 $this->get_bool_option( $this->_default_submenu_items, $id, $default ),
302 $id
303 );
304 }
305
306 /**
307 * Calculates admin settings menu slug.
308 * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug.
309 *
310 * @author Vova Feldman (@svovaf)
311 * @since 1.1.3
312 *
313 * @param string $page
314 *
315 * @return string
316 */
317 function get_slug( $page = '' ) {
318 return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ?
319 $this->_menu_slug :
320 $this->_module_unique_affix ) . ( empty( $page ) ? '' : ( '-' . $page ) );
321 }
322
323 /**
324 * @author Vova Feldman (@svovaf)
325 * @since 1.1.3
326 *
327 * @return string
328 */
329 function get_parent_slug() {
330 return $this->_parent_slug;
331 }
332
333 /**
334 * @author Vova Feldman (@svovaf)
335 * @since 1.1.3
336 *
337 * @return string
338 */
339 function get_type() {
340 return $this->_type;
341 }
342
343 /**
344 * @author Vova Feldman (@svovaf)
345 * @since 1.1.3
346 *
347 * @return bool
348 */
349 function is_cpt() {
350 return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) ||
351 // Back compatibility.
352 'cpt' === $this->_type
353 );
354 }
355
356 /**
357 * @author Vova Feldman (@svovaf)
358 * @since 1.1.3
359 *
360 * @return string
361 */
362 function get_parent_type() {
363 return $this->_parent_type;
364 }
365
366 /**
367 * @author Vova Feldman (@svovaf)
368 * @since 1.1.3
369 *
370 * @return string
371 */
372 function get_raw_slug() {
373 return $this->_menu_slug;
374 }
375
376 /**
377 * Get plugin's original menu slug.
378 *
379 * @author Vova Feldman (@svovaf)
380 * @since 1.1.3
381 *
382 * @return string
383 */
384 function get_original_menu_slug() {
385 if ( 'cpt' === $this->_type ) {
386 return add_query_arg( array(
387 'post_type' => $this->_menu_slug
388 ), 'edit.php' );
389 }
390
391 if ( false === strpos( $this->_menu_slug, '.php?' ) ) {
392 return $this->_menu_slug;
393 } else {
394 return $this->_module_unique_affix;
395 }
396 }
397
398 /**
399 * @author Vova Feldman (@svovaf)
400 * @since 1.1.3
401 *
402 * @return string
403 */
404 function get_top_level_menu_slug() {
405 return $this->has_custom_parent() ?
406 $this->get_parent_slug() :
407 $this->get_raw_slug();
408 }
409
410 /**
411 * Is user on plugin's admin activation page.
412 *
413 * @author Vova Feldman (@svovaf)
414 * @since 1.0.8
415 *
416 * @return bool
417 */
418 function is_main_settings_page() {
419 if ( $this->_menu_exists &&
420 ( fs_is_plugin_page( $this->_menu_slug ) || fs_is_plugin_page( $this->_module_unique_affix ) )
421 ) {
422 /**
423 * Module has a settings menu and the context page is the main settings page, so assume it's in
424 * activation (doesn't really check if already opted-in/skipped or not).
425 *
426 * @since 1.2.2
427 */
428 return true;
429 }
430
431 global $pagenow;
432 if ( ( WP_FS__MODULE_TYPE_THEME === $this->_module_type ) && Freemius::is_themes_page() ) {
433 /**
434 * In activation only when show_optin query string param is given.
435 *
436 * @since 1.2.2
437 */
438 return fs_request_get_bool( $this->_module_unique_affix . '_show_optin' );
439 }
440
441 return false;
442 }
443
444 #region Submenu Override
445
446 /**
447 * Override submenu's action.
448 *
449 * @author Vova Feldman (@svovaf)
450 * @since 1.1.0
451 *
452 * @param string $parent_slug
453 * @param string $menu_slug
454 * @param callable $function
455 *
456 * @return false|string If submenu exist, will return the hook name.
457 */
458 function override_submenu_action( $parent_slug, $menu_slug, $function ) {
459 global $submenu;
460
461 $menu_slug = plugin_basename( $menu_slug );
462 $parent_slug = plugin_basename( $parent_slug );
463
464 if ( ! isset( $submenu[ $parent_slug ] ) ) {
465 // Parent menu not exist.
466 return false;
467 }
468
469 $found_submenu_item = false;
470 foreach ( $submenu[ $parent_slug ] as $submenu_item ) {
471 if ( $menu_slug === $submenu_item[2] ) {
472 $found_submenu_item = $submenu_item;
473 break;
474 }
475 }
476
477 if ( false === $found_submenu_item ) {
478 // Submenu item not found.
479 return false;
480 }
481
482 // Remove current function.
483 $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
484 remove_all_actions( $hookname );
485
486 // Attach new action.
487 add_action( $hookname, $function );
488
489 return $hookname;
490 }
491
492 #endregion Submenu Override
493
494 #region Top level menu Override
495
496 /**
497 * Find plugin's admin dashboard main menu item.
498 *
499 * @author Vova Feldman (@svovaf)
500 * @since 1.0.2
501 *
502 * @return string[]|false
503 */
504 private function find_top_level_menu() {
505 global $menu;
506
507 $position = - 1;
508 $found_menu = false;
509
510 $menu_slug = $this->get_raw_slug();
511
512 $hook_name = get_plugin_page_hookname( $menu_slug, '' );
513 foreach ( $menu as $pos => $m ) {
514 if ( $menu_slug === $m[2] ) {
515 $position = $pos;
516 $found_menu = $m;
517 break;
518 }
519 }
520
521 if ( false === $found_menu ) {
522 return false;
523 }
524
525 return array(
526 'menu' => $found_menu,
527 'position' => $position,
528 'hook_name' => $hook_name
529 );
530 }
531
532 /**
533 * Find plugin's admin dashboard main submenu item.
534 *
535 * @author Vova Feldman (@svovaf)
536 * @since 1.2.1.6
537 *
538 * @return array|false
539 */
540 private function find_main_submenu() {
541 global $submenu;
542
543 $top_level_menu_slug = $this->get_top_level_menu_slug();
544
545 if ( ! isset( $submenu[ $top_level_menu_slug ] ) ) {
546 return false;
547 }
548
549 $submenu_slug = $this->get_raw_slug();
550
551 $position = - 1;
552 $found_submenu = false;
553
554 $hook_name = get_plugin_page_hookname( $submenu_slug, '' );
555
556 foreach ( $submenu[ $top_level_menu_slug ] as $pos => $sub ) {
557 if ( $submenu_slug === $sub[2] ) {
558 $position = $pos;
559 $found_submenu = $sub;
560 }
561 }
562
563 if ( false === $found_submenu ) {
564 return false;
565 }
566
567 return array(
568 'menu' => $found_submenu,
569 'parent_slug' => $top_level_menu_slug,
570 'position' => $position,
571 'hook_name' => $hook_name
572 );
573 }
574
575 /**
576 * Remove all sub-menu items.
577 *
578 * @author Vova Feldman (@svovaf)
579 * @since 1.0.7
580 *
581 * @return bool If submenu with plugin's menu slug was found.
582 */
583 private function remove_all_submenu_items() {
584 global $submenu;
585
586 $menu_slug = $this->get_raw_slug();
587
588 if ( ! isset( $submenu[ $menu_slug ] ) ) {
589 return false;
590 }
591
592 /**
593 * This method is NOT executed for WordPress.org themes.
594 * Since we maintain only one version of the SDK we added this small
595 * hack to avoid the error from Theme Check since it's a false-positive.
596 *
597 * @author Vova Feldman (@svovaf)
598 * @since 1.2.2.7
599 */
600 $submenu_ref = &$submenu;
601 $submenu_ref[ $menu_slug ] = array();
602
603 return true;
604 }
605
606 /**
607 *
608 * @author Vova Feldman (@svovaf)
609 * @since 1.0.9
610 *
611 * @param bool $remove_top_level_menu
612 *
613 * @return false|array[string]mixed
614 */
615 function remove_menu_item( $remove_top_level_menu = false ) {
616 $this->_logger->entrance();
617
618 // Find main menu item.
619 $top_level_menu = $this->find_top_level_menu();
620
621 if ( false === $top_level_menu ) {
622 return false;
623 }
624
625 // Remove it with its actions.
626 remove_all_actions( $top_level_menu['hook_name'] );
627
628 // Remove all submenu items.
629 $this->remove_all_submenu_items();
630
631 if ( $remove_top_level_menu ) {
632 global $menu;
633 unset( $menu[ $top_level_menu['position'] ] );
634 }
635
636 return $top_level_menu;
637 }
638
639 /**
640 * Get module's main admin setting page URL.
641 *
642 * @todo This method was only tested for wp.org compliant themes with a submenu item. Need to test for plugins with top level, submenu, and CPT top level, menu items.
643 *
644 * @author Vova Feldman (@svovaf)
645 * @since 1.2.2.7
646 *
647 * @return string
648 */
649 function main_menu_url() {
650 $this->_logger->entrance();
651
652 if ( $this->_is_top_level ) {
653 $menu = $this->find_top_level_menu();
654 } else {
655 $menu = $this->find_main_submenu();
656 }
657
658 $parent_slug = isset( $menu['parent_slug'] ) ?
659 $menu['parent_slug'] :
660 'admin.php';
661
662 return admin_url( $parent_slug . '?page=' . $menu['menu'][2] );
663 }
664
665 /**
666 * @author Vova Feldman (@svovaf)
667 * @since 1.1.4
668 *
669 * @param callable $function
670 *
671 * @return false|array[string]mixed
672 */
673 function override_menu_item( $function ) {
674 $found_menu = $this->remove_menu_item();
675
676 if ( false === $found_menu ) {
677 return false;
678 }
679
680 if ( ! $this->is_top_level() || ! $this->is_cpt() ) {
681 $menu_slug = plugin_basename( $this->get_slug() );
682
683 $hookname = get_plugin_page_hookname( $menu_slug, '' );
684
685 // Override menu action.
686 add_action( $hookname, $function );
687 } else {
688 global $menu;
689
690 // Remove original CPT menu.
691 unset( $menu[ $found_menu['position'] ] );
692
693 // Create new top-level menu action.
694 $hookname = self::add_page(
695 $found_menu['menu'][3],
696 $found_menu['menu'][0],
697 'manage_options',
698 $this->get_slug(),
699 $function,
700 $found_menu['menu'][6],
701 $found_menu['position']
702 );
703 }
704
705 return $hookname;
706 }
707
708 /**
709 * Adds a counter to the module's top level menu item.
710 *
711 * @author Vova Feldman (@svovaf)
712 * @since 1.2.1.5
713 *
714 * @param int $counter
715 * @param string $class
716 */
717 function add_counter_to_menu_item( $counter = 1, $class = '' ) {
718 global $menu, $submenu;
719
720 $mask = '%s <span class="update-plugins %s count-%3$s" aria-hidden="true"><span>%3$s<span class="screen-reader-text">%3$s notifications</span></span></span>';
721
722 /**
723 * This method is NOT executed for WordPress.org themes.
724 * Since we maintain only one version of the SDK we added this small
725 * hack to avoid the error from Theme Check since it's a false-positive.
726 *
727 * @author Vova Feldman (@svovaf)
728 * @since 1.2.2.7
729 */
730 $menu_ref = &$menu;
731 $submenu_ref = &$submenu;
732
733 if ( $this->_is_top_level ) {
734 // Find main menu item.
735 $found_menu = $this->find_top_level_menu();
736
737 if ( false !== $found_menu ) {
738 // Override menu label.
739 $menu_ref[ $found_menu['position'] ][0] = sprintf(
740 $mask,
741 $found_menu['menu'][0],
742 $class,
743 $counter
744 );
745 }
746 } else {
747 $found_submenu = $this->find_main_submenu();
748
749 if ( false !== $found_submenu ) {
750 // Override menu label.
751 $submenu_ref[ $found_submenu['parent_slug'] ][ $found_submenu['position'] ][0] = sprintf(
752 $mask,
753 $found_submenu['menu'][0],
754 $class,
755 $counter
756 );
757 }
758 }
759 }
760
761 #endregion Top level menu Override
762
763 /**
764 * Add a top-level menu page.
765 *
766 * Note for WordPress.org Theme/Plugin reviewer:
767 *
768 * This is a replication of `add_menu_page()` to avoid Theme Check warning.
769 *
770 * Why?
771 * ====
772 * Freemius is an SDK for plugin and theme developers. Since the core
773 * of the SDK is relevant both for plugins and themes, for obvious reasons,
774 * we only develop and maintain one code base.
775 *
776 * This method will not run for wp.org themes (only plugins) since theme
777 * admin settings/options are now only allowed in the customizer.
778 *
779 * If you have any questions or need clarifications, please don't hesitate
780 * pinging me on slack, my username is @svovaf.
781 *
782 * @author Vova Feldman (@svovaf)
783 * @since 1.2.2
784 *
785 * @param string $page_title The text to be displayed in the title tags of the page when the menu is
786 * selected.
787 * @param string $menu_title The text to be used for the menu.
788 * @param string $capability The capability required for this menu to be displayed to the user.
789 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
790 * @param callable|string $function The function to be called to output the content for this page.
791 * @param string $icon_url The URL to the icon to be used for this menu.
792 * * Pass a base64-encoded SVG using a data URI, which will be colored to
793 * match the color scheme. This should begin with
794 * 'data:image/svg+xml;base64,'.
795 * * Pass the name of a Dashicons helper class to use a font icon,
796 * e.g. 'dashicons-chart-pie'.
797 * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added
798 * via CSS.
799 * @param int $position The position in the menu order this one should appear.
800 *
801 * @return string The resulting page's hook_suffix.
802 */
803 static function add_page(
804 $page_title,
805 $menu_title,
806 $capability,
807 $menu_slug,
808 $function = '',
809 $icon_url = '',
810 $position = null
811 ) {
812 $fn = 'add_menu' . '_page';
813
814 return $fn(
815 $page_title,
816 $menu_title,
817 $capability,
818 $menu_slug,
819 $function,
820 $icon_url,
821 $position
822 );
823 }
824
825 /**
826 * Add page and update menu instance settings.
827 *
828 * @author Vova Feldman (@svovaf)
829 * @since 2.0.0
830 *
831 * @param string $page_title
832 * @param string $menu_title
833 * @param string $capability
834 * @param string $menu_slug
835 * @param callable|string $function
836 * @param string $icon_url
837 * @param int|null $position
838 *
839 * @return string
840 */
841 function add_page_and_update(
842 $page_title,
843 $menu_title,
844 $capability,
845 $menu_slug,
846 $function = '',
847 $icon_url = '',
848 $position = null
849 ) {
850 $this->_menu_slug = $menu_slug;
851 $this->_is_top_level = true;
852 $this->_menu_exists = true;
853 $this->_network_menu_exists = true;
854
855 return self::add_page(
856 $page_title,
857 $menu_title,
858 $capability,
859 $menu_slug,
860 $function,
861 $icon_url,
862 $position
863 );
864 }
865
866 /**
867 * Add a submenu page.
868 *
869 * Note for WordPress.org Theme/Plugin reviewer:
870 *
871 * This is a replication of `add_submenu_page()` to avoid Theme Check warning.
872 *
873 * Why?
874 * ====
875 * Freemius is an SDK for plugin and theme developers. Since the core
876 * of the SDK is relevant both for plugins and themes, for obvious reasons,
877 * we only develop and maintain one code base.
878 *
879 * This method will not run for wp.org themes (only plugins) since theme
880 * admin settings/options are now only allowed in the customizer.
881 *
882 * If you have any questions or need clarifications, please don't hesitate
883 * pinging me on slack, my username is @svovaf.
884 *
885 * @author Vova Feldman (@svovaf)
886 * @since 1.2.2
887 *
888 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard
889 * WordPress admin page).
890 * @param string $page_title The text to be displayed in the title tags of the page when the menu is
891 * selected.
892 * @param string $menu_title The text to be used for the menu.
893 * @param string $capability The capability required for this menu to be displayed to the user.
894 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
895 * @param callable|string $function The function to be called to output the content for this page.
896 *
897 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability
898 * required.
899 */
900 static function add_subpage(
901 $parent_slug,
902 $page_title,
903 $menu_title,
904 $capability,
905 $menu_slug,
906 $function = ''
907 ) {
908 $fn = 'add_submenu' . '_page';
909
910 return $fn( $parent_slug,
911 $page_title,
912 $menu_title,
913 $capability,
914 $menu_slug,
915 $function
916 );
917 }
918
919 /**
920 * Add sub page and update menu instance settings.
921 *
922 * @author Vova Feldman (@svovaf)
923 * @since 2.0.0
924 *
925 * @param string $parent_slug
926 * @param string $page_title
927 * @param string $menu_title
928 * @param string $capability
929 * @param string $menu_slug
930 * @param callable|string $function
931 *
932 * @return string
933 */
934 function add_subpage_and_update(
935 $parent_slug,
936 $page_title,
937 $menu_title,
938 $capability,
939 $menu_slug,
940 $function = ''
941 ) {
942 $this->_menu_slug = $menu_slug;
943 $this->_parent_slug = $parent_slug;
944 $this->_is_top_level = false;
945 $this->_menu_exists = true;
946 $this->_network_menu_exists = true;
947
948 return self::add_subpage(
949 $parent_slug,
950 $page_title,
951 $menu_title,
952 $capability,
953 $menu_slug,
954 $function
955 );
956 }
957 }