Commit 1ca43d9e authored by lucha's avatar lucha

Wordpress 4.7.2

parent 264d0fb8
......@@ -44,7 +44,10 @@ include( ABSPATH . 'wp-admin/admin-header.php' );
</h2>
<div class="changelog point-releases">
<h3><?php _e( 'Maintenance and Security Release' ); ?></h3>
<h3><?php _e( 'Maintenance and Security Releases' ); ?></h3>
<p><?php printf( __( '<strong>Version %s</strong> addressed some security issues.' ), '4.7.2' ); ?>
<?php printf( __( 'For more information, see <a href="%s">the release notes</a>.' ), 'https://codex.wordpress.org/Version_4.7.2' ); ?>
</p>
<p><?php printf( _n( '<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bug.',
'<strong>Version %1$s</strong> addressed some security issues and fixed %2$s bugs.', 62 ), '4.7.1', number_format_i18n( 62 ) ); ?>
<?php printf( __( 'For more information, see <a href="%s">the release notes</a>.' ), 'https://codex.wordpress.org/Version_4.7.1' ); ?>
......
......@@ -955,7 +955,7 @@ class WP_Posts_List_Table extends WP_List_Table {
echo "</strong>\n";
if ( ! is_post_type_hierarchical( $this->screen->post_type ) && 'excerpt' === $mode && current_user_can( 'read_post', $post->ID ) ) {
the_excerpt();
echo esc_html( get_the_excerpt() );
}
get_inline_data( $post );
......
......@@ -119,10 +119,28 @@ class WP_Press_This {
'post_type' => 'post',
'post_status' => 'draft',
'post_format' => ( ! empty( $_POST['post_format'] ) ) ? sanitize_text_field( $_POST['post_format'] ) : '',
'tax_input' => ( ! empty( $_POST['tax_input'] ) ) ? $_POST['tax_input'] : array(),
'post_category' => ( ! empty( $_POST['post_category'] ) ) ? $_POST['post_category'] : array(),
);
// Only accept categories if the user actually can assign
$category_tax = get_taxonomy( 'category' );
if ( current_user_can( $category_tax->cap->assign_terms ) ) {
$post_data['post_category'] = ( ! empty( $_POST['post_category'] ) ) ? $_POST['post_category'] : array();
}
// Only accept taxonomies if the user can actually assign
if ( ! empty( $_POST['tax_input'] ) ) {
$tax_input = $_POST['tax_input'];
foreach ( $tax_input as $tax => $_ti ) {
$tax_object = get_taxonomy( $tax );
if ( ! $tax_object || ! current_user_can( $tax_object->cap->assign_terms ) ) {
unset( $tax_input[ $tax ] );
}
}
$post_data['tax_input'] = $tax_input;
}
// Toggle status to pending if user cannot actually publish
if ( ! empty( $_POST['post_status'] ) && 'publish' === $_POST['post_status'] ) {
if ( current_user_can( 'publish_posts' ) ) {
$post_data['post_status'] = 'publish';
......@@ -453,7 +471,7 @@ class WP_Press_This {
* @since 4.2.0
*
* @param string $src Embed source URL.
* @return string If not from a supported provider, an empty string. Otherwise, a reformattd embed URL.
* @return string If not from a supported provider, an empty string. Otherwise, a reformatted embed URL.
*/
private function _limit_embed( $src ) {
$src = $this->_limit_url( $src );
......@@ -853,6 +871,12 @@ class WP_Press_This {
public function categories_html( $post ) {
$taxonomy = get_taxonomy( 'category' );
// Bail if user cannot assign terms
if ( ! current_user_can( $taxonomy->cap->assign_terms ) ) {
return;
}
// Only show "add" if user can edit terms
if ( current_user_can( $taxonomy->cap->edit_terms ) ) {
?>
<button type="button" class="add-cat-toggle button-link" aria-expanded="false">
......@@ -1272,6 +1296,12 @@ class WP_Press_This {
wp_enqueue_script( 'json2' );
wp_enqueue_script( 'editor' );
$categories_tax = get_taxonomy( 'category' );
$show_categories = current_user_can( $categories_tax->cap->assign_terms ) || current_user_can( $categories_tax->cap->edit_terms );
$tag_tax = get_taxonomy( 'post_tag' );
$show_tags = current_user_can( $tag_tax->cap->assign_terms );
$supports_formats = false;
$post_format = 0;
......@@ -1423,17 +1453,21 @@ class WP_Press_This {
</button>
<?php endif; ?>
<button type="button" class="button-link post-option">
<span class="dashicons dashicons-category"></span>
<span class="post-option-title"><?php _e( 'Categories' ); ?></span>
<span class="dashicons post-option-forward"></span>
</button>
<button type="button" class="button-link post-option">
<span class="dashicons dashicons-tag"></span>
<span class="post-option-title"><?php _e( 'Tags' ); ?></span>
<span class="dashicons post-option-forward"></span>
</button>
<?php if ( $show_categories ) : ?>
<button type="button" class="button-link post-option">
<span class="dashicons dashicons-category"></span>
<span class="post-option-title"><?php _e( 'Categories' ); ?></span>
<span class="dashicons post-option-forward"></span>
</button>
<?php endif; ?>
<?php if ( $show_tags ) : ?>
<button type="button" class="button-link post-option">
<span class="dashicons dashicons-tag"></span>
<span class="post-option-title"><?php _e( 'Tags' ); ?></span>
<span class="dashicons post-option-forward"></span>
</button>
<?php endif; ?>
</div>
<?php if ( $supports_formats ) : ?>
......@@ -1447,23 +1481,27 @@ class WP_Press_This {
</div>
<?php endif; ?>
<div class="setting-modal is-off-screen is-hidden">
<button type="button" class="button-link modal-close">
<span class="dashicons post-option-back"></span>
<span class="setting-title" aria-hidden="true"><?php _e( 'Categories' ); ?></span>
<span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
</button>
<?php $this->categories_html( $post ); ?>
</div>
<?php if ( $show_categories ) : ?>
<div class="setting-modal is-off-screen is-hidden">
<button type="button" class="button-link modal-close">
<span class="dashicons post-option-back"></span>
<span class="setting-title" aria-hidden="true"><?php _e( 'Categories' ); ?></span>
<span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
</button>
<?php $this->categories_html( $post ); ?>
</div>
<?php endif; ?>
<div class="setting-modal tags is-off-screen is-hidden">
<button type="button" class="button-link modal-close">
<span class="dashicons post-option-back"></span>
<span class="setting-title" aria-hidden="true"><?php _e( 'Tags' ); ?></span>
<span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
</button>
<?php $this->tags_html( $post ); ?>
</div>
<?php if ( $show_tags ) : ?>
<div class="setting-modal tags is-off-screen is-hidden">
<button type="button" class="button-link modal-close">
<span class="dashicons post-option-back"></span>
<span class="setting-title" aria-hidden="true"><?php _e( 'Tags' ); ?></span>
<span class="screen-reader-text"><?php _e( 'Back to post options' ) ?></span>
</button>
<?php $this->tags_html( $post ); ?>
</div>
<?php endif; ?>
</div><!-- .options-panel -->
</div><!-- .wrapper -->
......
......@@ -191,12 +191,11 @@ final class WP_Comment {
public static function get_instance( $id ) {
global $wpdb;
if ( ! is_numeric( $id ) || $id != floor( $id ) || ! $id ) {
$comment_id = (int) $id;
if ( ! $comment_id ) {
return false;
}
$comment_id = (int) $id;
$_comment = wp_cache_get( $comment_id, 'comment' );
if ( ! $_comment ) {
......
......@@ -210,12 +210,11 @@ final class WP_Post {
public static function get_instance( $post_id ) {
global $wpdb;
if ( ! is_numeric( $post_id ) || $post_id != floor( $post_id ) || ! $post_id ) {
$post_id = (int) $post_id;
if ( ! $post_id ) {
return false;
}
$post_id = (int) $post_id;
$_post = wp_cache_get( $post_id, 'posts' );
if ( ! $_post ) {
......
......@@ -2255,12 +2255,12 @@ class WP_Query {
if ( empty( $in_search_post_types ) ) {
$where .= ' AND 1=0 ';
} else {
$where .= " AND {$wpdb->posts}.post_type IN ('" . join("', '", $in_search_post_types ) . "')";
$where .= " AND {$wpdb->posts}.post_type IN ('" . join( "', '", array_map( 'esc_sql', $in_search_post_types ) ) . "')";
}
} elseif ( !empty( $post_type ) && is_array( $post_type ) ) {
$where .= " AND {$wpdb->posts}.post_type IN ('" . join("', '", $post_type) . "')";
$where .= " AND {$wpdb->posts}.post_type IN ('" . join("', '", esc_sql( $post_type ) ) . "')";
} elseif ( ! empty( $post_type ) ) {
$where .= " AND {$wpdb->posts}.post_type = '$post_type'";
$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_type = %s", $post_type );
$post_type_object = get_post_type_object ( $post_type );
} elseif ( $this->is_attachment ) {
$where .= " AND {$wpdb->posts}.post_type = 'attachment'";
......
......@@ -125,12 +125,11 @@ final class WP_Term {
public static function get_instance( $term_id, $taxonomy = null ) {
global $wpdb;
if ( ! is_numeric( $term_id ) || $term_id != floor( $term_id ) || ! $term_id ) {
$term_id = (int) $term_id;
if ( ! $term_id ) {
return false;
}
$term_id = (int) $term_id;
$_term = wp_cache_get( $term_id, 'terms' );
// If there isn't a cached version, hit the database.
......
......@@ -46,6 +46,13 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
return false;
}
if ( isset( $args['args'] ) ) {
$common_args = $args['args'];
unset( $args['args'] );
} else {
$common_args = array();
}
if ( isset( $args['callback'] ) ) {
// Upgrade a single set to multiple.
$args = array( $args );
......@@ -57,12 +64,13 @@ function register_rest_route( $namespace, $route, $args = array(), $override = f
'args' => array(),
);
foreach ( $args as $key => &$arg_group ) {
if ( ! is_numeric( $arg_group ) ) {
if ( ! is_numeric( $key ) ) {
// Route option, skip here.
continue;
}
$arg_group = array_merge( $defaults, $arg_group );
$arg_group['args'] = array_merge( $common_args, $arg_group['args'] );
}
$full_route = '/' . trim( $namespace, '/' ) . '/' . trim( $route, '/' );
......
......@@ -63,6 +63,12 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
) );
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
'args' => array(
'id' => array(
'description' => __( 'Unique identifier for the object.' ),
'type' => 'integer',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
......@@ -299,6 +305,36 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
return $response;
}
/**
* Get the comment, if the ID is valid.
*
* @since 4.7.2
*
* @param int $id Supplied ID.
* @return WP_Comment|WP_Error Comment object if ID is valid, WP_Error otherwise.
*/
protected function get_comment( $id ) {
$error = new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
if ( (int) $id <= 0 ) {
return $error;
}
$id = (int) $id;
$comment = get_comment( $id );
if ( empty( $comment ) ) {
return $error;
}
if ( ! empty( $comment->comment_post_ID ) ) {
$post = get_post( (int) $comment->comment_post_ID );
if ( empty( $post ) ) {
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
}
}
return $comment;
}
/**
* Checks if a given request has access to read the comment.
*
......@@ -309,12 +345,9 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return WP_Error|bool True if the request has read access for the item, error object otherwise.
*/
public function get_item_permissions_check( $request ) {
$id = (int) $request['id'];
$comment = get_comment( $id );
if ( ! $comment ) {
return true;
$comment = $this->get_comment( $request['id'] );
if ( is_wp_error( $comment ) ) {
return $comment;
}
if ( ! empty( $request['context'] ) && 'edit' === $request['context'] && ! current_user_can( 'moderate_comments' ) ) {
......@@ -344,18 +377,9 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
*/
public function get_item( $request ) {
$id = (int) $request['id'];
$comment = get_comment( $id );
if ( empty( $comment ) ) {
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
}
if ( ! empty( $comment->comment_post_ID ) ) {
$post = get_post( $comment->comment_post_ID );
if ( empty( $post ) ) {
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
}
$comment = $this->get_comment( $request['id'] );
if ( is_wp_error( $comment ) ) {
return $comment;
}
$data = $this->prepare_item_for_response( $comment, $request );
......@@ -624,12 +648,12 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return WP_Error|bool True if the request has access to update the item, error object otherwise.
*/
public function update_item_permissions_check( $request ) {
$comment = $this->get_comment( $request['id'] );
if ( is_wp_error( $comment ) ) {
return $comment;
}
$id = (int) $request['id'];
$comment = get_comment( $id );
if ( $comment && ! $this->check_edit_permission( $comment ) ) {
if ( ! $this->check_edit_permission( $comment ) ) {
return new WP_Error( 'rest_cannot_edit', __( 'Sorry, you are not allowed to edit this comment.' ), array( 'status' => rest_authorization_required_code() ) );
}
......@@ -646,14 +670,13 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
*/
public function update_item( $request ) {
$id = (int) $request['id'];
$comment = get_comment( $id );
if ( empty( $comment ) ) {
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
$comment = $this->get_comment( $request['id'] );
if ( is_wp_error( $comment ) ) {
return $comment;
}
$id = $comment->comment_ID;
if ( isset( $request['type'] ) && get_comment_type( $id ) !== $request['type'] ) {
return new WP_Error( 'rest_comment_invalid_type', __( 'Sorry, you are not allowed to change the comment type.' ), array( 'status' => 404 ) );
}
......@@ -744,11 +767,9 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return WP_Error|bool True if the request has access to delete the item, error object otherwise.
*/
public function delete_item_permissions_check( $request ) {
$id = (int) $request['id'];
$comment = get_comment( $id );
if ( ! $comment ) {
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
$comment = $this->get_comment( $request['id'] );
if ( is_wp_error( $comment ) ) {
return $comment;
}
if ( ! $this->check_edit_permission( $comment ) ) {
......@@ -767,15 +788,13 @@ class WP_REST_Comments_Controller extends WP_REST_Controller {
* @return WP_Error|WP_REST_Response Response object on success, or error object on failure.
*/
public function delete_item( $request ) {
$id = (int) $request['id'];
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
$comment = get_comment( $id );
if ( empty( $comment ) ) {
return new WP_Error( 'rest_comment_invalid_id', __( 'Invalid comment ID.' ), array( 'status' => 404 ) );
$comment = $this->get_comment( $request['id'] );
if ( is_wp_error( $comment ) ) {
return $comment;
}
$force = isset( $request['force'] ) ? (bool) $request['force'] : false;
/**
* Filters whether a comment can be trashed.
*
......
......@@ -48,6 +48,12 @@ class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
) );
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<status>[\w-]+)', array(
'args' => array(
'status' => array(
'description' => __( 'An alphanumeric identifier for the status.' ),
'type' => 'string',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
......
......@@ -48,6 +48,12 @@ class WP_REST_Post_Types_Controller extends WP_REST_Controller {
) );
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<type>[\w-]+)', array(
'args' => array(
'type' => array(
'description' => __( 'An alphanumeric identifier for the post type.' ),
'type' => 'string',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
......
......@@ -88,6 +88,12 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
);
}
register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
'args' => array(
'id' => array(
'description' => __( 'Unique identifier for the object.' ),
'type' => 'integer',
),
),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_item' ),
......@@ -349,6 +355,28 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
return $response;
}
/**
* Get the post, if the ID is valid.
*
* @since 4.7.2
*
* @param int $id Supplied ID.
* @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
*/
protected function get_post( $id ) {
$error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
if ( (int) $id <= 0 ) {
return $error;
}
$post = get_post( (int) $id );
if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
return $error;
}
return $post;
}
/**
* Checks if a given request has access to read a post.
*
......@@ -359,8 +387,10 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise.
*/
public function get_item_permissions_check( $request ) {
$post = get_post( (int) $request['id'] );
$post = $this->get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
if ( 'edit' === $request['context'] && $post && ! $this->check_update_permission( $post ) ) {
return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) );
......@@ -428,18 +458,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_item( $request ) {
$id = (int) $request['id'];
$post = get_post( $id );
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
$post = $this->get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
$data = $this->prepare_item_for_response( $post, $request );
$response = rest_ensure_response( $data );
if ( is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) {
$response->link_header( 'alternate', get_permalink( $id ), array( 'type' => 'text/html' ) );
$response->link_header( 'alternate', get_permalink( $post->ID ), array( 'type' => 'text/html' ) );
}
return $response;
......@@ -455,6 +483,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
*/
public function create_item_permissions_check( $request ) {
if ( ! empty( $request['id'] ) ) {
return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) );
}
$post_type = get_post_type_object( $this->post_type );
......@@ -591,8 +622,11 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
*/
public function update_item_permissions_check( $request ) {
$post = $this->get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
$post = get_post( $request['id'] );
$post_type = get_post_type_object( $this->post_type );
if ( $post && ! $this->check_update_permission( $post ) ) {
......@@ -624,11 +658,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function update_item( $request ) {
$id = (int) $request['id'];
$post = get_post( $id );
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
$valid_check = $this->get_post( $request['id'] );
if ( is_wp_error( $valid_check ) ) {
return $valid_check;
}
$post = $this->prepare_item_for_database( $request );
......@@ -714,8 +746,10 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
*/
public function delete_item_permissions_check( $request ) {
$post = get_post( $request['id'] );
$post = $this->get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
if ( $post && ! $this->check_delete_permission( $post ) ) {
return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this post.' ), array( 'status' => rest_authorization_required_code() ) );
......@@ -734,15 +768,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function delete_item( $request ) {
$id = (int) $request['id'];
$force = (bool) $request['force'];
$post = get_post( $id );
if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
$post = $this->get_post( $request['id'] );
if ( is_wp_error( $post ) ) {
return $post;
}
$id = $post->ID;