Since yesterday the wp_scheduled_auto_draft_delete
cron job somehow deletes all page entries from our menus. All entries in the table wp_postmeta
with meta_key = '_menu_item_object'
and meta_value="page"
get deleted in the process. By tracing back the DELETE query I found out that the menu entries are deleted by a function called _wp_delete_post_menu_item
. I got the following stacktrace for that function:
#0 _wp_delete_post_menu_item(3244)
#1 call_user_func_array(_wp_delete_post_menu_item, Array ([0] => 3244))
called at [/srv/www/htdocs/biva/wp-includes/plugin.php:470]
#2 do_action(delete_post, 3244) called at
[/srv/www/htdocs/biva/wp-includes/post.php:2483]
#3 wp_delete_post(3244, 1) called at
[/srv/www/htdocs/biva/wp-includes/post.php:5645]
#4 wp_delete_auto_drafts()
#5 call_user_func_array(wp_delete_auto_drafts, Array ()) called at
[/srv/www/htdocs/biva/wp-includes/plugin.php:546]
#6 do_action_ref_array(wp_scheduled_auto_draft_delete, Array ()) called
at [/srv/www/htdocs/biva/wp-cron.php:100]
But I’m stuck here, I’m not a wordpress developer and I have no clue why deleting old drafts results in deleting attached menu entries although the main pages still exist.
Workaround:
As a workaround we added the following to the top of wp-config
, wich will disable wp-cron
:
/** Disable wp-cron to prevent menu from getting deleted. Detailed Bug description:
http://wordpress.stackexchange.com/questions/145953 **/
define('DISABLE_WP_CRON', true);
If you are experiencing similar difficulties you might try locking the rows in the table wp_postmeta
with meta_key = '_menu_item_object'
and meta_value="page"
and then tracing back the error message when WP trys to delete these rows, that’s how we nailed down our error.
Reproduce the Error:
It is definitely the stealth publish plugin that is causing our error, one can easily reproduce it, by doing the following:
- Install a fresh WordPress 3.9.1.
- Install the stealth publish plugin http://wordpress.org/plugins/stealth-publish.
- Create a few test pages and add them to a new menu.
- Create a new page, with some dummy content, but do not save it!. Leave the page without saving.
- Change the system time 8 days into the future.
- The
wp_scheduled_auto_draft_delete
cron job will run because it runs daily and it hasn’t run for 7 days as soon as you visit your page. It will then find your never saved dummy page delete it as it is older than 7 days and the menu will vanish. - You might need to refresh the page a few times till the effect becomes visible.
I’ve recorded a screencast on how to reproduce the error (but I took not the time to comment it): http://www.youtube.com/watch?v=R9CTggjIfDY
1 Answer
This is what normal query run by wp_get_associated_nav_menu_items()
looks like:
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_postmeta
ON ( wp_posts.id = wp_postmeta.post_id )
WHERE 1 = 1
AND wp_posts.post_type="nav_menu_item"
AND (( wp_posts.post_status <> 'trash'
AND wp_posts.post_status <> 'auto-draft' ))
AND (( wp_postmeta.meta_key = '_menu_item_object_id'
AND Cast(wp_postmeta.meta_value AS CHAR) = '3111' ))
GROUP BY wp_posts.id
ORDER BY wp_posts.post_date DESC
This is what yours looks like:
SELECT wp_posts.*
FROM wp_posts
INNER JOIN wp_postmeta
ON ( wp_posts.id = wp_postmeta.post_id )
LEFT JOIN wp_postmeta AS mt1
ON ( wp_posts.id = mt1.post_id
AND mt1.meta_key = '_stealth-publish' )
INNER JOIN wp_postmeta AS mt2
ON ( wp_posts.id = mt2.post_id )
WHERE 1 = 1
AND wp_posts.post_type="nav_menu_item"
AND (( wp_posts.post_status <> 'trash'
AND wp_posts.post_status <> 'auto-draft' ))
AND ( ( wp_postmeta.meta_key = '_menu_item_object_id'
AND Cast(wp_postmeta.meta_value AS CHAR) = '3244' )
OR mt1.post_id IS NULL
OR ( mt2.meta_key = '_stealth-publish'
AND Cast(mt2.meta_value AS CHAR) != '1' ) )
GROUP BY wp_posts.id
ORDER BY wp_posts.post_date DESC
It would be my guess that _stealth-publish
stuff has no business whatsoever interfering with querying for nav menu items.