0

I have a menu, that I need to insert an image that have it's path saved in a meta key (_menu_item_img) and associated with a post ID, every menu entry has it's own image, and I need to grab it dynamically.

The approach I tried, and I can't find anything on google that could help me out.

wp_nav_menu( array( 'container' =>false, 'theme_location' => 'main_menu', 'menu_id' => 'main_menu', 'link_before' => get_post_meta($item->object_id, '_menu_item_img'))));

This is the class I'm using for adding a custom entry into the menu page:

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() {
        // @todo we can do some merging of provided options from WP options for from config
        self::$options['fields'] = array(
            'color' => array(
                'name' => 'img',
                'label' => __('Link para Imagem', 'xteam'),
                'container_class' => 'link-img',
                'input_type' => 'text',
            ),
        );

        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' ) );
    }

    static function get_fields_schema() {
        $schema = array();
        foreach(self::$options['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 _add_fields($new_fields, $item_output, $item, $depth, $args) {
        $schema = self::get_fields_schema($item->ID);
        foreach($schema 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) {
        if (get_post_type($post_id) !== 'nav_menu_item') {
            return;
        }
        $fields_schema = self::get_fields_schema($post_id);
        foreach($fields_schema as $field_schema) {
            $form_field_name = 'menu-item-' . $field_schema['name'];
            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);
            }
        }
    }

}

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);
        $new_fields = apply_filters( 'xteam_nav_menu_item_additional_fields', '', $item_output, $item, $depth, $args );
        // Inject $new_fields before: <div class="menu-item-actions description-wide submitbox">
        if ($new_fields) {
            $item_output = preg_replace('/(?=<div[^>]+class="[^"]*submitbox)/', $new_fields, $item_output);
        }
        $output .= $item_output;
    }
}

Can someone point me out where I am missing the point?

1 Answer 1

1

This code:

wp_nav_menu( array( 'container' =>false, 'theme_location' => 'main_menu', 'menu_id' => 'main_menu', 'link_before' => get_post_meta($item->object_id, '_menu_item_img'))));

Makes me think that the problem in on the front end when you try to display the values. For readability (and without the extra )):

wp_nav_menu( 
  array( 
    'container' =>false, 
    'theme_location' => 'main_menu', 
    'menu_id' => 'main_menu', 
    'link_before' => get_post_meta($item->object_id, '_menu_item_img')
  )
);

Essentially, the problem is pure PHP. If you had debugging enabled you'd notice that there is a Notice on the line where that code runs. That is because $item is not defined at that point. $item is defined as the walker callback actually executes but PHP doesn't notice your variable and wait until later to try to make sense of it. It is processed right there, when it is used.

You will need to create a custom walker for the front end display (something like this).

A filter on the_title might also do it:

function pre_title_wpse_134186($title) {
  return 'test'.$title;
}
add_filter('the_title','pre_title_wpse_134186');
wp_nav_menu( 
  array( 
    'container' =>false, 
    'theme_location' => 'main_menu', 
    'menu_id' => 'main_menu',
  )
);
remove_filter('the_title','pre_title_wpse_134186');

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.