From c5f9e9abeaf115d34834d94da3cf10f1fbd2077d Mon Sep 17 00:00:00 2001
From: Tonya Mork <hellofromtonya@git.wordpress.org>
Date: Wed, 10 Nov 2021 01:25:09 +0000
Subject: [PATCH] Revisions: Introduce `wp_get_post_revisions_url()` to get URL
 for editing revisions.

There's now a way to get a link to a given post's revisions. Introducing `wp_get_post_revisions_url()` and its unit tests.

Props adamsilverstein, audrasjb, costdev, davidbaumwald, garrett-eclipse, georgestephanis, hellofromTonya, iaaxpage.
Fixes #39062.

git-svn-id: https://develop.svn.wordpress.org/trunk@52095 602fd350-edb4-49c9-b593-d223f7449a82
---
 src/wp-includes/revision.php           |  34 ++++++
 tests/phpunit/tests/post/revisions.php | 159 +++++++++++++++++++++++++
 2 files changed, 193 insertions(+)

diff --git a/src/wp-includes/revision.php b/src/wp-includes/revision.php
index 70051a07da..941002ffc6 100644
--- a/src/wp-includes/revision.php
+++ b/src/wp-includes/revision.php
@@ -516,6 +516,40 @@ function wp_get_post_revisions( $post_id = 0, $args = null ) {
 	return $revisions;
 }
 
