Wordpress 3.5
[autoinstalls/wordpress.git] / wp-admin / includes / ajax-actions.php
1 <?php
2 /**
3  * WordPress Core Ajax Handlers.
4  *
5  * @package WordPress
6  * @subpackage Administration
7  */
8
9 /*
10  * No-privilege Ajax handlers.
11  */
12
13 function wp_ajax_nopriv_autosave() {
14         $id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
15
16         if ( ! $id )
17                 wp_die( -1 );
18
19         $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() );
20         $x = new WP_Ajax_Response( array(
21                 'what' => 'autosave',
22                 'id' => $id,
23                 'data' => $message
24         ) );
25         $x->send();
26 }
27
28 /*
29  * GET-based Ajax handlers.
30  */
31 function wp_ajax_fetch_list() {
32         global $wp_list_table;
33
34         $list_class = $_GET['list_args']['class'];
35         check_ajax_referer( "fetch-list-$list_class", '_ajax_fetch_list_nonce' );
36
37         $wp_list_table = _get_list_table( $list_class, array( 'screen' => $_GET['list_args']['screen']['id'] ) );
38         if ( ! $wp_list_table )
39                 wp_die( 0 );
40
41         if ( ! $wp_list_table->ajax_user_can() )
42                 wp_die( -1 );
43
44         $wp_list_table->ajax_response();
45
46         wp_die( 0 );
47 }
48 function wp_ajax_ajax_tag_search() {
49         global $wpdb;
50
51         if ( isset( $_GET['tax'] ) ) {
52                 $taxonomy = sanitize_key( $_GET['tax'] );
53                 $tax = get_taxonomy( $taxonomy );
54                 if ( ! $tax )
55                         wp_die( 0 );
56                 if ( ! current_user_can( $tax->cap->assign_terms ) )
57                         wp_die( -1 );
58         } else {
59                 wp_die( 0 );
60         }
61
62         $s = stripslashes( $_GET['q'] );
63
64         $comma = _x( ',', 'tag delimiter' );
65         if ( ',' !== $comma )
66                 $s = str_replace( $comma, ',', $s );
67         if ( false !== strpos( $s, ',' ) ) {
68                 $s = explode( ',', $s );
69                 $s = $s[count( $s ) - 1];
70         }
71         $s = trim( $s );
72         if ( strlen( $s ) < 2 )
73                 wp_die(); // require 2 chars for matching
74
75         $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 ) . '%' ) );
76
77         echo join( $results, "\n" );
78         wp_die();
79 }
80
81 function wp_ajax_wp_compression_test() {
82         if ( !current_user_can( 'manage_options' ) )
83                 wp_die( -1 );
84
85         if ( ini_get('zlib.output_compression') || 'ob_gzhandler' == ini_get('output_handler') ) {
86                 update_site_option('can_compress_scripts', 0);
87                 wp_die( 0 );
88         }
89
90         if ( isset($_GET['test']) ) {
91                 header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
92                 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
93                 header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
94                 header( 'Pragma: no-cache' );
95                 header('Content-Type: application/x-javascript; charset=UTF-8');
96                 $force_gzip = ( defined('ENFORCE_GZIP') && ENFORCE_GZIP );
97                 $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."';
98
99                  if ( 1 == $_GET['test'] ) {
100                         echo $test_str;
101                         wp_die();
102                  } elseif ( 2 == $_GET['test'] ) {
103                         if ( !isset($_SERVER['HTTP_ACCEPT_ENCODING']) )
104                                 wp_die( -1 );
105                         if ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') && function_exists('gzdeflate') && ! $force_gzip ) {
106                                 header('Content-Encoding: deflate');
107                                 $out = gzdeflate( $test_str, 1 );
108                         } elseif ( false !== stripos( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') && function_exists('gzencode') ) {
109                                 header('Content-Encoding: gzip');
110                                 $out = gzencode( $test_str, 1 );
111                         } else {
112                                 wp_die( -1 );
113                         }
114                         echo $out;
115                         wp_die();
116                 } elseif ( 'no' == $_GET['test'] ) {
117                         update_site_option('can_compress_scripts', 0);
118                 } elseif ( 'yes' == $_GET['test'] ) {
119                         update_site_option('can_compress_scripts', 1);
120                 }
121         }
122
123         wp_die( 0 );
124 }
125
126 function wp_ajax_imgedit_preview() {
127         $post_id = intval($_GET['postid']);
128         if ( empty($post_id) || !current_user_can('edit_post', $post_id) )
129                 wp_die( -1 );
130
131         check_ajax_referer( "image_editor-$post_id" );
132
133         include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
134         if ( ! stream_preview_image($post_id) )
135                 wp_die( -1 );
136
137         wp_die();
138 }
139
140 function wp_ajax_oembed_cache() {
141         global $wp_embed;
142
143         $return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0';
144         wp_die( $return );
145 }
146
147 function wp_ajax_autocomplete_user() {
148         if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) )
149                 wp_die( -1 );
150
151         if ( ! is_super_admin() && ! apply_filters( 'autocomplete_users_for_site_admins', false ) )
152                 wp_die( -1 );
153
154         $return = array();
155
156         // Check the type of request
157         if ( isset( $_REQUEST['autocomplete_type'] ) )
158                 $type = $_REQUEST['autocomplete_type'];
159         else
160                 $type = 'add';
161
162         // Exclude current users of this blog
163         if ( isset( $_REQUEST['site_id'] ) )
164                 $id = absint( $_REQUEST['site_id'] );
165         else
166                 $id = get_current_blog_id();
167
168         $include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
169         $exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
170
171         $users = get_users( array(
172                 'blog_id' => false,
173                 'search'  => '*' . $_REQUEST['term'] . '*',
174                 'include' => $include_blog_users,
175                 'exclude' => $exclude_blog_users,
176                 'search_columns' => array( 'user_login', 'user_nicename', 'user_email' ),
177         ) );
178
179         foreach ( $users as $user ) {
180                 $return[] = array(
181                         /* translators: 1: user_login, 2: user_email */
182                         'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ),
183                         'value' => $user->user_login,
184                 );
185         }
186
187         wp_die( json_encode( $return ) );
188 }
189
190 function wp_ajax_dashboard_widgets() {
191         require_once ABSPATH . 'wp-admin/includes/dashboard.php';
192
193         switch ( $_GET['widget'] ) {
194                 case 'dashboard_incoming_links' :
195                         wp_dashboard_incoming_links();
196                         break;
197                 case 'dashboard_primary' :
198                         wp_dashboard_primary();
199                         break;
200                 case 'dashboard_secondary' :
201                         wp_dashboard_secondary();
202                         break;
203                 case 'dashboard_plugins' :
204                         wp_dashboard_plugins();
205                         break;
206         }
207         wp_die();
208 }
209
210 function wp_ajax_logged_in() {
211         wp_die( 1 );
212 }
213
214 /*
215  * Ajax helper.
216  */
217
218 /**
219  * Sends back current comment total and new page links if they need to be updated.
220  *
221  * Contrary to normal success AJAX response ("1"), die with time() on success.
222  *
223  * @since 2.7
224  *
225  * @param int $comment_id
226  * @return die
227  */
228 function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) {
229         $total = (int) @$_POST['_total'];
230         $per_page = (int) @$_POST['_per_page'];
231         $page = (int) @$_POST['_page'];
232         $url = esc_url_raw( @$_POST['_url'] );
233         // JS didn't send us everything we need to know. Just die with success message
234         if ( !$total || !$per_page || !$page || !$url )
235                 wp_die( time() );
236
237         $total += $delta;
238         if ( $total < 0 )
239                 $total = 0;
240
241         // Only do the expensive stuff on a page-break, and about 1 other time per page
242         if ( 0 == $total % $per_page || 1 == mt_rand( 1, $per_page ) ) {
243                 $post_id = 0;
244                 $status = 'total_comments'; // What type of comment count are we looking for?
245                 $parsed = parse_url( $url );
246                 if ( isset( $parsed['query'] ) ) {
247                         parse_str( $parsed['query'], $query_vars );
248                         if ( !empty( $query_vars['comment_status'] ) )
249                                 $status = $query_vars['comment_status'];
250                         if ( !empty( $query_vars['p'] ) )
251                                 $post_id = (int) $query_vars['p'];
252                 }
253
254                 $comment_count = wp_count_comments($post_id);
255
256                 if ( isset( $comment_count->$status ) ) // We're looking for a known type of comment count
257                         $total = $comment_count->$status;
258                         // else use the decremented value from above
259         }
260
261         $time = time(); // The time since the last comment count
262
263         $x = new WP_Ajax_Response( array(
264                 'what' => 'comment',
265                 'id' => $comment_id, // here for completeness - not used
266                 'supplemental' => array(
267                         'total_items_i18n' => sprintf( _n( '1 item', '%s items', $total ), number_format_i18n( $total ) ),
268                         'total_pages' => ceil( $total / $per_page ),
269                         'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ),
270                         'total' => $total,
271                         'time' => $time
272                 )
273         ) );
274         $x->send();
275 }
276
277 /*
278  * POST-based Ajax handlers.
279  */
280
281 function _wp_ajax_add_hierarchical_term() {
282         $action = $_POST['action'];
283         $taxonomy = get_taxonomy(substr($action, 4));
284         check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
285         if ( !current_user_can( $taxonomy->cap->edit_terms ) )
286                 wp_die( -1 );
287         $names = explode(',', $_POST['new'.$taxonomy->name]);
288         $parent = isset($_POST['new'.$taxonomy->name.'_parent']) ? (int) $_POST['new'.$taxonomy->name.'_parent'] : 0;
289         if ( 0 > $parent )
290                 $parent = 0;
291         if ( $taxonomy->name == 'category' )
292                 $post_category = isset($_POST['post_category']) ? (array) $_POST['post_category'] : array();
293         else
294                 $post_category = ( isset($_POST['tax_input']) && isset($_POST['tax_input'][$taxonomy->name]) ) ? (array) $_POST['tax_input'][$taxonomy->name] : array();
295         $checked_categories = array_map( 'absint', (array) $post_category );
296         $popular_ids = wp_popular_terms_checklist($taxonomy->name, 0, 10, false);
297
298         foreach ( $names as $cat_name ) {
299                 $cat_name = trim($cat_name);
300                 $category_nicename = sanitize_title($cat_name);
301                 if ( '' === $category_nicename )
302                         continue;
303                 if ( !$cat_id = term_exists( $cat_name, $taxonomy->name, $parent ) )
304                         $cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) );
305                 if ( is_wp_error( $cat_id ) )
306                         continue;
307                 else if ( is_array( $cat_id ) )
308                         $cat_id = $cat_id['term_id'];
309                 $checked_categories[] = $cat_id;
310                 if ( $parent ) // Do these all at once in a second
311                         continue;
312                 ob_start();
313                         wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name, 'descendants_and_self' => $cat_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids ));
314                 $data = ob_get_contents();
315                 ob_end_clean();
316                 $add = array(
317                         'what' => $taxonomy->name,
318                         'id' => $cat_id,
319                         'data' => str_replace( array("\n", "\t"), '', $data),
320                         'position' => -1
321                 );
322         }
323
324         if ( $parent ) { // Foncy - replace the parent and all its children
325                 $parent = get_term( $parent, $taxonomy->name );
326                 $term_id = $parent->term_id;
327
328                 while ( $parent->parent ) { // get the top parent
329                         $parent = get_term( $parent->parent, $taxonomy->name );
330                         if ( is_wp_error( $parent ) )
331                                 break;
332                         $term_id = $parent->term_id;
333                 }
334
335                 ob_start();
336                         wp_terms_checklist( 0, array('taxonomy' => $taxonomy->name, 'descendants_and_self' => $term_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids));
337                 $data = ob_get_contents();
338                 ob_end_clean();
339                 $add = array(
340                         'what' => $taxonomy->name,
341                         'id' => $term_id,
342                         'data' => str_replace( array("\n", "\t"), '', $data),
343                         'position' => -1
344                 );
345         }
346
347         ob_start();
348                 wp_dropdown_categories( array(
349                         'taxonomy' => $taxonomy->name, 'hide_empty' => 0, 'name' => 'new'.$taxonomy->name.'_parent', 'orderby' => 'name',
350                         'hierarchical' => 1, 'show_option_none' => '&mdash; '.$taxonomy->labels->parent_item.' &mdash;'
351                 ) );
352         $sup = ob_get_contents();
353         ob_end_clean();
354         $add['supplemental'] = array( 'newcat_parent' => $sup );
355
356         $x = new WP_Ajax_Response( $add );
357         $x->send();
358 }
359
360 function wp_ajax_delete_comment() {
361         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
362
363         if ( !$comment = get_comment( $id ) )
364                 wp_die( time() );
365         if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) )
366                 wp_die( -1 );
367
368         check_ajax_referer( "delete-comment_$id" );
369         $status = wp_get_comment_status( $comment->comment_ID );
370
371         $delta = -1;
372         if ( isset($_POST['trash']) && 1 == $_POST['trash'] ) {
373                 if ( 'trash' == $status )
374                         wp_die( time() );
375                 $r = wp_trash_comment( $comment->comment_ID );
376         } elseif ( isset($_POST['untrash']) && 1 == $_POST['untrash'] ) {
377                 if ( 'trash' != $status )
378                         wp_die( time() );
379                 $r = wp_untrash_comment( $comment->comment_ID );
380                 if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'trash' ) // undo trash, not in trash
381                         $delta = 1;
382         } elseif ( isset($_POST['spam']) && 1 == $_POST['spam'] ) {
383                 if ( 'spam' == $status )
384                         wp_die( time() );
385                 $r = wp_spam_comment( $comment->comment_ID );
386         } elseif ( isset($_POST['unspam']) && 1 == $_POST['unspam'] ) {
387                 if ( 'spam' != $status )
388                         wp_die( time() );
389                 $r = wp_unspam_comment( $comment->comment_ID );
390                 if ( ! isset( $_POST['comment_status'] ) || $_POST['comment_status'] != 'spam' ) // undo spam, not in spam
391                         $delta = 1;
392         } elseif ( isset($_POST['delete']) && 1 == $_POST['delete'] ) {
393                 $r = wp_delete_comment( $comment->comment_ID );
394         } else {
395                 wp_die( -1 );
396         }
397
398         if ( $r ) // Decide if we need to send back '1' or a more complicated response including page links and comment counts
399                 _wp_ajax_delete_comment_response( $comment->comment_ID, $delta );
400         wp_die( 0 );
401 }
402
403 function wp_ajax_delete_tag() {
404         $tag_id = (int) $_POST['tag_ID'];
405         check_ajax_referer( "delete-tag_$tag_id" );
406
407         $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
408         $tax = get_taxonomy($taxonomy);
409
410         if ( !current_user_can( $tax->cap->delete_terms ) )
411                 wp_die( -1 );
412
413         $tag = get_term( $tag_id, $taxonomy );
414         if ( !$tag || is_wp_error( $tag ) )
415                 wp_die( 1 );
416
417         if ( wp_delete_term($tag_id, $taxonomy))
418                 wp_die( 1 );
419         else
420                 wp_die( 0 );
421 }
422
423 function wp_ajax_delete_link() {
424         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
425
426         check_ajax_referer( "delete-bookmark_$id" );
427         if ( !current_user_can( 'manage_links' ) )
428                 wp_die( -1 );
429
430         $link = get_bookmark( $id );
431         if ( !$link || is_wp_error( $link ) )
432                 wp_die( 1 );
433
434         if ( wp_delete_link( $id ) )
435                 wp_die( 1 );
436         else
437                 wp_die( 0 );
438 }
439
440 function wp_ajax_delete_meta() {
441         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
442
443         check_ajax_referer( "delete-meta_$id" );
444         if ( !$meta = get_metadata_by_mid( 'post', $id ) )
445                 wp_die( 1 );
446
447         if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta',  $meta->post_id, $meta->meta_key ) )
448                 wp_die( -1 );
449         if ( delete_meta( $meta->meta_id ) )
450                 wp_die( 1 );
451         wp_die( 0 );
452 }
453
454 function wp_ajax_delete_post( $action ) {
455         if ( empty( $action ) )
456                 $action = 'delete-post';
457         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
458
459         check_ajax_referer( "{$action}_$id" );
460         if ( !current_user_can( 'delete_post', $id ) )
461                 wp_die( -1 );
462
463         if ( !get_post( $id ) )
464                 wp_die( 1 );
465
466         if ( wp_delete_post( $id ) )
467                 wp_die( 1 );
468         else
469                 wp_die( 0 );
470 }
471
472 function wp_ajax_trash_post( $action ) {
473         if ( empty( $action ) )
474                 $action = 'trash-post';
475         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
476
477         check_ajax_referer( "{$action}_$id" );
478         if ( !current_user_can( 'delete_post', $id ) )
479                 wp_die( -1 );
480
481         if ( !get_post( $id ) )
482                 wp_die( 1 );
483
484         if ( 'trash-post' == $action )
485                 $done = wp_trash_post( $id );
486         else
487                 $done = wp_untrash_post( $id );
488
489         if ( $done )
490                 wp_die( 1 );
491
492         wp_die( 0 );
493 }
494
495 function wp_ajax_untrash_post( $action ) {
496         if ( empty( $action ) )
497                 $action = 'untrash-post';
498         wp_ajax_trash_post( $action );
499 }
500
501 function wp_ajax_delete_page( $action ) {
502         if ( empty( $action ) )
503                 $action = 'delete-page';
504         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
505
506         check_ajax_referer( "{$action}_$id" );
507         if ( !current_user_can( 'delete_page', $id ) )
508                 wp_die( -1 );
509
510         if ( ! get_post( $id ) )
511                 wp_die( 1 );
512
513         if ( wp_delete_post( $id ) )
514                 wp_die( 1 );
515         else
516                 wp_die( 0 );
517 }
518
519 function wp_ajax_dim_comment() {
520         $id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
521
522         if ( !$comment = get_comment( $id ) ) {
523                 $x = new WP_Ajax_Response( array(
524                         'what' => 'comment',
525                         'id' => new WP_Error('invalid_comment', sprintf(__('Comment %d does not exist'), $id))
526                 ) );
527                 $x->send();
528         }
529
530         if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) && ! current_user_can( 'moderate_comments' ) )
531                 wp_die( -1 );
532
533         $current = wp_get_comment_status( $comment->comment_ID );
534         if ( $_POST['new'] == $current )
535                 wp_die( time() );
536
537         check_ajax_referer( "approve-comment_$id" );
538         if ( in_array( $current, array( 'unapproved', 'spam' ) ) )
539                 $result = wp_set_comment_status( $comment->comment_ID, 'approve', true );
540         else
541                 $result = wp_set_comment_status( $comment->comment_ID, 'hold', true );
542
543         if ( is_wp_error($result) ) {
544                 $x = new WP_Ajax_Response( array(
545                         'what' => 'comment',
546                         'id' => $result
547                 ) );
548                 $x->send();
549         }
550
551         // Decide if we need to send back '1' or a more complicated response including page links and comment counts
552         _wp_ajax_delete_comment_response( $comment->comment_ID );
553         wp_die( 0 );
554 }
555
556 function wp_ajax_add_link_category( $action ) {
557         if ( empty( $action ) )
558                 $action = 'add-link-category';
559         check_ajax_referer( $action );
560         if ( !current_user_can( 'manage_categories' ) )
561                 wp_die( -1 );
562         $names = explode(',', $_POST['newcat']);
563         $x = new WP_Ajax_Response();
564         foreach ( $names as $cat_name ) {
565                 $cat_name = trim($cat_name);
566                 $slug = sanitize_title($cat_name);
567                 if ( '' === $slug )
568                         continue;
569                 if ( !$cat_id = term_exists( $cat_name, 'link_category' ) )
570                         $cat_id = wp_insert_term( $cat_name, 'link_category' );
571                 if ( is_wp_error( $cat_id ) )
572                         continue;
573                 else if ( is_array( $cat_id ) )
574                         $cat_id = $cat_id['term_id'];
575                 $cat_name = esc_html(stripslashes($cat_name));
576                 $x->add( array(
577                         'what' => 'link-category',
578                         'id' => $cat_id,
579                         '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>",
580                         'position' => -1
581                 ) );
582         }
583         $x->send();
584 }
585
586 function wp_ajax_add_tag() {
587         global $wp_list_table;
588
589         check_ajax_referer( 'add-tag', '_wpnonce_add-tag' );
590         $post_type = !empty($_POST['post_type']) ? $_POST['post_type'] : 'post';
591         $taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
592         $tax = get_taxonomy($taxonomy);
593
594         if ( !current_user_can( $tax->cap->edit_terms ) )
595                 wp_die( -1 );
596
597         $x = new WP_Ajax_Response();
598
599         $tag = wp_insert_term($_POST['tag-name'], $taxonomy, $_POST );
600
601         if ( !$tag || is_wp_error($tag) || (!$tag = get_term( $tag['term_id'], $taxonomy )) ) {
602                 $message = __('An error has occurred. Please reload the page and try again.');
603                 if ( is_wp_error($tag) && $tag->get_error_message() )
604                         $message = $tag->get_error_message();
605
606                 $x->add( array(
607                         'what' => 'taxonomy',
608                         'data' => new WP_Error('error', $message )
609                 ) );
610                 $x->send();
611         }
612
613         $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
614
615         $level = 0;
616         if ( is_taxonomy_hierarchical($taxonomy) ) {
617                 $level = count( get_ancestors( $tag->term_id, $taxonomy ) );
618                 ob_start();
619                 $wp_list_table->single_row( $tag, $level );
620                 $noparents = ob_get_clean();
621         }
622
623         ob_start();
624         $wp_list_table->single_row( $tag );
625         $parents = ob_get_clean();
626
627         $x->add( array(
628                 'what' => 'taxonomy',
629                 'supplemental' => compact('parents', 'noparents')
630                 ) );
631         $x->add( array(
632                 'what' => 'term',
633                 'position' => $level,
634                 'supplemental' => (array) $tag
635                 ) );
636         $x->send();
637 }
638
639 function wp_ajax_get_tagcloud() {
640         if ( isset( $_POST['tax'] ) ) {
641                 $taxonomy = sanitize_key( $_POST['tax'] );
642                 $tax = get_taxonomy( $taxonomy );
643                 if ( ! $tax )
644                         wp_die( 0 );
645                 if ( ! current_user_can( $tax->cap->assign_terms ) )
646                         wp_die( -1 );
647         } else {
648                 wp_die( 0 );
649         }
650
651         $tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) );
652
653         if ( empty( $tags ) )
654                 wp_die( isset( $tax->no_tagcloud ) ? $tax->no_tagcloud : __('No tags found!') );
655
656         if ( is_wp_error( $tags ) )
657                 wp_die( $tags->get_error_message() );
658
659         foreach ( $tags as $key => $tag ) {
660                 $tags[ $key ]->link = '#';
661                 $tags[ $key ]->id = $tag->term_id;
662         }
663
664         // We need raw tag names here, so don't filter the output
665         $return = wp_generate_tag_cloud( $tags, array('filter' => 0) );
666
667         if ( empty($return) )
668                 wp_die( 0 );
669
670         echo $return;
671
672         wp_die();
673 }
674
675 function wp_ajax_get_comments( $action ) {
676         global $wp_list_table, $post_id;
677         if ( empty( $action ) )
678                 $action = 'get-comments';
679
680         check_ajax_referer( $action );
681
682         $wp_list_table = _get_list_table( 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
683
684         if ( !current_user_can( 'edit_post', $post_id ) )
685                 wp_die( -1 );
686
687         $wp_list_table->prepare_items();
688
689         if ( !$wp_list_table->has_items() )
690                 wp_die( 1 );
691
692         $x = new WP_Ajax_Response();
693         ob_start();
694         foreach ( $wp_list_table->items as $comment ) {
695                 if ( ! current_user_can( 'edit_comment', $comment->comment_ID ) )
696                         continue;
697                 get_comment( $comment );
698                 $wp_list_table->single_row( $comment );
699         }
700         $comment_list_item = ob_get_contents();
701         ob_end_clean();
702
703         $x->add( array(
704                 'what' => 'comments',
705                 'data' => $comment_list_item
706         ) );
707         $x->send();
708 }
709
710 function wp_ajax_replyto_comment( $action ) {
711         global $wp_list_table, $wpdb;
712         if ( empty( $action ) )
713                 $action = 'replyto-comment';
714
715         check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );
716
717         $comment_post_ID = (int) $_POST['comment_post_ID'];
718         if ( !current_user_can( 'edit_post', $comment_post_ID ) )
719                 wp_die( -1 );
720
721         $status = $wpdb->get_var( $wpdb->prepare("SELECT post_status FROM $wpdb->posts WHERE ID = %d", $comment_post_ID) );
722
723         if ( empty($status) )
724                 wp_die( 1 );
725         elseif ( in_array($status, array('draft', 'pending', 'trash') ) )
726                 wp_die( __('ERROR: you are replying to a comment on a draft post.') );
727
728         $user = wp_get_current_user();
729         if ( $user->exists() ) {
730                 $user_ID = $user->ID;
731                 $comment_author       = $wpdb->escape($user->display_name);
732                 $comment_author_email = $wpdb->escape($user->user_email);
733                 $comment_author_url   = $wpdb->escape($user->user_url);
734                 $comment_content      = trim($_POST['content']);
735                 if ( current_user_can( 'unfiltered_html' ) ) {
736                         if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) {
737                                 kses_remove_filters(); // start with a clean slate
738                                 kses_init_filters(); // set up the filters
739                         }
740                 }
741         } else {
742                 wp_die( __( 'Sorry, you must be logged in to reply to a comment.' ) );
743         }
744
745         if ( '' == $comment_content )
746                 wp_die( __( 'ERROR: please type a comment.' ) );
747
748         $comment_parent = absint($_POST['comment_ID']);
749         $comment_auto_approved = false;
750         $commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
751
752         // automatically approve parent comment
753         if ( !empty($_POST['approve_parent']) ) {
754                 $parent = get_comment( $comment_parent );
755
756                 if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) {
757                         if ( wp_set_comment_status( $parent->comment_ID, 'approve' ) )
758                                 $comment_auto_approved = true;
759                 }
760         }
761
762         $comment_id = wp_new_comment( $commentdata );
763         $comment = get_comment($comment_id);
764         if ( ! $comment ) wp_die( 1 );
765
766         $position = ( isset($_POST['position']) && (int) $_POST['position'] ) ? (int) $_POST['position'] : '-1';
767
768         ob_start();
769                 if ( 'dashboard' == $_REQUEST['mode'] ) {
770                         require_once( ABSPATH . 'wp-admin/includes/dashboard.php' );
771                         _wp_dashboard_recent_comments_row( $comment );
772                 } else {
773                         if ( 'single' == $_REQUEST['mode'] ) {
774                                 $wp_list_table = _get_list_table('WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
775                         } else {
776                                 $wp_list_table = _get_list_table('WP_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
777                         }
778                         $wp_list_table->single_row( $comment );
779                 }
780                 $comment_list_item = ob_get_contents();
781         ob_end_clean();
782
783         $response =  array(
784                 'what' => 'comment',
785                 'id' => $comment->comment_ID,
786                 'data' => $comment_list_item,
787                 'position' => $position
788         );
789
790         if ( $comment_auto_approved )
791                 $response['supplemental'] = array( 'parent_approved' => $parent->comment_ID );
792
793         $x = new WP_Ajax_Response();
794         $x->add( $response );
795         $x->send();
796 }
797
798 function wp_ajax_edit_comment() {
799         global $wp_list_table;
800
801         check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' );
802
803         $comment_id = (int) $_POST['comment_ID'];
804         if ( ! current_user_can( 'edit_comment', $comment_id ) )
805                 wp_die( -1 );
806
807         if ( '' == $_POST['content'] )
808                 wp_die( __( 'ERROR: please type a comment.' ) );
809
810         $_POST['comment_status'] = $_POST['status'];
811         edit_comment();
812
813         $position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1';
814         $comments_status = isset($_POST['comments_listing']) ? $_POST['comments_listing'] : '';
815
816         $checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0;
817         $wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
818
819         $comment = get_comment( $comment_id );
820
821         ob_start();
822                 $wp_list_table->single_row( $comment );
823                 $comment_list_item = ob_get_contents();
824         ob_end_clean();
825
826         $x = new WP_Ajax_Response();
827
828         $x->add( array(
829                 'what' => 'edit_comment',
830                 'id' => $comment->comment_ID,
831                 'data' => $comment_list_item,
832                 'position' => $position
833         ));
834
835         $x->send();
836 }
837
838 function wp_ajax_add_menu_item() {
839         check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
840
841         if ( ! current_user_can( 'edit_theme_options' ) )
842                 wp_die( -1 );
843
844         require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
845
846         // For performance reasons, we omit some object properties from the checklist.
847         // The following is a hacky way to restore them when adding non-custom items.
848
849         $menu_items_data = array();
850         foreach ( (array) $_POST['menu-item'] as $menu_item_data ) {
851                 if (
852                         ! empty( $menu_item_data['menu-item-type'] ) &&
853                         'custom' != $menu_item_data['menu-item-type'] &&
854                         ! empty( $menu_item_data['menu-item-object-id'] )
855                 ) {
856                         switch( $menu_item_data['menu-item-type'] ) {
857                                 case 'post_type' :
858                                         $_object = get_post( $menu_item_data['menu-item-object-id'] );
859                                 break;
860
861                                 case 'taxonomy' :
862                                         $_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
863                                 break;
864                         }
865
866                         $_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
867                         $_menu_item = array_shift( $_menu_items );
868
869                         // Restore the missing menu item properties
870                         $menu_item_data['menu-item-description'] = $_menu_item->description;
871                 }
872
873                 $menu_items_data[] = $menu_item_data;
874         }
875
876         $item_ids = wp_save_nav_menu_items( 0, $menu_items_data );
877         if ( is_wp_error( $item_ids ) )
878                 wp_die( 0 );
879
880         $menu_items = array();
881
882         foreach ( (array) $item_ids as $menu_item_id ) {
883                 $menu_obj = get_post( $menu_item_id );
884                 if ( ! empty( $menu_obj->ID ) ) {
885                         $menu_obj = wp_setup_nav_menu_item( $menu_obj );
886                         $menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items
887                         $menu_items[] = $menu_obj;
888                 }
889         }
890
891         $walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] );
892
893         if ( ! class_exists( $walker_class_name ) )
894                 wp_die( 0 );
895
896         if ( ! empty( $menu_items ) ) {
897                 $args = array(
898                         'after' => '',
899                         'before' => '',
900                         'link_after' => '',
901                         'link_before' => '',
902                         'walker' => new $walker_class_name,
903                 );
904                 echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
905         }
906 }
907
908 function wp_ajax_add_meta() {
909         check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' );
910         $c = 0;
911         $pid = (int) $_POST['post_id'];
912         $post = get_post( $pid );
913
914         if ( isset($_POST['metakeyselect']) || isset($_POST['metakeyinput']) ) {
915                 if ( !current_user_can( 'edit_post', $pid ) )
916                         wp_die( -1 );
917                 if ( isset($_POST['metakeyselect']) && '#NONE#' == $_POST['metakeyselect'] && empty($_POST['metakeyinput']) )
918                         wp_die( 1 );
919                 if ( $post->post_status == 'auto-draft' ) {
920                         $save_POST = $_POST; // Backup $_POST
921                         $_POST = array(); // Make it empty for edit_post()
922                         $_POST['action'] = 'draft'; // Warning fix
923                         $_POST['post_ID'] = $pid;
924                         $_POST['post_type'] = $post->post_type;
925                         $_POST['post_status'] = 'draft';
926                         $now = current_time('timestamp', 1);
927                         $_POST['post_title'] = sprintf('Draft created on %s at %s', date(get_option('date_format'), $now), date(get_option('time_format'), $now));
928
929                         if ( $pid = edit_post() ) {
930                                 if ( is_wp_error( $pid ) ) {
931                                         $x = new WP_Ajax_Response( array(
932                                                 'what' => 'meta',
933                                                 'data' => $pid
934                                         ) );
935                                         $x->send();
936                                 }
937                                 $_POST = $save_POST; // Now we can restore original $_POST again
938                                 if ( !$mid = add_meta( $pid ) )
939                                         wp_die( __( 'Please provide a custom field value.' ) );
940                         } else {
941                                 wp_die( 0 );
942                         }
943                 } else if ( !$mid = add_meta( $pid ) ) {
944                         wp_die( __( 'Please provide a custom field value.' ) );
945                 }
946
947                 $meta = get_metadata_by_mid( 'post', $mid );
948                 $pid = (int) $meta->post_id;
949                 $meta = get_object_vars( $meta );
950                 $x = new WP_Ajax_Response( array(
951                         'what' => 'meta',
952                         'id' => $mid,
953                         'data' => _list_meta_row( $meta, $c ),
954                         'position' => 1,
955                         'supplemental' => array('postid' => $pid)
956                 ) );
957         } else { // Update?
958                 $mid = (int) key( $_POST['meta'] );
959                 $key = stripslashes( $_POST['meta'][$mid]['key'] );
960                 $value = stripslashes( $_POST['meta'][$mid]['value'] );
961                 if ( '' == trim($key) )
962                         wp_die( __( 'Please provide a custom field name.' ) );
963                 if ( '' == trim($value) )
964                         wp_die( __( 'Please provide a custom field value.' ) );
965                 if ( ! $meta = get_metadata_by_mid( 'post', $mid ) )
966                         wp_die( 0 ); // if meta doesn't exist
967                 if ( is_protected_meta( $meta->meta_key, 'post' ) || is_protected_meta( $key, 'post' ) ||
968                         ! current_user_can( 'edit_post_meta', $meta->post_id, $meta->meta_key ) ||
969                         ! current_user_can( 'edit_post_meta', $meta->post_id, $key ) )
970                         wp_die( -1 );
971                 if ( $meta->meta_value != $value || $meta->meta_key != $key ) {
972                         if ( !$u = update_metadata_by_mid( 'post', $mid, $value, $key ) )
973                                 wp_die( 0 ); // We know meta exists; we also know it's unchanged (or DB error, in which case there are bigger problems).
974                 }
975
976                 $x = new WP_Ajax_Response( array(
977                         'what' => 'meta',
978                         'id' => $mid, 'old_id' => $mid,
979                         'data' => _list_meta_row( array(
980                                 'meta_key' => $key,
981                                 'meta_value' => $value,
982                                 'meta_id' => $mid
983                         ), $c ),
984                         'position' => 0,
985                         'supplemental' => array('postid' => $meta->post_id)
986                 ) );
987         }
988         $x->send();
989 }
990
991 function wp_ajax_add_user( $action ) {
992         global $wp_list_table;
993         if ( empty( $action ) )
994                 $action = 'add-user';
995
996         check_ajax_referer( $action );
997         if ( ! current_user_can('create_users') )
998                 wp_die( -1 );
999         if ( ! $user_id = edit_user() ) {
1000                 wp_die( 0 );
1001         } elseif ( is_wp_error( $user_id ) ) {
1002                 $x = new WP_Ajax_Response( array(
1003                         'what' => 'user',
1004                         'id' => $user_id
1005                 ) );
1006                 $x->send();
1007         }
1008         $user_object = get_userdata( $user_id );
1009
1010         $wp_list_table = _get_list_table('WP_Users_List_Table');
1011
1012         $role = current( $user_object->roles );
1013
1014         $x = new WP_Ajax_Response( array(
1015                 'what' => 'user',
1016                 'id' => $user_id,
1017                 'data' => $wp_list_table->single_row( $user_object, '', $role ),
1018                 'supplemental' => array(
1019                         'show-link' => sprintf(__( 'User <a href="#%s">%s</a> added' ), "user-$user_id", $user_object->user_login),
1020                         'role' => $role,
1021                 )
1022         ) );
1023         $x->send();
1024 }
1025
1026 function wp_ajax_autosave() {
1027         global $login_grace_period;
1028
1029         define( 'DOING_AUTOSAVE', true );
1030
1031         $nonce_age = check_ajax_referer( 'autosave', 'autosavenonce' );
1032
1033         $_POST['post_category'] = explode(",", $_POST['catslist']);
1034         if ( $_POST['post_type'] == 'page' || empty($_POST['post_category']) )
1035                 unset($_POST['post_category']);
1036
1037         $do_autosave = (bool) $_POST['autosave'];
1038         $do_lock = true;
1039
1040         $data = $alert = '';
1041         /* translators: draft saved date format, see http://php.net/date */
1042         $draft_saved_date_format = __('g:i:s a');
1043         /* translators: %s: date and time */
1044         $message = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
1045
1046         $supplemental = array();
1047         if ( isset($login_grace_period) )
1048                 $alert .= sprintf( __('Your login has expired. Please open a new browser window and <a href="%s" target="_blank">log in again</a>. '), add_query_arg( 'interim-login', 1, wp_login_url() ) );
1049
1050         $id = $revision_id = 0;
1051
1052         $post_ID = (int) $_POST['post_ID'];
1053         $_POST['ID'] = $post_ID;
1054         $post = get_post($post_ID);
1055         if ( 'auto-draft' == $post->post_status )
1056                 $_POST['post_status'] = 'draft';
1057
1058         if ( $last = wp_check_post_lock( $post->ID ) ) {
1059                 $do_autosave = $do_lock = false;
1060
1061                 $last_user = get_userdata( $last );
1062                 $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
1063                 $data = __( 'Autosave disabled.' );
1064
1065                 $supplemental['disable_autosave'] = 'disable';
1066                 $alert .= sprintf( __( '%s is currently editing this article. If you update it, you will overwrite the changes.' ), esc_html( $last_user_name ) );
1067         }
1068
1069         if ( 'page' == $post->post_type ) {
1070                 if ( !current_user_can('edit_page', $post_ID) )
1071                         wp_die( __( 'You are not allowed to edit this page.' ) );
1072         } else {
1073                 if ( !current_user_can('edit_post', $post_ID) )
1074                         wp_die( __( 'You are not allowed to edit this post.' ) );
1075         }
1076
1077         if ( $do_autosave ) {
1078                 // Drafts and auto-drafts are just overwritten by autosave
1079                 if ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) {
1080                         $id = edit_post();
1081                 } else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
1082                         $revision_id = wp_create_post_autosave( $post->ID );
1083                         if ( is_wp_error($revision_id) )
1084                                 $id = $revision_id;
1085                         else
1086                                 $id = $post->ID;
1087                 }
1088                 $data = $message;
1089         } else {
1090                 if ( ! empty( $_POST['auto_draft'] ) )
1091                         $id = 0; // This tells us it didn't actually save
1092                 else
1093                         $id = $post->ID;
1094         }
1095
1096         if ( $do_lock && empty( $_POST['auto_draft'] ) && $id && is_numeric( $id ) ) {
1097                 $lock_result = wp_set_post_lock( $id );
1098                 $supplemental['active-post-lock'] = implode( ':', $lock_result );
1099         }
1100
1101         if ( $nonce_age == 2 ) {
1102                 $supplemental['replace-autosavenonce'] = wp_create_nonce('autosave');
1103                 $supplemental['replace-getpermalinknonce'] = wp_create_nonce('getpermalink');
1104                 $supplemental['replace-samplepermalinknonce'] = wp_create_nonce('samplepermalink');
1105                 $supplemental['replace-closedpostboxesnonce'] = wp_create_nonce('closedpostboxes');
1106                 $supplemental['replace-_ajax_linking_nonce'] = wp_create_nonce( 'internal-linking' );
1107                 if ( $id ) {
1108                         if ( $_POST['post_type'] == 'post' )
1109                                 $supplemental['replace-_wpnonce'] = wp_create_nonce('update-post_' . $id);
1110                         elseif ( $_POST['post_type'] == 'page' )
1111                                 $supplemental['replace-_wpnonce'] = wp_create_nonce('update-page_' . $id);
1112                 }
1113         }
1114
1115         if ( ! empty($alert) )
1116                 $supplemental['alert'] = $alert;
1117
1118         $x = new WP_Ajax_Response( array(
1119                 'what' => 'autosave',
1120                 'id' => $id,
1121                 'data' => $id ? $data : '',
1122                 'supplemental' => $supplemental
1123         ) );
1124         $x->send();
1125 }
1126
1127 function wp_ajax_closed_postboxes() {
1128         check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
1129         $closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array();
1130         $closed = array_filter($closed);
1131
1132         $hidden = isset( $_POST['hidden'] ) ? explode( ',', $_POST['hidden']) : array();
1133         $hidden = array_filter($hidden);
1134
1135         $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1136
1137         if ( $page != sanitize_key( $page ) )
1138                 wp_die( 0 );
1139
1140         if ( ! $user = wp_get_current_user() )
1141                 wp_die( -1 );
1142
1143         if ( is_array($closed) )
1144                 update_user_option($user->ID, "closedpostboxes_$page", $closed, true);
1145
1146         if ( is_array($hidden) ) {
1147                 $hidden = array_diff( $hidden, array('submitdiv', 'linksubmitdiv', 'manage-menu', 'create-menu') ); // postboxes that are always shown
1148                 update_user_option($user->ID, "metaboxhidden_$page", $hidden, true);
1149         }
1150
1151         wp_die( 1 );
1152 }
1153
1154 function wp_ajax_hidden_columns() {
1155         check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' );
1156         $hidden = isset( $_POST['hidden'] ) ? $_POST['hidden'] : '';
1157         $hidden = explode( ',', $_POST['hidden'] );
1158         $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1159
1160         if ( $page != sanitize_key( $page ) )
1161                 wp_die( 0 );
1162
1163         if ( ! $user = wp_get_current_user() )
1164                 wp_die( -1 );
1165
1166         if ( is_array($hidden) )
1167                 update_user_option($user->ID, "manage{$page}columnshidden", $hidden, true);
1168
1169         wp_die( 1 );
1170 }
1171
1172 function wp_ajax_update_welcome_panel() {
1173         check_ajax_referer( 'welcome-panel-nonce', 'welcomepanelnonce' );
1174
1175         if ( ! current_user_can( 'edit_theme_options' ) )
1176                 wp_die( -1 );
1177
1178         update_user_meta( get_current_user_id(), 'show_welcome_panel', empty( $_POST['visible'] ) ? 0 : 1 );
1179
1180         wp_die( 1 );
1181 }
1182
1183 function wp_ajax_menu_get_metabox() {
1184         if ( ! current_user_can( 'edit_theme_options' ) )
1185                 wp_die( -1 );
1186
1187         require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
1188
1189         if ( isset( $_POST['item-type'] ) && 'post_type' == $_POST['item-type'] ) {
1190                 $type = 'posttype';
1191                 $callback = 'wp_nav_menu_item_post_type_meta_box';
1192                 $items = (array) get_post_types( array( 'show_in_nav_menus' => true ), 'object' );
1193         } elseif ( isset( $_POST['item-type'] ) && 'taxonomy' == $_POST['item-type'] ) {
1194                 $type = 'taxonomy';
1195                 $callback = 'wp_nav_menu_item_taxonomy_meta_box';
1196                 $items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' );
1197         }
1198
1199         if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) {
1200                 $item = apply_filters( 'nav_menu_meta_box_object', $items[ $_POST['item-object'] ] );
1201                 ob_start();
1202                 call_user_func_array($callback, array(
1203                         null,
1204                         array(
1205                                 'id' => 'add-' . $item->name,
1206                                 'title' => $item->labels->name,
1207                                 'callback' => $callback,
1208                                 'args' => $item,
1209                         )
1210                 ));
1211
1212                 $markup = ob_get_clean();
1213
1214                 echo json_encode(array(
1215                         'replace-id' => $type . '-' . $item->name,
1216                         'markup' => $markup,
1217                 ));
1218         }
1219
1220         wp_die();
1221 }
1222
1223 function wp_ajax_wp_link_ajax() {
1224         check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' );
1225
1226         $args = array();
1227
1228         if ( isset( $_POST['search'] ) )
1229                 $args['s'] = stripslashes( $_POST['search'] );
1230         $args['pagenum'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
1231
1232         require(ABSPATH . WPINC . '/class-wp-editor.php');
1233         $results = _WP_Editors::wp_link_query( $args );
1234
1235         if ( ! isset( $results ) )
1236                 wp_die( 0 );
1237
1238         echo json_encode( $results );
1239         echo "\n";
1240
1241         wp_die();
1242 }
1243
1244 function wp_ajax_menu_locations_save() {
1245         if ( ! current_user_can( 'edit_theme_options' ) )
1246                 wp_die( -1 );
1247         check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
1248         if ( ! isset( $_POST['menu-locations'] ) )
1249                 wp_die( 0 );
1250         set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) );
1251         wp_die( 1 );
1252 }
1253
1254 function wp_ajax_meta_box_order() {
1255         check_ajax_referer( 'meta-box-order' );
1256         $order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false;
1257         $page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto';
1258
1259         if ( $page_columns != 'auto' )
1260                 $page_columns = (int) $page_columns;
1261
1262         $page = isset( $_POST['page'] ) ? $_POST['page'] : '';
1263
1264         if ( $page != sanitize_key( $page ) )
1265                 wp_die( 0 );
1266
1267         if ( ! $user = wp_get_current_user() )
1268                 wp_die( -1 );
1269
1270         if ( $order )
1271                 update_user_option($user->ID, "meta-box-order_$page", $order, true);
1272
1273         if ( $page_columns )
1274                 update_user_option($user->ID, "screen_layout_$page", $page_columns, true);
1275
1276         wp_die( 1 );
1277 }
1278
1279 function wp_ajax_menu_quick_search() {
1280         if ( ! current_user_can( 'edit_theme_options' ) )
1281                 wp_die( -1 );
1282
1283         require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
1284
1285         _wp_ajax_menu_quick_search( $_POST );
1286
1287         wp_die();
1288 }
1289
1290 function wp_ajax_get_permalink() {
1291         check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
1292         $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
1293         wp_die( add_query_arg( array( 'preview' => 'true' ), get_permalink( $post_id ) ) );
1294 }
1295
1296 function wp_ajax_sample_permalink() {
1297         check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' );
1298         $post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
1299         $title = isset($_POST['new_title'])? $_POST['new_title'] : '';
1300         $slug = isset($_POST['new_slug'])? $_POST['new_slug'] : null;
1301         wp_die( get_sample_permalink_html( $post_id, $title, $slug ) );
1302 }
1303
1304 function wp_ajax_inline_save() {
1305         global $wp_list_table;
1306
1307         check_ajax_referer( 'inlineeditnonce', '_inline_edit' );
1308
1309         if ( ! isset($_POST['post_ID']) || ! ( $post_ID = (int) $_POST['post_ID'] ) )
1310                 wp_die();
1311
1312         if ( 'page' == $_POST['post_type'] ) {
1313                 if ( ! current_user_can( 'edit_page', $post_ID ) )
1314                         wp_die( __( 'You are not allowed to edit this page.' ) );
1315         } else {
1316                 if ( ! current_user_can( 'edit_post', $post_ID ) )
1317                         wp_die( __( 'You are not allowed to edit this post.' ) );
1318         }
1319
1320         if ( $last = wp_check_post_lock( $post_ID ) ) {
1321                 $last_user = get_userdata( $last );
1322                 $last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
1323                 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 ) );
1324                 wp_die();
1325         }
1326
1327         $data = &$_POST;
1328
1329         $post = get_post( $post_ID, ARRAY_A );
1330         $post = add_magic_quotes($post); //since it is from db
1331
1332         $data['content'] = $post['post_content'];
1333         $data['excerpt'] = $post['post_excerpt'];
1334
1335         // rename
1336         $data['user_ID'] = $GLOBALS['user_ID'];
1337
1338         if ( isset($data['post_parent']) )
1339                 $data['parent_id'] = $data['post_parent'];
1340
1341         // status
1342         if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
1343                 $data['post_status'] = 'private';
1344         else
1345                 $data['post_status'] = $data['_status'];
1346
1347         if ( empty($data['comment_status']) )
1348                 $data['comment_status'] = 'closed';
1349         if ( empty($data['ping_status']) )
1350                 $data['ping_status'] = 'closed';
1351
1352         // update the post
1353         edit_post();
1354
1355         $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
1356
1357         $mode = $_POST['post_view'];
1358
1359         $level = 0;
1360         $request_post = array( get_post( $_POST['post_ID'] ) );
1361         $parent = $request_post[0]->post_parent;
1362
1363         while ( $parent > 0 ) {
1364                 $parent_post = get_post( $parent );
1365                 $parent = $parent_post->post_parent;
1366                 $level++;
1367         }
1368
1369         $wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level );
1370
1371         wp_die();
1372 }
1373
1374 function wp_ajax_inline_save_tax() {
1375         global $wp_list_table;
1376
1377         check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
1378
1379         $taxonomy = sanitize_key( $_POST['taxonomy'] );
1380         $tax = get_taxonomy( $taxonomy );
1381         if ( ! $tax )
1382                 wp_die( 0 );
1383
1384         if ( ! current_user_can( $tax->cap->edit_terms ) )
1385                 wp_die( -1 );
1386
1387         $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => 'edit-' . $taxonomy ) );
1388
1389         if ( ! isset($_POST['tax_ID']) || ! ( $id = (int) $_POST['tax_ID'] ) )
1390                 wp_die( -1 );
1391
1392         $tag = get_term( $id, $taxonomy );
1393         $_POST['description'] = $tag->description;
1394
1395         $updated = wp_update_term($id, $taxonomy, $_POST);
1396         if ( $updated && !is_wp_error($updated) ) {
1397                 $tag = get_term( $updated['term_id'], $taxonomy );
1398                 if ( !$tag || is_wp_error( $tag ) ) {
1399                         if ( is_wp_error($tag) && $tag->get_error_message() )
1400                                 wp_die( $tag->get_error_message() );
1401                         wp_die( __( 'Item not updated.' ) );
1402                 }
1403         } else {
1404                 if ( is_wp_error($updated) && $updated->get_error_message() )
1405                         wp_die( $updated->get_error_message() );
1406                 wp_die( __( 'Item not updated.' ) );
1407         }
1408         $level = 0;
1409         $parent = $tag->parent;
1410         while ( $parent > 0 ) {
1411                 $parent_tag = get_term( $parent, $taxonomy );
1412                 $parent = $parent_tag->parent;
1413                 $level++;
1414         }
1415         echo $wp_list_table->single_row( $tag, $level );
1416         wp_die();
1417 }
1418
1419 function wp_ajax_find_posts() {
1420         global $wpdb;
1421
1422         check_ajax_referer( 'find-posts' );
1423
1424         $post_types = get_post_types( array( 'public' => true ), 'objects' );
1425         unset( $post_types['attachment'] );
1426
1427         $s = stripslashes( $_POST['ps'] );
1428         $searchand = $search = '';
1429         $args = array(
1430                 'post_type' => array_keys( $post_types ),
1431                 'post_status' => 'any',
1432                 'posts_per_page' => 50,
1433         );
1434         if ( '' !== $s )
1435                 $args['s'] = $s;
1436
1437         $posts = get_posts( $args );
1438
1439         if ( ! $posts )
1440                 wp_die( __('No items found.') );
1441
1442         $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>';
1443         foreach ( $posts as $post ) {
1444                 $title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' );
1445
1446                 switch ( $post->post_status ) {
1447                         case 'publish' :
1448                         case 'private' :
1449                                 $stat = __('Published');
1450                                 break;
1451                         case 'future' :
1452                                 $stat = __('Scheduled');
1453                                 break;
1454                         case 'pending' :
1455                                 $stat = __('Pending Review');
1456                                 break;
1457                         case 'draft' :
1458                                 $stat = __('Draft');
1459                                 break;
1460                 }
1461
1462                 if ( '0000-00-00 00:00:00' == $post->post_date ) {
1463                         $time = '';
1464                 } else {
1465                         /* translators: date format in table columns, see http://php.net/date */
1466                         $time = mysql2date(__('Y/m/d'), $post->post_date);
1467                 }
1468
1469                 $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>';
1470                 $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";
1471         }
1472
1473         $html .= '</tbody></table>';
1474
1475         $x = new WP_Ajax_Response();
1476         $x->add( array(
1477                 'data' => $html
1478         ));
1479         $x->send();
1480 }
1481
1482 function wp_ajax_widgets_order() {
1483         check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
1484
1485         if ( !current_user_can('edit_theme_options') )
1486                 wp_die( -1 );
1487
1488         unset( $_POST['savewidgets'], $_POST['action'] );
1489
1490         // save widgets order for all sidebars
1491         if ( is_array($_POST['sidebars']) ) {
1492                 $sidebars = array();
1493                 foreach ( $_POST['sidebars'] as $key => $val ) {
1494                         $sb = array();
1495                         if ( !empty($val) ) {
1496                                 $val = explode(',', $val);
1497                                 foreach ( $val as $k => $v ) {
1498                                         if ( strpos($v, 'widget-') === false )
1499                                                 continue;
1500
1501                                         $sb[$k] = substr($v, strpos($v, '_') + 1);
1502                                 }
1503                         }
1504                         $sidebars[$key] = $sb;
1505                 }
1506                 wp_set_sidebars_widgets($sidebars);
1507                 wp_die( 1 );
1508         }
1509
1510         wp_die( -1 );
1511 }
1512
1513 function wp_ajax_save_widget() {
1514         global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
1515
1516         check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
1517
1518         if ( !current_user_can('edit_theme_options') || !isset($_POST['id_base']) )
1519                 wp_die( -1 );
1520
1521         unset( $_POST['savewidgets'], $_POST['action'] );
1522
1523         do_action('load-widgets.php');
1524         do_action('widgets.php');
1525         do_action('sidebar_admin_setup');
1526
1527         $id_base = $_POST['id_base'];
1528         $widget_id = $_POST['widget-id'];
1529         $sidebar_id = $_POST['sidebar'];
1530         $multi_number = !empty($_POST['multi_number']) ? (int) $_POST['multi_number'] : 0;
1531         $settings = isset($_POST['widget-' . $id_base]) && is_array($_POST['widget-' . $id_base]) ? $_POST['widget-' . $id_base] : false;
1532         $error = '<p>' . __('An error has occurred. Please reload the page and try again.') . '</p>';
1533
1534         $sidebars = wp_get_sidebars_widgets();
1535         $sidebar = isset($sidebars[$sidebar_id]) ? $sidebars[$sidebar_id] : array();
1536
1537         // delete
1538         if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
1539
1540                 if ( !isset($wp_registered_widgets[$widget_id]) )
1541                         wp_die( $error );
1542
1543                 $sidebar = array_diff( $sidebar, array($widget_id) );
1544                 $_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1');
1545         } elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) {
1546                 if ( !$multi_number )
1547                         wp_die( $error );
1548
1549                 $_POST['widget-' . $id_base] = array( $multi_number => array_shift($settings) );
1550                 $widget_id = $id_base . '-' . $multi_number;
1551                 $sidebar[] = $widget_id;
1552         }
1553         $_POST['widget-id'] = $sidebar;
1554
1555         foreach ( (array) $wp_registered_widget_updates as $name => $control ) {
1556
1557                 if ( $name == $id_base ) {
1558                         if ( !is_callable( $control['callback'] ) )
1559                                 continue;
1560
1561                         ob_start();
1562                                 call_user_func_array( $control['callback'], $control['params'] );
1563                         ob_end_clean();
1564                         break;
1565                 }
1566         }
1567
1568         if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
1569                 $sidebars[$sidebar_id] = $sidebar;
1570                 wp_set_sidebars_widgets($sidebars);
1571                 echo "deleted:$widget_id";
1572                 wp_die();
1573         }
1574
1575         if ( !empty($_POST['add_new']) )
1576                 wp_die();
1577
1578         if ( $form = $wp_registered_widget_controls[$widget_id] )
1579                 call_user_func_array( $form['callback'], $form['params'] );
1580
1581         wp_die();
1582 }
1583
1584 function wp_ajax_upload_attachment() {
1585         check_ajax_referer( 'media-form' );
1586
1587         if ( ! current_user_can( 'upload_files' ) )
1588                 wp_die();
1589
1590         if ( isset( $_REQUEST['post_id'] ) ) {
1591                 $post_id = $_REQUEST['post_id'];
1592                 if ( ! current_user_can( 'edit_post', $post_id ) )
1593                         wp_die();
1594         } else {
1595                 $post_id = null;
1596         }
1597
1598         $post_data = isset( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array();
1599
1600         // If the context is custom header or background, make sure the uploaded file is an image.
1601         if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) {
1602                 $wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false );
1603                 if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
1604                         echo json_encode( array(
1605                                 'success' => false,
1606                                 'data'    => array(
1607                                         'message'  => __( 'The uploaded file is not a valid image. Please try again.' ),
1608                                         'filename' => $_FILES['async-upload']['name'],
1609                                 )
1610                         ) );
1611
1612                         wp_die();
1613                 }
1614         }
1615
1616         $attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data );
1617
1618         if ( is_wp_error( $attachment_id ) ) {
1619                 echo json_encode( array(
1620                         'success' => false,
1621                         'data'    => array(
1622                                 'message'  => $attachment_id->get_error_message(),
1623                                 'filename' => $_FILES['async-upload']['name'],
1624                         )
1625                 ) );
1626
1627                 wp_die();
1628         }
1629
1630         if ( isset( $post_data['context'] ) && isset( $post_data['theme'] ) ) {
1631                 if ( 'custom-background' === $post_data['context'] )
1632                         update_post_meta( $attachment_id, '_wp_attachment_is_custom_background', $post_data['theme'] );
1633
1634                 if ( 'custom-header' === $post_data['context'] )
1635                         update_post_meta( $attachment_id, '_wp_attachment_is_custom_header', $post_data['theme'] );
1636         }
1637
1638         if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) )
1639                 wp_die();
1640
1641         echo json_encode( array(
1642                 'success' => true,
1643                 'data'    => $attachment,
1644         ) );
1645
1646         wp_die();
1647 }
1648
1649 function wp_ajax_image_editor() {
1650         $attachment_id = intval($_POST['postid']);
1651         if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) )
1652                 wp_die( -1 );
1653
1654         check_ajax_referer( "image_editor-$attachment_id" );
1655         include_once( ABSPATH . 'wp-admin/includes/image-edit.php' );
1656
1657         $msg = false;
1658         switch ( $_POST['do'] ) {
1659                 case 'save' :
1660                         $msg = wp_save_image($attachment_id);
1661                         $msg = json_encode($msg);
1662                         wp_die( $msg );
1663                         break;
1664                 case 'scale' :
1665                         $msg = wp_save_image($attachment_id);
1666                         break;
1667                 case 'restore' :
1668                         $msg = wp_restore_image($attachment_id);
1669                         break;
1670         }
1671
1672         wp_image_editor($attachment_id, $msg);
1673         wp_die();
1674 }
1675
1676 function wp_ajax_set_post_thumbnail() {
1677         $json = ! empty( $_REQUEST['json'] ); // New-style request
1678
1679         $post_ID = intval( $_POST['post_id'] );
1680         if ( ! current_user_can( 'edit_post', $post_ID ) )
1681                 wp_die( -1 );
1682
1683         $thumbnail_id = intval( $_POST['thumbnail_id'] );
1684
1685         if ( $json )
1686                 check_ajax_referer( "update-post_$post_ID" );
1687         else
1688                 check_ajax_referer( "set_post_thumbnail-$post_ID" );
1689
1690         if ( $thumbnail_id == '-1' ) {
1691                 if ( delete_post_thumbnail( $post_ID ) ) {
1692                         $return = _wp_post_thumbnail_html( null, $post_ID );
1693                         $json ? wp_send_json_success( $return ) : wp_die( $return );
1694                 } else {
1695                         wp_die( 0 );
1696                 }
1697         }
1698
1699         if ( set_post_thumbnail( $post_ID, $thumbnail_id ) ) {
1700                 $return = _wp_post_thumbnail_html( $thumbnail_id, $post_ID );
1701                 $json ? wp_send_json_success( $return ) : wp_die( $return );
1702         }
1703
1704         wp_die( 0 );
1705 }
1706
1707 function wp_ajax_date_format() {
1708         wp_die( date_i18n( sanitize_option( 'date_format', $_POST['date'] ) ) );
1709 }
1710
1711 function wp_ajax_time_format() {
1712         wp_die( date_i18n( sanitize_option( 'time_format', $_POST['date'] ) ) );
1713 }
1714
1715 function wp_ajax_wp_fullscreen_save_post() {
1716         $post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
1717
1718         $post = $post_type = null;
1719
1720         if ( $post_id )
1721                 $post = get_post( $post_id );
1722
1723         if ( $post )
1724                 $post_type = $post->post_type;
1725         elseif ( isset( $_POST['post_type'] ) && post_type_exists( $_POST['post_type'] ) )
1726                 $post_type = $_POST['post_type'];
1727
1728         check_ajax_referer('update-post_' . $post_id, '_wpnonce');
1729
1730         $post_id = edit_post();
1731
1732         if ( is_wp_error($post_id) ) {
1733                 if ( $post_id->get_error_message() )
1734                         $message = $post_id->get_error_message();
1735                 else
1736                         $message = __('Save failed');
1737
1738                 echo json_encode( array( 'message' => $message, 'last_edited' => '' ) );
1739                 wp_die();
1740         } else {
1741                 $message = __('Saved.');
1742         }
1743
1744         if ( $post ) {
1745                 $last_date = mysql2date( get_option('date_format'), $post->post_modified );
1746                 $last_time = mysql2date( get_option('time_format'), $post->post_modified );
1747         } else {
1748                 $last_date = date_i18n( get_option('date_format') );
1749                 $last_time = date_i18n( get_option('time_format') );
1750         }
1751
1752         if ( $last_id = get_post_meta($post_id, '_edit_last', true) ) {
1753                 $last_user = get_userdata($last_id);
1754                 $last_edited = sprintf( __('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), $last_date, $last_time );
1755         } else {
1756                 $last_edited = sprintf( __('Last edited on %1$s at %2$s'), $last_date, $last_time );
1757         }
1758
1759         echo json_encode( array( 'message' => $message, 'last_edited' => $last_edited ) );
1760         wp_die();
1761 }
1762
1763 function wp_ajax_wp_remove_post_lock() {
1764         if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) )
1765                 wp_die( 0 );
1766         $post_id = (int) $_POST['post_ID'];
1767         if ( ! $post = get_post( $post_id ) )
1768                 wp_die( 0 );
1769
1770         check_ajax_referer( 'update-post_' . $post_id );
1771
1772         if ( ! current_user_can( 'edit_post', $post_id ) )
1773                 wp_die( -1 );
1774
1775         $active_lock = array_map( 'absint', explode( ':', $_POST['active_post_lock'] ) );
1776         if ( $active_lock[1] != get_current_user_id() )
1777                 wp_die( 0 );
1778
1779         $new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', AUTOSAVE_INTERVAL * 2 ) + 5 ) . ':' . $active_lock[1];
1780         update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) );
1781         wp_die( 1 );
1782 }
1783
1784 function wp_ajax_dismiss_wp_pointer() {
1785         $pointer = $_POST['pointer'];
1786         if ( $pointer != sanitize_key( $pointer ) )
1787                 wp_die( 0 );
1788
1789 //      check_ajax_referer( 'dismiss-pointer_' . $pointer );
1790
1791         $dismissed = array_filter( explode( ',', (string) get_user_meta( get_current_user_id(), 'dismissed_wp_pointers', true ) ) );
1792
1793         if ( in_array( $pointer, $dismissed ) )
1794                 wp_die( 0 );
1795
1796         $dismissed[] = $pointer;
1797         $dismissed = implode( ',', $dismissed );
1798
1799         update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed );
1800         wp_die( 1 );
1801 }
1802
1803 /**
1804  * Get an attachment.
1805  *
1806  * @since 3.5.0
1807  */
1808 function wp_ajax_get_attachment() {
1809         if ( ! isset( $_REQUEST['id'] ) )
1810                 wp_send_json_error();
1811
1812         if ( ! $id = absint( $_REQUEST['id'] ) )
1813                 wp_send_json_error();
1814
1815         if ( ! $post = get_post( $id ) )
1816                 wp_send_json_error();
1817
1818         if ( 'attachment' != $post->post_type )
1819                 wp_send_json_error();
1820
1821         if ( ! current_user_can( 'upload_files' ) )
1822                 wp_send_json_error();
1823
1824         if ( ! $attachment = wp_prepare_attachment_for_js( $id ) )
1825                 wp_send_json_error();
1826
1827         wp_send_json_success( $attachment );
1828 }
1829
1830 /**
1831  * Query for attachments.
1832  *
1833  * @since 3.5.0
1834  */
1835 function wp_ajax_query_attachments() {
1836         if ( ! current_user_can( 'upload_files' ) )
1837                 wp_send_json_error();
1838
1839         $query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
1840         $query = array_intersect_key( $query, array_flip( array(
1841                 's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type',
1842                 'post_parent', 'post__in', 'post__not_in',
1843         ) ) );
1844
1845         $query['post_type'] = 'attachment';
1846         $query['post_status'] = 'inherit';
1847         if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) )
1848                 $query['post_status'] .= ',private';
1849
1850         $query = new WP_Query( $query );
1851
1852         $posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
1853         $posts = array_filter( $posts );
1854
1855         wp_send_json_success( $posts );
1856 }
1857
1858 /**
1859  * Save attachment attributes.
1860  *
1861  * @since 3.5.0
1862  */
1863 function wp_ajax_save_attachment() {
1864         if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) )
1865                 wp_send_json_error();
1866
1867         if ( ! $id = absint( $_REQUEST['id'] ) )
1868                 wp_send_json_error();
1869
1870         check_ajax_referer( 'update-post_' . $id, 'nonce' );
1871
1872         if ( ! current_user_can( 'edit_post', $id ) )
1873                 wp_send_json_error();
1874
1875         $changes = $_REQUEST['changes'];
1876         $post    = get_post( $id, ARRAY_A );
1877
1878         if ( 'attachment' != $post['post_type'] )
1879                 wp_send_json_error();
1880
1881         if ( isset( $changes['title'] ) )
1882                 $post['post_title'] = $changes['title'];
1883
1884         if ( isset( $changes['caption'] ) )
1885                 $post['post_excerpt'] = $changes['caption'];
1886
1887         if ( isset( $changes['description'] ) )
1888                 $post['post_content'] = $changes['description'];
1889
1890         if ( isset( $changes['alt'] ) ) {
1891                 $alt = get_post_meta( $id, '_wp_attachment_image_alt', true );
1892                 $new_alt = stripslashes( $changes['alt'] );
1893                 if ( $alt != $new_alt ) {
1894                         $new_alt = wp_strip_all_tags( $new_alt, true );
1895                         update_post_meta( $id, '_wp_attachment_image_alt', addslashes( $new_alt ) );
1896                 }
1897         }
1898
1899         wp_update_post( $post );
1900         wp_send_json_success();
1901 }
1902
1903 /**
1904  * Save backwards compatible attachment attributes.
1905  *
1906  * @since 3.5.0
1907  */
1908 function wp_ajax_save_attachment_compat() {
1909         if ( ! isset( $_REQUEST['id'] ) )
1910                 wp_send_json_error();
1911
1912         if ( ! $id = absint( $_REQUEST['id'] ) )
1913                 wp_send_json_error();
1914
1915         if ( empty( $_REQUEST['attachments'] ) || empty( $_REQUEST['attachments'][ $id ] ) )
1916                 wp_send_json_error();
1917         $attachment_data = $_REQUEST['attachments'][ $id ];
1918
1919         check_ajax_referer( 'update-post_' . $id, 'nonce' );
1920
1921         if ( ! current_user_can( 'edit_post', $id ) )
1922                 wp_send_json_error();
1923
1924         $post = get_post( $id, ARRAY_A );
1925
1926         if ( 'attachment' != $post['post_type'] )
1927                 wp_send_json_error();
1928
1929         $post = apply_filters( 'attachment_fields_to_save', $post, $attachment_data );
1930
1931         if ( isset( $post['errors'] ) ) {
1932                 $errors = $post['errors']; // @todo return me and display me!
1933                 unset( $post['errors'] );
1934         }
1935
1936         wp_update_post( $post );
1937
1938         foreach ( get_attachment_taxonomies( $post ) as $taxonomy ) {
1939                 if ( isset( $attachment_data[ $taxonomy ] ) )
1940                         wp_set_object_terms( $id, array_map( 'trim', preg_split( '/,+/', $attachment_data[ $taxonomy ] ) ), $taxonomy, false );
1941         }
1942
1943         if ( ! $attachment = wp_prepare_attachment_for_js( $id ) )
1944                 wp_send_json_error();
1945
1946         wp_send_json_success( $attachment );
1947 }
1948
1949 function wp_ajax_save_attachment_order() {
1950         if ( ! isset( $_REQUEST['post_id'] ) )
1951                 wp_send_json_error();
1952
1953         if ( ! $post_id = absint( $_REQUEST['post_id'] ) )
1954                 wp_send_json_error();
1955
1956         if ( empty( $_REQUEST['attachments'] ) )
1957                 wp_send_json_error();
1958
1959         check_ajax_referer( 'update-post_' . $post_id, 'nonce' );
1960
1961         $attachments = $_REQUEST['attachments'];
1962
1963         if ( ! current_user_can( 'edit_post', $post_id ) )
1964                 wp_send_json_error();
1965
1966         $post = get_post( $post_id, ARRAY_A );
1967
1968         foreach ( $attachments as $attachment_id => $menu_order ) {
1969                 if ( ! current_user_can( 'edit_post', $attachment_id ) )
1970                         continue;
1971                 if ( ! $attachment = get_post( $attachment_id ) )
1972                         continue;
1973                 if ( 'attachment' != $attachment->post_type )
1974                         continue;
1975
1976                 wp_update_post( array( 'ID' => $attachment_id, 'menu_order' => $menu_order ) );
1977         }
1978
1979         wp_send_json_success();
1980 }
1981
1982 /**
1983  * Generates the HTML to send an attachment to the editor.
1984  * Backwards compatible with the media_send_to_editor filter and the chain
1985  * of filters that follow.
1986  *
1987  * @since 3.5.0
1988  */
1989 function wp_ajax_send_attachment_to_editor() {
1990         check_ajax_referer( 'media-send-to-editor', 'nonce' );
1991
1992         $attachment = stripslashes_deep( $_POST['attachment'] );
1993
1994         $id = intval( $attachment['id'] );
1995
1996         if ( ! $post = get_post( $id ) )
1997                 wp_send_json_error();
1998
1999         if ( 'attachment' != $post->post_type )
2000                 wp_send_json_error();
2001
2002         if ( current_user_can( 'edit_post', $id ) ) {
2003                 // If this attachment is unattached, attach it. Primarily a back compat thing.
2004                 if ( 0 == $post->post_parent && $insert_into_post_id = intval( $_POST['post_id'] ) ) {
2005                         wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) );
2006                 }
2007         }
2008
2009         $rel = $url = '';
2010         $html = $title = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';
2011         if ( ! empty( $attachment['url'] ) ) {
2012                 $url = $attachment['url'];
2013                 if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url )
2014                         $rel = ' rel="attachment wp-att-' . $id . '"';
2015                 $html = '<a href="' . esc_url( $url ) . '"' . $rel . '>' . $html . '</a>';
2016         }
2017
2018         remove_filter( 'media_send_to_editor', 'image_media_send_to_editor', 10, 3 );
2019
2020         if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) {
2021                 $align = isset( $attachment['align'] ) ? $attachment['align'] : 'none';
2022                 $size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
2023                 $alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';
2024                 $caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : '';
2025                 $title = ''; // We no longer insert title tags into <img> tags, as they are redundant.
2026                 $html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt );
2027         }
2028
2029         $html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );
2030
2031         wp_send_json_success( $html );
2032 }
2033
2034 /**
2035  * Generates the HTML to send a non-image embed link to the editor.
2036  *
2037  * Backwards compatible with the following filters:
2038  * - file_send_to_editor_url
2039  * - audio_send_to_editor_url
2040  * - video_send_to_editor_url
2041  *
2042  * @since 3.5.0
2043  */
2044 function wp_ajax_send_link_to_editor() {
2045         check_ajax_referer( 'media-send-to-editor', 'nonce' );
2046
2047         if ( ! $src = stripslashes( $_POST['src'] ) )
2048                 wp_send_json_error();
2049
2050         if ( ! strpos( $src, '://' ) )
2051                 $src = 'http://' . $src;
2052
2053         if ( ! $src = esc_url_raw( $src ) )
2054                 wp_send_json_error();
2055
2056         if ( ! $title = trim( stripslashes( $_POST['title'] ) ) )
2057                 $title = wp_basename( $src );
2058
2059         $html = '';
2060         if ( $title )
2061                 $html = '<a href="' . esc_url( $src ) . '">' . $title . '</a>';
2062
2063         // Figure out what filter to run:
2064         $type = 'file';
2065         if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) )
2066                 && ( 'audio' == $ext_type || 'video' == $ext_type ) )
2067                         $type = $ext_type;
2068
2069         $html = apply_filters( $type . '_send_to_editor_url', $html, $src, $title );
2070
2071         wp_send_json_success( $html );
2072 }