Commit ac362d55a2 for wordpress.org

commit ac362d55a28041c8c39f27d897cc53a662adc1f3
Author: Mamaduka <mamaduka@git.wordpress.org>
Date:   Wed Oct 14 09:35:54 2026 +0000

    REST API: Add `action-trash` link to posts and comments.

    Adds a `https://api.w.org/action-trash` link relation to post and comment responses in the `edit` context. The link means the current user can move that item to the trash. Whether an item can be trashed is decided per record by `EMPTY_TRASH_DAYS`, `MEDIA_TRASH` and the `rest_{$type}_trashable` filters, so the route schema can't express it. The link exposes it for each item, which helps UIs that render long lists, like DataViews and Notes.

    Menu items can only be deleted permanently, so they don't get the link.

    Props mamaduka, timothyblynjacobs, adamsilverstein, isabel_brison, peterwilsoncc.
    Fixes #63670.
    Built from https://develop.svn.wordpress.org/trunk@64343


    git-svn-id: http://core.svn.wordpress.org/trunk@63493 1a063a9b-81f0-0310-95a4-ce76da25c4cd

diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
index 1fa960d584..277e2305bc 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php
@@ -326,10 +326,9 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {

 		$query        = new WP_Comment_Query();
 		$query_result = $query->query( $prepared_args );
+		$comments     = array();

 		if ( ! $is_head_request ) {
-			$comments = array();
-
 			foreach ( $query_result as $comment ) {
 				if ( ! $this->check_read_permission( $comment, $request ) ) {
 					continue;
@@ -1243,7 +1242,18 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 		$response = rest_ensure_response( $data );

 		if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
-			$response->add_links( $this->prepare_links( $comment ) );
+			$links = $this->prepare_links( $comment );
+			$response->add_links( $links );
+
+			if ( ! empty( $links['self']['href'] ) ) {
+				$actions = $this->get_available_actions( $comment, $request );
+
+				$self = $links['self']['href'];
+
+				foreach ( $actions as $rel ) {
+					$response->add_link( $rel, $self );
+				}
+			}
 		}

 		/**
@@ -1346,6 +1356,32 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
 		return $links;
 	}

+	/**
+	 * Gets the link relations available for the comment and current user.
+	 *
+	 * @since 7.2.0
+	 *
+	 * @param WP_Comment      $comment Comment object.
+	 * @param WP_REST_Request $request Request object.
+	 * @return string[] List of link relations.
+	 */
+	protected function get_available_actions( $comment, $request ) {
+		if ( 'edit' !== $request['context'] ) {
+			return array();
+		}
+
+		$rels = array();
+
+		if ( 'trash' !== $comment->comment_approved && $this->check_edit_permission( $comment ) ) {
+			/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php */
+			if ( apply_filters( 'rest_comment_trashable', ( EMPTY_TRASH_DAYS > 0 ), $comment ) ) {
+				$rels[] = 'https://api.w.org/action-trash';
+			}
+		}
+
+		return $rels;
+	}
+
 	/**
 	 * Prepends internal property prefix to query parameters to match our response fields.
 	 *
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php
index 919714c5a9..25ff7be699 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-menu-items-controller.php
@@ -691,6 +691,23 @@ class WP_REST_Menu_Items_Controller extends WP_REST_Posts_Controller {
 		return $links;
 	}

+	/**
+	 * Gets the link relations available for the menu item and current user.
+	 *
+	 * Menu items can only be deleted permanently, so the `action-trash` link is skipped.
+	 *
+	 * @since 7.2.0
+	 *
+	 * @param WP_Post         $post    Post object.
+	 * @param WP_REST_Request $request Request object.
+	 * @return array List of link relations.
+	 */
+	protected function get_available_actions( $post, $request ) {
+		$rels = parent::get_available_actions( $post, $request );
+
+		return array_values( array_diff( $rels, array( 'https://api.w.org/action-trash' ) ) );
+	}
+
 	/**
 	 * Retrieves Link Description Objects that should be added to the Schema for the nav menu items collection.
 	 *
@@ -700,6 +717,7 @@ class WP_REST_Menu_Items_Controller extends WP_REST_Posts_Controller {
 	 */
 	protected function get_schema_links() {
 		$links   = parent::get_schema_links();
+		$links   = array_values( wp_list_filter( $links, array( 'rel' => 'https://api.w.org/action-trash' ), 'NOT' ) );
 		$href    = rest_url( "{$this->namespace}/{$this->rest_base}/{id}" );
 		$links[] = array(
 			'rel'          => 'https://api.w.org/menu-item-object',
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
index 7310de2806..e276afe5a7 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
@@ -455,9 +455,8 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 			add_filter( 'post_password_required', array( $this, 'check_password_required' ), 10, 2 );
 		}

+		$posts = array();
 		if ( ! $is_head_request ) {
-			$posts = array();
-
 			update_post_author_caches( $query_result );
 			update_post_parent_caches( $query_result );

@@ -2334,6 +2333,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 * Gets the link relations available for the post and current user.
 	 *
 	 * @since 4.9.8
+	 * @since 7.2.0 Added the `action-trash` link relation.
 	 *
 	 * @param WP_Post         $post    Post object.
 	 * @param WP_REST_Request $request Request object.
@@ -2369,6 +2369,19 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 			}
 		}

+		if ( 'trash' !== $post->post_status && $this->check_delete_permission( $post ) ) {
+			$supports_trash = ( EMPTY_TRASH_DAYS > 0 );
+
+			if ( 'attachment' === $post->post_type ) {
+				$supports_trash = $supports_trash && MEDIA_TRASH;
+			}
+
+			/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */
+			if ( apply_filters( "rest_{$this->post_type}_trashable", $supports_trash, $post ) ) {
+				$rels[] = 'https://api.w.org/action-trash';
+			}
+		}
+
 		$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );

 		foreach ( $taxonomies as $tax ) {
@@ -2840,6 +2853,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 	 * Retrieves Link Description Objects that should be added to the Schema for the posts collection.
 	 *
 	 * @since 4.9.8
+	 * @since 7.2.0 Added the `action-trash` link relation.
 	 *
 	 * @return array
 	 */
@@ -2914,6 +2928,12 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 			);
 		}

+		$links[] = array(
+			'rel'   => 'https://api.w.org/action-trash',
+			'title' => __( 'The current user can move this post to the trash.' ),
+			'href'  => $href,
+		);
+
 		$taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) );

 		foreach ( $taxonomies as $tax ) {
diff --git a/wp-includes/version.php b/wp-includes/version.php
index deab535195..55a127d80b 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
  *
  * @global string $wp_version
  */
-$wp_version = '7.2-alpha-64342';
+$wp_version = '7.2-alpha-64343';

 /**
  * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.