Ticket #20564: 20564.11.diff
File 20564.11.diff, 11.2 KB (added by , 11 years ago) |
---|
-
src/wp-admin/includes/post.php
1314 1314 } else { 1315 1315 $post_id = (int) $post_data['post_ID']; 1316 1316 } 1317 1318 1317 $post_data = _wp_translate_postdata( true, $post_data ); 1319 1318 if ( is_wp_error( $post_data ) ) 1320 1319 return $post_data; 1321 1320 1322 1321 $post_author = get_current_user_id(); 1323 1324 1322 // Store one autosave per author. If there is already an autosave, overwrite it. 1325 1323 if ( $old_autosave = wp_get_post_autosave( $post_id, $post_author ) ) { 1326 1324 $new_autosave = _wp_post_revision_fields( $post_data, true ); 1327 1325 $new_autosave['ID'] = $old_autosave->ID; 1328 1326 $new_autosave['post_author'] = $post_author; 1329 1327 1328 // Auto-save revisioned meta fields. 1329 foreach ( _wp_post_revision_meta_keys() as $meta_key ) { 1330 if ( isset( $_POST[ $meta_key ] ) 1331 && get_post_meta( $new_autosave['ID'], $meta_key, true ) != wp_unslash( $_POST[ $meta_key ] ) ) 1332 { 1333 /* 1334 * Use the underlying delete_metadata() and add_metadata() functions 1335 * vs delete_post_meta() and add_post_meta() to make sure we're working 1336 * with the actual revision meta. 1337 */ 1338 delete_metadata( 'post', $new_autosave['ID'], $meta_key ); 1339 if ( ! empty( $_POST[ $meta_key ] ) ) { 1340 add_metadata( 'post', $new_autosave['ID'], $meta_key, $_POST[ $meta_key ] ); 1341 } 1342 } 1343 } 1344 1330 1345 // If the new autosave has the same content as the post, delete the autosave. 1331 1346 $post = get_post( $post_id ); 1332 1347 $autosave_is_different = false; -
src/wp-includes/revision.php
28 28 if ( !$fields ) { 29 29 // Allow these to be versioned 30 30 $fields = array( 31 'post_title' => __( 'Title' ),31 'post_title' => __( 'Title' ), 32 32 'post_content' => __( 'Content' ), 33 33 'post_excerpt' => __( 'Excerpt' ), 34 34 ); 35 35 36 // Runs only once 36 /** 37 * Filter the list of post fields to be revisioned. 38 * 39 * Fields are only revisioned once. 40 * 41 * @since 3.9.0 42 * 43 * @param array $fields An array of fields to be revisioned. 44 */ 37 45 $fields = apply_filters( '_wp_post_revision_fields', $fields ); 38 46 39 47 // WP uses these internally either in versioning or elsewhere - they cannot be versioned 40 foreach ( array( 'ID', 'post_name', 'post_parent', 'post_date', 'post_date_gmt', 'post_status', 'post_type', 'comment_count', 'post_author' ) as $protect ) 48 foreach ( array( 'ID', 'post_name', 'post_parent', 'post_date', 'post_date_gmt', 'post_status', 'post_type', 'comment_count', 'post_author' ) as $protect ) { 41 49 unset( $fields[$protect] ); 50 } 42 51 } 43 52 44 53 if ( !is_array($post) ) … … 59 68 } 60 69 61 70 /** 71 * Determine which post meta fields should be revisioned. 72 * 73 * @access private 74 * @since 3.9.0 75 * 76 * @return array An array of meta keys to be revisioned. 77 */ 78 function _wp_post_revision_meta_keys() { 79 /** 80 * Filter the list of post meta keys to be revisioned. 81 * 82 * @since 3.9.0 83 * 84 * @param array $keys An array of default meta fields to be revisioned. 85 */ 86 return apply_filters( 'wp_post_revision_meta_keys', array() ); 87 } 88 89 /** 62 90 * Saves an already existing post as a post revision. 63 91 * 64 92 * Typically used immediately after post updates. … … 102 130 if ( isset( $last_revision ) && apply_filters( 'wp_save_post_revision_check_for_changes', true, $last_revision, $post ) ) { 103 131 $post_has_changed = false; 104 132 133 // Check whether revisioned post fields have been changed. 105 134 foreach ( array_keys( _wp_post_revision_fields() ) as $field ) { 106 135 if ( normalize_whitespace( $post->$field ) != normalize_whitespace( $last_revision->$field ) ) { 107 136 $post_has_changed = true; 108 137 break; 109 138 } 110 139 } 111 //don't save revision if post unchanged 140 141 // Check whether revisioned post meta fields have changed. 142 foreach ( _wp_post_revision_meta_keys() as $meta_key ) { 143 if ( get_post_meta( $post->ID, $meta_key ) != get_post_meta( $last_revision->ID, $meta_key ) ) { 144 $post_has_changed = true; 145 break; 146 } 147 } 148 149 // Don't save revision if the post is unchanged. 112 150 if( ! $post_has_changed ) 113 151 return; 114 152 } … … 240 278 if ( $revision_id ) 241 279 do_action( '_wp_put_post_revision', $revision_id ); 242 280 281 // Save revisioned meta fields. 282 foreach ( _wp_post_revision_meta_keys() as $meta_key ) { 283 $meta_value = get_post_meta( $post_id, $meta_key, true ); 284 if ( empty( $meta_value ) ) { 285 continue; 286 } 287 288 /* 289 * Use the underlying add_metadata() function vs add_post_meta() 290 * to ensure metadata is added to the revision post and not its parent. 291 */ 292 add_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta_value ) ); 293 } 294 243 295 return $revision_id; 244 296 } 245 297 … … 307 359 308 360 $update['ID'] = $revision['post_parent']; 309 361 362 // Restore revisioned meta fields. 363 foreach ( _wp_post_revision_meta_keys() as $meta_key ) { 364 $meta_value = get_post_meta( $revision['ID'], $meta_key, true ); 365 if ( empty( $meta_value ) ) { 366 $meta_value = ''; 367 } 368 // Add slashes to data pulled from the database. 369 update_post_meta( $update['ID'], $meta_key, wp_slash( $meta_value ) ); 370 } 371 310 372 $update = wp_slash( $update ); //since data is from db 311 373 312 374 $post_id = wp_update_post( $update ); … … 448 510 $post->post_excerpt = $preview->post_excerpt; 449 511 450 512 add_filter( 'get_the_terms', '_wp_preview_terms_filter', 10, 3 ); 513 add_filter( 'get_post_metadata', '_wp_preview_meta_filter', 10, 4 ); 451 514 452 515 return $post; 453 516 } … … 471 534 } 472 535 473 536 /** 537 * Filters post meta retrieval to get values from the actual autosave post, 538 * and not its parent. 539 * 540 * Filters revisioned meta keys only. 541 * 542 * @access private 543 * @since 3.9.0 544 * 545 * @param mixed $value Meta value to filter. 546 * @param int $object_id Object ID. 547 * @param string $meta_key Meta key to filter a value for. 548 * @param bool $single Whether to return a single value. Default false. 549 * @return mixed Original meta value if the meta key isn't revisioned, the object doesn't exist, 550 * the post type is a revisionm or the post ID doesn't match the object ID. 551 * Otherwise, the revisioned meta value is returned for the preview. 552 */ 553 function _wp_preview_meta_filter( $value, $object_id, $meta_key, $single ) { 554 $post = get_post(); 555 if ( empty( $post ) 556 || $post->ID != $object_id 557 || ! in_array( $meta_key, _wp_post_revision_meta_keys() ) 558 || 'revision' == $post->post_type ) 559 { 560 return $value; 561 } 562 563 // Grab the autosave. 564 $preview = wp_get_post_autosave( $post->ID ); 565 if ( ! is_object( $preview ) ) { 566 return $value; 567 } 568 569 return get_post_meta( $preview->ID, $meta_key, $single ); 570 } 571 572 /** 474 573 * Filters terms lookup to set the post format. 475 574 * 476 575 * @since 3.6.0 -
tests/phpunit/tests/post/revisions.php
338 338 $this->assertTrue( user_can( $author_user_id, 'read_post', $revision->ID ) ); 339 339 } 340 340 } 341 342 /** 343 * Test the revisions system for storage of meta values 344 * @ticket 20564 345 */ 346 function test_revisions_stores_meta_values() { 347 // Set up a new post 348 $original_post_id = $post_id = $this->factory->post->create(); 349 // And update to store an initial revision 350 wp_update_post( array( 'post_content' => 'some initial content', 'ID' => $post_id ) ); 351 352 // One revision so far 353 $revisions = wp_get_post_revisions( $post_id ); 354 $this->assertCount( 1, $revisions ); 355 /** 356 * First set up a meta value 357 */ 358 359 // Store a custom meta value, which is not revisioned by default 360 update_post_meta( $post_id, 'meta_revision_test', 'original' ); 361 362 // Update the post, storing a revision 363 wp_update_post( array( 'post_content' => 'some more content', 'ID' => $post_id ) ); 364 365 // Two revisions so far 366 $revisions = wp_get_post_revisions( $post_id ); 367 $this->assertCount( 2, $revisions ); 368 369 370 // Next, store some updated meta values for the same key 371 update_post_meta( $post_id, 'meta_revision_test', 'update1' ); 372 373 // Save the post, changing content to force a revision 374 wp_update_post( array( 'post_content' => 'some updated content', 'ID' => $post_id ) ); 375 376 // Three revisions so far 377 $revisions = wp_get_post_revisions( $post_id ); 378 $this->assertCount( 3, $revisions ); 379 380 381 /** 382 * Now restore the original revision 383 */ 384 385 // Restore the previous revision 386 $revisions = (Array)wp_get_post_revisions( $post_id ); 387 // Go back two to load the previous revision 388 array_shift( $revisions ); 389 $last_revision = array_shift( $revisions ); 390 391 // Restore! 392 wp_restore_post_revision( $last_revision->ID ); 393 394 wp_update_post( array( 'ID' => $post_id ) ); 395 $revisions = wp_get_post_revisions( $post_id ); 396 $this->assertCount( 4, $revisions ); 397 398 /** 399 * Check the meta values to verify they are NOT revisioned - they are not revisioned by default 400 */ 401 402 // Custom post meta should NOT be restored, orignal value should not be restored, value still 'update1' 403 $this->assertEquals( 'update1', get_post_meta( $post_id, 'meta_revision_test', true ) ); 404 405 update_post_meta( $post_id, 'meta_revision_test', 'update2' ); 406 407 // Verify revision no saved when nothing has changed 408 wp_update_post( array( 'ID' => $post_id ) ); 409 $revisions = wp_get_post_revisions( $post_id ); 410 $this->assertCount( 4, $revisions ); 411 412 /* 413 * Now test the revisioning of custom meta when enabled by the wp_post_revision_meta_keys filter 414 */ 415 416 // Add the custom field to be revised via the wp_post_revision_meta_keys filter 417 add_filter( 'wp_post_revision_meta_keys', function( $keys ) { 418 $keys[] = 'meta_revision_test'; 419 return $keys; 420 }); 421 422 // Save the post, changing content to force a revision 423 wp_update_post( array( 'post_content' => 'more updated content', 'ID' => $post_id ) ); 424 425 // Five revisions so far 426 $revisions = wp_get_post_revisions( $post_id ); 427 $this->assertCount( 5, $revisions ); 428 429 // Store custom meta values, which should now be revisioned 430 update_post_meta( $post_id, 'meta_revision_test', 'update3' ); 431 432 /** 433 * Save the post again, custom meta should now be revisioned 434 * 435 * Note that a revision is saved even though there is no change 436 * in post content, becaused the revisioned post_meta has changed 437 * 438 */ 439 wp_update_post( array( 'ID' => $post_id ) ); 440 441 // Six revisions so far, this revision contains the existing post meta ('update2') 442 $revisions = wp_get_post_revisions( $post_id ); 443 $this->assertCount( 6, $revisions ); 444 445 // Verify that previous post meta is set 446 $this->assertEquals( 'update3', get_post_meta( $post_id, 'meta_revision_test', true ) ); 447 448 // Retore the previous revision 449 $revisions = wp_get_post_revisions( $post_id ); 450 // Go back two to load the previous revision 451 array_shift( $revisions ); 452 $last_revision = array_shift( $revisions ); 453 wp_restore_post_revision( $last_revision->ID ); 454 455 // Verify that previous post meta is restored 456 $this->assertEquals( 'update2', get_post_meta( $post_id, 'meta_revision_test', true ) ); 457 458 // Cleanup! 459 wp_delete_post( $original_post_id ); 460 461 } 341 462 }