PluginProbe
Gutenberg / 17.1.0
Gutenberg v17.1.0
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / compat / plugin / footnotes.php

footnotes.php in Gutenberg 17.1.0, at lib/compat/plugin/footnotes.php

251 lines 9.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Compatibility shim for the footnotes bloct to enable test passing while awaiting the tested code to be merged to core.
4 *
5 * See https://github.com/WordPress/gutenberg/pull/52988.
6 *
7 * Once merged, this shim can be removed.
8 *
9 * @package gutenberg
10 */
11
12 /**
13 * Remove footnote revision hooks when plugin is running on a version of core that already supports meta revisions.
14 */
15 if ( function_exists( 'wp_post_revision_meta_keys' ) ) {
16 if ( has_action( 'rest_after_insert_post', 'wp_add_footnotes_revisions_to_post_meta' ) ) {
17 remove_action( 'rest_after_insert_post', 'wp_add_footnotes_revisions_to_post_meta' );
18 }
19 if ( has_action( 'rest_after_insert_page', 'wp_add_footnotes_revisions_to_post_meta' ) ) {
20 remove_action( 'rest_after_insert_page', 'wp_add_footnotes_revisions_to_post_meta' );
21 }
22 if ( has_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' ) ) {
23 remove_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' );
24 }
25 if ( has_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' ) ) {
26 remove_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' );
27 }
28 if ( has_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision' ) ) {
29 remove_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision' );
30 }
31 if ( has_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' ) ) {
32 remove_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' );
33 }
34 if ( has_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' ) ) {
35 remove_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' );
36 }
37 if ( has_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference' ) ) {
38 remove_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference' );
39 }
40 } else {
41 /**
42 * For versions of core that don't support meta revisions, use hooks to add.
43 */
44 if ( ! function_exists( 'wp_save_footnotes_meta' ) ) {
45 /**
46 * Saves the footnotes meta value to the revision.
47 *
48 * @since 6.3.0
49 * @since 6.4.0 Core added post meta revisions, so this is no longer needed.
50 *
51 * @param int $revision_id The revision ID.
52 */
53 function wp_save_footnotes_meta( $revision_id ) {
54 $post_id = wp_is_post_revision( $revision_id );
55
56 if ( $post_id ) {
57 $footnotes = get_post_meta( $post_id, 'footnotes', true );
58
59 if ( $footnotes ) {
60 // Can't use update_post_meta() because it doesn't allow revisions.
61 update_metadata( 'post', $revision_id, 'footnotes', wp_slash( $footnotes ) );
62 }
63 }
64 }
65 if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) {
66 add_action( 'wp_after_insert_post', 'wp_save_footnotes_meta' );
67 }
68 }
69
70 if ( ! function_exists( 'wp_keep_footnotes_revision_id' ) ) {
71 /**
72 * Keeps track of the revision ID for "rest_after_insert_{$post_type}".
73 *
74 * @since 6.3.0
75 * @since 6.4.0 Core added post meta revisions, so this is no longer needed.
76 *
77 * @global int $wp_temporary_footnote_revision_id The footnote revision ID.
78 *
79 * @param int $revision_id The revision ID.
80 */
81 function wp_keep_footnotes_revision_id( $revision_id ) {
82 global $wp_temporary_footnote_revision_id;
83 $wp_temporary_footnote_revision_id = $revision_id;
84 }
85 if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) {
86 add_action( '_wp_put_post_revision', 'wp_keep_footnotes_revision_id' );
87 }
88 }
89
90 if ( ! function_exists( 'wp_add_footnotes_revisions_to_post_meta' ) ) {
91
92 /**
93 * This is a specific fix for the REST API. The REST API doesn't update
94 * the post and post meta in one go (through `meta_input`). While it
95 * does fix the `wp_after_insert_post` hook to be called correctly after
96 * updating meta, it does NOT fix hooks such as post_updated and
97 * save_post, which are normally also fired after post meta is updated
98 * in `wp_insert_post()`. Unfortunately, `wp_save_post_revision` is
99 * added to the `post_updated` action, which means the meta is not
100 * available at the time, so we have to add it afterwards through the
101 * `"rest_after_insert_{$post_type}"` action.
102 *
103 * @since 6.3.0
104 * @since 6.4.0 Core added post meta revisions, so this is no longer needed.
105 *
106 * @global int $wp_temporary_footnote_revision_id The footnote revision ID.
107 *
108 * @param WP_Post $post The post object.
109 */
110 function wp_add_footnotes_revisions_to_post_meta( $post ) {
111 global $wp_temporary_footnote_revision_id;
112
113 if ( $wp_temporary_footnote_revision_id ) {
114 $revision = get_post( $wp_temporary_footnote_revision_id );
115
116 if ( ! $revision ) {
117 return;
118 }
119
120 $post_id = $revision->post_parent;
121
122 // Just making sure we're updating the right revision.
123 if ( $post->ID === $post_id ) {
124 $footnotes = get_post_meta( $post_id, 'footnotes', true );
125
126 if ( $footnotes ) {
127 // Can't use update_post_meta() because it doesn't allow revisions.
128 update_metadata( 'post', $wp_temporary_footnote_revision_id, 'footnotes', wp_slash( $footnotes ) );
129 }
130 }
131 }
132 }
133
134 if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) {
135 add_action( 'rest_after_insert_post', 'wp_add_footnotes_revisions_to_post_meta' );
136 add_action( 'rest_after_insert_page', 'wp_add_footnotes_revisions_to_post_meta' );
137 }
138 }
139
140 if ( ! function_exists( 'wp_restore_footnotes_from_revision' ) ) {
141
142 /**
143 * Restores the footnotes meta value from the revision.
144 *
145 * @since 6.3.0
146 * @since 6.4.0 Core added post meta revisions, so this is no longer needed.
147 *
148 * @param int $post_id The post ID.
149 * @param int $revision_id The revision ID.
150 */
151 function wp_restore_footnotes_from_revision( $post_id, $revision_id ) {
152 $footnotes = get_post_meta( $revision_id, 'footnotes', true );
153
154 if ( $footnotes ) {
155 update_post_meta( $post_id, 'footnotes', wp_slash( $footnotes ) );
156 } else {
157 delete_post_meta( $post_id, 'footnotes' );
158 }
159 }
160 if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) {
161 add_action( 'wp_restore_post_revision', 'wp_restore_footnotes_from_revision', 10, 2 );
162 }
163 }
164
165 if ( ! function_exists( '_wp_rest_api_autosave_meta' ) ) {
166
167 /**
168 * The REST API autosave endpoint doesn't save meta, so we can use the
169 * `wp_creating_autosave` when it updates an exiting autosave, and
170 * `_wp_put_post_revision` when it creates a new autosave.
171 *
172 * @since 6.3.0
173 * @since 6.4.0 Core added post meta revisions, so this is no longer needed.
174 *
175 * @param int|array $autosave The autosave ID or array.
176 */
177 function _wp_rest_api_autosave_meta( $autosave ) {
178 // Ensure it's a REST API request.
179 if ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) {
180 return;
181 }
182
183 $body = rest_get_server()->get_raw_data();
184 $body = json_decode( $body, true );
185
186 if ( ! isset( $body['meta']['footnotes'] ) ) {
187 return;
188 }
189
190 // `wp_creating_autosave` passes the array,
191 // `_wp_put_post_revision` passes the ID.
192 $id = is_int( $autosave ) ? $autosave : $autosave['ID'];
193
194 if ( ! $id ) {
195 return;
196 }
197
198 // Can't use update_post_meta() because it doesn't allow revisions.
199 update_metadata( 'post', $id, 'footnotes', wp_slash( $body['meta']['footnotes'] ) );
200 }
201
202 if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) {
203 // See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L391C1-L391C1.
204 add_action( 'wp_creating_autosave', '_wp_rest_api_autosave_meta' );
205 // See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L398.
206 // Then https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/revision.php#L367.
207 add_action( '_wp_put_post_revision', '_wp_rest_api_autosave_meta' );
208 }
209 }
210
211 if ( ! function_exists( '_wp_rest_api_force_autosave_difference' ) ) {
212
213 /**
214 * This is a workaround for the autosave endpoint returning early if the
215 * revision field are equal. The problem is that "footnotes" is not real
216 * revision post field, so there's nothing to compare against.
217 *
218 * This trick sets the "footnotes" field (value doesn't matter), which will
219 * cause the autosave endpoint to always update the latest revision. That should
220 * be fine, it should be ok to update the revision even if nothing changed. Of
221 * course, this is temporary fix.
222 *
223 * @since 6.3.0
224 * @since 6.4.0 Core added post meta revisions, so this is no longer needed.
225 *
226 * @param WP_Post $prepared_post The prepared post object.
227 * @param WP_REST_Request $request The request object.
228 *
229 * See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L365-L384.
230 * See https://github.com/WordPress/wordpress-develop/blob/2103cb9966e57d452c94218bbc3171579b536a40/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php#L219.
231 */
232 function _wp_rest_api_force_autosave_difference( $prepared_post, $request ) {
233 // We only want to be altering POST requests.
234 if ( $request->get_method() !== 'POST' ) {
235 return $prepared_post;
236 }
237
238 // Only alter requests for the '/autosaves' route.
239 if ( substr( $request->get_route(), -strlen( '/autosaves' ) ) !== '/autosaves' ) {
240 return $prepared_post;
241 }
242
243 $prepared_post->footnotes = '[]';
244 return $prepared_post;
245 }
246 if ( ! function_exists( 'wp_post_revision_meta_keys' ) ) {
247 add_filter( 'rest_pre_insert_post', '_wp_rest_api_force_autosave_difference', 10, 2 );
248 }
249 }
250 }
251