Skip to content

Commit

Permalink
Footnotes: fix published preview (#53072)
Browse files Browse the repository at this point in the history
* Footnotes: fix published preview

* remove var dump

* Fix php lint

* PHP lint

* Address feedback

* Add e2e test
  • Loading branch information
ellatrix committed Aug 1, 2023
1 parent ee96729 commit cddff11
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 5 deletions.
73 changes: 73 additions & 0 deletions packages/block-library/src/footnotes/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,76 @@ function wp_get_footnotes_from_revision( $revision_field, $field, $revision ) {
return get_metadata( 'post', $revision->ID, $field, true );
}
add_filter( 'wp_post_revision_field_footnotes', 'wp_get_footnotes_from_revision', 10, 3 );

/**
* The REST API autosave endpoint doesn't save meta, so we can use the
* `wp_creating_autosave` when it updates an exiting autosave, and
* `_wp_put_post_revision` when it creates a new autosave.
*
* @since 6.3.0
*
* @param int|array $autosave The autosave ID or array.
*/
function _wp_rest_api_autosave_meta( $autosave ) {
// Ensure it's a REST API request.
if ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) {
return;
}

$body = rest_get_server()->get_raw_data();
$body = json_decode( $body, true );

if ( ! isset( $body['meta']['footnotes'] ) ) {
return;
}

// `wp_creating_autosave` passes the array,
// `_wp_put_post_revision` passes the ID.
$id = is_int( $autosave ) ? $autosave : $autosave['ID'];

if ( ! $id ) {
return;
}

update_post_meta( $id, 'footnotes', $body['meta']['footnotes'] );
}
// See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L391C1-L391C1.
add_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' );
// See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L398.
// Then https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/revision.php#L367.
add_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' );

/**
* This is a workaround for the autosave endpoint returning early if the
* revision field are equal. The problem is that "footnotes" is not real
* revision post field, so there's nothing to compare against.
*
* This trick sets the "footnotes" field (value doesn't matter), which will
* cause the autosave endpoint to always update the latest revision. That should
* be fine, it should be ok to update the revision even if nothing changed. Of
* course, this is temporary fix.
*
* @since 6.3.0
*
* @param WP_Post $prepared_post The prepared post object.
* @param WP_REST_Request $request The request object.
*
* See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L365-L384.
* See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L219.
*/
function _wp_rest_api_force_autosave_difference( $prepared_post, $request ) {
// We only want to be altering POST requests.
if ( $request->get_method() !== 'POST' ) {
return $prepared_post;
}

// Only alter requests for the '/autosaves' route.
if ( substr( $request->get_route(), -strlen( '/autosaves' ) ) !== '/autosaves' ) {
return $prepared_post;
}

$prepared_post->footnotes = '[]';
return $prepared_post;
}

add_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference', 10, 2 );
9 changes: 6 additions & 3 deletions packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,12 @@ export const saveEntityRecord =
data = Object.keys( data ).reduce(
( acc, key ) => {
if (
[ 'title', 'excerpt', 'content' ].includes(
key
)
[
'title',
'excerpt',
'content',
'meta',
].includes( key )
) {
acc[ key ] = data[ key ];
}
Expand Down
4 changes: 2 additions & 2 deletions packages/editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,8 @@ export const isEditedPostAutosaveable = createRegistrySelector(
return true;
}

// If the title or excerpt has changed, the post is autosaveable.
return [ 'title', 'excerpt' ].some(
// If title, excerpt, or meta have changed, the post is autosaveable.
return [ 'title', 'excerpt', 'meta' ].some(
( field ) =>
getPostRawValue( autosave[ field ] ) !==
getEditedPostAttribute( state, field )
Expand Down
40 changes: 40 additions & 0 deletions test/e2e/specs/editor/various/footnotes.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,4 +360,44 @@ test.describe( 'Footnotes', () => {
},
] );
} );

test( 'can be previewed when published', async ( { editor, page } ) => {
await editor.canvas.click( 'role=button[name="Add default block"i]' );
await page.keyboard.type( 'a' );

await editor.showBlockToolbar();
await editor.clickBlockToolbarButton( 'More' );
await page.locator( 'button:text("Footnote")' ).click();

await page.keyboard.type( '1' );

// Publish post.
await editor.publishPost();

await editor.canvas.click( 'ol.wp-block-footnotes li span' );
await page.keyboard.press( 'End' );
await page.keyboard.type( '2' );

const editorPage = page;
const previewPage = await editor.openPreviewPage();

await expect(
previewPage.locator( 'ol.wp-block-footnotes li' )
).toHaveText( '12 ↩︎' );

await previewPage.close();
await editorPage.bringToFront();

// Test again, this time with an existing revision (different code
// path).
await editor.canvas.click( 'ol.wp-block-footnotes li span' );
await page.keyboard.press( 'End' );
await page.keyboard.type( '3' );

const previewPage2 = await editor.openPreviewPage();

await expect(
previewPage2.locator( 'ol.wp-block-footnotes li' )
).toHaveText( '123 ↩︎' );
} );
} );

0 comments on commit cddff11

Please sign in to comment.