Skip to content

Instantly share code, notes, and snippets.

@iksent
Created September 10, 2019 06:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save iksent/153632acbf0ed772d51c049fa031a52d to your computer and use it in GitHub Desktop.
Save iksent/153632acbf0ed772d51c049fa031a52d to your computer and use it in GitHub Desktop.
Add new fields to nav_menu_item posts in the WordPress menu editor.
<?php
require_once plugin_dir_path( __FILE__ ) . '/CustomWalkerNavMenuEdit.php';
class AdminMenusImprover {
/**
* Class instance.
*
* @var AdminTaxonomiesImprover instance
*/
protected static $instance = false;
/**
* @var array
*/
private static $fields = [];
/**
* Get class instance
*/
public static function get_instance() {
if ( ! self::$instance ) {
self::$instance = new self();
self::$instance->do_hooks();
}
return self::$instance;
}
function do_hooks() {
add_action( 'init', array( $this, 'setup' ) );
}
function setup() {
if ( ! is_admin() ) {
return;
}
$this->init_fields();
add_filter( 'wp_edit_nav_menu_walker', function () {
return 'CustomWalkerNavMenuEdit';
} );
add_action( 'save_post', array( $this, 'save_fields_values' ), 10, 2 );
}
/*
* HERE you must add your fields
*/
static function init_fields() {
self::$fields = [
'color' => [
'label' => __('Color', 'YOUR_LANGUAGE_KEY'),
'type' => 'color'
],
'badge' => [
'label' => __('Badge', 'YOUR_LANGUAGE_KEY'),
//'type' => 'text',
//'is_full_width' => true
]
];
}
/**
* Generator for Id of item meta
*/
static function get_meta_key( $name ) {
$slug = 'FOR_EXAMPLE__YOUR_PLUGIN_SLUG';
return $slug . '_menu_item_' . $name;
}
/**
* Get current field value with definite name for definite menu item
*/
static function get_field_value( $menu_item_id, $name ) {
return get_post_meta( $menu_item_id, self::get_meta_key( $name ), true );
}
/**
* Get result fields HTML for single menu item
*/
public static function get_fields_html( $item, $depth, $args ) {
$new_fields = '';
foreach ( self::$fields as $name => $field ) {
$new_fields .= self::generate_field_html(
$item->ID,
$name,
self::get_field_value( $item->ID, $name ),
$field
);
}
return $new_fields;
}
/**
* Generate single field html
* @return string
*/
static function generate_field_html( $id, $name, $value, $field ) {
$is_full_width = isset( $field['is_full_width'] ) ? $field['is_full_width'] : false;
$label = isset( $field['label'] ) ? $field['label'] : '';
$type = isset( $field['type'] ) ? $field['type'] : 'text';
$class = $is_full_width ? 'wide' : 'thin';
return "
<p class='additional-menu-field-{$name} description description-{$class}'>
<label for='edit-menu-item-{$name}-{$id}'>
{$label}<br>
<input
type='{$type}'
id='edit-menu-item-{$name}-{$id}'
class='widefat code edit-menu-item-{$name}'
name='menu-item-{$name}[{$id}]'
value='{$value}'>
</label>
</p>
";
}
/**
* Save the newly submitted fields
* @hook {action} save_post
*/
public function save_fields_values( $post_id, $post ) {
if ( $post->post_type !== 'nav_menu_item' ) {
return $post_id; // prevent weird things from happening
}
foreach ( self::$fields as $name => $field ) {
$form_field_name = 'menu-item-' . $name;
if ( isset( $_POST[ $form_field_name ][ $post_id ] ) ) {
$key = self::get_meta_key( $name );
$value = stripslashes( $_POST[ $form_field_name ][ $post_id ] );
update_post_meta( $post_id, $key, $value );
}
}
}
}
<?php
require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
require_once plugin_dir_path( __FILE__ ) . '/AdminMenusImprover.php';
class CustomWalkerNavMenuEdit extends Walker_Nav_Menu_Edit {
function start_el( &$output, $item, $depth = 0, $args = [], $id = 0 ) {
$item_output = '';
parent::start_el( $item_output, $item, $depth, $args );
// Inject $new_fields before: <div class="menu-item-actions description-wide submitbox">
if ( $new_fields = AdminMenusImprover::get_fields_html( $item, $depth, $args ) ) {
$item_output = preg_replace( '/(?=<div[^>]+class="[^"]*submitbox)/', $new_fields, $item_output );
}
$output .= $item_output;
}
}
@iksent
Copy link
Author

iksent commented Sep 10, 2019

For starting using it, just copy 2 files, import AdminMenusImprover and call anywhere in admin file:
AdminMenusImprover::get_instance();

Here is the result.
2019-09-10_11-26-27

@iksent
Copy link
Author

iksent commented Sep 12, 2019

I have found the right way to make it: we must use this walker to be compatible with other plugins and themes.
If someone needs to rewrite the code using this walker, just leave a comment here, I will provide a new code with the changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment