<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[59899] trunk: REST API: Improve performance for HEAD requests.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/59899">59899</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/59899","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>TimothyBlynJacobs</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2025-03-02 22:05:08 +0000 (Sun, 02 Mar 2025)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>REST API: Improve performance for HEAD requests.
By default, the REST API responds to HEAD rqeuests by calling the GET handler and omitting the body from the response. While convenient, this ends up performing needless work that slows down the API response time.
This commit adjusts the Core controllers to specifically handle HEAD requests by not preparing the response body.
Fixes <a href="https://core.trac.wordpress.org/ticket/56481">#56481</a>.
Props antonvlasenko, janusdev, ironprogrammer, swissspidy, spacedmonkey, mukesh27, mamaduka, timothyblynjacobs.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesrestapiclasswprestrequestphp">trunk/src/wp-includes/rest-api/class-wp-rest-request.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestautosavescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestblockpatterncategoriescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestblocktypescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestcommentscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestfontcollectionscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-collections-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestglobalstylesrevisionscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestpatterndirectorycontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestposttypescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestpostscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestrevisionscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestsearchcontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestsidebarscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswpresttaxonomiescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswpresttemplateautosavescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-autosaves-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswpresttemplaterevisionscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-revisions-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswpresttemplatescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswpresttermscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestuserscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestwidgettypescontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php</a></li>
<li><a href="#trunksrcwpincludesrestapiendpointsclasswprestwidgetscontrollerphp">trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php</a></li>
<li><a href="#trunktestsphpunittestsfontsfontlibrarywpRestFontCollectionsControllerphp">trunk/tests/phpunit/tests/fonts/font-library/wpRestFontCollectionsController.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestautosavescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-autosaves-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestblocktypecontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-block-type-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestcategoriescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-categories-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestcommentscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-comments-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestglobalstylesrevisionscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestpatterndirectorycontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestposttypescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestpostscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestrequestphp">trunk/tests/phpunit/tests/rest-api/rest-request.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestrevisionscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-revisions-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestsearchcontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-search-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestsidebarscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-sidebars-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiresttagscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-tags-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiresttaxonomiescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestuserscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-users-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestwidgettypescontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-widget-types-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapirestwidgetscontrollerphp">trunk/tests/phpunit/tests/rest-api/rest-widgets-controller.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiwpRestBlockPatternCategoriesControllerphp">trunk/tests/phpunit/tests/rest-api/wpRestBlockPatternCategoriesController.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiwpRestTemplateAutosavesControllerphp">trunk/tests/phpunit/tests/rest-api/wpRestTemplateAutosavesController.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiwpRestTemplateRevisionsControllerphp">trunk/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php</a></li>
<li><a href="#trunktestsphpunittestsrestapiwpRestTemplatesControllerphp">trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesrestapiclasswprestrequestphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/class-wp-rest-request.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/class-wp-rest-request.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/class-wp-rest-request.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -162,6 +162,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Determines if the request is the given method.
+ *
+ * @since 6.8.0
+ *
+ * @param string $method HTTP method.
+ * @return bool Whether the request is of the given method.
+ */
+ public function is_method( $method ) {
+ return $this->get_method() === strtoupper( $method );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Canonicalizes the header name.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Ensures that header names are always treated the same regardless of
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestautosavescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -305,6 +305,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $parent;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $parent_id = $parent->ID;
</span><span class="cx" style="display: block; padding: 0 10px"> $revisions = wp_get_post_revisions( $parent_id, array( 'check_enabled' => false ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -448,6 +452,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $post = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-autosaves-controller.php */
+ return apply_filters( 'rest_prepare_autosave', new WP_REST_Response(), $post, $request );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = $this->revisions_controller->prepare_item_for_response( $post, $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestblockpatterncategoriescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-pattern-categories-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -81,6 +81,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $categories = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered();
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $categories as $category ) {
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestblocktypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -131,6 +131,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $block_types = $this->block_registry->get_all_registered();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -250,6 +255,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $block_type = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php */
+ return apply_filters( 'rest_prepare_block_type', new WP_REST_Response(), $block_type, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestcommentscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -262,6 +262,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $prepared_args['offset'] = $prepared_args['number'] * ( absint( $request['page'] ) - 1 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+ if ( $is_head_request ) {
+ // Force the 'fields' argument. For HEAD requests, only post IDs are required to calculate pagination.
+ $prepared_args['fields'] = 'ids';
+ // Disable priming comment meta for HEAD requests to improve performance.
+ $prepared_args['update_comment_meta_cache'] = false;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Filters WP_Comment_Query arguments when querying comments via the REST API.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -277,15 +285,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $query = new WP_Comment_Query();
</span><span class="cx" style="display: block; padding: 0 10px"> $query_result = $query->query( $prepared_args );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $comments = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $is_head_request ) {
+ $comments = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $query_result as $comment ) {
- if ( ! $this->check_read_permission( $comment, $request ) ) {
- continue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $query_result as $comment ) {
+ if ( ! $this->check_read_permission( $comment, $request ) ) {
+ continue;
+ }
+
+ $data = $this->prepare_item_for_response( $comment, $request );
+ $comments[] = $this->prepare_response_for_collection( $data );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- $data = $this->prepare_item_for_response( $comment, $request );
- $comments[] = $this->prepare_response_for_collection( $data );
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $total_comments = (int) $query->found_comments;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -303,7 +313,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $max_pages = (int) ceil( $total_comments / $request['per_page'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $comments );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $comments );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-Total', $total_comments );
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-TotalPages', $max_pages );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1041,6 +1051,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $comment = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-comments-controller.php */
+ return apply_filters( 'rest_prepare_comment', new WP_REST_Response(), $comment, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestfontcollectionscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-collections-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-collections-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-font-collections-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -89,6 +89,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $collections_page = array_slice( $collections_all, ( $page - 1 ) * $per_page, $per_page );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $items = array();
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $collections_page as $collection ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $item = $this->prepare_item_for_response( $collection, $request );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -97,11 +99,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> if ( is_wp_error( $item ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> continue;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /*
+ * Skip preparing the response body for HEAD requests.
+ * Cannot exit earlier due to backward compatibility reasons,
+ * as validation occurs in the prepare_item_for_response method.
+ */
+ if ( $is_head_request ) {
+ continue;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $item = $this->prepare_response_for_collection( $item );
</span><span class="cx" style="display: block; padding: 0 10px"> $items[] = $item;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $items );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $items );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-Total', (int) $total_items );
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-TotalPages', $max_pages );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -175,6 +187,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $collection_data;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Don't prepare the response body for HEAD requests.
+ * Can't exit at the beginning of the method due to the potential need to return a WP_Error object.
+ */
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-font-collections-controller.php */
+ return apply_filters( 'rest_prepare_font_collection', new WP_REST_Response(), $item, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> foreach ( $data_fields as $field ) {
</span><span class="cx" style="display: block; padding: 0 10px"> if ( rest_is_field_included( $field, $fields ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $data[ $field ] = $collection_data[ $field ];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -182,6 +203,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Don't prepare the response body for HEAD requests.
+ * Can't exit at the beginning of the method due to the potential need to return a WP_Error object.
+ */
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-font-collections-controller.php */
+ return apply_filters( 'rest_prepare_font_collection', new WP_REST_Response(), $item, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_ensure_response( $data );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( rest_is_field_included( '_links', $fields ) ) {
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestglobalstylesrevisionscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-revisions-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -163,6 +163,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $global_styles_config;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( wp_revisions_enabled( $parent ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $registered = $this->get_collection_params();
</span><span class="cx" style="display: block; padding: 0 10px"> $query_args = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -186,6 +188,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $is_head_request ) {
+ // Force the 'fields' argument. For HEAD requests, only post IDs are required to calculate pagination.
+ $query_args['fields'] = 'ids';
+ // Disable priming post meta for HEAD requests to improve performance.
+ $query_args['update_post_term_cache'] = false;
+ $query_args['update_post_meta_cache'] = false;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $revisions_query = new WP_Query();
</span><span class="cx" style="display: block; padding: 0 10px"> $revisions = $revisions_query->query( $query_args );
</span><span class="cx" style="display: block; padding: 0 10px"> $offset = isset( $query_args['offset'] ) ? (int) $query_args['offset'] : 0;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -228,15 +238,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $page = (int) $request['page'];
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $is_head_request ) {
+ $response = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $revisions as $revision ) {
- $data = $this->prepare_item_for_response( $revision, $request );
- $response[] = $this->prepare_response_for_collection( $data );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $revisions as $revision ) {
+ $data = $this->prepare_item_for_response( $revision, $request );
+ $response[] = $this->prepare_response_for_collection( $data );
+ }
+
+ $response = rest_ensure_response( $response );
+ } else {
+ $response = new WP_REST_Response();
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $response );
-
</del><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-Total', (int) $total_revisions );
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-TotalPages', (int) $max_pages );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -275,6 +289,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response|WP_Error Response object.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function prepare_item_for_response( $post, $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $parent = $this->get_parent( $request['parent'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $global_styles_config = $this->get_decoded_global_styles_json( $post->post_content );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestpatterndirectorycontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -161,6 +161,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return $raw_patterns;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $raw_patterns ) {
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestposttypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -109,6 +109,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px"> $types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -178,6 +183,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $post_type = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php */
+ return apply_filters( 'rest_prepare_post_type', new WP_REST_Response(), $post_type, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $taxonomies = wp_list_filter( get_object_taxonomies( $post_type->name, 'objects' ), array( 'show_in_rest' => true ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $taxonomies = wp_list_pluck( $taxonomies, 'name' );
</span><span class="cx" style="display: block; padding: 0 10px"> $base = ! empty( $post_type->rest_base ) ? $post_type->rest_base : $post_type->name;
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestpostscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -411,6 +411,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Force the post_type argument, since it's not a user input variable.
</span><span class="cx" style="display: block; padding: 0 10px"> $args['post_type'] = $this->post_type;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+ if ( $is_head_request ) {
+ // Force the 'fields' argument. For HEAD requests, only post IDs are required to calculate pagination.
+ $args['fields'] = 'ids';
+ // Disable priming post meta for HEAD requests to improve performance.
+ $args['update_post_term_cache'] = false;
+ $args['update_post_meta_cache'] = false;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Filters WP_Query arguments when querying posts via the REST API.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -443,22 +452,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'post_password_required', array( $this, 'check_password_required' ), 10, 2 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $posts = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $is_head_request ) {
+ $posts = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- update_post_author_caches( $query_result );
- update_post_parent_caches( $query_result );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ update_post_author_caches( $query_result );
+ update_post_parent_caches( $query_result );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( post_type_supports( $this->post_type, 'thumbnail' ) ) {
- update_post_thumbnail_cache( $posts_query );
- }
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( post_type_supports( $this->post_type, 'thumbnail' ) ) {
+ update_post_thumbnail_cache( $posts_query );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $query_result as $post ) {
- if ( ! $this->check_read_permission( $post ) ) {
- continue;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $query_result as $post ) {
+ if ( ! $this->check_read_permission( $post ) ) {
+ continue;
+ }
+
+ $data = $this->prepare_item_for_response( $post, $request );
+ $posts[] = $this->prepare_response_for_collection( $data );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- $data = $this->prepare_item_for_response( $post, $request );
- $posts[] = $this->prepare_response_for_collection( $data );
</del><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Reset filter.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -488,7 +499,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $posts );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $posts );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-Total', (int) $total_posts );
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-TotalPages', (int) $max_pages );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1833,6 +1844,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> setup_postdata( $post );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */
+ return apply_filters( "rest_prepare_{$this->post_type}", new WP_REST_Response(), $post, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Base fields for every post.
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestrevisionscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -253,6 +253,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( wp_revisions_enabled( $parent ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $registered = $this->get_collection_params();
</span><span class="cx" style="display: block; padding: 0 10px"> $args = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -287,6 +289,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $args['orderby'] = 'date ID';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $is_head_request ) {
+ // Force the 'fields' argument. For HEAD requests, only post IDs are required to calculate pagination.
+ $args['fields'] = 'ids';
+ // Disable priming post meta for HEAD requests to improve performance.
+ $args['update_post_term_cache'] = false;
+ $args['update_post_meta_cache'] = false;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */
</span><span class="cx" style="display: block; padding: 0 10px"> $args = apply_filters( 'rest_revision_query', $args, $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $query_args = $this->prepare_items_query( $args, $request );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -335,15 +345,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $page = (int) $request['page'];
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $is_head_request ) {
+ $response = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $revisions as $revision ) {
- $data = $this->prepare_item_for_response( $revision, $request );
- $response[] = $this->prepare_response_for_collection( $data );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $revisions as $revision ) {
+ $data = $this->prepare_item_for_response( $revision, $request );
+ $response[] = $this->prepare_response_for_collection( $data );
+ }
+
+ $response = rest_ensure_response( $response );
+ } else {
+ $response = new WP_REST_Response();
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $response );
-
</del><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-Total', (int) $total_revisions );
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-TotalPages', (int) $max_pages );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -574,6 +588,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> setup_postdata( $post );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-revisions-controller.php */
+ return apply_filters( 'rest_prepare_revision', new WP_REST_Response(), $post, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestsearchcontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-search-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -142,11 +142,14 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $ids = $result[ WP_REST_Search_Handler::RESULT_IDS ];
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $results = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+ if ( ! $is_head_request ) {
+ $results = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $ids as $id ) {
- $data = $this->prepare_item_for_response( $id, $request );
- $results[] = $this->prepare_response_for_collection( $data );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $ids as $id ) {
+ $data = $this->prepare_item_for_response( $id, $request );
+ $results[] = $this->prepare_response_for_collection( $data );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $total = (int) $result[ WP_REST_Search_Handler::RESULT_TOTAL ];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -162,7 +165,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $results );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $results );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-Total', $total );
</span><span class="cx" style="display: block; padding: 0 10px"> $response->header( 'X-WP-TotalPages', $max_pages );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestsidebarscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -119,6 +119,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response Response object on success.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->retrieve_widgets();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -321,6 +326,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $raw_sidebar = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-sidebars-controller.php */
+ return apply_filters( 'rest_prepare_sidebar', new WP_REST_Response(), $raw_sidebar, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $id = $raw_sidebar['id'];
</span><span class="cx" style="display: block; padding: 0 10px"> $sidebar = array( 'id' => $id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswpresttaxonomiescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -113,6 +113,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response Response object on success, or WP_Error object on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Retrieve the list of registered collection query parameters.
</span><span class="cx" style="display: block; padding: 0 10px"> $registered = $this->get_collection_params();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -210,6 +214,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $taxonomy = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-taxonomies-controller.php */
+ return apply_filters( 'rest_prepare_taxonomy', new WP_REST_Response(), $taxonomy, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswpresttemplateautosavescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-autosaves-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-autosaves-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-autosaves-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -175,6 +175,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $template = _build_block_template_result_from_post( $item );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = $this->parent_controller->prepare_item_for_response( $template, $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ return $response;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswpresttemplaterevisionscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-revisions-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-revisions-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-template-revisions-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -200,6 +200,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $template = _build_block_template_result_from_post( $item );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = $this->parent_controller->prepare_item_for_response( $template, $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ return $response;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswpresttemplatescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -269,6 +269,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $query = array();
</span><span class="cx" style="display: block; padding: 0 10px"> if ( isset( $request['wp_id'] ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $query['wp_id'] = $request['wp_id'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -668,6 +673,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response Response object.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function prepare_item_for_response( $item, $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /*
</span><span class="cx" style="display: block; padding: 0 10px"> * Resolve pattern blocks so they don't need to be resolved client-side
</span><span class="cx" style="display: block; padding: 0 10px"> * in the editor, improving performance.
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswpresttermscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -312,6 +312,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $prepared_args = array_merge( $prepared_args, $taxonomy_obj->args );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $is_head_request = $request->is_method( 'HEAD' );
+ if ( $is_head_request ) {
+ // Force the 'fields' argument. For HEAD requests, only term IDs are required.
+ $prepared_args['fields'] = 'ids';
+ // Disable priming term meta for HEAD requests to improve performance.
+ $prepared_args['update_term_meta_cache'] = false;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Filters get_terms() arguments when querying terms via the REST API.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -354,14 +362,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_terms = 0;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = array();
-
- foreach ( $query_result as $term ) {
- $data = $this->prepare_item_for_response( $term, $request );
- $response[] = $this->prepare_response_for_collection( $data );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $is_head_request ) {
+ $response = array();
+ foreach ( $query_result as $term ) {
+ $data = $this->prepare_item_for_response( $term, $request );
+ $response[] = $this->prepare_response_for_collection( $data );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $response );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $response );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Store pagination values for headers.
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = (int) $prepared_args['number'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -887,6 +896,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function prepare_item_for_response( $item, $request ) {
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-terms-controller.php */
+ return apply_filters( "rest_prepare_{$this->taxonomy}", new WP_REST_Response(), $item, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestuserscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -355,6 +355,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> $prepared_args['search'] = '*' . $prepared_args['search'] . '*';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ $is_head_request = $request->is_method( 'HEAD' );
+ if ( $is_head_request ) {
+ // Force the 'fields' argument. For HEAD requests, only user IDs are required.
+ $prepared_args['fields'] = 'id';
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Filters WP_User_Query arguments when querying users via the REST API.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -369,14 +375,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $query = new WP_User_Query( $prepared_args );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $users = array();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $is_head_request ) {
+ $users = array();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- foreach ( $query->get_results() as $user ) {
- $data = $this->prepare_item_for_response( $user, $request );
- $users[] = $this->prepare_response_for_collection( $data );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ foreach ( $query->get_results() as $user ) {
+ $data = $this->prepare_item_for_response( $user, $request );
+ $users[] = $this->prepare_response_for_collection( $data );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_ensure_response( $users );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $response = $is_head_request ? new WP_REST_Response() : rest_ensure_response( $users );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Store pagination values for headers then unset for count query.
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = (int) $prepared_args['number'];
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1021,6 +1029,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $user = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-users-controller.php */
+ return apply_filters( 'rest_prepare_user', new WP_REST_Response(), $user, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestwidgettypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -145,6 +145,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $data = array();
</span><span class="cx" style="display: block; padding: 0 10px"> foreach ( $this->get_widgets() as $widget ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $widget_type = $this->prepare_item_for_response( $widget, $request );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -298,6 +303,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // Restores the more descriptive, specific name for use within this method.
</span><span class="cx" style="display: block; padding: 0 10px"> $widget_type = $item;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-widget-types-controller.php */
+ return apply_filters( 'rest_prepare_widget_type', new WP_REST_Response(), $widget_type, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'id' => $widget_type['id'],
</span></span></pre></div>
<a id="trunksrcwpincludesrestapiendpointsclasswprestwidgetscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -136,6 +136,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @return WP_REST_Response Response object.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function get_items( $request ) {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ // Return early as this handler doesn't add any response headers.
+ return new WP_REST_Response();
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->retrieve_widgets();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $prepared = array();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -678,6 +683,12 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $widget = $wp_registered_widgets[ $widget_id ];
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ // Don't prepare the response body for HEAD requests.
+ if ( $request->is_method( 'HEAD' ) ) {
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-widgets-controller.php */
+ return apply_filters( 'rest_prepare_widget', new WP_REST_Response(), $widget, $request );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $parsed_id = wp_parse_widget_id( $widget_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $fields = $this->get_fields_for_response( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunktestsphpunittestsfontsfontlibrarywpRestFontCollectionsControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/fonts/font-library/wpRestFontCollectionsController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/fonts/font-library/wpRestFontCollectionsController.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/fonts/font-library/wpRestFontCollectionsController.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -78,9 +78,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Font_Collections_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_should_only_return_valid_collections() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_should_only_return_valid_collections( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setExpectedIncorrectUsage( 'WP_Font_Collection::load_from_json' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -92,7 +96,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/font-collections' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/font-collections' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $content = $response->get_data();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -99,7 +103,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_unregister_font_collection( 'invalid-collection' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 1, $content, 'The response should only contain valid collections.' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' !== $method ) {
+ $this->assertCount( 1, $content, 'The response should only contain valid collections.' );
+ return null;
+ }
+
+ $this->assertNull( $content, 'The response should be empty.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-WP-Total', $headers, 'The "X-WP-Total" header should be present in the response.' );
+ // Includes non-valid collections.
+ $this->assertSame( 2, $headers['X-WP-Total'], 'The "X-WP-Total" header value should be equal to 1.' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -127,19 +140,75 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $hook_name = 'rest_prepare_font_collection';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( $method, '/wp/v2/font-collections/mock-col-slug' );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Font_Collections_Controller::get_item
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_slug() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_invalid_slug( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/font-collections/non-existing-collection' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/font-collections/non-existing-collection' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_font_collection_not_found', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Font_Collections_Controller::get_item
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_collection() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_invalid_collection( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->setExpectedIncorrectUsage( 'WP_Font_Collection::load_from_json' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -152,7 +221,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/font-collections/' . $slug );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/font-collections/' . $slug );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_unregister_font_collection( $slug );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -161,10 +230,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Font_Collections_Controller::get_item
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_id_permission() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/font-collections/mock-col-slug' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_invalid_id_permission( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/font-collections/mock-col-slug' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestautosavescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-autosaves-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-autosaves-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-autosaves-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -179,9 +179,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_get_autosave_response( $data[0], $this->post_autosave );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_autosaves_data() {
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/posts/' . self::$post_id . '/autosaves' );
+
+ $hook_name = 'rest_prepare_autosave';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+
+ $this->assertNotWPError( $response );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/autosaves' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -189,16 +215,40 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_missing_parent() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_missing_parent( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_parent_post_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_invalid_parent_post_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/autosaves' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$page_id . '/autosaves' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -230,6 +280,43 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( self::$editor_id, $data['author'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ wp_set_current_user( self::$editor_id );
+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id );
+
+ $hook_name = 'rest_prepare_autosave';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_embed_context() {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -248,23 +335,41 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSameSets( $fields, array_keys( $data ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_no_permission() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_no_permission( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/autosaves/' . self::$autosave_post_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_missing_parent() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_missing_parent( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves/' . self::$autosave_post_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/autosaves/' . self::$autosave_post_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_parent_post_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_invalid_parent_post_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/autosaves' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$page_id . '/autosaves' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestblocktypecontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-block-type-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-block-type-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-block-type-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -602,47 +602,128 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $block_name = 'fake/test';
+ wp_set_current_user( self::$admin_id );
+
+ $hook_name = 'rest_prepare_block_type';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $request = new WP_REST_Request( $method, '/wp/v2/block-types/' . $block_name );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_block_type_data() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/block-types' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 47620
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_wrong_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_wrong_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/block-types' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/block-types' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 47620
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_wrong_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_wrong_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/block-types/fake/test' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/block-types/fake/test' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 47620
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/block-types' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/block-types' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 47620
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/block-types/fake/test' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/block-types/fake/test' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_block_type_cannot_view', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 47620
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_prepare_item() {
</span><span class="cx" style="display: block; padding: 0 10px"> $registry = new WP_Block_Type_Registry();
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestcategoriescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-categories-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-categories-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-categories-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -576,8 +576,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 'Child', $data[0]['name'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_terms_invalid_parent_arg() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_terms_invalid_parent_arg( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/categories' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'parent', 'invalid-parent' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -609,17 +615,25 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_no_route', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_terms_pagination_headers() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_terms_pagination_headers( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $total_categories = self::$total_categories;
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $total_categories / 10 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Start of the index + Uncategorized default term.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/categories' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/categories' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_categories, $headers['X-WP-Total'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_pages, $headers['X-WP-TotalPages'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 10, $response->get_data() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' !== $method ) {
+ $this->assertCount( 10, $response->get_data() );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $next_link = add_query_arg(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'page' => 2,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -662,7 +676,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_categories, $headers['X-WP-Total'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_pages, $headers['X-WP-TotalPages'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 1, $response->get_data() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' !== $method ) {
+ $this->assertCount( 1, $response->get_data() );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $prev_link = add_query_arg(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'page' => $total_pages - 1,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -679,7 +695,9 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_categories, $headers['X-WP-Total'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_pages, $headers['X-WP-TotalPages'] );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 0, $response->get_data() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' !== $method ) {
+ $this->assertCount( 0, $response->get_data() );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $prev_link = add_query_arg(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'page' => $total_pages,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1236,4 +1254,112 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $category = get_term( 1, 'category' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_taxonomy_term( $category, $data, $response->get_links() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_only_fetches_ids_for_head_requests( $method ) {
+ $is_head_request = 'HEAD' === $method;
+ $request = new WP_REST_Request( $method, '/wp/v2/categories' );
+
+ $filter = new MockAction();
+
+ add_filter( 'terms_pre_query', array( $filter, 'filter' ), 10, 2 );
+
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 200, $response->get_status() );
+ if ( $is_head_request ) {
+ $this->assertEmpty( $response->get_data() );
+ } else {
+ $this->assertNotEmpty( $response->get_data() );
+ }
+
+ $args = $filter->get_args();
+ $this->assertTrue( isset( $args[0][1] ), 'Query parameters were not captured.' );
+ $this->assertInstanceOf( WP_Term_Query::class, $args[0][1], 'Query parameters were not captured.' );
+
+ /** @var WP_Term_Query $query */
+ $query = $args[0][1];
+
+ if ( $is_head_request ) {
+ $this->assertArrayHasKey( 'fields', $query->query_vars, 'The fields parameter is not set in the query vars.' );
+ $this->assertSame( 'ids', $query->query_vars['fields'], 'The query must fetch only term IDs.' );
+ $this->assertArrayHasKey( 'update_term_meta_cache', $query->query_vars, 'The update_term_meta_cache key is missing in the query vars.' );
+ $this->assertFalse( $query->query_vars['update_term_meta_cache'], 'The update_term_meta_cache value should be false for HEAD requests.' );
+ } else {
+ $this->assertTrue(
+ ! array_key_exists( 'fields', $query->query_vars ) || 'ids' !== $query->query_vars['fields'],
+ 'The fields parameter should not be forced to "ids" for non-HEAD requests.'
+ );
+ $this->assertArrayHasKey( 'update_term_meta_cache', $query->query_vars, 'The update_term_meta_cache key is missing in the query vars.' );
+ $this->assertTrue( $query->query_vars['update_term_meta_cache'], 'The update_term_meta_cache value should be true for HEAD requests.' );
+ }
+
+ if ( ! $is_head_request ) {
+ return;
+ }
+
+ global $wpdb;
+ $terms_table = preg_quote( $wpdb->terms, '/' );
+
+ $pattern = '/SELECT\s+t\.term_id.+FROM\s+' . $terms_table . '\s+AS\s+t\s+INNER\s+JOIN/is';
+
+ // Assert that the SQL query only fetches the term_id column.
+ $this->assertMatchesRegularExpression( $pattern, $query->request, 'The SQL query does not match the expected string.' );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $category_id = self::factory()->category->create();
+
+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/categories/%d', $category_id ) );
+
+ $hook_name = 'rest_prepare_category';
+
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestcommentscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-comments-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-comments-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-comments-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -432,19 +432,43 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertCount( 2, $comments );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission_for_no_post() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_no_permission_for_no_post( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'post', 0 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_edit_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_edit_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -593,12 +617,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_private_post_no_permissions() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_private_post_no_permissions( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $post_id = self::factory()->post->create( array( 'post_status' => 'private' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'post', $post_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read_post', $response, 401 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -801,7 +831,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $id, $data[0]['id'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comments_pagination_headers() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comments_pagination_headers( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $total_comments = self::$total_comments;
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $total_comments / 10 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -808,7 +844,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Start of the index.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_comments, $headers['X-WP-Total'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -884,8 +920,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringNotContainsString( 'rel="next"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comments_invalid_date() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/comments' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comments_invalid_date( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/comments' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'after', 'foo' );
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'before', 'bar' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -997,23 +1039,41 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( substr( get_avatar_url( $comment->comment_author_email ), 9 ), substr( $data['author_avatar_urls'][96], 9 ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_invalid_id() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/comments/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_invalid_id( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/comments/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_comment_invalid_id', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_invalid_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_invalid_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%s', self::$approved_id ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/comments/%s', self::$approved_id ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_invalid_post_id() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_invalid_post_id( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $comment_id = self::factory()->comment->create(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1023,12 +1083,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments/' . $comment_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments/' . $comment_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_invalid_post_id_as_admin() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_invalid_post_id_as_admin( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $comment_id = self::factory()->comment->create(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1038,23 +1104,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments/' . $comment_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments/' . $comment_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_id', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_not_approved() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_not_approved( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$hold_id ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/comments/%d', self::$hold_id ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_not_approved_same_user() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_not_approved_same_user( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%d', self::$hold_id ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/comments/%d', self::$hold_id ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1098,7 +1176,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayNotHasKey( 'children', $response->get_links() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_with_password_without_edit_post_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_comment_with_password_without_edit_post_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $args = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1108,15 +1192,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $password_comment = self::factory()->comment->create( $args );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%s', $password_comment ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/comments/%s', $password_comment ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 38692
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_comment_with_password_with_valid_password() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_comment_with_password_with_valid_password( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $args = array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1126,7 +1214,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $password_comment = self::factory()->comment->create( $args );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/comments/%s', $password_comment ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/comments/%s', $password_comment ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'password', 'toomanysecrets' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3365,9 +3453,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 42238
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_check_read_post_permission_with_invalid_post_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_check_read_post_permission_with_invalid_post_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> register_post_type(
</span><span class="cx" style="display: block; padding: 0 10px"> 'bug-post',
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3386,8 +3478,95 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->setExpectedIncorrectUsage( 'map_meta_cap' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/comments/' . $comment_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/comments/' . $comment_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 403, $response->get_status() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_only_fetches_ids_for_head_requests( $method ) {
+ $is_head_request = 'HEAD' === $method;
+ $request = new WP_REST_Request( $method, '/wp/v2/comments' );
+
+ $filter = new MockAction();
+
+ add_filter( 'comments_pre_query', array( $filter, 'filter' ), 10, 2 );
+
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 200, $response->get_status() );
+ if ( $is_head_request ) {
+ $this->assertEmpty( $response->get_data() );
+ } else {
+ $this->assertNotEmpty( $response->get_data() );
+ }
+
+ $args = $filter->get_args();
+ $this->assertTrue( isset( $args[0][1] ), 'Query parameters were not captured.' );
+ $this->assertInstanceOf( WP_Comment_Query::class, $args[0][1], 'Query parameters were not captured.' );
+
+ /** @var WP_Comment_Query $query */
+ $query = $args[0][1];
+
+ if ( $is_head_request ) {
+ $this->assertArrayHasKey( 'fields', $query->query_vars, 'The fields parameter is not set in the query vars.' );
+ $this->assertSame( 'ids', $query->query_vars['fields'], 'The query must fetch only post IDs.' );
+ $this->assertArrayHasKey( 'update_comment_meta_cache', $query->query_vars, 'The update_comment_meta_cache key is missing in the query vars.' );
+ $this->assertFalse( $query->query_vars['update_comment_meta_cache'], 'The update_comment_meta_cache value should be false for HEAD requests.' );
+ } else {
+ $this->assertTrue( ! array_key_exists( 'fields', $query->query_vars ) || 'ids' !== $query->query_vars['fields'], 'The fields parameter should not be forced to "ids" for non-HEAD requests.' );
+ $this->assertArrayHasKey( 'update_comment_meta_cache', $query->query_vars, 'The update_comment_meta_cache key is missing in the query vars.' );
+ $this->assertTrue( $query->query_vars['update_comment_meta_cache'], 'The update_comment_meta_cache value should be true for non-HEAD requests.' );
+ return;
+ }
+
+ global $wpdb;
+ $comments_table = preg_quote( $wpdb->comments, '/' );
+ $pattern = '/^SELECT\s+SQL_CALC_FOUND_ROWS\s+' . $comments_table . '\.comment_ID\s+FROM\s+' . $comments_table . '\s+WHERE/i';
+
+ // Assert that the SQL query only fetches the ID column.
+ $this->assertMatchesRegularExpression( $pattern, $query->request, 'The SQL query does not match the expected string.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/comments/%d', self::$approved_id ) );
+
+ $hook_name = 'rest_prepare_comment';
+
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $headers = $response->get_headers();
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestglobalstylesrevisionscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-global-styles-revisions-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -245,18 +245,34 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_missing_parent() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_missing_parent( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Utility function to check the items in WP_REST_Global_Styles_Controller::get_items
</span><span class="cx" style="display: block; padding: 0 10px"> * against the expected values.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -311,6 +327,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @covers WP_REST_Global_Styles_Controller::prepare_item_for_response
+ */
+ public function test_get_items_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 59810
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_item
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -327,16 +356,34 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @covers WP_REST_Global_Styles_Controller::get_item
+ * @covers WP_REST_Global_Styles_Controller::prepare_item_for_response
+ */
+ public function test_get_item_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/' . $this->revision_1_id );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 59810
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_revision
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_revision_id_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_invalid_revision_id_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_post_invalid_id';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 404;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/20000001' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions/20000001' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( $expected_error, $response, $expected_status );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -419,14 +466,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 60131
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_item_permissions_check
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_permissions_check() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_permissions_check( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$author_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -435,13 +486,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Tests the pagination header of the first page.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_pagination_header_of_the_first_page
- *
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_pagination_header_of_the_first_page() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_pagination_header_of_the_first_page( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $rest_route = '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -449,7 +502,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $this->total_revisions / $per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $page = 1; // First page.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', $rest_route );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, $rest_route );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -476,11 +529,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_pagination_header_of_the_last_page
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_pagination_header_of_the_last_page() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_pagination_header_of_the_last_page( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $rest_route = '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -488,7 +545,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $this->total_revisions / $per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $page = 2; // Last page.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', $rest_route );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, $rest_route );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -514,11 +571,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_invalid_per_page_should_error
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_per_page_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_per_page_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = -1; // Invalid number.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -525,7 +586,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_invalid_param';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', $per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( $expected_error, $response, $expected_status );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -536,11 +597,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_out_of_bounds_page_should_error
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_out_of_bounds_page_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_out_of_bounds_page_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -549,7 +614,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_page_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -565,11 +630,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_invalid_max_pages_should_error
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_max_pages_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_max_pages_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -577,7 +646,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_page_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -689,11 +758,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_total_revisions_offset_should_return_empty_data
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_total_revisions_offset_should_return_empty_data() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_total_revisions_offset_should_return_empty_data( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -701,7 +774,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_offset_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -717,11 +790,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_out_of_bound_offset_should_error
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_out_of_bound_offset_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_out_of_bound_offset_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -729,7 +806,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_offset_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -745,11 +822,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_impossible_high_number_offset_should_error
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_impossible_high_number_offset_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_impossible_high_number_offset_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -757,7 +838,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_offset_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -773,11 +854,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * Duplicate of WP_Test_REST_Revisions_Controller::test_get_items_invalid_offset_should_error
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 58524
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Global_Styles_Controller::get_items
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_offset_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_offset_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -785,7 +870,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_invalid_param';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/global-styles/' . self::$global_styles_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestpatterndirectorycontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -145,6 +145,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_block_patterns_data() {
+ wp_set_current_user( self::$contributor_id );
+ self::mock_successful_response( 'browse-all', true );
+
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/pattern-directory/patterns' );
+
+ $hook_name = 'rest_prepare_block_pattern';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+
+ $this->assertNotWPError( $response );
+ $response = rest_ensure_response( $response );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Pattern_Directory_Controller::get_items
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -219,15 +245,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Pattern_Directory_Controller::get_items
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_wdotorg_unavailable() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_wdotorg_unavailable( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> self::prevent_requests_to_host( 'api.wordpress.org' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/pattern-directory/patterns' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_do_request( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'patterns_api_failed', $response, 500 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -234,12 +265,29 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Pattern_Directory_Controller::get_items
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_logged_out() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_logged_out( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/pattern-directory/patterns' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params( array( 'search' => 'button' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_do_request( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -283,15 +331,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Pattern_Directory_Controller::get_items
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 5.8.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_response_data() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_response_data( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> self::mock_successful_response( 'invalid-data', true );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/pattern-directory/patterns' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_do_request( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 500, $response->status );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestposttypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -44,14 +44,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayNotHasKey( 'revision', $data );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_permission_for_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_invalid_permission_for_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/types' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/types' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item() {
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/types/post' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -61,6 +79,42 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/types/post' );
+
+ $hook_name = 'rest_prepare_post_type';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 53656
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_cpt() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -106,8 +160,14 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( array(), $data['taxonomies'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_type() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/types/invalid' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_item_invalid_type( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/types/invalid' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_type_invalid', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -121,9 +181,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_post_type_object_response( 'edit', $response );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_permission_for_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_item_invalid_permission_for_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/types/post' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/types/post' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -245,6 +311,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return 123;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_post_types_data() {
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/types' );
+ $hook_name = 'rest_prepare_post_type';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> protected function check_post_type_obj( $context, $post_type_obj, $data, $links ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $post_type_obj->label, $data['name'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $post_type_obj->name, $data['slug'] );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestpostscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-posts-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -274,12 +274,44 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_post_data() {
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/posts' );
+
+ $hook_name = 'rest_prepare_post';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+
+ $this->assertNotWPError( $response );
+ $response = rest_ensure_response( $response );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+
+ $headers = $response->get_headers();
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertArrayHasKey( 'Link', $headers, 'The "Link" header should be present in the response.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * A valid query that returns 0 results should return an empty JSON list.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * In case of a HEAD request, the response should not contain a body.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @link https://github.com/WP-API/WP-API/issues/862
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @covers WP_REST_Posts_Controller::get_items
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_empty_query() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_empty_query( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'author' => REST_TESTS_IMPOSSIBLY_HIGH_NUMBER,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -287,11 +319,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertEmpty( $response->get_data() );
- $this->assertSame( 200, $response->get_status() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'HEAD' ) ) {
+ $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' );
+ } else {
+ $this->assertSame( array(), $response->get_data(), 'Failed asserting that response data is an empty array for GET request.' );
+ }
+
+ $headers = $response->get_headers();
+ $this->assertSame( 0, $headers['X-WP-Total'], 'Failed asserting that X-WP-Total header is 0.' );
+ $this->assertSame( 0, $headers['X-WP-TotalPages'], 'Failed asserting that X-WP-TotalPages header is 0.' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_author_query() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_author_query( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> self::factory()->post->create( array( 'post_author' => self::$editor_id ) );
</span><span class="cx" style="display: block; padding: 0 10px"> self::factory()->post->create( array( 'post_author' => self::$author_id ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -298,32 +343,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_posts = self::$total_posts + 2;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // All posts in the database.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', self::$per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( $total_posts, $response->get_data() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( $total_posts, $response->get_data() );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ } else {
+ $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts, $headers['X-WP-Total'] );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> // Limit to editor and author.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'author', array( self::$editor_id, self::$author_id ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 2, $data );
- $this->assertSameSets( array( self::$editor_id, self::$author_id ), wp_list_pluck( $data, 'author' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( 2, $data );
+ $this->assertSameSets( array( self::$editor_id, self::$author_id ), wp_list_pluck( $data, 'author' ) );
+ } else {
+ $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( 2, $headers['X-WP-Total'], 'Failed asserting that X-WP-Total header is 2.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Limit to editor.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'author', self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 1, $data );
- $this->assertSame( self::$editor_id, $data[0]['author'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( 1, $data );
+ $this->assertSame( self::$editor_id, $data[0]['author'] );
+ } else {
+ $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( 1, $headers['X-WP-Total'], 'Failed asserting that X-WP-Total header is 1.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_author_exclude_query() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_author_exclude_query( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> self::factory()->post->create( array( 'post_author' => self::$editor_id ) );
</span><span class="cx" style="display: block; padding: 0 10px"> self::factory()->post->create( array( 'post_author' => self::$author_id ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -330,42 +400,66 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_posts = self::$total_posts + 2;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // All posts in the database.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', self::$per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( $total_posts, $response->get_data() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( $total_posts, $response->get_data() );
+ } else {
+ $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Exclude editor and author.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', self::$per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'author_exclude', array( self::$editor_id, self::$author_id ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( $total_posts - 2, $data );
- $this->assertNotEquals( self::$editor_id, $data[0]['author'] );
- $this->assertNotEquals( self::$author_id, $data[0]['author'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( $total_posts - 2, $data );
+ $this->assertNotEquals( self::$editor_id, $data[0]['author'] );
+ $this->assertNotEquals( self::$author_id, $data[0]['author'] );
+ } else {
+ $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts - 2, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Exclude editor.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', self::$per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'author_exclude', self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( $total_posts - 1, $data );
- $this->assertNotEquals( self::$editor_id, $data[0]['author'] );
- $this->assertNotEquals( self::$editor_id, $data[1]['author'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( $total_posts - 1, $data );
+ $this->assertNotEquals( self::$editor_id, $data[0]['author'] );
+ $this->assertNotEquals( self::$editor_id, $data[1]['author'] );
+ } else {
+ $this->assertNull( $response->get_data(), 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts - 1, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Invalid 'author_exclude' should error.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'author_exclude', 'invalid' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_include_query() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_include_query( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $id1 = self::factory()->post->create(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'post_status' => 'publish',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -379,14 +473,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Order defaults to date descending.
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'include', array( $id1, $id2 ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 2, $data );
- $this->assertSame( $id2, $data[0]['id'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( 2, $data );
+ $this->assertSame( $id2, $data[0]['id'] );
+ } else {
+ $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( 2, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertPostsOrderedBy( '{posts}.post_date DESC' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // 'orderby' => 'include'.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -393,12 +494,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'orderby', 'include' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 2, $data );
- $this->assertSame( $id1, $data[0]['id'] );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $request->is_method( 'get' ) ) {
+ $this->assertCount( 2, $data );
+ $this->assertSame( $id1, $data[0]['id'] );
+ } else {
+ $this->assertNull( $data, 'Failed asserting that response data is null for HEAD request.' );
+ $headers = $response->get_headers();
+ $this->assertSame( 2, $headers['X-WP-Total'], 'Failed asserting that the number of posts is correct.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertPostsOrderedBy( "FIELD({posts}.ID,$id1,$id2)" );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Invalid 'include' should error.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'include', 'invalid' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1729,12 +1837,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSameSets( $parent_ids, $primed[1] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_pagination_headers() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_pagination_headers( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $total_posts = self::$total_posts;
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $total_posts / 10 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Start of the index.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_posts, $headers['X-WP-Total'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1752,7 +1866,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> self::factory()->post->create();
</span><span class="cx" style="display: block; padding: 0 10px"> ++$total_posts;
</span><span class="cx" style="display: block; padding: 0 10px"> ++$total_pages;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', 3 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1774,7 +1888,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringContainsString( '<' . $next_link . '>; rel="next"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Last page.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', $total_pages );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1790,7 +1904,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringNotContainsString( 'rel="next"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Out of bounds.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', 100 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1798,7 +1912,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // With query params.
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $total_posts / 5 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => 5,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1827,6 +1941,78 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringContainsString( '<' . $next_link . '>; rel="next"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_only_fetches_ids_for_head_requests( $method ) {
+ $is_head_request = 'HEAD' === $method;
+ $request = new WP_REST_Request( $method, '/wp/v2/posts' );
+
+ $filter = new MockAction();
+
+ add_filter( 'posts_pre_query', array( $filter, 'filter' ), 10, 2 );
+
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 200, $response->get_status() );
+ if ( $is_head_request ) {
+ $this->assertEmpty( $response->get_data() );
+ } else {
+ $this->assertNotEmpty( $response->get_data() );
+ }
+
+ $args = $filter->get_args();
+ $this->assertTrue( isset( $args[0][1] ), 'Query parameters were not captured.' );
+ $this->assertInstanceOf( WP_Query::class, $args[0][1], 'Query parameters were not captured.' );
+
+ /** @var WP_Query $query */
+ $query = $args[0][1];
+
+ if ( $is_head_request ) {
+ $this->assertArrayHasKey( 'fields', $query->query, 'The fields parameter is not set in the query vars.' );
+ $this->assertSame( 'ids', $query->query['fields'], 'The query must fetch only post IDs.' );
+ $this->assertArrayHasKey( 'fields', $query->query_vars, 'The fields parameter is not set in the query vars.' );
+ $this->assertSame( 'ids', $query->query_vars['fields'], 'The query must fetch only post IDs.' );
+ $this->assertArrayHasKey( 'update_post_term_cache', $query->query_vars, 'The "update_post_term_cache" parameter is missing in the query vars.' );
+ $this->assertFalse( $query->query_vars['update_post_term_cache'], 'The "update_post_term_cache" parameter must be false for HEAD requests.' );
+ $this->assertArrayHasKey( 'update_post_meta_cache', $query->query_vars, 'The "update_post_meta_cache" parameter is missing in the query vars.' );
+ $this->assertFalse( $query->query_vars['update_post_meta_cache'], 'The "update_post_meta_cache" parameter must be false for HEAD requests.' );
+ } else {
+ $this->assertTrue( ! array_key_exists( 'fields', $query->query ) || 'ids' !== $query->query['fields'], 'The fields parameter should not be forced to "ids" for non-HEAD requests.' );
+ $this->assertTrue( ! array_key_exists( 'fields', $query->query_vars ) || 'ids' !== $query->query_vars['fields'], 'The fields parameter should not be forced to "ids" for non-HEAD requests.' );
+ $this->assertArrayHasKey( 'update_post_term_cache', $query->query_vars, 'The "update_post_term_cache" parameter is missing in the query vars.' );
+ $this->assertTrue( $query->query_vars['update_post_term_cache'], 'The "update_post_term_cache" parameter must be true for non-HEAD requests.' );
+ $this->assertArrayHasKey( 'update_post_meta_cache', $query->query_vars, 'The "update_post_meta_cache" parameter is missing in the query vars.' );
+ $this->assertTrue( $query->query_vars['update_post_meta_cache'], 'The "update_post_meta_cache" parameter must be true for non-HEAD requests.' );
+ }
+
+ if ( ! $is_head_request ) {
+ return;
+ }
+
+ global $wpdb;
+ $posts_table = preg_quote( $wpdb->posts, '/' );
+ $pattern = '/^SELECT\s+SQL_CALC_FOUND_ROWS\s+' . $posts_table . '\.ID\s+FROM\s+' . $posts_table . '\s+WHERE/i';
+
+ // Assert that the SQL query only fetches the ID column.
+ $this->assertMatchesRegularExpression( $pattern, $query->request, 'The SQL query does not match the expected string.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_status_draft_permissions() {
</span><span class="cx" style="display: block; padding: 0 10px"> $draft_id = self::factory()->post->create( array( 'post_status' => 'draft' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1973,6 +2159,43 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_get_post_response( $response, 'view' );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/posts/%d', self::$post_id ) );
+
+ $hook_name = 'rest_prepare_' . get_post_type( self::$post_id );
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'Link', $headers, 'The "Link" header should be present in the response.' );
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_links() {
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestrequestphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-request.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-request.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-request.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1081,4 +1081,49 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertWPError( $valid );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 'rest_invalid_param', $valid->get_error_code() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * Tests that WP_REST_Request::is_method() correctly detects the request method,
+ * regardless of case sensitivity.
+ *
+ * @dataProvider data_is_method_should_detect_method_ignoring_case
+ * @ticket 56481
+ *
+ * @param string $method The expected HTTP method of the request.
+ * @param string $input_method The HTTP method to check against.
+ * @param bool $expected The expected result of the is_method() check.
+ */
+ public function test_is_method_should_detect_method_ignoring_case( $method, $input_method, $expected ) {
+ $request = new WP_REST_Request();
+ $request->set_method( $method );
+ $result = $request->is_method( $input_method );
+
+ $this->assertSame( $expected, $result, 'Failed asserting that the WP_REST_Request::is_method() method correctly detects the request method.' );
+ }
+
+ /**
+ * Provides test cases for verifying HTTP method comparison is case-insensitive.
+ *
+ * @return array
+ */
+ public function data_is_method_should_detect_method_ignoring_case() {
+ return array(
+ // GET.
+ 'GET same case' => array( 'GET', 'GET', true ),
+ 'GET different case' => array( 'GET', 'get', true ),
+ 'GET different case #2' => array( 'GET', 'get', true ),
+ 'GET different case #3' => array( 'GET', 'gEt', true ),
+ 'GET wrong method' => array( 'GET', 'POST', false ),
+ // POST.
+ 'POST same case' => array( 'POST', 'POST', true ),
+ 'POST different case' => array( 'POST', 'post', true ),
+ 'POST different case #2' => array( 'POST', 'pOsT', true ),
+ 'POST wrong method' => array( 'POST', 'GET', false ),
+ // HEAD.
+ 'HEAD same case' => array( 'HEAD', 'HEAD', true ),
+ 'HEAD different case' => array( 'HEAD', 'head', true ),
+ 'HEAD different case #2' => array( 'HEAD', 'HeAd', true ),
+ 'HEAD wrong method' => array( 'HEAD', 'GET', false ),
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestrevisionscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-revisions-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-revisions-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-revisions-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -162,9 +162,38 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_get_revision_response( $data[2], $this->revision_1 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_revisions_data() {
+ wp_set_current_user( self::$editor_id );
+
+ $hook_name = 'rest_prepare_revision';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+
+ add_filter( $hook_name, $callback );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/posts/' . self::$post_id . '/revisions' );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+
+ $this->assertNotWPError( $response );
+ $response = rest_ensure_response( $response );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -173,16 +202,40 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_missing_parent() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_missing_parent( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_parent_post_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_invalid_parent_post_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$page_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -213,6 +266,43 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( self::$editor_id, $data['author'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ wp_set_current_user( self::$editor_id );
+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
+
+ $hook_name = 'rest_prepare_revision';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'GET' === $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_embed_context() {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -231,9 +321,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSameSets( $fields, array_keys( $data ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_id1 );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 401 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -242,16 +338,28 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_missing_parent() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_missing_parent( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions/' . $this->revision_id1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . REST_TESTS_IMPOSSIBLY_HIGH_NUMBER . '/revisions/' . $this->revision_id1 );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_parent_post_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_invalid_parent_post_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$page_id . '/revisions/' . $this->revision_id1 );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$page_id . '/revisions/' . $this->revision_id1 );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -269,11 +377,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 59875
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_parent_id() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_invalid_parent_id( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_2_1_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions/' . $this->revision_2_1_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_revision_parent_id_mismatch', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -510,9 +622,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test the pagination header of the first page.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_pagination_header_of_the_first_page() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_pagination_header_of_the_first_page( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $rest_route = '/wp/v2/posts/' . self::$post_id . '/revisions';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -520,7 +636,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $this->total_revisions / $per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $page = 1; // First page.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', $rest_route );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, $rest_route );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -545,9 +661,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test the pagination header of the last page.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_pagination_header_of_the_last_page() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_pagination_header_of_the_last_page( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $rest_route = '/wp/v2/posts/' . self::$post_id . '/revisions';
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -555,7 +675,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $this->total_revisions / $per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $page = 2; // Last page.
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', $rest_route );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, $rest_route );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -576,12 +696,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringContainsString( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
</ins><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test that invalid 'per_page' query should error.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_per_page_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_per_page_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = -1; // Invalid number.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -588,7 +713,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_invalid_param';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', $per_page );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( $expected_error, $response, $expected_status );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -597,9 +722,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test that out of bounds 'page' query should error.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_out_of_bounds_page_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_out_of_bounds_page_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -608,7 +737,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_page_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -622,9 +751,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test that impossibly high 'page' query should error.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_max_pages_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_max_pages_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -632,7 +765,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_page_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => $per_page,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -770,9 +903,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test that out of bound 'offset' query should error.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_out_of_bound_offset_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_out_of_bound_offset_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -780,7 +917,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_offset_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -794,9 +931,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test that impossible high number for 'offset' query should error.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_impossible_high_number_offset_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_impossible_high_number_offset_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -804,7 +945,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_revision_invalid_offset_number';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -818,9 +959,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test that invalid 'offset' query should error.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 40510
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_offset_should_error() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_invalid_offset_should_error( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $per_page = 2;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -828,7 +973,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_error = 'rest_invalid_param';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_status = 400;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/posts/' . self::$post_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/posts/' . self::$post_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_query_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'offset' => $offset,
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestsearchcontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-search-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-search-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-search-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -161,6 +161,101 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Test pagination headers.
+ *
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_pagination_headers( $method ) {
+ $total_posts = count( self::$my_title_post_ids ) + count( self::$my_title_page_ids ) + count( self::$my_content_post_ids );
+ $per_page = 3;
+ $total_pages = (int) ceil( $total_posts / $per_page );
+
+ // Start of the index.
+ $response = $this->do_request_with_params(
+ array(
+ 'per_page' => $per_page,
+ ),
+ $method
+ );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts, $headers['X-WP-Total'] );
+ $this->assertSame( $total_pages, $headers['X-WP-TotalPages'] );
+
+ $next_link = add_query_arg(
+ array(
+ 'per_page' => $per_page,
+ 'page' => 2,
+ ),
+ rest_url( '/wp/v2/search' )
+ );
+ $this->assertStringNotContainsString( 'rel="prev"', $headers['Link'] );
+ $this->assertStringContainsString( '<' . $next_link . '>; rel="next"', $headers['Link'] );
+
+ $response = $this->do_request_with_params(
+ array(
+ 'per_page' => $per_page,
+ 'page' => 3,
+ ),
+ $method
+ );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts, $headers['X-WP-Total'] );
+ $this->assertSame( $total_pages, $headers['X-WP-TotalPages'] );
+ $prev_link = add_query_arg(
+ array(
+ 'per_page' => $per_page,
+ 'page' => 2,
+ ),
+ rest_url( '/wp/v2/search' )
+ );
+ $this->assertStringContainsString( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
+ $next_link = add_query_arg(
+ array(
+ 'per_page' => $per_page,
+ 'page' => 4,
+ ),
+ rest_url( '/wp/v2/search' )
+ );
+ $this->assertStringContainsString( '<' . $next_link . '>; rel="next"', $headers['Link'] );
+
+ // Last page.
+ $response = $this->do_request_with_params(
+ array(
+ 'per_page' => $per_page,
+ 'page' => $total_pages,
+ ),
+ $method
+ );
+ $headers = $response->get_headers();
+ $this->assertSame( $total_posts, $headers['X-WP-Total'] );
+ $this->assertSame( $total_pages, $headers['X-WP-TotalPages'] );
+ $prev_link = add_query_arg(
+ array(
+ 'per_page' => $per_page,
+ 'page' => $total_pages - 1,
+ ),
+ rest_url( '/wp/v2/search' )
+ );
+ $this->assertStringContainsString( '<' . $prev_link . '>; rel="prev"', $headers['Link'] );
+ $this->assertStringNotContainsString( 'rel="next"', $headers['Link'] );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Search through all content with a low limit.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_with_limit() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -239,13 +334,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Search through an invalid type
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_search_type_invalid() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_search_type_invalid( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = $this->do_request_with_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => 100,
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'invalid',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ),
+ $method
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -253,6 +354,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Search through posts of an invalid post type.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_search_type_post_subtype_invalid() {
</span><span class="cx" style="display: block; padding: 0 10px"> $response = $this->do_request_with_params(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -462,13 +568,19 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Tests that non-public post types are not allowed.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_non_public_post_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_non_public_post_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = $this->do_request_with_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'post',
</span><span class="cx" style="display: block; padding: 0 10px"> 'subtype' => 'post,nav_menu_item',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ),
+ $method
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -632,15 +744,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Search through posts of an invalid post type.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 51458
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_search_term_subtype_invalid() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_search_term_subtype_invalid( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = $this->do_request_with_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => 100,
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => 'term',
</span><span class="cx" style="display: block; padding: 0 10px"> 'subtype' => 'invalid',
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ),
+ $method
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -890,14 +1008,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 60771
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_sanitize_subtypes_validates_type() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_sanitize_subtypes_validates_type( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = $this->do_request_with_params(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'subtype' => 'page',
</span><span class="cx" style="display: block; padding: 0 10px"> 'type' => array( 'invalid' ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ ),
+ $method
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestsidebarscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-sidebars-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-sidebars-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-sidebars-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -152,11 +152,38 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_sidebar_data() {
+ wp_widgets_init();
+
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/sidebars' );
+
+ $hook_name = 'rest_prepare_sidebar';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+
+ $this->assertNotWPError( $response );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/sidebars' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/sidebars' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -501,9 +528,68 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $hook_name = 'rest_prepare_sidebar';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->setup_sidebar(
+ 'sidebar-1',
+ array(
+ 'name' => 'Test sidebar',
+ )
+ );
+
+ $request = new WP_REST_Request( $method, '/wp/v2/sidebars/sidebar-1' );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->setup_sidebar(
</span><span class="cx" style="display: block; padding: 0 10px"> 'sidebar-1',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -512,7 +598,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/sidebars/sidebar-1' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/sidebars/sidebar-1' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -552,9 +638,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_wrong_permission_author() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_wrong_permission_author( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$author_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->setup_sidebar(
</span><span class="cx" style="display: block; padding: 0 10px"> 'sidebar-1',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -563,7 +653,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/sidebars/sidebar-1' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/sidebars/sidebar-1' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiresttagscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-tags-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-tags-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-tags-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -627,12 +627,18 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_no_route', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_terms_pagination_headers() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_terms_pagination_headers( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $total_tags = self::$total_tags;
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $total_tags / 10 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Start of the index.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/tags' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/tags' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_tags, $headers['X-WP-Total'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1502,4 +1508,112 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $tag = get_term( $id, 'post_tag' );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_taxonomy_term( $tag, $data, $response->get_links() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_only_fetches_ids_for_head_requests( $method ) {
+ $is_head_request = 'HEAD' === $method;
+ $request = new WP_REST_Request( $method, '/wp/v2/tags' );
+
+ $filter = new MockAction();
+
+ add_filter( 'terms_pre_query', array( $filter, 'filter' ), 10, 2 );
+
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 200, $response->get_status() );
+ if ( $is_head_request ) {
+ $this->assertEmpty( $response->get_data() );
+ } else {
+ $this->assertNotEmpty( $response->get_data() );
+ }
+
+ $args = $filter->get_args();
+ $this->assertTrue( isset( $args[0][1] ), 'Query parameters were not captured.' );
+ $this->assertInstanceOf( WP_Term_Query::class, $args[0][1], 'Query parameters were not captured.' );
+
+ /** @var WP_Term_Query $query */
+ $query = $args[0][1];
+
+ if ( $is_head_request ) {
+ $this->assertArrayHasKey( 'fields', $query->query_vars, 'The fields parameter is not set in the query vars.' );
+ $this->assertSame( 'ids', $query->query_vars['fields'], 'The query must fetch only term IDs.' );
+ $this->assertArrayHasKey( 'update_term_meta_cache', $query->query_vars, 'The update_term_meta_cache key is missing in the query vars.' );
+ $this->assertFalse( $query->query_vars['update_term_meta_cache'], 'The update_term_meta_cache value should be false for HEAD requests.' );
+ } else {
+ $this->assertTrue(
+ ! array_key_exists( 'fields', $query->query_vars ) || 'ids' !== $query->query_vars['fields'],
+ 'The fields parameter should not be forced to "ids" for non-HEAD requests.'
+ );
+ $this->assertArrayHasKey( 'update_term_meta_cache', $query->query_vars, 'The update_term_meta_cache key is missing in the query vars.' );
+ $this->assertTrue( $query->query_vars['update_term_meta_cache'], 'The update_term_meta_cache value should be true for HEAD requests.' );
+ }
+
+ if ( ! $is_head_request ) {
+ return;
+ }
+
+ global $wpdb;
+ $terms_table = preg_quote( $wpdb->terms, '/' );
+
+ $pattern = '/SELECT\s+t\.term_id.+FROM\s+' . $terms_table . '\s+AS\s+t\s+INNER\s+JOIN/is';
+
+ // Assert that the SQL query only fetches the term_id column.
+ $this->assertMatchesRegularExpression( $pattern, $query->request, 'The SQL query does not match the expected string.' );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( string $method ) {
+ $tag_id = self::factory()->tag->create();
+
+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/tags/%d', $tag_id ) );
+
+ $hook_name = 'rest_prepare_post_tag';
+
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiresttaxonomiescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-taxonomies-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -60,6 +60,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 'tags', $data['post_tag']['rest_base'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_taxonomy_data() {
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/taxonomies' );
+ $hook_name = 'rest_prepare_taxonomy';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_context_edit() {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -79,14 +95,33 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 'tags', $data['post_tag']['rest_base'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_invalid_permission_for_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_invalid_permission_for_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/taxonomies' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_view', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_taxonomies_for_type() {
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'type', 'post' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -94,11 +129,20 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_taxonomies_for_type_response( 'post', $response );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_taxonomies_for_invalid_type() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_taxonomies_for_invalid_type( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/taxonomies' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'type', 'wingding' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' === $method ) {
+ return null;
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> $data = $response->get_data();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( '{}', json_encode( $data ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -109,6 +153,41 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_taxonomy_object_response( 'view', $response );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/taxonomies/category' );
+ $hook_name = 'rest_prepare_taxonomy';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_edit_context() {
</span><span class="cx" style="display: block; padding: 0 10px"> $editor_id = self::factory()->user->create( array( 'role' => 'editor' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( $editor_id );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -118,33 +197,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_taxonomy_object_response( 'edit', $response );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_permission_for_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_item_invalid_permission_for_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/category' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/taxonomies/category' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_forbidden_context', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_invalid_taxonomy() {
- $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/invalid' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_invalid_taxonomy( $method ) {
+ $request = new WP_REST_Request( $method, '/wp/v2/taxonomies/invalid' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_taxonomy_invalid', $response, 404 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_non_public_taxonomy_not_authenticated() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_non_public_taxonomy_not_authenticated( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> register_taxonomy( 'api-private', 'post', array( 'public' => false ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/api-private' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/taxonomies/api-private' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_forbidden', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_non_public_taxonomy_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_non_public_taxonomy_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> register_taxonomy( 'api-private', 'post', array( 'public' => false ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/taxonomies/api-private' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/taxonomies/api-private' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_forbidden', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestuserscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-users-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-users-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-users-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -234,15 +234,30 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_user_data( $userdata, $data, 'view', $data['_links'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_with_edit_context() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_with_edit_context( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$user );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( 200, $response->get_status() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertSame(
+ 200,
+ $response->get_status(),
+ sprintf( 'Expected HTTP status code 200 but got %s.', $response->get_status() )
+ );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' === $method ) {
+ $this->assertNull( $response->get_data(), 'Expected null response data for HEAD request, but received non-null data.' );
+ return null;
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $all_data = $response->get_data();
</span><span class="cx" style="display: block; padding: 0 10px"> $data = $all_data[0];
</span><span class="cx" style="display: block; padding: 0 10px"> $userdata = get_userdata( $data['id'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -249,9 +264,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->check_user_data( $userdata, $data, 'edit', $data['_links'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_with_edit_context_without_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_with_edit_context_without_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> // Test with a user not logged in.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -261,7 +294,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> // capability in question: 'list_users'.
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'context', 'edit' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -319,7 +352,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertNotContains( self::$user, $user_ids );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_pagination_headers() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_pagination_headers( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $total_users = self::$total_users;
</span><span class="cx" style="display: block; padding: 0 10px"> $total_pages = (int) ceil( $total_users / 10 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -326,7 +365,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$user );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Start of the index.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $total_users, $headers['X-WP-Total'] );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -344,7 +383,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> self::factory()->user->create();
</span><span class="cx" style="display: block; padding: 0 10px"> ++$total_users;
</span><span class="cx" style="display: block; padding: 0 10px"> ++$total_pages;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', 3 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -366,7 +405,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringContainsString( '<' . $next_link . '>; rel="next"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Last page.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', $total_pages );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -382,7 +421,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertStringNotContainsString( 'rel="next"', $headers['Link'] );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Out of bounds.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', 100 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -411,14 +450,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertCount( 5, $response->get_data() );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_page() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_page( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$user );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'per_page', 5 );
</span><span class="cx" style="display: block; padding: 0 10px"> $request->set_param( 'page', 2 );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertCount( 5, $response->get_data() );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ if ( 'HEAD' !== $method ) {
+ $this->assertCount( 5, $response->get_data() );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> $prev_link = add_query_arg(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'per_page' => 5,
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1265,17 +1314,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_user_cannot_view', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_current_user() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_current_user( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$user );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/users/me' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/users/me' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( 200, $response->get_status() );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->check_get_user_response( $response, 'view' );
-
</del><span class="cx" style="display: block; padding: 0 10px"> $headers = $response->get_headers();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertArrayNotHasKey( 'Location', $headers );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( 'HEAD' === $method ) {
+ // HEAD responses only contain headers. Bail.
+ return null;
+ }
+ $this->check_get_user_response( $response, 'view' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $links = $response->get_links();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( rest_url( 'wp/v2/users/' . self::$user ), $links['self'][0]['href'] );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3158,6 +3216,96 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ wp_set_current_user( self::$user );
+ $request = new WP_REST_Request( $method, sprintf( '/wp/v2/users/%d', self::$user ) );
+
+ $hook_name = 'rest_prepare_user';
+
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
+ */
+ public function test_get_items_only_fetches_ids_for_head_requests( $method ) {
+ $is_head_request = 'HEAD' === $method;
+ $request = new WP_REST_Request( $method, '/wp/v2/users' );
+
+ $filter = new MockAction();
+
+ add_filter( 'pre_user_query', array( $filter, 'filter' ), 10, 2 );
+
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 200, $response->get_status() );
+ if ( $is_head_request ) {
+ $this->assertNull( $response->get_data() );
+ } else {
+ $this->assertNotEmpty( $response->get_data() );
+ }
+
+ $args = $filter->get_args();
+ $this->assertTrue( isset( $args[0][0] ), 'Query parameters were not captured.' );
+ $this->assertInstanceOf( WP_User_Query::class, $args[0][0], 'Query parameters were not captured.' );
+
+ /** @var WP_User $query */
+ $query = $args[0][0];
+
+ if ( $is_head_request ) {
+ $this->assertArrayHasKey( 'fields', $query->query_vars, 'The fields parameter is not set in the query vars.' );
+ $this->assertSame( 'id', $query->query_vars['fields'], 'The query must fetch only user IDs.' );
+ } else {
+ $this->assertTrue(
+ ! array_key_exists( 'fields', $query->query_vars ) || 'id' !== $query->query_vars['fields'],
+ 'The fields parameter should not be forced to "id" for non-HEAD requests.'
+ );
+ }
+
+ if ( ! $is_head_request ) {
+ return;
+ }
+
+ global $wpdb;
+ $users_table = preg_quote( $wpdb->users, '/' );
+ $pattern = '/SELECT SQL_CALC_FOUND_ROWS wptests_users.ID\n\s+FROM\s+' . $users_table . '/is';
+
+ // Assert that the SQL query only fetches the id column.
+ $this->assertMatchesRegularExpression( $pattern, $query->request, 'The SQL query does not match the expected string.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> protected function check_user_data( $user, $data, $context, $links ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $user->ID, $data['id'] );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $user->display_name, $data['name'] );
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestwidgettypescontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-widget-types-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-widget-types-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-widget-types-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -122,6 +122,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_widget_types_data() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/widget-types' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 53303
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_ordering() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -182,6 +193,56 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $widget_name = 'calendar';
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( $method, '/wp/v2/widget-types/' . $widget_name );
+
+ $hook_name = 'rest_prepare_widget_type';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_widget_legacy() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -200,12 +261,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_widget_invalid_name() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_widget_invalid_name( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $widget_type = 'fake';
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types/' . $widget_type );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widget-types/' . $widget_type );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_widget_type_invalid', $response, 404 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -251,41 +316,57 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_wrong_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_wrong_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widget-types' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_wrong_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_wrong_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types/calendar' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widget-types/calendar' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widget-types' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widget-types/calendar' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widget-types/calendar' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapirestwidgetscontrollerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/rest-widgets-controller.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/rest-widgets-controller.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/rest-widgets-controller.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -228,16 +228,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widgets' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widgets' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Data provider intended to provide HTTP method names for testing GET and HEAD requests.
+ *
+ * @return array
+ */
+ public static function data_readable_http_methods() {
+ return array(
+ 'GET request' => array( 'GET' ),
+ 'HEAD request' => array( 'HEAD' ),
+ );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 53915
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_no_permission_show_in_rest() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -332,11 +348,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_wrong_permission_author() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_wrong_permission_author( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$author_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widgets' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widgets' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -377,8 +397,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/widgets' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $data = $response->get_data();
- $data = $this->remove_links( $data );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ remove_filter( 'pre_http_request', array( $this, 'mocked_rss_response' ) );
+ $data = $response->get_data();
+ $data = $this->remove_links( $data );
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertSameSets(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="cx" style="display: block; padding: 0 10px"> array(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -406,6 +427,54 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_widget_factory->widgets['WP_Widget_RSS']->widget_options['show_instance_in_rest'] = true;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_items_with_head_request_should_not_prepare_widget_data( $method ) {
+ $block_content = '<!-- wp:paragraph --><p>Block test</p><!-- /wp:paragraph -->';
+
+ $this->setup_widget(
+ 'rss',
+ 1,
+ array(
+ 'title' => 'RSS test',
+ 'url' => 'https://wordpress.org/news/feed',
+ )
+ );
+ $this->setup_widget(
+ 'block',
+ 1,
+ array(
+ 'content' => $block_content,
+ )
+ );
+ $this->setup_sidebar(
+ 'sidebar-1',
+ array(
+ 'name' => 'Test sidebar',
+ ),
+ array( 'block-1', 'rss-1', 'testwidget' )
+ );
+
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/widgets' );
+
+ $hook_name = 'rest_prepare_post';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+
+ add_filter( $hook_name, $callback );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+
+ $this->assertNotWPError( $response );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 0, $filter->get_call_count(), 'The "' . $hook_name . '" filter was called when it should not be for HEAD requests.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function mocked_rss_response() {
</span><span class="cx" style="display: block; padding: 0 10px"> $single_value_headers = array(
</span><span class="cx" style="display: block; padding: 0 10px"> 'Content-Type' => 'application/rss+xml; charset=UTF-8',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -528,9 +597,64 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
+ */
+ public function test_get_item_should_allow_adding_headers_via_filter( $method ) {
+ $this->setup_widget(
+ 'text',
+ 1,
+ array(
+ 'text' => 'Custom text test',
+ )
+ );
+ $this->setup_sidebar(
+ 'sidebar-1',
+ array(
+ 'name' => 'Test sidebar',
+ ),
+ array( 'text-1' )
+ );
+
+ $request = new WP_REST_Request( $method, '/wp/v2/widgets/text-1' );
+
+ $hook_name = 'rest_prepare_widget';
+ $filter = new MockAction();
+ $callback = array( $filter, 'filter' );
+ add_filter( $hook_name, $callback );
+ $header_filter = new class() {
+ public static function add_custom_header( $response ) {
+ $response->header( 'X-Test-Header', 'Test' );
+
+ return $response;
+ }
+ };
+ add_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+ $response = rest_get_server()->dispatch( $request );
+ remove_filter( $hook_name, $callback );
+ remove_filter( $hook_name, array( $header_filter, 'add_custom_header' ) );
+
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertSame( 1, $filter->get_call_count(), 'The "' . $hook_name . '" filter was not called when it should be for GET/HEAD requests.' );
+ $headers = $response->get_headers();
+ $this->assertArrayHasKey( 'X-Test-Header', $headers, 'The "X-Test-Header" header should be present in the response.' );
+ $this->assertSame( 'Test', $headers['X-Test-Header'], 'The "X-Test-Header" header value should be equal to "Test".' );
+ if ( 'HEAD' !== $method ) {
+ return null;
+ }
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_no_permission() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_no_permission( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->setup_widget(
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -548,15 +672,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> array( 'text-1' )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widgets/text-1' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widgets/text-1' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 401 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @dataProvider data_readable_http_methods
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41683
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
+ * @param string $method The HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_wrong_permission_author() {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_wrong_permission_author( $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$author_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->setup_widget(
</span><span class="cx" style="display: block; padding: 0 10px"> 'text',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -572,7 +700,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> )
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/widgets/text-1' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/widgets/text-1' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_widgets', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiwpRestBlockPatternCategoriesControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/wpRestBlockPatternCategoriesController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/wpRestBlockPatternCategoriesController.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/wpRestBlockPatternCategoriesController.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -124,6 +124,17 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_items_with_head_request_should_not_prepare_block_pattern_categories_data() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', static::REQUEST_ROUTE );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'The response status should be 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Verify capability check for unauthorized request (not logged in).
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_unauthorized() {
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiwpRestTemplateAutosavesControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/wpRestTemplateAutosavesController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/wpRestTemplateAutosavesController.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/wpRestTemplateAutosavesController.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -35,6 +35,11 @@
</span><span class="cx" style="display: block; padding: 0 10px"> const TEMPLATE_PART_POST_TYPE = 'wp_template_part';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @var string
+ */
+ const PARENT_POST_TYPE = 'wp_template';
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Admin user ID.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 6.4.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -293,6 +298,28 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_items_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $autosave_post_id = wp_create_post_autosave(
+ array(
+ 'post_content' => 'Autosave content.',
+ 'post_ID' => self::$template_post->ID,
+ 'post_type' => self::PARENT_POST_TYPE,
+ )
+ );
+
+ $request = new WP_REST_Request(
+ 'HEAD',
+ '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/autosaves'
+ );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Data provider for test_get_items_with_data_provider.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return array
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -427,6 +454,26 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_item_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+
+ $autosave_post_id = wp_create_post_autosave(
+ array(
+ 'post_content' => 'Autosave content.',
+ 'post_ID' => self::$template_post->ID,
+ 'post_type' => self::PARENT_POST_TYPE,
+ )
+ );
+
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/autosaves/' . $autosave_post_id );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Data provider for test_get_item_with_data_provider.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return array
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiwpRestTemplateRevisionsControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/wpRestTemplateRevisionsController.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -426,18 +426,33 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 'template parts' => array( 'template_part_post', 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME ),
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @ticket 56481
+ */
+ public function test_get_items_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request(
+ 'HEAD',
+ '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/revisions'
+ );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * @dataProvider data_get_items_endpoint_should_return_unauthorized_https_status_code_for_unauthorized_request
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Template_Revisions_Controller::get_items_permissions_check
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 56922
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $rest_base Base part of the REST API endpoint to test.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $template_id Template ID to use in the test.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_endpoint_should_return_unauthorized_https_status_code_for_unauthorized_request( $rest_base, $template_id ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_endpoint_should_return_unauthorized_https_status_code_for_unauthorized_request( $rest_base, $template_id, $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( 0 );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/' . $rest_base . '/' . $template_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/' . $rest_base . '/' . $template_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, WP_Http::UNAUTHORIZED );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -449,8 +464,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function data_get_items_endpoint_should_return_unauthorized_https_status_code_for_unauthorized_request() {
</span><span class="cx" style="display: block; padding: 0 10px"> return array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'templates' => array( 'templates', self::TEST_THEME . '//' . self::TEMPLATE_NAME ),
- 'template parts' => array( 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'templates, GET request' => array( 'templates', self::TEST_THEME . '//' . self::TEMPLATE_NAME, 'GET' ),
+ 'templates, HEAD request' => array( 'templates', self::TEST_THEME . '//' . self::TEMPLATE_NAME, 'HEAD' ),
+ 'template parts, GET request' => array( 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME, 'GET' ),
+ 'template parts, HEAD request' => array( 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME, 'HEAD' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -458,13 +475,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @dataProvider data_get_items_endpoint_should_return_forbidden_https_status_code_for_users_with_insufficient_permissions
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Template_Revisions_Controller::get_items_permissions_check
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 56922
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $rest_base Base part of the REST API endpoint to test.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $template_id Template ID to use in the test.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_items_endpoint_should_return_forbidden_https_status_code_for_users_with_insufficient_permissions( $rest_base, string $template_id ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_endpoint_should_return_forbidden_https_status_code_for_users_with_insufficient_permissions( $rest_base, string $template_id, $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$contributor_id );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/' . $rest_base . '/' . $template_id . '/revisions' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/' . $rest_base . '/' . $template_id . '/revisions' );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_read', $response, WP_Http::FORBIDDEN );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -476,8 +495,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function data_get_items_endpoint_should_return_forbidden_https_status_code_for_users_with_insufficient_permissions() {
</span><span class="cx" style="display: block; padding: 0 10px"> return array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'templates' => array( 'templates', self::TEST_THEME . '//' . self::TEMPLATE_NAME ),
- 'template parts' => array( 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'templates, GET request' => array( 'templates', self::TEST_THEME . '//' . self::TEMPLATE_NAME, 'GET' ),
+ 'templates, HEAD request' => array( 'templates', self::TEST_THEME . '//' . self::TEMPLATE_NAME, 'HEAD' ),
+ 'template parts, GET request' => array( 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME, 'GET' ),
+ 'template parts, HEAD request' => array( 'template-parts', self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME, 'HEAD' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -597,6 +618,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ */
+ public function test_get_item_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $revisions = wp_get_post_revisions( self::$template_post, array( 'fields' => 'ids' ) );
+ $revision_id = array_shift( $revisions );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/templates/' . self::TEST_THEME . '/' . self::TEMPLATE_NAME . '/revisions/' . $revision_id );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Data provider for test_get_item_with_data_provider.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @return array
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -612,11 +646,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @dataProvider data_get_item_not_found
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Template_Revisions_Controller::get_item
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 56922
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $parent_post_property_name A class property name that contains the parent post object.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $rest_base Base part of the REST API endpoint to test.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_not_found( $parent_post_property_name, $rest_base ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_not_found( $parent_post_property_name, $rest_base, $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $parent_post = self::$$parent_post_property_name;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -624,7 +660,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $revisions = wp_get_post_revisions( $parent_post, array( 'fields' => 'ids' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $revision_id = array_shift( $revisions );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/' . $rest_base . '/invalid//parent/revisions/' . $revision_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/' . $rest_base . '/invalid//parent/revisions/' . $revision_id );
</ins><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_post_invalid_parent', $response, WP_Http::NOT_FOUND );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -636,8 +672,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function data_get_item_not_found() {
</span><span class="cx" style="display: block; padding: 0 10px"> return array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'templates' => array( 'template_post', 'templates' ),
- 'template parts' => array( 'template_part_post', 'template-parts' ),
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'templates, GET request' => array( 'template_post', 'templates', 'GET' ),
+ 'templates, HEAD request' => array( 'template_post', 'templates', 'HEAD' ),
+ 'template parts, GET request' => array( 'template_part_post', 'template-parts', 'GET' ),
+ 'template parts, HEAD request' => array( 'template_part_post', 'template-parts', 'HEAD' ),
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -645,13 +683,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @dataProvider data_get_item_invalid_parent_id
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Template_Revisions_Controller::get_item
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 59875
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $parent_post_property_name A class property name that contains the parent post object.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $actual_parent_post_property_name A class property name that contains the parent post object.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $rest_base Base part of the REST API endpoint to test.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $template_id Template ID to use in the test.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $method HTTP method to use.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- public function test_get_item_invalid_parent_id( $parent_post_property_name, $actual_parent_post_property_name, $rest_base, $template_id ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_invalid_parent_id( $parent_post_property_name, $actual_parent_post_property_name, $rest_base, $template_id, $method ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$admin_id );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $parent_post = self::$$parent_post_property_name;
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -659,7 +699,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $revisions = wp_get_post_revisions( $parent_post, array( 'fields' => 'ids' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> $revision_id = array_shift( $revisions );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $request = new WP_REST_Request( 'GET', '/wp/v2/' . $rest_base . '/' . $template_id . '/revisions/' . $revision_id );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $request = new WP_REST_Request( $method, '/wp/v2/' . $rest_base . '/' . $template_id . '/revisions/' . $revision_id );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_revision_parent_id_mismatch', $response, 404 );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -675,18 +715,34 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function data_get_item_invalid_parent_id() {
</span><span class="cx" style="display: block; padding: 0 10px"> return array(
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'templates' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'templates, GET request' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'template_post',
</span><span class="cx" style="display: block; padding: 0 10px"> 'template_post_2',
</span><span class="cx" style="display: block; padding: 0 10px"> 'templates',
</span><span class="cx" style="display: block; padding: 0 10px"> self::TEST_THEME . '//' . self::TEMPLATE_NAME_2,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'GET',
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- 'template parts' => array(
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'templates, HEAD request' => array(
+ 'template_post',
+ 'template_post_2',
+ 'templates',
+ self::TEST_THEME . '//' . self::TEMPLATE_NAME_2,
+ 'HEAD',
+ ),
+ 'template parts, GET request' => array(
</ins><span class="cx" style="display: block; padding: 0 10px"> 'template_part_post',
</span><span class="cx" style="display: block; padding: 0 10px"> 'template_part_post_2',
</span><span class="cx" style="display: block; padding: 0 10px"> 'template-parts',
</span><span class="cx" style="display: block; padding: 0 10px"> self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME_2,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'GET',
</ins><span class="cx" style="display: block; padding: 0 10px"> ),
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ 'template parts, HEAD request' => array(
+ 'template_part_post',
+ 'template_part_post_2',
+ 'template-parts',
+ self::TEST_THEME . '//' . self::TEMPLATE_PART_NAME_2,
+ 'HEAD',
+ ),
</ins><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre></div>
<a id="trunktestsphpunittestsrestapiwpRestTemplatesControllerphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php 2025-03-02 19:46:43 UTC (rev 59898)
+++ trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php 2025-03-02 22:05:08 UTC (rev 59899)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -176,8 +176,21 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Templates_Controller::get_items
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_items_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/templates' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @covers WP_REST_Templates_Controller::get_items
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_items_editor() {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/templates' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -268,8 +281,22 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 56481
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers WP_REST_Templates_Controller::get_item
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @covers WP_REST_Templates_Controller::prepare_item_for_response
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ public function test_get_item_should_return_no_response_body_for_head_requests() {
+ wp_set_current_user( self::$admin_id );
+ $request = new WP_REST_Request( 'HEAD', '/wp/v2/templates/default//my_template' );
+ $response = rest_get_server()->dispatch( $request );
+ $this->assertSame( 200, $response->get_status(), 'Response status is 200.' );
+ $this->assertNull( $response->get_data(), 'The server should not generate a body in response to a HEAD request.' );
+ }
+
+ /**
+ * @covers WP_REST_Templates_Controller::get_item
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> public function test_get_item_editor() {
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$editor_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/templates/default//my_template' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -311,7 +338,6 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_set_current_user( self::$subscriber_id );
</span><span class="cx" style="display: block; padding: 0 10px"> $request = new WP_REST_Request( 'GET', '/wp/v2/templates/default//my_template' );
</span><span class="cx" style="display: block; padding: 0 10px"> $response = rest_get_server()->dispatch( $request );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $response = rest_get_server()->dispatch( $request );
</del><span class="cx" style="display: block; padding: 0 10px"> $this->assertErrorResponse( 'rest_cannot_manage_templates', $response, 403 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span></span></pre>
</div>
</div>
</body>
</html>