?> <div id="adminmenumain" role="navigation" aria-label="<?php esc_attr_e('Main menu'); ?> "> <a href="#wpbody-content" class="screen-reader-shortcut"><?php _e('Skip to main content'); ?> </a> <a href="#wp-toolbar" class="screen-reader-shortcut"><?php _e('Skip to toolbar'); ?> </a> <div id="adminmenuback"></div> <div id="adminmenuwrap"> <ul id="adminmenu"> <?php _wp_menu_output($menu, $submenu); /** * Fires after the admin menu has been output. * * @since 2.5.0 */ do_action('adminmenu'); ?> </ul> </div> </div>
/** * Adds the new, modified admin menu. * * @since Client Dash 1.6 */ public function add_modified_admin_menu() { global $menu, $submenu, $self, $pagenow, $submenu_file, $parent_file, $cd_parent_file, $_registered_pages, $plugin_page, $cd_submenu_file, $ClientDash, $admin_page_hooks; if (!self::is_current_adminmenu_active()) { return; } // This is a strange little hack. When moving a sub-menu page to a top-level page, there are some // caveats. One being, WordPress doesn't know what the heck to do!... You will get a permissions // denied error without this line because of the hook names being different than normal. This simply // ensures that it will not be un-reachable. if (!empty($plugin_page)) { $_registered_pages["admin_page_{$plugin_page}"] = true; } // Get current role $current_role = $this->get_user_role(); // Get menu items and then index items by db ID $unsorted_menu_items = wp_get_nav_menu_items($this->all_menu_IDs[$current_role], array('orderby' => 'ID', 'output' => ARRAY_A, 'output_key' => 'ID')); // Bail if no items if (empty($unsorted_menu_items)) { return; } $menu_items = array(); foreach ($unsorted_menu_items as $_item) { $menu_items[$_item->db_id] = $_item; } // If menu not empty, cycle through all items and add them as either menus or sub-menus if (!empty($menu_items) && !is_wp_error($menu_items)) { foreach ($menu_items as $dbID => $menu_item) { // If this item is a CD Core page and isn't currently enabled for this role (no content), then // don't add it (and also remove it from the list for making sure none of its sub-menus load) if ($menu_item->cd_type == 'cd_core' && !isset($ClientDash->content_sections[str_replace('cd_', '', $menu_item->url)])) { unset($menu_items[$dbID]); continue; } // If webmaster page, change the title if ($menu_item->url == 'cd_webmaster') { $menu_item->title = get_option('cd_webmaster_name', $ClientDash->option_defaults['webmaster_name']); $menu_item->cd_page_title = get_option('cd_webmaster_name', $ClientDash->option_defaults['webmaster_name']); } // If the comments page, get the html generated mimicked from WP core (/wp-admin/menus.php:~94) if ($menu_item->title == 'Comments') { $awaiting_mod = wp_count_comments(); $awaiting_mod = $awaiting_mod->moderated; $menu_item->title = sprintf(__('Comments %s'), "<span class='awaiting-mod count-{$awaiting_mod}'><span class='pending-count'>" . number_format_i18n($awaiting_mod) . "</span></span>"); } if (strpos($menu_item->url, 'separator') !== false) { // If a separator $menu[$menu_item->menu_order] = array('', 'read', $menu_item->url, '', 'wp-menu-separator'); } elseif ($menu_item->menu_item_parent == 0) { // If a parent // If this was originally a sub-menu, we need to fix the link (unless the slug is already // a hardlink) if (strpos($menu_item->url, '.php') === false && ($parent_slug = !empty($menu_item->cd_submenu_parent) ? $menu_item->cd_submenu_parent : false)) { $menu_item->url = $parent_slug . (strpos($parent_slug, '?') !== false ? '&' : '?') . "page={$menu_item->url}"; } // If extra parameters are set, add them on if (!empty($menu_item->cd_params)) { $menu_item->url .= $menu_item->cd_params; } // Allowed query params for when filtering the url $args = array('page' => true, 'post_type' => true, 'taxonomy' => true); // If this page has added extra to the url if (!empty($menu_item->cd_params)) { $params = explode('&', $menu_item->cd_params); foreach ($params as $param) { if (!empty($param)) { preg_match('/.*(?==)/', $param, $matches); $args[$matches[0]] = true; } } } // Get the filtered url $url = $this->get_cleaned_url($args); // If the url matches, add it to an array storing all matching urls if ($url == $menu_item->url) { $this->matching_urls[] = array('parent' => $menu_item->url, 'submenu' => false); } $hookname = get_plugin_page_hookname($menu_item->url, ''); if (empty($menu_item->cd_icon)) { $icon_url = 'dashicons-admin-generic'; $icon_class = 'menu-icon-generic '; } else { $icon_url = set_url_scheme($menu_item->cd_icon); $icon_class = ''; } $menu[$menu_item->menu_order] = array($menu_item->title, 'read', $menu_item->url, $menu_item->cd_page_title, 'menu-top ' . $icon_class . $hookname . ' ' . esc_attr(implode(' ', $menu_item->classes)), $hookname, $icon_url); // Here's the deal... When we add the menu page here, we've already done it once (from other plugins // and such), so the callbacks are already set. BUT, the callbacks are used by adding an action, the // action hookname is based off of the menu title and the menu slug. SO, it's okay that we don't add // the callback here again (because it's already been added before we removed it), but the problem is, // if we change the title then the hookname that WP is now looking for doesn't match the one that was // already created. SO, if the title was changed, we need to modify the global $admin_page_hooks so // that the action name matches the ORIGINAL title, not the new title. WHEW! if ($menu_item->original_title != $menu_item->title) { $admin_page_hooks[$menu_item->url] = strtolower($menu_item->original_title); } } else { // If a sub-menu // If the parent has been unset, then don't add the sub-menu if (!isset($menu_items[(int) $menu_item->menu_item_parent])) { continue; } // If extra parameters are set, add them on if (!empty($menu_item->cd_params)) { $menu_item->url .= $menu_item->cd_params; } // Allowed query params for when filtering the url $args = array('page' => true, 'post_type' => true, 'taxonomy' => true); // If this page has added extra to the url if (!empty($menu_item->cd_params)) { $params = explode('&', $menu_item->cd_params); foreach ($params as $param) { if (!empty($param)) { preg_match('/.*(?==)/', $param, $matches); $args[$matches[0]] = true; } } } // Get the filtered url $url = $this->get_cleaned_url($args); // If the url matches, add it to an array storing all matching urls if ($url == $menu_item->url) { $this->matching_urls[] = array('parent' => $menu_items[(int) $menu_item->menu_item_parent]->url, 'submenu' => $menu_item->url); } $submenu[$menu_items[$menu_item->menu_item_parent]->url][$menu_item->menu_order] = array($menu_item->title, 'read', $menu_item->url, $menu_item->cd_page_title); } } } // Sort the menus and the sub-menus by array_key so they are in proper order ksort($menu); foreach ($submenu as $menu_parent => $sub_menus) { ksort($submenu[$menu_parent]); } // In the case of a sub-menu item being moved to a parent item, WordPress will be confused // about which menu item is active. So I compensate for this by overriding the "self" and // "parent_file" globals with the new (previously sub-menu) slug. This corrects the issue. // Get the most specific url (the biggest value). Only proceed if there is at least one matching url. if (!empty($this->matching_urls)) { $url = max($this->matching_urls); // Set the self (or what WP thinks we're viewing) to the ENTIRE slug, not just the parent. $self = $url['parent']; $pagenow = $url['parent']; $plugin_page = $url['parent']; $parent_file = $url['parent']; // Tell WP what our new submenu file is (because it's custom), otherwise, default to // the parent $submenu_file = !empty($url['submenu']) ? $url['submenu'] : $url['parent']; } // Instead of allowing WP to add its menu with this function, I've emptied the global $menu and $submenu variables // when this is initially called. And then IMMEDIATELY after there is a hook "adminmenu" that I call the exact // same function again, though I'm adding the 3rd param as false (normally true). This means that the parent // menu items do NOT have to link to where the first sub-menu item goes to, which is normaly functionality. // This is a private function, sorry WP! _wp_menu_output($menu, $submenu, false); }