Make WordPress Core

Opened 2 years ago

Closed 2 years ago

#55129 closed defect (bug) (worksforme)

WP REST API - Updating "status" field on a "post" from "future" to "publish" does not work

Reported by: mcmwebsol's profile mcmwebsol Owned by:
Milestone: Priority: normal
Severity: normal Version: 4.7
Component: REST API Keywords: reporter-feedback
Focuses: Cc:

Description

When using the WP REST API's "posts" endpoint to update an existing post, the "status" field will not update from "future" to "publish".

Example Request:
curl -X POST https://example.com/wp-json/wp/v2/posts/2742 -d '{"status":"publish"}'

Example Response:
{"id":2742,"date":"2022-02-12T12:30:00","date_gmt":"2022-02-12T18:30:00","guid":{"rendered":"https:\/\/subdomain.wpengine.com\/?p=2742","raw":"https:\/\/subdomainagi.wpengine.com\/?p=2742"},"modified":"2022-02-09T12:30:22","modified_gmt":"2022-02-09T18:30:22","password":"","slug":"formerly-scheduled-test","status":"future","type":"post","link":"https:\/\/robertsonstagi.wpengine.com\/?p=2742","title":{"raw":"Formerly Scheduled Test","rendered":"Formerly Scheduled Test"},"content":{"raw":"
fake content here<\/p>\r\n","rendered":"

fake content here<\/p>\n","protected":false,"block_version":0},"excerpt":{"raw":"","rendered":"

fake content here<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_yoast_wpseo_focuskw":"","_yoast_wpseo_metadesc":"","tdm_status":"","tdm_grid_status":"","_yoast_wpseo_primary_category":17,"_yoast_wpseo_focuskeywords":""},"categories":[17,13],"tags":[57],"permalink_template":"https:\/\/robertsonstagi.wpengine.com\/%postname%\/","generated_slug":"formerly-scheduled-test","td_post_theme_settings":"","yoast_head":"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t\n

Note that updating the status from "draft" to "publish" works (and vice versa). Also updating the status from "future" to "draft" works (and vice versa). Additonally, updating the date/time of a "future" status works (at least if the date/time is in the future).

Thank you

Attachments (1)

wp_rest_api_cannot_change_status_from_future_to_publish.png (66.1 KB) - added by mcmwebsol 2 years ago.
Screenshot

Download all attachments as: .zip

Change History (10)

#1 follow-up: @rafiahmedd
2 years ago

I just check the issue and I can see it's working perfectly fine with

Content-Type: multipart/form-data


#2 in reply to: ↑ 1 @mcmwebsol
2 years ago

Replying to rafiahmedd:

I just check the issue and I can see it's working perfectly fine with

Content-Type: multipart/form-data


I tried it now with Content-Type: multipart/form-data using the below PHP code (sensitive information scrubbed) and it still does not update the status to "publish"

$siteURL = 'https://subdomain.wpengine.com';
$url = $siteURL.'/wp-json/wp/v2/posts/3302';
$data = array(

'status' => 'publish'

);
$username = 'user';
$password = 'pass'
posty($url, $data, $username, $password);

function posty($url, $data, $username, $password) {

$ch = curl_init($url);


$headers = [

'Cache-Control: no-cache',
'Content-Type: multipart/form-data',
'Accept: application/json'

];


curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password" );
curl_setopt($ch, CURLOPT_HEADER, 0); set to 0 to eliminate header info from response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
Returns response data instead of TRUE(1)
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); use HTTP POST to send form data
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
for now..
curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
$resp = curl_exec($ch); execute post and get results


print " resp=$resp ";


$jsonResponse = json_decode($resp, TRUE);


$newID = FALSE;


if ( isset($jsonResponseid?) ) {

$newID = $jsonResponseid?;

}
else {

echo '<div class="mcm-errors">An error occurred. Error Code: '.htmlentities($jsonResponsecode?).

' Error Message: '.htmlentities($jsonResponsemessage?).' </div>';

var_dump($resp);

}


return $newID;


}

#3 @rafiahmedd
2 years ago

@mcmwebsol use Bacis Authentication, if you are using WordPress then I will suggest you to use wp_remote_post() for post.

#4 @mcmwebsol
2 years ago

I switched to using wp_remote_post() using basic auth, changed the active theme to Twenty Twenty-Two, and deactivated all plugins but still the status will not change. It's possible it has something to do with the WP Engine hosting environment though.

Also, there's nothing in the error log.

PHP code is below:
<?php
/ Loads the WordPress Environment and Template */
require('./wp-config.php');

$siteURL = 'https://subdomain.wpengine.com';
$url = $siteURL.'/wp-json/wp/v2/posts/3302';
$data = array(

'status' => 'publish'

);
$username = 'user';
$password = 'pass';

$args = array(

'method' => 'POST',
'timeout' => 45,
'headers' => array(

'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),
'Content-Type: multipart/form-data'

),

'body' => json_encode($data)

);

$resp = wp_remote_post($url, $args);
if ( is_wp_error( $resp ) )

print " Error: ".$resp->get_error_message();

else

print_r($resp);

?>

Site health status report is below:

`
### wp-core ###

version: 5.9
site_language: en_US
user_language: en_US
timezone: America/Chicago
permalink: /%postname%/
https_status: true
multisite: false
user_registration: 0
blog_public: 0
default_comment_status: open
environment_type: production
user_count: 22
dotorg_communication: true

### wp-paths-sizes ###

wordpress_path: /nas/content/live/sitehere
wordpress_size: 146.27 MB (153377539 bytes)
uploads_path: /nas/content/live/sitehere/wp-content/uploads
uploads_size: 1.81 GB (1940542861 bytes)
themes_path: /nas/content/live/sitehere/wp-content/themes
themes_size: 12.66 MB (13270757 bytes)
plugins_path: /nas/content/live/sitehere/wp-content/plugins
plugins_size: 221.73 MB (232501723 bytes)
database_size: 64.22 MB (67338240 bytes)
total_size: 2.24 GB (2407031120 bytes)

### wp-dropins (2) ###

advanced-cache.php: true
object-cache.php: true

### wp-active-theme ###

name: Twenty Twenty-Two (twentytwentytwo)
version: 1.0
author: the WordPress team
author_website: https://wordpress.org/
parent_theme: none
theme_features: core-block-patterns, post-thumbnails, responsive-embeds, editor-styles, html5, automatic-feed-links, block-templates, widgets-block-editor, wp-block-styles, editor-style
theme_path: /nas/content/live/sitehere/wp-content/themes/twentytwentytwo
auto_update: Disabled

### wp-themes-inactive (4) ###
SCRUBBED

### wp-mu-plugins (6) ###

Force Strong Passwords - WPE Edition: version: 1.8.0, author: Jason Cosper
WPE ElasticPress Autosuggest Logger: version: 1.0.0, author: WP Engine
WP Engine Cache Plugin: version: 1.0.5, author: WP Engine
WP Engine Seamless Login Plugin: version: 1.5.5, author: WP Engine
WP Engine Security Auditor: version: 1.0.10, author: wpengine
WP Engine System: version: 5.0.1, author: WP Engine

### wp-plugins-inactive (47) ###
SCRUBBED

### wp-media ###

image_editor: WP_Image_Editor_Imagick
imagick_module_version: 1687
imagemagick_version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org
imagick_version: 3.5.1
file_uploads: File uploads is turned off
post_max_size: 100M
upload_max_filesize: 50M
max_effective_size: 50 MB
max_file_uploads: 20
imagick_limits:

imagick::RESOURCETYPE_AREA: 137 MB
imagick::RESOURCETYPE_DISK: 1073741824
imagick::RESOURCETYPE_FILE: 6144
imagick::RESOURCETYPE_MAP: 512 MB
imagick::RESOURCETYPE_MEMORY: 256 MB
imagick::RESOURCETYPE_THREAD: 1

imagemagick_file_formats: 3FR, AAI, AI, ART, ARW, AVI, AVS, BGR, BGRA, BGRO, BIE, BMP, BMP2, BMP3, BRF, CAL, CALS, CANVAS, CAPTION, CIN, CIP, CLIP, CMYK, CMYKA, CR2, CRW, CUR, CUT, DATA, DCM, DCR, DCX, DDS, DFONT, DJVU, DNG, DOT, DPX, DXT1, DXT5, EPDF, EPI, EPS, EPS2, EPS3, EPSF, EPSI, EPT, EPT2, EPT3, ERF, EXR, FAX, FILE, FITS, FRACTAL, FTP, FTS, G3, G4, GIF, GIF87, GRADIENT, GRAY, GROUP4, GV, H, HALD, HDR, HISTOGRAM, HRZ, HTM, HTML, HTTP, HTTPS, ICB, ICO, ICON, IIQ, INFO, INLINE, IPL, ISOBRL, ISOBRL6, JBG, JBIG, JNG, JNX, JPE, JPEG, JPG, JPS, JSON, K25, KDC, LABEL, M2V, M4V, MAC, MAGICK, MAP, MASK, MAT, MATTE, MEF, MIFF, MKV, MNG, MONO, MOV, MP4, MPC, MPEG, MPG, MRW, MSL, MSVG, MTV, MVG, NEF, NRW, NULL, ORF, OTB, OTF, PAL, PALM, PAM, PANGO, PATTERN, PBM, PCD, PCDS, PCL, PCT, PCX, PDB, PDF, PDFA, PEF, PES, PFA, PFB, PFM, PGM, PICON, PICT, PIX, PJPEG, PLASMA, PNG, PNG00, PNG24, PNG32, PNG48, PNG64, PNG8, PNM, PPM, PREVIEW, PS, PS2, PS3, PSB, PSD, PTIF, PWP, RADIAL-GRADIENT, RAF, RAS, RAW, RGB, RGBA, RGBO, RGF, RLA, RLE, RMF, RW2, SCR, SCT, SFW, SGI, SHTML, SIX, SIXEL, SPARSE-COLOR, SR2, SRF, STEGANO, SUN, SVG, SVGZ, TEXT, TGA, THUMBNAIL, TIFF, TIFF64, TILE, TIM, TTC, TTF, TXT, UBRL, UBRL6, UIL, UYVY, VDA, VICAR, VID, VIFF, VIPS, VST, WBMP, WMF, WMV, WMZ, WPG, X, X3F, XBM, XC, XCF, XPM, XPS, XV, XWD, YCbCr, YCbCrA, YUV
gd_version: 2.2.5
gd_formats: GIF, JPEG, PNG, WebP, BMP, XPM
ghostscript_version: unknown

### wp-server ###

server_architecture: Linux 5.4.0-1052-gcp x86_64
httpd_software: Apache
php_version: 7.4.26 64bit
php_sapi: apache2handler
max_input_variables: 10000
time_limit: 3600
memory_limit: 512M
max_input_time: 3600
upload_max_filesize: 50M
php_post_max_size: 100M
curl_version: 7.58.0 OpenSSL/1.1.1
suhosin: false
imagick_availability: true
pretty_permalinks: true
htaccess_extra_rules: false

### wp-database ###

extension: mysqli
server_version: 5.7.36-39-log
client_version: mysqlnd 7.4.26
max_allowed_packet: 16777216
max_connections: 500

### wp-constants ###

WP_HOME: undefined
WP_SITEURL: undefined
WP_CONTENT_DIR: /nas/content/live/sitehere/wp-content
WP_PLUGIN_DIR: /nas/content/live/sitehere/wp-content/plugins
WP_MEMORY_LIMIT: 40M
WP_MAX_MEMORY_LIMIT: 512M
WP_DEBUG: false
WP_DEBUG_DISPLAY: true
WP_DEBUG_LOG: false
SCRIPT_DEBUG: false
WP_CACHE: true
CONCATENATE_SCRIPTS: undefined
COMPRESS_SCRIPTS: undefined
COMPRESS_CSS: undefined
WP_ENVIRONMENT_TYPE: Undefined
DB_CHARSET: utf8
DB_COLLATE: utf8_unicode_ci

### wp-filesystem ###

wordpress: writable
wp-content: writable
uploads: writable
plugins: writable
themes: writable
mu-plugins: writable

`

#5 @rafiahmedd
2 years ago

You can follow this one:-

<?php
$api_response = wp_remote_post( 'https://WEBSITE/wp-json/wp/v2/posts/{POST_ID}/', array(
        'headers' => array(
                'Authorization' => 'Basic ' . base64_encode( 'LOGIN:PASSWORD' )
        ),
        'body' => array(
                'status' => 'publish'
        )
) );


if( wp_remote_retrieve_response_message( $api_response ) === 'OK' ) {
        echo 'The post has been updated successfully';
}

#6 @mcmwebsol
2 years ago

I tried that. It does result in 'The post has been updated successfully' but still doesn't set the status to 'publish'. I also tried it on another host, so it must not be an issue with WP Engine hosting.

#7 @TimothyBlynJacobs
2 years ago

  • Keywords reporter-feedback added
  • Version changed from 5.9 to 4.7

Welcome to trac, and thanks for the ticket @mcmwebsol!

The reason you are seeing this behavior is that wp_insert_post requires a publish date that is within a minute of the current time when publishing a post. Otherwise, the post_status is forced to be future.

So when you update the post to publish make sure to also pass a new date that is set to the current time.

The REST API could automatically set the date to now when passing a status of publish. That would be inserting magic into the REST API controller that bypasses the safe guards in wp_insert_post, so I'm not sure we'd want to introduce that behavior. Thoughts @spacedmonkey?

Here is sample code that you can execute with WP-CLI to see that behavior in action.

<?php
$request = new WP_REST_Request( 'POST', '/wp/v2/posts' );
$request->set_body_params( [
        'status'   => 'future',
        'date_gmt' => gmdate( 'Y-m-d\TH:i:s', strtotime( 'tomorrow' ) ),
        'title'    => 'Test Post',
        'content'  => 'Test Content',
] );
$response = rest_do_request( $request );

if ( is_wp_error( $response ) ) {
        wp_die( $response );
}

$request = new WP_REST_Request( 'PUT', '/wp/v2/posts/' . $response->get_data()['id'] );
$request->set_body_params( [ 'status' => 'publish', 'date_gmt' => gmdate( 'Y-m-d\TH:i:s' ) ] );

$response = rest_do_request( $request );

if ( is_wp_error( $response ) ) {
        wp_die( $response );
}

echo $response->get_data()['status'] . PHP_EOL;
echo $response->get_data()['date'] . PHP_EOL;

#8 @mcmwebsol
2 years ago

Okay, that explains it, thanks!

#9 @TimothyBlynJacobs
2 years ago

  • Milestone Awaiting Review deleted
  • Resolution set to worksforme
  • Status changed from new to closed

No problem! I'm going to close this out.

Note: See TracTickets for help on using tickets.