+/**
+ * Returns the url for viewing and potentially restoring revisions of a given post.
+ *
+ * @since 5.9.0
+ *
+ * @param int|WP_Post $post_id Optional. Post ID or WP_Post object. Default is global `$post`.
+ * @return null|string The URL for editing revisions on the given post, otherwise null.
+ */
+function wp_get_post_revisions_url( $post_id = 0 ) {
+	$post = get_post( $post_id );
+
+	if ( ! $post instanceof WP_Post ) {
+		return null;
+	}
+
+	// If the post is a revision, return early.
+	if ( 'revision' === $post->post_type ) {
+		return get_edit_post_link( $post );
+	}
+
+	if ( ! wp_revisions_enabled( $post ) ) {
+		return null;
+	}
+
+	$revisions = wp_get_post_revisions( $post->ID, array( 'posts_per_page' => 1 ) );
+
+	if ( 0 === count( $revisions ) ) {
+		return null;
+	}
+
+	$revision = reset( $revisions );
+	return get_edit_post_link( $revision );
+}
+
 /**
  * Determine if revisions are enabled for a given post.
  *
diff --git a/tests/phpunit/tests/post/revisions.php b/tests/phpunit/tests/post/revisions.php
index 35e43f18ae..4ff458a012 100644
--- a/tests/phpunit/tests/post/revisions.php
+++ b/tests/phpunit/tests/post/revisions.php
@@ -654,4 +654,163 @@ class Tests_Post_Revisions extends WP_UnitTestCase {
 
 		$this->assertWPError( $revision );
 	}
+
+	/**
+	 * Tests that wp_get_post_revisions_url() returns the revisions URL.
+	 *
+	 * @ticket 39062
+	 *
+	 * @dataProvider data_wp_get_post_revisions_url
+	 *
+	 * @covers ::wp_get_post_revisions_url
+	 *
+	 * @param int $revisions The number of revisions to create.
+	 */
+	public function test_wp_get_post_revisions_url( $revisions ) {
+		wp_set_current_user( self::$admin_user_id );
+
+		$post_id            = self::factory()->post->create( array( 'post_title' => 'Some Post' ) );
+		$latest_revision_id = null;
+
+		if ( 0 !== $revisions ) {
+			$latest_revision_id = $post_id;
+
+			for ( $i = 0; $i < $revisions; ++$i ) {
+				wp_update_post(
+					array(
+						'ID'         => $post_id,
+						'post_title' => 'Some Post ' . $i,
+					)
+				);
+
+				$latest_revision_id++;
+			}
+		}
+
+		$expected = admin_url( 'revision.php?revision=' . $latest_revision_id );
+
+		$this->assertSame(
+			$expected,
+			wp_get_post_revisions_url( $post_id ),
+			'Failed when passed the Post ID'
+		);
+
+		$this->assertSame(
+			$expected,
+			wp_get_post_revisions_url( $latest_revision_id ),
+			'Failed when passed the latest revision ID'
+		);
+	}
+
+	/**
+	 * Tests that wp_get_post_revisions_url() returns the revisions URL
+	 * when passed a WP_Post object.
+	 *
+	 * @ticket 39062
+	 *
+	 * @dataProvider data_wp_get_post_revisions_url
+	 *
+	 * @covers ::wp_get_post_revisions_url
+	 *
+	 * @param int $revisions The number of revisions to create.
+	 */
+	public function test_wp_get_post_revisions_url_with_post_object( $revisions ) {
+		wp_set_current_user( self::$admin_user_id );
+
+		$post               = self::factory()->post->create_and_get( array( 'post_title' => 'Some Post' ) );
+		$latest_revision_id = null;
+
+		if ( 0 !== $revisions ) {
+			$latest_revision_id = $post->ID;
+
+			for ( $i = 0; $i < $revisions; ++$i ) {
+				wp_update_post(
+					array(
+						'ID'         => $post->ID,
+						'post_title' => 'Some Post ' . $i,
+					)
+				);
+
+				$latest_revision_id++;
+			}
+		}
+
+		$expected = admin_url( 'revision.php?revision=' . $latest_revision_id );
+
+		$this->assertSame(
+			$expected,
+			wp_get_post_revisions_url( $post ),
+			'Failed when passed the Post Object'
+		);
+
+		$this->assertSame(
+			$expected,
+			wp_get_post_revisions_url( $latest_revision_id ),
+			'Failed when passed the latest revision ID'
+		);
+	}
+
+	/**
+	 * Data provider.
+	 *
+	 * @return array
+	 */
+	public function data_wp_get_post_revisions_url() {
+		return array(
+			'one revision'       => array( 'revisions' => 1 ),
+			'multiple revisions' => array( 'revisions' => 2 ),
+		);
+	}
+
+	/**
+	 * Tests that wp_get_post_revisions_url() returns NULL when a post does not exist.
+	 *
+	 * @ticket 39062
+	 *
+	 * @covers ::wp_get_post_revisions_url
+	 */
+	public function test_wp_get_post_revisions_url_returns_null_when_post_does_not_exist() {
+		wp_set_current_user( self::$admin_user_id );
+		$post_id = 99999;
+		$this->assertNull( wp_get_post_revisions_url( $post_id ) );
+	}
+
+	/**
+	 * Tests that wp_get_post_revisions_url() returns NULL when there are no revisions.
+	 *
+	 * @ticket 39062
+	 *
+	 * @covers ::wp_get_post_revisions_url
+	 */
+	public function test_wp_get_post_revisions_url_returns_null_with_no_revisions() {
+		wp_set_current_user( self::$admin_user_id );
+		$post_id = self::factory()->post->create( array( 'post_title' => 'Some Post' ) );
+		$this->assertNull( wp_get_post_revisions_url( $post_id ) );
+	}
+
+	/**
+	 * Tests that wp_get_post_revisions_url() returns NULL when revisions are disabled.
+	 *
+	 * @ticket 39062
+	 *
+	 * @covers ::wp_get_post_revisions_url
+	 */
+	public function test_wp_get_post_revisions_url_returns_null_with_revisions_disabled() {
+		wp_set_current_user( self::$admin_user_id );
+
+		remove_post_type_support( 'post', 'revisions' );
+
+		$post_id = self::factory()->post->create( array( 'post_title' => 'Some Post' ) );
+
+		wp_update_post(
+			array(
+				'ID'         => $post_id,
+				'post_title' => 'Some Post 2',
+			)
+		);
+
+		$this->assertNull( wp_get_post_revisions_url( $post_id ) );
+
+		add_post_type_support( 'post', 'revisions' );
+	}
 }