3 * WordPress Core Ajax Handlers.
6 * @subpackage Administration
10 * No-privilege Ajax handlers.
14 * Heartbeat API (experimental)
16 * Runs when the user is not logged in.
18 function wp_ajax_nopriv_heartbeat() {
21 // screen_id is the same as $current_screen->id and the JS global 'pagenow'
22 if ( ! empty($_POST['screen_id']) )
23 $screen_id = sanitize_key($_POST['screen_id']);
27 if ( ! empty($_POST['data']) ) {
28 $data = wp_unslash( (array) $_POST['data'] );
29 $response = apply_filters( 'heartbeat_nopriv_received', $response, $data, $screen_id );
32 $response = apply_filters( 'heartbeat_nopriv_send', $response, $screen_id );
34 // Allow the transport to be replaced with long-polling easily
35 do_action( 'heartbeat_nopriv_tick', $response, $screen_id );
37 // send the current time according to the server
38 $response['server_time'] = time();
40 wp_send_json($response);
44 * GET-based Ajax handlers.
46 function wp_ajax_fetch_list() {
47 global $wp_list_table;
49 $list_class = $_GET['list_args']['class'];
50 check_ajax_referer( "fetch-list-$list_class", '_ajax_fetch_list_nonce' );
52 $wp_list_table = _get_list_table( $list_class, array( 'screen' => $_GET['list_args']['screen']['id'] ) );
53 if ( ! $wp_list_table )
56 if ( ! $wp_list_table->ajax_user_can() )
59 $wp_list_table->ajax_response();
63 function wp_ajax_ajax_tag_search() {
66 if ( isset( $_GET['tax'] ) ) {
67 $taxonomy = sanitize_key( $_GET['tax'] );
68 $tax = get_taxonomy( $taxonomy );
71 if ( ! current_user_can( $tax->cap->assign_terms ) )
77 $s = wp_unslash( $_GET['q'] );
79 $comma = _x( ',', 'tag delimiter' );
81 $s = str_replace( $comma, ',', $s );
82 if ( false !== strpos( $s, ',' ) ) {
83 $s = explode( ',', $s );
84 $s = $s[count( $s ) - 1];
87 if ( strlen( $s ) < 2 )
88 wp_die(); // require 2 chars for matching
90 $results = $wpdb->get_col( $wpdb->prepare( "SELECT t.name FROM $wpdb->term_taxonomy AS tt INNER JOIN $wpdb->terms AS t ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.name LIKE (%s)", $taxonomy, '%' . like_escape( $s ) . '%' ) );
92 echo join( $results, "\n" );
96 function wp_ajax_wp_compression_test() {
97 if ( !current_user_can( 'manage_options' ) )
100 if ( ini_get('zlib.output_compression') || 'ob_gzhandler' == ini_get('output_handler') ) {
101 update_site_option('can_compress_scripts', 0);
105 if ( isset($_GET['test']) ) {
106 header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
107 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
108 header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
109 header( 'Pragma: no-cache' );
110 header('Content-Type: application/x-javascript; charset=UTF-8');
111 $force_gzip = ( defined('ENFORCE_GZIP') && ENFORCE_GZIP );
112 $test_str = '"wpCompressionTest Lorem ipsum dolor sit amet consectetuer mollis sapien urna ut a. Eu nonummy condimentum fringilla tempor pretium platea vel nibh netus Maecenas. Hac molestie amet justo quis pellentesque est ultrices interdum nibh Morbi. Cras mattis pretium Phasellus ante ipsum ipsum ut sociis Suspendisse Lorem. Ante et non molestie. Porta urna Vestibulum egestas id congue nibh eu risus gravida sit. Ac augue auctor Ut et non a elit massa id sodales. Elit eu Nulla at nibh adipiscing mattis lacus mauris at tempus. Netus nibh quis suscipit nec feugiat eget sed lorem et urna. Pellentesque lacus at ut massa consectetuer ligula ut auctor semper Pellentesque. Ut metus massa nibh quam Curabitur molestie nec mauris congue. Volutpat molestie elit justo facilisis neque ac risus Ut nascetur tristique. Vitae sit lorem tellus et quis Phasellus lacus tincidunt nunc Fusce. Pharetra wisi Suspendisse mus sagittis libero lacinia Integer consequat ac Phasellus. Et urna ac cursus tortor aliquam Aliquam amet tellus volutpat Vestibulum. Justo interdum condimentum In augue congue tellus sollicitudin Quisque quis nibh."';
114 if ( 1 == $_GET['test'] ) {
117 } elseif ( 2 == $_GET['test'] ) {
118 if ( !isset($_SERVER['HTTP_ACCEPT_ENCODING']) )
120 if ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && function_exists('gzdeflate') && ! $force_gzip ) {
121 header('Content-Encoding: deflate');
122 $out = gzdeflate( $test_str, 1 );
123 } elseif ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode') ) {
124 header('Content-Encoding: gzip');
125 $out = gzencode( $test_str, 1 );
131 } elseif ( 'no' == $_GET['test'] ) {
132 update_site_option('can_compress_scripts', 0);
133 } elseif ( 'yes' == $_GET['test'] ) {
134 update_site_option('can_compress_scripts', 1);
141 function wp_ajax_imgedit_preview() {
142 $post_id = intval($_GET['postid']);
143 if ( empty($post_id) || !current_user_can('edit_post', $post_id) )
146 check_ajax_referer( "image_editor-$post_id" );
148 include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
149 if ( ! stream_preview_image($post_id) )
155 function wp_ajax_oembed_cache() {
158 $return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0';
162 function wp_ajax_autocomplete_user() {
163 if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) )
166 if ( ! is_super_admin() && ! apply_filters( 'autocomplete_users_for_site_admins', false ) )
171 // Check the type of request
172 if ( isset( $_REQUEST['autocomplete_type'] ) )
173 $type = $_REQUEST['autocomplete_type'];
177 // Exclude current users of this blog
178 if ( isset( $_REQUEST['site_id'] ) )
179 $id = absint( $_REQUEST['site_id'] );
181 $id = get_current_blog_id();
183 $include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
184 $exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
186 $users = get_users( array(
188 'search' => '*' . $_REQUEST['term'] . '*',
189 'include' => $include_blog_users,
190 'exclude' => $exclude_blog_users,
191 'search_columns' => array( 'user_login', 'user_nicename', 'user_email' ),
194 foreach ( $users as $user ) {
196 /* translators: 1: user_login, 2: user_email */
197 'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ),
198 'value' => $user->user_login,
202 wp_die( json_encode( $return ) );
205 function wp_ajax_dashboard_widgets() {
206 require_once ABSPATH . 'wp-admin/includes/dashboard.php';
208 switch ( $_GET['widget'] ) {
209 case 'dashboard_incoming_links' :
210 wp_dashboard_incoming_links();
212 case 'dashboard_primary' :
213 wp_dashboard_primary();
215 case 'dashboard_secondary' :
216 wp_dashboard_secondary();
218 case 'dashboard_plugins' :
219 wp_dashboard_plugins();
225 function wp_ajax_logged_in() {
234 * Sends back current comment total and new page links if they need to be updated.
236 * Contrary to normal success AJAX response ("1"), die with time() on success.
240 * @param int $comment_id
243 function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) {
244 $total = (int) @$_POST['_total'];
245 $per_page = (int) @$_POST['_per_page'];
246 $page = (int) @$_POST['_page'];
247 $url = esc_url_raw( @$_POST['_url'] );
248 // JS didn't send us everything we need to know. Just die with success message
249 if ( !$total || !$per_page || !$page || !$url )
256 // Only do the expensive stuff on a page-break, and about 1 other time per page
257 if ( 0 == $total % $per_page || 1 == mt_rand( 1, $per_page ) ) {
259 $status = 'total_comments'; // What type of comment count are we looking for?
260 $parsed = parse_url( $url );
261 if ( isset( $parsed['query'] ) ) {
262 parse_str( $parsed['query'], $query_vars );
263 if ( !empty( $query_vars['comment_status'] ) )
264 $status = $query_vars['comment_status'];
265 if ( !empty( $query_vars['p'] ) )
266 $post_id = (int) $query_vars['p'];
269 $comment_count = wp_count_comments($post_id);
271 if ( isset( $comment_count->$status ) ) // We're looking for a known type of comment count
272 $total = $comment_count->$status;
273 // else use the decremented value from above
276 $time = time(); // The time since the last comment count
278 $x = new WP_Ajax_Response( array(
280 'id' => $comment_id, // here for completeness - not used
281 'supplemental' => array(
282 'total_items_i18n' => sprintf( _n( '1 item', '%s items', $total ), number_format_i18n( $total ) ),
283 'total_pages' => ceil( $total / $per_page ),
284 'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ),
293 * POST-based Ajax handlers.
296 function _wp_ajax_add_hierarchical_term() {
297 $action = $_POST['action'];
298 $taxonomy = get_taxonomy(substr($action, 4));
299 check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
300 if ( !current_user_can( $taxonomy->cap->edit_terms ) )
302 $names = explode(',', $_POST['new'.$taxonomy->name]);
303 $parent = isset($_POST['new'.$taxonomy->name.'_parent']) ? (int) $_POST['new'.$taxonomy->name.'_parent'] : 0;
306 if ( $taxonomy->name == 'category' )
307 $post_category = isset($_POST['post_category']) ? (array) $_POST['post_category'] : array();
309 $post_category = ( isset($_POST['tax_input']) && isset($_POST['tax_input'][$taxonomy->name]) ) ? (array) $_POST['tax_input'][$taxonomy->name] : array();
310 $checked_categories = array_map( 'absint', (array) $post_category );
311 $popular_ids = wp_popular_terms_checklist($taxonomy->name, 0, 10, false);
313 foreach ( $names as $cat_name ) {
314 $cat_name = trim($cat_name);
315 $category_nicename = sanitize_title($cat_name);
316 if ( '' === $category_nicename )
318 if ( !$cat_id = term_exists( $cat_name, $taxonomy->name, $parent ) )
319 $cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) );
320 if ( is_wp_error( $cat_id ) )
322 else if ( is_array( $cat_id ) )
323 $cat_id = $cat_id['term_id'];
324 $checked_categories[] = $cat_id;
325 if ( $parent ) // Do these all at once in a second
328 wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name, 'descendants_and_self' => $cat_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids ));
329 $data = ob_get_contents();
332 'what' => $taxonomy->name,
334 'data' => str_replace( array("\n", "\t"), '', $data),
339 if ( $parent ) { // Foncy - replace the parent and all its children
340 $parent = get_term( $parent, $taxonomy->name );
341 $term_id = $parent->term_id;
343 while ( $parent->parent ) { // get the top parent
344 $parent = get_term( $parent->parent, $taxonomy->name );
345 if ( is_wp_error( $parent ) )
347 $term_id = $parent->term_id;
351 wp_terms_checklist( 0, array('taxonomy' => $taxonomy->name, 'descendants_and_self' => $term_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids));
352 $data = ob_get_contents();
355 'what' => $taxonomy->name,
357 'data' => str_replace( array("\n", "\t"), '', $data),
363 wp_dropdown_categories( array(
364 'taxonomy' => $taxonomy->name, 'hide_empty' => 0, 'name' => 'new'.$taxonomy->name.'_parent', 'orderby' => 'name',
365 'hierarchical' => 1, 'show_option_none' => '— '.$taxonomy->labels->parent_item.' —'
367 $sup = ob_get_contents();
369 $add['supplemental'] = array( 'newcat_parent' => $sup );
371 $x = new WP_Ajax_Response( $add );
375 function wp_ajax_delete_comment() {
376 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
378 if ( !$comment = get_comment( $id ) )
380 if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) )
383 check_ajax_referer( "delete-comment_$id" );
384 $status = wp_get_comment_status( $comment->comment_ID );
387 if ( isset($_POST['trash']) && 1 == $_POST['trash'] ) {
388 if ( 'trash' == $status )
390 $r = wp_trash_comment( $comment->comment_ID );
391 } elseif ( isset($_POST['untrash']) && 1 == $_POST['untrash'] ) {
392 if ( 'trash' != $status )
394 $r = wp_untrash_comment( $comment->comment_ID );
395 if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'trash' ) // undo trash, not in trash
397 } elseif ( isset($_POST['spam']) && 1 == $_POST['spam'] ) {
398 if ( 'spam' == $status )
400 $r = wp_spam_comment( $comment->comment_ID );
401 } elseif ( isset($_POST['unspam']) && 1 == $_POST['unspam'] ) {
402 if ( 'spam' != $status )
404 $r = wp_unspam_comment( $comment->comment_ID );
405 if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'spam' ) // undo spam, not in spam
407 } elseif ( isset($_POST['delete']) && 1 == $_POST['delete'] ) {
408 $r = wp_delete_comment( $comment->comment_ID );
413 if ( $r ) // Decide if we need to send back '1' or a more complicated response including page links and comment counts
414 _wp_ajax_delete_comment_response( $comment->comment_ID, $delta );
418 function wp_ajax_delete_tag() {
419 $tag_id = (int) $_POST['tag_ID'];
420 check_ajax_referer( "delete-tag_$tag_id" );
422 $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
423 $tax = get_taxonomy($taxonomy);
425 if ( !current_user_can( $tax->cap->delete_terms ) )
428 $tag = get_term( $tag_id, $taxonomy );
429 if ( !$tag || is_wp_error( $tag ) )
432 if ( wp_delete_term($tag_id, $taxonomy))
438 function wp_ajax_delete_link() {
439 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
441 check_ajax_referer( "delete-bookmark_$id" );
442 if ( !current_user_can( 'manage_links' ) )
445 $link = get_bookmark( $id );
446 if ( !$link || is_wp_error( $link ) )
449 if ( wp_delete_link( $id ) )
455 function wp_ajax_delete_meta() {
456 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
458 check_ajax_referer( "delete-meta_$id" );
459 if ( !$meta = get_metadata_by_mid( 'post', $id ) )
462 if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $meta->post_id, $meta->meta_key ) )
464 if ( delete_meta( $meta->meta_id ) )
469 function wp_ajax_delete_post( $action ) {
470 if ( empty( $action ) )
471 $action = 'delete-post';
472 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
474 check_ajax_referer( "{$action}_$id" );
475 if ( !current_user_can( 'delete_post', $id ) )
478 if ( !get_post( $id ) )
481 if ( wp_delete_post( $id ) )
487 function wp_ajax_trash_post( $action ) {
488 if ( empty( $action ) )
489 $action = 'trash-post';
490 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
492 check_ajax_referer( "{$action}_$id" );
493 if ( !current_user_can( 'delete_post', $id ) )
496 if ( !get_post( $id ) )
499 if ( 'trash-post' == $action )
500 $done = wp_trash_post( $id );
502 $done = wp_untrash_post( $id );
510 function wp_ajax_untrash_post( $action ) {
511 if ( empty( $action ) )
512 $action = 'untrash-post';
513 wp_ajax_trash_post( $action );
516 function wp_ajax_delete_page( $action ) {
517 if ( empty( $action ) )
518 $action = 'delete-page';
519 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
521 check_ajax_referer( "{$action}_$id" );
522 if ( !current_user_can( 'delete_page', $id ) )
525 if ( ! get_post( $id ) )
528 if ( wp_delete_post( $id ) )
534 function wp_ajax_dim_comment() {
535 $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
537 if ( !$comment = get_comment( $id ) ) {
538 $x = new WP_Ajax_Response( array(
540 'id' => new WP_Error('invalid_comment', sprintf(__('Comment %d does not exist'), $id))
545 if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) && ! current_user_can( 'moderate_comments' ) )
548 $current = wp_get_comment_status( $comment->comment_ID );
549 if ( $_POST['new'] == $current )
552 check_ajax_referer( "approve-comment_$id" );
553 if ( in_array( $current, array( 'unapproved', 'spam' ) ) )
554 $result = wp_set_comment_status( $comment->comment_ID, 'approve', true );
556 $result = wp_set_comment_status( $comment->comment_ID, 'hold', true );
558 if ( is_wp_error($result) ) {
559 $x = new WP_Ajax_Response( array(
566 // Decide if we need to send back '1' or a more complicated response including page links and comment counts
567 _wp_ajax_delete_comment_response( $comment->comment_ID );
571 function wp_ajax_add_link_category( $action ) {
572 if ( empty( $action ) )
573 $action = 'add-link-category';
574 check_ajax_referer( $action );
575 if ( !current_user_can( 'manage_categories' ) )
577 $names = explode(',', wp_unslash( $_POST['newcat'] ) );
578 $x = new WP_Ajax_Response();
579 foreach ( $names as $cat_name ) {
580 $cat_name = trim($cat_name);
581 $slug = sanitize_title($cat_name);
584 if ( !$cat_id = term_exists( $cat_name, 'link_category' ) )
585 $cat_id = wp_insert_term( $cat_name, 'link_category' );
586 if ( is_wp_error( $cat_id ) )
588 else if ( is_array( $cat_id ) )
589 $cat_id = $cat_id['term_id'];
590 $cat_name = esc_html( $cat_name );
592 'what' => 'link-category',
594 'data' => "<li id='link-category-$cat_id'><label for='in-link-category-$cat_id' class='selectit'><input value='" . esc_attr($cat_id) . "' type='checkbox' checked='checked' name='link_category[]' id='in-link-category-$cat_id'/> $cat_name</label></li>",
601 function wp_ajax_add_tag() {
602 global $wp_list_table;
604 check_ajax_referer( 'add-tag', '_wpnonce_add-tag' );
605 $post_type = !empty($_POST['post_type']) ? $_POST['post_type'] : 'post';
606 $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
607 $tax = get_taxonomy($taxonomy);
609 if ( !current_user_can( $tax->cap->edit_terms ) )
612 $x = new WP_Ajax_Response();
614 $tag = wp_insert_term($_POST['tag-name'], $taxonomy, $_POST );
616 if ( !$tag || is_wp_error($tag) || (!$tag = get_term( $tag['term_id'], $taxonomy )) ) {
617 $message = __('An error has occurred. Please reload the page and try again.');
618 if ( is_wp_error($tag) && $tag->get_error_message() )
619 $message = $tag->get_error_message();
622 'what' => 'taxonomy',
623 'data' => new WP_Error('error', $message )
628 $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
631 if ( is_taxonomy_hierarchical($taxonomy) ) {
632 $level = count( get_ancestors( $tag->term_id, $taxonomy ) );
634 $wp_list_table->single_row( $tag, $level );
635 $noparents = ob_get_clean();
639 $wp_list_table->single_row( $tag );
640 $parents = ob_get_clean();
643 'what' => 'taxonomy',
644 'supplemental' => compact('parents', 'noparents')
648 'position' => $level,
649 'supplemental' => (array) $tag
654 function wp_ajax_get_tagcloud() {
655 if ( isset( $_POST['tax'] ) ) {
656 $taxonomy = sanitize_key( $_POST['tax'] );
657 $tax = get_taxonomy( $taxonomy );
660 if ( ! current_user_can( $tax->cap->assign_terms ) )
666 $tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) );
668 if ( empty( $tags ) )
669 wp_die( $tax->labels->not_found );
671 if ( is_wp_error( $tags ) )
672 wp_die( $tags->get_error_message() );
674 foreach ( $tags as $key => $tag ) {
675 $tags[ $key ]->link = '#';
676 $tags[ $key ]->id = $tag->term_id;
679 // We need raw tag names here, so don't filter the output
680 $return = wp_generate_tag_cloud( $tags, array('filter' => 0) );
682 if ( empty($return) )
690 function wp_ajax_get_comments( $action ) {
691 global $wp_list_table, $post_id;
692 if ( empty( $action ) )
693 $action = 'get-comments';
695 check_ajax_referer( $action );
697 $wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
699 if ( !current_user_can( 'edit_post', $post_id ) )
702 $wp_list_table->prepare_items();
704 if ( !$wp_list_table->has_items() )
707 $x = new WP_Ajax_Response();
709 foreach ( $wp_list_table->items as $comment ) {
710 if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) )
712 get_comment( $comment );
713 $wp_list_table->single_row( $comment );
715 $comment_list_item = ob_get_contents();
719 'what' => 'comments',
720 'data' => $comment_list_item
725 function wp_ajax_replyto_comment( $action ) {
726 global $wp_list_table, $wpdb;
727 if ( empty( $action ) )
728 $action = 'replyto-comment';
730 check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );
732 $comment_post_ID = (int) $_POST['comment_post_ID'];
733 $post = get_post( $comment_post_ID );
737 if ( !current_user_can( 'edit_post', $comment_post_ID ) )
740 if ( empty( $post->post_status ) )
742 elseif ( in_array($post->post_status, array('draft', 'pending', 'trash') ) )
743 wp_die( __('ERROR: you are replying to a comment on a draft post.') );
745 $user = wp_get_current_user();
746 if ( $user->exists() ) {
747 $user_ID = $user->ID;
748 $comment_author = wp_slash( $user->display_name );
749 $comment_author_email = wp_slash( $user->user_email );
750 $comment_author_url = wp_slash( $user->user_url );
751 $comment_content = trim($_POST['content']);
752 if ( current_user_can( 'unfiltered_html' ) ) {
753 if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) {
754 kses_remove_filters(); // start with a clean slate
755 kses_init_filters(); // set up the filters
759 wp_die( __( 'Sorry, you must be logged in to reply to a comment.' ) );
762 if ( '' == $comment_content )
763 wp_die( __( 'ERROR: please type a comment.' ) );
765 $comment_parent = absint($_POST['comment_ID']);
766 $comment_auto_approved = false;
767 $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
769 // automatically approve parent comment
770 if ( !empty($_POST['approve_parent']) ) {
771 $parent = get_comment( $comment_parent );
773 if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) {
774 if ( wp_set_comment_status( $parent->comment_ID, 'approve' ) )
775 $comment_auto_approved = true;
779 $comment_id = wp_new_comment( $commentdata );
780 $comment = get_comment($comment_id);
781 if ( ! $comment ) wp_die( 1 );
783 $position = ( isset($_POST['position']) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1';
786 if ( 'dashboard' == $_REQUEST['mode'] ) {
787 require_once( ABSPATH . 'wp-admin/includes/dashboard.php' );
788 _wp_dashboard_recent_comments_row( $comment );
790 if ( 'single' == $_REQUEST['mode'] ) {
791 $wp_list_table = _get_list_table('WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
793 $wp_list_table = _get_list_table('WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
795 $wp_list_table->single_row( $comment );
797 $comment_list_item = ob_get_contents();
802 'id' => $comment->comment_ID,
803 'data' => $comment_list_item,
804 'position' => $position
807 if ( $comment_auto_approved )
808 $response['supplemental'] = array( 'parent_approved' => $parent->comment_ID );
810 $x = new WP_Ajax_Response();
811 $x->add( $response );
815 function wp_ajax_edit_comment() {
816 global $wp_list_table;
818 check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' );
820 $comment_id = (int) $_POST['comment_ID'];
821 if ( ! current_user_can( 'edit_comment', $comment_id ) )
824 if ( '' == $_POST['content'] )
825 wp_die( __( 'ERROR: please type a comment.' ) );
827 $_POST['comment_status'] = $_POST['status'];
830 $position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1';
831 $comments_status = isset($_POST['comments_listing']) ? $_POST['comments_listing'] : '';
833 $checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0;
834 $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
836 $comment = get_comment( $comment_id );
839 $wp_list_table->single_row( $comment );
840 $comment_list_item = ob_get_contents();
843 $x = new WP_Ajax_Response();
846 'what' => 'edit_comment',
847 'id' => $comment->comment_ID,
848 'data' => $comment_list_item,
849 'position' => $position
855 function wp_ajax_add_menu_item() {
856 check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
858 if ( ! current_user_can( 'edit_theme_options' ) )
861 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
863 // For performance reasons, we omit some object properties from the checklist.
864 // The following is a hacky way to restore them when adding non-custom items.
866 $menu_items_data = array();
867 foreach ( (array) $_POST['menu-item'] as $menu_item_data ) {
869 ! empty( $menu_item_data['menu-item-type'] ) &&
870 'custom' != $menu_item_data['menu-item-type'] &&
871 ! empty( $menu_item_data['menu-item-object-id'] )
873 switch( $menu_item_data['menu-item-type'] ) {
875 $_object = get_post( $menu_item_data['menu-item-object-id'] );
879 $_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
883 $_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
884 $_menu_item = array_shift( $_menu_items );
886 // Restore the missing menu item properties
887 $menu_item_data['menu-item-description'] = $_menu_item->description;
890 $menu_items_data[] = $menu_item_data;
893 $item_ids = wp_save_nav_menu_items( 0, $menu_items_data );
894 if ( is_wp_error( $item_ids ) )
897 $menu_items = array();
899 foreach ( (array) $item_ids as $menu_item_id ) {
900 $menu_obj = get_post( $menu_item_id );
901 if ( ! empty( $menu_obj->ID ) ) {
902 $menu_obj = wp_setup_nav_menu_item( $menu_obj );
903 $menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items
904 $menu_items[] = $menu_obj;
908 $walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] );
910 if ( ! class_exists( $walker_class_name ) )
913 if ( ! empty( $menu_items ) ) {
919 'walker' => new $walker_class_name,
921 echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
926 function wp_ajax_add_meta() {
927 check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' );
929 $pid = (int) $_POST['post_id'];
930 $post = get_post( $pid );
932 if ( isset($_POST['metakeyselect']) || isset($_POST['metakeyinput']) ) {
933 if ( !current_user_can( 'edit_post', $pid ) )
935 if ( isset($_POST['metakeyselect']) && '#NONE#' == $_POST['metakeyselect'] && empty($_POST['metakeyinput']) )
937 if ( $post->post_status == 'auto-draft' ) {
938 $save_POST = $_POST; // Backup $_POST
939 $_POST = array(); // Make it empty for edit_post()
940 $_POST['action'] = 'draft'; // Warning fix
941 $_POST['post_ID'] = $pid;
942 $_POST['post_type'] = $post->post_type;
943 $_POST['post_status'] = 'draft';
944 $now = current_time('timestamp', 1);
945 $_POST['post_title'] = sprintf( __( 'Draft created on %1$s at %2$s' ), date( get_option( 'date_format' ), $now ), date( get_option( 'time_format' ), $now ) );
947 if ( $pid = edit_post() ) {
948 if ( is_wp_error( $pid ) ) {
949 $x = new WP_Ajax_Response( array(
955 $_POST = $save_POST; // Now we can restore original $_POST again
956 if ( !$mid = add_meta( $pid ) )
957 wp_die( __( 'Please provide a custom field value.' ) );
961 } else if ( !$mid = add_meta( $pid ) ) {
962 wp_die( __( 'Please provide a custom field value.' ) );
965 $meta = get_metadata_by_mid( 'post', $mid );
966 $pid = (int) $meta->post_id;
967 $meta = get_object_vars( $meta );
968 $x = new WP_Ajax_Response( array(
971 'data' => _list_meta_row( $meta, $c ),
973 'supplemental' => array('postid' => $pid)
976 $mid = (int) key( $_POST['meta'] );
977 $key = wp_unslash( $_POST['meta'][$mid]['key'] );
978 $value = wp_unslash( $_POST['meta'][$mid]['value'] );
979 if ( '' == trim($key) )
980 wp_die( __( 'Please provide a custom field name.' ) );
981 if ( '' == trim($value) )
982 wp_die( __( 'Please provide a custom field value.' ) );
983 if ( ! $meta = get_metadata_by_mid( 'post', $mid ) )
984 wp_die( 0 ); // if meta doesn't exist
985 if ( is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) ||
986 ! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) ||
987 ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) )
989 if ( $meta->meta_value != $value || $meta->meta_key != $key ) {
990 if ( !$u = update_metadata_by_mid( 'post', $mid, $value, $key ) )
991 wp_die( 0 ); // We know meta exists; we also know it's unchanged (or DB error, in which case there are bigger problems).
994 $x = new WP_Ajax_Response( array(
996 'id' => $mid, 'old_id' => $mid,
997 'data' => _list_meta_row( array(
999 'meta_value' => $value,
1003 'supplemental' => array('postid' => $meta->post_id)
1009 function wp_ajax_add_user( $action ) {
1010 global $wp_list_table;
1011 if ( empty( $action ) )
1012 $action = 'add-user';
1014 check_ajax_referer( $action );
1015 if ( ! current_user_can('create_users') )
1017 if ( ! $user_id = edit_user() ) {
1019 } elseif ( is_wp_error( $user_id ) ) {
1020 $x = new WP_Ajax_Response( array(
1026 $user_object = get_userdata( $user_id );
1028 $wp_list_table = _get_list_table('WP_Users_List_Table');
1030 $role = current( $user_object->roles );
1032 $x = new WP_Ajax_Response( array(
1035 'data' => $wp_list_table->single_row( $user_object, '', $role ),
1036 'supplemental' => array(
1037 'show-link' => sprintf(__( 'User <a href="#%s">%s</a> added' ), "user-$user_id", $user_object->user_login),
1044 function wp_ajax_autosave() {
1045 define( 'DOING_AUTOSAVE', true );
1047 check_ajax_referer( 'autosave', 'autosavenonce' );
1049 $_POST['post_category'] = explode(",", $_POST['catslist']);
1050 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1051 unset($_POST['post_category']);
1054 $supplemental = array();
1055 $id = $revision_id = 0;
1057 $post_id = (int) $_POST['post_id'];
1058 $_POST['ID'] = $_POST['post_ID'] = $post_id;
1059 $post = get_post($post_id);
1060 if ( 'auto-draft' == $post->post_status )
1061 $_POST['post_status'] = 'draft';
1063 if ( 'page' == $post->post_type ) {
1064 if ( !current_user_can('edit_page', $post->ID) )
1065 wp_die( __( 'You are not allowed to edit this page.' ) );
1067 if ( !current_user_can('edit_post', $post->ID) )
1068 wp_die( __( 'You are not allowed to edit this post.' ) );
1071 if ( ! empty( $_POST['autosave'] ) ) {
1072 if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
1073 // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked
1076 // Non drafts or other users drafts are not overwritten. The autosave is stored in a special post revision for each user.
1077 $revision_id = wp_create_post_autosave( $post->ID );
1078 if ( is_wp_error($revision_id) )
1084 if ( ! is_wp_error($id) ) {
1085 /* translators: draft saved date format, see http://php.net/date */
1086 $draft_saved_date_format = __('g:i:s a');
1087 /* translators: %s: date and time */
1088 $data = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
1091 if ( ! empty( $_POST['auto_draft'] ) )
1092 $id = 0; // This tells us it didn't actually save
1097 // @todo Consider exposing any errors, rather than having 'Saving draft...'
1098 $x = new WP_Ajax_Response( array(
1099 'what' => 'autosave',
1102 'supplemental' => $supplemental
1107 function wp_ajax_closed_postboxes() {
1108 check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
1109 $closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array();
1110 $closed = array_filter($closed);
1112 $hidden = isset( $_POST['hidden'] ) ? explode( ',', $_POST['hidden']) : array();
1113 $hidden = array_filter($hidden);
1115 $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1117 if ( $page != sanitize_key( $page ) )
1120 if ( ! $user = wp_get_current_user() )
1123 if ( is_array($closed) )
1124 update_user_option($user->ID, "closedpostboxes_$page", $closed, true);
1126 if ( is_array($hidden) ) {
1127 $hidden = array_diff( $hidden, array('submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu') ); // postboxes that are always shown
1128 update_user_option($user->ID, "metaboxhidden_$page", $hidden, true);
1134 function wp_ajax_hidden_columns() {
1135 check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' );
1136 $hidden = isset( $_POST['hidden'] ) ? $_POST['hidden'] : '';
1137 $hidden = explode( ',', $_POST['hidden'] );
1138 $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1140 if ( $page != sanitize_key( $page ) )
1143 if ( ! $user = wp_get_current_user() )
1146 if ( is_array($hidden) )
1147 update_user_option($user->ID, "manage{$page}columnshidden", $hidden, true);
1152 function wp_ajax_update_welcome_panel() {
1153 check_ajax_referer( 'welcome-panel-nonce', 'welcomepanelnonce' );
1155 if ( ! current_user_can( 'edit_theme_options' ) )
1158 update_user_meta( get_current_user_id(), 'show_welcome_panel', empty( $_POST['visible'] ) ? 0 : 1 );
1163 function wp_ajax_menu_get_metabox() {
1164 if ( ! current_user_can( 'edit_theme_options' ) )
1167 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
1169 if ( isset( $_POST['item-type'] ) && 'post_type' == $_POST['item-type'] ) {
1171 $callback = 'wp_nav_menu_item_post_type_meta_box';
1172 $items = (array) get_post_types( array( 'show_in_nav_menus' => true ), 'object' );
1173 } elseif ( isset( $_POST['item-type'] ) && 'taxonomy' == $_POST['item-type'] ) {
1175 $callback = 'wp_nav_menu_item_taxonomy_meta_box';
1176 $items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' );
1179 if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) {
1180 $item = apply_filters( 'nav_menu_meta_box_object', $items[ $_POST['item-object'] ] );
1182 call_user_func_array($callback, array(
1185 'id' => 'add-' . $item->name,
1186 'title' => $item->labels->name,
1187 'callback' => $callback,
1192 $markup = ob_get_clean();
1194 echo json_encode(array(
1195 'replace-id' => $type . '-' . $item->name,
1196 'markup' => $markup,
1203 function wp_ajax_wp_link_ajax() {
1204 check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' );
1208 if ( isset( $_POST['search'] ) )
1209 $args['s'] = wp_unslash( $_POST['search'] );
1210 $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
1212 require(ABSPATH . WPINC . '/class-wp-editor.php');
1213 $results = _WP_Editors::wp_link_query( $args );
1215 if ( ! isset( $results ) )
1218 echo json_encode( $results );
1224 function wp_ajax_menu_locations_save() {
1225 if ( ! current_user_can( 'edit_theme_options' ) )
1227 check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
1228 if ( ! isset( $_POST['menu-locations'] ) )
1230 set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) );
1234 function wp_ajax_meta_box_order() {
1235 check_ajax_referer( 'meta-box-order' );
1236 $order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false;
1237 $page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto';
1239 if ( $page_columns != 'auto' )
1240 $page_columns = (int) $page_columns;
1242 $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1244 if ( $page != sanitize_key( $page ) )
1247 if ( ! $user = wp_get_current_user() )
1251 update_user_option($user->ID, "meta-box-order_$page", $order, true);
1253 if ( $page_columns )
1254 update_user_option($user->ID, "screen_layout_$page", $page_columns, true);
1259 function wp_ajax_menu_quick_search() {
1260 if ( ! current_user_can( 'edit_theme_options' ) )
1263 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
1265 _wp_ajax_menu_quick_search( $_POST );
1270 function wp_ajax_get_permalink() {
1271 check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
1272 $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
1273 wp_die( add_query_arg( array( 'preview' => 'true' ), get_permalink( $post_id ) ) );
1276 function wp_ajax_sample_permalink() {
1277 check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' );
1278 $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
1279 $title = isset($_POST['new_title'])? $_POST['new_title'] : '';
1280 $slug = isset($_POST['new_slug'])? $_POST['new_slug'] : null;
1281 wp_die( get_sample_permalink_html( $post_id, $title, $slug ) );
1284 function wp_ajax_inline_save() {
1285 global $wp_list_table;
1287 check_ajax_referer( 'inlineeditnonce', '_inline_edit' );
1289 if ( ! isset($_POST['post_ID']) || ! ( $post_ID = (int) $_POST['post_ID'] ) )
1292 if ( 'page' == $_POST['post_type'] ) {
1293 if ( ! current_user_can( 'edit_page', $post_ID ) )
1294 wp_die( __( 'You are not allowed to edit this page.' ) );
1296 if ( ! current_user_can( 'edit_post', $post_ID ) )
1297 wp_die( __( 'You are not allowed to edit this post.' ) );
1300 if ( $last = wp_check_post_lock( $post_ID ) ) {
1301 $last_user = get_userdata( $last );
1302 $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
1303 printf( $_POST['post_type'] == 'page' ? __( 'Saving is disabled: %s is currently editing this page.' ) : __( 'Saving is disabled: %s is currently editing this post.' ), esc_html( $last_user_name ) );
1309 $post = get_post( $post_ID, ARRAY_A );
1310 $post = wp_slash($post); //since it is from db
1312 $data['content'] = $post['post_content'];
1313 $data['excerpt'] = $post['post_excerpt'];
1316 $data['user_ID'] = $GLOBALS['user_ID'];
1318 if ( isset($data['post_parent']) )
1319 $data['parent_id'] = $data['post_parent'];
1322 if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
1323 $data['post_status'] = 'private';
1325 $data['post_status'] = $data['_status'];
1327 if ( empty($data['comment_status']) )
1328 $data['comment_status'] = 'closed';
1329 if ( empty($data['ping_status']) )
1330 $data['ping_status'] = 'closed';
1332 // Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published.
1333 if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) {
1334 $post['post_status'] = 'publish';
1335 $data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] );
1341 $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
1343 $mode = $_POST['post_view'];
1346 $request_post = array( get_post( $_POST['post_ID'] ) );
1347 $parent = $request_post[0]->post_parent;
1349 while ( $parent > 0 ) {
1350 $parent_post = get_post( $parent );
1351 $parent = $parent_post->post_parent;
1355 $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level );
1360 function wp_ajax_inline_save_tax() {
1361 global $wp_list_table;
1363 check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
1365 $taxonomy = sanitize_key( $_POST['taxonomy'] );
1366 $tax = get_taxonomy( $taxonomy );
1370 if ( ! current_user_can( $tax->cap->edit_terms ) )
1373 $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => 'edit-' . $taxonomy ) );
1375 if ( ! isset($_POST['tax_ID']) || ! ( $id = (int) $_POST['tax_ID'] ) )
1378 $tag = get_term( $id, $taxonomy );
1379 $_POST['description'] = $tag->description;
1381 $updated = wp_update_term($id, $taxonomy, $_POST);
1382 if ( $updated && !is_wp_error($updated) ) {
1383 $tag = get_term( $updated['term_id'], $taxonomy );
1384 if ( !$tag || is_wp_error( $tag ) ) {
1385 if ( is_wp_error($tag) && $tag->get_error_message() )
1386 wp_die( $tag->get_error_message() );
1387 wp_die( __( 'Item not updated.' ) );
1390 if ( is_wp_error($updated) && $updated->get_error_message() )
1391 wp_die( $updated->get_error_message() );
1392 wp_die( __( 'Item not updated.' ) );
1395 $parent = $tag->parent;
1396 while ( $parent > 0 ) {
1397 $parent_tag = get_term( $parent, $taxonomy );
1398 $parent = $parent_tag->parent;
1401 $wp_list_table->single_row( $tag, $level );
1405 function wp_ajax_find_posts() {
1408 check_ajax_referer( 'find-posts' );
1410 $post_types = get_post_types( array( 'public' => true ), 'objects' );
1411 unset( $post_types['attachment'] );
1413 $s = wp_unslash( $_POST['ps'] );
1414 $searchand = $search = '';
1416 'post_type' => array_keys( $post_types ),
1417 'post_status' => 'any',
1418 'posts_per_page' => 50,
1423 $posts = get_posts( $args );
1426 wp_die( __('No items found.') );
1428 $html = '<table class="widefat" cellspacing="0"><thead><tr><th class="found-radio"><br /></th><th>'.__('Title').'</th><th class="no-break">'.__('Type').'</th><th class="no-break">'.__('Date').'</th><th class="no-break">'.__('Status').'</th></tr></thead><tbody>';
1429 foreach ( $posts as $post ) {
1430 $title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' );
1432 switch ( $post->post_status ) {
1435 $stat = __('Published');
1438 $stat = __('Scheduled');
1441 $stat = __('Pending Review');
1444 $stat = __('Draft');
1448 if ( '0000-00-00 00:00:00' == $post->post_date ) {
1451 /* translators: date format in table columns, see http://php.net/date */
1452 $time = mysql2date(__('Y/m/d'), $post->post_date);
1455 $html .= '<tr class="found-posts"><td class="found-radio"><input type="radio" id="found-'.$post->ID.'" name="found_post_id" value="' . esc_attr($post->ID) . '"></td>';
1456 $html .= '<td><label for="found-'.$post->ID.'">' . esc_html( $title ) . '</label></td><td class="no-break">' . esc_html( $post_types[$post->post_type]->labels->singular_name ) . '</td><td class="no-break">'.esc_html( $time ) . '</td><td class="no-break">' . esc_html( $stat ). ' </td></tr>' . "\n\n";
1459 $html .= '</tbody></table>';
1461 $x = new WP_Ajax_Response();
1468 function wp_ajax_widgets_order() {
1469 check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
1471 if ( !current_user_can('edit_theme_options') )
1474 unset( $_POST['savewidgets'], $_POST['action'] );
1476 // save widgets order for all sidebars
1477 if ( is_array($_POST['sidebars']) ) {
1478 $sidebars = array();
1479 foreach ( $_POST['sidebars'] as $key => $val ) {
1481 if ( !empty($val) ) {
1482 $val = explode(',', $val);
1483 foreach ( $val as $k => $v ) {
1484 if ( strpos($v, 'widget-') === false )
1487 $sb[$k] = substr($v, strpos($v, '_') + 1);
1490 $sidebars[$key] = $sb;
1492 wp_set_sidebars_widgets($sidebars);
1499 function wp_ajax_save_widget() {
1500 global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
1502 check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
1504 if ( !current_user_can('edit_theme_options') || !isset($_POST['id_base']) )
1507 unset( $_POST['savewidgets'], $_POST['action'] );
1509 do_action('load-widgets.php');
1510 do_action('widgets.php');
1511 do_action('sidebar_admin_setup');
1513 $id_base = $_POST['id_base'];
1514 $widget_id = $_POST['widget-id'];
1515 $sidebar_id = $_POST['sidebar'];
1516 $multi_number = !empty($_POST['multi_number']) ? (int) $_POST['multi_number'] : 0;
1517 $settings = isset($_POST['widget-' . $id_base]) && is_array($_POST['widget-' . $id_base]) ? $_POST['widget-' . $id_base] : false;
1518 $error = '<p>' . __('An error has occurred. Please reload the page and try again.') . '</p>';
1520 $sidebars = wp_get_sidebars_widgets();
1521 $sidebar = isset($sidebars[$sidebar_id]) ? $sidebars[$sidebar_id] : array();
1524 if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
1526 if ( !isset($wp_registered_widgets[$widget_id]) )
1529 $sidebar = array_diff( $sidebar, array($widget_id) );
1530 $_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1');
1531 } elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) {
1532 if ( !$multi_number )
1535 $_POST['widget-' . $id_base] = array( $multi_number => array_shift($settings) );
1536 $widget_id = $id_base . '-' . $multi_number;
1537 $sidebar[] = $widget_id;
1539 $_POST['widget-id'] = $sidebar;
1541 foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
1543 if ( $name == $id_base ) {
1544 if ( !is_callable( $control['callback'] ) )
1548 call_user_func_array( $control['callback'], $control['params'] );
1554 if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
1555 $sidebars[$sidebar_id] = $sidebar;
1556 wp_set_sidebars_widgets($sidebars);
1557 echo "deleted:$widget_id";
1561 if ( !empty($_POST['add_new']) )
1564 if ( $form = $wp_registered_widget_controls[$widget_id] )
1565 call_user_func_array( $form['callback'], $form['params'] );
1570 function wp_ajax_upload_attachment() {
1571 check_ajax_referer( 'media-form' );
1573 if ( ! current_user_can( 'upload_files' ) )
1576 if ( isset( $_REQUEST['post_id'] ) ) {
1577 $post_id = $_REQUEST['post_id'];
1578 if ( ! current_user_can( 'edit_post', $post_id ) )
1584 $post_data = isset( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array();
1586 // If the context is custom header or background, make sure the uploaded file is an image.
1587 if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) {
1588 $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false );
1589 if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
1590 echo json_encode( array(
1593 'message' => __( 'The uploaded file is not a valid image. Please try again.' ),
1594 'filename' => $_FILES['async-upload']['name'],
1602 $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data );
1604 if ( is_wp_error( $attachment_id ) ) {
1605 echo json_encode( array(
1608 'message' => $attachment_id->get_error_message(),
1609 'filename' => $_FILES['async-upload']['name'],
1616 if ( isset( $post_data['context'] ) && isset( $post_data['theme'] ) ) {
1617 if ( 'custom-background' === $post_data['context'] )
1618 update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', $post_data['theme'] );
1620 if ( 'custom-header' === $post_data['context'] )
1621 update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', $post_data['theme'] );
1624 if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) )
1627 echo json_encode( array(
1629 'data' => $attachment,
1635 function wp_ajax_image_editor() {
1636 $attachment_id = intval($_POST['postid']);
1637 if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) )
1640 check_ajax_referer( "image_editor-$attachment_id" );
1641 include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
1644 switch ( $_POST['do'] ) {
1646 $msg = wp_save_image($attachment_id);
1647 $msg = json_encode($msg);
1651 $msg = wp_save_image($attachment_id);
1654 $msg = wp_restore_image($attachment_id);
1658 wp_image_editor($attachment_id, $msg);
1662 function wp_ajax_set_post_thumbnail() {
1663 $json = ! empty( $_REQUEST['json'] ); // New-style request
1665 $post_ID = intval( $_POST['post_id'] );
1666 if ( ! current_user_can( 'edit_post', $post_ID ) )
1669 $thumbnail_id = intval( $_POST['thumbnail_id'] );
1672 check_ajax_referer( "update-post_$post_ID" );
1674 check_ajax_referer( "set_post_thumbnail-$post_ID" );
1676 if ( $thumbnail_id == '-1' ) {
1677 if ( delete_post_thumbnail( $post_ID ) ) {
1678 $return = _wp_post_thumbnail_html( null, $post_ID );
1679 $json ? wp_send_json_success( $return ) : wp_die( $return );
1685 if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) {
1686 $return = _wp_post_thumbnail_html( $thumbnail_id, $post_ID );
1687 $json ? wp_send_json_success( $return ) : wp_die( $return );
1693 function wp_ajax_date_format() {
1694 wp_die( date_i18n( sanitize_option( 'date_format', $_POST['date'] ) ) );
1697 function wp_ajax_time_format() {
1698 wp_die( date_i18n( sanitize_option( 'time_format', $_POST['date'] ) ) );
1701 function wp_ajax_wp_fullscreen_save_post() {
1702 $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
1704 $post = $post_type = null;
1707 $post = get_post( $post_id );
1710 $post_type = $post->post_type;
1711 elseif ( isset( $_POST['post_type'] ) && post_type_exists( $_POST['post_type'] ) )
1712 $post_type = $_POST['post_type'];
1714 check_ajax_referer('update-post_' . $post_id, '_wpnonce');
1716 $post_id = edit_post();
1718 if ( is_wp_error($post_id) ) {
1719 if ( $post_id->get_error_message() )
1720 $message = $post_id->get_error_message();
1722 $message = __('Save failed');
1724 echo json_encode( array( 'message' => $message, 'last_edited' => '' ) );
1727 $message = __('Saved.');
1731 $last_date = mysql2date( get_option('date_format'), $post->post_modified );
1732 $last_time = mysql2date( get_option('time_format'), $post->post_modified );
1734 $last_date = date_i18n( get_option('date_format') );
1735 $last_time = date_i18n( get_option('time_format') );
1738 if ( $last_id = get_post_meta($post_id, '_edit_last', true) ) {
1739 $last_user = get_userdata($last_id);
1740 $last_edited = sprintf( __('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), $last_date, $last_time );
1742 $last_edited = sprintf( __('Last edited on %1$s at %2$s'), $last_date, $last_time );
1745 echo json_encode( array( 'message' => $message, 'last_edited' => $last_edited ) );
1749 function wp_ajax_wp_remove_post_lock() {
1750 if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) )
1752 $post_id = (int) $_POST['post_ID'];
1753 if ( ! $post = get_post( $post_id ) )
1756 check_ajax_referer( 'update-post_' . $post_id );
1758 if ( ! current_user_can( 'edit_post', $post_id ) )
1761 $active_lock = array_map( 'absint', explode( ':', $_POST['active_post_lock'] ) );
1762 if ( $active_lock[1] != get_current_user_id() )
1765 $new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', 120 ) + 5 ) . ':' . $active_lock[1];
1766 update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) );
1770 function wp_ajax_dismiss_wp_pointer() {
1771 $pointer = $_POST['pointer'];
1772 if ( $pointer != sanitize_key( $pointer ) )
1775 // check_ajax_referer( 'dismiss-pointer_' . $pointer );
1777 $dismissed = array_filter( explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ) );
1779 if ( in_array( $pointer, $dismissed ) )
1782 $dismissed[] = $pointer;
1783 $dismissed = implode( ',', $dismissed );
1785 update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed );
1790 * Get an attachment.
1794 function wp_ajax_get_attachment() {
1795 if ( ! isset( $_REQUEST['id'] ) )
1796 wp_send_json_error();
1798 if ( ! $id = absint( $_REQUEST['id'] ) )
1799 wp_send_json_error();
1801 if ( ! $post = get_post( $id ) )
1802 wp_send_json_error();
1804 if ( 'attachment' != $post->post_type )
1805 wp_send_json_error();
1807 if ( ! current_user_can( 'upload_files' ) )
1808 wp_send_json_error();
1810 if ( ! $attachment = wp_prepare_attachment_for_js( $id ) )
1811 wp_send_json_error();
1813 wp_send_json_success( $attachment );
1817 * Query for attachments.
1821 function wp_ajax_query_attachments() {
1822 if ( ! current_user_can( 'upload_files' ) )
1823 wp_send_json_error();
1825 $query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
1826 $query = array_intersect_key( $query, array_flip( array(
1827 's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type',
1828 'post_parent', 'post__in', 'post__not_in',
1831 $query['post_type'] = 'attachment';
1832 $query['post_status'] = 'inherit';
1833 if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) )
1834 $query['post_status'] .= ',private';
1836 $query = new WP_Query( $query );
1838 $posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
1839 $posts = array_filter( $posts );
1841 wp_send_json_success( $posts );
1845 * Save attachment attributes.
1849 function wp_ajax_save_attachment() {
1850 if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) )
1851 wp_send_json_error();
1853 if ( ! $id = absint( $_REQUEST['id'] ) )
1854 wp_send_json_error();
1856 check_ajax_referer( 'update-post_' . $id, 'nonce' );
1858 if ( ! current_user_can( 'edit_post', $id ) )
1859 wp_send_json_error();
1861 $changes = $_REQUEST['changes'];
1862 $post = get_post( $id, ARRAY_A );
1864 if ( 'attachment' != $post['post_type'] )
1865 wp_send_json_error();
1867 if ( isset( $changes['title'] ) )
1868 $post['post_title'] = $changes['title'];
1870 if ( isset( $changes['caption'] ) )
1871 $post['post_excerpt'] = $changes['caption'];
1873 if ( isset( $changes['description'] ) )
1874 $post['post_content'] = $changes['description'];
1876 if ( isset( $changes['alt'] ) ) {
1877 $alt = wp_unslash( $changes['alt'] );
1878 if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) {
1879 $alt = wp_strip_all_tags( $alt, true );
1880 update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) );
1884 wp_update_post( $post );
1885 wp_send_json_success();
1889 * Save backwards compatible attachment attributes.
1893 function wp_ajax_save_attachment_compat() {
1894 if ( ! isset( $_REQUEST['id'] ) )
1895 wp_send_json_error();
1897 if ( ! $id = absint( $_REQUEST['id'] ) )
1898 wp_send_json_error();
1900 if ( empty( $_REQUEST['attachments'] ) || empty( $_REQUEST['attachments'][ $id ] ) )
1901 wp_send_json_error();
1902 $attachment_data = $_REQUEST['attachments'][ $id ];
1904 check_ajax_referer( 'update-post_' . $id, 'nonce' );
1906 if ( ! current_user_can( 'edit_post', $id ) )
1907 wp_send_json_error();
1909 $post = get_post( $id, ARRAY_A );
1911 if ( 'attachment' != $post['post_type'] )
1912 wp_send_json_error();
1914 $post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data );
1916 if ( isset( $post['errors'] ) ) {
1917 $errors = $post['errors']; // @todo return me and display me!
1918 unset( $post['errors'] );
1921 wp_update_post( $post );
1923 foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) {
1924 if ( isset( $attachment_data[ $taxonomy ] ) )
1925 wp_set_object_terms( $id, array_map( 'trim', preg_split( '/,+/', $attachment_data[ $taxonomy ] ) ), $taxonomy, false );
1928 if ( ! $attachment = wp_prepare_attachment_for_js( $id ) )
1929 wp_send_json_error();
1931 wp_send_json_success( $attachment );
1934 function wp_ajax_save_attachment_order() {
1935 if ( ! isset( $_REQUEST['post_id'] ) )
1936 wp_send_json_error();
1938 if ( ! $post_id = absint( $_REQUEST['post_id'] ) )
1939 wp_send_json_error();
1941 if ( empty( $_REQUEST['attachments'] ) )
1942 wp_send_json_error();
1944 check_ajax_referer( 'update-post_' . $post_id, 'nonce' );
1946 $attachments = $_REQUEST['attachments'];
1948 if ( ! current_user_can( 'edit_post', $post_id ) )
1949 wp_send_json_error();
1951 $post = get_post( $post_id, ARRAY_A );
1953 foreach ( $attachments as $attachment_id => $menu_order ) {
1954 if ( ! current_user_can( 'edit_post', $attachment_id ) )
1956 if ( ! $attachment = get_post( $attachment_id ) )
1958 if ( 'attachment' != $attachment->post_type )
1961 wp_update_post( array( 'ID' => $attachment_id, 'menu_order' => $menu_order ) );
1964 wp_send_json_success();
1968 * Generates the HTML to send an attachment to the editor.
1969 * Backwards compatible with the media_send_to_editor filter and the chain
1970 * of filters that follow.
1974 function wp_ajax_send_attachment_to_editor() {
1975 check_ajax_referer( 'media-send-to-editor', 'nonce' );
1977 $attachment = wp_unslash( $_POST['attachment'] );
1979 $id = intval( $attachment['id'] );
1981 if ( ! $post = get_post( $id ) )
1982 wp_send_json_error();
1984 if ( 'attachment' != $post->post_type )
1985 wp_send_json_error();
1987 if ( current_user_can( 'edit_post', $id ) ) {
1988 // If this attachment is unattached, attach it. Primarily a back compat thing.
1989 if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) {
1990 wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) );
1995 $html = $title = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';
1996 if ( ! empty( $attachment['url'] ) ) {
1997 $url = $attachment['url'];
1998 if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url )
1999 $rel = ' rel="attachment wp-att-' . $id . '"';
2000 $html = '<a href="' . esc_url( $url ) . '"' . $rel . '>' . $html . '</a>';
2003 remove_filter( 'media_send_to_editor', 'image_media_send_to_editor' );
2005 if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) {
2006 $align = isset( $attachment['align'] ) ? $attachment['align'] : 'none';
2007 $size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
2008 $alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';
2009 $caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : '';
2010 $title = ''; // We no longer insert title tags into <img> tags, as they are redundant.
2011 $html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt );
2012 } elseif ( 'video' === substr( $post->post_mime_type, 0, 5 ) || 'audio' === substr( $post->post_mime_type, 0, 5 ) ) {
2013 $html = stripslashes_deep( $_POST['html'] );
2016 $html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );
2018 wp_send_json_success( $html );
2022 * Generates the HTML to send a non-image embed link to the editor.
2024 * Backwards compatible with the following filters:
2025 * - file_send_to_editor_url
2026 * - audio_send_to_editor_url
2027 * - video_send_to_editor_url
2031 function wp_ajax_send_link_to_editor() {
2032 check_ajax_referer( 'media-send-to-editor', 'nonce' );
2034 if ( ! $src = wp_unslash( $_POST['src'] ) )
2035 wp_send_json_error();
2037 if ( ! strpos( $src, '://' ) )
2038 $src = 'http://' . $src;
2040 if ( ! $src = esc_url_raw( $src ) )
2041 wp_send_json_error();
2043 if ( ! $title = trim( wp_unslash( $_POST['title'] ) ) )
2044 $title = wp_basename( $src );
2048 $html = '<a href="' . esc_url( $src ) . '">' . $title . '</a>';
2050 // Figure out what filter to run:
2052 if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) )
2053 && ( 'audio' == $ext_type || 'video' == $ext_type ) )
2056 $html = apply_filters( $type . '_send_to_editor_url', $html, $src, $title );
2058 wp_send_json_success( $html );
2062 * Heartbeat API (experimental)
2064 * Runs when the user is logged in.
2066 function wp_ajax_heartbeat() {
2067 if ( empty( $_POST['_nonce'] ) )
2068 wp_send_json_error();
2070 $response = array();
2072 if ( false === wp_verify_nonce( $_POST['_nonce'], 'heartbeat-nonce' ) ) {
2073 // User is logged in but nonces have expired.
2074 $response['nonces_expired'] = true;
2075 wp_send_json($response);
2078 // screen_id is the same as $current_screen->id and the JS global 'pagenow'
2079 if ( ! empty($_POST['screen_id']) )
2080 $screen_id = sanitize_key($_POST['screen_id']);
2082 $screen_id = 'front';
2084 if ( ! empty($_POST['data']) ) {
2085 $data = (array) $_POST['data'];
2086 $response = apply_filters( 'heartbeat_received', $response, $data, $screen_id );
2089 $response = apply_filters( 'heartbeat_send', $response, $screen_id );
2091 // Allow the transport to be replaced with long-polling easily
2092 do_action( 'heartbeat_tick', $response, $screen_id );
2094 // Send the current time according to the server
2095 $response['server_time'] = time();
2097 wp_send_json($response);
2100 function wp_ajax_get_revision_diffs() {
2101 require ABSPATH . 'wp-admin/includes/revision.php';
2103 if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) )
2104 wp_send_json_error();
2106 if ( ! current_user_can( 'read_post', $post->ID ) )
2107 wp_send_json_error();
2109 // Really just pre-loading the cache here.
2110 if ( ! $revisions = wp_get_post_revisions( $post->ID, array( 'check_enabled' => false ) ) )
2111 wp_send_json_error();
2114 @set_time_limit( 0 );
2116 foreach ( $_REQUEST['compare'] as $compare_key ) {
2117 list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to
2120 'id' => $compare_key,
2121 'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ),
2124 wp_send_json_success( $return );