3 * WordPress AJAX Process Execution.
6 * @subpackage Administration
10 * Executing AJAX process.
14 define('DOING_AJAX', true);
15 define('WP_ADMIN', true);
17 if ( ! isset( $_REQUEST['action'] ) )
20 require_once('../wp-load.php');
22 require_once('./includes/admin.php');
23 @header('Content-Type: text/html; charset=' . get_option('blog_charset'));
24 send_nosniff_header();
26 do_action('admin_init');
28 if ( ! is_user_logged_in() ) {
30 if ( isset( $_POST['action'] ) && $_POST['action'] == 'autosave' ) {
31 $id = isset($_POST['post_ID'])? (int) $_POST['post_ID'] : 0;
36 $message = sprintf( __('<strong>ALERT: You are logged out!</strong> Could not save draft. <a href="%s" target="_blank">Please log in again.</a>'), wp_login_url() );
37 $x = new WP_Ajax_Response( array(
45 if ( !empty( $_REQUEST['action'] ) )
46 do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
51 if ( isset( $_GET['action'] ) ) :
52 switch ( $action = $_GET['action'] ) :
55 $list_class = $_GET['list_args']['class'];
56 check_ajax_referer( "fetch-list-$list_class", '_ajax_fetch_list_nonce' );
58 $current_screen = (object) $_GET['list_args']['screen'];
59 //TODO fix this in a better way see #15336
60 $current_screen->is_network = 'false' === $current_screen->is_network ? false : true;
61 $current_screen->is_user = 'false' === $current_screen->is_user ? false : true;
63 define( 'WP_NETWORK_ADMIN', $current_screen->is_network );
64 define( 'WP_USER_ADMIN', $current_screen->is_user );
66 $wp_list_table = _get_list_table( $list_class );
67 if ( ! $wp_list_table )
70 if ( ! $wp_list_table->ajax_user_can() )
73 $wp_list_table->ajax_response();
77 case 'ajax-tag-search' :
78 if ( isset( $_GET['tax'] ) ) {
79 $taxonomy = sanitize_key( $_GET['tax'] );
80 $tax = get_taxonomy( $taxonomy );
83 if ( ! current_user_can( $tax->cap->assign_terms ) )
89 $s = stripslashes( $_GET['q'] );
91 if ( false !== strpos( $s, ',' ) ) {
92 $s = explode( ',', $s );
93 $s = $s[count( $s ) - 1];
96 if ( strlen( $s ) < 2 )
97 die; // require 2 chars for matching
99 $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 ) . '%' ) );
101 echo join( $results, "\n" );
104 case 'wp-compression-test' :
105 if ( !current_user_can( 'manage_options' ) )
108 if ( ini_get('zlib.output_compression') || 'ob_gzhandler' == ini_get('output_handler') ) {
109 update_site_option('can_compress_scripts', 0);
113 if ( isset($_GET['test']) ) {
114 header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
115 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
116 header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
117 header( 'Pragma: no-cache' );
118 header('Content-Type: application/x-javascript; charset=UTF-8');
119 $force_gzip = ( defined('ENFORCE_GZIP') && ENFORCE_GZIP );
120 $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."';
122 if ( 1 == $_GET['test'] ) {
125 } elseif ( 2 == $_GET['test'] ) {
126 if ( !isset($_SERVER['HTTP_ACCEPT_ENCODING']) )
128 if ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && function_exists('gzdeflate') && ! $force_gzip ) {
129 header('Content-Encoding: deflate');
130 $out = gzdeflate( $test_str, 1 );
131 } elseif ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode') ) {
132 header('Content-Encoding: gzip');
133 $out = gzencode( $test_str, 1 );
139 } elseif ( 'no' == $_GET['test'] ) {
140 update_site_option('can_compress_scripts', 0);
141 } elseif ( 'yes' == $_GET['test'] ) {
142 update_site_option('can_compress_scripts', 1);
148 case 'imgedit-preview' :
149 $post_id = intval($_GET['postid']);
150 if ( empty($post_id) || !current_user_can('edit_post', $post_id) )
153 check_ajax_referer( "image_editor-$post_id" );
155 include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
156 if ( ! stream_preview_image($post_id) )
161 case 'menu-quick-search':
162 if ( ! current_user_can( 'edit_theme_options' ) )
165 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
167 _wp_ajax_menu_quick_search( $_REQUEST );
171 case 'oembed-cache' :
172 $return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0';
176 do_action( 'wp_ajax_' . $_GET['action'] );
183 * Sends back current comment total and new page links if they need to be updated.
185 * Contrary to normal success AJAX response ("1"), die with time() on success.
189 * @param int $comment_id
192 function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) {
193 $total = (int) @$_POST['_total'];
194 $per_page = (int) @$_POST['_per_page'];
195 $page = (int) @$_POST['_page'];
196 $url = esc_url_raw( @$_POST['_url'] );
197 // JS didn't send us everything we need to know. Just die with success message
198 if ( !$total || !$per_page || !$page || !$url )
199 die( (string) time() );
205 // Only do the expensive stuff on a page-break, and about 1 other time per page
206 if ( 0 == $total % $per_page || 1 == mt_rand( 1, $per_page ) ) {
208 $status = 'total_comments'; // What type of comment count are we looking for?
209 $parsed = parse_url( $url );
210 if ( isset( $parsed['query'] ) ) {
211 parse_str( $parsed['query'], $query_vars );
212 if ( !empty( $query_vars['comment_status'] ) )
213 $status = $query_vars['comment_status'];
214 if ( !empty( $query_vars['p'] ) )
215 $post_id = (int) $query_vars['p'];
218 $comment_count = wp_count_comments($post_id);
220 if ( isset( $comment_count->$status ) ) // We're looking for a known type of comment count
221 $total = $comment_count->$status;
222 // else use the decremented value from above
225 $time = time(); // The time since the last comment count
227 $x = new WP_Ajax_Response( array(
229 'id' => $comment_id, // here for completeness - not used
230 'supplemental' => array(
231 'total_items_i18n' => sprintf( _n( '1 item', '%s items', $total ), number_format_i18n( $total ) ),
232 'total_pages' => ceil( $total / $per_page ),
233 'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ),
241 function _wp_ajax_add_hierarchical_term() {
242 $action = $_POST['action'];
243 $taxonomy = get_taxonomy(substr($action, 4));
244 check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
245 if ( !current_user_can( $taxonomy->cap->edit_terms ) )
247 $names = explode(',', $_POST['new'.$taxonomy->name]);
248 $parent = isset($_POST['new'.$taxonomy->name.'_parent']) ? (int) $_POST['new'.$taxonomy->name.'_parent'] : 0;
251 if ( $taxonomy->name == 'category' )
252 $post_category = isset($_POST['post_category']) ? (array) $_POST['post_category'] : array();
254 $post_category = ( isset($_POST['tax_input']) && isset($_POST['tax_input'][$taxonomy->name]) ) ? (array) $_POST['tax_input'][$taxonomy->name] : array();
255 $checked_categories = array_map( 'absint', (array) $post_category );
256 $popular_ids = wp_popular_terms_checklist($taxonomy->name, 0, 10, false);
258 foreach ( $names as $cat_name ) {
259 $cat_name = trim($cat_name);
260 $category_nicename = sanitize_title($cat_name);
261 if ( '' === $category_nicename )
263 if ( !($cat_id = term_exists($cat_name, $taxonomy->name, $parent)) ) {
264 $new_term = wp_insert_term($cat_name, $taxonomy->name, array('parent' => $parent));
265 $cat_id = $new_term['term_id'];
267 $checked_categories[] = $cat_id;
268 if ( $parent ) // Do these all at once in a second
270 $category = get_term( $cat_id, $taxonomy->name );
272 wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name, 'descendants_and_self' => $cat_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids ));
273 $data = ob_get_contents();
276 'what' => $taxonomy->name,
278 'data' => str_replace( array("\n", "\t"), '', $data),
283 if ( $parent ) { // Foncy - replace the parent and all its children
284 $parent = get_term( $parent, $taxonomy->name );
285 $term_id = $parent->term_id;
287 while ( $parent->parent ) { // get the top parent
288 $parent = &get_term( $parent->parent, $taxonomy->name );
289 if ( is_wp_error( $parent ) )
291 $term_id = $parent->term_id;
295 wp_terms_checklist( 0, array('taxonomy' => $taxonomy->name, 'descendants_and_self' => $term_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids));
296 $data = ob_get_contents();
299 'what' => $taxonomy->name,
301 'data' => str_replace( array("\n", "\t"), '', $data),
307 wp_dropdown_categories( array(
308 'taxonomy' => $taxonomy->name, 'hide_empty' => 0, 'name' => 'new'.$taxonomy->name.'_parent', 'orderby' => 'name',
309 'hierarchical' => 1, 'show_option_none' => '— '.$taxonomy->labels->parent_item.' —'
311 $sup = ob_get_contents();
313 $add['supplemental'] = array( 'newcat_parent' => $sup );
315 $x = new WP_Ajax_Response( $add );
319 $id = isset($_POST['id'])? (int) $_POST['id'] : 0;
320 switch ( $action = $_POST['action'] ) :
321 case 'delete-comment' : // On success, die with time() instead of 1
322 if ( !$comment = get_comment( $id ) )
323 die( (string) time() );
324 if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) )
327 check_ajax_referer( "delete-comment_$id" );
328 $status = wp_get_comment_status( $comment->comment_ID );
331 if ( isset($_POST['trash']) && 1 == $_POST['trash'] ) {
332 if ( 'trash' == $status )
333 die( (string) time() );
334 $r = wp_trash_comment( $comment->comment_ID );
335 } elseif ( isset($_POST['untrash']) && 1 == $_POST['untrash'] ) {
336 if ( 'trash' != $status )
337 die( (string) time() );
338 $r = wp_untrash_comment( $comment->comment_ID );
339 if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'trash' ) // undo trash, not in trash
341 } elseif ( isset($_POST['spam']) && 1 == $_POST['spam'] ) {
342 if ( 'spam' == $status )
343 die( (string) time() );
344 $r = wp_spam_comment( $comment->comment_ID );
345 } elseif ( isset($_POST['unspam']) && 1 == $_POST['unspam'] ) {
346 if ( 'spam' != $status )
347 die( (string) time() );
348 $r = wp_unspam_comment( $comment->comment_ID );
349 if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'spam' ) // undo spam, not in spam
351 } elseif ( isset($_POST['delete']) && 1 == $_POST['delete'] ) {
352 $r = wp_delete_comment( $comment->comment_ID );
357 if ( $r ) // Decide if we need to send back '1' or a more complicated response including page links and comment counts
358 _wp_ajax_delete_comment_response( $comment->comment_ID, $delta );
362 $tag_id = (int) $_POST['tag_ID'];
363 check_ajax_referer( "delete-tag_$tag_id" );
365 $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
366 $tax = get_taxonomy($taxonomy);
368 if ( !current_user_can( $tax->cap->delete_terms ) )
371 $tag = get_term( $tag_id, $taxonomy );
372 if ( !$tag || is_wp_error( $tag ) )
375 if ( wp_delete_term($tag_id, $taxonomy))
381 check_ajax_referer( "delete-bookmark_$id" );
382 if ( !current_user_can( 'manage_links' ) )
385 $link = get_bookmark( $id );
386 if ( !$link || is_wp_error( $link ) )
389 if ( wp_delete_link( $id ) )
395 check_ajax_referer( "delete-meta_$id" );
396 if ( !$meta = get_post_meta_by_id( $id ) )
399 if ( !current_user_can( 'edit_post', $meta->post_id ) || is_protected_meta( $meta->meta_key ) )
401 if ( delete_meta( $meta->meta_id ) )
406 check_ajax_referer( "{$action}_$id" );
407 if ( !current_user_can( 'delete_post', $id ) )
410 if ( !get_post( $id ) )
413 if ( wp_delete_post( $id ) )
419 case 'untrash-post' :
420 check_ajax_referer( "{$action}_$id" );
421 if ( !current_user_can( 'delete_post', $id ) )
424 if ( !get_post( $id ) )
427 if ( 'trash-post' == $action )
428 $done = wp_trash_post( $id );
430 $done = wp_untrash_post( $id );
438 check_ajax_referer( "{$action}_$id" );
439 if ( !current_user_can( 'delete_page', $id ) )
442 if ( !get_page( $id ) )
445 if ( wp_delete_post( $id ) )
450 case 'dim-comment' : // On success, die with time() instead of 1
452 if ( !$comment = get_comment( $id ) ) {
453 $x = new WP_Ajax_Response( array(
455 'id' => new WP_Error('invalid_comment', sprintf(__('Comment %d does not exist'), $id))
460 if ( !current_user_can( 'edit_post', $comment->comment_post_ID ) && !current_user_can( 'moderate_comments' ) )
463 $current = wp_get_comment_status( $comment->comment_ID );
464 if ( $_POST['new'] == $current )
465 die( (string) time() );
467 check_ajax_referer( "approve-comment_$id" );
468 if ( in_array( $current, array( 'unapproved', 'spam' ) ) )
469 $result = wp_set_comment_status( $comment->comment_ID, 'approve', true );
471 $result = wp_set_comment_status( $comment->comment_ID, 'hold', true );
473 if ( is_wp_error($result) ) {
474 $x = new WP_Ajax_Response( array(
481 // Decide if we need to send back '1' or a more complicated response including page links and comment counts
482 _wp_ajax_delete_comment_response( $comment->comment_ID );
485 case 'add-link-category' : // On the Fly
486 check_ajax_referer( $action );
487 if ( !current_user_can( 'manage_categories' ) )
489 $names = explode(',', $_POST['newcat']);
490 $x = new WP_Ajax_Response();
491 foreach ( $names as $cat_name ) {
492 $cat_name = trim($cat_name);
493 $slug = sanitize_title($cat_name);
496 if ( !$cat_id = term_exists( $cat_name, 'link_category' ) ) {
497 $cat_id = wp_insert_term( $cat_name, 'link_category' );
499 $cat_id = $cat_id['term_id'];
500 $cat_name = esc_html(stripslashes($cat_name));
502 'what' => 'link-category',
504 '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>",
511 check_ajax_referer( 'add-tag' );
512 $post_type = !empty($_POST['post_type']) ? $_POST['post_type'] : 'post';
513 $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
514 $tax = get_taxonomy($taxonomy);
516 if ( !current_user_can( $tax->cap->edit_terms ) )
519 $x = new WP_Ajax_Response();
521 $tag = wp_insert_term($_POST['tag-name'], $taxonomy, $_POST );
523 if ( !$tag || is_wp_error($tag) || (!$tag = get_term( $tag['term_id'], $taxonomy )) ) {
524 $message = __('An error has occurred. Please reload the page and try again.');
525 if ( is_wp_error($tag) && $tag->get_error_message() )
526 $message = $tag->get_error_message();
529 'what' => 'taxonomy',
530 'data' => new WP_Error('error', $message )
535 set_current_screen( $_POST['screen'] );
537 $wp_list_table = _get_list_table('WP_Terms_List_Table');
540 if ( is_taxonomy_hierarchical($taxonomy) ) {
541 $level = count( get_ancestors( $tag->term_id, $taxonomy ) );
543 $wp_list_table->single_row( $tag, $level );
544 $noparents = ob_get_clean();
548 $wp_list_table->single_row( $tag );
549 $parents = ob_get_clean();
552 'what' => 'taxonomy',
553 'supplemental' => compact('parents', 'noparents')
557 'position' => $level,
558 'supplemental' => (array) $tag
562 case 'get-tagcloud' :
563 if ( isset( $_POST['tax'] ) ) {
564 $taxonomy = sanitize_key( $_POST['tax'] );
565 $tax = get_taxonomy( $taxonomy );
568 if ( ! current_user_can( $tax->cap->assign_terms ) )
574 $tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) );
576 if ( empty( $tags ) )
577 die( isset( $tax->no_tagcloud ) ? $tax->no_tagcloud : __('No tags found!') );
579 if ( is_wp_error( $tags ) )
580 die( $tags->get_error_message() );
582 foreach ( $tags as $key => $tag ) {
583 $tags[ $key ]->link = '#';
584 $tags[ $key ]->id = $tag->term_id;
587 // We need raw tag names here, so don't filter the output
588 $return = wp_generate_tag_cloud( $tags, array('filter' => 0) );
590 if ( empty($return) )
597 case 'get-comments' :
598 check_ajax_referer( $action );
600 set_current_screen( 'edit-comments' );
602 $wp_list_table = _get_list_table('WP_Post_Comments_List_Table');
604 if ( !current_user_can( 'edit_post', $post_id ) )
607 $wp_list_table->prepare_items();
609 if ( !$wp_list_table->has_items() )
612 $comment_list_item = '';
613 $x = new WP_Ajax_Response();
614 foreach ( $wp_list_table->items as $comment ) {
615 get_comment( $comment );
617 $wp_list_table->single_row( $comment );
618 $comment_list_item .= ob_get_contents();
622 'what' => 'comments',
623 'data' => $comment_list_item
627 case 'replyto-comment' :
628 check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );
630 set_current_screen( 'edit-comments' );
632 $comment_post_ID = (int) $_POST['comment_post_ID'];
633 if ( !current_user_can( 'edit_post', $comment_post_ID ) )
636 $status = $wpdb->get_var( $wpdb->prepare("SELECT post_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) );
638 if ( empty($status) )
640 elseif ( in_array($status, array('draft', 'pending', 'trash') ) )
641 die( __('Error: you are replying to a comment on a draft post.') );
643 $user = wp_get_current_user();
645 $comment_author = $wpdb->escape($user->display_name);
646 $comment_author_email = $wpdb->escape($user->user_email);
647 $comment_author_url = $wpdb->escape($user->user_url);
648 $comment_content = trim($_POST['content']);
649 if ( current_user_can('unfiltered_html') ) {
650 if ( wp_create_nonce('unfiltered-html-comment_' . $comment_post_ID) != $_POST['_wp_unfiltered_html_comment'] ) {
651 kses_remove_filters(); // start with a clean slate
652 kses_init_filters(); // set up the filters
656 die( __('Sorry, you must be logged in to reply to a comment.') );
659 if ( '' == $comment_content )
660 die( __('Error: please type a comment.') );
662 $comment_parent = absint($_POST['comment_ID']);
663 $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
665 $comment_id = wp_new_comment( $commentdata );
666 $comment = get_comment($comment_id);
667 if ( ! $comment ) die('1');
669 $position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1';
671 $x = new WP_Ajax_Response();
674 if ( 'dashboard' == $_REQUEST['mode'] ) {
675 require_once( ABSPATH . 'wp-admin/includes/dashboard.php' );
676 _wp_dashboard_recent_comments_row( $comment );
678 if ( 'single' == $_REQUEST['mode'] ) {
679 $wp_list_table = _get_list_table('WP_Post_Comments_List_Table');
681 $wp_list_table = _get_list_table('WP_Comments_List_Table');
683 $wp_list_table->single_row( $comment );
685 $comment_list_item = ob_get_contents();
690 'id' => $comment->comment_ID,
691 'data' => $comment_list_item,
692 'position' => $position
697 case 'edit-comment' :
698 check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' );
700 set_current_screen( 'edit-comments' );
702 $comment_post_ID = (int) $_POST['comment_post_ID'];
703 if ( ! current_user_can( 'edit_post', $comment_post_ID ) )
706 if ( '' == $_POST['content'] )
707 die( __('Error: please type a comment.') );
709 $comment_id = (int) $_POST['comment_ID'];
710 $_POST['comment_status'] = $_POST['status'];
713 $position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1';
714 $comments_status = isset($_POST['comments_listing']) ? $_POST['comments_listing'] : '';
716 $checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0;
717 $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table' );
720 $wp_list_table->single_row( get_comment( $comment_id ) );
721 $comment_list_item = ob_get_contents();
724 $x = new WP_Ajax_Response();
727 'what' => 'edit_comment',
728 'id' => $comment->comment_ID,
729 'data' => $comment_list_item,
730 'position' => $position
735 case 'add-menu-item' :
736 if ( ! current_user_can( 'edit_theme_options' ) )
739 check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
741 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
743 // For performance reasons, we omit some object properties from the checklist.
744 // The following is a hacky way to restore them when adding non-custom items.
746 $menu_items_data = array();
747 foreach ( (array) $_POST['menu-item'] as $menu_item_data ) {
749 ! empty( $menu_item_data['menu-item-type'] ) &&
750 'custom' != $menu_item_data['menu-item-type'] &&
751 ! empty( $menu_item_data['menu-item-object-id'] )
753 switch( $menu_item_data['menu-item-type'] ) {
755 $_object = get_post( $menu_item_data['menu-item-object-id'] );
759 $_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
763 $_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
764 $_menu_item = array_shift( $_menu_items );
766 // Restore the missing menu item properties
767 $menu_item_data['menu-item-description'] = $_menu_item->description;
770 $menu_items_data[] = $menu_item_data;
773 $item_ids = wp_save_nav_menu_items( 0, $menu_items_data );
774 if ( is_wp_error( $item_ids ) )
777 foreach ( (array) $item_ids as $menu_item_id ) {
778 $menu_obj = get_post( $menu_item_id );
779 if ( ! empty( $menu_obj->ID ) ) {
780 $menu_obj = wp_setup_nav_menu_item( $menu_obj );
781 $menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items
782 $menu_items[] = $menu_obj;
786 if ( ! empty( $menu_items ) ) {
792 'walker' => new Walker_Nav_Menu_Edit,
794 echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
798 check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' );
800 $pid = (int) $_POST['post_id'];
801 $post = get_post( $pid );
803 if ( isset($_POST['metakeyselect']) || isset($_POST['metakeyinput']) ) {
804 if ( !current_user_can( 'edit_post', $pid ) )
806 if ( isset($_POST['metakeyselect']) && '#NONE#' == $_POST['metakeyselect'] && empty($_POST['metakeyinput']) )
808 if ( $post->post_status == 'auto-draft' ) {
809 $save_POST = $_POST; // Backup $_POST
810 $_POST = array(); // Make it empty for edit_post()
811 $_POST['action'] = 'draft'; // Warning fix
812 $_POST['post_ID'] = $pid;
813 $_POST['post_type'] = $post->post_type;
814 $_POST['post_status'] = 'draft';
815 $now = current_time('timestamp', 1);
816 $_POST['post_title'] = sprintf('Draft created on %s at %s', date(get_option('date_format'), $now), date(get_option('time_format'), $now));
818 if ( $pid = edit_post() ) {
819 if ( is_wp_error( $pid ) ) {
820 $x = new WP_Ajax_Response( array(
826 $_POST = $save_POST; // Now we can restore original $_POST again
827 if ( !$mid = add_meta( $pid ) )
828 die(__('Please provide a custom field value.'));
832 } else if ( !$mid = add_meta( $pid ) ) {
833 die(__('Please provide a custom field value.'));
836 $meta = get_post_meta_by_id( $mid );
837 $pid = (int) $meta->post_id;
838 $meta = get_object_vars( $meta );
839 $x = new WP_Ajax_Response( array(
842 'data' => _list_meta_row( $meta, $c ),
844 'supplemental' => array('postid' => $pid)
847 $mid = (int) array_pop( $var_by_ref = array_keys($_POST['meta']) );
848 $key = $_POST['meta'][$mid]['key'];
849 $value = $_POST['meta'][$mid]['value'];
850 if ( '' == trim($key) )
851 die(__('Please provide a custom field name.'));
852 if ( '' == trim($value) )
853 die(__('Please provide a custom field value.'));
854 if ( !$meta = get_post_meta_by_id( $mid ) )
855 die('0'); // if meta doesn't exist
856 if ( !current_user_can( 'edit_post', $meta->post_id ) )
858 if ( is_protected_meta( $meta->meta_key ) )
860 if ( $meta->meta_value != stripslashes($value) || $meta->meta_key != stripslashes($key) ) {
861 if ( !$u = update_meta( $mid, $key, $value ) )
862 die('0'); // We know meta exists; we also know it's unchanged (or DB error, in which case there are bigger problems).
865 $key = stripslashes($key);
866 $value = stripslashes($value);
867 $x = new WP_Ajax_Response( array(
869 'id' => $mid, 'old_id' => $mid,
870 'data' => _list_meta_row( array(
872 'meta_value' => $value,
876 'supplemental' => array('postid' => $meta->post_id)
882 check_ajax_referer( $action );
883 if ( !current_user_can('create_users') )
885 if ( !$user_id = add_user() )
887 elseif ( is_wp_error( $user_id ) ) {
888 $x = new WP_Ajax_Response( array(
894 $user_object = new WP_User( $user_id );
896 $wp_list_table = _get_list_table('WP_Users_List_Table');
898 $x = new WP_Ajax_Response( array(
901 'data' => $wp_list_table->single_row( $user_object, '', $user_object->roles[0] ),
902 'supplemental' => array(
903 'show-link' => sprintf(__( 'User <a href="#%s">%s</a> added' ), "user-$user_id", $user_object->user_login),
904 'role' => $user_object->roles[0]
909 case 'autosave' : // The name of this action is hardcoded in edit_post()
910 define( 'DOING_AUTOSAVE', true );
912 $nonce_age = check_ajax_referer( 'autosave', 'autosavenonce' );
914 $_POST['post_category'] = explode(",", $_POST['catslist']);
915 if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
916 unset($_POST['post_category']);
918 $do_autosave = (bool) $_POST['autosave'];
922 /* translators: draft saved date format, see http://php.net/date */
923 $draft_saved_date_format = __('g:i:s a');
924 /* translators: %s: date and time */
925 $message = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
927 $supplemental = array();
928 if ( isset($login_grace_period) )
929 $supplemental['session_expired'] = add_query_arg( 'interim-login', 1, wp_login_url() );
931 $id = $revision_id = 0;
933 $post_ID = (int) $_POST['post_ID'];
934 $_POST['ID'] = $post_ID;
935 $post = get_post($post_ID);
936 if ( 'auto-draft' == $post->post_status )
937 $_POST['post_status'] = 'draft';
939 if ( $last = wp_check_post_lock( $post->ID ) ) {
940 $do_autosave = $do_lock = false;
942 $last_user = get_userdata( $last );
943 $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
944 $data = new WP_Error( 'locked', sprintf(
945 $_POST['post_type'] == 'page' ? __( 'Autosave disabled: %s is currently editing this page.' ) : __( 'Autosave disabled: %s is currently editing this post.' ),
946 esc_html( $last_user_name )
949 $supplemental['disable_autosave'] = 'disable';
952 if ( 'page' == $post->post_type ) {
953 if ( !current_user_can('edit_page', $post_ID) )
954 die(__('You are not allowed to edit this page.'));
956 if ( !current_user_can('edit_post', $post_ID) )
957 die(__('You are not allowed to edit this post.'));
960 if ( $do_autosave ) {
961 // Drafts and auto-drafts are just overwritten by autosave
962 if ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) {
964 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
965 $revision_id = wp_create_post_autosave( $post->ID );
966 if ( is_wp_error($revision_id) )
973 if ( isset( $_POST['auto_draft'] ) && '1' == $_POST['auto_draft'] )
974 $id = 0; // This tells us it didn't actually save
979 if ( $do_lock && ( isset( $_POST['auto_draft'] ) && ( $_POST['auto_draft'] != '1' ) ) && $id && is_numeric($id) )
980 wp_set_post_lock( $id );
982 if ( $nonce_age == 2 ) {
983 $supplemental['replace-autosavenonce'] = wp_create_nonce('autosave');
984 $supplemental['replace-getpermalinknonce'] = wp_create_nonce('getpermalink');
985 $supplemental['replace-samplepermalinknonce'] = wp_create_nonce('samplepermalink');
986 $supplemental['replace-closedpostboxesnonce'] = wp_create_nonce('closedpostboxes');
988 if ( $_POST['post_type'] == 'post' )
989 $supplemental['replace-_wpnonce'] = wp_create_nonce('update-post_' . $id);
990 elseif ( $_POST['post_type'] == 'page' )
991 $supplemental['replace-_wpnonce'] = wp_create_nonce('update-page_' . $id);
995 $x = new WP_Ajax_Response( array(
996 'what' => 'autosave',
998 'data' => $id ? $data : '',
999 'supplemental' => $supplemental
1003 case 'closed-postboxes' :
1004 check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
1005 $closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array();
1006 $closed = array_filter($closed);
1008 $hidden = isset( $_POST['hidden'] ) ? explode( ',', $_POST['hidden']) : array();
1009 $hidden = array_filter($hidden);
1011 $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1013 if ( !preg_match( '/^[a-z_-]+$/', $page ) )
1016 if ( ! $user = wp_get_current_user() )
1019 if ( is_array($closed) )
1020 update_user_option($user->ID, "closedpostboxes_$page", $closed, true);
1022 if ( is_array($hidden) ) {
1023 $hidden = array_diff( $hidden, array('submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu') ); // postboxes that are always shown
1024 update_user_option($user->ID, "metaboxhidden_$page", $hidden, true);
1029 case 'hidden-columns' :
1030 check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' );
1031 $hidden = isset( $_POST['hidden'] ) ? $_POST['hidden'] : '';
1032 $hidden = explode( ',', $_POST['hidden'] );
1033 $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1035 if ( !preg_match( '/^[a-z_-]+$/', $page ) )
1038 if ( ! $user = wp_get_current_user() )
1041 if ( is_array($hidden) )
1042 update_user_option($user->ID, "manage{$page}columnshidden", $hidden, true);
1046 case 'menu-get-metabox' :
1047 if ( ! current_user_can( 'edit_theme_options' ) )
1050 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
1052 if ( isset( $_POST['item-type'] ) && 'post_type' == $_POST['item-type'] ) {
1054 $callback = 'wp_nav_menu_item_post_type_meta_box';
1055 $items = (array) get_post_types( array( 'show_in_nav_menus' => true ), 'object' );
1056 } elseif ( isset( $_POST['item-type'] ) && 'taxonomy' == $_POST['item-type'] ) {
1058 $callback = 'wp_nav_menu_item_taxonomy_meta_box';
1059 $items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' );
1062 if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) {
1063 $item = apply_filters( 'nav_menu_meta_box_object', $items[ $_POST['item-object'] ] );
1065 call_user_func_array($callback, array(
1068 'id' => 'add-' . $item->name,
1069 'title' => $item->labels->name,
1070 'callback' => $callback,
1075 $markup = ob_get_clean();
1077 echo json_encode(array(
1078 'replace-id' => $type . '-' . $item->name,
1079 'markup' => $markup,
1085 case 'menu-quick-search':
1086 if ( ! current_user_can( 'edit_theme_options' ) )
1089 require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
1091 _wp_ajax_menu_quick_search( $_REQUEST );
1095 case 'wp-link-ajax':
1096 require_once ABSPATH . 'wp-admin/includes/internal-linking.php';
1098 check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' );
1102 if ( isset( $_POST['search'] ) )
1103 $args['s'] = stripslashes( $_POST['search'] );
1104 $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
1106 $results = wp_link_query( $args );
1108 if ( ! isset( $results ) )
1111 echo json_encode( $results );
1116 case 'menu-locations-save':
1117 if ( ! current_user_can( 'edit_theme_options' ) )
1119 check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
1120 if ( ! isset( $_POST['menu-locations'] ) )
1122 set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) );
1125 case 'meta-box-order':
1126 check_ajax_referer( 'meta-box-order' );
1127 $order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false;
1128 $page_columns = isset( $_POST['page_columns'] ) ? (int) $_POST['page_columns'] : 0;
1129 $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1131 if ( !preg_match( '/^[a-z_-]+$/', $page ) )
1134 if ( ! $user = wp_get_current_user() )
1138 update_user_option($user->ID, "meta-box-order_$page", $order, true);
1140 if ( $page_columns )
1141 update_user_option($user->ID, "screen_layout_$page", $page_columns, true);
1145 case 'get-permalink':
1146 check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
1147 $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
1148 die(add_query_arg(array('preview' => 'true'), get_permalink($post_id)));
1150 case 'sample-permalink':
1151 check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' );
1152 $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
1153 $title = isset($_POST['new_title'])? $_POST['new_title'] : '';
1154 $slug = isset($_POST['new_slug'])? $_POST['new_slug'] : null;
1155 die(get_sample_permalink_html($post_id, $title, $slug));
1158 check_ajax_referer( 'inlineeditnonce', '_inline_edit' );
1160 if ( ! isset($_POST['post_ID']) || ! ( $post_ID = (int) $_POST['post_ID'] ) )
1163 if ( 'page' == $_POST['post_type'] ) {
1164 if ( ! current_user_can( 'edit_page', $post_ID ) )
1165 die( __('You are not allowed to edit this page.') );
1167 if ( ! current_user_can( 'edit_post', $post_ID ) )
1168 die( __('You are not allowed to edit this post.') );
1171 set_current_screen( $_POST['screen'] );
1173 if ( $last = wp_check_post_lock( $post_ID ) ) {
1174 $last_user = get_userdata( $last );
1175 $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
1176 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 ) );
1182 $post = get_post( $post_ID, ARRAY_A );
1183 $post = add_magic_quotes($post); //since it is from db
1185 $data['content'] = $post['post_content'];
1186 $data['excerpt'] = $post['post_excerpt'];
1189 $data['user_ID'] = $GLOBALS['user_ID'];
1191 if ( isset($data['post_parent']) )
1192 $data['parent_id'] = $data['post_parent'];
1195 if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
1196 $data['post_status'] = 'private';
1198 $data['post_status'] = $data['_status'];
1200 if ( empty($data['comment_status']) )
1201 $data['comment_status'] = 'closed';
1202 if ( empty($data['ping_status']) )
1203 $data['ping_status'] = 'closed';
1208 $wp_list_table = _get_list_table('WP_Posts_List_Table');
1210 $mode = $_POST['post_view'];
1211 $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ) );
1215 case 'inline-save-tax':
1216 check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
1218 $taxonomy = sanitize_key( $_POST['taxonomy'] );
1219 $tax = get_taxonomy( $taxonomy );
1223 if ( ! current_user_can( $tax->cap->edit_terms ) )
1226 set_current_screen( 'edit-' . $taxonomy );
1228 $wp_list_table = _get_list_table('WP_Terms_List_Table');
1230 if ( ! isset($_POST['tax_ID']) || ! ( $id = (int) $_POST['tax_ID'] ) )
1233 $tag = get_term( $id, $taxonomy );
1234 $_POST['description'] = $tag->description;
1236 $updated = wp_update_term($id, $taxonomy, $_POST);
1237 if ( $updated && !is_wp_error($updated) ) {
1238 $tag = get_term( $updated['term_id'], $taxonomy );
1239 if ( !$tag || is_wp_error( $tag ) ) {
1240 if ( is_wp_error($tag) && $tag->get_error_message() )
1241 die( $tag->get_error_message() );
1242 die( __('Item not updated.') );
1245 echo $wp_list_table->single_row( $tag );
1247 if ( is_wp_error($updated) && $updated->get_error_message() )
1248 die( $updated->get_error_message() );
1249 die( __('Item not updated.') );
1255 check_ajax_referer( 'find-posts' );
1257 if ( empty($_POST['ps']) )
1260 if ( !empty($_POST['post_type']) && in_array( $_POST['post_type'], get_post_types() ) )
1261 $what = $_POST['post_type'];
1265 $s = stripslashes($_POST['ps']);
1266 preg_match_all('/".*?("|$)|((?<=[\\s",+])|^)[^\\s",+]+/', $s, $matches);
1267 $search_terms = array_map('_search_terms_tidy', $matches[0]);
1269 $searchand = $search = '';
1270 foreach ( (array) $search_terms as $term ) {
1271 $term = esc_sql( like_escape( $term ) );
1272 $search .= "{$searchand}(($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%'))";
1273 $searchand = ' AND ';
1275 $term = esc_sql( like_escape( $s ) );
1276 if ( count($search_terms) > 1 && $search_terms[0] != $s )
1277 $search .= " OR ($wpdb->posts.post_title LIKE '%{$term}%') OR ($wpdb->posts.post_content LIKE '%{$term}%')";
1279 $posts = $wpdb->get_results( "SELECT ID, post_title, post_status, post_date FROM $wpdb->posts WHERE post_type = '$what' AND post_status IN ('draft', 'publish') AND ($search) ORDER BY post_date_gmt DESC LIMIT 50" );
1282 $posttype = get_post_type_object($what);
1283 exit($posttype->labels->not_found);
1286 $html = '<table class="widefat" cellspacing="0"><thead><tr><th class="found-radio"><br /></th><th>'.__('Title').'</th><th>'.__('Date').'</th><th>'.__('Status').'</th></tr></thead><tbody>';
1287 foreach ( $posts as $post ) {
1289 switch ( $post->post_status ) {
1292 $stat = __('Published');
1295 $stat = __('Scheduled');
1298 $stat = __('Pending Review');
1301 $stat = __('Draft');
1305 if ( '0000-00-00 00:00:00' == $post->post_date ) {
1308 /* translators: date format in table columns, see http://php.net/date */
1309 $time = mysql2date(__('Y/m/d'), $post->post_date);
1312 $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>';
1313 $html .= '<td><label for="found-'.$post->ID.'">'.esc_html( $post->post_title ).'</label></td><td>'.esc_html( $time ).'</td><td>'.esc_html( $stat ).'</td></tr>'."\n\n";
1315 $html .= '</tbody></table>';
1317 $x = new WP_Ajax_Response();
1325 case 'widgets-order' :
1326 check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
1328 if ( !current_user_can('edit_theme_options') )
1331 unset( $_POST['savewidgets'], $_POST['action'] );
1333 // save widgets order for all sidebars
1334 if ( is_array($_POST['sidebars']) ) {
1335 $sidebars = array();
1336 foreach ( $_POST['sidebars'] as $key => $val ) {
1338 if ( !empty($val) ) {
1339 $val = explode(',', $val);
1340 foreach ( $val as $k => $v ) {
1341 if ( strpos($v, 'widget-') === false )
1344 $sb[$k] = substr($v, strpos($v, '_') + 1);
1347 $sidebars[$key] = $sb;
1349 wp_set_sidebars_widgets($sidebars);
1355 case 'save-widget' :
1356 check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
1358 if ( !current_user_can('edit_theme_options') || !isset($_POST['id_base']) )
1361 unset( $_POST['savewidgets'], $_POST['action'] );
1363 do_action('load-widgets.php');
1364 do_action('widgets.php');
1365 do_action('sidebar_admin_setup');
1367 $id_base = $_POST['id_base'];
1368 $widget_id = $_POST['widget-id'];
1369 $sidebar_id = $_POST['sidebar'];
1370 $multi_number = !empty($_POST['multi_number']) ? (int) $_POST['multi_number'] : 0;
1371 $settings = isset($_POST['widget-' . $id_base]) && is_array($_POST['widget-' . $id_base]) ? $_POST['widget-' . $id_base] : false;
1372 $error = '<p>' . __('An error has occurred. Please reload the page and try again.') . '</p>';
1374 $sidebars = wp_get_sidebars_widgets();
1375 $sidebar = isset($sidebars[$sidebar_id]) ? $sidebars[$sidebar_id] : array();
1378 if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
1380 if ( !isset($wp_registered_widgets[$widget_id]) )
1383 $sidebar = array_diff( $sidebar, array($widget_id) );
1384 $_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1');
1385 } elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) {
1386 if ( !$multi_number )
1389 $_POST['widget-' . $id_base] = array( $multi_number => array_shift($settings) );
1390 $widget_id = $id_base . '-' . $multi_number;
1391 $sidebar[] = $widget_id;
1393 $_POST['widget-id'] = $sidebar;
1395 foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
1397 if ( $name == $id_base ) {
1398 if ( !is_callable( $control['callback'] ) )
1402 call_user_func_array( $control['callback'], $control['params'] );
1408 if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
1409 $sidebars[$sidebar_id] = $sidebar;
1410 wp_set_sidebars_widgets($sidebars);
1411 echo "deleted:$widget_id";
1415 if ( !empty($_POST['add_new']) )
1418 if ( $form = $wp_registered_widget_controls[$widget_id] )
1419 call_user_func_array( $form['callback'], $form['params'] );
1423 case 'image-editor':
1424 $attachment_id = intval($_POST['postid']);
1425 if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) )
1428 check_ajax_referer( "image_editor-$attachment_id" );
1429 include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
1432 switch ( $_POST['do'] ) {
1434 $msg = wp_save_image($attachment_id);
1435 $msg = json_encode($msg);
1439 $msg = wp_save_image($attachment_id);
1442 $msg = wp_restore_image($attachment_id);
1446 wp_image_editor($attachment_id, $msg);
1449 case 'set-post-thumbnail':
1450 $post_ID = intval( $_POST['post_id'] );
1451 if ( !current_user_can( 'edit_post', $post_ID ) )
1453 $thumbnail_id = intval( $_POST['thumbnail_id'] );
1455 check_ajax_referer( "set_post_thumbnail-$post_ID" );
1457 if ( $thumbnail_id == '-1' ) {
1458 delete_post_meta( $post_ID, '_thumbnail_id' );
1459 die( _wp_post_thumbnail_html() );
1462 if ( set_post_thumbnail( $post_ID, $thumbnail_id ) )
1463 die( _wp_post_thumbnail_html( $thumbnail_id ) );
1466 case 'date_format' :
1467 die( date_i18n( sanitize_option( 'date_format', $_POST['date'] ) ) );
1469 case 'time_format' :
1470 die( date_i18n( sanitize_option( 'time_format', $_POST['date'] ) ) );
1473 do_action( 'wp_ajax_' . $_POST['action'] );