Skip to content

Instantly share code, notes, and snippets.

@foysalit
Created July 11, 2013 22:41
Show Gist options
  • Select an option

  • Save foysalit/5979971 to your computer and use it in GitHub Desktop.

Select an option

Save foysalit/5979971 to your computer and use it in GitHub Desktop.
Adding custom field in the wordpress nav menu items. and displaying the field values using a custom walker class.
/**
* Proof of concept for how to add new fields to nav_menu_item posts in the WordPress menu editor.
* @author Weston Ruter (@westonruter), X-Team
* direct link to the gist - https://gist.github.com/kucrut/3804376
*/
add_action( 'init', array( 'XTeam_Nav_Menu_Item_Custom_Fields', 'setup' ) );
class XTeam_Nav_Menu_Item_Custom_Fields {
static $options = array(
'item_tpl' => '
<p class="additional-menu-field-{name} description description-thin">
<label for="edit-menu-item-{name}-{id}">
{label}<br>
<input
type="{input_type}"
id="edit-menu-item-{name}-{id}"
class="widefat code edit-menu-item-{name}"
name="menu-item-{name}[{id}]"
value="{value}">
</label>
</p>
',
);
static function setup() {
if ( !is_admin() )
return;
$new_fields = apply_filters( 'xteam_nav_menu_item_additional_fields', array() );
if ( empty($new_fields) )
return;
self::$options['fields'] = self::get_fields_schema( $new_fields );
add_filter( 'wp_edit_nav_menu_walker', function () {
return 'XTeam_Walker_Nav_Menu_Edit';
});
//add_filter( 'xteam_nav_menu_item_additional_fields', array( __CLASS__, '_add_fields' ), 10, 5 );
add_action( 'save_post', array( __CLASS__, '_save_post' ), 10, 2 );
}
static function get_fields_schema( $new_fields ) {
$schema = array();
foreach( $new_fields as $name => $field) {
if (empty($field['name'])) {
$field['name'] = $name;
}
$schema[] = $field;
}
return $schema;
}
static function get_menu_item_postmeta_key($name) {
return '_menu_item_' . $name;
}
/**
* Inject the
* @hook {action} save_post
*/
static function get_field( $item, $depth, $args ) {
$new_fields = '';
foreach( self::$options['fields'] as $field ) {
$field['value'] = get_post_meta($item->ID, self::get_menu_item_postmeta_key($field['name']), true);
$field['id'] = $item->ID;
$new_fields .= str_replace(
array_map(function($key){ return '{' . $key . '}'; }, array_keys($field)),
array_values(array_map('esc_attr', $field)),
self::$options['item_tpl']
);
}
return $new_fields;
}
/**
* Save the newly submitted fields
* @hook {action} save_post
*/
static function _save_post($post_id, $post) {
if ( $post->post_type !== 'nav_menu_item' ) {
return $post_id; // prevent weird things from happening
}
foreach( self::$options['fields'] as $field_schema ) {
$form_field_name = 'menu-item-' . $field_schema['name'];
// @todo FALSE should always be used as the default $value, otherwise we wouldn't be able to clear checkboxes
if (isset($_POST[$form_field_name][$post_id])) {
$key = self::get_menu_item_postmeta_key($field_schema['name']);
$value = stripslashes($_POST[$form_field_name][$post_id]);
update_post_meta($post_id, $key, $value);
}
}
}
}
// @todo This class needs to be in it's own file so we can include id J.I.T.
// requiring the nav-menu.php file on every page load is not so wise
require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
class XTeam_Walker_Nav_Menu_Edit extends Walker_Nav_Menu_Edit {
function start_el(&$output, $item, $depth, $args) {
$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 = XTeam_Nav_Menu_Item_Custom_Fields::get_field( $item, $depth, $args ) ) {
$item_output = preg_replace('/(?=<div[^>]+class="[^"]*submitbox)/', $new_fields, $item_output);
}
$output .= $item_output;
}
}
// To add a new field just create a new array like the $fields['color'] and add it into the hook
// Somewhere in config...
add_filter( 'xteam_nav_menu_item_additional_fields', 'mytheme_menu_item_additional_fields' );
function mytheme_menu_item_additional_fields( $fields ) {
$fields['color'] = array(
'name' => 'color',
'label' => __('Color', 'xteam'),
'container_class' => 'link-color',
'input_type' => 'color',
);
return $fields;
}
/**
* Now whereever you want to use these custom field values in the menu
* you need to passa custom walker class with the wp_nav_menu call and
* you need to add a custom walker class like below
*/
wp_nav_menu(array (
'menu' => 'header_menu',
'container' => FALSE,
'container_id' => FALSE,
'menu_class' => '',
'menu_id' => FALSE,
'depth' => 1,
'walker' => new Custom_Walker
));
/**
* Create HTML list of nav menu items.
* Replacement for the native Walker, using the description.
*
* @see http://wordpress.stackexchange.com/q/14037/
* @author toscho, http://toscho.de
*/
class Custom_Walker extends Walker_Nav_Menu
{
/**
* Start the element output.
*
* @param string $output Passed by reference. Used to append additional content.
* @param object $item Menu item data object.
* @param int $depth Depth of menu item. May be used for padding.
* @param array $args Additional strings.
* @return void
*/
function start_el(&$output, $item, $depth, $args)
{
$classes = empty ( $item->classes ) ? array () : (array) $item->classes;
$class_names = join(
' '
, apply_filters(
'nav_menu_css_class'
, array_filter( $classes ), $item
)
);
! empty ( $class_names )
and $class_names = ' class="'. esc_attr( $class_names ) . '"';
$output .= "<li id='menu-item-$item->ID' $class_names>";
$attributes = '';
! empty( $item->attr_title )
and $attributes .= ' title="' . esc_attr( $item->attr_title ) .'"';
! empty( $item->target )
and $attributes .= ' target="' . esc_attr( $item->target ) .'"';
! empty( $item->xfn )
and $attributes .= ' rel="' . esc_attr( $item->xfn ) .'"';
! empty( $item->url )
and $attributes .= ' href="' . esc_attr( $item->url ) .'"';
// insert description for top level elements only
// you may change this
$description = ( ! empty ( $item->description ) and 0 == $depth )
? '<small class="nav_desc">' . esc_attr( $item->description ) . '</small>' : '';
$title = apply_filters( 'the_title', $item->title, $item->ID );
//get the value of the custom fields
//the meta key value needs to be prepened by _menu_item
//so if the custom field was added by using the key named "color" the meta key would be "_menu_item_color"
$cf = get_post_meta($item->ID, '_menu_item_color', true);
//var_dump($cf);
$item_output = $args->before
. "<a $attributes>"
. $args->link_before
. $title
. '</a> '
. $args->link_after
. $description
. $args->after;
// Since $output is called by reference we don't need to return anything.
$output .= apply_filters(
'walker_nav_menu_start_el'
, $item_output
, $item
, $depth
, $args
);
}
}
@berkaygeldec
Copy link
Copy Markdown

adding code to the top of the page?

@berkaygeldec
Copy link
Copy Markdown

I turned to the text field but write how the data in that field?

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