Classic Editor preview shows published field values on every other click when the post has `_acf_changed` saved in its meta

Open
#1,052 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
php, wordpress
Domain
backend

Research direction

Start with includes/revisions.php, especially acf_revisions::wp_preview_post_fields() and the _acf_changed revision registration described in the report. Trace how WordPress creates and restores Classic Editor autosaves, then reproduce the alternating preview behavior with a published post whose _acf_changed meta is 1. Done means repeated previews keep showing the current unsaved field values without leaving the request flag on the parent post.

Written by the indexing model from the issue text.

Description

Describe the bug

In the Classic Editor, on a published post, if the post's own meta contains _acf_changed with a value of 1, then previewing a change to an ACF field only works on every other click. On alternate clicks WordPress deletes the autosave, and the preview shows the published values.

This came to us through a WPGraphQL for ACF report (https://github.com/wp-graphql/wp-graphql/issues/4529), but it reproduces in WordPress's own front-end preview with only ACF PRO and the Classic Editor plugin active.

The cause, as far as I can tell:

  • acf_revisions::wp_preview_post_fields() (revisions.php#L150-L163) adds _acf_changed to the revision fields on a preview request, so that wp_create_post_autosave() sees the autosave as different from the post and updates it rather than deleting it.
  • wp_create_post_autosave() compares the posted _acf_changed ('1') against $post->_acf_changed, which WP_Post::__get() reads from the post's meta. Normally that's empty, so the values differ and the autosave is kept.
  • Since 6.2.6, _acf_changed is registered with revisions_enabled (revisions.php#L52-L78), so restoring an autosave from the Revisions screen copies _acf_changed = 1 onto the post itself, and later updates don't remove it.
  • Once the post has 1 saved, the comparison matches. If title, content and excerpt are unchanged too, WordPress decides the autosave is identical to the post and deletes it. The next click creates a fresh autosave, the one after deletes it again, and so on.

To Reproduce

  1. Activate ACF PRO and the Classic Editor plugin.
  2. Create a field group with a Text field, shown on Pages.
  3. Create a page, set the field to A, and publish it. Render the field in the template, or use any other way to view the preview.
  4. Change the title and set the field to B, click Preview, then leave the editor without updating.
  5. Go to the page's Revisions screen and click "Restore This Autosave".
  6. wp post meta get <page-id> _acf_changed now returns 1. Clicking Update in the editor afterwards doesn't clear it.
  7. In the editor, change only the field to C and click Preview: the preview shows C.
  8. Click Preview again without changing anything: the preview shows the published value, and the autosave has been deleted.
  9. Keep clicking: it alternates between the two.

Deleting the meta (wp post meta delete <page-id> _acf_changed) makes every click work again. Changing the title or content along with the field also avoids it.

Expected behavior

Every preview click shows the current unsaved field values. _acf_changed is a request flag, so it shouldn't end up persisted on the parent post, or the comparison shouldn't depend on what's stored there.

Possible fixes, in case they're useful:

  • don't restore _acf_changed onto the parent post in wp_restore_post_revision (or delete it from the parent afterwards)
  • in wp_preview_post_fields(), set a value that can't match stored meta, for example a timestamp or a random string, rather than relying on the post not having 1 saved

The block editor isn't affected, because the REST autosave controller compares meta strictly and always sees a difference.

Version Information:

  • WordPress 7.0
  • PHP 8.3.35
  • ACF PRO 6.8.4 (the original report was on 6.3.8, which has the same revisions code)
  • Classic Editor 1.7.0
  • Chromium (headless, driven by Playwright)

Additional context

AdvancedCustomFields/acf#903 covers block editor previews and is a different problem.

Dominant language
PHP
Stars
947
Forks
198
PR merge metrics
No merged PRs in 30d

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from AdvancedCustomFields/acf

All issues in AdvancedCustomFields/acf

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.