PluginProbe
Advanced Custom Fields (ACF®) / 6.1.0
Advanced Custom Fields (ACF®) v6.1.0
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 All 230 releases
advanced-custom-fields / includes / revisions.php
revisions.php
448 lines 9.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly
5 }
6
7 if ( ! class_exists( 'acf_revisions' ) ) :
8 #[AllowDynamicProperties]
9 class acf_revisions {
10
11 // vars
12 var $cache = array();
13
14
15 /*
16 * __construct
17 *
18 * A good place to add actions / filters
19 *
20 * @type function
21 * @date 11/08/13
22 *
23 * @param N/A
24 * @return N/A
25 */
26
27 function __construct() {
28
29 // actions
30 add_action( 'wp_restore_post_revision', array( $this, 'wp_restore_post_revision' ), 10, 2 );
31
32 // filters
33 add_filter( 'wp_save_post_revision_check_for_changes', array( $this, 'wp_save_post_revision_check_for_changes' ), 10, 3 );
34 add_filter( '_wp_post_revision_fields', array( $this, 'wp_preview_post_fields' ), 10, 2 );
35 add_filter( '_wp_post_revision_fields', array( $this, 'wp_post_revision_fields' ), 10, 2 );
36 add_filter( 'acf/validate_post_id', array( $this, 'acf_validate_post_id' ), 10, 2 );
37
38 }
39
40
41 /*
42 * wp_preview_post_fields
43 *
44 * This function is used to trick WP into thinking that one of the $post's fields has changed and
45 * will allow an autosave to be updated.
46 * Fixes an odd bug causing the preview page to render the non autosave post data on every odd attempt
47 *
48 * @type function
49 * @date 21/10/2014
50 * @since 5.1.0
51 *
52 * @param $fields (array)
53 * @return $fields
54 */
55
56 function wp_preview_post_fields( $fields ) {
57
58 // bail early if not previewing a post
59 if ( acf_maybe_get_POST( 'wp-preview' ) !== 'dopreview' ) {
60 return $fields;
61 }
62
63 // add to fields if ACF has changed
64 if ( acf_maybe_get_POST( '_acf_changed' ) ) {
65
66 $fields['_acf_changed'] = 'different than 1';
67
68 }
69
70 // return
71 return $fields;
72
73 }
74
75
76 /*
77 * wp_save_post_revision_check_for_changes
78 *
79 * This filter will return false and force WP to save a revision. This is required due to
80 * WP checking only post_title, post_excerpt and post_content values, not custom fields.
81 *
82 * @type filter
83 * @date 19/09/13
84 *
85 * @param $return (boolean) defaults to true
86 * @param $last_revision (object) the last revision that WP will compare against
87 * @param $post (object) the $post that WP will compare against
88 * @return $return (boolean)
89 */
90
91 function wp_save_post_revision_check_for_changes( $return, $last_revision, $post ) {
92
93 // if acf has changed, return false and prevent WP from performing 'compare' logic
94 if ( acf_maybe_get_POST( '_acf_changed' ) ) {
95 return false;
96 }
97
98 // return
99 return $return;
100
101 }
102
103
104 /*
105 * wp_post_revision_fields
106 *
107 * This filter will add the ACF fields to the returned array
108 * Versions 3.5 and 3.6 of WP feature different uses of the revisions filters, so there are
109 * some hacks to allow both versions to work correctly
110 *
111 * @type filter
112 * @date 11/08/13
113 *
114 * @param $post_id (int)
115 * @return $post_id (int)
116 */
117
118 function wp_post_revision_fields( $fields, $post = null ) {
119
120 // validate page
121 if ( acf_is_screen( 'revision' ) || acf_is_ajax( 'get-revision-diffs' ) ) {
122
123 // bail early if is restoring
124 if ( acf_maybe_get_GET( 'action' ) === 'restore' ) {
125 return $fields;
126 }
127
128 // allow
129
130 } else {
131
132 // bail early (most likely saving a post)
133 return $fields;
134
135 }
136
137 // vars
138 $append = array();
139 $order = array();
140 $post_id = acf_maybe_get( $post, 'ID' );
141
142 // compatibility with WP < 4.5 (test)
143 if ( ! $post_id ) {
144
145 global $post;
146 $post_id = $post->ID;
147
148 }
149
150 // get all postmeta
151 $meta = get_post_meta( $post_id );
152
153 // bail early if no meta
154 if ( ! $meta ) {
155 return $fields;
156 }
157
158 // loop
159 foreach ( $meta as $name => $value ) {
160
161 // attempt to find key value
162 $key = acf_maybe_get( $meta, '_' . $name );
163
164 // bail early if no key
165 if ( ! $key ) {
166 continue;
167 }
168
169 // update vars
170 $value = $value[0];
171 $key = $key[0];
172
173 // Load field.
174 $field = acf_get_field( $key );
175 if ( ! $field ) {
176 continue;
177 }
178
179 // get field
180 $field_title = $field['label'] . ' (' . $name . ')';
181 $field_order = $field['menu_order'];
182 $ancestors = acf_get_field_ancestors( $field );
183
184 // ancestors
185 if ( ! empty( $ancestors ) ) {
186
187 // vars
188 $count = count( $ancestors );
189 $oldest = acf_get_field( $ancestors[ $count - 1 ] );
190
191 // update vars
192 $field_title = str_repeat( '- ', $count ) . $field_title;
193 $field_order = $oldest['menu_order'] . '.1';
194
195 }
196
197 // append
198 $append[ $name ] = $field_title;
199 $order[ $name ] = $field_order;
200
201 // hook into specific revision field filter and return local value
202 add_filter( "_wp_post_revision_field_{$name}", array( $this, 'wp_post_revision_field' ), 10, 4 );
203
204 }
205
206 // append
207 if ( ! empty( $append ) ) {
208
209 // vars
210 $prefix = '_';
211
212 // add prefix
213 $append = acf_add_array_key_prefix( $append, $prefix );
214 $order = acf_add_array_key_prefix( $order, $prefix );
215
216 // sort by name (orders sub field values correctly)
217 array_multisort( $order, $append );
218
219 // remove prefix
220 $append = acf_remove_array_key_prefix( $append, $prefix );
221
222 // append
223 $fields = $fields + $append;
224
225 }
226
227 // return
228 return $fields;
229
230 }
231
232
233 /*
234 * wp_post_revision_field
235 *
236 * This filter will load the value for the given field and return it for rendering
237 *
238 * @type filter
239 * @date 11/08/13
240 *
241 * @param $value (mixed) should be false as it has not yet been loaded
242 * @param $field_name (string) The name of the field
243 * @param $post (mixed) Holds the $post object to load from - in WP 3.5, this is not passed!
244 * @param $direction (string) to / from - not used
245 * @return $value (string)
246 */
247 function wp_post_revision_field( $value, $field_name, $post = null, $direction = false ) {
248
249 // bail early if is empty.
250 if ( empty( $value ) ) {
251 return '';
252 }
253
254 $value = acf_maybe_unserialize( $value );
255 $post_id = $post->ID;
256
257 // load field.
258 $field = acf_maybe_get_field( $field_name, $post_id );
259
260 // default formatting.
261 if ( is_array( $value ) ) {
262 $value = implode( ', ', $value );
263 } elseif ( is_object( $value ) ) {
264 $value = serialize( $value );
265 }
266
267 // image.
268 if ( is_array( $field ) && isset( $field['type'] ) && ( $field['type'] === 'image' || $field['type'] === 'file' ) ) {
269 $url = wp_get_attachment_url( $value );
270 $value = $value . ' (' . $url . ')';
271 }
272
273 return $value;
274 }
275
276
277 /*
278 * wp_restore_post_revision
279 *
280 * This action will copy and paste the metadata from a revision to the post
281 *
282 * @type action
283 * @date 11/08/13
284 *
285 * @param $parent_id (int) the destination post
286 * @return $revision_id (int) the source post
287 */
288
289 function wp_restore_post_revision( $post_id, $revision_id ) {
290
291 // copy postmeta from revision to post (restore from revision)
292 acf_copy_postmeta( $revision_id, $post_id );
293
294 // Make sure the latest revision is also updated to match the new $post data
295 // get latest revision
296 $revision = acf_get_post_latest_revision( $post_id );
297
298 // save
299 if ( $revision ) {
300
301 // copy postmeta from revision to latest revision (potentialy may be the same, but most likely are different)
302 acf_copy_postmeta( $revision_id, $revision->ID );
303
304 }
305
306 }
307
308
309 /*
310 * acf_validate_post_id
311 *
312 * This function will modify the $post_id and allow loading values from a revision
313 *
314 * @type function
315 * @date 6/3/17
316 * @since 5.5.10
317 *
318 * @param $post_id (int)
319 * @param $_post_id (int)
320 * @return $post_id (int)
321 */
322
323 function acf_validate_post_id( $post_id, $_post_id ) {
324
325 // phpcs:disable WordPress.Security.NonceVerification.Recommended
326 // bail early if no preview in URL
327 if ( ! isset( $_GET['preview'] ) ) {
328 return $post_id;
329 }
330
331 // bail early if $post_id is not numeric
332 if ( ! is_numeric( $post_id ) ) {
333 return $post_id;
334 }
335
336 // vars
337 $k = $post_id;
338 $preview_id = 0;
339
340 // check cache
341 if ( isset( $this->cache[ $k ] ) ) {
342 return $this->cache[ $k ];
343 }
344
345 // validate
346 if ( isset( $_GET['preview_id'] ) ) {
347
348 $preview_id = (int) $_GET['preview_id'];
349
350 } elseif ( isset( $_GET['p'] ) ) {
351
352 $preview_id = (int) $_GET['p'];
353
354 } elseif ( isset( $_GET['page_id'] ) ) {
355
356 $preview_id = (int) $_GET['page_id'];
357
358 }
359 // phpcs:enable WordPress.Security.NonceVerification.Recommended
360
361 // bail early id $preview_id does not match $post_id
362 if ( $preview_id != $post_id ) {
363 return $post_id;
364 }
365
366 // attempt find revision
367 $revision = acf_get_post_latest_revision( $post_id );
368
369 // save
370 if ( $revision && $revision->post_parent == $post_id ) {
371
372 $post_id = (int) $revision->ID;
373
374 }
375
376 // set cache
377 $this->cache[ $k ] = $post_id;
378
379 // return
380 return $post_id;
381
382 }
383
384 }
385
386 // initialize
387 acf()->revisions = new acf_revisions();
388
389 endif; // class_exists check
390
391
392 /*
393 * acf_save_post_revision
394 *
395 * This function will copy meta from a post to it's latest revision
396 *
397 * @type function
398 * @date 26/09/2016
399 * @since 5.4.0
400 *
401 * @param $post_id (int)
402 * @return n/a
403 */
404
405 function acf_save_post_revision( $post_id = 0 ) {
406
407 // get latest revision
408 $revision = acf_get_post_latest_revision( $post_id );
409
410 // save
411 if ( $revision ) {
412
413 acf_copy_postmeta( $post_id, $revision->ID );
414
415 }
416
417 }
418
419
420 /*
421 * acf_get_post_latest_revision
422 *
423 * This function will return the latest revision for a given post
424 *
425 * @type function
426 * @date 25/06/2016
427 * @since 5.3.8
428 *
429 * @param $post_id (int)
430 * @return $post_id (int)
431 */
432
433 function acf_get_post_latest_revision( $post_id ) {
434
435 // vars
436 $revisions = wp_get_post_revisions( $post_id );
437
438 // shift off and return first revision (will return null if no revisions)
439 $revision = array_shift( $revisions );
440
441 // return
442 return $revision;
443
444 }
445
446
447
448