diff -r c7c34916027a -r 177826044cd9 wp/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php --- a/wp/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php Mon Oct 14 18:06:33 2019 +0200 +++ b/wp/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php Mon Oct 14 18:28:13 2019 +0200 @@ -75,7 +75,7 @@ // Attaching media to a post requires ability to edit said post. if ( ! empty( $request['post'] ) ) { - $parent = get_post( (int) $request['post'] ); + $parent = get_post( (int) $request['post'] ); $post_parent_type = get_post_type_object( $parent->post_type ); if ( ! current_user_can( $post_parent_type->cap->edit_post, $request['post'] ) ) { @@ -101,7 +101,7 @@ } // Get the file via $_FILES or raw data. - $files = $request->get_file_params(); + $files = $request->get_file_params(); $headers = $request->get_headers(); if ( ! empty( $files ) ) { @@ -114,13 +114,16 @@ return $file; } - $name = basename( $file['file'] ); + $name = wp_basename( $file['file'] ); $name_parts = pathinfo( $name ); - $name = trim( substr( $name, 0, -(1 + strlen( $name_parts['extension'] ) ) ) ); + $name = trim( substr( $name, 0, -( 1 + strlen( $name_parts['extension'] ) ) ) ); - $url = $file['url']; - $type = $file['type']; - $file = $file['file']; + $url = $file['url']; + $type = $file['type']; + $file = $file['file']; + + // Include image functions to get access to wp_read_image_metadata(). + require_once ABSPATH . 'wp-admin/includes/image.php'; // use image exif/iptc data for title and caption defaults if possible $image_meta = wp_read_image_metadata( $file ); @@ -135,12 +138,12 @@ } } - $attachment = $this->prepare_item_for_database( $request ); + $attachment = $this->prepare_item_for_database( $request ); $attachment->post_mime_type = $type; - $attachment->guid = $url; + $attachment->guid = $url; if ( empty( $attachment->post_title ) ) { - $attachment->post_title = preg_replace( '/\.[^.]+$/', '', basename( $file ) ); + $attachment->post_title = preg_replace( '/\.[^.]+$/', '', wp_basename( $file ) ); } // $post_parent is inherited from $attachment['post_parent']. @@ -169,8 +172,8 @@ */ do_action( 'rest_insert_attachment', $attachment, $request, true ); - // Include admin functions to get access to wp_generate_attachment_metadata(). - require_once ABSPATH . 'wp-admin/includes/admin.php'; + // Include admin function to get access to wp_generate_attachment_metadata(). + require_once ABSPATH . 'wp-admin/includes/media.php'; wp_update_attachment_metadata( $id, wp_generate_attachment_metadata( $id, $file ) ); @@ -185,6 +188,18 @@ } $request->set_param( 'context', 'edit' ); + + /** + * Fires after a single attachment is completely created or updated via the REST API. + * + * @since 5.0.0 + * + * @param WP_Post $attachment Inserted or updated attachment object. + * @param WP_REST_Request $request Request object. + * @param bool $creating True when creating an attachment, false when updating. + */ + do_action( 'rest_after_insert_attachment', $attachment, $request, true ); + $response = $this->prepare_item_for_response( $attachment, $request ); $response = rest_ensure_response( $response ); $response->set_status( 201 ); @@ -213,7 +228,7 @@ } $response = rest_ensure_response( $response ); - $data = $response->get_data(); + $data = $response->get_data(); if ( isset( $request['alt_text'] ) ) { update_post_meta( $data['id'], '_wp_attachment_image_alt', $request['alt_text'] ); @@ -221,9 +236,6 @@ $attachment = get_post( $request['id'] ); - /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */ - do_action( 'rest_insert_attachment', $data, $request, false ); - $fields_update = $this->update_additional_fields_for_object( $attachment, $request ); if ( is_wp_error( $fields_update ) ) { @@ -231,6 +243,10 @@ } $request->set_param( 'context', 'edit' ); + + /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */ + do_action( 'rest_after_insert_attachment', $attachment, $request, false ); + $response = $this->prepare_item_for_response( $attachment, $request ); $response = rest_ensure_response( $response ); @@ -372,7 +388,12 @@ // Wrap the data in a response object. $response = rest_ensure_response( $data ); - $response->add_links( $links ); + + foreach ( $links as $rel => $rel_links ) { + foreach ( $rel_links as $link ) { + $response->add_link( $rel, $link['href'], $link['attributes'] ); + } + } /** * Filters an attachment returned from the REST API. @@ -400,10 +421,10 @@ $schema = parent::get_item_schema(); $schema['properties']['alt_text'] = array( - 'description' => __( 'Alternative text to display when attachment is not displayed.' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - 'arg_options' => array( + 'description' => __( 'Alternative text to display when attachment is not displayed.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'arg_options' => array( 'sanitize_callback' => 'sanitize_text_field', ), ); @@ -417,7 +438,7 @@ 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database() ), 'properties' => array( - 'raw' => array( + 'raw' => array( 'description' => __( 'Caption for the attachment, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), @@ -440,7 +461,7 @@ 'validate_callback' => null, // Note: validation implemented in self::prepare_item_for_database() ), 'properties' => array( - 'raw' => array( + 'raw' => array( 'description' => __( 'Description for the object, as it exists in the database.' ), 'type' => 'string', 'context' => array( 'edit' ), @@ -455,39 +476,39 @@ ); $schema['properties']['media_type'] = array( - 'description' => __( 'Attachment type.' ), - 'type' => 'string', - 'enum' => array( 'image', 'file' ), - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, + 'description' => __( 'Attachment type.' ), + 'type' => 'string', + 'enum' => array( 'image', 'file' ), + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, ); $schema['properties']['mime_type'] = array( - 'description' => __( 'The attachment MIME type.' ), - 'type' => 'string', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, + 'description' => __( 'The attachment MIME type.' ), + 'type' => 'string', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, ); $schema['properties']['media_details'] = array( - 'description' => __( 'Details about the media file, specific to its type.' ), - 'type' => 'object', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, + 'description' => __( 'Details about the media file, specific to its type.' ), + 'type' => 'object', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, ); $schema['properties']['post'] = array( - 'description' => __( 'The ID for the associated post of the attachment.' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit' ), + 'description' => __( 'The ID for the associated post of the attachment.' ), + 'type' => 'integer', + 'context' => array( 'view', 'edit' ), ); $schema['properties']['source_url'] = array( - 'description' => __( 'URL to the original attachment file.' ), - 'type' => 'string', - 'format' => 'uri', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, + 'description' => __( 'URL to the original attachment file.' ), + 'type' => 'string', + 'format' => 'uri', + 'context' => array( 'view', 'edit', 'embed' ), + 'readonly' => true, ); unset( $schema['properties']['password'] ); @@ -536,8 +557,8 @@ // Get the content-type. $type = array_shift( $headers['content_type'] ); - /** Include admin functions to get access to wp_tempnam() and wp_handle_sideload() */ - require_once ABSPATH . 'wp-admin/includes/admin.php'; + /** Include admin functions to get access to wp_tempnam() and wp_handle_sideload(). */ + require_once ABSPATH . 'wp-admin/includes/file.php'; // Save the file. $tmpfname = wp_tempnam( $filename ); @@ -657,16 +678,16 @@ * @return array Query parameters for the attachment collection as an array. */ public function get_collection_params() { - $params = parent::get_collection_params(); - $params['status']['default'] = 'inherit'; + $params = parent::get_collection_params(); + $params['status']['default'] = 'inherit'; $params['status']['items']['enum'] = array( 'inherit', 'private', 'trash' ); - $media_types = $this->get_media_types(); + $media_types = $this->get_media_types(); $params['media_type'] = array( - 'default' => null, - 'description' => __( 'Limit result set to attachments of a particular media type.' ), - 'type' => 'string', - 'enum' => array_keys( $media_types ), + 'default' => null, + 'description' => __( 'Limit result set to attachments of a particular media type.' ), + 'type' => 'string', + 'enum' => array_keys( $media_types ), ); $params['mime_type'] = array( @@ -679,24 +700,6 @@ } /** - * Validates whether the user can query private statuses. - * - * @since 4.7.0 - * - * @param mixed $value Status value. - * @param WP_REST_Request $request Request object. - * @param string $parameter Additional parameter to pass for validation. - * @return WP_Error|bool True if the user may query, WP_Error if not. - */ - public function validate_user_can_query_private_statuses( $value, $request, $parameter ) { - if ( 'inherit' === $value ) { - return true; - } - - return parent::validate_user_can_query_private_statuses( $value, $request, $parameter ); - } - - /** * Handles an upload via multipart/form-data ($_FILES). * * @since 4.7.0 @@ -723,7 +726,7 @@ // Pass off to WP to handle the actual upload. $overrides = array( - 'test_form' => false, + 'test_form' => false, ); // Bypasses is_uploaded_file() when running unit tests. @@ -736,8 +739,8 @@ return $size_check; } - /** Include admin functions to get access to wp_handle_upload() */ - require_once ABSPATH . 'wp-admin/includes/admin.php'; + /** Include admin function to get access to wp_handle_upload(). */ + require_once ABSPATH . 'wp-admin/includes/file.php'; $file = wp_handle_upload( $files['file'], $overrides ); @@ -805,6 +808,9 @@ return new WP_Error( 'rest_upload_file_too_big', sprintf( __( 'This file is too big. Files must be less than %s KB in size.' ), get_site_option( 'fileupload_maxk', 1500 ) ), array( 'status' => 400 ) ); } + // Include admin function to get access to upload_is_user_over_quota(). + require_once ABSPATH . 'wp-admin/includes/ms.php'; + if ( upload_is_user_over_quota( false ) ) { return new WP_Error( 'rest_upload_user_quota_exceeded', __( 'You have used your space quota. Please delete files before uploading.' ), array( 'status' => 400 ) ); }