Get last modified date for menu link

The nav_menu_link_attributes filter can be used to accomplish this, so a walker is not necessary. Here’s an example with comments along the way to explain what’s happening.

add_filter( 'nav_menu_link_attributes', 'wpse_nav_menu_link_attributes', 10, 4 );
/**
 * Filters the HTML attributes applied to a menu item's anchor element.
 *
 * Adds data-modified attribute to links.
 * - For single post types, the data-modified attribute's value stores the
 *   modified date for that post.
 *
 * - For post type archives, the data-modified attribute's value stores the
 *   modified date for the most recently published post in the archive.
 *
 * - For taxonomies, the data-modified attribute's value stores the
 *   modified date for the most recently published post assigned to the taxonomy term.
 *
 * ----
 *
 * Docs below via WordPress core.
 *
 * @param array $atts {
 *     The HTML attributes applied to the menu item's `<a>` element, empty strings are ignored.
 *
 *     @type string $title  Title attribute.
 *     @type string $target Target attribute.
 *     @type string $rel    The rel attribute.
 *     @type string $href   The href attribute.
 * }
 * @param WP_Post  $item  The current menu item.
 * @param stdClass $args  An object of wp_nav_menu() arguments.
 * @param int      $depth Depth of menu item. Used for padding.
 */
function wpse_nav_menu_link_attributes( $atts, $item, $args, $depth ) {

    // Get all post meta for this menu item. Post, Page, and other info is
    // stored in the menu item post's meta data.
    $item_meta = get_post_meta( $item->ID );

    // Modify date format to suit your preferneces.
    // http://php.net/manual/en/function.date.php
    $date_format="l F j, Y";

    // Bail if there is no meta.
    if ( ! $item_meta ) {
        return $atts;
    }

    $menu_item_type = false;
    // Bail if _menu_item_type is unavailable.
    if ( ! isset( $item_meta['_menu_item_type'][0] ) ) {
        return $atts;
    } else {
        $menu_item_type = $item_meta['_menu_item_type'][0]; // For readability.
    }

    // Handle post types and post type archives accordingly.
    switch ( $menu_item_type ) {

        /**
         * Handle single post type menu item type. E.g.: posts/pages/etc.
         */
        case 'post_type' :

            // Bail if _menu_item_object_id is unavailable.
            if ( ! isset( $item_meta['_menu_item_object_id'][0] ) ) {               
                return $atts;
            } else {
                $menu_item_object_id = $item_meta['_menu_item_object_id'][0]; // For readability.
            }

            // Handle special case when this is the page for posts.
            $show_on_front  = get_option( 'show_on_front' ); // 'page' for static front page, 'posts' for latest posts.
            $page_for_posts = get_option( 'page_for_posts' ); 
            if ( 'page' === $show_on_front && $page_for_posts === $menu_item_object_id ) {
                // Get the most recent post of the post post type. ...Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo.
                $recent_post = get_posts( [
                    'posts_per_page' => 1,
                    'post_type'      => 'post',
                    'orderby'        => 'date',
                    'order'          => 'DESC',                 
                    'post_status'    => 'publish',
                ] );

                // Add the data-modified attribute and set the date via the most recent post.
                if ( is_array( $recent_post ) ) {
                    $atts['data-modified'] = esc_attr( get_the_modified_date(
                            $date_format,
                            $recent_post[0]
                    ) );
                }

            // Handle typical case for single post/page/custom post type.
            } else { 
                // Add the data-modified attribute and set the value to post's modified date.
                $atts['data-modified'] = esc_attr( get_the_modified_date(
                        $date_format, 
                        get_post( $menu_item_object_id )
                ) );
            }
        break;

        /**
         *  Handle post type archive menu item type.
         */
        case 'post_type_archive' :

            // Bail if _menu_item_object is unavailable.
            if ( ! isset( $item_meta['_menu_item_object'][0] ) ) {              
                return $atts;
            } else {
                $menu_item_object = $item_meta['_menu_item_object'][0]; // For readability.
            }

            // Get the most recent post of this archive's type.
            $recent_post = get_posts( [
                'posts_per_page' => 1,
                'post_type'      => $menu_item_object,
                'orderby'        => 'date',
                'order'          => 'DESC',                 
                'post_status'    => 'publish',
            ] );

            // Add the data-modified attribute and set the date via the most recent post.
            if ( is_array( $recent_post ) ) {
                $atts['data-modified'] = esc_attr( get_the_modified_date(
                        $date_format,
                        $recent_post[0]
                ) );
            }
        break;

        /**
         *  Handle taxonomy menu item type.
         */
        case 'taxonomy' :

            // Bail if _menu_item_object is unavailable.
            if ( ! isset( $item_meta['_menu_item_object'][0] ) ) {              
                return $atts;
            } else {
                $menu_item_object = $item_meta['_menu_item_object'][0];
            }

            // Bail if _menu_item_object_id is unavailable.
            if ( ! isset( $item_meta['_menu_item_object_id'][0] ) ) {               
                return $atts;
            } else {
                $menu_item_object_id = $item_meta['_menu_item_object_id'][0];
            }

            // Get the most recent post using this taxonomy and term.
            $recent_post = get_posts( [
                'posts_per_page' => 1,
                'post_type'      => 'any',
                'orderby'        => 'date',
                'order'          => 'DESC',
                'post_status'    => 'publish',
                'tax_query' => array (
                    [
                        'taxonomy' => $menu_item_object,
                        'terms'    => $menu_item_object_id,
                        'field'    => 'id',
                    ],
                )       
            ] );            

            // Add the data-modified attribute and set the date via the most recent post using this taxonomy and term.
            if ( is_array( $recent_post ) ) {
                $atts['data-modified'] = esc_attr( get_the_modified_date(
                        $date_format,
                        $recent_post[0]
                ) );
            }
        break;

    } // end switch

    return $atts;
}

Note: Each link in a menu is stored as a custom post type named nav_menu_item. The additional information (such as the post ID that the menu item post points to) is stored in post meta. The post_id field of the meta will point back to the nav_menu_item‘s post id.

Leave a Comment