diff -r 3d4e9c994f10 -r a86126ab1dd4 wp/wp-admin/includes/ajax-actions.php --- a/wp/wp-admin/includes/ajax-actions.php Tue Oct 22 16:11:46 2019 +0200 +++ b/wp/wp-admin/includes/ajax-actions.php Tue Dec 15 13:49:49 2020 +0100 @@ -22,7 +22,7 @@ function wp_ajax_nopriv_heartbeat() { $response = array(); - // screen_id is the same as $current_screen->id and the JS global 'pagenow'. + // 'screen_id' is the same as $current_screen->id and the JS global 'pagenow'. if ( ! empty( $_POST['screen_id'] ) ) { $screen_id = sanitize_key( $_POST['screen_id'] ); } else { @@ -39,7 +39,7 @@ * * @param array $response The no-priv Heartbeat response. * @param array $data The $_POST data sent. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ $response = apply_filters( 'heartbeat_nopriv_received', $response, $data, $screen_id ); } @@ -50,7 +50,7 @@ * @since 3.6.0 * * @param array $response The no-priv Heartbeat response. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ $response = apply_filters( 'heartbeat_nopriv_send', $response, $screen_id ); @@ -62,7 +62,7 @@ * @since 3.6.0 * * @param array $response The no-priv Heartbeat response. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ do_action( 'heartbeat_nopriv_tick', $response, $screen_id ); @@ -111,6 +111,7 @@ $taxonomy = sanitize_key( $_GET['tax'] ); $tax = get_taxonomy( $taxonomy ); + if ( ! $tax ) { wp_die( 0 ); } @@ -125,10 +126,12 @@ if ( ',' !== $comma ) { $s = str_replace( $comma, ',', $s ); } + if ( false !== strpos( $s, ',' ) ) { $s = explode( ',', $s ); $s = $s[ count( $s ) - 1 ]; } + $s = trim( $s ); /** @@ -146,20 +149,20 @@ * Require $term_search_min_chars chars for matching (default: 2) * ensure it's a non-negative, non-zero integer. */ - if ( ( $term_search_min_chars == 0 ) || ( strlen( $s ) < $term_search_min_chars ) ) { + if ( ( 0 == $term_search_min_chars ) || ( strlen( $s ) < $term_search_min_chars ) ) { wp_die(); } $results = get_terms( - $taxonomy, array( + 'taxonomy' => $taxonomy, 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false, ) ); - echo join( $results, "\n" ); + echo join( "\n", $results ); wp_die(); } @@ -173,7 +176,7 @@ wp_die( -1 ); } - if ( ini_get( 'zlib.output_compression' ) || 'ob_gzhandler' == ini_get( 'output_handler' ) ) { + if ( ini_get( 'zlib.output_compression' ) || 'ob_gzhandler' === ini_get( 'output_handler' ) ) { update_site_option( 'can_compress_scripts', 0 ); wp_die( 0 ); } @@ -193,6 +196,7 @@ if ( ! isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) ) { wp_die( -1 ); } + if ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate' ) && function_exists( 'gzdeflate' ) && ! $force_gzip ) { header( 'Content-Encoding: deflate' ); $out = gzdeflate( $test_str, 1 ); @@ -202,12 +206,13 @@ } else { wp_die( -1 ); } + echo $out; wp_die(); - } elseif ( 'no' == $_GET['test'] ) { + } elseif ( 'no' === $_GET['test'] ) { check_ajax_referer( 'update_can_compress_scripts' ); update_site_option( 'can_compress_scripts', 0 ); - } elseif ( 'yes' == $_GET['test'] ) { + } elseif ( 'yes' === $_GET['test'] ) { check_ajax_referer( 'update_can_compress_scripts' ); update_site_option( 'can_compress_scripts', 1 ); } @@ -229,7 +234,8 @@ check_ajax_referer( "image_editor-$post_id" ); - include_once( ABSPATH . 'wp-admin/includes/image-edit.php' ); + include_once ABSPATH . 'wp-admin/includes/image-edit.php'; + if ( ! stream_preview_image( $post_id ) ) { wp_die( -1 ); } @@ -266,36 +272,37 @@ $return = array(); - // Check the type of request - // Current allowed values are `add` and `search` + // Check the type of request. + // Current allowed values are `add` and `search`. if ( isset( $_REQUEST['autocomplete_type'] ) && 'search' === $_REQUEST['autocomplete_type'] ) { $type = $_REQUEST['autocomplete_type']; } else { $type = 'add'; } - // Check the desired field for value - // Current allowed values are `user_email` and `user_login` + // Check the desired field for value. + // Current allowed values are `user_email` and `user_login`. if ( isset( $_REQUEST['autocomplete_field'] ) && 'user_email' === $_REQUEST['autocomplete_field'] ) { $field = $_REQUEST['autocomplete_field']; } else { $field = 'user_login'; } - // Exclude current users of this blog + // Exclude current users of this blog. if ( isset( $_REQUEST['site_id'] ) ) { $id = absint( $_REQUEST['site_id'] ); } else { $id = get_current_blog_id(); } - $include_blog_users = ( $type == 'search' ? get_users( + $include_blog_users = ( 'search' === $type ? get_users( array( 'blog_id' => $id, 'fields' => 'ID', ) ) : array() ); - $exclude_blog_users = ( $type == 'add' ? get_users( + + $exclude_blog_users = ( 'add' === $type ? get_users( array( 'blog_id' => $id, 'fields' => 'ID', @@ -314,7 +321,7 @@ foreach ( $users as $user ) { $return[] = array( - /* translators: 1: user_login, 2: user_email */ + /* translators: 1: User login, 2: User email address. */ 'label' => sprintf( _x( '%1$s (%2$s)', 'user autocomplete result' ), $user->user_login, $user->user_email ), 'value' => $user->$field, ); @@ -324,12 +331,12 @@ } /** - * Handles AJAX requests for community events + * Handles Ajax requests for community events * * @since 4.8.0 */ function wp_ajax_get_community_events() { - require_once( ABSPATH . 'wp-admin/includes/class-wp-community-events.php' ); + require_once ABSPATH . 'wp-admin/includes/class-wp-community-events.php'; check_ajax_referer( 'community_events' ); @@ -384,7 +391,7 @@ require_once ABSPATH . 'wp-admin/includes/dashboard.php'; $pagenow = $_GET['pagenow']; - if ( $pagenow === 'dashboard-user' || $pagenow === 'dashboard-network' || $pagenow === 'dashboard' ) { + if ( 'dashboard-user' === $pagenow || 'dashboard-network' === $pagenow || 'dashboard' === $pagenow ) { set_current_screen( $pagenow ); } @@ -414,8 +421,8 @@ * * Contrary to normal success Ajax response ("1"), die with time() on success. * + * @since 2.7.0 * @access private - * @since 2.7.0 * * @param int $comment_id * @param int $delta @@ -426,7 +433,7 @@ $page = isset( $_POST['_page'] ) ? (int) $_POST['_page'] : 0; $url = isset( $_POST['_url'] ) ? esc_url_raw( $_POST['_url'] ) : ''; - // JS didn't send us everything we need to know. Just die with success message + // JS didn't send us everything we need to know. Just die with success message. if ( ! $total || ! $per_page || ! $page || ! $url ) { $time = time(); $comment = get_comment( $comment_id ); @@ -454,12 +461,12 @@ 'time' => $time, 'in_moderation' => $counts->moderated, 'i18n_comments_text' => sprintf( - /* translators: %s: number of comments approved */ + /* translators: %s: Number of comments. */ _n( '%s Comment', '%s Comments', $counts->approved ), number_format_i18n( $counts->approved ) ), 'i18n_moderation_text' => sprintf( - /* translators: %s: number of comments in moderation */ + /* translators: %s: Number of comments. */ _n( '%s Comment in moderation', '%s Comments in moderation', $counts->moderated ), number_format_i18n( $counts->moderated ) ), @@ -475,20 +482,24 @@ $total = 0; } - // Only do the expensive stuff on a page-break, and about 1 other time per page + // Only do the expensive stuff on a page-break, and about 1 other time per page. if ( 0 == $total % $per_page || 1 == mt_rand( 1, $per_page ) ) { $post_id = 0; // What type of comment count are we looking for? $status = 'all'; $parsed = parse_url( $url ); + if ( isset( $parsed['query'] ) ) { parse_str( $parsed['query'], $query_vars ); + if ( ! empty( $query_vars['comment_status'] ) ) { $status = $query_vars['comment_status']; } + if ( ! empty( $query_vars['p'] ) ) { $post_id = (int) $query_vars['p']; } + if ( ! empty( $query_vars['comment_type'] ) ) { $type = $query_vars['comment_type']; } @@ -518,7 +529,7 @@ 'supplemental' => array( 'status' => $comment ? $comment->comment_approved : '', 'postId' => $comment ? $comment->comment_post_ID : '', - /* translators: %s: number of comments */ + /* translators: %s: Number of comments. */ 'total_items_i18n' => sprintf( _n( '%s item', '%s items', $total ), number_format_i18n( $total ) ), 'total_pages' => ceil( $total / $per_page ), 'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ), @@ -526,7 +537,7 @@ 'time' => $time, 'in_moderation' => $counts->moderated, 'i18n_moderation_text' => sprintf( - /* translators: %s: number of comments in moderation */ + /* translators: %s: Number of comments. */ _n( '%s Comment in moderation', '%s Comments in moderation', $counts->moderated ), number_format_i18n( $counts->moderated ) ), @@ -543,44 +554,53 @@ /** * Ajax handler for adding a hierarchical term. * + * @since 3.1.0 * @access private - * @since 3.1.0 */ function _wp_ajax_add_hierarchical_term() { $action = $_POST['action']; $taxonomy = get_taxonomy( substr( $action, 4 ) ); check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name ); + if ( ! current_user_can( $taxonomy->cap->edit_terms ) ) { wp_die( -1 ); } + $names = explode( ',', $_POST[ 'new' . $taxonomy->name ] ); $parent = isset( $_POST[ 'new' . $taxonomy->name . '_parent' ] ) ? (int) $_POST[ 'new' . $taxonomy->name . '_parent' ] : 0; + if ( 0 > $parent ) { $parent = 0; } - if ( $taxonomy->name == 'category' ) { + + if ( 'category' === $taxonomy->name ) { $post_category = isset( $_POST['post_category'] ) ? (array) $_POST['post_category'] : array(); } else { $post_category = ( isset( $_POST['tax_input'] ) && isset( $_POST['tax_input'][ $taxonomy->name ] ) ) ? (array) $_POST['tax_input'][ $taxonomy->name ] : array(); } + $checked_categories = array_map( 'absint', (array) $post_category ); $popular_ids = wp_popular_terms_checklist( $taxonomy->name, 0, 10, false ); foreach ( $names as $cat_name ) { $cat_name = trim( $cat_name ); $category_nicename = sanitize_title( $cat_name ); + if ( '' === $category_nicename ) { continue; } $cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) ); + if ( ! $cat_id || is_wp_error( $cat_id ) ) { continue; } else { $cat_id = $cat_id['term_id']; } + $checked_categories[] = $cat_id; - if ( $parent ) { // Do these all at once in a second + + if ( $parent ) { // Do these all at once in a second. continue; } @@ -606,11 +626,11 @@ ); } - if ( $parent ) { // Foncy - replace the parent and all its children + if ( $parent ) { // Foncy - replace the parent and all its children. $parent = get_term( $parent, $taxonomy->name ); $term_id = $parent->term_id; - while ( $parent->parent ) { // get the top parent + while ( $parent->parent ) { // Get the top parent. $parent = get_term( $parent->parent, $taxonomy->name ); if ( is_wp_error( $parent ) ) { break; @@ -669,41 +689,52 @@ function wp_ajax_delete_comment() { $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; - if ( ! $comment = get_comment( $id ) ) { + $comment = get_comment( $id ); + + if ( ! $comment ) { wp_die( time() ); } + if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) ) { wp_die( -1 ); } check_ajax_referer( "delete-comment_$id" ); $status = wp_get_comment_status( $comment ); - - $delta = -1; + $delta = -1; + if ( isset( $_POST['trash'] ) && 1 == $_POST['trash'] ) { - if ( 'trash' == $status ) { + if ( 'trash' === $status ) { wp_die( time() ); } + $r = wp_trash_comment( $comment ); } elseif ( isset( $_POST['untrash'] ) && 1 == $_POST['untrash'] ) { - if ( 'trash' != $status ) { + if ( 'trash' !== $status ) { wp_die( time() ); } + $r = wp_untrash_comment( $comment ); - if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'trash' ) { // undo trash, not in trash + + // Undo trash, not in Trash. + if ( ! isset( $_POST['comment_status'] ) || 'trash' !== $_POST['comment_status'] ) { $delta = 1; } } elseif ( isset( $_POST['spam'] ) && 1 == $_POST['spam'] ) { - if ( 'spam' == $status ) { + if ( 'spam' === $status ) { wp_die( time() ); } + $r = wp_spam_comment( $comment ); } elseif ( isset( $_POST['unspam'] ) && 1 == $_POST['unspam'] ) { - if ( 'spam' != $status ) { + if ( 'spam' !== $status ) { wp_die( time() ); } + $r = wp_unspam_comment( $comment ); - if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'spam' ) { // undo spam, not in spam + + // Undo spam, not in spam. + if ( ! isset( $_POST['comment_status'] ) || 'spam' !== $_POST['comment_status'] ) { $delta = 1; } } elseif ( isset( $_POST['delete'] ) && 1 == $_POST['delete'] ) { @@ -712,9 +743,11 @@ wp_die( -1 ); } - if ( $r ) { // Decide if we need to send back '1' or a more complicated response including page links and comment counts + if ( $r ) { + // Decide if we need to send back '1' or a more complicated response including page links and comment counts. _wp_ajax_delete_comment_response( $comment->comment_ID, $delta ); } + wp_die( 0 ); } @@ -733,6 +766,7 @@ $taxonomy = ! empty( $_POST['taxonomy'] ) ? $_POST['taxonomy'] : 'post_tag'; $tag = get_term( $tag_id, $taxonomy ); + if ( ! $tag || is_wp_error( $tag ) ) { wp_die( 1 ); } @@ -753,6 +787,7 @@ $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; check_ajax_referer( "delete-bookmark_$id" ); + if ( ! current_user_can( 'manage_links' ) ) { wp_die( -1 ); } @@ -778,16 +813,20 @@ $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; check_ajax_referer( "delete-meta_$id" ); - if ( ! $meta = get_metadata_by_mid( 'post', $id ) ) { + $meta = get_metadata_by_mid( 'post', $id ); + + if ( ! $meta ) { wp_die( 1 ); } if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $meta->post_id, $meta->meta_key ) ) { wp_die( -1 ); } + if ( delete_meta( $meta->meta_id ) ) { wp_die( 1 ); } + wp_die( 0 ); } @@ -802,9 +841,10 @@ if ( empty( $action ) ) { $action = 'delete-post'; } + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; - check_ajax_referer( "{$action}_$id" ); + if ( ! current_user_can( 'delete_post', $id ) ) { wp_die( -1 ); } @@ -821,7 +861,7 @@ } /** - * Ajax handler for sending a post to the trash. + * Ajax handler for sending a post to the Trash. * * @since 3.1.0 * @@ -831,9 +871,10 @@ if ( empty( $action ) ) { $action = 'trash-post'; } + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; - check_ajax_referer( "{$action}_$id" ); + if ( ! current_user_can( 'delete_post', $id ) ) { wp_die( -1 ); } @@ -842,7 +883,7 @@ wp_die( 1 ); } - if ( 'trash-post' == $action ) { + if ( 'trash-post' === $action ) { $done = wp_trash_post( $id ); } else { $done = wp_untrash_post( $id ); @@ -856,7 +897,7 @@ } /** - * Ajax handler to restore a post from the trash. + * Ajax handler to restore a post from the Trash. * * @since 3.1.0 * @@ -866,6 +907,7 @@ if ( empty( $action ) ) { $action = 'untrash-post'; } + wp_ajax_trash_post( $action ); } @@ -880,9 +922,10 @@ if ( empty( $action ) ) { $action = 'delete-page'; } + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; - check_ajax_referer( "{$action}_$id" ); + if ( ! current_user_can( 'delete_page', $id ) ) { wp_die( -1 ); } @@ -904,14 +947,18 @@ * @since 3.1.0 */ function wp_ajax_dim_comment() { - $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; - - if ( ! $comment = get_comment( $id ) ) { + $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0; + $comment = get_comment( $id ); + + if ( ! $comment ) { $x = new WP_Ajax_Response( array( 'what' => 'comment', - /* translators: %d: comment ID */ - 'id' => new WP_Error( 'invalid_comment', sprintf( __( 'Comment %d does not exist' ), $id ) ), + 'id' => new WP_Error( + 'invalid_comment', + /* translators: %d: Comment ID. */ + sprintf( __( 'Comment %d does not exist' ), $id ) + ), ) ); $x->send(); @@ -922,12 +969,14 @@ } $current = wp_get_comment_status( $comment ); + if ( isset( $_POST['new'] ) && $_POST['new'] == $current ) { wp_die( time() ); } check_ajax_referer( "approve-comment_$id" ); - if ( in_array( $current, array( 'unapproved', 'spam' ) ) ) { + + if ( in_array( $current, array( 'unapproved', 'spam' ), true ) ) { $result = wp_set_comment_status( $comment, 'approve', true ); } else { $result = wp_set_comment_status( $comment, 'hold', true ); @@ -943,7 +992,7 @@ $x->send(); } - // Decide if we need to send back '1' or a more complicated response including page links and comment counts + // Decide if we need to send back '1' or a more complicated response including page links and comment counts. _wp_ajax_delete_comment_response( $comment->comment_ID ); wp_die( 0 ); } @@ -959,27 +1008,35 @@ if ( empty( $action ) ) { $action = 'add-link-category'; } + check_ajax_referer( $action ); $tax = get_taxonomy( 'link_category' ); + if ( ! current_user_can( $tax->cap->manage_terms ) ) { wp_die( -1 ); } + $names = explode( ',', wp_unslash( $_POST['newcat'] ) ); $x = new WP_Ajax_Response(); + foreach ( $names as $cat_name ) { $cat_name = trim( $cat_name ); $slug = sanitize_title( $cat_name ); + if ( '' === $slug ) { continue; } $cat_id = wp_insert_term( $cat_name, 'link_category' ); + if ( ! $cat_id || is_wp_error( $cat_id ) ) { continue; } else { $cat_id = $cat_id['term_id']; } + $cat_name = esc_html( $cat_name ); + $x->add( array( 'what' => 'link-category', @@ -1010,8 +1067,13 @@ $tag = wp_insert_term( $_POST['tag-name'], $taxonomy, $_POST ); - if ( ! $tag || is_wp_error( $tag ) || ( ! $tag = get_term( $tag['term_id'], $taxonomy ) ) ) { + if ( $tag && ! is_wp_error( $tag ) ) { + $tag = get_term( $tag['term_id'], $taxonomy ); + } + + if ( ! $tag || is_wp_error( $tag ) ) { $message = __( 'An error has occurred. Please reload the page and try again.' ); + if ( is_wp_error( $tag ) && $tag->get_error_message() ) { $message = $tag->get_error_message(); } @@ -1047,6 +1109,7 @@ 'supplemental' => compact( 'parents', 'noparents' ), ) ); + $x->add( array( 'what' => 'term', @@ -1054,6 +1117,7 @@ 'supplemental' => (array) $tag, ) ); + $x->send(); } @@ -1069,6 +1133,7 @@ $taxonomy = sanitize_key( $_POST['tax'] ); $tax = get_taxonomy( $taxonomy ); + if ( ! $tax ) { wp_die( 0 ); } @@ -1078,11 +1143,11 @@ } $tags = get_terms( - $taxonomy, array( - 'number' => 45, - 'orderby' => 'count', - 'order' => 'DESC', + 'taxonomy' => $taxonomy, + 'number' => 45, + 'orderby' => 'count', + 'order' => 'DESC', ) ); @@ -1099,7 +1164,7 @@ $tags[ $key ]->id = $tag->term_id; } - // We need raw tag names here, so don't filter the output + // We need raw tag names here, so don't filter the output. $return = wp_generate_tag_cloud( $tags, array( @@ -1113,7 +1178,6 @@ } echo $return; - wp_die(); } @@ -1122,15 +1186,17 @@ * * @since 3.1.0 * - * @global int $post_id + * @global int $post_id * * @param string $action Action to perform. */ function wp_ajax_get_comments( $action ) { global $post_id; + if ( empty( $action ) ) { $action = 'get-comments'; } + check_ajax_referer( $action ); if ( empty( $post_id ) && ! empty( $_REQUEST['p'] ) ) { @@ -1157,6 +1223,7 @@ } $x = new WP_Ajax_Response(); + ob_start(); foreach ( $wp_list_table->items as $comment ) { if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) && 0 === $comment->comment_approved ) { @@ -1173,6 +1240,7 @@ 'data' => $comment_list_item, ) ); + $x->send(); } @@ -1192,6 +1260,7 @@ $comment_post_ID = (int) $_POST['comment_post_ID']; $post = get_post( $comment_post_ID ); + if ( ! $post ) { wp_die( -1 ); } @@ -1202,26 +1271,28 @@ if ( empty( $post->post_status ) ) { wp_die( 1 ); - } elseif ( in_array( $post->post_status, array( 'draft', 'pending', 'trash' ) ) ) { - wp_die( __( 'ERROR: you are replying to a comment on a draft post.' ) ); + } elseif ( in_array( $post->post_status, array( 'draft', 'pending', 'trash' ), true ) ) { + wp_die( __( 'Error: You can’t reply to a comment on a draft post.' ) ); } $user = wp_get_current_user(); + if ( $user->exists() ) { $user_ID = $user->ID; $comment_author = wp_slash( $user->display_name ); $comment_author_email = wp_slash( $user->user_email ); $comment_author_url = wp_slash( $user->user_url ); $comment_content = trim( $_POST['content'] ); - $comment_type = isset( $_POST['comment_type'] ) ? trim( $_POST['comment_type'] ) : ''; + $comment_type = isset( $_POST['comment_type'] ) ? trim( $_POST['comment_type'] ) : 'comment'; + if ( current_user_can( 'unfiltered_html' ) ) { if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) ) { $_POST['_wp_unfiltered_html_comment'] = ''; } if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) { - kses_remove_filters(); // start with a clean slate - kses_init_filters(); // set up the filters + kses_remove_filters(); // Start with a clean slate. + kses_init_filters(); // Set up the filters. remove_filter( 'pre_comment_content', 'wp_filter_post_kses' ); add_filter( 'pre_comment_content', 'wp_filter_kses' ); } @@ -1230,14 +1301,16 @@ wp_die( __( 'Sorry, you must be logged in to reply to a comment.' ) ); } - if ( '' == $comment_content ) { - wp_die( __( 'ERROR: please type a comment.' ) ); + if ( '' === $comment_content ) { + wp_die( __( 'Error: Please type your comment text.' ) ); } $comment_parent = 0; + if ( isset( $_POST['comment_ID'] ) ) { $comment_parent = absint( $_POST['comment_ID'] ); } + $comment_auto_approved = false; $commentdata = compact( 'comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID' ); @@ -1245,7 +1318,7 @@ if ( ! empty( $_POST['approve_parent'] ) ) { $parent = get_comment( $comment_parent ); - if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) { + if ( $parent && '0' === $parent->comment_approved && $parent->comment_post_ID == $comment_post_ID ) { if ( ! current_user_can( 'edit_comment', $parent->comment_ID ) ) { wp_die( -1 ); } @@ -1263,6 +1336,7 @@ } $comment = get_comment( $comment_id ); + if ( ! $comment ) { wp_die( 1 ); } @@ -1270,11 +1344,11 @@ $position = ( isset( $_POST['position'] ) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1'; ob_start(); - if ( isset( $_REQUEST['mode'] ) && 'dashboard' == $_REQUEST['mode'] ) { - require_once( ABSPATH . 'wp-admin/includes/dashboard.php' ); + if ( isset( $_REQUEST['mode'] ) && 'dashboard' === $_REQUEST['mode'] ) { + require_once ABSPATH . 'wp-admin/includes/dashboard.php'; _wp_dashboard_recent_comments_row( $comment ); } else { - if ( isset( $_REQUEST['mode'] ) && 'single' == $_REQUEST['mode'] ) { + if ( isset( $_REQUEST['mode'] ) && 'single' === $_REQUEST['mode'] ) { $wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); } else { $wp_list_table = _get_list_table( 'WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); @@ -1294,12 +1368,12 @@ $response['supplemental'] = array( 'in_moderation' => $counts->moderated, 'i18n_comments_text' => sprintf( - /* translators: %s: number of comments approved */ + /* translators: %s: Number of comments. */ _n( '%s Comment', '%s Comments', $counts->approved ), number_format_i18n( $counts->approved ) ), 'i18n_moderation_text' => sprintf( - /* translators: %s: number of comments in moderation */ + /* translators: %s: Number of comments. */ _n( '%s Comment in moderation', '%s Comments in moderation', $counts->moderated ), number_format_i18n( $counts->moderated ) ), @@ -1324,24 +1398,30 @@ check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' ); $comment_id = (int) $_POST['comment_ID']; + if ( ! current_user_can( 'edit_comment', $comment_id ) ) { wp_die( -1 ); } - if ( '' == $_POST['content'] ) { - wp_die( __( 'ERROR: please type a comment.' ) ); + if ( '' === $_POST['content'] ) { + wp_die( __( 'Error: Please type your comment text.' ) ); } if ( isset( $_POST['status'] ) ) { $_POST['comment_status'] = $_POST['status']; } - edit_comment(); + + $updated = edit_comment(); + if ( is_wp_error( $updated ) ) { + wp_die( $updated->get_error_message() ); + } $position = ( isset( $_POST['position'] ) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1'; $checkbox = ( isset( $_POST['checkbox'] ) && true == $_POST['checkbox'] ) ? 1 : 0; $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) ); $comment = get_comment( $comment_id ); + if ( empty( $comment->comment_ID ) ) { wp_die( -1 ); } @@ -1380,12 +1460,12 @@ // For performance reasons, we omit some object properties from the checklist. // The following is a hacky way to restore them when adding non-custom items. - $menu_items_data = array(); + foreach ( (array) $_POST['menu-item'] as $menu_item_data ) { if ( ! empty( $menu_item_data['menu-item-type'] ) && - 'custom' != $menu_item_data['menu-item-type'] && + 'custom' !== $menu_item_data['menu-item-type'] && ! empty( $menu_item_data['menu-item-object-id'] ) ) { switch ( $menu_item_data['menu-item-type'] ) { @@ -1405,7 +1485,7 @@ $_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) ); $_menu_item = reset( $_menu_items ); - // Restore the missing menu item properties + // Restore the missing menu item properties. $menu_item_data['menu-item-description'] = $_menu_item->description; } @@ -1421,10 +1501,11 @@ foreach ( (array) $item_ids as $menu_item_id ) { $menu_obj = get_post( $menu_item_id ); + if ( ! empty( $menu_obj->ID ) ) { $menu_obj = wp_setup_nav_menu_item( $menu_obj ); $menu_obj->title = empty( $menu_obj->title ) ? __( 'Menu Item' ) : $menu_obj->title; - $menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items + $menu_obj->label = $menu_obj->title; // Don't show "(pending)" in ajax-added items. $menu_items[] = $menu_obj; } } @@ -1444,8 +1525,10 @@ 'link_before' => '', 'walker' => new $walker_class_name, ); + echo walk_nav_menu_tree( $menu_items, 0, (object) $args ); } + wp_die(); } @@ -1464,22 +1547,24 @@ if ( ! current_user_can( 'edit_post', $pid ) ) { wp_die( -1 ); } - if ( isset( $_POST['metakeyselect'] ) && '#NONE#' == $_POST['metakeyselect'] && empty( $_POST['metakeyinput'] ) ) { + + if ( isset( $_POST['metakeyselect'] ) && '#NONE#' === $_POST['metakeyselect'] && empty( $_POST['metakeyinput'] ) ) { wp_die( 1 ); } // If the post is an autodraft, save the post as a draft and then attempt to save the meta. - if ( $post->post_status == 'auto-draft' ) { + if ( 'auto-draft' === $post->post_status ) { $post_data = array(); - $post_data['action'] = 'draft'; // Warning fix + $post_data['action'] = 'draft'; // Warning fix. $post_data['post_ID'] = $pid; $post_data['post_type'] = $post->post_type; $post_data['post_status'] = 'draft'; $now = time(); - /* translators: 1: Post creation date, 2: Post creation time */ - $post_data['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), date( __( 'F j, Y' ), $now ), date( __( 'g:i a' ), $now ) ); + /* translators: 1: Post creation date, 2: Post creation time. */ + $post_data['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), gmdate( __( 'F j, Y' ), $now ), gmdate( __( 'g:i a' ), $now ) ); $pid = edit_post( $post_data ); + if ( $pid ) { if ( is_wp_error( $pid ) ) { $x = new WP_Ajax_Response( @@ -1491,20 +1576,25 @@ $x->send(); } - if ( ! $mid = add_meta( $pid ) ) { + $mid = add_meta( $pid ); + if ( ! $mid ) { wp_die( __( 'Please provide a custom field value.' ) ); } } else { wp_die( 0 ); } - } elseif ( ! $mid = add_meta( $pid ) ) { - wp_die( __( 'Please provide a custom field value.' ) ); + } else { + $mid = add_meta( $pid ); + if ( ! $mid ) { + wp_die( __( 'Please provide a custom field value.' ) ); + } } $meta = get_metadata_by_mid( 'post', $mid ); $pid = (int) $meta->post_id; $meta = get_object_vars( $meta ); - $x = new WP_Ajax_Response( + + $x = new WP_Ajax_Response( array( 'what' => 'meta', 'id' => $mid, @@ -1517,19 +1607,28 @@ $mid = (int) key( $_POST['meta'] ); $key = wp_unslash( $_POST['meta'][ $mid ]['key'] ); $value = wp_unslash( $_POST['meta'][ $mid ]['value'] ); - if ( '' == trim( $key ) ) { + + if ( '' === trim( $key ) ) { wp_die( __( 'Please provide a custom field name.' ) ); } - if ( ! $meta = get_metadata_by_mid( 'post', $mid ) ) { - wp_die( 0 ); // if meta doesn't exist + + $meta = get_metadata_by_mid( 'post', $mid ); + + if ( ! $meta ) { + wp_die( 0 ); // If meta doesn't exist. } - if ( is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) || + + if ( + is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) || ! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) || - ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) ) { + ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) + ) { wp_die( -1 ); } + if ( $meta->meta_value != $value || $meta->meta_key != $key ) { - if ( ! $u = update_metadata_by_mid( 'post', $mid, $value, $key ) ) { + $u = update_metadata_by_mid( 'post', $mid, $value, $key ); + if ( ! $u ) { wp_die( 0 ); // We know meta exists; we also know it's unchanged (or DB error, in which case there are bigger problems). } } @@ -1568,10 +1667,14 @@ } check_ajax_referer( $action ); + if ( ! current_user_can( 'create_users' ) ) { wp_die( -1 ); } - if ( ! $user_id = edit_user() ) { + + $user_id = edit_user(); + + if ( ! $user_id ) { wp_die( 0 ); } elseif ( is_wp_error( $user_id ) ) { $x = new WP_Ajax_Response( @@ -1582,8 +1685,8 @@ ); $x->send(); } - $user_object = get_userdata( $user_id ); - + + $user_object = get_userdata( $user_id ); $wp_list_table = _get_list_table( 'WP_Users_List_Table' ); $role = current( $user_object->roles ); @@ -1595,7 +1698,7 @@ 'data' => $wp_list_table->single_row( $user_object, '', $role ), 'supplemental' => array( 'show-link' => sprintf( - /* translators: %s: the new user */ + /* translators: %s: The new user. */ __( 'User %s added' ), '' . $user_object->user_login . '' ), @@ -1621,11 +1724,12 @@ $page = isset( $_POST['page'] ) ? $_POST['page'] : ''; - if ( $page != sanitize_key( $page ) ) { + if ( sanitize_key( $page ) != $page ) { wp_die( 0 ); } - if ( ! $user = wp_get_current_user() ) { + $user = wp_get_current_user(); + if ( ! $user ) { wp_die( -1 ); } @@ -1634,7 +1738,8 @@ } if ( is_array( $hidden ) ) { - $hidden = array_diff( $hidden, array( 'submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu' ) ); // postboxes that are always shown + // Postboxes that are always shown. + $hidden = array_diff( $hidden, array( 'submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu' ) ); update_user_option( $user->ID, "metaboxhidden_$page", $hidden, true ); } @@ -1650,11 +1755,12 @@ check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' ); $page = isset( $_POST['page'] ) ? $_POST['page'] : ''; - if ( $page != sanitize_key( $page ) ) { + if ( sanitize_key( $page ) != $page ) { wp_die( 0 ); } - if ( ! $user = wp_get_current_user() ) { + $user = wp_get_current_user(); + if ( ! $user ) { wp_die( -1 ); } @@ -1693,11 +1799,11 @@ require_once ABSPATH . 'wp-admin/includes/nav-menu.php'; - if ( isset( $_POST['item-type'] ) && 'post_type' == $_POST['item-type'] ) { + if ( isset( $_POST['item-type'] ) && 'post_type' === $_POST['item-type'] ) { $type = 'posttype'; $callback = 'wp_nav_menu_item_post_type_meta_box'; $items = (array) get_post_types( array( 'show_in_nav_menus' => true ), 'object' ); - } elseif ( isset( $_POST['item-type'] ) && 'taxonomy' == $_POST['item-type'] ) { + } elseif ( isset( $_POST['item-type'] ) && 'taxonomy' === $_POST['item-type'] ) { $type = 'taxonomy'; $callback = 'wp_nav_menu_item_taxonomy_meta_box'; $items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' ); @@ -1708,19 +1814,16 @@ /** This filter is documented in wp-admin/includes/nav-menu.php */ $item = apply_filters( 'nav_menu_meta_box_object', $menus_meta_box_object ); + + $box_args = array( + 'id' => 'add-' . $item->name, + 'title' => $item->labels->name, + 'callback' => $callback, + 'args' => $item, + ); + ob_start(); - call_user_func_array( - $callback, - array( - null, - array( - 'id' => 'add-' . $item->name, - 'title' => $item->labels->name, - 'callback' => $callback, - 'args' => $item, - ), - ) - ); + $callback( null, $box_args ); $markup = ob_get_clean(); @@ -1756,7 +1859,7 @@ $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1; if ( ! class_exists( '_WP_Editors', false ) ) { - require( ABSPATH . WPINC . '/class-wp-editor.php' ); + require ABSPATH . WPINC . '/class-wp-editor.php'; } $results = _WP_Editors::wp_link_query( $args ); @@ -1780,10 +1883,13 @@ if ( ! current_user_can( 'edit_theme_options' ) ) { wp_die( -1 ); } + check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' ); + if ( ! isset( $_POST['menu-locations'] ) ) { wp_die( 0 ); } + set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) ); wp_die( 1 ); } @@ -1798,17 +1904,18 @@ $order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false; $page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto'; - if ( $page_columns != 'auto' ) { + if ( 'auto' !== $page_columns ) { $page_columns = (int) $page_columns; } $page = isset( $_POST['page'] ) ? $_POST['page'] : ''; - if ( $page != sanitize_key( $page ) ) { + if ( sanitize_key( $page ) != $page ) { wp_die( 0 ); } - if ( ! $user = wp_get_current_user() ) { + $user = wp_get_current_user(); + if ( ! $user ) { wp_die( -1 ); } @@ -1820,7 +1927,7 @@ update_user_option( $user->ID, "screen_layout_$page", $page_columns, true ); } - wp_die( 1 ); + wp_send_json_success(); } /** @@ -1876,11 +1983,13 @@ check_ajax_referer( 'inlineeditnonce', '_inline_edit' ); - if ( ! isset( $_POST['post_ID'] ) || ! ( $post_ID = (int) $_POST['post_ID'] ) ) { + if ( ! isset( $_POST['post_ID'] ) || ! (int) $_POST['post_ID'] ) { wp_die(); } - if ( 'page' == $_POST['post_type'] ) { + $post_ID = (int) $_POST['post_ID']; + + if ( 'page' === $_POST['post_type'] ) { if ( ! current_user_can( 'edit_page', $post_ID ) ) { wp_die( __( 'Sorry, you are not allowed to edit this page.' ) ); } @@ -1890,14 +1999,16 @@ } } - if ( $last = wp_check_post_lock( $post_ID ) ) { + $last = wp_check_post_lock( $post_ID ); + if ( $last ) { $last_user = get_userdata( $last ); $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' ); - /* translators: %s: user who is currently editing the post */ + /* translators: %s: User's display name. */ $msg_template = __( 'Saving is disabled: %s is currently editing this post.' ); - if ( $_POST['post_type'] == 'page' ) { - /* translators: %s: user who is currently editing the page */ + + if ( 'page' === $_POST['post_type'] ) { + /* translators: %s: User's display name. */ $msg_template = __( 'Saving is disabled: %s is currently editing this page.' ); } @@ -1923,7 +2034,7 @@ } // Status. - if ( isset( $data['keep_private'] ) && 'private' == $data['keep_private'] ) { + if ( isset( $data['keep_private'] ) && 'private' === $data['keep_private'] ) { $data['visibility'] = 'private'; $data['post_status'] = 'private'; } else { @@ -1933,6 +2044,7 @@ if ( empty( $data['comment_status'] ) ) { $data['comment_status'] = 'closed'; } + if ( empty( $data['ping_status'] ) ) { $data['ping_status'] = 'closed'; } @@ -1949,7 +2061,7 @@ } // Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published. - if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) { + if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ), true ) ) { $post['post_status'] = 'publish'; $data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] ); } @@ -1959,7 +2071,7 @@ $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) ); - $mode = $_POST['post_view'] === 'excerpt' ? 'excerpt' : 'list'; + $mode = 'excerpt' === $_POST['post_view'] ? 'excerpt' : 'list'; $level = 0; if ( is_post_type_hierarchical( $wp_list_table->screen->post_type ) ) { @@ -1988,14 +2100,17 @@ $taxonomy = sanitize_key( $_POST['taxonomy'] ); $tax = get_taxonomy( $taxonomy ); + if ( ! $tax ) { wp_die( 0 ); } - if ( ! isset( $_POST['tax_ID'] ) || ! ( $id = (int) $_POST['tax_ID'] ) ) { + if ( ! isset( $_POST['tax_ID'] ) || ! (int) $_POST['tax_ID'] ) { wp_die( -1 ); } + $id = (int) $_POST['tax_ID']; + if ( ! current_user_can( 'edit_term', $id ) ) { wp_die( -1 ); } @@ -2006,6 +2121,7 @@ $_POST['description'] = $tag->description; $updated = wp_update_term( $id, $taxonomy, $_POST ); + if ( $updated && ! is_wp_error( $updated ) ) { $tag = get_term( $updated['term_id'], $taxonomy ); if ( ! $tag || is_wp_error( $tag ) ) { @@ -2020,13 +2136,16 @@ } wp_die( __( 'Item not updated.' ) ); } + $level = 0; $parent = $tag->parent; + while ( $parent > 0 ) { $parent_tag = get_term( $parent, $taxonomy ); $parent = $parent_tag->parent; $level++; } + $wp_list_table->single_row( $tag, $level ); wp_die(); } @@ -2050,6 +2169,7 @@ 'post_status' => 'any', 'posts_per_page' => 50, ); + if ( '' !== $s ) { $args['s'] = $s; } @@ -2064,7 +2184,7 @@ $alt = ''; foreach ( $posts as $post ) { $title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' ); - $alt = ( 'alternate' == $alt ) ? '' : 'alternate'; + $alt = ( 'alternate' === $alt ) ? '' : 'alternate'; switch ( $post->post_status ) { case 'publish': @@ -2082,10 +2202,10 @@ break; } - if ( '0000-00-00 00:00:00' == $post->post_date ) { + if ( '0000-00-00 00:00:00' === $post->post_date ) { $time = ''; } else { - /* translators: date format in table columns, see https://secure.php.net/date */ + /* translators: Date format in table columns, see https://www.php.net/date */ $time = mysql2date( __( 'Y/m/d' ), $post->post_date ); } @@ -2115,10 +2235,13 @@ // Save widgets order for all sidebars. if ( is_array( $_POST['sidebars'] ) ) { $sidebars = array(); + foreach ( wp_unslash( $_POST['sidebars'] ) as $key => $val ) { $sb = array(); + if ( ! empty( $val ) ) { $val = explode( ',', $val ); + foreach ( $val as $k => $v ) { if ( strpos( $v, 'widget-' ) === false ) { continue; @@ -2129,6 +2252,7 @@ } $sidebars[ $key ] = $sb; } + wp_set_sidebars_widgets( $sidebars ); wp_die( 1 ); } @@ -2161,14 +2285,14 @@ * * @since 2.8.0 */ - do_action( 'load-widgets.php' ); + do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** * Fires early when editing the widgets displayed in sidebars. * * @since 2.8.0 */ - do_action( 'widgets.php' ); + do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); @@ -2237,7 +2361,8 @@ wp_die(); } - if ( $form = $wp_registered_widget_controls[ $widget_id ] ) { + $form = $wp_registered_widget_controls[ $widget_id ]; + if ( $form ) { call_user_func_array( $form['callback'], $form['params'] ); } @@ -2270,9 +2395,9 @@ unset( $_POST['removeinactivewidgets'], $_POST['action'] ); /** This action is documented in wp-admin/includes/ajax-actions.php */ - do_action( 'load-widgets.php' ); + do_action( 'load-widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/includes/ajax-actions.php */ - do_action( 'widgets.php' ); + do_action( 'widgets.php' ); // phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores /** This action is documented in wp-admin/widgets.php */ do_action( 'sidebar_admin_setup' ); @@ -2294,6 +2419,63 @@ } /** + * Ajax handler for creating missing image sub-sizes for just uploaded images. + * + * @since 5.3.0 + */ +function wp_ajax_media_create_image_subsizes() { + check_ajax_referer( 'media-form' ); + + if ( ! current_user_can( 'upload_files' ) ) { + wp_send_json_error( array( 'message' => __( 'Sorry, you are not allowed to upload files.' ) ) ); + } + + if ( empty( $_POST['attachment_id'] ) ) { + wp_send_json_error( array( 'message' => __( 'Upload failed. Please reload and try again.' ) ) ); + } + + $attachment_id = (int) $_POST['attachment_id']; + + if ( ! empty( $_POST['_wp_upload_failed_cleanup'] ) ) { + // Upload failed. Cleanup. + if ( wp_attachment_is_image( $attachment_id ) && current_user_can( 'delete_post', $attachment_id ) ) { + $attachment = get_post( $attachment_id ); + + // Created at most 10 min ago. + if ( $attachment && ( time() - strtotime( $attachment->post_date_gmt ) < 600 ) ) { + wp_delete_attachment( $attachment_id, true ); + wp_send_json_success(); + } + } + } + + // Set a custom header with the attachment_id. + // Used by the browser/client to resume creating image sub-sizes after a PHP fatal error. + if ( ! headers_sent() ) { + header( 'X-WP-Upload-Attachment-ID: ' . $attachment_id ); + } + + // This can still be pretty slow and cause timeout or out of memory errors. + // The js that handles the response would need to also handle HTTP 500 errors. + wp_update_image_subsizes( $attachment_id ); + + if ( ! empty( $_POST['_legacy_support'] ) ) { + // The old (inline) uploader. Only needs the attachment_id. + $response = array( 'id' => $attachment_id ); + } else { + // Media modal and Media Library grid view. + $response = wp_prepare_attachment_for_js( $attachment_id ); + + if ( ! $response ) { + wp_send_json_error( array( 'message' => __( 'Upload failed.' ) ) ); + } + } + + // At this point the image has been uploaded successfully. + wp_send_json_success( $response ); +} + +/** * Ajax handler for uploading attachments * * @since 3.3.0 @@ -2322,6 +2504,7 @@ if ( isset( $_REQUEST['post_id'] ) ) { $post_id = $_REQUEST['post_id']; + if ( ! current_user_can( 'edit_post', $post_id ) ) { echo wp_json_encode( array( @@ -2346,8 +2529,9 @@ } // If the context is custom header or background, make sure the uploaded file is an image. - if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) { + if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ), true ) ) { $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'] ); + if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) { echo wp_json_encode( array( @@ -2389,7 +2573,8 @@ } } - if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) ) { + $attachment = wp_prepare_attachment_for_js( $attachment_id ); + if ( ! $attachment ) { wp_die(); } @@ -2410,19 +2595,23 @@ */ function wp_ajax_image_editor() { $attachment_id = intval( $_POST['postid'] ); + if ( empty( $attachment_id ) || ! current_user_can( 'edit_post', $attachment_id ) ) { wp_die( -1 ); } check_ajax_referer( "image_editor-$attachment_id" ); - include_once( ABSPATH . 'wp-admin/includes/image-edit.php' ); + include_once ABSPATH . 'wp-admin/includes/image-edit.php'; $msg = false; switch ( $_POST['do'] ) { case 'save': $msg = wp_save_image( $attachment_id ); - $msg = wp_json_encode( $msg ); - wp_die( $msg ); + if ( $msg->error ) { + wp_send_json_error( $msg ); + } + + wp_send_json_success( $msg ); break; case 'scale': $msg = wp_save_image( $attachment_id ); @@ -2432,8 +2621,25 @@ break; } + ob_start(); wp_image_editor( $attachment_id, $msg ); - wp_die(); + $html = ob_get_clean(); + + if ( $msg->error ) { + wp_send_json_error( + array( + 'message' => $msg, + 'html' => $html, + ) + ); + } + + wp_send_json_success( + array( + 'message' => $msg, + 'html' => $html, + ) + ); } /** @@ -2442,7 +2648,7 @@ * @since 3.1.0 */ function wp_ajax_set_post_thumbnail() { - $json = ! empty( $_REQUEST['json'] ); // New-style request + $json = ! empty( $_REQUEST['json'] ); // New-style request. $post_ID = intval( $_POST['post_id'] ); if ( ! current_user_can( 'edit_post', $post_ID ) ) { @@ -2457,7 +2663,7 @@ check_ajax_referer( "set_post_thumbnail-$post_ID" ); } - if ( $thumbnail_id == '-1' ) { + if ( '-1' == $thumbnail_id ) { if ( delete_post_thumbnail( $post_ID ) ) { $return = _wp_post_thumbnail_html( null, $post_ID ); $json ? wp_send_json_success( $return ) : wp_die( $return ); @@ -2599,12 +2805,13 @@ $last_time = date_i18n( __( 'g:i a' ) ); } - if ( $last_id = get_post_meta( $post_id, '_edit_last', true ) ) { + $last_id = get_post_meta( $post_id, '_edit_last', true ); + if ( $last_id ) { $last_user = get_userdata( $last_id ); - /* translators: 1: display_name of last user, 2: date of last edit, 3: time of last edit. */ + /* translators: 1: User's display name, 2: Date of last edit, 3: Time of last edit. */ $last_edited = sprintf( __( 'Last edited by %1$s on %2$s at %3$s' ), esc_html( $last_user->display_name ), $last_date, $last_time ); } else { - /* translators: 1: date of last edit, 2: time of last edit. */ + /* translators: 1: Date of last edit, 2: Time of last edit. */ $last_edited = sprintf( __( 'Last edited on %1$s at %2$s' ), $last_date, $last_time ); } @@ -2620,8 +2827,11 @@ if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) ) { wp_die( 0 ); } + $post_id = (int) $_POST['post_ID']; - if ( ! $post = get_post( $post_id ) ) { + $post = get_post( $post_id ); + + if ( ! $post ) { wp_die( 0 ); } @@ -2632,7 +2842,8 @@ } $active_lock = array_map( 'absint', explode( ':', $_POST['active_post_lock'] ) ); - if ( $active_lock[1] != get_current_user_id() ) { + + if ( get_current_user_id() != $active_lock[1] ) { wp_die( 0 ); } @@ -2656,7 +2867,8 @@ */ function wp_ajax_dismiss_wp_pointer() { $pointer = $_POST['pointer']; - if ( $pointer != sanitize_key( $pointer ) ) { + + if ( sanitize_key( $pointer ) != $pointer ) { wp_die( 0 ); } @@ -2664,7 +2876,7 @@ $dismissed = array_filter( explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ) ); - if ( in_array( $pointer, $dismissed ) ) { + if ( in_array( $pointer, $dismissed, true ) ) { wp_die( 0 ); } @@ -2685,15 +2897,17 @@ wp_send_json_error(); } - if ( ! $id = absint( $_REQUEST['id'] ) ) { + $id = absint( $_REQUEST['id'] ); + if ( ! $id ) { wp_send_json_error(); } - if ( ! $post = get_post( $id ) ) { + $post = get_post( $id ); + if ( ! $post ) { wp_send_json_error(); } - if ( 'attachment' != $post->post_type ) { + if ( 'attachment' !== $post->post_type ) { wp_send_json_error(); } @@ -2701,7 +2915,8 @@ wp_send_json_error(); } - if ( ! $attachment = wp_prepare_attachment_for_js( $id ) ) { + $attachment = wp_prepare_attachment_for_js( $id ); + if ( ! $attachment ) { wp_send_json_error(); } @@ -2733,6 +2948,7 @@ 'year', 'monthnum', ); + foreach ( get_taxonomies_for_attachments( 'objects' ) as $t ) { if ( $t->query_var && isset( $query[ $t->query_var ] ) ) { $keys[] = $t->query_var; @@ -2741,9 +2957,12 @@ $query = array_intersect_key( $query, array_flip( $keys ) ); $query['post_type'] = 'attachment'; - if ( MEDIA_TRASH - && ! empty( $_REQUEST['query']['post_status'] ) - && 'trash' === $_REQUEST['query']['post_status'] ) { + + if ( + MEDIA_TRASH && + ! empty( $_REQUEST['query']['post_status'] ) && + 'trash' === $_REQUEST['query']['post_status'] + ) { $query['post_status'] = 'trash'; } else { $query['post_status'] = 'inherit'; @@ -2787,7 +3006,8 @@ wp_send_json_error(); } - if ( ! $id = absint( $_REQUEST['id'] ) ) { + $id = absint( $_REQUEST['id'] ); + if ( ! $id ) { wp_send_json_error(); } @@ -2800,7 +3020,7 @@ $changes = $_REQUEST['changes']; $post = get_post( $id, ARRAY_A ); - if ( 'attachment' != $post['post_type'] ) { + if ( 'attachment' !== $post['post_type'] ) { wp_send_json_error(); } @@ -2826,7 +3046,7 @@ if ( isset( $changes['alt'] ) ) { $alt = wp_unslash( $changes['alt'] ); - if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) { + if ( get_post_meta( $id, '_wp_attachment_image_alt', true ) !== $alt ) { $alt = wp_strip_all_tags( $alt, true ); update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) ); } @@ -2835,10 +3055,12 @@ if ( wp_attachment_is( 'audio', $post['ID'] ) ) { $changed = false; $id3data = wp_get_attachment_metadata( $post['ID'] ); + if ( ! is_array( $id3data ) ) { $changed = true; $id3data = array(); } + foreach ( wp_get_attachment_id3_keys( (object) $post, 'edit' ) as $key => $label ) { if ( isset( $changes[ $key ] ) ) { $changed = true; @@ -2870,13 +3092,15 @@ wp_send_json_error(); } - if ( ! $id = absint( $_REQUEST['id'] ) ) { + $id = absint( $_REQUEST['id'] ); + if ( ! $id ) { wp_send_json_error(); } if ( empty( $_REQUEST['attachments'] ) || empty( $_REQUEST['attachments'][ $id ] ) ) { wp_send_json_error(); } + $attachment_data = $_REQUEST['attachments'][ $id ]; check_ajax_referer( 'update-post_' . $id, 'nonce' ); @@ -2887,7 +3111,7 @@ $post = get_post( $id, ARRAY_A ); - if ( 'attachment' != $post['post_type'] ) { + if ( 'attachment' !== $post['post_type'] ) { wp_send_json_error(); } @@ -2907,7 +3131,9 @@ } } - if ( ! $attachment = wp_prepare_attachment_for_js( $id ) ) { + $attachment = wp_prepare_attachment_for_js( $id ); + + if ( ! $attachment ) { wp_send_json_error(); } @@ -2924,7 +3150,8 @@ wp_send_json_error(); } - if ( ! $post_id = absint( $_REQUEST['post_id'] ) ) { + $post_id = absint( $_REQUEST['post_id'] ); + if ( ! $post_id ) { wp_send_json_error(); } @@ -2944,10 +3171,14 @@ if ( ! current_user_can( 'edit_post', $attachment_id ) ) { continue; } - if ( ! $attachment = get_post( $attachment_id ) ) { + + $attachment = get_post( $attachment_id ); + + if ( ! $attachment ) { continue; } - if ( 'attachment' != $attachment->post_type ) { + + if ( 'attachment' !== $attachment->post_type ) { continue; } @@ -2978,17 +3209,20 @@ $id = intval( $attachment['id'] ); - if ( ! $post = get_post( $id ) ) { + $post = get_post( $id ); + if ( ! $post ) { wp_send_json_error(); } - if ( 'attachment' != $post->post_type ) { + if ( 'attachment' !== $post->post_type ) { wp_send_json_error(); } if ( current_user_can( 'edit_post', $id ) ) { // If this attachment is unattached, attach it. Primarily a back compat thing. - if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) { + $insert_into_post_id = intval( $_POST['post_id'] ); + + if ( 0 == $post->post_parent && $insert_into_post_id ) { wp_update_post( array( 'ID' => $id, @@ -3020,7 +3254,7 @@ $html = stripslashes_deep( $_POST['html'] ); } else { $html = isset( $attachment['post_title'] ) ? $attachment['post_title'] : ''; - $rel = $rel ? ' rel="attachment wp-att-' . $id . '"' : ''; // Hard-coded string, $id is already sanitized + $rel = $rel ? ' rel="attachment wp-att-' . $id . '"' : ''; // Hard-coded string, $id is already sanitized. if ( ! empty( $url ) ) { $html = '' . $html . ''; @@ -3045,7 +3279,7 @@ * * @since 3.5.0 * - * @global WP_Post $post + * @global WP_Post $post Global post object. * @global WP_Embed $wp_embed */ function wp_ajax_send_link_to_editor() { @@ -3053,7 +3287,8 @@ check_ajax_referer( 'media-send-to-editor', 'nonce' ); - if ( ! $src = wp_unslash( $_POST['src'] ) ) { + $src = wp_unslash( $_POST['src'] ); + if ( ! $src ) { wp_send_json_error(); } @@ -3061,11 +3296,13 @@ $src = 'http://' . $src; } - if ( ! $src = esc_url_raw( $src ) ) { + $src = esc_url_raw( $src ); + if ( ! $src ) { wp_send_json_error(); } - if ( ! $link_text = trim( wp_unslash( $_POST['link_text'] ) ) ) { + $link_text = trim( wp_unslash( $_POST['link_text'] ) ); + if ( ! $link_text ) { $link_text = wp_basename( $src ); } @@ -3078,7 +3315,7 @@ $fallback = $wp_embed->maybe_make_link( $src ); if ( $check_embed !== $fallback ) { - // TinyMCE view for [embed] will parse this + // TinyMCE view for [embed] will parse this. $html = '[embed]' . $src . '[/embed]'; } elseif ( $link_text ) { $html = '' . $link_text . ''; @@ -3088,9 +3325,12 @@ // Figure out what filter to run: $type = 'file'; - if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) ) - && ( 'audio' == $ext_type || 'video' == $ext_type ) ) { + $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ); + if ( $ext ) { + $ext_type = wp_ext2type( $ext ); + if ( 'audio' === $ext_type || 'video' === $ext_type ) { $type = $ext_type; + } } /** This filter is documented in wp-admin/includes/media.php */ @@ -3111,10 +3351,11 @@ wp_send_json_error(); } - $response = $data = array(); + $response = array(); + $data = array(); $nonce_state = wp_verify_nonce( $_POST['_nonce'], 'heartbeat-nonce' ); - // screen_id is the same as $current_screen->id and the JS global 'pagenow'. + // 'screen_id' is the same as $current_screen->id and the JS global 'pagenow'. if ( ! empty( $_POST['screen_id'] ) ) { $screen_id = sanitize_key( $_POST['screen_id'] ); } else { @@ -3133,7 +3374,7 @@ * * @param array $response The Heartbeat response. * @param array $data The $_POST data sent. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ $response = apply_filters( 'wp_refresh_nonces', $response, $data, $screen_id ); @@ -3152,7 +3393,7 @@ * * @param array $response The Heartbeat response. * @param array $data The $_POST data sent. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ $response = apply_filters( 'heartbeat_received', $response, $data, $screen_id ); } @@ -3163,7 +3404,7 @@ * @since 3.6.0 * * @param array $response The Heartbeat response. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ $response = apply_filters( 'heartbeat_send', $response, $screen_id ); @@ -3175,11 +3416,11 @@ * @since 3.6.0 * * @param array $response The Heartbeat response. - * @param string $screen_id The screen id. + * @param string $screen_id The screen ID. */ do_action( 'heartbeat_tick', $response, $screen_id ); - // Send the current time according to the server + // Send the current time according to the server. $response['server_time'] = time(); wp_send_json( $response ); @@ -3193,7 +3434,8 @@ function wp_ajax_get_revision_diffs() { require ABSPATH . 'wp-admin/includes/revision.php'; - if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) ) { + $post = get_post( (int) $_REQUEST['post_id'] ); + if ( ! $post ) { wp_send_json_error(); } @@ -3202,12 +3444,13 @@ } // Really just pre-loading the cache here. - if ( ! $revisions = wp_get_post_revisions( $post->ID, array( 'check_enabled' => false ) ) ) { + $revisions = wp_get_post_revisions( $post->ID, array( 'check_enabled' => false ) ); + if ( ! $revisions ) { wp_send_json_error(); } $return = array(); - @set_time_limit( 0 ); + set_time_limit( 0 ); foreach ( $_REQUEST['compare'] as $compare_key ) { list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to @@ -3297,6 +3540,7 @@ } $update_php = network_admin_url( 'update.php?action=install-theme' ); + foreach ( $api->themes as &$theme ) { $theme->install_url = add_query_arg( array( @@ -3341,7 +3585,8 @@ $theme->author = wp_kses( $theme->author['display_name'], $themes_allowedtags ); $theme->version = wp_kses( $theme->version, $themes_allowedtags ); $theme->description = wp_kses( $theme->description, $themes_allowedtags ); - $theme->stars = wp_star_rating( + + $theme->stars = wp_star_rating( array( 'rating' => $theme->rating, 'type' => 'percent', @@ -3349,8 +3594,11 @@ 'echo' => false, ) ); - $theme->num_ratings = number_format_i18n( $theme->num_ratings ); - $theme->preview_url = set_url_scheme( $theme->preview_url ); + + $theme->num_ratings = number_format_i18n( $theme->num_ratings ); + $theme->preview_url = set_url_scheme( $theme->preview_url ); + $theme->compatible_wp = is_wp_version_compatible( $theme->requires ); + $theme->compatible_php = is_php_version_compatible( $theme->requires_php ); } wp_send_json_success( $api ); @@ -3361,7 +3609,7 @@ * * @since 4.0.0 * - * @global WP_Post $post Global $post. + * @global WP_Post $post Global post object. * @global WP_Embed $wp_embed Embed API instance. * @global WP_Scripts $wp_scripts * @global int $content_width @@ -3372,9 +3620,12 @@ if ( empty( $_POST['shortcode'] ) ) { wp_send_json_error(); } + $post_id = isset( $_POST['post_ID'] ) ? intval( $_POST['post_ID'] ) : 0; + if ( $post_id > 0 ) { $post = get_post( $post_id ); + if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) { wp_send_json_error(); } @@ -3387,6 +3638,7 @@ preg_match( '/' . get_shortcode_regex() . '/s', $shortcode, $matches ); $atts = shortcode_parse_atts( $matches[3] ); + if ( ! empty( $matches[5] ) ) { $url = $matches[5]; } elseif ( ! empty( $atts['src'] ) ) { @@ -3435,7 +3687,7 @@ wp_send_json_error( array( 'type' => 'not-embeddable', - /* translators: %s: URL which cannot be embedded, between code tags */ + /* translators: %s: URL that could not be embedded. */ 'message' => sprintf( __( '%s failed to embed.' ), '' . esc_html( $url ) . '' ), ) ); @@ -3444,6 +3696,7 @@ if ( has_shortcode( $parsed, 'audio' ) || has_shortcode( $parsed, 'video' ) ) { $styles = ''; $mce_styles = wpview_media_sandbox_styles(); + foreach ( $mce_styles as $style ) { $styles .= sprintf( '', $style ); } @@ -3451,9 +3704,11 @@ $html = do_shortcode( $parsed ); global $wp_scripts; + if ( ! empty( $wp_scripts ) ) { $wp_scripts->done = array(); } + ob_start(); wp_print_scripts( array( 'mediaelement-vimeo', 'wp-mediaelement' ) ); $scripts = ob_get_clean(); @@ -3494,7 +3749,7 @@ /** * @since 4.0.0 * - * @global WP_Post $post + * @global WP_Post $post Global post object. * @global WP_Scripts $wp_scripts */ function wp_ajax_parse_media_shortcode() { @@ -3510,7 +3765,7 @@ $post = get_post( (int) $_POST['post_ID'] ); } - // the embed shortcode requires a post + // The embed shortcode requires a post. if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) { if ( 'embed' === $shortcode ) { wp_send_json_error(); @@ -3568,6 +3823,7 @@ */ function wp_ajax_destroy_sessions() { $user = get_userdata( (int) $_POST['user_id'] ); + if ( $user ) { if ( ! current_user_can( 'edit_user', $user->ID ) ) { $user = false; @@ -3586,7 +3842,7 @@ $sessions = WP_Session_Tokens::get_instance( $user->ID ); - if ( $user->ID === get_current_user_id() ) { + if ( get_current_user_id() === $user->ID ) { $sessions->destroy_others( wp_get_session_token() ); $message = __( 'You are now logged out everywhere else.' ); } else { @@ -3607,6 +3863,7 @@ $attachment_id = absint( $_POST['id'] ); check_ajax_referer( 'image_editor-' . $attachment_id, 'nonce' ); + if ( empty( $attachment_id ) || ! current_user_can( 'edit_post', $attachment_id ) ) { wp_send_json_error(); } @@ -3635,7 +3892,7 @@ break; } - /** This filter is documented in wp-admin/custom-header.php */ + /** This filter is documented in wp-admin/includes/class-custom-image-header.php */ $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication. $object = $wp_site_icon->create_attachment_object( $cropped, $attachment_id ); unset( $object['ID'] ); @@ -3663,7 +3920,7 @@ */ do_action( 'wp_ajax_crop_image_pre_save', $context, $attachment_id, $cropped ); - /** This filter is documented in wp-admin/custom-header.php */ + /** This filter is documented in wp-admin/includes/class-custom-image-header.php */ $cropped = apply_filters( 'wp_create_file_in_uploads', $cropped, $attachment_id ); // For replication. $parent_url = wp_get_attachment_url( $attachment_id ); @@ -3773,8 +4030,8 @@ wp_send_json_error( $status ); } - include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + include_once ABSPATH . 'wp-admin/includes/theme.php'; $api = themes_api( 'theme_information', @@ -3902,7 +4159,7 @@ $status['oldVersion'] = $theme->get( 'Version' ); } - include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; $current = get_site_transient( 'update_themes' ); if ( empty( $current ) ) { @@ -3953,7 +4210,7 @@ } // An unhandled error occurred. - $status['errorMessage'] = __( 'Update failed.' ); + $status['errorMessage'] = __( 'Theme update failed.' ); wp_send_json_error( $status ); } @@ -3997,9 +4254,11 @@ // Check filesystem credentials. `delete_theme()` will bail otherwise. $url = wp_nonce_url( 'themes.php?action=delete&stylesheet=' . urlencode( $stylesheet ), 'delete-theme_' . $stylesheet ); + ob_start(); $credentials = request_filesystem_credentials( $url ); ob_end_clean(); + if ( false === $credentials || ! WP_Filesystem( $credentials ) ) { global $wp_filesystem; @@ -4014,7 +4273,7 @@ wp_send_json_error( $status ); } - include_once( ABSPATH . 'wp-admin/includes/theme.php' ); + include_once ABSPATH . 'wp-admin/includes/theme.php'; $result = delete_theme( $stylesheet ); @@ -4061,8 +4320,8 @@ wp_send_json_error( $status ); } - include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); - include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; + include_once ABSPATH . 'wp-admin/includes/plugin-install.php'; $api = plugins_api( 'plugin_information', @@ -4179,11 +4438,11 @@ $status['pluginName'] = $plugin_data['Name']; if ( $plugin_data['Version'] ) { - /* translators: %s: Plugin version */ + /* translators: %s: Plugin version. */ $status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] ); } - include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); + require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; wp_update_plugins(); @@ -4203,18 +4462,18 @@ $status['errorMessage'] = $skin->get_error_messages(); wp_send_json_error( $status ); } elseif ( is_array( $result ) && ! empty( $result[ $plugin ] ) ) { - $plugin_update_data = current( $result ); /* - * If the `update_plugins` site transient is empty (e.g. when you update - * two plugins in quick succession before the transient repopulates), - * this may be the return. + * Plugin is already at the latest version. + * + * This may also be the return value if the `update_plugins` site transient is empty, + * e.g. when you update two plugins in quick succession before the transient repopulates. * * Preferably something can be done to ensure `update_plugins` isn't empty. * For now, surface some sort of error here. */ - if ( true === $plugin_update_data ) { - $status['errorMessage'] = __( 'Plugin update failed.' ); + if ( true === $result[ $plugin ] ) { + $status['errorMessage'] = $upgrader->strings['up_to_date']; wp_send_json_error( $status ); } @@ -4222,9 +4481,10 @@ $plugin_data = reset( $plugin_data ); if ( $plugin_data['Version'] ) { - /* translators: %s: Plugin version */ + /* translators: %s: Plugin version. */ $status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] ); } + wp_send_json_success( $status ); } elseif ( false === $result ) { global $wp_filesystem; @@ -4290,9 +4550,11 @@ // Check filesystem credentials. `delete_plugins()` will bail otherwise. $url = wp_nonce_url( 'plugins.php?action=delete-selected&verify-delete=1&checked[]=' . $plugin, 'bulk-plugins' ); + ob_start(); $credentials = request_filesystem_credentials( $url ); ob_end_clean(); + if ( false === $credentials || ! WP_Filesystem( $credentials ) ) { global $wp_filesystem; @@ -4330,6 +4592,9 @@ function wp_ajax_search_plugins() { check_ajax_referer( 'updates' ); + // Ensure after_plugin_row_{$plugin_file} gets hooked. + wp_plugin_update_rows(); + $pagenow = isset( $_POST['pagenow'] ) ? sanitize_key( $_POST['pagenow'] ) : ''; if ( 'plugins-network' === $pagenow || 'plugins' === $pagenow ) { set_current_screen( $pagenow ); @@ -4428,10 +4693,12 @@ * Ajax handler for editing a theme or plugin file. * * @since 4.9.0 + * * @see wp_edit_theme_plugin_file() */ function wp_ajax_edit_theme_plugin_file() { $r = wp_edit_theme_plugin_file( wp_unslash( $_POST ) ); // Validation of args is done in wp_edit_theme_plugin_file(). + if ( is_wp_error( $r ) ) { wp_send_json_error( array_merge( @@ -4461,6 +4728,7 @@ if ( empty( $_POST['id'] ) ) { wp_send_json_error( __( 'Missing request ID.' ) ); } + $request_id = (int) $_POST['id']; if ( $request_id < 1 ) { @@ -4473,8 +4741,8 @@ check_ajax_referer( 'wp-privacy-export-personal-data-' . $request_id, 'security' ); - // Get the request data. - $request = wp_get_user_request_data( $request_id ); + // Get the request. + $request = wp_get_user_request( $request_id ); if ( ! $request || 'export_personal_data' !== $request->action_name ) { wp_send_json_error( __( 'Invalid request type.' ) ); @@ -4488,11 +4756,13 @@ if ( ! isset( $_POST['exporter'] ) ) { wp_send_json_error( __( 'Missing exporter index.' ) ); } + $exporter_index = (int) $_POST['exporter']; if ( ! isset( $_POST['page'] ) ) { wp_send_json_error( __( 'Missing page index.' ) ); } + $page = (int) $_POST['page']; $send_as_email = isset( $_POST['sendAsEmail'] ) ? ( 'true' === $_POST['sendAsEmail'] ) : false; @@ -4505,14 +4775,14 @@ * @param array $args { * An array of callable exporters of personal data. Default empty array. * - * @type array { + * @type array ...$0 { * Array of personal data exporters. * - * @type string $callback Callable exporter function that accepts an - * email address and a page and returns an array - * of name => value pairs of personal data. - * @type string $exporter_friendly_name Translated user facing friendly name for the - * exporter. + * @type callable $callback Callable exporter function that accepts an + * email address and a page and returns an array + * of name => value pairs of personal data. + * @type string $exporter_friendly_name Translated user facing friendly name for the + * exporter. * } * } */ @@ -4542,13 +4812,14 @@ if ( ! is_array( $exporter ) ) { wp_send_json_error( - /* translators: %s: exporter array index */ + /* translators: %s: Exporter array index. */ sprintf( __( 'Expected an array describing the exporter at index %s.' ), $exporter_key ) ); } + if ( ! array_key_exists( 'exporter_friendly_name', $exporter ) ) { wp_send_json_error( - /* translators: %s: exporter array index */ + /* translators: %s: Exporter array index. */ sprintf( __( 'Exporter array at index %s does not include a friendly name.' ), $exporter_key ) ); } @@ -4557,13 +4828,14 @@ if ( ! array_key_exists( 'callback', $exporter ) ) { wp_send_json_error( - /* translators: %s: exporter friendly name */ + /* translators: %s: Exporter friendly name. */ sprintf( __( 'Exporter does not include a callback: %s.' ), esc_html( $exporter_friendly_name ) ) ); } + if ( ! is_callable( $exporter['callback'] ) ) { wp_send_json_error( - /* translators: %s: exporter friendly name */ + /* translators: %s: Exporter friendly name. */ sprintf( __( 'Exporter callback is not a valid callback: %s.' ), esc_html( $exporter_friendly_name ) ) ); } @@ -4577,25 +4849,28 @@ if ( ! is_array( $response ) ) { wp_send_json_error( - /* translators: %s: exporter friendly name */ + /* translators: %s: Exporter friendly name. */ sprintf( __( 'Expected response as an array from exporter: %s.' ), esc_html( $exporter_friendly_name ) ) ); } + if ( ! array_key_exists( 'data', $response ) ) { wp_send_json_error( - /* translators: %s: exporter friendly name */ + /* translators: %s: Exporter friendly name. */ sprintf( __( 'Expected data in response array from exporter: %s.' ), esc_html( $exporter_friendly_name ) ) ); } + if ( ! is_array( $response['data'] ) ) { wp_send_json_error( - /* translators: %s: exporter friendly name */ + /* translators: %s: Exporter friendly name. */ sprintf( __( 'Expected data array in response array from exporter: %s.' ), esc_html( $exporter_friendly_name ) ) ); } + if ( ! array_key_exists( 'done', $response ) ) { wp_send_json_error( - /* translators: %s: exporter friendly name */ + /* translators: %s: Exporter friendly name. */ sprintf( __( 'Expected done (boolean) in response array from exporter: %s.' ), esc_html( $exporter_friendly_name ) ) ); } @@ -4657,8 +4932,8 @@ check_ajax_referer( 'wp-privacy-erase-personal-data-' . $request_id, 'security' ); - // Get the request data. - $request = wp_get_user_request_data( $request_id ); + // Get the request. + $request = wp_get_user_request( $request_id ); if ( ! $request || 'remove_personal_data' !== $request->action_name ) { wp_send_json_error( __( 'Invalid request type.' ) ); @@ -4690,15 +4965,15 @@ * @param array $args { * An array of callable erasers of personal data. Default empty array. * - * @type array { + * @type array ...$0 { * Array of personal data exporters. * - * @type string $callback Callable eraser that accepts an email address and - * a page and returns an array with boolean values for - * whether items were removed or retained and any messages - * from the eraser, as well as if additional pages are - * available. - * @type string $exporter_friendly_name Translated user facing friendly name for the eraser. + * @type callable $callback Callable eraser that accepts an email address and + * a page and returns an array with boolean values for + * whether items were removed or retained and any messages + * from the eraser, as well as if additional pages are + * available. + * @type string $exporter_friendly_name Translated user facing friendly name for the eraser. * } * } */ @@ -4724,12 +4999,12 @@ $eraser = $erasers[ $eraser_key ]; if ( ! is_array( $eraser ) ) { - /* translators: %d: eraser array index */ + /* translators: %d: Eraser array index. */ wp_send_json_error( sprintf( __( 'Expected an array describing the eraser at index %d.' ), $eraser_index ) ); } if ( ! array_key_exists( 'eraser_friendly_name', $eraser ) ) { - /* translators: %d: eraser array index */ + /* translators: %d: Eraser array index. */ wp_send_json_error( sprintf( __( 'Eraser array at index %d does not include a friendly name.' ), $eraser_index ) ); } @@ -4738,7 +5013,7 @@ if ( ! array_key_exists( 'callback', $eraser ) ) { wp_send_json_error( sprintf( - /* translators: %s: eraser friendly name */ + /* translators: %s: Eraser friendly name. */ __( 'Eraser does not include a callback: %s.' ), esc_html( $eraser_friendly_name ) ) @@ -4748,7 +5023,7 @@ if ( ! is_callable( $eraser['callback'] ) ) { wp_send_json_error( sprintf( - /* translators: %s: eraser friendly name */ + /* translators: %s: Eraser friendly name. */ __( 'Eraser callback is not valid: %s.' ), esc_html( $eraser_friendly_name ) ) @@ -4765,7 +5040,7 @@ if ( ! is_array( $response ) ) { wp_send_json_error( sprintf( - /* translators: 1: eraser friendly name, 2: eraser array index */ + /* translators: 1: Eraser friendly name, 2: Eraser array index. */ __( 'Did not receive array from %1$s eraser (index %2$d).' ), esc_html( $eraser_friendly_name ), $eraser_index @@ -4776,7 +5051,7 @@ if ( ! array_key_exists( 'items_removed', $response ) ) { wp_send_json_error( sprintf( - /* translators: 1: eraser friendly name, 2: eraser array index */ + /* translators: 1: Eraser friendly name, 2: Eraser array index. */ __( 'Expected items_removed key in response array from %1$s eraser (index %2$d).' ), esc_html( $eraser_friendly_name ), $eraser_index @@ -4787,7 +5062,7 @@ if ( ! array_key_exists( 'items_retained', $response ) ) { wp_send_json_error( sprintf( - /* translators: 1: eraser friendly name, 2: eraser array index */ + /* translators: 1: Eraser friendly name, 2: Eraser array index. */ __( 'Expected items_retained key in response array from %1$s eraser (index %2$d).' ), esc_html( $eraser_friendly_name ), $eraser_index @@ -4798,7 +5073,7 @@ if ( ! array_key_exists( 'messages', $response ) ) { wp_send_json_error( sprintf( - /* translators: 1: eraser friendly name, 2: eraser array index */ + /* translators: 1: Eraser friendly name, 2: Eraser array index. */ __( 'Expected messages key in response array from %1$s eraser (index %2$d).' ), esc_html( $eraser_friendly_name ), $eraser_index @@ -4809,7 +5084,7 @@ if ( ! is_array( $response['messages'] ) ) { wp_send_json_error( sprintf( - /* translators: 1: eraser friendly name, 2: eraser array index */ + /* translators: 1: Eraser friendly name, 2: Eraser array index. */ __( 'Expected messages key to reference an array in response array from %1$s eraser (index %2$d).' ), esc_html( $eraser_friendly_name ), $eraser_index @@ -4820,7 +5095,7 @@ if ( ! array_key_exists( 'done', $response ) ) { wp_send_json_error( sprintf( - /* translators: 1: eraser friendly name, 2: eraser array index */ + /* translators: 1: Eraser friendly name, 2: Eraser array index. */ __( 'Expected done flag in response array from %1$s eraser (index %2$d).' ), esc_html( $eraser_friendly_name ), $eraser_index @@ -4875,10 +5150,10 @@ } if ( ! class_exists( 'WP_Site_Health' ) ) { - require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' ); - } - - $site_health = new WP_Site_Health(); + require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php'; + } + + $site_health = WP_Site_Health::get_instance(); wp_send_json_success( $site_health->get_test_dotorg_communication() ); } @@ -4895,10 +5170,10 @@ } if ( ! class_exists( 'WP_Site_Health' ) ) { - require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' ); - } - - $site_health = new WP_Site_Health(); + require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php'; + } + + $site_health = WP_Site_Health::get_instance(); wp_send_json_success( $site_health->get_test_is_in_debug_mode() ); } @@ -4915,14 +5190,13 @@ } if ( ! class_exists( 'WP_Site_Health' ) ) { - require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' ); - } - - $site_health = new WP_Site_Health(); + require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php'; + } + + $site_health = WP_Site_Health::get_instance(); wp_send_json_success( $site_health->get_test_background_updates() ); } - /** * Ajax handler for site health checks on loopback requests. * @@ -4936,10 +5210,10 @@ } if ( ! class_exists( 'WP_Site_Health' ) ) { - require_once( ABSPATH . 'wp-admin/includes/class-wp-site-health.php' ); - } - - $site_health = new WP_Site_Health(); + require_once ABSPATH . 'wp-admin/includes/class-wp-site-health.php'; + } + + $site_health = WP_Site_Health::get_instance(); wp_send_json_success( $site_health->get_test_loopback_requests() ); } @@ -4973,7 +5247,7 @@ } if ( ! class_exists( 'WP_Debug_Data' ) ) { - require_once( ABSPATH . 'wp-admin/includes/class-wp-debug-data.php' ); + require_once ABSPATH . 'wp-admin/includes/class-wp-debug-data.php'; } $sizes_data = WP_Debug_Data::get_sizes(); @@ -5012,3 +5286,82 @@ wp_send_json_success( $all_sizes ); } + +/** + * Ajax handler to renew the REST API nonce. + * + * @since 5.3.0 + */ +function wp_ajax_rest_nonce() { + exit( wp_create_nonce( 'wp_rest' ) ); +} + +/** + * Ajax handler to enable or disable plugin and theme auto-updates. + * + * @since 5.5.0 + */ +function wp_ajax_toggle_auto_updates() { + check_ajax_referer( 'updates' ); + + if ( empty( $_POST['type'] ) || empty( $_POST['asset'] ) || empty( $_POST['state'] ) ) { + wp_send_json_error( array( 'error' => __( 'Invalid data. No selected item.' ) ) ); + } + + $asset = sanitize_text_field( urldecode( $_POST['asset'] ) ); + + if ( 'enable' !== $_POST['state'] && 'disable' !== $_POST['state'] ) { + wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown state.' ) ) ); + } + $state = $_POST['state']; + + if ( 'plugin' !== $_POST['type'] && 'theme' !== $_POST['type'] ) { + wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) ); + } + $type = $_POST['type']; + + switch ( $type ) { + case 'plugin': + if ( ! current_user_can( 'update_plugins' ) ) { + $error_message = __( 'Sorry, you are not allowed to modify plugins.' ); + wp_send_json_error( array( 'error' => $error_message ) ); + } + + $option = 'auto_update_plugins'; + /** This filter is documented in wp-admin/includes/class-wp-plugins-list-table.php */ + $all_items = apply_filters( 'all_plugins', get_plugins() ); + break; + case 'theme': + if ( ! current_user_can( 'update_themes' ) ) { + $error_message = __( 'Sorry, you are not allowed to modify themes.' ); + wp_send_json_error( array( 'error' => $error_message ) ); + } + + $option = 'auto_update_themes'; + $all_items = wp_get_themes(); + break; + default: + wp_send_json_error( array( 'error' => __( 'Invalid data. Unknown type.' ) ) ); + } + + if ( ! array_key_exists( $asset, $all_items ) ) { + $error_message = __( 'Invalid data. The item does not exist.' ); + wp_send_json_error( array( 'error' => $error_message ) ); + } + + $auto_updates = (array) get_site_option( $option, array() ); + + if ( 'disable' === $state ) { + $auto_updates = array_diff( $auto_updates, array( $asset ) ); + } else { + $auto_updates[] = $asset; + $auto_updates = array_unique( $auto_updates ); + } + + // Remove items that have been deleted since the site option was last updated. + $auto_updates = array_intersect( $auto_updates, array_keys( $all_items ) ); + + update_site_option( $option, $auto_updates ); + + wp_send_json_success(); +}