AdminPageFramework_Model_Menu__RegisterMenu   B
last analyzed

Complexity

Total Complexity 44

Size/Duplication

Total Lines 590
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 44
eloc 204
dl 0
loc 590
rs 8.8798
c 0
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A _setSubMenuPageByIndex() 0 9 1
A _replyToRemoveRootMenuPage() 0 23 3
A _getDefaultPageSlug() 0 9 3
A _registerSubMenuItem() 0 34 4
A _setPageHooks() 0 39 2
A _removePageSubmenuItem() 0 19 1
A _getSubMenuPageIndex() 0 26 4
A _addLinkSubmenuItem() 0 25 2
A _isCurrentPage() 0 2 1
A _removePageSubMenuItemByIndex() 0 10 1
A ___addSubMenuPage() 0 17 2
A __construct() 0 29 2
A _getRootMenuSlug() 0 7 2
A _addPageSubmenuItem() 0 51 5
A _replyToRegisterSubMenuItems() 0 34 3
A _replyToLoadPageForAjax() 0 13 4
A _replyToRegisterRootMenu() 0 7 2
A _registerRootMenuPage() 0 18 2

How to fix   Complexity   

Complex Class

Complex classes like AdminPageFramework_Model_Menu__RegisterMenu often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AdminPageFramework_Model_Menu__RegisterMenu, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Admin Page Framework
4
 *
5
 * http://admin-page-framework.michaeluno.jp/
6
 * Copyright (c) 2013-2022, Michael Uno; Licensed MIT
7
 *
8
 */
9
10
/**
11
 * Provides methods to register an admin sidebar menu item.
12
 *
13
 * @since           3.7.4
14
 * @extends         AdminPageFramework_Controller_Page
15
 * @package         AdminPageFramework/Factory/AdminPage/Model
16
 * @internal
17
 */
