[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Build Administration Menu. 4 * 5 * @package WordPress 6 * @subpackage Administration 7 */ 8 9 if ( is_network_admin() ) { 10 11 /** 12 * Fires before the administration menu loads in the Network Admin. 13 * 14 * The hook fires before menus and sub-menus are removed based on user privileges. 15 * 16 * @since 3.1.0 17 * @access private 18 */ 19 do_action( '_network_admin_menu' ); 20 } elseif ( is_user_admin() ) { 21 22 /** 23 * Fires before the administration menu loads in the User Admin. 24 * 25 * The hook fires before menus and sub-menus are removed based on user privileges. 26 * 27 * @since 3.1.0 28 * @access private 29 */ 30 do_action( '_user_admin_menu' ); 31 } else { 32 33 /** 34 * Fires before the administration menu loads in the admin. 35 * 36 * The hook fires before menus and sub-menus are removed based on user privileges. 37 * 38 * @since 2.2.0 39 * @access private 40 */ 41 do_action( '_admin_menu' ); 42 } 43 44 // Create list of page plugin hook names. 45 foreach ( $menu as $menu_page ) { 46 $pos = strpos( $menu_page[2], '?' ); 47 48 if ( false !== $pos ) { 49 // Handle post_type=post|page|foo pages. 50 $hook_name = substr( $menu_page[2], 0, $pos ); 51 $hook_args = substr( $menu_page[2], $pos + 1 ); 52 wp_parse_str( $hook_args, $hook_args ); 53 54 // Set the hook name to be the post type. 55 if ( isset( $hook_args['post_type'] ) ) { 56 $hook_name = $hook_args['post_type']; 57 } else { 58 $hook_name = basename( $hook_name, '.php' ); 59 } 60 unset( $hook_args ); 61 } else { 62 $hook_name = basename( $menu_page[2], '.php' ); 63 } 64 65 $hook_name = sanitize_title( $hook_name ); 66 67 if ( isset( $compat[ $hook_name ] ) ) { 68 $hook_name = $compat[ $hook_name ]; 69 } elseif ( ! $hook_name ) { 70 continue; 71 } 72 73 $admin_page_hooks[ $menu_page[2] ] = $hook_name; 74 } 75 unset( $menu_page, $compat ); 76 77 $_wp_submenu_nopriv = array(); 78 $_wp_menu_nopriv = array(); 79 // Loop over submenus and remove pages for which the user does not have privs. 80 foreach ( $submenu as $parent => $sub ) { 81 foreach ( $sub as $index => $data ) { 82 if ( ! current_user_can( $data[1] ) ) { 83 unset( $submenu[ $parent ][ $index ] ); 84 $_wp_submenu_nopriv[ $parent ][ $data[2] ] = true; 85 } 86 } 87 unset( $index, $data ); 88 89 if ( empty( $submenu[ $parent ] ) ) { 90 unset( $submenu[ $parent ] ); 91 } 92 } 93 unset( $sub, $parent ); 94 95 /* 96 * Loop over the top-level menu. 97 * Menus for which the original parent is not accessible due to lack of privileges 98 * will have the next submenu in line be assigned as the new menu parent. 99 */ 100 foreach ( $menu as $id => $data ) { 101 if ( empty( $submenu[ $data[2] ] ) ) { 102 continue; 103 } 104 105 $subs = $submenu[ $data[2] ]; 106 $first_sub = reset( $subs ); 107 $old_parent = $data[2]; 108 $new_parent = $first_sub[2]; 109 110 /* 111 * If the first submenu is not the same as the assigned parent, 112 * make the first submenu the new parent. 113 */ 114 if ( $new_parent !== $old_parent ) { 115 $_wp_real_parent_file[ $old_parent ] = $new_parent; 116 117 $menu[ $id ][2] = $new_parent; 118 119 foreach ( $submenu[ $old_parent ] as $index => $data ) { 120 $submenu[ $new_parent ][ $index ] = $submenu[ $old_parent ][ $index ]; 121 unset( $submenu[ $old_parent ][ $index ] ); 122 } 123 unset( $submenu[ $old_parent ], $index ); 124 125 if ( isset( $_wp_submenu_nopriv[ $old_parent ] ) ) { 126 $_wp_submenu_nopriv[ $new_parent ] = $_wp_submenu_nopriv[ $old_parent ]; 127 } 128 } 129 } 130 unset( $id, $data, $subs, $first_sub, $old_parent, $new_parent ); 131 132 if ( is_network_admin() ) { 133 134 /** 135 * Fires before the administration menu loads in the Network Admin. 136 * 137 * @since 3.1.0 138 * 139 * @param string $context Empty context. 140 */ 141 do_action( 'network_admin_menu', '' ); 142 } elseif ( is_user_admin() ) { 143 144 /** 145 * Fires before the administration menu loads in the User Admin. 146 * 147 * @since 3.1.0 148 * 149 * @param string $context Empty context. 150 */ 151 do_action( 'user_admin_menu', '' ); 152 } else { 153 154 /** 155 * Fires before the administration menu loads in the admin. 156 * 157 * @since 1.5.0 158 * 159 * @param string $context Empty context. 160 */ 161 do_action( 'admin_menu', '' ); 162 } 163 164 /* 165 * Remove menus that have no accessible submenus and require privileges 166 * that the user does not have. Run re-parent loop again. 167 */ 168 foreach ( $menu as $id => $data ) { 169 if ( ! current_user_can( $data[1] ) ) { 170 $_wp_menu_nopriv[ $data[2] ] = true; 171 } 172 173 /* 174 * If there is only one submenu and it is has same destination as the parent, 175 * remove the submenu. 176 */ 177 if ( ! empty( $submenu[ $data[2] ] ) && 1 === count( $submenu[ $data[2] ] ) ) { 178 $subs = $submenu[ $data[2] ]; 179 $first_sub = reset( $subs ); 180 181 if ( $data[2] === $first_sub[2] ) { 182 unset( $submenu[ $data[2] ] ); 183 } 184 } 185 186 // If submenu is empty... 187 if ( empty( $submenu[ $data[2] ] ) ) { 188 // And user doesn't have privs, remove menu. 189 if ( isset( $_wp_menu_nopriv[ $data[2] ] ) ) { 190 unset( $menu[ $id ] ); 191 } 192 } 193 } 194 unset( $id, $data, $subs, $first_sub ); 195 196 /** 197 * Adds a CSS class to a string. 198 * 199 * @since 2.7.0 200 * 201 * @param string $class_to_add The CSS class to add. 202 * @param string $classes The string to add the CSS class to. 203 * @return string The string with the CSS class added. 204 */ 205 function add_cssclass( $class_to_add, $classes ) { 206 if ( empty( $classes ) ) { 207 return $class_to_add; 208 } 209 210 return $classes . ' ' . $class_to_add; 211 } 212 213 /** 214 * Adds CSS classes for top-level administration menu items. 215 * 216 * The list of added classes includes `.menu-top-first` and `.menu-top-last`. 217 * 218 * @since 2.7.0 219 * 220 * @param array $menu The array of administration menu items. 221 * @return array The array of administration menu items with the CSS classes added. 222 */ 223 function add_menu_classes( $menu ) { 224 $first_item = false; 225 $last_order = false; 226 $items_count = count( $menu ); 227 228 $i = 0; 229 230 foreach ( $menu as $order => $top ) { 231 ++$i; 232 233 if ( 0 === $order ) { // Dashboard is always shown/single. 234 $menu[0][4] = add_cssclass( 'menu-top-first', $top[4] ); 235 $last_order = 0; 236 continue; 237 } 238 239 if ( str_starts_with( $top[2], 'separator' ) && false !== $last_order ) { // If separator. 240 $first_item = true; 241 $classes = $menu[ $last_order ][4]; 242 243 $menu[ $last_order ][4] = add_cssclass( 'menu-top-last', $classes ); 244 continue; 245 } 246 247 if ( $first_item ) { 248 $first_item = false; 249 $classes = $menu[ $order ][4]; 250 251 $menu[ $order ][4] = add_cssclass( 'menu-top-first', $classes ); 252 } 253 254 if ( $i === $items_count ) { // Last item. 255 $classes = $menu[ $order ][4]; 256 257 $menu[ $order ][4] = add_cssclass( 'menu-top-last', $classes ); 258 } 259 260 $last_order = $order; 261 } 262 263 /** 264 * Filters administration menu array with classes added for top-level items. 265 * 266 * @since 2.7.0 267 * 268 * @param array $menu Associative array of administration menu items. 269 */ 270 return apply_filters( 'add_menu_classes', $menu ); 271 } 272 273 uksort( $menu, 'strnatcasecmp' ); // Make it all pretty. 274 275 /** 276 * Filters whether to enable custom ordering of the administration menu. 277 * 278 * See the {@see 'menu_order'} filter for reordering menu items. 279 * 280 * @since 2.8.0 281 * 282 * @param bool $custom Whether custom ordering is enabled. Default false. 283 */ 284 if ( apply_filters( 'custom_menu_order', false ) ) { 285 $menu_order = array(); 286 287 foreach ( $menu as $menu_item ) { 288 $menu_order[] = $menu_item[2]; 289 } 290 unset( $menu_item ); 291 292 $default_menu_order = $menu_order; 293 294 /** 295 * Filters the order of administration menu items. 296 * 297 * A truthy value must first be passed to the {@see 'custom_menu_order'} filter 298 * for this filter to work. Use the following to enable custom menu ordering: 299 * 300 * add_filter( 'custom_menu_order', '__return_true' ); 301 * 302 * @since 2.8.0 303 * 304 * @param array $menu_order An ordered array of menu items. 305 */ 306 $menu_order = apply_filters( 'menu_order', $menu_order ); 307 $menu_order = array_flip( $menu_order ); 308 309 $default_menu_order = array_flip( $default_menu_order ); 310 311 /** 312 * @global array $menu_order 313 * @global array $default_menu_order 314 * 315 * @param array $a 316 * @param array $b 317 * @return int 318 */ 319 function sort_menu( $a, $b ) { 320 global $menu_order, $default_menu_order; 321 322 $a = $a[2]; 323 $b = $b[2]; 324 325 if ( isset( $menu_order[ $a ] ) && ! isset( $menu_order[ $b ] ) ) { 326 return -1; 327 } elseif ( ! isset( $menu_order[ $a ] ) && isset( $menu_order[ $b ] ) ) { 328 return 1; 329 } elseif ( isset( $menu_order[ $a ] ) && isset( $menu_order[ $b ] ) ) { 330 if ( $menu_order[ $a ] === $menu_order[ $b ] ) { 331 return 0; 332 } 333 return ( $menu_order[ $a ] < $menu_order[ $b ] ) ? -1 : 1; 334 } else { 335 return ( $default_menu_order[ $a ] <= $default_menu_order[ $b ] ) ? -1 : 1; 336 } 337 } 338 339 usort( $menu, 'sort_menu' ); 340 unset( $menu_order, $default_menu_order ); 341 } 342 343 // Prevent adjacent separators. 344 $prev_menu_was_separator = false; 345 foreach ( $menu as $id => $data ) { 346 if ( false === stristr( $data[4], 'wp-menu-separator' ) ) { 347 348 // This item is not a separator, so falsey the toggler and do nothing. 349 $prev_menu_was_separator = false; 350 } else { 351 352 // The previous item was a separator, so unset this one. 353 if ( true === $prev_menu_was_separator ) { 354 unset( $menu[ $id ] ); 355 } 356 357 // This item is a separator, so truthy the toggler and move on. 358 $prev_menu_was_separator = true; 359 } 360 } 361 unset( $id, $data, $prev_menu_was_separator ); 362 363 // Remove the last menu item if it is a separator. 364 $last_menu_key = array_keys( $menu ); 365 $last_menu_key = array_pop( $last_menu_key ); 366 if ( ! empty( $menu ) && 'wp-menu-separator' === $menu[ $last_menu_key ][4] ) { 367 unset( $menu[ $last_menu_key ] ); 368 } 369 unset( $last_menu_key ); 370 371 if ( ! user_can_access_admin_page() ) { 372 373 /** 374 * Fires when access to an admin page is denied. 375 * 376 * @since 2.5.0 377 */ 378 do_action( 'admin_page_access_denied' ); 379 380 wp_die( __( 'Sorry, you are not allowed to access this page.' ), 403 ); 381 } 382 383 $menu = add_menu_classes( $menu );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Wed Dec 25 08:20:01 2024 | Cross-referenced by PHPXref |