← All changes
|
json-endpoints/class.wpcom-json-api-update-post-v1-1-endpoint.php
+45
-31
12.0.3
→
16.3-a.1
View file →
| @@ -8,8 +8,12 @@ | ||
| 8 | 8 | * Delete a post: /sites/%s/posts/%d/delete |
| 9 | 9 | * Restore a post: /sites/%s/posts/%d/restore |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | +if ( ! defined( 'ABSPATH' ) ) { | |
| 13 | + exit( 0 ); | |
| 14 | +} | |
| 15 | + | |
| 12 | 16 | new WPCOM_JSON_API_Update_Post_v1_1_Endpoint( |
| 13 | 17 | array( |
| 14 | 18 | 'description' => 'Create a post.', |
| 15 | 19 | 'group' => 'posts', |
| @@ -204,8 +208,10 @@ | ||
| 204 | 208 | |
| 205 | 209 | // phpcs:disable PEAR.NamingConventions.ValidClassName.Invalid |
| 206 | 210 | /** |
| 207 | 211 | * Update post v1.1 endpoint class. |
| 212 | + * | |
| 213 | + * @phan-constructor-used-for-side-effects | |
| 208 | 214 | */ |
| 209 | 215 | class WPCOM_JSON_API_Update_Post_v1_1_Endpoint extends WPCOM_JSON_API_Post_v1_1_Endpoint { |
| 210 | 216 | /** |
| 211 | 217 | * WPCOM_JSON_API_Update_Post_v1_1_Endpoint constructor. |
| @@ -258,8 +264,11 @@ | ||
| 258 | 264 | * @param int $blog_id Blog ID. |
| 259 | 265 | * @param int $post_id Post ID. |
| 260 | 266 | */ |
| 261 | 267 | public function write_post( $path, $blog_id, $post_id ) { |
| 268 | + $delete_featured_image = null; | |
| 269 | + $media_results = array(); | |
| 270 | + $post = null; | |
| 262 | 271 | global $wpdb; |
| 263 | 272 | |
| 264 | 273 | $new = $this->api->ends_with( $path, '/new' ); |
| 265 | 274 | $args = $this->query_args(); |
| @@ -265,9 +274,9 @@ | ||
| 265 | 274 | $args = $this->query_args(); |
| 266 | 275 | |
| 267 | 276 | // unhook publicize, it's hooked again later -- without this, skipping services is impossible. |
| 268 | 277 | if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) { |
| 269 | - remove_action( 'save_post', array( $GLOBALS['publicize_ui']->publicize, 'async_publicize_post' ), 100, 2 ); | |
| 278 | + remove_action( 'save_post', array( $GLOBALS['publicize_ui']->publicize, 'async_publicize_post' ), 100 ); | |
| 270 | 279 | add_action( 'rest_api_inserted_post', array( $GLOBALS['publicize_ui']->publicize, 'async_publicize_post' ) ); |
| 271 | 280 | |
| 272 | 281 | if ( $this->should_load_theme_functions( $post_id ) ) { |
| 273 | 282 | $this->load_theme_functions(); |
| @@ -328,8 +337,13 @@ | ||
| 328 | 337 | if ( ! is_array( $input ) || ! $input ) { |
| 329 | 338 | return new WP_Error( 'invalid_input', 'Invalid request input', 400 ); |
| 330 | 339 | } |
| 331 | 340 | |
| 341 | + $post = get_post( $post_id ); | |
| 342 | + if ( ! $post || is_wp_error( $post ) ) { | |
| 343 | + return new WP_Error( 'unknown_post', 'Unknown post', 404 ); | |
| 344 | + } | |
| 345 | + | |
| 332 | 346 | if ( isset( $input['status'] ) && 'trash' === $input['status'] && ! current_user_can( 'delete_post', $post_id ) ) { |
| 333 | 347 | return new WP_Error( 'unauthorized', 'User cannot delete post', 403 ); |
| 334 | 348 | } |
| 335 | 349 | |
| @@ -337,14 +351,10 @@ | ||
| 337 | 351 | if ( isset( $input['status'] ) && 'future' === $input['status'] ) { |
| 338 | 352 | $input['status'] = 'publish'; |
| 339 | 353 | } |
| 340 | 354 | |
| 341 | - $post = get_post( $post_id ); | |
| 342 | 355 | $_post_type = ( ! empty( $input['type'] ) ) ? $input['type'] : $post->post_type; |
| 343 | 356 | $post_type = get_post_type_object( $_post_type ); |
| 344 | - if ( ! $post || is_wp_error( $post ) ) { | |
| 345 | - return new WP_Error( 'unknown_post', 'Unknown post', 404 ); | |
| 346 | - } | |
| 347 | 357 | |
| 348 | 358 | if ( ! current_user_can( 'edit_post', $post->ID ) ) { |
| 349 | 359 | return new WP_Error( 'unauthorized', 'User cannot edit post', 403 ); |
| 350 | 360 | } |
| @@ -360,9 +370,9 @@ | ||
| 360 | 370 | if ( ( isset( $input['status'] ) && 'publish' === $input['status'] ) && 'publish' !== $post->post_status && ! current_user_can( 'publish_post', $post->ID ) ) { |
| 361 | 371 | $input['status'] = 'pending'; |
| 362 | 372 | } |
| 363 | 373 | $last_status = $post->post_status; |
| 364 | - $new_status = isset( $input['status'] ) ? $input['status'] : $last_status; | |
| 374 | + $new_status = $input['status'] ?? $last_status; | |
| 365 | 375 | |
| 366 | 376 | // Make sure that drafts get the current date when transitioning to publish if not supplied in the post. |
| 367 | 377 | // Similarly, scheduled posts that are manually published before their scheduled date should have the date reset. |
| 368 | 378 | $date_in_past = ( strtotime( $post->post_date_gmt ) < time() ); |
| @@ -517,9 +527,10 @@ | ||
| 517 | 527 | $is_open = WPCOM_JSON_API::is_truthy( $discussion[ $discussion_open ] ); |
| 518 | 528 | $discussion[ $discussion_status ] = $is_open ? 'open' : 'closed'; |
| 519 | 529 | } |
| 520 | 530 | |
| 521 | - if ( in_array( $discussion[ $discussion_status ], array( 'open', 'closed' ), true ) ) { | |
| 531 | + if ( isset( $discussion[ $discussion_status ] ) && | |
| 532 | + in_array( $discussion[ $discussion_status ], array( 'open', 'closed' ), true ) ) { | |
| 522 | 533 | $insert[ $discussion_status ] = $discussion[ $discussion_status ]; |
| 523 | 534 | } |
| 524 | 535 | } |
| 525 | 536 | } |
| @@ -530,12 +541,12 @@ | ||
| 530 | 541 | $insert['menu_order'] = $input['menu_order']; |
| 531 | 542 | unset( $input['menu_order'] ); |
| 532 | 543 | } |
| 533 | 544 | |
| 534 | - $publicize = isset( $input['publicize'] ) ? $input['publicize'] : null; | |
| 545 | + $publicize = $input['publicize'] ?? null; | |
| 535 | 546 | unset( $input['publicize'] ); |
| 536 | 547 | |
| 537 | - $publicize_custom_message = isset( $input['publicize_message'] ) ? $input['publicize_message'] : null; | |
| 548 | + $publicize_custom_message = $input['publicize_message'] ?? null; | |
| 538 | 549 | unset( $input['publicize_message'] ); |
| 539 | 550 | |
| 540 | 551 | if ( isset( $input['featured_image'] ) ) { |
| 541 | 552 | $featured_image = trim( $input['featured_image'] ); |
| @@ -542,18 +553,18 @@ | ||
| 542 | 553 | $delete_featured_image = empty( $featured_image ); |
| 543 | 554 | unset( $input['featured_image'] ); |
| 544 | 555 | } |
| 545 | 556 | |
| 546 | - $metadata = isset( $input['metadata'] ) ? $input['metadata'] : null; | |
| 557 | + $metadata = $input['metadata'] ?? null; | |
| 547 | 558 | unset( $input['metadata'] ); |
| 548 | 559 | |
| 549 | - $likes = isset( $input['likes_enabled'] ) ? $input['likes_enabled'] : null; | |
| 560 | + $likes = $input['likes_enabled'] ?? null; | |
| 550 | 561 | unset( $input['likes_enabled'] ); |
| 551 | 562 | |
| 552 | - $sharing = isset( $input['sharing_enabled'] ) ? $input['sharing_enabled'] : null; | |
| 563 | + $sharing = $input['sharing_enabled'] ?? null; | |
| 553 | 564 | unset( $input['sharing_enabled'] ); |
| 554 | 565 | |
| 555 | - $sticky = isset( $input['sticky'] ) ? $input['sticky'] : null; | |
| 566 | + $sticky = $input['sticky'] ?? null; | |
| 556 | 567 | unset( $input['sticky'] ); |
| 557 | 568 | |
| 558 | 569 | foreach ( $input as $key => $value ) { |
| 559 | 570 | $insert[ "post_$key" ] = $value; |
| @@ -575,9 +586,9 @@ | ||
| 575 | 586 | $media_files = ! empty( $input['media'] ) ? $input['media'] : array(); |
| 576 | 587 | $media_urls = ! empty( $input['media_urls'] ) ? $input['media_urls'] : array(); |
| 577 | 588 | $media_attrs = ! empty( $input['media_attrs'] ) ? $input['media_attrs'] : array(); |
| 578 | 589 | $media_results = $this->handle_media_creation_v1_1( $media_files, $media_urls, $media_attrs ); |
| 579 | - $media_id_string = join( ',', array_filter( array_map( 'absint', $media_results['media_ids'] ) ) ); | |
| 590 | + $media_id_string = implode( ',', array_filter( array_map( 'absint', $media_results['media_ids'] ) ) ); | |
| 580 | 591 | } |
| 581 | 592 | |
| 582 | 593 | if ( $new ) { |
| 583 | 594 | if ( isset( $input['content'] ) && ! has_shortcode( $input['content'], 'gallery' ) && ( $has_media || $has_media_by_url ) ) { |
| @@ -691,9 +702,9 @@ | ||
| 691 | 702 | |
| 692 | 703 | // Set sharing status of the post. |
| 693 | 704 | if ( $new ) { |
| 694 | 705 | $sharing_enabled = isset( $sharing ) ? (bool) $sharing : true; |
| 695 | - if ( false === $sharing_enabled ) { | |
| 706 | + if ( ! $sharing_enabled ) { | |
| 696 | 707 | update_post_meta( $post_id, 'sharing_disabled', 1 ); |
| 697 | 708 | } |
| 698 | 709 | } elseif ( isset( $sharing ) && true === $sharing ) { |
| 699 | 710 | delete_post_meta( $post_id, 'sharing_disabled' ); |
| @@ -743,9 +754,9 @@ | ||
| 743 | 754 | foreach ( $service_connections as $service_connection ) { |
| 744 | 755 | update_post_meta( $post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $service_connection->unique_id, 1 ); |
| 745 | 756 | } |
| 746 | 757 | } |
| 747 | - } elseif ( is_array( $publicize ) && ( count( $publicize ) > 0 ) ) { | |
| 758 | + } elseif ( is_array( $publicize ) && ( $publicize !== array() ) ) { | |
| 748 | 759 | foreach ( $GLOBALS['publicize_ui']->publicize->get_services( 'all' ) as $name => $service ) { |
| 749 | 760 | /* |
| 750 | 761 | * We support both indexed and associative arrays: |
| 751 | 762 | * * indexed are to pass entire services |
| @@ -752,14 +763,14 @@ | ||
| 752 | 763 | * * associative are to pass specific connections per service |
| 753 | 764 | * |
| 754 | 765 | * We do support mixed arrays: mixed integer and string keys (see 3rd example below). |
| 755 | 766 | * |
| 756 | - * EG: array( 'twitter', 'facebook') will only publicize to those, ignoring the other available services | |
| 757 | - * Form data: publicize[]=twitter&publicize[]=facebook | |
| 758 | - * EG: array( 'twitter' => '(int) $pub_conn_id_0, (int) $pub_conn_id_3', 'facebook' => (int) $pub_conn_id_7 ) will publicize to two Twitter accounts, and one Facebook connection, of potentially many. | |
| 759 | - * Form data: publicize[twitter]=$pub_conn_id_0,$pub_conn_id_3&publicize[facebook]=$pub_conn_id_7 | |
| 760 | - * EG: array( 'twitter', 'facebook' => '(int) $pub_conn_id_0, (int) $pub_conn_id_3' ) will publicize to all available Twitter accounts, but only 2 of potentially many Facebook connections | |
| 761 | - * Form data: publicize[]=twitter&publicize[facebook]=$pub_conn_id_0,$pub_conn_id_3 | |
| 767 | + * EG: array( 'linkedin', 'facebook') will only publicize to those, ignoring the other available services | |
| 768 | + * Form data: publicize[]=linkedin&publicize[]=facebook | |
| 769 | + * EG: array( 'linkedin' => '(int) $pub_conn_id_0, (int) $pub_conn_id_3', 'facebook' => (int) $pub_conn_id_7 ) will publicize to two LinkedIn accounts, and one Facebook connection, of potentially many. | |
| 770 | + * Form data: publicize[linkedin]=$pub_conn_id_0,$pub_conn_id_3&publicize[facebook]=$pub_conn_id_7 | |
| 771 | + * EG: array( 'linkedin', 'facebook' => '(int) $pub_conn_id_0, (int) $pub_conn_id_3' ) will publicize to all available LinkedIn accounts, but only 2 of potentially many Facebook connections | |
| 772 | + * Form data: publicize[]=linkedin&publicize[facebook]=$pub_conn_id_0,$pub_conn_id_3 | |
| 762 | 773 | */ |
| 763 | 774 | |
| 764 | 775 | // Delete any stale SKIP value for the service by name. We'll add it back by ID. |
| 765 | 776 | delete_post_meta( $post_id, $GLOBALS['publicize_ui']->publicize->POST_SKIP . $name ); |
| @@ -824,9 +835,9 @@ | ||
| 824 | 835 | |
| 825 | 836 | $meta = (object) $meta; |
| 826 | 837 | |
| 827 | 838 | if ( |
| 828 | - in_array( $meta->key, Jetpack_SEO_Posts::POST_META_KEYS_ARRAY, true ) && | |
| 839 | + in_array( $meta->key ?? null, Jetpack_SEO_Posts::POST_META_KEYS_ARRAY, true ) && | |
| 829 | 840 | ! Jetpack_SEO_Utils::is_enabled_jetpack_seo() |
| 830 | 841 | ) { |
| 831 | 842 | return new WP_Error( 'unauthorized', __( 'SEO tools are not enabled for this site.', 'jetpack' ), 403 ); |
| 832 | 843 | } |
| @@ -854,12 +865,12 @@ | ||
| 854 | 865 | continue; |
| 855 | 866 | } |
| 856 | 867 | } |
| 857 | 868 | |
| 858 | - $unslashed_meta_key = wp_unslash( $meta->key ); // should match what the final key will be. | |
| 859 | - $meta->key = wp_slash( $meta->key ); | |
| 860 | - $unslashed_existing_meta_key = wp_unslash( $existing_meta_item->meta_key ); | |
| 861 | - $existing_meta_item->meta_key = wp_slash( $existing_meta_item->meta_key ); | |
| 869 | + $unslashed_meta_key = isset( $meta->key ) ? wp_unslash( $meta->key ) : null; // should match what the final key will be. | |
| 870 | + $meta->key = isset( $meta->key ) ? wp_slash( $meta->key ) : null; | |
| 871 | + $unslashed_existing_meta_key = isset( $existing_meta_item->meta_key ) ? wp_unslash( $existing_meta_item->meta_key ) : null; | |
| 872 | + $existing_meta_item->meta_key = isset( $existing_meta_item->meta_key ) ? wp_slash( $existing_meta_item->meta_key ) : null; | |
| 862 | 873 | |
| 863 | 874 | // make sure that the meta id passed matches the existing meta key. |
| 864 | 875 | if ( ! empty( $meta->id ) && ! empty( $meta->key ) ) { |
| 865 | 876 | $meta_by_id = get_metadata_by_mid( 'post', $meta->id ); |
| @@ -923,11 +934,13 @@ | ||
| 923 | 934 | if ( ! empty( $media_results['errors'] ) ) { |
| 924 | 935 | $return['media_errors'] = $media_results['errors']; |
| 925 | 936 | } |
| 926 | 937 | |
| 927 | - if ( 'publish' !== $post->post_status ) { | |
| 938 | + // Generate suggestions for new posts or non-published posts | |
| 939 | + if ( $new || ( isset( $return['status'] ) && 'publish' !== $return['status'] ) ) { | |
| 928 | 940 | $sal_site = $this->get_sal_post_by( 'ID', $post_id, $args['context'] ); |
| 929 | - $return['other_URLs'] = (object) $sal_site->get_permalink_suggestions( $input['title'] ); | |
| 941 | + $title = $input['title'] ?? ''; | |
| 942 | + $return['other_URLs'] = (object) $sal_site->get_permalink_suggestions( $title ); | |
| 930 | 943 | } |
| 931 | 944 | |
| 932 | 945 | /** This action is documented in json-endpoints/class.wpcom-json-api-site-settings-endpoint.php */ |
| 933 | 946 | do_action( 'wpcom_json_api_objects', 'posts' ); |
| @@ -1102,9 +1115,10 @@ | ||
| 1102 | 1115 | protected function untrash_post( $post, $input ) { |
| 1103 | 1116 | wp_untrash_post( $post->ID ); |
| 1104 | 1117 | $untrashed_post = get_post( $post->ID ); |
| 1105 | 1118 | // Lets make sure that we use the reverted the slug. |
| 1106 | - if ( isset( $untrashed_post->post_name ) && $untrashed_post->post_name . '__trashed' === $input['slug'] ) { | |
| 1119 | + if ( isset( $input['slug'] ) && isset( $untrashed_post->post_name ) && | |
| 1120 | + $untrashed_post->post_name . '__trashed' === $input['slug'] ) { | |
| 1107 | 1121 | unset( $input['slug'] ); |
| 1108 | 1122 | } |
| 1109 | 1123 | return $input; |
| 1110 | 1124 | } |
| @@ -1118,9 +1132,9 @@ | ||
| 1118 | 1132 | */ |
| 1119 | 1133 | protected function should_load_theme_functions( $post_id = null ) { |
| 1120 | 1134 | if ( empty( $post_id ) ) { |
| 1121 | 1135 | $input = $this->input( true ); |
| 1122 | - $type = $input['type']; | |
| 1136 | + $type = $input['type'] ?? null; | |
| 1123 | 1137 | } else { |
| 1124 | 1138 | $type = get_post_type( $post_id ); |
| 1125 | 1139 | } |
| 1126 | 1140 | |