WordPress.org

Make WordPress Core

Ticket #33418: wp-admin-menu.diff

File wp-admin-menu.diff, 29.2 KB (added by wonderboymusic, 5 years ago)
  • src/wp-admin/menu.php

     
    1717 *     4: ID
    1818 *     5: Icon for top level menu
    1919 *
     20 * This class exposes the following globals $dynamically
     21 *
    2022 * @global array $menu
     23 * @global array $submenu
     24 * @global array $_wp_real_parent_file
     25 * @global array $compat
     26 * @global int   $_wp_last_object_menu
     27 * @global int   $_wp_last_utility_menu
    2128 */
     29class WP_Admin_Menu {
     30        public $menu;
     31        public $submenu;
     32        public $_wp_real_parent_file = array();
     33        public $compat;
     34        // The index of the last top-level menu in the object menu group
     35        public $_wp_last_object_menu = 25;
     36        // The index of the last top-level menu in the utility menu group
     37        public $_wp_last_utility_menu = 80;
    2238
    23 $menu[2] = array( __('Dashboard'), 'read', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'dashicons-dashboard' );
     39        private $appearance_cap;
     40        private $update_data;
    2441
    25 $submenu[ 'index.php' ][0] = array( __('Home'), 'read', 'index.php' );
     42        public function __construct( $export = true ) {
     43                $this->appearance_cap = current_user_can( 'switch_themes' ) ? 'switch_themes' : 'edit_theme_options';
     44                $this->update_data = wp_get_update_data();
    2645
    27 if ( is_multisite() ) {
    28         $submenu[ 'index.php' ][5] = array( __('My Sites'), 'read', 'my-sites.php' );
    29 }
     46                $this->compat = $this->get_compat();
     47                $this->_wp_real_parent_file = $this->get_top_level_back_compat();
    3048
    31 if ( ! is_multisite() || is_super_admin() )
    32         $update_data = wp_get_update_data();
     49                $this->menu = $this->get_top_level();
    3350
    34 if ( ! is_multisite() ) {
    35         if ( current_user_can( 'update_core' ) )
    36                 $cap = 'update_core';
    37         elseif ( current_user_can( 'update_plugins' ) )
    38                 $cap = 'update_plugins';
    39         else
    40                 $cap = 'update_themes';
    41         $submenu[ 'index.php' ][10] = array( sprintf( __('Updates %s'), "<span class='update-plugins count-{$update_data['counts']['total']}' title='{$update_data['title']}'><span class='update-count'>" . number_format_i18n($update_data['counts']['total']) . "</span></span>" ), $cap, 'update-core.php');
    42         unset( $cap );
    43 }
     51                foreach ( $this->menu as $top_level ) {
     52                        // [2] is URL, example: index.php
     53                        $this->add_submenu( $top_level[2] );
     54                }
    4455
    45 $menu[4] = array( '', 'read', 'separator1', '', 'wp-menu-separator' );
     56                $this->add_post_type_menus();
    4657
    47 $menu[5] = array( __('Posts'), 'edit_posts', 'edit.php', '', 'open-if-no-js menu-top menu-icon-post', 'menu-posts', 'dashicons-admin-post' );
    48         $submenu['edit.php'][5]  = array( __('All Posts'), 'edit_posts', 'edit.php' );
    49         /* translators: add new post */
    50         $submenu['edit.php'][10]  = array( _x('Add New', 'post'), get_post_type_object( 'post' )->cap->create_posts, 'post-new.php' );
     58                if ( $export ) {
     59                        $this->export();
     60                }
     61        }
    5162
    52         $i = 15;
    53         foreach ( get_taxonomies( array(), 'objects' ) as $tax ) {
    54                 if ( ! $tax->show_ui || ! $tax->show_in_menu || ! in_array('post', (array) $tax->object_type, true) )
    55                         continue;
     63        public function export() {
     64                $vars = get_object_vars( $this );
     65                foreach ( $vars as $var => $value ) {
     66                        $GLOBALS[ $var ] = $value;
     67                }
     68        }
    5669
    57                 $submenu['edit.php'][$i++] = array( esc_attr( $tax->labels->menu_name ), $tax->cap->manage_terms, 'edit-tags.php?taxonomy=' . $tax->name );
     70        public function get_top_level() {
     71                $comment_count = wp_count_comments();
     72                $count = '';
     73                if ( ! is_multisite() || ( is_super_admin() || current_user_can( 'update_plugins' ) ) ) {
     74                        $count = "<span class='update-plugins count-{$this->update_data['counts']['plugins']}'><span class='plugin-count'>" .
     75                                number_format_i18n($this->update_data['counts']['plugins']) .
     76                        "</span></span>";
     77                }
     78
     79                $comments_name = sprintf(
     80                        __( 'Comments %s' ),
     81                        "<span class='awaiting-mod count-{$comment_count->moderated}'><span class='pending-count'>" .
     82                                        number_format_i18n( $comment_count->moderated ) .
     83                        "</span></span>"
     84                );
     85
     86                $menu = array(
     87                        2  => array( __( 'Dashboard' ), 'read', 'index.php', '', 'menu-top menu-top-first menu-icon-dashboard', 'menu-dashboard', 'dashicons-dashboard' ),
     88                        4  => array( '', 'read', 'separator1', '', 'wp-menu-separator' ),
     89                        5  => array( __( 'Posts' ), 'edit_posts', 'edit.php', '', 'open-if-no-js menu-top menu-icon-post', 'menu-posts', 'dashicons-admin-post' ),
     90                        10 => array( __( 'Media' ), 'upload_files', 'upload.php', '', 'menu-top menu-icon-media', 'menu-media', 'dashicons-admin-media' ),
     91                        15 => array( __( 'Links' ), 'manage_links', 'link-manager.php', '', 'menu-top menu-icon-links', 'menu-links', 'dashicons-admin-links' ),
     92                        20 => array( __( 'Pages' ), 'edit_pages', 'edit.php?post_type=page', '', 'menu-top menu-icon-page', 'menu-pages', 'dashicons-admin-page' ),
     93                        25 => array( $comments_name, 'edit_posts', 'edit-comments.php', '', 'menu-top menu-icon-comments', 'menu-comments', 'dashicons-admin-comments' ),
     94                        59 => array( '', 'read', 'separator2', '', 'wp-menu-separator' ),
     95                        60 => array( __( 'Appearance' ), $this->appearance_cap, 'themes.php', '', 'menu-top menu-icon-appearance', 'menu-appearance', 'dashicons-admin-appearance' ),
     96                        65 => array( sprintf( __( 'Plugins %s' ), $count ), 'activate_plugins', 'plugins.php', '', 'menu-top menu-icon-plugins', 'menu-plugins', 'dashicons-admin-plugins' ),
     97                        75 => array( __( 'Tools' ), 'edit_posts', 'tools.php', '', 'menu-top menu-icon-tools', 'menu-tools', 'dashicons-admin-tools' ),
     98                        80 => array( __( 'Settings' ), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' ),
     99                        99 => array( '', 'read', 'separator-last', '', 'wp-menu-separator' ),
     100                );
     101
     102                if ( current_user_can( 'list_users' ) ) {
     103                        $menu[70] = array( __( 'Users' ), 'list_users', 'users.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' );
     104                } else {
     105                        $menu[70] = array( __( 'Profile' ), 'read', 'profile.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' );
     106                }
     107
     108                return $menu;
    58109        }
    59         unset($tax);
    60110
    61 $menu[10] = array( __('Media'), 'upload_files', 'upload.php', '', 'menu-top menu-icon-media', 'menu-media', 'dashicons-admin-media' );
    62         $submenu['upload.php'][5] = array( __('Library'), 'upload_files', 'upload.php');
    63         /* translators: add new file */
    64         $submenu['upload.php'][10] = array( _x('Add New', 'file'), 'upload_files', 'media-new.php');
    65         foreach ( get_taxonomies_for_attachments( 'objects' ) as $tax ) {
    66                 if ( ! $tax->show_ui || ! $tax->show_in_menu )
    67                         continue;
     111        public function get_index_submenu() {
     112                $submenu = array(
     113                        0 => array( __( 'Home' ), 'read', 'index.php' ),
     114                );
    68115
    69                 $submenu['upload.php'][$i++] = array( esc_attr( $tax->labels->menu_name ), $tax->cap->manage_terms, 'edit-tags.php?taxonomy=' . $tax->name . '&amp;post_type=attachment' );
     116                if ( is_multisite() ) {
     117                        $submenu[5] = array( __( 'My Sites' ), 'read', 'my-sites.php' );
     118                } else {
     119                        if ( current_user_can( 'update_core' ) ) {
     120                                $cap = 'update_core';
     121                        } elseif ( current_user_can( 'update_plugins' ) ) {
     122                                $cap = 'update_plugins';
     123                        } else {
     124                                $cap = 'update_themes';
     125                        }
     126                        $name = sprintf(
     127                                __( 'Updates %s' ),
     128                                "<span class='update-plugins count-{$this->update_data['counts']['total']}' title='{$this->update_data['title']}'><span class='update-count'>" .
     129                                        number_format_i18n($this->update_data['counts']['total']) .
     130                                "</span></span>"
     131                        );
     132                        $submenu[10] = array( $name, $cap, 'update-core.php' );
     133                }
     134
     135                return $submenu;
    70136        }
    71         unset($tax);
    72137
    73 $menu[15] = array( __('Links'), 'manage_links', 'link-manager.php', '', 'menu-top menu-icon-links', 'menu-links', 'dashicons-admin-links' );
    74         $submenu['link-manager.php'][5] = array( _x('All Links', 'admin menu'), 'manage_links', 'link-manager.php' );
    75         /* translators: add new links */
    76         $submenu['link-manager.php'][10] = array( _x('Add New', 'link'), 'manage_links', 'link-add.php' );
    77         $submenu['link-manager.php'][15] = array( __('Link Categories'), 'manage_categories', 'edit-tags.php?taxonomy=link_category' );
     138        public function get_post_submenu() {
     139                $submenu = array(
     140                        5 => array( __( 'All Posts' ), 'edit_posts', 'edit.php' ),
     141                        /* translators: add new post */
     142                        10 => array( _x( 'Add New', 'post' ), get_post_type_object( 'post' )->cap->create_posts, 'post-new.php' ),
     143                );
    78144
    79 $menu[20] = array( __('Pages'), 'edit_pages', 'edit.php?post_type=page', '', 'menu-top menu-icon-page', 'menu-pages', 'dashicons-admin-page' );
    80         $submenu['edit.php?post_type=page'][5] = array( __('All Pages'), 'edit_pages', 'edit.php?post_type=page' );
    81         /* translators: add new page */
    82         $submenu['edit.php?post_type=page'][10] = array( _x('Add New', 'page'), get_post_type_object( 'page' )->cap->create_posts, 'post-new.php?post_type=page' );
    83         $i = 15;
    84         foreach ( get_taxonomies( array(), 'objects' ) as $tax ) {
    85                 if ( ! $tax->show_ui || ! $tax->show_in_menu  || ! in_array('page', (array) $tax->object_type, true) )
    86                         continue;
     145                $i = 15;
     146                foreach ( get_taxonomies( array(), 'objects' ) as $tax ) {
     147                        if ( ! $tax->show_ui || ! $tax->show_in_menu || ! in_array( 'post', (array) $tax->object_type, true ) ) {
     148                                continue;
     149                        }
     150                        $submenu[ $i++ ] = array(
     151                                esc_attr( $tax->labels->menu_name ),
     152                                $tax->cap->manage_terms,
     153                                'edit-tags.php?taxonomy=' . $tax->name
     154                        );
     155                }
    87156
    88                 $submenu['edit.php?post_type=page'][$i++] = array( esc_attr( $tax->labels->menu_name ), $tax->cap->manage_terms, 'edit-tags.php?taxonomy=' . $tax->name . '&amp;post_type=page' );
     157                return $submenu;
    89158        }
    90         unset($tax);
    91159
    92 $awaiting_mod = wp_count_comments();
    93 $awaiting_mod = $awaiting_mod->moderated;
    94 $menu[25] = array( sprintf( __('Comments %s'), "<span class='awaiting-mod count-$awaiting_mod'><span class='pending-count'>" . number_format_i18n($awaiting_mod) . "</span></span>" ), 'edit_posts', 'edit-comments.php', '', 'menu-top menu-icon-comments', 'menu-comments', 'dashicons-admin-comments' );
    95 unset($awaiting_mod);
     160        public function get_upload_submenu() {
     161                $submenu = array(
     162                        5  => array( __( 'Library' ), 'upload_files', 'upload.php' ),
     163                        /* translators: add new file */
     164                        10 => array( _x( 'Add New', 'file' ), 'upload_files', 'media-new.php' ),
     165                );
    96166
    97 $submenu[ 'edit-comments.php' ][0] = array( __('All Comments'), 'edit_posts', 'edit-comments.php' );
     167                $i = 15;
     168                foreach ( get_taxonomies_for_attachments( 'objects' ) as $tax ) {
     169                        if ( ! $tax->show_ui || ! $tax->show_in_menu ) {
     170                                continue;
     171                        }
    98172
    99 $_wp_last_object_menu = 25; // The index of the last top-level menu in the object menu group
     173                        $submenu[ $i++ ] = array(
     174                                esc_attr( $tax->labels->menu_name ),
     175                                $tax->cap->manage_terms,
     176                                'edit-tags.php?taxonomy=' . $tax->name . '&amp;post_type=attachment'
     177                        );
     178                }
    100179
    101 foreach ( (array) get_post_types( array('show_ui' => true, '_builtin' => false, 'show_in_menu' => true ) ) as $ptype ) {
    102         $ptype_obj = get_post_type_object( $ptype );
    103         // Check if it should be a submenu.
    104         if ( $ptype_obj->show_in_menu !== true )
    105                 continue;
    106         $ptype_menu_position = is_int( $ptype_obj->menu_position ) ? $ptype_obj->menu_position : ++$_wp_last_object_menu; // If we're to use $_wp_last_object_menu, increment it first.
    107         $ptype_for_id = sanitize_html_class( $ptype );
     180                return $submenu;
     181        }
    108182
    109         if ( is_string( $ptype_obj->menu_icon ) ) {
    110                 // Special handling for data:image/svg+xml and Dashicons.
    111                 if ( 0 === strpos( $ptype_obj->menu_icon, 'data:image/svg+xml;base64,' ) || 0 === strpos( $ptype_obj->menu_icon, 'dashicons-' ) ) {
    112                         $menu_icon = $ptype_obj->menu_icon;
    113                 } else {
    114                         $menu_icon = esc_url( $ptype_obj->menu_icon );
     183        public function get_link_manager_submenu() {
     184                return array(
     185                        5  => array( _x( 'All Links', 'admin menu' ), 'manage_links', 'link-manager.php' ),
     186                        /* translators: add new links */
     187                        10 => array( _x( 'Add New', 'link' ), 'manage_links', 'link-add.php' ),
     188                        15 => array( __( 'Link Categories' ), 'manage_categories', 'edit-tags.php?taxonomy=link_category' ),
     189                );
     190        }
     191
     192        public function get_page_submenu() {
     193                $submenu = array(
     194                        5  => array( __( 'All Pages' ), 'edit_pages', 'edit.php?post_type=page' ),
     195                        /* translators: add new page */
     196                        10 => array( _x( 'Add New', 'page' ), get_post_type_object( 'page' )->cap->create_posts, 'post-new.php?post_type=page' ),
     197                );
     198
     199                $i = 15;
     200                foreach ( get_taxonomies( array(), 'objects' ) as $tax ) {
     201                        if ( ! $tax->show_ui || ! $tax->show_in_menu  || ! in_array('page', (array) $tax->object_type, true ) ) {
     202                                continue;
     203                        }
     204
     205                        $submenu[ $i++ ] = array(
     206                                esc_attr( $tax->labels->menu_name ),
     207                                $tax->cap->manage_terms,
     208                                'edit-tags.php?taxonomy=' . $tax->name . '&amp;post_type=page'
     209                        );
    115210                }
    116                 $ptype_class = $ptype_for_id;
    117         } else {
    118                 $menu_icon   = 'dashicons-admin-post';
    119                 $ptype_class = 'post';
     211
     212                return $submenu;
    120213        }
    121214
    122         /*
    123          * If $ptype_menu_position is already populated or will be populated
    124          * by a hard-coded value below, increment the position.
    125          */
    126         $core_menu_positions = array(59, 60, 65, 70, 75, 80, 85, 99);
    127         while ( isset($menu[$ptype_menu_position]) || in_array($ptype_menu_position, $core_menu_positions) )
    128                 $ptype_menu_position++;
     215        public function get_comment_submenu() {
     216                return array(
     217                        0 => array( __( 'All Comments' ), 'edit_posts', 'edit-comments.php' ),
     218                );
     219        }
    129220
    130         $menu[$ptype_menu_position] = array( esc_attr( $ptype_obj->labels->menu_name ), $ptype_obj->cap->edit_posts, "edit.php?post_type=$ptype", '', 'menu-top menu-icon-' . $ptype_class, 'menu-posts-' . $ptype_for_id, $menu_icon );
    131         $submenu["edit.php?post_type=$ptype"][5]  = array( $ptype_obj->labels->all_items, $ptype_obj->cap->edit_posts,  "edit.php?post_type=$ptype");
    132         $submenu["edit.php?post_type=$ptype"][10]  = array( $ptype_obj->labels->add_new, $ptype_obj->cap->create_posts, "post-new.php?post_type=$ptype" );
     221        public function get_theme_submenu() {
     222                $customize_url = add_query_arg( 'return', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'customize.php' );
    133223
    134         $i = 15;
    135         foreach ( get_taxonomies( array(), 'objects' ) as $tax ) {
    136                 if ( ! $tax->show_ui || ! $tax->show_in_menu || ! in_array($ptype, (array) $tax->object_type, true) )
    137                         continue;
     224                $submenu = array(
     225                        5 => array( __( 'Themes' ), $this->appearance_cap, 'themes.php' ),
     226                        6 => array( __( 'Customize' ), 'customize', esc_url( $customize_url ), '', 'hide-if-no-customize' ),
     227                );
    138228
    139                 $submenu["edit.php?post_type=$ptype"][$i++] = array( esc_attr( $tax->labels->menu_name ), $tax->cap->manage_terms, "edit-tags.php?taxonomy=$tax->name&amp;post_type=$ptype" );
     229                if ( current_theme_supports( 'menus' ) || current_theme_supports( 'widgets' ) ) {
     230                        $submenu[10] = array( __( 'Menus' ), 'edit_theme_options', 'nav-menus.php' );
     231                }
     232
     233                if ( current_theme_supports( 'custom-header' ) && current_user_can( 'customize') ) {
     234                        $customize_header_url = add_query_arg( array( 'autofocus' => array( 'control' => 'header_image' ) ), $customize_url );
     235                        $submenu[15] = array( __( 'Header' ), $this->appearance_cap, esc_url( $customize_header_url ), '', 'hide-if-no-customize' );
     236                }
     237
     238                if ( current_theme_supports( 'custom-background' ) && current_user_can( 'customize') ) {
     239                        $customize_background_url = add_query_arg( array( 'autofocus' => array( 'control' => 'background_image' ) ), $customize_url );
     240                        $submenu[20] = array( __( 'Background' ), $this->appearance_cap, esc_url( $customize_background_url ), '', 'hide-if-no-customize' );
     241                }
     242
     243                if ( ! is_multisite() ) {
     244                        // Add 'Editor' to the bottom of the Appearance menu.
     245                        add_action( 'admin_menu', '_add_themes_utility_last', 101 );
     246                }
     247
     248                return $submenu;
    140249        }
    141 }
    142 unset($ptype, $ptype_obj, $ptype_class, $ptype_for_id, $ptype_menu_position, $menu_icon, $i, $tax);
    143250
    144 $menu[59] = array( '', 'read', 'separator2', '', 'wp-menu-separator' );
     251        public function get_plugin_submenu() {
     252                $submenu = array(
     253                        5 => array( __( 'Installed Plugins' ), 'activate_plugins', 'plugins.php' )
     254                );
    145255
    146 $appearance_cap = current_user_can( 'switch_themes') ? 'switch_themes' : 'edit_theme_options';
     256                if ( ! is_multisite() ) {
     257                        /* translators: add new plugin */
     258                        $submenu[10] = array( _x( 'Add New', 'plugin' ), 'install_plugins', 'plugin-install.php' );
     259                        $submenu[15] = array( _x( 'Editor', 'plugin editor' ), 'edit_plugins', 'plugin-editor.php' );
     260                }
     261                return $submenu;
     262        }
    147263
    148 $menu[60] = array( __( 'Appearance' ), $appearance_cap, 'themes.php', '', 'menu-top menu-icon-appearance', 'menu-appearance', 'dashicons-admin-appearance' );
    149         $submenu['themes.php'][5] = array( __( 'Themes' ), $appearance_cap, 'themes.php' );
     264        public function get_tools_submenu() {
     265                $submenu = array(
     266                        5  => array( __( 'Available Tools' ), 'edit_posts', 'tools.php' ),
     267                        10 => array( __( 'Import' ), 'import', 'import.php' ),
     268                        15 => array( __( 'Export' ), 'export', 'export.php' ),
     269                );
    150270
    151         $customize_url = add_query_arg( 'return', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'customize.php' );
    152         $submenu['themes.php'][6] = array( __( 'Customize' ), 'customize', esc_url( $customize_url ), '', 'hide-if-no-customize' );
     271                if ( is_multisite() ) {
     272                        if ( ! is_main_site() ) {
     273                                $submenu[25] = array( __( 'Delete Site' ), 'delete_site', 'ms-delete-site.php' );
     274                        }
     275                } else  {
     276                        if ( defined( 'WP_ALLOW_MULTISITE' ) && WP_ALLOW_MULTISITE ) {
     277                                $submenu[50] = array( __( 'Network Setup' ), 'manage_options', 'network.php' );
     278                        }
     279                }
    153280
    154         if ( current_theme_supports( 'menus' ) || current_theme_supports( 'widgets' ) ) {
    155                 $submenu['themes.php'][10] = array( __( 'Menus' ), 'edit_theme_options', 'nav-menus.php' );
     281                return $submenu;
    156282        }
    157283
    158         if ( current_theme_supports( 'custom-header' ) && current_user_can( 'customize') ) {
    159                 $customize_header_url = add_query_arg( array( 'autofocus' => array( 'control' => 'header_image' ) ), $customize_url );
    160                 $submenu['themes.php'][15] = array( __( 'Header' ), $appearance_cap, esc_url( $customize_header_url ), '', 'hide-if-no-customize' );
     284        public function get_options_submenu() {
     285                return array(
     286                        10 => array( _x( 'General', 'settings screen' ), 'manage_options', 'options-general.php' ),
     287                        15 => array( __( 'Writing' ), 'manage_options', 'options-writing.php' ),
     288                        20 => array( __( 'Reading' ), 'manage_options', 'options-reading.php' ),
     289                        25 => array( __( 'Discussion' ), 'manage_options', 'options-discussion.php' ),
     290                        30 => array( __( 'Media' ), 'manage_options', 'options-media.php' ),
     291                        40 => array( __( 'Permalinks' ), 'manage_options', 'options-permalink.php' ),
     292                );
    161293        }
    162294
    163         if ( current_theme_supports( 'custom-background' ) && current_user_can( 'customize') ) {
    164                 $customize_background_url = add_query_arg( array( 'autofocus' => array( 'control' => 'background_image' ) ), $customize_url );
    165                 $submenu['themes.php'][20] = array( __( 'Background' ), $appearance_cap, esc_url( $customize_background_url ), '', 'hide-if-no-customize' );
     295        public function get_user_submenu() {
     296                $submenu = array(
     297                        5  => array( __( 'All Users' ), 'list_users', 'users.php' ),
     298                        15 => array( __( 'Your Profile' ), 'read', 'profile.php' )
     299                );
     300
     301                if ( current_user_can( 'create_users' ) ) {
     302                        $submenu[10] = array( _x( 'Add New', 'user' ), 'create_users', 'user-new.php' );
     303                } elseif ( is_multisite() ) {
     304                        $submenu[10] = array( _x( 'Add New', 'user' ), 'promote_users', 'user-new.php' );
     305                }
     306
     307                return $submenu;
    166308        }
    167309
    168         unset( $customize_url );
     310        public function get_profile_submenu() {
     311                $submenu = array(
     312                        5 => array( __( 'Your Profile' ), 'read', 'profile.php' )
     313                );
    169314
    170 unset( $appearance_cap );
     315                if ( current_user_can( 'create_users' ) ) {
     316                        $submenu[10] = array( __( 'Add New User' ), 'create_users', 'user-new.php' );
     317                } elseif ( is_multisite() ) {
     318                        $submenu[10] = array( __( 'Add New User' ), 'promote_users', 'user-new.php' );
     319                }
    171320
    172 // Add 'Editor' to the bottom of the Appearance menu.
    173 if ( ! is_multisite() ) {
    174         add_action('admin_menu', '_add_themes_utility_last', 101);
    175 }
    176 /**
    177  *
    178  */
    179 function _add_themes_utility_last() {
    180         // Must use API on the admin_menu hook, direct modification is only possible on/before the _admin_menu hook
    181         add_submenu_page('themes.php', _x('Editor', 'theme editor'), _x('Editor', 'theme editor'), 'edit_themes', 'theme-editor.php');
    182 }
     321                return $submenu;
     322        }
    183323
    184 $count = '';
    185 if ( ! is_multisite() && current_user_can( 'update_plugins' ) ) {
    186         if ( ! isset( $update_data ) )
    187                 $update_data = wp_get_update_data();
    188         $count = "<span class='update-plugins count-{$update_data['counts']['plugins']}'><span class='plugin-count'>" . number_format_i18n($update_data['counts']['plugins']) . "</span></span>";
    189 }
     324        public function add_submenu( $file ) {
     325                $sub = array();
    190326
    191 $menu[65] = array( sprintf( __('Plugins %s'), $count ), 'activate_plugins', 'plugins.php', '', 'menu-top menu-icon-plugins', 'menu-plugins', 'dashicons-admin-plugins' );
     327                switch ( $file ) {
     328                case 'index.php':
     329                        $sub = $this->get_index_submenu();
     330                        break;
    192331
    193 $submenu['plugins.php'][5]  = array( __('Installed Plugins'), 'activate_plugins', 'plugins.php' );
     332                case 'edit.php':
     333                        $sub = $this->get_post_submenu();
     334                        break;
    194335
    195         if ( ! is_multisite() ) {
    196                 /* translators: add new plugin */
    197                 $submenu['plugins.php'][10] = array( _x('Add New', 'plugin'), 'install_plugins', 'plugin-install.php' );
    198                 $submenu['plugins.php'][15] = array( _x('Editor', 'plugin editor'), 'edit_plugins', 'plugin-editor.php' );
     336                case 'upload.php':
     337                        $sub = $this->get_upload_submenu();
     338                        break;
     339
     340                case 'link-manager.php':
     341                        $sub = $this->get_link_manager_submenu();
     342                        break;
     343
     344                case 'edit.php?post_type=page':
     345                        $sub = $this->get_page_submenu();
     346                        break;
     347
     348                case 'edit-comments.php':
     349                        $sub = $this->get_comment_submenu();
     350                        break;
     351
     352                case 'themes.php':
     353                        $sub = $this->get_theme_submenu();
     354                        break;
     355
     356                case 'plugins.php':
     357                        $sub = $this->get_plugin_submenu();
     358                        break;
     359
     360                case 'tools.php':
     361                        $sub = $this->get_tools_submenu();
     362                        break;
     363
     364                case 'options-general.php':
     365                        $sub = $this->get_options_submenu();
     366                        break;
     367
     368                case 'users.php':
     369                        $sub = $this->get_user_submenu();
     370                        break;
     371
     372                case 'profile.php':
     373                        $sub = $this->get_profile_submenu();
     374                        break;
     375                }
     376
     377                $this->submenu[ $file ] = $sub;
    199378        }
    200379
    201 unset( $update_data );
     380        // Back-compat for old top-levels
     381        public function get_top_level_back_compat() {
     382                $files = array(
     383                        'post.php' => 'edit.php',
     384                        'post-new.php' => 'edit.php',
     385                        'edit-pages.php' => 'edit.php?post_type=page',
     386                        'page-new.php' => 'edit.php?post_type=page',
     387                        'wpmu-admin.php' => 'tools.php',
     388                        'ms-admin.php' => 'tools.php',
     389                );
    202390
    203 if ( current_user_can('list_users') )
    204         $menu[70] = array( __('Users'), 'list_users', 'users.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' );
    205 else
    206         $menu[70] = array( __('Profile'), 'read', 'profile.php', '', 'menu-top menu-icon-users', 'menu-users', 'dashicons-admin-users' );
     391                if ( current_user_can('list_users') ) {
     392                        // Back-compat for plugins adding submenus to profile.php.
     393                        $files['profile.php'] = 'users.php';
     394                } else {
     395                        $files['users.php'] = 'profile.php';
     396                }
    207397
    208 if ( current_user_can('list_users') ) {
    209         $_wp_real_parent_file['profile.php'] = 'users.php'; // Back-compat for plugins adding submenus to profile.php.
    210         $submenu['users.php'][5] = array(__('All Users'), 'list_users', 'users.php');
    211         if ( current_user_can( 'create_users' ) ) {
    212                 $submenu['users.php'][10] = array(_x('Add New', 'user'), 'create_users', 'user-new.php');
    213         } elseif ( is_multisite() ) {
    214                 $submenu['users.php'][10] = array(_x('Add New', 'user'), 'promote_users', 'user-new.php');
     398                return $files;
    215399        }
    216400
    217         $submenu['users.php'][15] = array(__('Your Profile'), 'read', 'profile.php');
    218 } else {
    219         $_wp_real_parent_file['users.php'] = 'profile.php';
    220         $submenu['profile.php'][5] = array(__('Your Profile'), 'read', 'profile.php');
    221         if ( current_user_can( 'create_users' ) ) {
    222                 $submenu['profile.php'][10] = array(__('Add New User'), 'create_users', 'user-new.php');
    223         } elseif ( is_multisite() ) {
    224                 $submenu['profile.php'][10] = array(__('Add New User'), 'promote_users', 'user-new.php');
     401        // ensure we're backwards compatible
     402        public function get_compat() {
     403                return array(
     404                        'index' => 'dashboard',
     405                        'edit' => 'posts',
     406                        'post' => 'posts',
     407                        'upload' => 'media',
     408                        'link-manager' => 'links',
     409                        'edit-pages' => 'pages',
     410                        'page' => 'pages',
     411                        'edit-comments' => 'comments',
     412                        'options-general' => 'settings',
     413                        'themes' => 'appearance',
     414                );
    225415        }
    226 }
    227416
    228 $menu[75] = array( __('Tools'), 'edit_posts', 'tools.php', '', 'menu-top menu-icon-tools', 'menu-tools', 'dashicons-admin-tools' );
    229         $submenu['tools.php'][5] = array( __('Available Tools'), 'edit_posts', 'tools.php' );
    230         $submenu['tools.php'][10] = array( __('Import'), 'import', 'import.php' );
    231         $submenu['tools.php'][15] = array( __('Export'), 'export', 'export.php' );
    232         if ( is_multisite() && !is_main_site() )
    233                 $submenu['tools.php'][25] = array( __('Delete Site'), 'delete_site', 'ms-delete-site.php' );
    234         if ( ! is_multisite() && defined('WP_ALLOW_MULTISITE') && WP_ALLOW_MULTISITE )
    235                 $submenu['tools.php'][50] = array(__('Network Setup'), 'manage_options', 'network.php');
     417        public function add_post_type_menus() {
     418                $core_menu_positions = array( 59, 60, 65, 70, 75, 80, 85, 99 );
     419                $post_types = get_post_types( array( 'show_ui' => true, '_builtin' => false, 'show_in_menu' => true ), 'objects' );
     420                $show_types = wp_list_filter( $post_types, array( 'show_in_menu' => true ) );
    236421
    237 $menu[80] = array( __('Settings'), 'manage_options', 'options-general.php', '', 'menu-top menu-icon-settings', 'menu-settings', 'dashicons-admin-settings' );
    238         $submenu['options-general.php'][10] = array(_x('General', 'settings screen'), 'manage_options', 'options-general.php');
    239         $submenu['options-general.php'][15] = array(__('Writing'), 'manage_options', 'options-writing.php');
    240         $submenu['options-general.php'][20] = array(__('Reading'), 'manage_options', 'options-reading.php');
    241         $submenu['options-general.php'][25] = array(__('Discussion'), 'manage_options', 'options-discussion.php');
    242         $submenu['options-general.php'][30] = array(__('Media'), 'manage_options', 'options-media.php');
    243         $submenu['options-general.php'][40] = array(__('Permalinks'), 'manage_options', 'options-permalink.php');
     422                foreach ( $show_types as $ptype ) {
     423                        // If we're to use $_wp_last_object_menu, increment it first.
     424                        $ptype_menu_position = is_int( $ptype->menu_position ) ? $ptype->menu_position : ++$this->_wp_last_object_menu;
     425                        $ptype_for_id = sanitize_html_class( $ptype->name );
    244426
    245 $_wp_last_utility_menu = 80; // The index of the last top-level menu in the utility menu group
     427                        if ( is_string( $ptype->menu_icon ) ) {
     428                                // Special handling for data:image/svg+xml and Dashicons.
     429                                if ( 0 === strpos( $ptype->menu_icon, 'data:image/svg+xml;base64,' ) || 0 === strpos( $ptype->menu_icon, 'dashicons-' ) ) {
     430                                        $menu_icon = $ptype->menu_icon;
     431                                } else {
     432                                        $menu_icon = esc_url( $ptype->menu_icon );
     433                                }
     434                                $ptype_class = $ptype_for_id;
     435                        } else {
     436                                $menu_icon   = 'dashicons-admin-post';
     437                                $ptype_class = 'post';
     438                        }
    246439
    247 $menu[99] = array( '', 'read', 'separator-last', '', 'wp-menu-separator' );
     440                        /*
     441                         * If $ptype_menu_position is already populated or will be populated
     442                         * by a hard-coded value below, increment the position.
     443                         */
     444                        while ( isset( $this->menu[ $ptype_menu_position ] ) || in_array( $ptype_menu_position, $core_menu_positions ) ) {
     445                                $ptype_menu_position++;
     446                        }
    248447
    249 // Back-compat for old top-levels
    250 $_wp_real_parent_file['post.php'] = 'edit.php';
    251 $_wp_real_parent_file['post-new.php'] = 'edit.php';
    252 $_wp_real_parent_file['edit-pages.php'] = 'edit.php?post_type=page';
    253 $_wp_real_parent_file['page-new.php'] = 'edit.php?post_type=page';
    254 $_wp_real_parent_file['wpmu-admin.php'] = 'tools.php';
    255 $_wp_real_parent_file['ms-admin.php'] = 'tools.php';
     448                        $this->menu[ $ptype_menu_position ] = array(
     449                                esc_attr( $ptype->labels->menu_name ),
     450                                $ptype->cap->edit_posts,
     451                                "edit.php?post_type={$ptype->name}",
     452                                '',
     453                                'menu-top menu-icon-' . $ptype_class,
     454                                'menu-posts-' . $ptype_for_id,
     455                                $menu_icon
     456                        );
    256457
    257 // ensure we're backwards compatible
    258 $compat = array(
    259         'index' => 'dashboard',
    260         'edit' => 'posts',
    261         'post' => 'posts',
    262         'upload' => 'media',
    263         'link-manager' => 'links',
    264         'edit-pages' => 'pages',
    265         'page' => 'pages',
    266         'edit-comments' => 'comments',
    267         'options-general' => 'settings',
    268         'themes' => 'appearance',
    269         );
     458                        $this->add_post_type_submenu( $ptype );
     459                }
     460        }
    270461
    271 require_once(ABSPATH . 'wp-admin/includes/menu.php');
     462        public function add_post_type_submenu( $ptype ) {
     463                $submenu = array(
     464                        5  => array( $ptype->labels->all_items, $ptype->cap->edit_posts,  "edit.php?post_type={$ptype->name}"),
     465                        10 => array( $ptype->labels->add_new, $ptype->cap->create_posts, "post-new.php?post_type={$ptype->name}" )
     466                );
     467
     468                $i = 15;
     469                foreach ( get_taxonomies( array(), 'objects' ) as $tax ) {
     470                        if ( ! $tax->show_ui || ! $tax->show_in_menu || ! in_array( $ptype->name, (array) $tax->object_type, true ) ) {
     471                                continue;
     472                        }
     473
     474                        $submenu[ $i++ ] = array(
     475                                esc_attr( $tax->labels->menu_name ),
     476                                $tax->cap->manage_terms,
     477                                "edit-tags.php?taxonomy={$tax->name}&amp;post_type={$ptype->name}"
     478                        );
     479                }
     480
     481                $this->submenu[ "edit.php?post_type={$ptype->name}" ] = $submenu;
     482        }
     483}
     484
     485function _add_themes_utility_last() {
     486        // Must use API on the admin_menu hook, direct modification is only possible on/before the _admin_menu hook
     487        add_submenu_page('themes.php', _x( 'Editor', 'theme editor' ), _x( 'Editor', 'theme editor' ), 'edit_themes', 'theme-editor.php' );
     488}
     489
     490new WP_Admin_Menu();
     491
     492require_once( ABSPATH . 'wp-admin/includes/menu.php' );