PluginProbe
Tiered Pricing Table for WooCommerce / 2.3.2
Tiered Pricing Table for WooCommerce v2.3.2
7.1.7 7.1.5 7.1.4 7.1.1 6.5.0 6.4.0 6.1.0 trunk 1.0 1.1 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.2.0 2.2.1 2.2.2 2.2.3 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 All 90 releases
tier-pricing-table / freemius / includes / managers / class-fs-admin-menu-manager.php

class-fs-admin-menu-manager.php in Tiered Pricing Table for WooCommerce 2.3.2, at freemius/includes/managers/class-fs-admin-menu-manager.php

980 lines 24.5 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
186 $this->_is_override_exact = $this->get_bool_option( $menu, 'override_exact' );
187
188 if ( isset( $menu['parent'] ) ) {
189 $this->_parent_slug = $this->get_option( $menu['parent'], 'slug' );
190 // @deprecated
191 $this->_parent_type = $this->get_option( $menu['parent'], 'type', 'page' );
192
193 // If parent's slug is different, then it's NOT a top level menu item.
194 $this->_is_top_level = ( $this->_parent_slug === $this->_menu_slug );
195 } else {
196 /**
197 * If no parent then top level if:
198 * - Has custom admin menu ('page')
199 * - CPT menu type ('cpt')
200 */
201 // $this->_is_top_level = in_array( $this->_type, array(
202 // 'cpt',
203 // 'page'
204 // ) );
205 }
206
207 $first_path = $this->get_option( $menu, 'first-path', false );
208
209 if ( ! empty( $first_path ) && is_string( $first_path ) ) {
210 $this->_first_time_path = $first_path;
211 }
212 }
213 }
214
215 /**
216 * Check if top level menu.
217 *
218 * @author Vova Feldman (@svovaf)
219 * @since 1.1.3
220 *
221 * @return bool False if submenu item.
222 */
223 function is_top_level() {
224 return $this->_is_top_level;
225 }
226
227 /**
228 * Check if the page should be override on exact URL match.
229 *
230 * @author Vova Feldman (@svovaf)
231 * @since 1.1.3
232 *
233 * @return bool False if submenu item.
234 */
235 function is_override_exact() {
236 return $this->_is_override_exact;
237 }
238
239
240 /**
241 * Get the path of the page the user should be forwarded to after first activation.
242 *
243 * @author Vova Feldman (@svovaf)
244 * @since 1.1.3
245 *
246 * @param bool $is_network Since 2.4.5
247 *
248 * @return string
249 */
250 function get_first_time_path( $is_network = false ) {
251 if ( empty ( $this->_first_time_path ) ) {
252 return $this->_first_time_path;
253 }
254
255 if ( $is_network ) {
256 return network_admin_url( $this->_first_time_path );
257 } else {
258 return admin_url( $this->_first_time_path );
259 }
260 }
261
262 /**
263 * Check if plugin's menu item is part of a custom top level menu.
264 *
265 * @author Vova Feldman (@svovaf)
266 * @since 1.1.3
267 *
268 * @return bool
269 */
270 function has_custom_parent() {
271 return ! $this->_is_top_level && is_string( $this->_parent_slug );
272 }
273
274 /**
275 * @author Leo Fajardo (@leorw)
276 * @since 1.2.2
277 *
278 * @return bool
279 */
280 function has_menu() {
281 return $this->_menu_exists;
282 }
283
284 /**
285 * @author Vova Feldman (@svovaf)
286 * @since 2.0.0
287 *
288 * @return bool
289 */
290 function has_network_menu() {
291 return $this->_network_menu_exists;
292 }
293
294 /**
295 * @author Leo Fajardo (@leorw)
296 *
297 * @param string $menu_slug
298 *
299 * @since 2.1.3
300 */
301 function set_slug_and_network_menu_exists_flag($menu_slug ) {
302 $this->_menu_slug = $menu_slug;
303 $this->_network_menu_exists = false;
304 }
305
306 /**
307 * @author Vova Feldman (@svovaf)
308 * @since 1.1.3
309 *
310 * @param string $id
311 * @param bool $default
312 * @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.
313 *
314 * @return bool
315 */
316 function is_submenu_item_visible( $id, $default = true, $ignore_menu_existence = false ) {
317 if ( ! $ignore_menu_existence && ! $this->has_menu() ) {
318 return false;
319 }
320
321 return fs_apply_filter(
322 $this->_module_unique_affix,
323 'is_submenu_visible',
324 $this->get_bool_option( $this->_default_submenu_items, $id, $default ),
325 $id
326 );
327 }
328
329 /**
330 * Calculates admin settings menu slug.
331 * If plugin's menu slug is a file (e.g. CPT), uses plugin's slug as the menu slug.
332 *
333 * @author Vova Feldman (@svovaf)
334 * @since 1.1.3
335 *
336 * @param string $page
337 *
338 * @return string
339 */
340 function get_slug( $page = '' ) {
341 return ( ( false === strpos( $this->_menu_slug, '.php?' ) ) ?
342 $this->_menu_slug :
343 $this->_module_unique_affix ) . ( empty( $page ) ? '' : ( '-' . $page ) );
344 }
345
346 /**
347 * @author Vova Feldman (@svovaf)
348 * @since 1.1.3
349 *
350 * @return string
351 */
352 function get_parent_slug() {
353 return $this->_parent_slug;
354 }
355
356 /**
357 * @author Vova Feldman (@svovaf)
358 * @since 1.1.3
359 *
360 * @return string
361 */
362 function get_type() {
363 return $this->_type;
364 }
365
366 /**
367 * @author Vova Feldman (@svovaf)
368 * @since 1.1.3
369 *
370 * @return bool
371 */
372 function is_cpt() {
373 return ( 0 === strpos( $this->_menu_slug, 'edit.php?post_type=' ) ||
374 // Back compatibility.
375 'cpt' === $this->_type
376 );
377 }
378
379 /**
380 * @author Vova Feldman (@svovaf)
381 * @since 1.1.3
382 *
383 * @return string
384 */
385 function get_parent_type() {
386 return $this->_parent_type;
387 }
388
389 /**
390 * @author Vova Feldman (@svovaf)
391 * @since 1.1.3
392 *
393 * @return string
394 */
395 function get_raw_slug() {
396 return $this->_menu_slug;
397 }
398
399 /**
400 * Get plugin's original menu slug.
401 *
402 * @author Vova Feldman (@svovaf)
403 * @since 1.1.3
404 *
405 * @return string
406 */
407 function get_original_menu_slug() {
408 if ( 'cpt' === $this->_type ) {
409 return add_query_arg( array(
410 'post_type' => $this->_menu_slug
411 ), 'edit.php' );
412 }
413
414 if ( false === strpos( $this->_menu_slug, '.php?' ) ) {
415 return $this->_menu_slug;
416 } else {
417 return $this->_module_unique_affix;
418 }
419 }
420
421 /**
422 * @author Vova Feldman (@svovaf)
423 * @since 1.1.3
424 *
425 * @return string
426 */
427 function get_top_level_menu_slug() {
428 return $this->has_custom_parent() ?
429 $this->get_parent_slug() :
430 $this->get_raw_slug();
431 }
432
433 /**
434 * Is user on plugin's admin activation page.
435 *
436 * @author Vova Feldman (@svovaf)
437 * @since 1.0.8
438 *
439 * @return bool
440 */
441 function is_main_settings_page() {
442 if ( $this->_menu_exists &&
443 ( fs_is_plugin_page( $this->_menu_slug ) || fs_is_plugin_page( $this->_module_unique_affix ) )
444 ) {
445 /**
446 * Module has a settings menu and the context page is the main settings page, so assume it's in
447 * activation (doesn't really check if already opted-in/skipped or not).
448 *
449 * @since 1.2.2
450 */
451 return true;
452 }
453
454 global $pagenow;
455 if ( ( WP_FS__MODULE_TYPE_THEME === $this->_module_type ) && Freemius::is_themes_page() ) {
456 /**
457 * In activation only when show_optin query string param is given.
458 *
459 * @since 1.2.2
460 */
461 return fs_request_get_bool( $this->_module_unique_affix . '_show_optin' );
462 }
463
464 return false;
465 }
466
467 #region Submenu Override
468
469 /**
470 * Override submenu's action.
471 *
472 * @author Vova Feldman (@svovaf)
473 * @since 1.1.0
474 *
475 * @param string $parent_slug
476 * @param string $menu_slug
477 * @param callable $function
478 *
479 * @return false|string If submenu exist, will return the hook name.
480 */
481 function override_submenu_action( $parent_slug, $menu_slug, $function ) {
482 global $submenu;
483
484 $menu_slug = plugin_basename( $menu_slug );
485 $parent_slug = plugin_basename( $parent_slug );
486
487 if ( ! isset( $submenu[ $parent_slug ] ) ) {
488 // Parent menu not exist.
489 return false;
490 }
491
492 $found_submenu_item = false;
493 foreach ( $submenu[ $parent_slug ] as $submenu_item ) {
494 if ( $menu_slug === $submenu_item[2] ) {
495 $found_submenu_item = $submenu_item;
496 break;
497 }
498 }
499
500 if ( false === $found_submenu_item ) {
501 // Submenu item not found.
502 return false;
503 }
504
505 // Remove current function.
506 $hookname = get_plugin_page_hookname( $menu_slug, $parent_slug );
507 remove_all_actions( $hookname );
508
509 // Attach new action.
510 add_action( $hookname, $function );
511
512 return $hookname;
513 }
514
515 #endregion Submenu Override
516
517 #region Top level menu Override
518
519 /**
520 * Find plugin's admin dashboard main menu item.
521 *
522 * @author Vova Feldman (@svovaf)
523 * @since 1.0.2
524 *
525 * @return string[]|false
526 */
527 private function find_top_level_menu() {
528 global $menu;
529
530 $position = - 1;
531 $found_menu = false;
532
533 $menu_slug = $this->get_raw_slug();
534
535 $hook_name = get_plugin_page_hookname( $menu_slug, '' );
536 foreach ( $menu as $pos => $m ) {
537 if ( $menu_slug === $m[2] ) {
538 $position = $pos;
539 $found_menu = $m;
540 break;
541 }
542 }
543
544 if ( false === $found_menu ) {
545 return false;
546 }
547
548 return array(
549 'menu' => $found_menu,
550 'position' => $position,
551 'hook_name' => $hook_name
552 );
553 }
554
555 /**
556 * Find plugin's admin dashboard main submenu item.
557 *
558 * @author Vova Feldman (@svovaf)
559 * @since 1.2.1.6
560 *
561 * @return array|false
562 */
563 private function find_main_submenu() {
564 global $submenu;
565
566 $top_level_menu_slug = $this->get_top_level_menu_slug();
567
568 if ( ! isset( $submenu[ $top_level_menu_slug ] ) ) {
569 return false;
570 }
571
572 $submenu_slug = $this->get_raw_slug();
573
574 $position = - 1;
575 $found_submenu = false;
576
577 $hook_name = get_plugin_page_hookname( $submenu_slug, '' );
578
579 foreach ( $submenu[ $top_level_menu_slug ] as $pos => $sub ) {
580 if ( $submenu_slug === $sub[2] ) {
581 $position = $pos;
582 $found_submenu = $sub;
583 }
584 }
585
586 if ( false === $found_submenu ) {
587 return false;
588 }
589
590 return array(
591 'menu' => $found_submenu,
592 'parent_slug' => $top_level_menu_slug,
593 'position' => $position,
594 'hook_name' => $hook_name
595 );
596 }
597
598 /**
599 * Remove all sub-menu items.
600 *
601 * @author Vova Feldman (@svovaf)
602 * @since 1.0.7
603 *
604 * @return bool If submenu with plugin's menu slug was found.
605 */
606 private function remove_all_submenu_items() {
607 global $submenu;
608
609 $menu_slug = $this->get_raw_slug();
610
611 if ( ! isset( $submenu[ $menu_slug ] ) ) {
612 return false;
613 }
614
615 /**
616 * This method is NOT executed for WordPress.org themes.
617 * Since we maintain only one version of the SDK we added this small
618 * hack to avoid the error from Theme Check since it's a false-positive.
619 *
620 * @author Vova Feldman (@svovaf)
621 * @since 1.2.2.7
622 */
623 $submenu_ref = &$submenu;
624 $submenu_ref[ $menu_slug ] = array();
625
626 return true;
627 }
628
629 /**
630 *
631 * @author Vova Feldman (@svovaf)
632 * @since 1.0.9
633 *
634 * @param bool $remove_top_level_menu
635 *
636 * @return false|array[string]mixed
637 */
638 function remove_menu_item( $remove_top_level_menu = false ) {
639 $this->_logger->entrance();
640
641 // Find main menu item.
642 $top_level_menu = $this->find_top_level_menu();
643
644 if ( false === $top_level_menu ) {
645 return false;
646 }
647
648 // Remove it with its actions.
649 remove_all_actions( $top_level_menu['hook_name'] );
650
651 // Remove all submenu items.
652 $this->remove_all_submenu_items();
653
654 if ( $remove_top_level_menu ) {
655 global $menu;
656 unset( $menu[ $top_level_menu['position'] ] );
657 }
658
659 return $top_level_menu;
660 }
661
662 /**
663 * Get module's main admin setting page URL.
664 *
665 * @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.
666 *
667 * @author Vova Feldman (@svovaf)
668 * @since 1.2.2.7
669 *
670 * @return string
671 */
672 function main_menu_url() {
673 $this->_logger->entrance();
674
675 if ( $this->_is_top_level ) {
676 $menu = $this->find_top_level_menu();
677 } else {
678 $menu = $this->find_main_submenu();
679 }
680
681 $parent_slug = isset( $menu['parent_slug'] ) ?
682 $menu['parent_slug'] :
683 'admin.php';
684
685 return admin_url( $parent_slug . '?page=' . $menu['menu'][2] );
686 }
687
688 /**
689 * @author Vova Feldman (@svovaf)
690 * @since 1.1.4
691 *
692 * @param callable $function
693 *
694 * @return false|array[string]mixed
695 */
696 function override_menu_item( $function ) {
697 $found_menu = $this->remove_menu_item();
698
699 if ( false === $found_menu ) {
700 return false;
701 }
702
703 if ( ! $this->is_top_level() || ! $this->is_cpt() ) {
704 $menu_slug = plugin_basename( $this->get_slug() );
705
706 $hookname = get_plugin_page_hookname( $menu_slug, '' );
707
708 // Override menu action.
709 add_action( $hookname, $function );
710 } else {
711 global $menu;
712
713 // Remove original CPT menu.
714 unset( $menu[ $found_menu['position'] ] );
715
716 // Create new top-level menu action.
717 $hookname = self::add_page(
718 $found_menu['menu'][3],
719 $found_menu['menu'][0],
720 'manage_options',
721 $this->get_slug(),
722 $function,
723 $found_menu['menu'][6],
724 $found_menu['position']
725 );
726 }
727
728 return $hookname;
729 }
730
731 /**
732 * Adds a counter to the module's top level menu item.
733 *
734 * @author Vova Feldman (@svovaf)
735 * @since 1.2.1.5
736 *
737 * @param int $counter
738 * @param string $class
739 */
740 function add_counter_to_menu_item( $counter = 1, $class = '' ) {
741 global $menu, $submenu;
742
743 $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>';
744
745 /**
746 * This method is NOT executed for WordPress.org themes.
747 * Since we maintain only one version of the SDK we added this small
748 * hack to avoid the error from Theme Check since it's a false-positive.
749 *
750 * @author Vova Feldman (@svovaf)
751 * @since 1.2.2.7
752 */
753 $menu_ref = &$menu;
754 $submenu_ref = &$submenu;
755
756 if ( $this->_is_top_level ) {
757 // Find main menu item.
758 $found_menu = $this->find_top_level_menu();
759
760 if ( false !== $found_menu ) {
761 // Override menu label.
762 $menu_ref[ $found_menu['position'] ][0] = sprintf(
763 $mask,
764 $found_menu['menu'][0],
765 $class,
766 $counter
767 );
768 }
769 } else {
770 $found_submenu = $this->find_main_submenu();
771
772 if ( false !== $found_submenu ) {
773 // Override menu label.
774 $submenu_ref[ $found_submenu['parent_slug'] ][ $found_submenu['position'] ][0] = sprintf(
775 $mask,
776 $found_submenu['menu'][0],
777 $class,
778 $counter
779 );
780 }
781 }
782 }
783
784 #endregion Top level menu Override
785
786 /**
787 * Add a top-level menu page.
788 *
789 * Note for WordPress.org Theme/Plugin reviewer:
790 *
791 * This is a replication of `add_menu_page()` to avoid Theme Check warning.
792 *
793 * Why?
794 * ====
795 * Freemius is an SDK for plugin and theme developers. Since the core
796 * of the SDK is relevant both for plugins and themes, for obvious reasons,
797 * we only develop and maintain one code base.
798 *
799 * This method will not run for wp.org themes (only plugins) since theme
800 * admin settings/options are now only allowed in the customizer.
801 *
802 * If you have any questions or need clarifications, please don't hesitate
803 * pinging me on slack, my username is @svovaf.
804 *
805 * @author Vova Feldman (@svovaf)
806 * @since 1.2.2
807 *
808 * @param string $page_title The text to be displayed in the title tags of the page when the menu is
809 * selected.
810 * @param string $menu_title The text to be used for the menu.
811 * @param string $capability The capability required for this menu to be displayed to the user.
812 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
813 * @param callable|string $function The function to be called to output the content for this page.
814 * @param string $icon_url The URL to the icon to be used for this menu.
815 * * Pass a base64-encoded SVG using a data URI, which will be colored to
816 * match the color scheme. This should begin with
817 * 'data:image/svg+xml;base64,'.
818 * * Pass the name of a Dashicons helper class to use a font icon,
819 * e.g. 'dashicons-chart-pie'.
820 * * Pass 'none' to leave div.wp-menu-image empty so an icon can be added
821 * via CSS.
822 * @param int $position The position in the menu order this one should appear.
823 *
824 * @return string The resulting page's hook_suffix.
825 */
826 static function add_page(
827 $page_title,
828 $menu_title,
829 $capability,
830 $menu_slug,
831 $function = '',
832 $icon_url = '',
833 $position = null
834 ) {
835 $fn = 'add_menu' . '_page';
836
837 return $fn(
838 $page_title,
839 $menu_title,
840 $capability,
841 $menu_slug,
842 $function,
843 $icon_url,
844 $position
845 );
846 }
847
848 /**
849 * Add page and update menu instance settings.
850 *
851 * @author Vova Feldman (@svovaf)
852 * @since 2.0.0
853 *
854 * @param string $page_title
855 * @param string $menu_title
856 * @param string $capability
857 * @param string $menu_slug
858 * @param callable|string $function
859 * @param string $icon_url
860 * @param int|null $position
861 *
862 * @return string
863 */
864 function add_page_and_update(
865 $page_title,
866 $menu_title,
867 $capability,
868 $menu_slug,
869 $function = '',
870 $icon_url = '',
871 $position = null
872 ) {
873 $this->_menu_slug = $menu_slug;
874 $this->_is_top_level = true;
875 $this->_menu_exists = true;
876 $this->_network_menu_exists = true;
877
878 return self::add_page(
879 $page_title,
880 $menu_title,
881 $capability,
882 $menu_slug,
883 $function,
884 $icon_url,
885 $position
886 );
887 }
888
889 /**
890 * Add a submenu page.
891 *
892 * Note for WordPress.org Theme/Plugin reviewer:
893 *
894 * This is a replication of `add_submenu_page()` to avoid Theme Check warning.
895 *
896 * Why?
897 * ====
898 * Freemius is an SDK for plugin and theme developers. Since the core
899 * of the SDK is relevant both for plugins and themes, for obvious reasons,
900 * we only develop and maintain one code base.
901 *
902 * This method will not run for wp.org themes (only plugins) since theme
903 * admin settings/options are now only allowed in the customizer.
904 *
905 * If you have any questions or need clarifications, please don't hesitate
906 * pinging me on slack, my username is @svovaf.
907 *
908 * @author Vova Feldman (@svovaf)
909 * @since 1.2.2
910 *
911 * @param string $parent_slug The slug name for the parent menu (or the file name of a standard
912 * WordPress admin page).
913 * @param string $page_title The text to be displayed in the title tags of the page when the menu is
914 * selected.
915 * @param string $menu_title The text to be used for the menu.
916 * @param string $capability The capability required for this menu to be displayed to the user.
917 * @param string $menu_slug The slug name to refer to this menu by (should be unique for this menu).
918 * @param callable|string $function The function to be called to output the content for this page.
919 *
920 * @return false|string The resulting page's hook_suffix, or false if the user does not have the capability
921 * required.
922 */
923 static function add_subpage(
924 $parent_slug,
925 $page_title,
926 $menu_title,
927 $capability,
928 $menu_slug,
929 $function = ''
930 ) {
931 $fn = 'add_submenu' . '_page';
932
933 return $fn( $parent_slug,
934 $page_title,
935 $menu_title,
936 $capability,
937 $menu_slug,
938 $function
939 );
940 }
941
942 /**
943 * Add sub page and update menu instance settings.
944 *
945 * @author Vova Feldman (@svovaf)
946 * @since 2.0.0
947 *
948 * @param string $parent_slug
949 * @param string $page_title
950 * @param string $menu_title
951 * @param string $capability
952 * @param string $menu_slug
953 * @param callable|string $function
954 *
955 * @return string
956 */
957 function add_subpage_and_update(
958 $parent_slug,
959 $page_title,
960 $menu_title,
961 $capability,
962 $menu_slug,
963 $function = ''
964 ) {
965 $this->_menu_slug = $menu_slug;
966 $this->_parent_slug = $parent_slug;
967 $this->_is_top_level = false;
968 $this->_menu_exists = true;
969 $this->_network_menu_exists = true;
970
971 return self::add_subpage(
972 $parent_slug,
973 $page_title,
974 $menu_title,
975 $capability,
976 $menu_slug,
977 $function
978 );
979 }
980 }