Admin Panel. 15+ Hooks for functions.php
Another collection of hacks that can be used for the WordPress admin panel. All codes have been tested for functionality up to WP version 4.7. Here are popular hooks sorted by popularity (based on the site wordpress.stackexchange.com).
More collections of hacks:
All Site Settings on One Page
Enabling a hidden page in the admin panel. This small piece of code will add another item to the site settings menu. By going to the added page, you will see all the site settings at once. This page can be accessed via the link: example.com/wp-admin/options.php.
The code only works for the site administrator; other roles will not see the new menu item.
## Adds a link to the all settings page in the admin menu item "Settings" add_action('admin_menu', 'all_settings_link'); function all_settings_link(){ add_options_page( __('All Settings'), __('All Settings'), 'manage_options', 'options.php?foo' ); }
Removing Update Notifications in WordPress for Everyone Except Admin
add_action( 'admin_head', function () { if ( ! current_user_can( 'manage_options' ) ) { remove_action( 'admin_notices', 'update_nag', 3 ); remove_action( 'admin_notices', 'maintenance_nag', 10 ); } } );
Old version, comments said it no longer works:
## removes the message about a new version of WordPress for all users except the administrator if( is_admin() && ! current_user_can('manage_options') ){ add_action( 'init', function(){ remove_action( 'init', 'wp_version_check' ); }, 2 ); add_filter( 'pre_option_update_core', '__return_null'); }
Removing Meta Boxes on the Post Edit Page
On the post edit page, there are often meta boxes that are never used. To speed up the admin panel a bit and remove unnecessary elements from the interface, they can be deleted. Read more in the function description remove_meta_box()
## Removing meta boxes on the post edit page add_action('admin_menu','remove_default_post_screen_metaboxes'); function remove_default_post_screen_metaboxes() { // for posts remove_meta_box( 'postcustom','post','normal' ); // custom fields remove_meta_box( 'postexcerpt','post','normal' ); // excerpt remove_meta_box( 'commentstatusdiv','post','normal' ); // comments remove_meta_box( 'trackbacksdiv','post','normal' ); // notification block remove_meta_box( 'slugdiv','post','normal' ); // alternative title block remove_meta_box( 'authordiv','post','normal' ); // author // for pages remove_meta_box( 'postcustom','page','normal' ); // custom fields remove_meta_box( 'postexcerpt','page','normal' ); // excerpt remove_meta_box( 'commentstatusdiv','page','normal' ); // comments remove_meta_box( 'trackbacksdiv','page','normal' ); // notification block remove_meta_box( 'slugdiv','page','normal' ); // alternative title block remove_meta_box( 'authordiv','page','normal' ); // author }
Custom Order of Items in the Main Menu of the Admin Panel
WordPress has a feature that allows you to change the order of items in the main menu in the admin panel in any way. Not everyone knows about this feature. By default, it is not enabled - it needs to be turned on via the hook custom_menu_order. See the code below for more details.
The code below will change the menu order. "Pages" will come first, followed by "Posts," and then the custom post type "events." By changing the order of the array elements, you can change the menu item order in any way.
## Custom order of items in the main menu of the admin panel if( is_admin() ){ add_filter('custom_menu_order', '__return_true'); // enable manual sorting add_filter('menu_order', 'custom_menu_order'); // manual sorting function custom_menu_order( $menu_order ){ /* $menu_order - an array where the menu items are set in the desired order. Array( [0] => index.php [1] => separator1 [2] => edit.php [3] => upload.php [4] => edit.php?post_type=page [5] => edit-comments.php [6] => edit.php?post_type=events [7] => separator2 [8] => themes.php [9] => plugins.php [10] => snippets [11] => users.php [12] => tools.php [13] => options-general.php [14] => separator-last [15] => edit.php?post_type=cfs ) */ if( ! $menu_order ) return true; return array( 'index.php', // dashboard 'edit.php?post_type=page', // pages 'edit.php', // posts 'edit.php?post_type=events', // events type posts ); } }
Move Selected Category to its Place in the Hierarchy
- There is a tree structure of categories.
- I publish a post and place it in a child category.
- As a result, the selected category is at the top, but it needs to be in its place in the category hierarchy.
## cancel showing the selected term at the top in the checkbox list of terms add_filter( 'wp_terms_checklist_args', 'set_checked_ontop_default', 10 ); function set_checked_ontop_default( $args ) { // change the default parameter to false if( ! isset($args['checked_ontop']) ) $args['checked_ontop'] = false; return $args; }
Removing the "All Categories" and "Frequently Used" Tabs in the Categories Meta Box in the Admin Panel
This hack I often use here and there. I think it's convenient!

