Opened 5 years ago
Last modified 5 years ago
#49332 new defect (bug)
method Walker_Nav_Menu::start_el should not call filter the_title on non post menu items
Reported by: | erwinbr | Owned by: | |
---|---|---|---|
Milestone: | Awaiting Review | Priority: | normal |
Severity: | normal | Version: | 5.3.2 |
Component: | Menus | Keywords: | |
Focuses: | Cc: |
Description
I am working on a site with a.o:
- WP 5.3.2
- WPML 4.3.6
- Estatik-pro 3.8.1
- Divi 3.29.1
And am seeing the following notices in the debug log:
PHP Notice: Trying to get property 'post_type' of non-object in .\wp-content\plugins\estatik-pro_3.8.1\functions.php on line 386
PHP Stack trace:
PHP 1. {main}() .\index.php:0
PHP 2. require() .\index.php:17
PHP 3. require_once() .\wp-blog-header.php:19
PHP 4. include() .\wp-includes\template-loader.php:98
PHP 5. get_header() .\wp-content\themes\Divi\single.php:3
PHP 6. locate_template() .\wp-includes\general-template.php:41
PHP 7. load_template() .\wp-includes\template.php:671
PHP 8. require_once() .\wp-includes\template.php:722
PHP 9. wp_nav_menu() .\wp-content\themes\Divi\header.php:263
PHP 10. walk_nav_menu_tree() .\wp-includes\nav-menu-template.php:217
PHP 11. Walker_Nav_Menu->walk() .\wp-includes\nav-menu-template.php:583
PHP 12. Walker_Nav_Menu->display_element() .\wp-includes\class-wp-walker.php:244
PHP 13. Walker_Nav_Menu->display_element() .\wp-includes\class-wp-walker.php:156
PHP 14. Walker_Nav_Menu->start_el() .\wp-includes\class-wp-walker.php:144
PHP 15. apply_filters() .\wp-includes\class-walker-nav-menu.php:213
PHP 16. WP_Hook->apply_filters() .\wp-includes\plugin.php:206
PHP 17. es_the_title_filter() .\wp-includes\class-wp-hook.php:288
(If you want, I can post a stack trace with variable info.)
Diving into this problem I noticed that:
- The main nav menu does not only contain items that are a post, but also the language switcher flags (added by WPML)
- On line 213 of file wp-includes/class-walker-nav-menu.php, Walker_Nav_Menu->start_el() calls
apply_filters( 'the_title', $item->title, $item->ID );
for all items in the menu, be it posts or other items. - Estatik-pro hooks into this filter and calls get_post() on the given ID which is not a post ID:
<?php function es_the_title_filter( $title, $id = null ) { global $es_settings; $post = get_post( $id ); if ( is_single() && $post->post_type == Es_Property::get_post_type_name() ) { ... } return $title; } add_filter( 'the_title', 'es_the_title_filter', 10, 2 );
Who is wrong?
- WPML: by adding non-posts to menu's.
- Estatik-pro for not checking that the filter is called for non-posts?
- Walker_Nav_Menu->start_el() for unconditionally calling the filter 'the_title' on all menu-items?
IMO:
- Menu-items can be other things than posts, and WPML shows that this is indeed possible.
- The filter 'the_title' seems to be explicitly for altering a post title, not titles of images, non-post menu-items, or whatever. So Estatik-pro should not have to check that the given ID is indeed from a post.
- Walker_Nav_Menu->start_el() calls its own filter 'nav_menu_item_title' directly after calling the 'the_title' filter (though still documenting $item as a WP_Post).
Based on the above, my conclusion is: Walker_Nav_Menu->start_el() should check if the item is a WP_Post before calling the 'the_title' filter.
If you agree, solving this should be easy, surround line 213 with
if ( $item instanceof WP_Post ) { ... }
However, in a lot of places it is documented that a menu-item is a WP_Post and changing that may take considerably more work.