Support

Account

Home Forums General Issues Saved Drafts not displaying custom fields

Solving

Saved Drafts not displaying custom fields

  • Same issue here, WordPress 4.9.16.


    @figureone
    If you need test results for suggested changes, let me know.

    Edit: Found similar issue here in another thread, suggestion of CamiloAPR there seems to work, not sure why.

  • Hi, this issue is also appearing for me. WP 5.5.3 with Classic Editor. get_field just returns null when GET preview=true.

  • Same problem here, with WP 5.5.3 / ACF 5.9.2 / Classic Editor 1.6 (unset $_GET[‘preview’] works).

  • Aloha Elliot,

    I have traced the issue (on vanilla WordPress) to a change in version 5.9.2 to includes/acf-meta-functions.php. The result is that ACF postmeta does not get created for revision IDs in the database. This happens whether you are saving a draft, or updating a published page. This means:
    * if you try to preview an unpublished revision, you won’t see any ACF fields (the original problem in this thread);
    * if you try to browse revisions, you will see empty ACF postmeta for all the revisions
    * if you try to restore a revision, it won’t have any ACF postmeta associated with it, causing the post’s ACF fields to be deleted.

    Because of that 3rd point, this is probably higher severity. Here’s the diff that causes the issue in acf_update_metadata():

    @@ -240,17 +238,14 @@ function acf_update_metadata( $post_id = 0, $name = '', $value = '', $hidden = f
        return false;
      }
    
    - // Update option.
    - if( $type === 'option' ) {
    -
    + // Determine CRUD function.
    + if( function_exists("update_{$type}_meta") ) {
    +   return call_user_func("update_{$type}_meta", $id, "{$prefix}{$name}", $value);
    + } else {
        // Unslash value to match update_metadata() functionality.
        $value = wp_unslash( $value );
        $autoload = (bool) acf_get_setting('autoload');
        return update_option( "{$prefix}{$id}_{$name}", $value, $autoload );
    -
    - // Update meta.
    - } else {
    -   return update_metadata( $type, $id, "{$prefix}{$name}", $value );
      }
     }

    I can confirm that reverting the change above restores functionality (i.e., ACF saves postmeta to revision IDs when saving/updating a post).

    These are related changes (to acf_get_metadata() and acf_delete_metadata()), just in case they are relevant:

    diff --git a/includes/acf-meta-functions.php b/includes/acf-meta-functions.php
    index 1d26f03..9e8c81a 100644
    --- a/includes/acf-meta-functions.php
    +++ b/includes/acf-meta-functions.php
    @@ -196,14 +196,12 @@ function acf_get_metadata( $post_id = 0, $name = '', $hidden = false ) {
        return null;
      }
    
    - // Check option.
    - if( $type === 'option' ) {
    -   return get_option( "{$prefix}{$id}_{$name}", null );
    -
    - // Check meta.
    - } else {
    -   $meta = get_metadata( $type, $id, "{$prefix}{$name}", false );
    + // Determine CRUD function.
    + if( function_exists("get_{$type}_meta") ) {
    +   $meta = call_user_func("get_{$type}_meta", $id, "{$prefix}{$name}", false);
        return isset($meta[0]) ? $meta[0] : null;
    + } else {
    +   return get_option( "{$prefix}{$id}_{$name}", null );
      }
     }
    
    @@ -286,14 +281,12 @@ function acf_delete_metadata( $post_id = 0, $name = '', $hidden = false ) {
        return false;
      }
    
    - // Update option.
    - if( $type === 'option' ) {
    + // Determine CRUD function.
    + if( function_exists("delete_{$type}_meta") ) {
    +   return call_user_func("delete_{$type}_meta", $id, "{$prefix}{$name}");
    + } else {
        $autoload = (bool) acf_get_setting('autoload');
        return delete_option( "{$prefix}{$id}_{$name}" );
    -
    - // Update meta.
    - } else {
    -   return delete_metadata( $type, $id, "{$prefix}{$name}" );
      }
     }
    
  • Aloha Elliot,

    I have traced the issue (on vanilla WordPress) to a change in version 5.9.2 to includes/acf-meta-functions.php. The result is that ACF postmeta does not get created for revision IDs in the database. This happens whether you are saving a draft, or updating a published page. This means:
    * if you try to preview an unpublished revision, you won’t see any ACF fields (the original problem in this thread);
    * if you try to browse revisions, you will see empty ACF postmeta for all the revisions
    * if you try to restore a revision, it won’t have any ACF postmeta associated with it, causing the post’s ACF fields to be deleted.

    Because of that 3rd point, this is probably higher severity. Here’s the diff that causes the issue in acf_update_metadata():

    @@ -240,17 +238,14 @@ function acf_update_metadata( $post_id = 0, $name = '', $value = '', $hidden = f
        return false;
      }
    
    - // Update option.
    - if( $type === 'option' ) {
    -
    + // Determine CRUD function.
    + if( function_exists("update_{$type}_meta") ) {
    +   return call_user_func("update_{$type}_meta", $id, "{$prefix}{$name}", $value);
    + } else {
        // Unslash value to match update_metadata() functionality.
        $value = wp_unslash( $value );
        $autoload = (bool) acf_get_setting('autoload');
        return update_option( "{$prefix}{$id}_{$name}", $value, $autoload );
    -
    - // Update meta.
    - } else {
    -   return update_metadata( $type, $id, "{$prefix}{$name}", $value );
      }
     }
    
    

    I can confirm that reverting the change above restores functionality (i.e., ACF saves postmeta to revision IDs when saving/updating a post).

    These are related changes (to acf_get_metadata() and acf_delete_metadata()), just in case they are relevant:

    
    diff --git a/includes/acf-meta-functions.php b/includes/acf-meta-functions.php
    index 1d26f03..9e8c81a 100644
    --- a/includes/acf-meta-functions.php
    +++ b/includes/acf-meta-functions.php
    @@ -196,14 +196,12 @@ function acf_get_metadata( $post_id = 0, $name = '', $hidden = false ) {
        return null;
      }
    
    - // Check option.
    - if( $type === 'option' ) {
    -   return get_option( "{$prefix}{$id}_{$name}", null );
    -
    - // Check meta.
    - } else {
    -   $meta = get_metadata( $type, $id, "{$prefix}{$name}", false );
    + // Determine CRUD function.
    + if( function_exists("get_{$type}_meta") ) {
    +   $meta = call_user_func("get_{$type}_meta", $id, "{$prefix}{$name}", false);
        return isset($meta[0]) ? $meta[0] : null;
    + } else {
    +   return get_option( "{$prefix}{$id}_{$name}", null );
      }
     }
    
    @@ -286,14 +281,12 @@ function acf_delete_metadata( $post_id = 0, $name = '', $hidden = false ) {
        return false;
      }
    
    - // Update option.
    - if( $type === 'option' ) {
    + // Determine CRUD function.
    + if( function_exists("delete_{$type}_meta") ) {
    +   return call_user_func("delete_{$type}_meta", $id, "{$prefix}{$name}");
    + } else {
        $autoload = (bool) acf_get_setting('autoload');
        return delete_option( "{$prefix}{$id}_{$name}" );
    -
    - // Update meta.
    - } else {
    -   return delete_metadata( $type, $id, "{$prefix}{$name}" );
      }
     }
    
  • Aloha Elliot,

    I looked up the docs and found that the problem is caused by a subtle difference between update_post_meta() and update_metadata(). In version 5.9.2, you switched to using update_{$type}_meta() in includes/acf-meta-functions.php, but these wrapper functions do not allow updating meta on revisions. See the comment in the core source:
    https://developer.wordpress.org/reference/functions/update_post_meta/#source

    This also applies to delete_post_meta(), FYI:
    https://developer.wordpress.org/reference/functions/delete_post_meta/#source

    So basically when you switched, all acf_update_metadata() and acf_delete_metadata() calls now operate on the parent post if a revision ID is specified. I would suggest reverting to update_metadata() and delete_metadata() to avoid this.

    https://developer.wordpress.org/reference/functions/update_post_meta/
    https://developer.wordpress.org/reference/functions/update_metadata/

  • Hi @figureone

    Thanks so much for digging into this. This looks like a major oversight on our behalf! Please allow me to review the source code in detail and I’ll be in touch shortly.

  • Sounds good, thanks for the quick response!

    I ended up diagnosing the issue by doing a diff of all changes between 5.9.1 and 5.9.2, and slowly reverting changes back to 5.9.1 until I saw the problem disappear. Here’s the gist of just the relevant changes, if needed:
    https://gist.github.com/figureone/66fb7004596dc611ae7b3165193461ac

    It looks like you were refactoring to better split up changes to options vs. meta, by relying on the existence of "update_{$type}_meta to determine whether to do a meta update or an options update.

    If you want to keep that style, you can maybe use if ( get_meta_table( $type ) ) instead, and then follow with a call to update_metadata( $type, ... ) if it’s true, and update_option() if not. (Similar for the get and delete variants.)

    Looks like that’s how core does the check in update_metadata():
    https://developer.wordpress.org/reference/functions/update_metadata/#source

  • @figureone You are absolutely spot-on! Thanks mate.

    I’ve reviewed, tested and implemented a fix to the meta functions which you can find in the following Gist: https://gist.github.com/elliotcondon/9d3f3f94b51581150b434e3cd7c566cd

    Can you please copy and replace the contents of this Gist into the “includes/acf-meta-functions.php” file and retest the revisions issue?

    Hoping to hear back from you shortly. I’ll continue testing on our end, and can confirm positive results so far.

  • Just tested the hotfix: works great!

  • Thanks @figureone – Glad to have you confirming the fix!

  • FYI, hotfix appears also to work fine with WordPress 4.9.16.

    Thanks everybody for reports, investigation and quick support.

  • Works with WP 5.5.3 too. Thank you all.

Viewing 13 posts - 51 through 63 (of 63 total)

The topic ‘Saved Drafts not displaying custom fields’ is closed to new replies.