The code removes such tabs and from the meta boxes of custom hierarchical taxonomies.
# Removes the "Frequently Used" tab for the categories meta box for all posts add_action( 'admin_head', 'func_hook_admin_styles' ); function func_hook_admin_styles() { $cs = get_current_screen(); // not the post edit page if ( $cs->base !== 'post' || empty( $cs->post_type ) ) { return; } ?> <style> .postbox div.tabs-panel{ max-height:1200px; border:0; } .category-tabs{ display:none; } </style> <?php }
Change Checkbox to Radio in the Categories Widget
If the site is intended to always specify only one category for a post, it can be more convenient to change the checkboxes in the categories widget to radio buttons. This way, when changing the category, the previously selected category will be automatically deselected, and only one category will always be specified for the post.
The example below shows how to do this for the taxonomies category and my_category.
Option 1:
## Change checkbox to radio on post pages add_action( 'admin_print_footer_scripts', 'func_hook_admin_footer_scripts', 99 ); function func_hook_admin_footer_scripts(){ if( get_current_screen()->base !== 'post' ) return; ?> <script> [ 'category', 'my_category' ].forEach(function(taxname){ jQuery( '#' + taxname + 'div input[type="checkbox"]' ).prop( 'type', 'radio' ); }) </script> <?php }
Option 2 (for perfectionists - adds the script only when there is a taxonomy widget)
## Change checkbox to radio on post pages add_action( 'admin_print_footer_scripts', 'func_hook_admin_footer_scripts', 99 ); function func_hook_admin_footer_scripts(){ // for which taxonomies to change checkbox to radio $taxonomies = [ 'category', 'my_category' ]; $cs = get_current_screen(); if( $cs->base === 'post' && ($taxonomies = array_intersect( get_object_taxonomies( $cs->post_type ), $taxonomies )) ){ ?> <script> <?= json_encode($taxonomies) ?>.forEach(function(taxname){ jQuery( '#' + taxname + 'div input[type="checkbox"]' ).prop( 'type', 'radio' ); }) </script> <?php } }
Adding Post Types, Taxonomies to the "Right Now" Widget in the Dashboard
To see the numbers - how many posts of each type have been created right in the dashboard, you can extend the "Right Now" widget (previously called "At a Glance").

