Make WordPress Core


Ignore:
Timestamp:
09/26/2023 03:30:34 PM (9 months ago)
Author:
adamsilverstein
Message:

Revisions: framework for storing post meta revisions.

Enable the storing of post meta in revisions including autosaves and previews:

Add a new argument revisions_enabled to the register_meta function which enables storing meta in revisions.

Add a new wp_post_revision_meta_keys filter which developers can use to control which meta is revisioned - it passes an array of the meta keys with revisions enabled as well as the post type.

Meta keys with revisions enabled are also stored for autosaves, and are restored when a revision or autosave is restored. In addition, meta values are now stored with the autosave revision used for previews. Changes to meta can now be previewed correctly without overwriting the published meta (see #20299) or passing data as a query variable, as the editor currently does to preview changes to the featured image.

Changes to meta with revisions enabled are considered when determining if a new revision should be created. A new revision is created if the meta value has changed since the last revision.

Revisions are now saved on the wp_after_insert_post hook instead of post_updated. The wp_after_insert_post action is fired after post meta has been saved by the REST API which enables attaching meta to the revision. To ensure backwards compatibility with existing action uses, wp_save_post_revision_on_insert function exits early if plugins have removed the previous do_action( 'post_updated', 'wp_save_post_revision' ) call.

Props: alexkingorg, johnbillion, markjaquith, WraithKenny, kovshenin, azaozz, tv-productions, p51labs, mattheu, mikeschroder, Mamaduka, ellatrix, timothyblynjacobs, jakemgold, bookwyrm, ryanduff, mintindeed, wonderboymusic, sanchothefat, westonruter, spacedmonkey, hellofromTonya, drewapicture, adamsilverstein, swisspiddy.
Fixes #20564, #20299.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-admin/includes/post.php

    r56712 r56714  
    19711971         *
    19721972         * @since 4.1.0
     1973         * @since 6.4.0 The `$is_update` parameter was added to indicate if the autosave is being updated or was newly created.
    19731974         *
    19741975         * @param array $new_autosave Post array - the autosave that is about to be saved.
     1976         * @param bool  $is_update    Whether this is an existing autosave.
    19751977         */
    1976         do_action( 'wp_creating_autosave', $new_autosave );
    1977 
     1978        do_action( 'wp_creating_autosave', $new_autosave, true );
    19781979        return wp_update_post( $new_autosave );
    19791980    }
     
    19831984
    19841985    // Otherwise create the new autosave as a special post revision.
    1985     return _wp_put_post_revision( $post_data, true );
     1986    $revision = _wp_put_post_revision( $post_data, true );
     1987
     1988    if ( ! is_wp_error( $revision ) && 0 !== $revision ) {
     1989
     1990        /** This action is documented in wp-admin/includes/post.php */
     1991        do_action( 'wp_creating_autosave', get_post( $revision, ARRAY_A ), false );
     1992    }
     1993
     1994    return $revision;
     1995}
     1996
     1997/**
     1998 * Autosave the revisioned meta fields.
     1999 *
     2000 * Iterates through the revisioned meta fields and checks each to see if they are set,
     2001 * and have a changed value. If so, the meta value is saved and attached to the autosave.
     2002 *
     2003 * @since 6.4.0
     2004 *
     2005 * @param array $new_autosave The new post data being autosaved.
     2006 */
     2007function wp_autosave_post_revisioned_meta_fields( $new_autosave ) {
     2008    /*
     2009     * The post data arrives as either $_POST['data']['wp_autosave'] or the $_POST
     2010     * itself. This sets $posted_data to the correct variable.
     2011     *
     2012     * Ignoring sanitization to avoid altering meta. Ignoring the nonce check because
     2013     * this is hooked on inner core hooks where a valid nonce was already checked.
     2014     *
     2015     * @phpcs:disable WordPress.Security
     2016     */
     2017    $posted_data = isset( $_POST['data']['wp_autosave'] ) ? $_POST['data']['wp_autosave'] : $_POST;
     2018    // phpcs:enable
     2019
     2020    $post_type = get_post_type( $new_autosave['post_parent'] );
     2021
     2022    /*
     2023     * Go thru the revisioned meta keys and save them as part of the autosave, if
     2024     * the meta key is part of the posted data, the meta value is not blank and
     2025     * the the meta value has changes from the last autosaved value.
     2026     */
     2027    foreach ( wp_post_revision_meta_keys( $post_type ) as $meta_key ) {
     2028
     2029        if (
     2030        isset( $posted_data[ $meta_key ] ) &&
     2031        get_post_meta( $new_autosave['ID'], $meta_key, true ) !== wp_unslash( $posted_data[ $meta_key ] )
     2032        ) {
     2033            /*
     2034             * Use the underlying delete_metadata() and add_metadata() functions
     2035             * vs delete_post_meta() and add_post_meta() to make sure we're working
     2036             * with the actual revision meta.
     2037             */
     2038            delete_metadata( 'post', $new_autosave['ID'], $meta_key );
     2039
     2040            /*
     2041             * One last check to ensure meta value not empty().
     2042             */
     2043            if ( ! empty( $posted_data[ $meta_key ] ) ) {
     2044                /*
     2045                 * Add the revisions meta data to the autosave.
     2046                 */
     2047                add_metadata( 'post', $new_autosave['ID'], $meta_key, $posted_data[ $meta_key ] );
     2048            }
     2049        }
     2050    }
    19862051}
    19872052
Note: See TracChangeset for help on using the changeset viewer.