18
class AdminPageFramework_Model_Menu__RegisterMenu extends AdminPageFramework_FrameworkUtility {
19
20
    /**
21
     * Stores a factory object.
22
     */
23
    public $oFactory;
24
25
    /**
26
     * Sets up hooks
27
     *
28
     * @internal
29
     */
30
    public function __construct( $oFactory, $sActionHook='admin_menu' ) {
31
32
        $this->oFactory = $oFactory;
33
        add_action(
34
            $sActionHook,
35
            array( $this, '_replyToRegisterRootMenu' ),
36
            98      // this is below the value set in the `AdminPageFramework_Property_page_meta_box` class.
37
        );
38
        add_action(
39
            $sActionHook,
40
            array( $this, '_replyToRegisterSubMenuItems' ),
41
            99
42
        );
43
        add_action(
44
            $sActionHook,
45
            array( $this, '_replyToRemoveRootMenuPage' ),
46
            100
47
        );
48
49
        add_action(
50
            $sActionHook,
51
            array( $this, 'sortAdminSubMenu' ), // defined in the framework utility class.
52
            9999
53
        );
54
55
        // Stores sub-menu items to sort.
56
        $GLOBALS[ '_apf_sub_menus_to_sort' ] = isset( $GLOBALS[ '_apf_sub_menus_to_sort' ] )
57
            ? $GLOBALS[ '_apf_sub_menus_to_sort' ]
58
            : array();
59
60
    }
61
62
63
    /**
64
     * Builds the sidebar menu of the added pages.
65
     *
66
     * @since       2.0.0
67
     * @since       3.1.1       Moved from `AdminPageFramework_Menu`.
68
     * @since       3.7.4       Moved from `AdminPageFramework_Model_Menu`. Changed the name from `_replyToBuildMenu()`.
69
     * @since       3.8.3       Renamed from `_replyToRegisterMenu`.
70
     * @callback    action      admin_menu
71
     * @internal
72
     * @uses        remove_submenu_page
73
     */
74
    public function _replyToRegisterRootMenu() {
75
76
        // If the root menu label is not set but the slug is set,
77
        if ( ! $this->oFactory->oProp->aRootMenu[ 'fCreateRoot' ] ) {
78
            return;
79
        }
80
        $this->_registerRootMenuPage();
81
82
    }
83
        /**
84
         * Registers the root menu page.
85
         *
86
         * @since       2.0.0
87
         * @since       3.1.1       Moved from `AdminPageFramework_Menu`.
88
         * @internal
89
         * @uses        add_menu_page
90
         */
91
        private function _registerRootMenuPage() {
92
93
            if ( $this->oFactory->oProp->bIsAdminAjax ) {
94
                $this->oFactory->oProp->aRootMenu[ '_page_hook' ] = $this->oFactory->oProp->sClassName;
95
                return;
96
            }
97
98
            $this->oFactory->oProp->aRootMenu[ '_page_hook' ] = add_menu_page(
99
                $this->oFactory->oProp->sClassName,                 // Page title - will be invisible anyway
100
                $this->oFactory->oProp->aRootMenu[ 'sTitle' ],      // Menu title - should be the root page title.
101
                $this->oFactory->oProp->sCapability,                // Capability - access right
102
                $this->oFactory->oProp->aRootMenu[ 'sPageSlug' ],   // Menu ID
103
                '',                                       // Callback function for the page content output - the root page will be removed so no need to register a function.
104
                $this->oFactory->oProp->aRootMenu[ 'sIcon16x16' ],  // icon path
105
                $this->getElement(
106
                    $this->oFactory->oProp->aRootMenu,
107
                    'iPosition',
108
                    null
109
                )  // menu position
110
            );
111
112
        }
113
114
    /**
115
     * Registers sub-menu items.
116
     *
117
     * @since       3.8.3
118
     * @callback    action      admin_menu
119
     * @internal
120
     * @uses        remove_submenu_page
121
     */
122
    public function _replyToRegisterSubMenuItems() {
123
124
        // Let external scripts add sub-menu pages.
125
        $_aPages = $this->addAndApplyFilter(
126
            $this->oFactory,    // caller object
127
            "pages_{$this->oFactory->oProp->sClassName}",   // filter
128
            $this->oFactory->oProp->aPages  // arguments
129
        );
130
131
        // Set the default page, the first element.
132
        $this->oFactory->oProp->sDefaultPageSlug = $this->_getDefaultPageSlug( $_aPages );
133
134
        // Format the `$aPages` property and register the pages.
135
        $_iParsedIndex    = 0;
136
        $_aFormattedPages = array();
137
        foreach( $_aPages as $_aSubMenuItem ) {
138
139
            // needs to be sanitized because there are hook filters applied to this array.
140
            $_oFormatter = new AdminPageFramework_Format_SubMenuItem(
141
                $_aSubMenuItem,
142
                $this->oFactory,
143
                ++$_iParsedIndex
144
            );
145
            $_aSubMenuItem = $_oFormatter->get();
146
147
            // store the page hook; this is same as the value stored in the global $page_hook or $hook_suffix variable.
148
            $_aSubMenuItem[ '_page_hook' ] = $this->_registerSubMenuItem( $_aSubMenuItem );
149
            $_sKey = isset( $_aSubMenuItem[ 'href' ] )
150
                ? $_aSubMenuItem[ 'href' ]
151
                : $_aSubMenuItem[ 'page_slug' ];
152
            $_aFormattedPages[ $_sKey ] = $_aSubMenuItem;
153
154
        }
155
        $this->oFactory->oProp->aPages = $_aFormattedPages;
156
157
    }
158
159
        /**
160
         * Sets the default page.
161
         *
162
         * The first item of the added pages.
163
         *
164
         * @internal
165
         * @since       3.6.0
166
         * @since       3.8.3       Changed it to receive a pages definition array and return the found page slug.
167
         * @since       3.8.3       Renamed from `_setDefaultPage`.
168
         * @return      string
169
         */
170
        private function _getDefaultPageSlug( array $aPages ) {
171
172
            foreach( $aPages as $_aPage ) {
173
                if ( ! isset( $_aPage[ 'page_slug' ] ) ) {
174
                    continue;
175
                }
176
                return $_aPage[ 'page_slug' ];
177
            }
178
            return '';
179
180
        }
181
182
        /**
183
         * Registers the sub-menu item.
184
         *
185
         * @since       2.0.0
186
         * @since       3.0.0       Changed the name from `registerSubMenuPage()`.
187
         * @since       3.1.1       Moved from `AdminPageFramework_Menu`.
188
         * @remark      The sub menu page slug should be unique because `add_submenu_page()` can add one callback per page slug.
189
         * @remark      Assumes the argument array is already formatted.
190
         * @internal
191
         * @return      string      The page hook if the page is added.
192
         */
193
        private function _registerSubMenuItem( array $aArgs ) {
194
195
            if ( ! current_user_can( $aArgs[ 'capability' ] ) ) {
196
                return '';
197
            }
198
199
            $_sRootPageSlug = $this->oFactory->oProp->aRootMenu[ 'sPageSlug' ];
200
            $_sRootMenuSlug = $this->_getRootMenuSlug( $_sRootPageSlug );
201
202
            // It is possible that the page_slug key is not set if the user uses a method like setPageHeadingTabsVisibility() prior to addSubMenuItam().
203
            if ( 'page' === $aArgs[ 'type' ] ) {
204
                return $this->_addPageSubmenuItem(
205
                    $_sRootPageSlug,
206
                    $_sRootMenuSlug,
207
                    $aArgs[ 'page_slug' ],
208
                    $this->getElement( $aArgs, 'page_title', $aArgs[ 'title' ] ),
209
                    $this->getElement( $aArgs, 'menu_title', $aArgs[ 'title' ] ),
210
                    $aArgs[ 'capability' ],
211
                    $aArgs[ 'show_in_menu' ],
212
                    $aArgs[ 'order' ]
213
                );
214
            }
215
            if ( 'link' === $aArgs[ 'type' ] ) {
216
                return $this->_addLinkSubmenuItem(
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->_addLinkSubmenuIt...enu'], $aArgs['order']) targeting AdminPageFramework_Model...::_addLinkSubmenuItem() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
Bug Best Practice introduced by
The expression return $this->_addLinkSu...enu'], $aArgs['order']) returns the type void which is incompatible with the documented return type string.
Loading history...
217
                    $_sRootMenuSlug,
218
                    $aArgs[ 'title' ],
219
                    $aArgs[ 'capability' ],
220
                    $aArgs[ 'href' ],
221
                    $aArgs[ 'show_in_menu' ],
222
                    $aArgs[ 'order' ]
223
                );
224
            }
225
226
            return '';
227
228
        }
229
            /**
230
             * @remark      To be compatible with `add_submenu_page()`
231
             * @since       3.7.10
232
             * @return      string
233
             * @uses        plugin_basename
234
             */
235
            private function _getRootMenuSlug( $sRootPageSlug ) {
236
237
                if ( isset( self::$_aRootMenuSlugCache[ $sRootPageSlug ] ) ) {
238
                    return self::$_aRootMenuSlugCache[ $sRootPageSlug ];
239
                }
240
                self::$_aRootMenuSlugCache[ $sRootPageSlug ] = plugin_basename( $sRootPageSlug );
241
                return self::$_aRootMenuSlugCache[ $sRootPageSlug ];
242
243
            }
244
                /**
245
                 * @since       3.7.10
246
                 */
247
                static private $_aRootMenuSlugCache = array();
248
249
            /**
250
             * Adds a page sub-menu item.
251
             *
252
             * @since       3.3.0
253
             * @since       3.1.1       Moved from `AdminPageFramework_Menu`.
254
             * @since       3.7.4       Added the `$nOrder` parameter.
255
             * @return      string      The page hook of the added page.
256
             */
257
            private function _addPageSubmenuItem( $sRootPageSlug, $sMenuSlug, $sPageSlug, $sPageTitle, $sMenuTitle, $sCapability, $bShowInMenu, $nOrder ) {
258
259
                if ( ! $sPageSlug ) {
260
                    return '';
261
                }
262
                $_sPageHook = $this->___addSubMenuPage(
263
                    $sRootPageSlug,         // the root (parent) page slug
264
                    $sPageTitle,            // page title
265
                    $sMenuTitle,            // menu title
266
                    $sCapability,           // capability
267
                    $sPageSlug              // menu slug
268
                );
269
270
//                $_sPageHook = add_submenu_page(
271
//                    $sRootPageSlug,         // the root (parent) page slug
272
//                    $sPageTitle,            // page title
273
//                    $sMenuTitle,            // menu title
274
//                    $sCapability,           // capability
275
//                    $sPageSlug,             // menu slug
276
//                    array( $this->oFactory, '_replyToRenderPage' )  // callback 3.7.10+
277
//                );
278
                $this->_setPageHooks( $_sPageHook, $sPageSlug );
279
280
                // Now we are going to remove the added sub-menu from the WordPress global variable.
281
                $_nSubMenuPageIndex = $this->_getSubMenuPageIndex(
282
                    $sMenuSlug,
283
                    $sMenuTitle,
284
                    $sPageTitle,
285
                    $sPageSlug
286
                );
287
                if ( null === $_nSubMenuPageIndex ) {
288
                    return $_sPageHook;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $_sPageHook could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
289
                }
290
291
                $_aRemovedMenuItem = $this->_removePageSubmenuItem( $_nSubMenuPageIndex, $sMenuSlug, $sPageSlug, $sMenuTitle );
292
293
                // If the visibility option is `false`, remove the one just added from the sub-menu global array
294
                if ( ! $bShowInMenu && ! $this->_isCurrentPage( $sPageSlug ) ) {
295
                    return $_sPageHook;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $_sPageHook could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
296
                }
297
298
                // Set the order index in the element of the `submenu` global array.
299
                $this->_setSubMenuPageByIndex(
300
                    $nOrder,                // user-set order
301
                    $_aRemovedMenuItem,     // will be reassign with a new index
302
                    $sMenuSlug
303
                );
304
305
                // Update the property for sorting.
306
                $GLOBALS[ '_apf_sub_menus_to_sort' ][ $sMenuSlug ] = $sMenuSlug;
307
                return $_sPageHook;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $_sPageHook could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
308
309
            }
310
311
                /**
312
                 * @param       string $sRootPageSlug
313
                 * @param       string $sPageTitle
314
                 * @param       string $sMenuTitle
315
                 * @param       string $sCapability
316
                 * @param       string $sPageSlug
317
                 * @since       3.8.14
318
                 * @return      false|string
319
                 * @uses        add_submenu_page
320
                 */
321
                private function ___addSubMenuPage(
322
                    $sRootPageSlug,         // the root (parent) page slug
323
                    $sPageTitle,            // page title
324
                    $sMenuTitle,            // menu title
325
                    $sCapability,           // capability
326
                    $sPageSlug              // menu slug
327
                ) {
328
                    if ( $this->oFactory->oProp->bIsAdminAjax ) {
329
                        return $sPageSlug;
330
                    }
331
                    return add_submenu_page(
332
                        $sRootPageSlug,         // the root (parent) page slug
333
                        $sPageTitle,            // page title
334
                        $sMenuTitle,            // menu title
335
                        $sCapability,           // capability
336
                        $sPageSlug,             // menu slug
337
                        array( $this->oFactory, '_replyToRenderPage' )  // callback 3.7.10+
338
                    );
339
                }
340
                /**
341
                 * Checks whether the given page slug is of the currently loading page.
342
                 *
343
                 * Used to decide whether the menu item of the current hidden page should be shown.
344
                 * Currently, the menu will be displayed even it is a hidden menu page item if it is the currently loading page.
345
                 * @return      boolean
346
                 * @since       3.7.4
347
                 */
348
                private function _isCurrentPage( $sPageSlug ) {
349
                    return $sPageSlug === $this->getElement( $this->oFactory->oProp->aQuery, 'page' );
350
                }
351
352
                /**
353
                 * Sets up hooks for the page.
354
                 * @since       3.7.4
355
                 */
356
                private function _setPageHooks( $sPageHook, $sPageSlug ) {
357
358
                    // Ensure only it is added one time per page slug.
359
                    if ( isset( $this->oFactory->oProp->aPageHooks[ $sPageHook ] ) ) {
360
                        return;
361
                    }
362
363
                    /**
364
                     * Give a lower priority as the page meta box class also hooks the current_screen to register form elements.
365
                     * When the validation callback is triggered, their form registration should be done already. So this hook should be loaded later than them.
366
                     * @since       3.4.1
367
                     */
368
                    add_action(
369
                        'current_screen',
370
                        array( $this->oFactory, "load_pre_" . $sPageSlug ),
371
                        20
372
                    );
373
                    /**
374
                     * For Ajax calls.
375
                     * @since       3.8.14
376
                     * @since       3.8.22  Change the action to `pseudo_current_screen_{$sPageSlug}` from `pseudo_current_screen` to avoid overload in `admin-ajax.php`.
377
                     */
378
                    add_action( "pseudo_current_screen_{$sPageSlug}", array( $this, '_replyToLoadPageForAjax' ), 20 ); // 3.8.22
379
380
                    /**
381
                     * It is possible that an in-page tab is added during the above hooks and the current page is the default tab without the tab GET query key in the url.
382
                     * Set a low priority because the user may add in-page tabs in their callback method of this action hook.
383
                     * @since       3.6.3
384
                     */
385
                    add_action( "load_" . $sPageSlug, array( $this->oFactory, '_replyToFinalizeInPageTabs' ), 9999 );
386
387
                    // 3.6.3+
388
                    add_action( "load_after_" . $sPageSlug, array( $this->oFactory, '_replyToEnqueuePageAssets' ) );
389
                    add_action( "load_after_" . $sPageSlug, array( $this->oFactory, '_replyToEnablePageMetaBoxes' ) );  // 3.7.10+
390
391
                    $this->oFactory->oProp->aPageHooks[ $sPageSlug ] = $this->getAOrB(
392
                        is_network_admin(),
393
                        $sPageHook . '-network',
394
                        $sPageHook
395
                    );
396
397
                }
398
399
400
                /**
401
                 * @since       3.7.4
402
                 * @return      void
403
                 * @param       numeric     $$nOrder            A user set order (menu position, index).
0 ignored issues
show
Bug introduced by
The type numeric was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
404
                 * @param       array       $aSubMenuItem       The sub menu item array set in the global `$submenu` array.
405
                 */
406
                private function _setSubMenuPageByIndex( $nOrder, $aSubMenuItem, $sMenuSlug ) {
407
408
                    $_nNewIndex = $this->getUnusedNumericIndex(
409
                        $this->getElementAsArray( $GLOBALS, array( 'submenu', $sMenuSlug ) ), // subject array to parser
410
                        $nOrder,    // a desired menu position
411
                        5           // offset
412
                    );
413
414
                    $GLOBALS[ 'submenu' ][ $sMenuSlug ][ $_nNewIndex ] = $aSubMenuItem;
415
416
                }
417
418
                /**
419
                 * Finds the sub-menu page index of the given menu slug by menu and page title.
420
                 * @return      numeric|null
421
                 */
422
                private function _getSubMenuPageIndex( $sMenuSlug, $sMenuTitle, $sPageTitle, $sPageSlug ) {
423
424
                    foreach( $this->getElementAsArray( $GLOBALS, array( 'submenu', $sMenuSlug ) ) as $_iIndex => $_aSubMenu ) {
425
426
                        if ( ! isset( $_aSubMenu[ 3 ] ) ) {
427
                            continue;
428
                        }
429
430
                        // the array structure is defined in plugin.php - $submenu[$parent_slug][] = array ( $menu_title, $capability, $menu_slug, $page_title )
431
                        $_aA = array(
432
                            $_aSubMenu[ 0 ],
433
                            $_aSubMenu[ 3 ],
434
                            $_aSubMenu[ 2 ],
435
                        );
436
                        $_aB = array(
437
                            $sMenuTitle,
438
                            $sPageTitle,
439
                            $sPageSlug,
440
                        );
441
                        if ( $_aA !== $_aB ) {
442
                            continue;
443
                        }
444
                        return $_iIndex;
445
446
                    }
447
                    return null;
448
449
                }
450
451
                /**
452
                 * Removes a page sub-menu item.
453
                 *
454
                 * @since       3.3.0
455
                 * @since       3.1.1       Moved from `AdminPageFramework_Menu`. Chagned the return type.
456
                 * @return      array       removed menu item.
457
                 */
458
                private function _removePageSubmenuItem( $nSubMenuPageIndex, $sMenuSlug, $sPageSlug, $sMenuTitle ){
459
460
                    $_aRemovedMenuItem = $this->_removePageSubMenuItemByIndex(
461
                        $nSubMenuPageIndex,
462
                        $sMenuSlug,
463
                        $sPageSlug
464
                    );
465
466
                    // The page title in the browser window title bar will miss the page title as this is left as it is.
467
                    $this->oFactory->oProp->aHiddenPages[ $sPageSlug ] = $sMenuTitle;
468
                    // @deprecated 3.7.6 - the below function caused the page title to get doubled in the `<title>` tag.
469
                    /* add_filter(
470
                        'admin_title',
471
                        array( $this, '_replyToFixPageTitleForHiddenPages' ),
472
                        10,
473
                        2
474
                    ); */
475
476
                    return $_aRemovedMenuItem;
477
478
                }
479
480
                    /**
481
                     * A callback function for the admin_title filter to fix the page title for hidden pages.
482
                     *
483
                     * @since       2.1.4
484
                     * @since       3.1.1       Moved from `AdminPageFramework_Menu`.
485
                     * @internal
486
                     * @callback    filter      admin_title
487
                     * return       string
488
                     * @deprecated  3.7.6       Not sure what this was for. This caused the page title in the `<title>` tag to be doubled.
489
                     */
490
                    /* public function _replyToFixPageTitleForHiddenPages( $sAdminTitle, $sPageTitle ) {
491
492
                        if ( isset( $_GET[ 'page' ], $this->oFactory->oProp->aHiddenPages[ $_GET[ 'page' ] ] ) ) { // sanitization unnecessary
493
                            return $this->oFactory->oProp->aHiddenPages[ $this->oFactory->oUtil->getHTTPQueryGET( 'page', '' ) ] . $sAdminTitle;
494
                        }
495
                        return $sAdminTitle;
496
                    }   */
497
498
                    /**
499
                     * Remove the specified item from the menu.
500
                     *
501
                     * If the current page is being accessed, do not remove it from the menu.
502
                     *
503
                     * @since       3.5.3
504
                     * @since       3.7.4       Changed the parameter structure. Changed the return value.
505
                     * @return      array       the removed item.
506
                     * @internal
507
                     */
508
                    private function _removePageSubMenuItemByIndex( $_iIndex, $sMenuSlug, $sPageSlug ) {
509
510
                        // Extract the contents.
511
                        $_aSubMenuItem = $this->getElementAsArray(
512
                            $GLOBALS,
513
                            array( 'submenu', $sMenuSlug, $_iIndex )
514
                        );
515
516
                        unset( $GLOBALS[ 'submenu' ][ $sMenuSlug ][ $_iIndex ] );
517
                        return $_aSubMenuItem;
518
519
                    }
520
            /**
521
             * Adds a link sub-menu item.
522
             *
523
             * @since       3.3.0
524
             * @since       3.1.1       Moved from `AdminPageFramework_Menu`.
525
             * @since       3.5.3       Added the `$bShowInMenu` parameter.
526
             * @since       3.7.4       Added the `$nOrder` parameter.
527
             * @return      void
528
             */
529
            private function _addLinkSubmenuItem( $sMenuSlug, $sTitle, $sCapability, $sHref, $bShowInMenu, $nOrder ) {
530
531
                if ( ! $bShowInMenu ) {
532
                    return;
533
                }
534
535
                $_aSubMenuItems = $this->getElementAsArray(
536
                    $GLOBALS,
537
                    array( 'submenu', $sMenuSlug )
538
                );
539
540
                $_nIndex = $this->getUnusedNumericIndex(
541
                    $_aSubMenuItems,
542
                    $nOrder,
543
                    5   // offset
544
                );
545
                $_aSubMenuItems[ $_nIndex ] = array(
546
                    $sTitle,        // 0
547
                    $sCapability,   // 1
548
                    $sHref,         // 2
549
                );
550
                $GLOBALS[ 'submenu' ][ $sMenuSlug ] = $_aSubMenuItems;
551
552
                // Update the property for sorting.
553
                $GLOBALS[ '_apf_sub_menus_to_sort' ][ $sMenuSlug ] = $sMenuSlug;
554
555
            }
556
557
    /**
558
     * For loading admin-ajax.php, allow only items that add a page that matches currently loading page.
559
     * @since   3.8.22
560
     * @internal
561
     * @callback    action  pseudo_current_screen_{$sPageSlug}
562
     */
563
    public function _replyToLoadPageForAjax() {
564
        $_sCurrentPageSlug = $this->oFactory->oProp->getCurrentPageSlugIfAdded();
565
        if ( ! $_sCurrentPageSlug ) {
566
            return;
567
        }
568
        $_sCurrentTabSlug  = $this->oFactory->oProp->getCurrentInPageTabSlugIfAdded( $_sCurrentPageSlug );
569
        if (
570
            ! empty( $this->oFactory->oProp->aInPageTabs )      // it means at least one in-page tab is added
571
            && ! $_sCurrentTabSlug // the current tab could not be retrieved
572
        ) {
573
            return;
574
        }
575
        call_user_func_array( array( $this->oFactory, "load_pre_" . $_sCurrentPageSlug ), array() );
576
    }
577
578
    /**
579
     * Removes the root menu page which gets automatically added by the system.
580
     *
581
     * @since       3.8.3
582
     * @callback    action      admin_menu
583
     * @internal
584
     */
585
    public function _replyToRemoveRootMenuPage() {
586
587
        // After adding the sub menus, if the root menu is created, remove the page that is automatically created when registering the root menu.
588
        if ( ! $this->oFactory->oProp->aRootMenu[ 'fCreateRoot' ] ) {
589
            return;
590
        }
591
        if ( $this->oFactory->oProp->bIsAdminAjax ) {
592
            return;
593
        }
594
595
        /**
596
         * Namespace slugs have backslashes but the registered slugs backslashes are all converted to forward-slashes.
597
         * @since       3.5.16
598
         */
599
        $_sMenuSlug =             str_replace(
600
            '\\',
601
            '/',
602
            $this->oFactory->oProp->aRootMenu[ 'sPageSlug' ]
603
        );
604
605
        remove_submenu_page(
606
            $_sMenuSlug, // parent menu slug
607
            $_sMenuSlug // sub-menu slug
608
        );
609
610
    }
611
612
}
613