## Adds all post types to the "Right Now" widget in the dashboard add_action( 'dashboard_glance_items' , 'add_right_now_info' ); function add_right_now_info( $items ){ if( ! current_user_can('edit_posts') ) return $items; // exit // post types $args = array( 'public' => true, '_builtin' => false ); $post_types = get_post_types( $args, 'object', 'and' ); foreach( $post_types as $post_type ){ $num_posts = wp_count_posts( $post_type->name ); $num = number_format_i18n( $num_posts->publish ); $text = _n( $post_type->labels->singular_name, $post_type->labels->name, intval( $num_posts->publish ) ); $items[] = "<a href=\"edit.php?post_type=$post_type->name\">$num $text</a>"; } // taxonomies $taxonomies = get_taxonomies( $args, 'object', 'and' ); foreach( $taxonomies as $taxonomy ){ $num_terms = wp_count_terms( $taxonomy->name ); $num = number_format_i18n( $num_terms ); $text = _n( $taxonomy->labels->singular_name, $taxonomy->labels->name , intval( $num_terms ) ); $items[] = "<a href='edit-tags.php?taxonomy=$taxonomy->name'>$num $text</a>"; } // users global $wpdb; $num = $wpdb->get_var("SELECT COUNT(ID) FROM $wpdb->users"); $text = _n( 'User', 'Users', $num ); $items[] = "<a href='users.php'>$num $text</a>"; return $items; }
Read more about the code in a separate article.
Adds Post Thumbnails to the Posts Table in the Admin Panel
In the posts table in the admin panel, it is sometimes very convenient to see which thumbnail or first uploaded image is set for the post. This column can be easily added by installing a small piece of code.
It works automatically for all post types. But if the thumbnail is needed for specific ones, uncomment the line in the code and specify the post types for which the thumbnail should be displayed.
## Adds post thumbnails to the posts table in the admin panel if(1){ add_action('init', 'add_post_thumbs_in_post_list_table', 20 ); function add_post_thumbs_in_post_list_table(){ // check which posts support thumbnails $supports = get_theme_support('post-thumbnails'); // $ptype_names = array('post','page'); // specifies types for which the column is needed separately // Automatically determine post types if( ! isset($ptype_names) ){ if( $supports === true ){ $ptype_names = get_post_types(array( 'public'=>true ), 'names'); $ptype_names = array_diff( $ptype_names, array('attachment') ); } // for individual post types elseif( is_array($supports) ){ $ptype_names = $supports[0]; } } // add filters for all found post types foreach( $ptype_names as $ptype ){ add_filter( "manage_{$ptype}_posts_columns", 'add_thumb_column' ); add_action( "manage_{$ptype}_posts_custom_column", 'add_thumb_value', 10, 2 ); } } // add column function add_thumb_column( $columns ){ // adjust column width via css add_action('admin_notices', function(){ echo ' <style> .column-thumbnail{ width:80px; text-align:center; } </style>'; }); $num = 1; // after which column to insert new ones $new_columns = array( 'thumbnail' => __('Thumbnail') ); return array_slice( $columns, 0, $num ) + $new_columns + array_slice( $columns, $num ); } // fill the column function add_thumb_value( $colname, $post_id ){ if( 'thumbnail' == $colname ){ $width = $height = 45; // thumbnail if( $thumbnail_id = get_post_meta( $post_id, '_thumbnail_id', true ) ){ $thumb = wp_get_attachment_image( $thumbnail_id, array($width, $height), true ); } // from the gallery... elseif( $attachments = get_children( array( 'post_parent' => $post_id, 'post_mime_type' => 'image', 'post_type' => 'attachment', 'numberposts' => 1, 'order' => 'DESC', ) ) ){ $attach = array_shift( $attachments ); $thumb = wp_get_attachment_image( $attach->ID, array($width, $height), true ); } echo empty($thumb) ? ' ' : $thumb; } } }
Disabling Pings on Your Posts
When a post is published with a link in the text to another post on your site that has the ability to receive notifications enabled, a ping appears in the comments - a notification that the post was referenced somewhere. This is convenient to see that someone referred to your post, but when your site links to your site - it is illogical and even bothersome.
To disable this strange behavior, insert the following code into functions.php:
# Disabling pings on your own posts add_action( 'pre_ping', 'kama_disable_inner_ping' ); function kama_disable_inner_ping( & $links ){ foreach( $links as $k => $val ){ if( false !== strpos( $val, str_replace('www.', '', $_SERVER['HTTP_HOST']) ) ) unset( $links[$k] ); } }
Read more in the post: Disabling Pings on Your Posts
Disabling All Default WordPress Widgets
To disable all default WordPress widgets that exist by default, insert the following code into functions.php:
add_action( 'widgets_init', 'unregister_basic_widgets' ); function unregister_basic_widgets(){ unregister_widget( 'WP_Widget_Pages' ); // Pages widget unregister_widget( 'WP_Widget_Calendar' ); // Calendar unregister_widget( 'WP_Widget_Archives' ); // Archives unregister_widget( 'WP_Widget_Links' ); // Links unregister_widget( 'WP_Widget_Meta' ); // Meta widget unregister_widget( 'WP_Widget_Search' ); // Search unregister_widget( 'WP_Widget_Text' ); // Text unregister_widget( 'WP_Widget_Categories' ); // Categories unregister_widget( 'WP_Widget_Recent_Posts' ); // Recent posts unregister_widget( 'WP_Widget_Recent_Comments' ); // Recent comments unregister_widget( 'WP_Widget_RSS' ); // RSS unregister_widget( 'WP_Widget_Tag_Cloud' ); // Tag cloud unregister_widget( 'WP_Nav_Menu_Widget' ); // Menu }
Changing the Post Type Name
Build In PostBy default, WordPress has two post types: Posts and Pages. This example shows how to change their names throughout the admin area.
Sometimes it is convenient or logical to replace the word "Posts" and all related names of "Posts" in the admin area with another word, for example, "Articles":

The code is simple and works very quickly:
add_filter( 'post_type_labels_post', 'rename_posts_labels' ); # replace the word "posts" with "Articles" for post type 'post' function rename_posts_labels( $labels ){ // automatic replacement is not possible: Post = Article, and in the text we will get "View article" $new = [ 'name' => 'Articles', 'singular_name' => 'Article', 'add_new' => 'Add article', 'add_new_item' => 'Add article', 'edit_item' => 'Edit article', 'new_item' => 'New article', 'view_item' => 'View article', 'search_items' => 'Search articles', 'not_found' => 'Articles not found.', 'not_found_in_trash' => 'Articles not found in trash.', 'parent_item_colon' => '', 'all_items' => 'All articles', 'archives' => 'Article archives', 'insert_into_item' => 'Insert into article', 'uploaded_to_this_item' => 'Uploaded for this article', 'featured_image' => 'Article thumbnail', 'filter_items_list' => 'Filter articles list', 'items_list_navigation' => 'Articles list navigation', 'items_list' => 'Articles list', 'menu_name' => 'Articles', 'name_admin_bar' => 'Article', ]; return (object) array_merge( (array) $labels, $new ); }
Read more about how this code appeared in the question.
Disabling Update Notifications for Inactive Plugins
add_filter( 'transient_update_plugins', 'update_active_plugins' ); // Hook for 2.8.+ //add_filter( 'option_update_plugins', 'update_active_plugins' ); // Hook for 2.7.x function update_active_plugins( $value = '' ){ /* The $value array passed in contains the list of plugins with time marks when the last time the groups was checked for version match The $value->response node contains an array of the items that are out of date. This response node is used by the 'Plugins' menu for example to indicate there are updates. Also on the actual plugins listing to provide the yellow box below a given plugin to indicate action is needed by the user. */ if( (isset($value->response)) && (count($value->response)) ){ // Get the list cut current active plugins $active_plugins = get_option('active_plugins'); if ($active_plugins) { // Here we start to compare the $value->response // items checking each against the active plugins list. foreach($value->response as $plugin_idx => $plugin_item) { // If the response item is not an active plugin then remove it. // This will prevent WordPress from indicating the plugin needs update actions. if (!in_array($plugin_idx, $active_plugins)) unset($value->response[$plugin_idx]); } } else { // If no active plugins then ignore the inactive out of date ones. foreach($value->response as $plugin_idx => $plugin_item) { unset($value->response); } } } return $value; }
Important: disabling update notifications even for inactive plugins can be risky. When a plugin may have a vulnerable file that can be exploited regardless of the plugin's activity. However, this is quite rare...
Auto-Deleting license.txt and readme.html
In the main WordPress directory, there are these two files. Anyone can open them and determine that the site runs on WordPress and which version is being used.
This code will be a great addition to the Clearfy plugin.
How does it work? It checks for the file's existence when you enter the admin panel. If the file exists, PHP attempts to delete it automatically. If there are insufficient permissions to delete, the admin will see a message to manually delete the files license.txt and readme.html.
## Deleting files license.txt and readme.html for protection ## ver 2 if( is_admin() && ! defined('DOING_AJAX') ){ add_action( 'init', 'remove_license_txt_readme_html' ); function remove_license_txt_readme_html(){ $license_file = ABSPATH .'/license.txt'; $readme_file = ABSPATH .'/readme.html'; if( file_exists($license_file) && current_user_can('manage_options') ){ $deleted = unlink($license_file) && unlink($readme_file); if( ! $deleted ) $GLOBALS['readmedel'] = 'Failed to delete files: license.txt and readme.html from the folder `'. ABSPATH .'`. Please delete them manually!'; else $GLOBALS['readmedel'] = 'Files: license.txt and readme.html deleted from the folder `'. ABSPATH .'`.'; add_action( 'admin_notices', function(){ echo '<div class="error is-dismissible"><p>'. $GLOBALS['readmedel'] .'</p></div>'; } ); } } }
Search-Filter Taxonomy Elements by Names in the Admin Meta Box
Suppose you have many categories on your site, for example, 200. Or these can be non-standard categories but sections for WooCommerce. Finding the desired category (taxonomy element) in such a list is extremely inconvenient.
It would be convenient to have a filter so that you can type part of the category name and only terms that contain the entered substring remain in the meta box.
Insert the following code into the theme's functions.php, and you will get such a term filter:
## Filter elements in taxonomy for the taxonomy meta box in the admin panel. ## Allows convenient filtering (searching) of taxonomy elements by name when there are many add_action( 'admin_print_scripts', 'my_admin_term_filter', 99 ); function my_admin_term_filter() { $screen = get_current_screen(); if( 'post' !== $screen->base ) return; // only for the editing page of any post ?> <script> jQuery(document).ready(function($){ var $categoryDivs = $('.categorydiv'); $categoryDivs.prepend('<input type="search" class="fc-search-field" placeholder="filter..." style="width:100%" />'); $categoryDivs.on('keyup search', '.fc-search-field', function (event) { var searchTerm = event.target.value, $listItems = $(this).parent().find('.categorychecklist li'); if( $.trim(searchTerm) ){ $listItems.hide().filter(function () { return $(this).text().toLowerCase().indexOf(searchTerm.toLowerCase()) !== -1; }).show(); } else { $listItems.show(); } }); }); </script> <?php }
This code shows the entire branch if categories are in hierarchical form:
Source. Taken from the Post Category Filter
Menu Notifications in the Admin Panel (Counters in the Menu)
If there are updates for plugins, we see a circle with the number of plugins in the menu. Such circles with numbers can be added to any menu item. For example, we need to show such a notification if there are posts pending approval:
add_action( 'admin_menu', 'add_user_menu_bubble' ); function add_user_menu_bubble(){ global $menu; // posts $count = wp_count_posts()->pending; // pending approval if( $count ){ foreach( $menu as $key => $value ){ if( $menu[$key][2] == 'edit.php' ){ $menu[$key][0] .= ' <span class="awaiting-mod"><span class="pending-count">' . $count . '</span></span>'; break; } } } }
Recoloring the Admin Bar (Toolbar) for Different Environments
Build In PostUse wp_get_environment_type() to get the current development environment.
- standard black for Local development environment
- blue for QA (testing) and for development
- orange for staging
- red for production.
<?php /** * Adminpanel environment color for WordPress. * It helps to highlight environments in color. Developers, Content Managers, * and others will never confuse the environment where they work. * * Author: Andrei Pisarevskii * Author Email: [email protected] * Author Site: https://wp-yoda.com/en/ * * Version: 0.3 * Source Code: https://gist.github.com/renakdup/36f4a8474d0cb13ecadf0393811d5330 * * Licence: MIT License */ namespace Renakdup\AdminpanelEnvColor; AdminpanelEnvColor::init(); final class AdminpanelEnvColor { public static function init() { add_action( 'admin_head', [ __CLASS__, 'add_admin_bar_style' ] ); add_action( 'wp_head', [ __CLASS__, 'add_admin_bar_style' ] ); add_action( 'admin_bar_menu', [ __CLASS__, 'add_admin_bar_env_item' ], 100 ); } public static function add_admin_bar_style() { $adminpanel_colors = apply_filters( 'renakdup/adminpanel_env_color/colors', [ 'local' => null, // default wp color 'development' => '#2271b1', // blue 'staging' => '#cc6f00', // orange 'production' => '#6d0d0f', // red ] ); // phpcs:disable WordPress.CodeAnalysis.AssignmentInCondition.Found, Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure, WordPress.Security.EscapeOutput.OutputNotEscaped if ( $color = $adminpanel_colors[ wp_get_environment_type() ] ) { echo '<style> #wpadminbar { background-color: ' . $color . '!important; } #adminmenu li.wp-has-current-submenu a.wp-has-current-submenu { background-color: ' . $color . '!important; } </style>'; } // phpcs:enable echo '<style>.rd_adminpanel_env_color a { box-shadow: inset 0 32px 5px rgba(0, 0, 0, 0.5) !important; padding-left: 30px !important; padding-right: 30px !important; } </style>'; } /** * @param $wp_admin_bar \WP_Admin_Bar * * @return void */ public static function add_admin_bar_env_item( $wp_admin_bar ) { $args = [ 'id' => 'rd_adminpanel_env_color', 'parent' => 'top-secondary', 'title' => 'ENV: ' . ucfirst( wp_get_environment_type() ), 'href' => '#', 'meta' => [ 'class' => 'rd_adminpanel_env_color', 'title' => 'Your environment', ], ]; $wp_admin_bar->add_node( $args ); } }
To change the colors or names of environments, use the filter renakdup/adminpanel_env_color/colors
.
To disable coloring for specific roles, use remove_filter().
--
Read more in the original article.
-
Source: wordpress.stackexchange.com, personal experience, questions from this site, etc.