Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Footnotes: fix published preview #53072

Merged
merged 6 commits into from
Aug 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 ↩︎' );
} );
} );