wp/wp-admin/includes/ajax-actions.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Administration
     6  * @subpackage Administration
     7  */
     7  */
     8 
     8 
     9 /*
     9 //
    10  * No-privilege Ajax handlers.
    10 // No-privilege Ajax handlers.
    11  */
    11 //
    12 
    12 
    13 /**
    13 /**
    14  * Heartbeat API (experimental)
    14  * Ajax handler for the Heartbeat API in
       
    15  * the no-privilege context.
    15  *
    16  *
    16  * Runs when the user is not logged in.
    17  * Runs when the user is not logged in.
       
    18  *
       
    19  * @since 3.6.0
    17  */
    20  */
    18 function wp_ajax_nopriv_heartbeat() {
    21 function wp_ajax_nopriv_heartbeat() {
    19 	$response = array();
    22 	$response = array();
    20 
    23 
    21 	// screen_id is the same as $current_screen->id and the JS global 'pagenow'
    24 	// screen_id is the same as $current_screen->id and the JS global 'pagenow'.
    22 	if ( ! empty($_POST['screen_id']) )
    25 	if ( ! empty($_POST['screen_id']) )
    23 		$screen_id = sanitize_key($_POST['screen_id']);
    26 		$screen_id = sanitize_key($_POST['screen_id']);
    24 	else
    27 	else
    25 		$screen_id = 'front';
    28 		$screen_id = 'front';
    26 
    29 
    59 	 * @param array|object $response  The no-priv Heartbeat response.
    62 	 * @param array|object $response  The no-priv Heartbeat response.
    60 	 * @param string       $screen_id The screen id.
    63 	 * @param string       $screen_id The screen id.
    61 	 */
    64 	 */
    62 	do_action( 'heartbeat_nopriv_tick', $response, $screen_id );
    65 	do_action( 'heartbeat_nopriv_tick', $response, $screen_id );
    63 
    66 
    64 	// send the current time according to the server
    67 	// Send the current time according to the server.
    65 	$response['server_time'] = time();
    68 	$response['server_time'] = time();
    66 
    69 
    67 	wp_send_json($response);
    70 	wp_send_json($response);
    68 }
    71 }
    69 
    72 
    70 /*
    73 //
    71  * GET-based Ajax handlers.
    74 // GET-based Ajax handlers.
       
    75 //
       
    76 
       
    77 /**
       
    78  * Ajax handler for fetching a list table.
       
    79  *
       
    80  * @since 3.1.0
    72  */
    81  */
    73 function wp_ajax_fetch_list() {
    82 function wp_ajax_fetch_list() {
    74 	global $wp_list_table;
    83 	global $wp_list_table;
    75 
    84 
    76 	$list_class = $_GET['list_args']['class'];
    85 	$list_class = $_GET['list_args']['class'];
    85 
    94 
    86 	$wp_list_table->ajax_response();
    95 	$wp_list_table->ajax_response();
    87 
    96 
    88 	wp_die( 0 );
    97 	wp_die( 0 );
    89 }
    98 }
       
    99 
       
   100 /**
       
   101  * Ajax handler for tag search.
       
   102  *
       
   103  * @since 3.1.0
       
   104  */
    90 function wp_ajax_ajax_tag_search() {
   105 function wp_ajax_ajax_tag_search() {
    91 	global $wpdb;
   106 	if ( ! isset( $_GET['tax'] ) ) {
    92 
       
    93 	if ( isset( $_GET['tax'] ) ) {
       
    94 		$taxonomy = sanitize_key( $_GET['tax'] );
       
    95 		$tax = get_taxonomy( $taxonomy );
       
    96 		if ( ! $tax )
       
    97 			wp_die( 0 );
       
    98 		if ( ! current_user_can( $tax->cap->assign_terms ) )
       
    99 			wp_die( -1 );
       
   100 	} else {
       
   101 		wp_die( 0 );
   107 		wp_die( 0 );
       
   108 	}
       
   109 
       
   110 	$taxonomy = sanitize_key( $_GET['tax'] );
       
   111 	$tax = get_taxonomy( $taxonomy );
       
   112 	if ( ! $tax ) {
       
   113 		wp_die( 0 );
       
   114 	}
       
   115 
       
   116 	if ( ! current_user_can( $tax->cap->assign_terms ) ) {
       
   117 		wp_die( -1 );
   102 	}
   118 	}
   103 
   119 
   104 	$s = wp_unslash( $_GET['q'] );
   120 	$s = wp_unslash( $_GET['q'] );
   105 
   121 
   106 	$comma = _x( ',', 'tag delimiter' );
   122 	$comma = _x( ',', 'tag delimiter' );
   109 	if ( false !== strpos( $s, ',' ) ) {
   125 	if ( false !== strpos( $s, ',' ) ) {
   110 		$s = explode( ',', $s );
   126 		$s = explode( ',', $s );
   111 		$s = $s[count( $s ) - 1];
   127 		$s = $s[count( $s ) - 1];
   112 	}
   128 	}
   113 	$s = trim( $s );
   129 	$s = trim( $s );
   114 	if ( strlen( $s ) < 2 )
   130 
   115 		wp_die(); // require 2 chars for matching
   131 	/**
       
   132 	 * Filter the minimum number of characters required to fire a tag search via AJAX.
       
   133 	 *
       
   134 	 * @since 4.0.0
       
   135 	 *
       
   136 	 * @param int    $characters The minimum number of characters required. Default 2.
       
   137 	 * @param object $tax        The taxonomy object.
       
   138 	 * @param string $s          The search term.
       
   139 	 */
       
   140 	$term_search_min_chars = (int) apply_filters( 'term_search_min_chars', 2, $tax, $s );
       
   141 
       
   142 	/*
       
   143 	 * Require $term_search_min_chars chars for matching (default: 2)
       
   144 	 * ensure it's a non-negative, non-zero integer.
       
   145 	 */
       
   146 	if ( ( $term_search_min_chars == 0 ) || ( strlen( $s ) < $term_search_min_chars ) ){
       
   147 		wp_die();
       
   148 	}
   116 
   149 
   117 	$results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false ) );
   150 	$results = get_terms( $taxonomy, array( 'name__like' => $s, 'fields' => 'names', 'hide_empty' => false ) );
   118 
   151 
   119 	echo join( $results, "\n" );
   152 	echo join( $results, "\n" );
   120 	wp_die();
   153 	wp_die();
   121 }
   154 }
   122 
   155 
       
   156 /**
       
   157  * Ajax handler for compression testing.
       
   158  *
       
   159  * @since 3.1.0
       
   160  */
   123 function wp_ajax_wp_compression_test() {
   161 function wp_ajax_wp_compression_test() {
   124 	if ( !current_user_can( 'manage_options' ) )
   162 	if ( !current_user_can( 'manage_options' ) )
   125 		wp_die( -1 );
   163 		wp_die( -1 );
   126 
   164 
   127 	if ( ini_get('zlib.output_compression') || 'ob_gzhandler' == ini_get('output_handler') ) {
   165 	if ( ini_get('zlib.output_compression') || 'ob_gzhandler' == ini_get('output_handler') ) {
   132 	if ( isset($_GET['test']) ) {
   170 	if ( isset($_GET['test']) ) {
   133 		header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
   171 		header( 'Expires: Wed, 11 Jan 1984 05:00:00 GMT' );
   134 		header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
   172 		header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
   135 		header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
   173 		header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
   136 		header( 'Pragma: no-cache' );
   174 		header( 'Pragma: no-cache' );
   137 		header('Content-Type: application/x-javascript; charset=UTF-8');
   175 		header('Content-Type: application/javascript; charset=UTF-8');
   138 		$force_gzip = ( defined('ENFORCE_GZIP') && ENFORCE_GZIP );
   176 		$force_gzip = ( defined('ENFORCE_GZIP') && ENFORCE_GZIP );
   139 		$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."';
   177 		$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."';
   140 
   178 
   141 		 if ( 1 == $_GET['test'] ) {
   179 		 if ( 1 == $_GET['test'] ) {
   142 		 	echo $test_str;
   180 		 	echo $test_str;
   163 	}
   201 	}
   164 
   202 
   165 	wp_die( 0 );
   203 	wp_die( 0 );
   166 }
   204 }
   167 
   205 
       
   206 /**
       
   207  * Ajax handler for image editor previews.
       
   208  *
       
   209  * @since 3.1.0
       
   210  */
   168 function wp_ajax_imgedit_preview() {
   211 function wp_ajax_imgedit_preview() {
   169 	$post_id = intval($_GET['postid']);
   212 	$post_id = intval($_GET['postid']);
   170 	if ( empty($post_id) || !current_user_can('edit_post', $post_id) )
   213 	if ( empty($post_id) || !current_user_can('edit_post', $post_id) )
   171 		wp_die( -1 );
   214 		wp_die( -1 );
   172 
   215 
   177 		wp_die( -1 );
   220 		wp_die( -1 );
   178 
   221 
   179 	wp_die();
   222 	wp_die();
   180 }
   223 }
   181 
   224 
       
   225 /**
       
   226  * Ajax handler for oEmbed caching.
       
   227  *
       
   228  * @since 3.1.0
       
   229  */
   182 function wp_ajax_oembed_cache() {
   230 function wp_ajax_oembed_cache() {
   183 	global $wp_embed;
   231 	$GLOBALS['wp_embed']->cache_oembed( $_GET['post'] );
   184 
   232 	wp_die( 0 );
   185 	$return = ( $wp_embed->cache_oembed( $_GET['post'] ) ) ? '1' : '0';
   233 }
   186 	wp_die( $return );
   234 
   187 }
   235 /**
   188 
   236  * Ajax handler for user autocomplete.
       
   237  *
       
   238  * @since 3.4.0
       
   239  */
   189 function wp_ajax_autocomplete_user() {
   240 function wp_ajax_autocomplete_user() {
   190 	if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) )
   241 	if ( ! is_multisite() || ! current_user_can( 'promote_users' ) || wp_is_large_network( 'users' ) )
   191 		wp_die( -1 );
   242 		wp_die( -1 );
   192 
   243 
   193 	/** This filter is documented in wp-admin/user-new.php */
   244 	/** This filter is documented in wp-admin/user-new.php */
   195 		wp_die( -1 );
   246 		wp_die( -1 );
   196 
   247 
   197 	$return = array();
   248 	$return = array();
   198 
   249 
   199 	// Check the type of request
   250 	// Check the type of request
   200 	if ( isset( $_REQUEST['autocomplete_type'] ) )
   251 	// Current allowed values are `add` and `search`
       
   252 	if ( isset( $_REQUEST['autocomplete_type'] ) && 'search' === $_REQUEST['autocomplete_type'] ) {
   201 		$type = $_REQUEST['autocomplete_type'];
   253 		$type = $_REQUEST['autocomplete_type'];
   202 	else
   254 	} else {
   203 		$type = 'add';
   255 		$type = 'add';
       
   256 	}
       
   257 
       
   258 	// Check the desired field for value
       
   259 	// Current allowed values are `user_email` and `user_login`
       
   260 	if ( isset( $_REQUEST['autocomplete_field'] ) && 'user_email' === $_REQUEST['autocomplete_field'] ) {
       
   261 		$field = $_REQUEST['autocomplete_field'];
       
   262 	} else {
       
   263 		$field = 'user_login';
       
   264 	}
   204 
   265 
   205 	// Exclude current users of this blog
   266 	// Exclude current users of this blog
   206 	if ( isset( $_REQUEST['site_id'] ) )
   267 	if ( isset( $_REQUEST['site_id'] ) ) {
   207 		$id = absint( $_REQUEST['site_id'] );
   268 		$id = absint( $_REQUEST['site_id'] );
   208 	else
   269 	} else {
   209 		$id = get_current_blog_id();
   270 		$id = get_current_blog_id();
       
   271 	}
   210 
   272 
   211 	$include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
   273 	$include_blog_users = ( $type == 'search' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
   212 	$exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
   274 	$exclude_blog_users = ( $type == 'add' ? get_users( array( 'blog_id' => $id, 'fields' => 'ID' ) ) : array() );
   213 
   275 
   214 	$users = get_users( array(
   276 	$users = get_users( array(
   221 
   283 
   222 	foreach ( $users as $user ) {
   284 	foreach ( $users as $user ) {
   223 		$return[] = array(
   285 		$return[] = array(
   224 			/* translators: 1: user_login, 2: user_email */
   286 			/* translators: 1: user_login, 2: user_email */
   225 			'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ),
   287 			'label' => sprintf( __( '%1$s (%2$s)' ), $user->user_login, $user->user_email ),
   226 			'value' => $user->user_login,
   288 			'value' => $user->$field,
   227 		);
   289 		);
   228 	}
   290 	}
   229 
   291 
   230 	wp_die( json_encode( $return ) );
   292 	wp_die( wp_json_encode( $return ) );
   231 }
   293 }
   232 
   294 
       
   295 /**
       
   296  * Ajax handler for dashboard widgets.
       
   297  *
       
   298  * @since 3.4.0
       
   299  */
   233 function wp_ajax_dashboard_widgets() {
   300 function wp_ajax_dashboard_widgets() {
   234 	require_once ABSPATH . 'wp-admin/includes/dashboard.php';
   301 	require_once ABSPATH . 'wp-admin/includes/dashboard.php';
   235 
   302 
       
   303 	$pagenow = $_GET['pagenow'];
       
   304 	if ( $pagenow === 'dashboard-user' || $pagenow === 'dashboard-network' || $pagenow === 'dashboard' ) {
       
   305 		set_current_screen( $pagenow );
       
   306 	}
       
   307 
   236 	switch ( $_GET['widget'] ) {
   308 	switch ( $_GET['widget'] ) {
   237 		case 'dashboard_incoming_links' :
       
   238 			wp_dashboard_incoming_links();
       
   239 			break;
       
   240 		case 'dashboard_primary' :
   309 		case 'dashboard_primary' :
   241 			wp_dashboard_primary();
   310 			wp_dashboard_primary();
   242 			break;
   311 			break;
   243 		case 'dashboard_secondary' :
       
   244 			wp_dashboard_secondary();
       
   245 			break;
       
   246 		case 'dashboard_plugins' :
       
   247 			wp_dashboard_plugins();
       
   248 			break;
       
   249 	}
   312 	}
   250 	wp_die();
   313 	wp_die();
   251 }
   314 }
   252 
   315 
       
   316 /**
       
   317  * Ajax handler for Customizer preview logged-in status.
       
   318  *
       
   319  * @since 3.4.0
       
   320  */
   253 function wp_ajax_logged_in() {
   321 function wp_ajax_logged_in() {
   254 	wp_die( 1 );
   322 	wp_die( 1 );
   255 }
   323 }
   256 
   324 
   257 /*
   325 //
   258  * Ajax helper.
   326 // Ajax helpers.
   259  */
   327 //
   260 
   328 
   261 /**
   329 /**
   262  * Sends back current comment total and new page links if they need to be updated.
   330  * Sends back current comment total and new page links if they need to be updated.
   263  *
   331  *
   264  * Contrary to normal success AJAX response ("1"), die with time() on success.
   332  * Contrary to normal success AJAX response ("1"), die with time() on success.
   265  *
   333  *
   266  * @since 2.7
   334  * @since 2.7.0
   267  *
   335  *
   268  * @param int $comment_id
   336  * @param int $comment_id
   269  * @return die
   337  * @return die
   270  */
   338  */
   271 function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) {
   339 function _wp_ajax_delete_comment_response( $comment_id, $delta = -1 ) {
   295 				$post_id = (int) $query_vars['p'];
   363 				$post_id = (int) $query_vars['p'];
   296 		}
   364 		}
   297 
   365 
   298 		$comment_count = wp_count_comments($post_id);
   366 		$comment_count = wp_count_comments($post_id);
   299 
   367 
   300 		if ( isset( $comment_count->$status ) ) // We're looking for a known type of comment count
   368 		// We're looking for a known type of comment count.
       
   369 		if ( isset( $comment_count->$status ) )
   301 			$total = $comment_count->$status;
   370 			$total = $comment_count->$status;
   302 			// else use the decremented value from above
   371 			// Else use the decremented value from above.
   303 	}
   372 	}
   304 
   373 
   305 	$time = time(); // The time since the last comment count
   374 	// The time since the last comment count.
       
   375 	$time = time();
   306 
   376 
   307 	$x = new WP_Ajax_Response( array(
   377 	$x = new WP_Ajax_Response( array(
   308 		'what' => 'comment',
   378 		'what' => 'comment',
   309 		'id' => $comment_id, // here for completeness - not used
   379 		// Here for completeness - not used.
       
   380 		'id' => $comment_id,
   310 		'supplemental' => array(
   381 		'supplemental' => array(
   311 			'total_items_i18n' => sprintf( _n( '1 item', '%s items', $total ), number_format_i18n( $total ) ),
   382 			'total_items_i18n' => sprintf( _n( '%s item', '%s items', $total ), number_format_i18n( $total ) ),
   312 			'total_pages' => ceil( $total / $per_page ),
   383 			'total_pages' => ceil( $total / $per_page ),
   313 			'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ),
   384 			'total_pages_i18n' => number_format_i18n( ceil( $total / $per_page ) ),
   314 			'total' => $total,
   385 			'total' => $total,
   315 			'time' => $time
   386 			'time' => $time
   316 		)
   387 		)
   317 	) );
   388 	) );
   318 	$x->send();
   389 	$x->send();
   319 }
   390 }
   320 
   391 
   321 /*
   392 //
   322  * POST-based Ajax handlers.
   393 // POST-based Ajax handlers.
   323  */
   394 //
   324 
   395 
       
   396 /**
       
   397  * Ajax handler for adding a hierarchical term.
       
   398  *
       
   399  * @since 3.1.0
       
   400  */
   325 function _wp_ajax_add_hierarchical_term() {
   401 function _wp_ajax_add_hierarchical_term() {
   326 	$action = $_POST['action'];
   402 	$action = $_POST['action'];
   327 	$taxonomy = get_taxonomy(substr($action, 4));
   403 	$taxonomy = get_taxonomy(substr($action, 4));
   328 	check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
   404 	check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
   329 	if ( !current_user_can( $taxonomy->cap->edit_terms ) )
   405 	if ( !current_user_can( $taxonomy->cap->edit_terms ) )
   344 		$category_nicename = sanitize_title($cat_name);
   420 		$category_nicename = sanitize_title($cat_name);
   345 		if ( '' === $category_nicename )
   421 		if ( '' === $category_nicename )
   346 			continue;
   422 			continue;
   347 		if ( !$cat_id = term_exists( $cat_name, $taxonomy->name, $parent ) )
   423 		if ( !$cat_id = term_exists( $cat_name, $taxonomy->name, $parent ) )
   348 			$cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) );
   424 			$cat_id = wp_insert_term( $cat_name, $taxonomy->name, array( 'parent' => $parent ) );
   349 		if ( is_wp_error( $cat_id ) )
   425 		if ( is_wp_error( $cat_id ) ) {
   350 			continue;
   426 			continue;
   351 		else if ( is_array( $cat_id ) )
   427 		} elseif ( is_array( $cat_id ) ) {
   352 			$cat_id = $cat_id['term_id'];
   428 			$cat_id = $cat_id['term_id'];
       
   429 		}
   353 		$checked_categories[] = $cat_id;
   430 		$checked_categories[] = $cat_id;
   354 		if ( $parent ) // Do these all at once in a second
   431 		if ( $parent ) // Do these all at once in a second
   355 			continue;
   432 			continue;
   356 		ob_start();
   433 		ob_start();
   357 			wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name, 'descendants_and_self' => $cat_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids ));
   434 			wp_terms_checklist( 0, array( 'taxonomy' => $taxonomy->name, 'descendants_and_self' => $cat_id, 'selected_cats' => $checked_categories, 'popular_cats' => $popular_ids ));
   399 
   476 
   400 	$x = new WP_Ajax_Response( $add );
   477 	$x = new WP_Ajax_Response( $add );
   401 	$x->send();
   478 	$x->send();
   402 }
   479 }
   403 
   480 
       
   481 /**
       
   482  * Ajax handler for deleting a comment.
       
   483  *
       
   484  * @since 3.1.0
       
   485  */
   404 function wp_ajax_delete_comment() {
   486 function wp_ajax_delete_comment() {
   405 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   487 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   406 
   488 
   407 	if ( !$comment = get_comment( $id ) )
   489 	if ( !$comment = get_comment( $id ) )
   408 		wp_die( time() );
   490 		wp_die( time() );
   442 	if ( $r ) // Decide if we need to send back '1' or a more complicated response including page links and comment counts
   524 	if ( $r ) // Decide if we need to send back '1' or a more complicated response including page links and comment counts
   443 		_wp_ajax_delete_comment_response( $comment->comment_ID, $delta );
   525 		_wp_ajax_delete_comment_response( $comment->comment_ID, $delta );
   444 	wp_die( 0 );
   526 	wp_die( 0 );
   445 }
   527 }
   446 
   528 
       
   529 /**
       
   530  * Ajax handler for deleting a tag.
       
   531  *
       
   532  * @since 3.1.0
       
   533  */
   447 function wp_ajax_delete_tag() {
   534 function wp_ajax_delete_tag() {
   448 	$tag_id = (int) $_POST['tag_ID'];
   535 	$tag_id = (int) $_POST['tag_ID'];
   449 	check_ajax_referer( "delete-tag_$tag_id" );
   536 	check_ajax_referer( "delete-tag_$tag_id" );
   450 
   537 
   451 	$taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
   538 	$taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
   462 		wp_die( 1 );
   549 		wp_die( 1 );
   463 	else
   550 	else
   464 		wp_die( 0 );
   551 		wp_die( 0 );
   465 }
   552 }
   466 
   553 
       
   554 /**
       
   555  * Ajax handler for deleting a link.
       
   556  *
       
   557  * @since 3.1.0
       
   558  */
   467 function wp_ajax_delete_link() {
   559 function wp_ajax_delete_link() {
   468 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   560 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   469 
   561 
   470 	check_ajax_referer( "delete-bookmark_$id" );
   562 	check_ajax_referer( "delete-bookmark_$id" );
   471 	if ( !current_user_can( 'manage_links' ) )
   563 	if ( !current_user_can( 'manage_links' ) )
   479 		wp_die( 1 );
   571 		wp_die( 1 );
   480 	else
   572 	else
   481 		wp_die( 0 );
   573 		wp_die( 0 );
   482 }
   574 }
   483 
   575 
       
   576 /**
       
   577  * Ajax handler for deleting meta.
       
   578  *
       
   579  * @since 3.1.0
       
   580  */
   484 function wp_ajax_delete_meta() {
   581 function wp_ajax_delete_meta() {
   485 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   582 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   486 
   583 
   487 	check_ajax_referer( "delete-meta_$id" );
   584 	check_ajax_referer( "delete-meta_$id" );
   488 	if ( !$meta = get_metadata_by_mid( 'post', $id ) )
   585 	if ( !$meta = get_metadata_by_mid( 'post', $id ) )
   493 	if ( delete_meta( $meta->meta_id ) )
   590 	if ( delete_meta( $meta->meta_id ) )
   494 		wp_die( 1 );
   591 		wp_die( 1 );
   495 	wp_die( 0 );
   592 	wp_die( 0 );
   496 }
   593 }
   497 
   594 
       
   595 /**
       
   596  * Ajax handler for deleting a post.
       
   597  *
       
   598  * @since 3.1.0
       
   599  *
       
   600  * @param string $action Action to perform.
       
   601  */
   498 function wp_ajax_delete_post( $action ) {
   602 function wp_ajax_delete_post( $action ) {
   499 	if ( empty( $action ) )
   603 	if ( empty( $action ) )
   500 		$action = 'delete-post';
   604 		$action = 'delete-post';
   501 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   605 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   502 
   606 
   511 		wp_die( 1 );
   615 		wp_die( 1 );
   512 	else
   616 	else
   513 		wp_die( 0 );
   617 		wp_die( 0 );
   514 }
   618 }
   515 
   619 
       
   620 /**
       
   621  * Ajax handler for sending a post to the trash.
       
   622  *
       
   623  * @since 3.1.0
       
   624  *
       
   625  * @param string $action Action to perform.
       
   626  */
   516 function wp_ajax_trash_post( $action ) {
   627 function wp_ajax_trash_post( $action ) {
   517 	if ( empty( $action ) )
   628 	if ( empty( $action ) )
   518 		$action = 'trash-post';
   629 		$action = 'trash-post';
   519 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   630 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   520 
   631 
   534 		wp_die( 1 );
   645 		wp_die( 1 );
   535 
   646 
   536 	wp_die( 0 );
   647 	wp_die( 0 );
   537 }
   648 }
   538 
   649 
       
   650 /**
       
   651  * Ajax handler to restore a post from the trash.
       
   652  *
       
   653  * @since 3.1.0
       
   654  *
       
   655  * @param string $action Action to perform.
       
   656  */
   539 function wp_ajax_untrash_post( $action ) {
   657 function wp_ajax_untrash_post( $action ) {
   540 	if ( empty( $action ) )
   658 	if ( empty( $action ) )
   541 		$action = 'untrash-post';
   659 		$action = 'untrash-post';
   542 	wp_ajax_trash_post( $action );
   660 	wp_ajax_trash_post( $action );
   543 }
   661 }
   558 		wp_die( 1 );
   676 		wp_die( 1 );
   559 	else
   677 	else
   560 		wp_die( 0 );
   678 		wp_die( 0 );
   561 }
   679 }
   562 
   680 
       
   681 /**
       
   682  * Ajax handler to dim a comment.
       
   683  *
       
   684  * @since 3.1.0
       
   685  */
   563 function wp_ajax_dim_comment() {
   686 function wp_ajax_dim_comment() {
   564 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   687 	$id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
   565 
   688 
   566 	if ( !$comment = get_comment( $id ) ) {
   689 	if ( !$comment = get_comment( $id ) ) {
   567 		$x = new WP_Ajax_Response( array(
   690 		$x = new WP_Ajax_Response( array(
   595 	// Decide if we need to send back '1' or a more complicated response including page links and comment counts
   718 	// Decide if we need to send back '1' or a more complicated response including page links and comment counts
   596 	_wp_ajax_delete_comment_response( $comment->comment_ID );
   719 	_wp_ajax_delete_comment_response( $comment->comment_ID );
   597 	wp_die( 0 );
   720 	wp_die( 0 );
   598 }
   721 }
   599 
   722 
       
   723 /**
       
   724  * Ajax handler for deleting a link category.
       
   725  *
       
   726  * @since 3.1.0
       
   727  *
       
   728  * @param string $action Action to perform.
       
   729  */
   600 function wp_ajax_add_link_category( $action ) {
   730 function wp_ajax_add_link_category( $action ) {
   601 	if ( empty( $action ) )
   731 	if ( empty( $action ) )
   602 		$action = 'add-link-category';
   732 		$action = 'add-link-category';
   603 	check_ajax_referer( $action );
   733 	check_ajax_referer( $action );
   604 	if ( !current_user_can( 'manage_categories' ) )
   734 	if ( !current_user_can( 'manage_categories' ) )
   610 		$slug = sanitize_title($cat_name);
   740 		$slug = sanitize_title($cat_name);
   611 		if ( '' === $slug )
   741 		if ( '' === $slug )
   612 			continue;
   742 			continue;
   613 		if ( !$cat_id = term_exists( $cat_name, 'link_category' ) )
   743 		if ( !$cat_id = term_exists( $cat_name, 'link_category' ) )
   614 			$cat_id = wp_insert_term( $cat_name, 'link_category' );
   744 			$cat_id = wp_insert_term( $cat_name, 'link_category' );
   615 		if ( is_wp_error( $cat_id ) )
   745 		if ( is_wp_error( $cat_id ) ) {
   616 			continue;
   746 			continue;
   617 		else if ( is_array( $cat_id ) )
   747 		} elseif ( is_array( $cat_id ) ) {
   618 			$cat_id = $cat_id['term_id'];
   748 			$cat_id = $cat_id['term_id'];
       
   749 		}
   619 		$cat_name = esc_html( $cat_name );
   750 		$cat_name = esc_html( $cat_name );
   620 		$x->add( array(
   751 		$x->add( array(
   621 			'what' => 'link-category',
   752 			'what' => 'link-category',
   622 			'id' => $cat_id,
   753 			'id' => $cat_id,
   623 			'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>",
   754 			'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>",
   625 		) );
   756 		) );
   626 	}
   757 	}
   627 	$x->send();
   758 	$x->send();
   628 }
   759 }
   629 
   760 
       
   761 /**
       
   762  * Ajax handler to add a tag.
       
   763  *
       
   764  * @since 3.1.0
       
   765  */
   630 function wp_ajax_add_tag() {
   766 function wp_ajax_add_tag() {
   631 	global $wp_list_table;
   767 	global $wp_list_table;
   632 
   768 
   633 	check_ajax_referer( 'add-tag', '_wpnonce_add-tag' );
   769 	check_ajax_referer( 'add-tag', '_wpnonce_add-tag' );
   634 	$post_type = !empty($_POST['post_type']) ? $_POST['post_type'] : 'post';
       
   635 	$taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
   770 	$taxonomy = !empty($_POST['taxonomy']) ? $_POST['taxonomy'] : 'post_tag';
   636 	$tax = get_taxonomy($taxonomy);
   771 	$tax = get_taxonomy($taxonomy);
   637 
   772 
   638 	if ( !current_user_can( $tax->cap->edit_terms ) )
   773 	if ( !current_user_can( $tax->cap->edit_terms ) )
   639 		wp_die( -1 );
   774 		wp_die( -1 );
   656 
   791 
   657 	$wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
   792 	$wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
   658 
   793 
   659 	$level = 0;
   794 	$level = 0;
   660 	if ( is_taxonomy_hierarchical($taxonomy) ) {
   795 	if ( is_taxonomy_hierarchical($taxonomy) ) {
   661 		$level = count( get_ancestors( $tag->term_id, $taxonomy ) );
   796 		$level = count( get_ancestors( $tag->term_id, $taxonomy, 'taxonomy' ) );
   662 		ob_start();
   797 		ob_start();
   663 		$wp_list_table->single_row( $tag, $level );
   798 		$wp_list_table->single_row( $tag, $level );
   664 		$noparents = ob_get_clean();
   799 		$noparents = ob_get_clean();
   665 	}
   800 	}
   666 
   801 
   678 		'supplemental' => (array) $tag
   813 		'supplemental' => (array) $tag
   679 		) );
   814 		) );
   680 	$x->send();
   815 	$x->send();
   681 }
   816 }
   682 
   817 
       
   818 /**
       
   819  * Ajax handler for getting a tagcloud.
       
   820  *
       
   821  * @since 3.1.0
       
   822  */
   683 function wp_ajax_get_tagcloud() {
   823 function wp_ajax_get_tagcloud() {
   684 	if ( isset( $_POST['tax'] ) ) {
   824 	if ( ! isset( $_POST['tax'] ) ) {
   685 		$taxonomy = sanitize_key( $_POST['tax'] );
       
   686 		$tax = get_taxonomy( $taxonomy );
       
   687 		if ( ! $tax )
       
   688 			wp_die( 0 );
       
   689 		if ( ! current_user_can( $tax->cap->assign_terms ) )
       
   690 			wp_die( -1 );
       
   691 	} else {
       
   692 		wp_die( 0 );
   825 		wp_die( 0 );
       
   826 	}
       
   827 
       
   828 	$taxonomy = sanitize_key( $_POST['tax'] );
       
   829 	$tax = get_taxonomy( $taxonomy );
       
   830 	if ( ! $tax ) {
       
   831 		wp_die( 0 );
       
   832 	}
       
   833 
       
   834 	if ( ! current_user_can( $tax->cap->assign_terms ) ) {
       
   835 		wp_die( -1 );
   693 	}
   836 	}
   694 
   837 
   695 	$tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) );
   838 	$tags = get_terms( $taxonomy, array( 'number' => 45, 'orderby' => 'count', 'order' => 'DESC' ) );
   696 
   839 
   697 	if ( empty( $tags ) )
   840 	if ( empty( $tags ) )
   714 	echo $return;
   857 	echo $return;
   715 
   858 
   716 	wp_die();
   859 	wp_die();
   717 }
   860 }
   718 
   861 
       
   862 /**
       
   863  * Ajax handler for getting comments.
       
   864  *
       
   865  * @since 3.1.0
       
   866  *
       
   867  * @param string $action Action to perform.
       
   868  */
   719 function wp_ajax_get_comments( $action ) {
   869 function wp_ajax_get_comments( $action ) {
   720 	global $wp_list_table, $post_id;
   870 	global $wp_list_table, $post_id;
   721 	if ( empty( $action ) )
   871 	if ( empty( $action ) )
   722 		$action = 'get-comments';
   872 		$action = 'get-comments';
   723 
   873 
   758 		'data' => $comment_list_item
   908 		'data' => $comment_list_item
   759 	) );
   909 	) );
   760 	$x->send();
   910 	$x->send();
   761 }
   911 }
   762 
   912 
       
   913 /**
       
   914  * Ajax handler for replying to a comment.
       
   915  *
       
   916  * @since 3.1.0
       
   917  *
       
   918  * @param string $action Action to perform.
       
   919  */
   763 function wp_ajax_replyto_comment( $action ) {
   920 function wp_ajax_replyto_comment( $action ) {
   764 	global $wp_list_table, $wpdb;
   921 	global $wp_list_table;
   765 	if ( empty( $action ) )
   922 	if ( empty( $action ) )
   766 		$action = 'replyto-comment';
   923 		$action = 'replyto-comment';
   767 
   924 
   768 	check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );
   925 	check_ajax_referer( $action, '_ajax_nonce-replyto-comment' );
   769 
   926 
   784 	if ( $user->exists() ) {
   941 	if ( $user->exists() ) {
   785 		$user_ID = $user->ID;
   942 		$user_ID = $user->ID;
   786 		$comment_author       = wp_slash( $user->display_name );
   943 		$comment_author       = wp_slash( $user->display_name );
   787 		$comment_author_email = wp_slash( $user->user_email );
   944 		$comment_author_email = wp_slash( $user->user_email );
   788 		$comment_author_url   = wp_slash( $user->user_url );
   945 		$comment_author_url   = wp_slash( $user->user_url );
   789 		$comment_content      = trim($_POST['content']);
   946 		$comment_content      = trim( $_POST['content'] );
       
   947 		$comment_type         = isset( $_POST['comment_type'] ) ? trim( $_POST['comment_type'] ) : '';
   790 		if ( current_user_can( 'unfiltered_html' ) ) {
   948 		if ( current_user_can( 'unfiltered_html' ) ) {
   791 			if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) )
   949 			if ( ! isset( $_POST['_wp_unfiltered_html_comment'] ) )
   792 				$_POST['_wp_unfiltered_html_comment'] = '';
   950 				$_POST['_wp_unfiltered_html_comment'] = '';
   793 
   951 
   794 			if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) {
   952 			if ( wp_create_nonce( 'unfiltered-html-comment' ) != $_POST['_wp_unfiltered_html_comment'] ) {
   807 	if ( isset( $_POST['comment_ID'] ) )
   965 	if ( isset( $_POST['comment_ID'] ) )
   808 		$comment_parent = absint( $_POST['comment_ID'] );
   966 		$comment_parent = absint( $_POST['comment_ID'] );
   809 	$comment_auto_approved = false;
   967 	$comment_auto_approved = false;
   810 	$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
   968 	$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type', 'comment_parent', 'user_ID');
   811 
   969 
   812 	// automatically approve parent comment
   970 	// Automatically approve parent comment.
   813 	if ( !empty($_POST['approve_parent']) ) {
   971 	if ( !empty($_POST['approve_parent']) ) {
   814 		$parent = get_comment( $comment_parent );
   972 		$parent = get_comment( $comment_parent );
   815 
   973 
   816 		if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) {
   974 		if ( $parent && $parent->comment_approved === '0' && $parent->comment_post_ID == $comment_post_ID ) {
   817 			if ( wp_set_comment_status( $parent->comment_ID, 'approve' ) )
   975 			if ( wp_set_comment_status( $parent->comment_ID, 'approve' ) )
   852 	$x = new WP_Ajax_Response();
  1010 	$x = new WP_Ajax_Response();
   853 	$x->add( $response );
  1011 	$x->add( $response );
   854 	$x->send();
  1012 	$x->send();
   855 }
  1013 }
   856 
  1014 
       
  1015 /**
       
  1016  * Ajax handler for editing a comment.
       
  1017  *
       
  1018  * @since 3.1.0
       
  1019  */
   857 function wp_ajax_edit_comment() {
  1020 function wp_ajax_edit_comment() {
   858 	global $wp_list_table;
  1021 	global $wp_list_table;
   859 
  1022 
   860 	check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' );
  1023 	check_ajax_referer( 'replyto-comment', '_ajax_nonce-replyto-comment' );
   861 
  1024 
   869 	if ( isset( $_POST['status'] ) )
  1032 	if ( isset( $_POST['status'] ) )
   870 		$_POST['comment_status'] = $_POST['status'];
  1033 		$_POST['comment_status'] = $_POST['status'];
   871 	edit_comment();
  1034 	edit_comment();
   872 
  1035 
   873 	$position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1';
  1036 	$position = ( isset($_POST['position']) && (int) $_POST['position']) ? (int) $_POST['position'] : '-1';
   874 	$comments_status = isset($_POST['comments_listing']) ? $_POST['comments_listing'] : '';
       
   875 
       
   876 	$checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0;
  1037 	$checkbox = ( isset($_POST['checkbox']) && true == $_POST['checkbox'] ) ? 1 : 0;
   877 	$wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
  1038 	$wp_list_table = _get_list_table( $checkbox ? 'WP_Comments_List_Table' : 'WP_Post_Comments_List_Table', array( 'screen' => 'edit-comments' ) );
   878 
  1039 
   879 	$comment = get_comment( $comment_id );
  1040 	$comment = get_comment( $comment_id );
   880 	if ( empty( $comment->comment_ID ) )
  1041 	if ( empty( $comment->comment_ID ) )
   894 	));
  1055 	));
   895 
  1056 
   896 	$x->send();
  1057 	$x->send();
   897 }
  1058 }
   898 
  1059 
       
  1060 /**
       
  1061  * Ajax handler for adding a menu item.
       
  1062  *
       
  1063  * @since 3.1.0
       
  1064  */
   899 function wp_ajax_add_menu_item() {
  1065 function wp_ajax_add_menu_item() {
   900 	check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
  1066 	check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
   901 
  1067 
   902 	if ( ! current_user_can( 'edit_theme_options' ) )
  1068 	if ( ! current_user_can( 'edit_theme_options' ) )
   903 		wp_die( -1 );
  1069 		wp_die( -1 );
   923 					$_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
  1089 					$_object = get_term( $menu_item_data['menu-item-object-id'], $menu_item_data['menu-item-object'] );
   924 				break;
  1090 				break;
   925 			}
  1091 			}
   926 
  1092 
   927 			$_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
  1093 			$_menu_items = array_map( 'wp_setup_nav_menu_item', array( $_object ) );
   928 			$_menu_item = array_shift( $_menu_items );
  1094 			$_menu_item = reset( $_menu_items );
   929 
  1095 
   930 			// Restore the missing menu item properties
  1096 			// Restore the missing menu item properties
   931 			$menu_item_data['menu-item-description'] = $_menu_item->description;
  1097 			$menu_item_data['menu-item-description'] = $_menu_item->description;
   932 		}
  1098 		}
   933 
  1099 
   947 			$menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items
  1113 			$menu_obj->label = $menu_obj->title; // don't show "(pending)" in ajax-added items
   948 			$menu_items[] = $menu_obj;
  1114 			$menu_items[] = $menu_obj;
   949 		}
  1115 		}
   950 	}
  1116 	}
   951 
  1117 
   952 	/**
  1118 	/** This filter is documented in wp-admin/includes/nav-menu.php */
   953 	 * Filter the Walker class used when adding nav menu items.
       
   954 	 *
       
   955 	 * @since 3.4.0
       
   956 	 *
       
   957 	 * @param string $class   The walker class to use. Default 'Walker_Nav_Menu_Edit'.
       
   958 	 * @param int    $menu_id The menu id, derived from $_POST['menu'].
       
   959 	 */
       
   960 	$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] );
  1119 	$walker_class_name = apply_filters( 'wp_edit_nav_menu_walker', 'Walker_Nav_Menu_Edit', $_POST['menu'] );
   961 
  1120 
   962 	if ( ! class_exists( $walker_class_name ) )
  1121 	if ( ! class_exists( $walker_class_name ) )
   963 		wp_die( 0 );
  1122 		wp_die( 0 );
   964 
  1123 
   973 		echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
  1132 		echo walk_nav_menu_tree( $menu_items, 0, (object) $args );
   974 	}
  1133 	}
   975 	wp_die();
  1134 	wp_die();
   976 }
  1135 }
   977 
  1136 
       
  1137 /**
       
  1138  * Ajax handler for adding meta.
       
  1139  *
       
  1140  * @since 3.1.0
       
  1141  */
   978 function wp_ajax_add_meta() {
  1142 function wp_ajax_add_meta() {
   979 	check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' );
  1143 	check_ajax_referer( 'add-meta', '_ajax_nonce-add-meta' );
   980 	$c = 0;
  1144 	$c = 0;
   981 	$pid = (int) $_POST['post_id'];
  1145 	$pid = (int) $_POST['post_id'];
   982 	$post = get_post( $pid );
  1146 	$post = get_post( $pid );
   984 	if ( isset($_POST['metakeyselect']) || isset($_POST['metakeyinput']) ) {
  1148 	if ( isset($_POST['metakeyselect']) || isset($_POST['metakeyinput']) ) {
   985 		if ( !current_user_can( 'edit_post', $pid ) )
  1149 		if ( !current_user_can( 'edit_post', $pid ) )
   986 			wp_die( -1 );
  1150 			wp_die( -1 );
   987 		if ( isset($_POST['metakeyselect']) && '#NONE#' == $_POST['metakeyselect'] && empty($_POST['metakeyinput']) )
  1151 		if ( isset($_POST['metakeyselect']) && '#NONE#' == $_POST['metakeyselect'] && empty($_POST['metakeyinput']) )
   988 			wp_die( 1 );
  1152 			wp_die( 1 );
       
  1153 
       
  1154 		// If the post is an autodraft, save the post as a draft and then attempt to save the meta.
   989 		if ( $post->post_status == 'auto-draft' ) {
  1155 		if ( $post->post_status == 'auto-draft' ) {
   990 			$save_POST = $_POST; // Backup $_POST
  1156 			$save_POST = $_POST; // Backup $_POST
   991 			$_POST = array(); // Make it empty for edit_post()
  1157 			$_POST = array(); // Make it empty for edit_post()
   992 			$_POST['action'] = 'draft'; // Warning fix
  1158 			$_POST['action'] = 'draft'; // Warning fix
   993 			$_POST['post_ID'] = $pid;
  1159 			$_POST['post_ID'] = $pid;
  1008 				if ( !$mid = add_meta( $pid ) )
  1174 				if ( !$mid = add_meta( $pid ) )
  1009 					wp_die( __( 'Please provide a custom field value.' ) );
  1175 					wp_die( __( 'Please provide a custom field value.' ) );
  1010 			} else {
  1176 			} else {
  1011 				wp_die( 0 );
  1177 				wp_die( 0 );
  1012 			}
  1178 			}
  1013 		} else if ( !$mid = add_meta( $pid ) ) {
  1179 		} elseif ( ! $mid = add_meta( $pid ) ) {
  1014 			wp_die( __( 'Please provide a custom field value.' ) );
  1180 			wp_die( __( 'Please provide a custom field value.' ) );
  1015 		}
  1181 		}
  1016 
  1182 
  1017 		$meta = get_metadata_by_mid( 'post', $mid );
  1183 		$meta = get_metadata_by_mid( 'post', $mid );
  1018 		$pid = (int) $meta->post_id;
  1184 		$pid = (int) $meta->post_id;
  1056 		) );
  1222 		) );
  1057 	}
  1223 	}
  1058 	$x->send();
  1224 	$x->send();
  1059 }
  1225 }
  1060 
  1226 
       
  1227 /**
       
  1228  * Ajax handler for adding a user.
       
  1229  *
       
  1230  * @since 3.1.0
       
  1231  *
       
  1232  * @param string $action Action to perform.
       
  1233  */
  1061 function wp_ajax_add_user( $action ) {
  1234 function wp_ajax_add_user( $action ) {
  1062 	global $wp_list_table;
  1235 	global $wp_list_table;
  1063 	if ( empty( $action ) )
  1236 	if ( empty( $action ) )
  1064 		$action = 'add-user';
  1237 		$action = 'add-user';
  1065 
  1238 
  1091 		)
  1264 		)
  1092 	) );
  1265 	) );
  1093 	$x->send();
  1266 	$x->send();
  1094 }
  1267 }
  1095 
  1268 
  1096 function wp_ajax_autosave() {
  1269 /**
  1097 	define( 'DOING_AUTOSAVE', true );
  1270  * Ajax handler for closed post boxes.
  1098 
  1271  *
  1099 	check_ajax_referer( 'autosave', 'autosavenonce' );
  1272  * @since 3.1.0
  1100 
  1273  */
  1101 	if ( ! empty( $_POST['catslist'] ) )
       
  1102 		$_POST['post_category'] = explode( ',', $_POST['catslist'] );
       
  1103 	if ( $_POST['post_type'] == 'page' || empty( $_POST['post_category'] ) )
       
  1104 		unset( $_POST['post_category'] );
       
  1105 
       
  1106 	$data = '';
       
  1107 	$supplemental = array();
       
  1108 	$id = $revision_id = 0;
       
  1109 
       
  1110 	$post_id = (int) $_POST['post_id'];
       
  1111 	$_POST['ID'] = $_POST['post_ID'] = $post_id;
       
  1112 	$post = get_post( $post_id );
       
  1113 	if ( empty( $post->ID ) || ! current_user_can( 'edit_post', $post->ID ) )
       
  1114 		wp_die( __( 'You are not allowed to edit this post.' ) );
       
  1115 
       
  1116 	if ( 'page' == $post->post_type && ! current_user_can( 'edit_page', $post->ID ) )
       
  1117 		wp_die( __( 'You are not allowed to edit this page.' ) );
       
  1118 
       
  1119 	if ( 'auto-draft' == $post->post_status )
       
  1120 		$_POST['post_status'] = 'draft';
       
  1121 
       
  1122 	if ( ! empty( $_POST['autosave'] ) ) {
       
  1123 		if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
       
  1124 			// Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked
       
  1125 			$id = edit_post();
       
  1126 		} else {
       
  1127 			// Non drafts or other users drafts are not overwritten. The autosave is stored in a special post revision for each user.
       
  1128 			$revision_id = wp_create_post_autosave( $post->ID );
       
  1129 			if ( is_wp_error($revision_id) )
       
  1130 				$id = $revision_id;
       
  1131 			else
       
  1132 				$id = $post->ID;
       
  1133 		}
       
  1134 
       
  1135 		if ( ! is_wp_error($id) ) {
       
  1136 			/* translators: draft saved date format, see http://php.net/date */
       
  1137 			$draft_saved_date_format = __('g:i:s a');
       
  1138 			/* translators: %s: date and time */
       
  1139 			$data = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
       
  1140 		}
       
  1141 	} else {
       
  1142 		if ( ! empty( $_POST['auto_draft'] ) )
       
  1143 			$id = 0; // This tells us it didn't actually save
       
  1144 		else
       
  1145 			$id = $post->ID;
       
  1146 	}
       
  1147 
       
  1148 	// @todo Consider exposing any errors, rather than having 'Saving draft...'
       
  1149 	$x = new WP_Ajax_Response( array(
       
  1150 		'what' => 'autosave',
       
  1151 		'id' => $id,
       
  1152 		'data' => $data,
       
  1153 		'supplemental' => $supplemental
       
  1154 	) );
       
  1155 	$x->send();
       
  1156 }
       
  1157 
       
  1158 function wp_ajax_closed_postboxes() {
  1274 function wp_ajax_closed_postboxes() {
  1159 	check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
  1275 	check_ajax_referer( 'closedpostboxes', 'closedpostboxesnonce' );
  1160 	$closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array();
  1276 	$closed = isset( $_POST['closed'] ) ? explode( ',', $_POST['closed']) : array();
  1161 	$closed = array_filter($closed);
  1277 	$closed = array_filter($closed);
  1162 
  1278 
  1180 	}
  1296 	}
  1181 
  1297 
  1182 	wp_die( 1 );
  1298 	wp_die( 1 );
  1183 }
  1299 }
  1184 
  1300 
       
  1301 /**
       
  1302  * Ajax handler for hidden columns.
       
  1303  *
       
  1304  * @since 3.1.0
       
  1305  */
  1185 function wp_ajax_hidden_columns() {
  1306 function wp_ajax_hidden_columns() {
  1186 	check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' );
  1307 	check_ajax_referer( 'screen-options-nonce', 'screenoptionnonce' );
  1187 	$hidden = isset( $_POST['hidden'] ) ? $_POST['hidden'] : '';
  1308 	$hidden = explode( ',', isset( $_POST['hidden'] ) ? $_POST['hidden'] : '' );
  1188 	$hidden = explode( ',', $_POST['hidden'] );
       
  1189 	$page = isset( $_POST['page'] ) ? $_POST['page'] : '';
  1309 	$page = isset( $_POST['page'] ) ? $_POST['page'] : '';
  1190 
  1310 
  1191 	if ( $page != sanitize_key( $page ) )
  1311 	if ( $page != sanitize_key( $page ) )
  1192 		wp_die( 0 );
  1312 		wp_die( 0 );
  1193 
  1313 
  1198 		update_user_option($user->ID, "manage{$page}columnshidden", $hidden, true);
  1318 		update_user_option($user->ID, "manage{$page}columnshidden", $hidden, true);
  1199 
  1319 
  1200 	wp_die( 1 );
  1320 	wp_die( 1 );
  1201 }
  1321 }
  1202 
  1322 
       
  1323 /**
       
  1324  * Ajax handler for updating whether to display the welcome panel.
       
  1325  *
       
  1326  * @since 3.1.0
       
  1327  */
  1203 function wp_ajax_update_welcome_panel() {
  1328 function wp_ajax_update_welcome_panel() {
  1204 	check_ajax_referer( 'welcome-panel-nonce', 'welcomepanelnonce' );
  1329 	check_ajax_referer( 'welcome-panel-nonce', 'welcomepanelnonce' );
  1205 
  1330 
  1206 	if ( ! current_user_can( 'edit_theme_options' ) )
  1331 	if ( ! current_user_can( 'edit_theme_options' ) )
  1207 		wp_die( -1 );
  1332 		wp_die( -1 );
  1209 	update_user_meta( get_current_user_id(), 'show_welcome_panel', empty( $_POST['visible'] ) ? 0 : 1 );
  1334 	update_user_meta( get_current_user_id(), 'show_welcome_panel', empty( $_POST['visible'] ) ? 0 : 1 );
  1210 
  1335 
  1211 	wp_die( 1 );
  1336 	wp_die( 1 );
  1212 }
  1337 }
  1213 
  1338 
       
  1339 /**
       
  1340  * Ajax handler for retrieving menu meta boxes.
       
  1341  *
       
  1342  * @since 3.1.0
       
  1343  */
  1214 function wp_ajax_menu_get_metabox() {
  1344 function wp_ajax_menu_get_metabox() {
  1215 	if ( ! current_user_can( 'edit_theme_options' ) )
  1345 	if ( ! current_user_can( 'edit_theme_options' ) )
  1216 		wp_die( -1 );
  1346 		wp_die( -1 );
  1217 
  1347 
  1218 	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
  1348 	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
  1227 		$items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' );
  1357 		$items = (array) get_taxonomies( array( 'show_ui' => true ), 'object' );
  1228 	}
  1358 	}
  1229 
  1359 
  1230 	if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) {
  1360 	if ( ! empty( $_POST['item-object'] ) && isset( $items[$_POST['item-object']] ) ) {
  1231 		$menus_meta_box_object = $items[ $_POST['item-object'] ];
  1361 		$menus_meta_box_object = $items[ $_POST['item-object'] ];
  1232 		/**
  1362 
  1233 		 * Filter a nav menu meta box object.
  1363 		/** This filter is documented in wp-admin/includes/nav-menu.php */
  1234 		 *
       
  1235 		 * @since 3.0.0
       
  1236 		 *
       
  1237 		 * @param object $menus_meta_box_object A nav menu meta box object, such as Page, Post, Category, Tag, etc.
       
  1238 		 */
       
  1239 		$item = apply_filters( 'nav_menu_meta_box_object', $menus_meta_box_object );
  1364 		$item = apply_filters( 'nav_menu_meta_box_object', $menus_meta_box_object );
  1240 		ob_start();
  1365 		ob_start();
  1241 		call_user_func_array($callback, array(
  1366 		call_user_func_array($callback, array(
  1242 			null,
  1367 			null,
  1243 			array(
  1368 			array(
  1248 			)
  1373 			)
  1249 		));
  1374 		));
  1250 
  1375 
  1251 		$markup = ob_get_clean();
  1376 		$markup = ob_get_clean();
  1252 
  1377 
  1253 		echo json_encode(array(
  1378 		echo wp_json_encode(array(
  1254 			'replace-id' => $type . '-' . $item->name,
  1379 			'replace-id' => $type . '-' . $item->name,
  1255 			'markup' => $markup,
  1380 			'markup' => $markup,
  1256 		));
  1381 		));
  1257 	}
  1382 	}
  1258 
  1383 
  1259 	wp_die();
  1384 	wp_die();
  1260 }
  1385 }
  1261 
  1386 
       
  1387 /**
       
  1388  * Ajax handler for internal linking.
       
  1389  *
       
  1390  * @since 3.1.0
       
  1391  */
  1262 function wp_ajax_wp_link_ajax() {
  1392 function wp_ajax_wp_link_ajax() {
  1263 	check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' );
  1393 	check_ajax_referer( 'internal-linking', '_ajax_linking_nonce' );
  1264 
  1394 
  1265 	$args = array();
  1395 	$args = array();
  1266 
  1396 
  1272 	$results = _WP_Editors::wp_link_query( $args );
  1402 	$results = _WP_Editors::wp_link_query( $args );
  1273 
  1403 
  1274 	if ( ! isset( $results ) )
  1404 	if ( ! isset( $results ) )
  1275 		wp_die( 0 );
  1405 		wp_die( 0 );
  1276 
  1406 
  1277 	echo json_encode( $results );
  1407 	echo wp_json_encode( $results );
  1278 	echo "\n";
  1408 	echo "\n";
  1279 
  1409 
  1280 	wp_die();
  1410 	wp_die();
  1281 }
  1411 }
  1282 
  1412 
       
  1413 /**
       
  1414  * Ajax handler for menu locations save.
       
  1415  *
       
  1416  * @since 3.1.0
       
  1417  */
  1283 function wp_ajax_menu_locations_save() {
  1418 function wp_ajax_menu_locations_save() {
  1284 	if ( ! current_user_can( 'edit_theme_options' ) )
  1419 	if ( ! current_user_can( 'edit_theme_options' ) )
  1285 		wp_die( -1 );
  1420 		wp_die( -1 );
  1286 	check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
  1421 	check_ajax_referer( 'add-menu_item', 'menu-settings-column-nonce' );
  1287 	if ( ! isset( $_POST['menu-locations'] ) )
  1422 	if ( ! isset( $_POST['menu-locations'] ) )
  1288 		wp_die( 0 );
  1423 		wp_die( 0 );
  1289 	set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) );
  1424 	set_theme_mod( 'nav_menu_locations', array_map( 'absint', $_POST['menu-locations'] ) );
  1290 	wp_die( 1 );
  1425 	wp_die( 1 );
  1291 }
  1426 }
  1292 
  1427 
       
  1428 /**
       
  1429  * Ajax handler for saving the meta box order.
       
  1430  *
       
  1431  * @since 3.1.0
       
  1432  */
  1293 function wp_ajax_meta_box_order() {
  1433 function wp_ajax_meta_box_order() {
  1294 	check_ajax_referer( 'meta-box-order' );
  1434 	check_ajax_referer( 'meta-box-order' );
  1295 	$order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false;
  1435 	$order = isset( $_POST['order'] ) ? (array) $_POST['order'] : false;
  1296 	$page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto';
  1436 	$page_columns = isset( $_POST['page_columns'] ) ? $_POST['page_columns'] : 'auto';
  1297 
  1437 
  1313 		update_user_option($user->ID, "screen_layout_$page", $page_columns, true);
  1453 		update_user_option($user->ID, "screen_layout_$page", $page_columns, true);
  1314 
  1454 
  1315 	wp_die( 1 );
  1455 	wp_die( 1 );
  1316 }
  1456 }
  1317 
  1457 
       
  1458 /**
       
  1459  * Ajax handler for menu quick searching.
       
  1460  *
       
  1461  * @since 3.1.0
       
  1462  */
  1318 function wp_ajax_menu_quick_search() {
  1463 function wp_ajax_menu_quick_search() {
  1319 	if ( ! current_user_can( 'edit_theme_options' ) )
  1464 	if ( ! current_user_can( 'edit_theme_options' ) )
  1320 		wp_die( -1 );
  1465 		wp_die( -1 );
  1321 
  1466 
  1322 	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
  1467 	require_once ABSPATH . 'wp-admin/includes/nav-menu.php';
  1324 	_wp_ajax_menu_quick_search( $_POST );
  1469 	_wp_ajax_menu_quick_search( $_POST );
  1325 
  1470 
  1326 	wp_die();
  1471 	wp_die();
  1327 }
  1472 }
  1328 
  1473 
       
  1474 /**
       
  1475  * Ajax handler to retrieve a permalink.
       
  1476  *
       
  1477  * @since 3.1.0
       
  1478  */
  1329 function wp_ajax_get_permalink() {
  1479 function wp_ajax_get_permalink() {
  1330 	check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
  1480 	check_ajax_referer( 'getpermalink', 'getpermalinknonce' );
  1331 	$post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
  1481 	$post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
  1332 	wp_die( add_query_arg( array( 'preview' => 'true' ), get_permalink( $post_id ) ) );
  1482 	wp_die( add_query_arg( array( 'preview' => 'true' ), get_permalink( $post_id ) ) );
  1333 }
  1483 }
  1334 
  1484 
       
  1485 /**
       
  1486  * Ajax handler to retrieve a sample permalink.
       
  1487  *
       
  1488  * @since 3.1.0
       
  1489  */
  1335 function wp_ajax_sample_permalink() {
  1490 function wp_ajax_sample_permalink() {
  1336 	check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' );
  1491 	check_ajax_referer( 'samplepermalink', 'samplepermalinknonce' );
  1337 	$post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
  1492 	$post_id = isset($_POST['post_id'])? intval($_POST['post_id']) : 0;
  1338 	$title = isset($_POST['new_title'])? $_POST['new_title'] : '';
  1493 	$title = isset($_POST['new_title'])? $_POST['new_title'] : '';
  1339 	$slug = isset($_POST['new_slug'])? $_POST['new_slug'] : null;
  1494 	$slug = isset($_POST['new_slug'])? $_POST['new_slug'] : null;
  1340 	wp_die( get_sample_permalink_html( $post_id, $title, $slug ) );
  1495 	wp_die( get_sample_permalink_html( $post_id, $title, $slug ) );
  1341 }
  1496 }
  1342 
  1497 
       
  1498 /**
       
  1499  * Ajax handler for Quick Edit saving a post from a list table.
       
  1500  *
       
  1501  * @since 3.1.0
       
  1502  */
  1343 function wp_ajax_inline_save() {
  1503 function wp_ajax_inline_save() {
  1344 	global $wp_list_table;
  1504 	global $wp_list_table;
  1345 
  1505 
  1346 	check_ajax_referer( 'inlineeditnonce', '_inline_edit' );
  1506 	check_ajax_referer( 'inlineeditnonce', '_inline_edit' );
  1347 
  1507 
  1364 	}
  1524 	}
  1365 
  1525 
  1366 	$data = &$_POST;
  1526 	$data = &$_POST;
  1367 
  1527 
  1368 	$post = get_post( $post_ID, ARRAY_A );
  1528 	$post = get_post( $post_ID, ARRAY_A );
  1369 	$post = wp_slash($post); //since it is from db
  1529 
       
  1530 	// Since it's coming from the database.
       
  1531 	$post = wp_slash($post);
  1370 
  1532 
  1371 	$data['content'] = $post['post_content'];
  1533 	$data['content'] = $post['post_content'];
  1372 	$data['excerpt'] = $post['post_excerpt'];
  1534 	$data['excerpt'] = $post['post_excerpt'];
  1373 
  1535 
  1374 	// rename
  1536 	// Rename.
  1375 	$data['user_ID'] = get_current_user_id();
  1537 	$data['user_ID'] = get_current_user_id();
  1376 
  1538 
  1377 	if ( isset($data['post_parent']) )
  1539 	if ( isset($data['post_parent']) )
  1378 		$data['parent_id'] = $data['post_parent'];
  1540 		$data['parent_id'] = $data['post_parent'];
  1379 
  1541 
  1380 	// status
  1542 	// Status.
  1381 	if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
  1543 	if ( isset($data['keep_private']) && 'private' == $data['keep_private'] )
  1382 		$data['post_status'] = 'private';
  1544 		$data['post_status'] = 'private';
  1383 	else
  1545 	else
  1384 		$data['post_status'] = $data['_status'];
  1546 		$data['post_status'] = $data['_status'];
  1385 
  1547 
  1386 	if ( empty($data['comment_status']) )
  1548 	if ( empty($data['comment_status']) )
  1387 		$data['comment_status'] = 'closed';
  1549 		$data['comment_status'] = 'closed';
  1388 	if ( empty($data['ping_status']) )
  1550 	if ( empty($data['ping_status']) )
  1389 		$data['ping_status'] = 'closed';
  1551 		$data['ping_status'] = 'closed';
  1390 
  1552 
       
  1553 	// Exclude terms from taxonomies that are not supposed to appear in Quick Edit.
       
  1554 	if ( ! empty( $data['tax_input'] ) ) {
       
  1555 		foreach ( $data['tax_input'] as $taxonomy => $terms ) {
       
  1556 			$tax_object = get_taxonomy( $taxonomy );
       
  1557 			/** This filter is documented in wp-admin/includes/class-wp-posts-list-table.php */
       
  1558 			if ( ! apply_filters( 'quick_edit_show_taxonomy', $tax_object->show_in_quick_edit, $taxonomy, $post['post_type'] ) ) {
       
  1559 				unset( $data['tax_input'][ $taxonomy ] );
       
  1560 			}
       
  1561 		}
       
  1562 	}
       
  1563 
  1391 	// Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published.
  1564 	// Hack: wp_unique_post_slug() doesn't work for drafts, so we will fake that our post is published.
  1392 	if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) {
  1565 	if ( ! empty( $data['post_name'] ) && in_array( $post['post_status'], array( 'draft', 'pending' ) ) ) {
  1393 		$post['post_status'] = 'publish';
  1566 		$post['post_status'] = 'publish';
  1394 		$data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] );
  1567 		$data['post_name'] = wp_unique_post_slug( $data['post_name'], $post['ID'], $post['post_status'], $post['post_type'], $post['post_parent'] );
  1395 	}
  1568 	}
  1396 
  1569 
  1397 	// update the post
  1570 	// Update the post.
  1398 	edit_post();
  1571 	edit_post();
  1399 
  1572 
  1400 	$wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
  1573 	$wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
  1401 
       
  1402 	$mode = $_POST['post_view'];
       
  1403 
  1574 
  1404 	$level = 0;
  1575 	$level = 0;
  1405 	$request_post = array( get_post( $_POST['post_ID'] ) );
  1576 	$request_post = array( get_post( $_POST['post_ID'] ) );
  1406 	$parent = $request_post[0]->post_parent;
  1577 	$parent = $request_post[0]->post_parent;
  1407 
  1578 
  1414 	$wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level );
  1585 	$wp_list_table->display_rows( array( get_post( $_POST['post_ID'] ) ), $level );
  1415 
  1586 
  1416 	wp_die();
  1587 	wp_die();
  1417 }
  1588 }
  1418 
  1589 
       
  1590 /**
       
  1591  * Ajax handler for quick edit saving for a term.
       
  1592  *
       
  1593  * @since 3.1.0
       
  1594  */
  1419 function wp_ajax_inline_save_tax() {
  1595 function wp_ajax_inline_save_tax() {
  1420 	global $wp_list_table;
  1596 	global $wp_list_table;
  1421 
  1597 
  1422 	check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
  1598 	check_ajax_referer( 'taxinlineeditnonce', '_inline_edit' );
  1423 
  1599 
  1459 	}
  1635 	}
  1460 	$wp_list_table->single_row( $tag, $level );
  1636 	$wp_list_table->single_row( $tag, $level );
  1461 	wp_die();
  1637 	wp_die();
  1462 }
  1638 }
  1463 
  1639 
       
  1640 /**
       
  1641  * Ajax handler for querying posts for the Find Posts modal.
       
  1642  *
       
  1643  * @see window.findPosts
       
  1644  *
       
  1645  * @since 3.1.0
       
  1646  */
  1464 function wp_ajax_find_posts() {
  1647 function wp_ajax_find_posts() {
  1465 	global $wpdb;
       
  1466 
       
  1467 	check_ajax_referer( 'find-posts' );
  1648 	check_ajax_referer( 'find-posts' );
  1468 
  1649 
  1469 	$post_types = get_post_types( array( 'public' => true ), 'objects' );
  1650 	$post_types = get_post_types( array( 'public' => true ), 'objects' );
  1470 	unset( $post_types['attachment'] );
  1651 	unset( $post_types['attachment'] );
  1471 
  1652 
  1472 	$s = wp_unslash( $_POST['ps'] );
  1653 	$s = wp_unslash( $_POST['ps'] );
  1473 	$searchand = $search = '';
       
  1474 	$args = array(
  1654 	$args = array(
  1475 		'post_type' => array_keys( $post_types ),
  1655 		'post_type' => array_keys( $post_types ),
  1476 		'post_status' => 'any',
  1656 		'post_status' => 'any',
  1477 		'posts_per_page' => 50,
  1657 		'posts_per_page' => 50,
  1478 	);
  1658 	);
  1479 	if ( '' !== $s )
  1659 	if ( '' !== $s )
  1480 		$args['s'] = $s;
  1660 		$args['s'] = $s;
  1481 
  1661 
  1482 	$posts = get_posts( $args );
  1662 	$posts = get_posts( $args );
  1483 
  1663 
  1484 	if ( ! $posts )
  1664 	if ( ! $posts ) {
  1485 		wp_die( __('No items found.') );
  1665 		wp_send_json_error( __( 'No items found.' ) );
  1486 
  1666 	}
  1487 	$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>';
  1667 
       
  1668 	$html = '<table class="widefat"><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>';
       
  1669 	$alt = '';
  1488 	foreach ( $posts as $post ) {
  1670 	foreach ( $posts as $post ) {
  1489 		$title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' );
  1671 		$title = trim( $post->post_title ) ? $post->post_title : __( '(no title)' );
       
  1672 		$alt = ( 'alternate' == $alt ) ? '' : 'alternate';
  1490 
  1673 
  1491 		switch ( $post->post_status ) {
  1674 		switch ( $post->post_status ) {
  1492 			case 'publish' :
  1675 			case 'publish' :
  1493 			case 'private' :
  1676 			case 'private' :
  1494 				$stat = __('Published');
  1677 				$stat = __('Published');
  1509 		} else {
  1692 		} else {
  1510 			/* translators: date format in table columns, see http://php.net/date */
  1693 			/* translators: date format in table columns, see http://php.net/date */
  1511 			$time = mysql2date(__('Y/m/d'), $post->post_date);
  1694 			$time = mysql2date(__('Y/m/d'), $post->post_date);
  1512 		}
  1695 		}
  1513 
  1696 
  1514 		$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>';
  1697 		$html .= '<tr class="' . trim( 'found-posts ' . $alt ) . '"><td class="found-radio"><input type="radio" id="found-'.$post->ID.'" name="found_post_id" value="' . esc_attr($post->ID) . '"></td>';
  1515 		$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";
  1698 		$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";
  1516 	}
  1699 	}
  1517 
  1700 
  1518 	$html .= '</tbody></table>';
  1701 	$html .= '</tbody></table>';
  1519 
  1702 
  1520 	$x = new WP_Ajax_Response();
  1703 	wp_send_json_success( $html );
  1521 	$x->add( array(
  1704 }
  1522 		'data' => $html
  1705 
  1523 	));
  1706 /**
  1524 	$x->send();
  1707  * Ajax handler for saving the widgets order.
  1525 }
  1708  *
  1526 
  1709  * @since 3.1.0
       
  1710  */
  1527 function wp_ajax_widgets_order() {
  1711 function wp_ajax_widgets_order() {
  1528 	check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
  1712 	check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
  1529 
  1713 
  1530 	if ( !current_user_can('edit_theme_options') )
  1714 	if ( !current_user_can('edit_theme_options') )
  1531 		wp_die( -1 );
  1715 		wp_die( -1 );
  1532 
  1716 
  1533 	unset( $_POST['savewidgets'], $_POST['action'] );
  1717 	unset( $_POST['savewidgets'], $_POST['action'] );
  1534 
  1718 
  1535 	// save widgets order for all sidebars
  1719 	// Save widgets order for all sidebars.
  1536 	if ( is_array($_POST['sidebars']) ) {
  1720 	if ( is_array($_POST['sidebars']) ) {
  1537 		$sidebars = array();
  1721 		$sidebars = array();
  1538 		foreach ( $_POST['sidebars'] as $key => $val ) {
  1722 		foreach ( $_POST['sidebars'] as $key => $val ) {
  1539 			$sb = array();
  1723 			$sb = array();
  1540 			if ( !empty($val) ) {
  1724 			if ( !empty($val) ) {
  1553 	}
  1737 	}
  1554 
  1738 
  1555 	wp_die( -1 );
  1739 	wp_die( -1 );
  1556 }
  1740 }
  1557 
  1741 
       
  1742 /**
       
  1743  * Ajax handler for saving a widget.
       
  1744  *
       
  1745  * @since 3.1.0
       
  1746  */
  1558 function wp_ajax_save_widget() {
  1747 function wp_ajax_save_widget() {
  1559 	global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
  1748 	global $wp_registered_widgets, $wp_registered_widget_controls, $wp_registered_widget_updates;
  1560 
  1749 
  1561 	check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
  1750 	check_ajax_referer( 'save-sidebar-widgets', 'savewidgets' );
  1562 
  1751 
  1577 	 *
  1766 	 *
  1578 	 * @since 2.8.0
  1767 	 * @since 2.8.0
  1579 	 */
  1768 	 */
  1580 	do_action( 'widgets.php' );
  1769 	do_action( 'widgets.php' );
  1581 
  1770 
  1582 	/**
  1771 	/** This action is documented in wp-admin/widgets.php */
  1583 	 * Fires early when editing the widgets displayed in sidebars.
       
  1584 	 *
       
  1585 	 * @since 2.2.0
       
  1586 	 */
       
  1587 	do_action( 'sidebar_admin_setup' );
  1772 	do_action( 'sidebar_admin_setup' );
  1588 
  1773 
  1589 	$id_base = $_POST['id_base'];
  1774 	$id_base = $_POST['id_base'];
  1590 	$widget_id = $_POST['widget-id'];
  1775 	$widget_id = $_POST['widget-id'];
  1591 	$sidebar_id = $_POST['sidebar'];
  1776 	$sidebar_id = $_POST['sidebar'];
  1594 	$error = '<p>' . __('An error has occurred. Please reload the page and try again.') . '</p>';
  1779 	$error = '<p>' . __('An error has occurred. Please reload the page and try again.') . '</p>';
  1595 
  1780 
  1596 	$sidebars = wp_get_sidebars_widgets();
  1781 	$sidebars = wp_get_sidebars_widgets();
  1597 	$sidebar = isset($sidebars[$sidebar_id]) ? $sidebars[$sidebar_id] : array();
  1782 	$sidebar = isset($sidebars[$sidebar_id]) ? $sidebars[$sidebar_id] : array();
  1598 
  1783 
  1599 	// delete
  1784 	// Delete.
  1600 	if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
  1785 	if ( isset($_POST['delete_widget']) && $_POST['delete_widget'] ) {
  1601 
  1786 
  1602 		if ( !isset($wp_registered_widgets[$widget_id]) )
  1787 		if ( !isset($wp_registered_widgets[$widget_id]) )
  1603 			wp_die( $error );
  1788 			wp_die( $error );
  1604 
  1789 
  1606 		$_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1');
  1791 		$_POST = array('sidebar' => $sidebar_id, 'widget-' . $id_base => array(), 'the-widget-id' => $widget_id, 'delete_widget' => '1');
  1607 	} elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) {
  1792 	} elseif ( $settings && preg_match( '/__i__|%i%/', key($settings) ) ) {
  1608 		if ( !$multi_number )
  1793 		if ( !$multi_number )
  1609 			wp_die( $error );
  1794 			wp_die( $error );
  1610 
  1795 
  1611 		$_POST['widget-' . $id_base] = array( $multi_number => array_shift($settings) );
  1796 		$_POST[ 'widget-' . $id_base ] = array( $multi_number => reset( $settings ) );
  1612 		$widget_id = $id_base . '-' . $multi_number;
  1797 		$widget_id = $id_base . '-' . $multi_number;
  1613 		$sidebar[] = $widget_id;
  1798 		$sidebar[] = $widget_id;
  1614 	}
  1799 	}
  1615 	$_POST['widget-id'] = $sidebar;
  1800 	$_POST['widget-id'] = $sidebar;
  1616 
  1801 
  1641 		call_user_func_array( $form['callback'], $form['params'] );
  1826 		call_user_func_array( $form['callback'], $form['params'] );
  1642 
  1827 
  1643 	wp_die();
  1828 	wp_die();
  1644 }
  1829 }
  1645 
  1830 
       
  1831 /**
       
  1832  * Ajax handler for saving a widget.
       
  1833  *
       
  1834  * @since 3.9.0
       
  1835  */
       
  1836 function wp_ajax_update_widget() {
       
  1837 	global $wp_customize;
       
  1838 	$wp_customize->widgets->wp_ajax_update_widget();
       
  1839 }
       
  1840 
       
  1841 /**
       
  1842  * Ajax handler for uploading attachments
       
  1843  *
       
  1844  * @since 3.3.0
       
  1845  */
  1646 function wp_ajax_upload_attachment() {
  1846 function wp_ajax_upload_attachment() {
  1647 	check_ajax_referer( 'media-form' );
  1847 	check_ajax_referer( 'media-form' );
  1648 
  1848 	/*
  1649 	if ( ! current_user_can( 'upload_files' ) )
  1849 	 * This function does not use wp_send_json_success() / wp_send_json_error()
       
  1850 	 * as the html4 Plupload handler requires a text/html content-type for older IE.
       
  1851 	 * See https://core.trac.wordpress.org/ticket/31037
       
  1852 	 */
       
  1853 
       
  1854 	if ( ! current_user_can( 'upload_files' ) ) {
       
  1855 		echo wp_json_encode( array(
       
  1856 			'success' => false,
       
  1857 			'data'    => array(
       
  1858 				'message'  => __( "You don't have permission to upload files." ),
       
  1859 				'filename' => $_FILES['async-upload']['name'],
       
  1860 			)
       
  1861 		) );
       
  1862 
  1650 		wp_die();
  1863 		wp_die();
       
  1864 	}
  1651 
  1865 
  1652 	if ( isset( $_REQUEST['post_id'] ) ) {
  1866 	if ( isset( $_REQUEST['post_id'] ) ) {
  1653 		$post_id = $_REQUEST['post_id'];
  1867 		$post_id = $_REQUEST['post_id'];
  1654 		if ( ! current_user_can( 'edit_post', $post_id ) )
  1868 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
       
  1869 			echo wp_json_encode( array(
       
  1870 				'success' => false,
       
  1871 				'data'    => array(
       
  1872 					'message'  => __( "You don't have permission to attach files to this post." ),
       
  1873 					'filename' => $_FILES['async-upload']['name'],
       
  1874 				)
       
  1875 			) );
       
  1876 
  1655 			wp_die();
  1877 			wp_die();
       
  1878 		}
  1656 	} else {
  1879 	} else {
  1657 		$post_id = null;
  1880 		$post_id = null;
  1658 	}
  1881 	}
  1659 
  1882 
  1660 	$post_data = isset( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array();
  1883 	$post_data = isset( $_REQUEST['post_data'] ) ? $_REQUEST['post_data'] : array();
  1661 
  1884 
  1662 	// If the context is custom header or background, make sure the uploaded file is an image.
  1885 	// If the context is custom header or background, make sure the uploaded file is an image.
  1663 	if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) {
  1886 	if ( isset( $post_data['context'] ) && in_array( $post_data['context'], array( 'custom-header', 'custom-background' ) ) ) {
  1664 		$wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'], false );
  1887 		$wp_filetype = wp_check_filetype_and_ext( $_FILES['async-upload']['tmp_name'], $_FILES['async-upload']['name'] );
  1665 		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
  1888 		if ( ! wp_match_mime_types( 'image', $wp_filetype['type'] ) ) {
  1666 			echo json_encode( array(
  1889 			echo wp_json_encode( array(
  1667 				'success' => false,
  1890 				'success' => false,
  1668 				'data'    => array(
  1891 				'data'    => array(
  1669 					'message'  => __( 'The uploaded file is not a valid image. Please try again.' ),
  1892 					'message'  => __( 'The uploaded file is not a valid image. Please try again.' ),
  1670 					'filename' => $_FILES['async-upload']['name'],
  1893 					'filename' => $_FILES['async-upload']['name'],
  1671 				)
  1894 				)
  1676 	}
  1899 	}
  1677 
  1900 
  1678 	$attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data );
  1901 	$attachment_id = media_handle_upload( 'async-upload', $post_id, $post_data );
  1679 
  1902 
  1680 	if ( is_wp_error( $attachment_id ) ) {
  1903 	if ( is_wp_error( $attachment_id ) ) {
  1681 		echo json_encode( array(
  1904 		echo wp_json_encode( array(
  1682 			'success' => false,
  1905 			'success' => false,
  1683 			'data'    => array(
  1906 			'data'    => array(
  1684 				'message'  => $attachment_id->get_error_message(),
  1907 				'message'  => $attachment_id->get_error_message(),
  1685 				'filename' => $_FILES['async-upload']['name'],
  1908 				'filename' => $_FILES['async-upload']['name'],
  1686 			)
  1909 			)
  1698 	}
  1921 	}
  1699 
  1922 
  1700 	if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) )
  1923 	if ( ! $attachment = wp_prepare_attachment_for_js( $attachment_id ) )
  1701 		wp_die();
  1924 		wp_die();
  1702 
  1925 
  1703 	echo json_encode( array(
  1926 	echo wp_json_encode( array(
  1704 		'success' => true,
  1927 		'success' => true,
  1705 		'data'    => $attachment,
  1928 		'data'    => $attachment,
  1706 	) );
  1929 	) );
  1707 
  1930 
  1708 	wp_die();
  1931 	wp_die();
  1709 }
  1932 }
  1710 
  1933 
       
  1934 /**
       
  1935  * Ajax handler for image editing.
       
  1936  *
       
  1937  * @since 3.1.0
       
  1938  */
  1711 function wp_ajax_image_editor() {
  1939 function wp_ajax_image_editor() {
  1712 	$attachment_id = intval($_POST['postid']);
  1940 	$attachment_id = intval($_POST['postid']);
  1713 	if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) )
  1941 	if ( empty($attachment_id) || !current_user_can('edit_post', $attachment_id) )
  1714 		wp_die( -1 );
  1942 		wp_die( -1 );
  1715 
  1943 
  1718 
  1946 
  1719 	$msg = false;
  1947 	$msg = false;
  1720 	switch ( $_POST['do'] ) {
  1948 	switch ( $_POST['do'] ) {
  1721 		case 'save' :
  1949 		case 'save' :
  1722 			$msg = wp_save_image($attachment_id);
  1950 			$msg = wp_save_image($attachment_id);
  1723 			$msg = json_encode($msg);
  1951 			$msg = wp_json_encode($msg);
  1724 			wp_die( $msg );
  1952 			wp_die( $msg );
  1725 			break;
  1953 			break;
  1726 		case 'scale' :
  1954 		case 'scale' :
  1727 			$msg = wp_save_image($attachment_id);
  1955 			$msg = wp_save_image($attachment_id);
  1728 			break;
  1956 			break;
  1733 
  1961 
  1734 	wp_image_editor($attachment_id, $msg);
  1962 	wp_image_editor($attachment_id, $msg);
  1735 	wp_die();
  1963 	wp_die();
  1736 }
  1964 }
  1737 
  1965 
       
  1966 /**
       
  1967  * Ajax handler for setting the featured image.
       
  1968  *
       
  1969  * @since 3.1.0
       
  1970  */
  1738 function wp_ajax_set_post_thumbnail() {
  1971 function wp_ajax_set_post_thumbnail() {
  1739 	$json = ! empty( $_REQUEST['json'] ); // New-style request
  1972 	$json = ! empty( $_REQUEST['json'] ); // New-style request
  1740 
  1973 
  1741 	$post_ID = intval( $_POST['post_id'] );
  1974 	$post_ID = intval( $_POST['post_id'] );
  1742 	if ( ! current_user_can( 'edit_post', $post_ID ) )
  1975 	if ( ! current_user_can( 'edit_post', $post_ID ) )
  1764 	}
  1997 	}
  1765 
  1998 
  1766 	wp_die( 0 );
  1999 	wp_die( 0 );
  1767 }
  2000 }
  1768 
  2001 
       
  2002 /**
       
  2003  * AJAX handler for setting the featured image for an attachment.
       
  2004  *
       
  2005  * @since 4.0.0
       
  2006  *
       
  2007  * @see set_post_thumbnail()
       
  2008  */
       
  2009 function wp_ajax_set_attachment_thumbnail() {
       
  2010 	if ( empty( $_POST['urls'] ) || ! is_array( $_POST['urls'] ) ) {
       
  2011 		wp_send_json_error();
       
  2012 	}
       
  2013 
       
  2014 	$thumbnail_id = (int) $_POST['thumbnail_id'];
       
  2015 	if ( empty( $thumbnail_id ) ) {
       
  2016 		wp_send_json_error();
       
  2017 	}
       
  2018 
       
  2019 	$post_ids = array();
       
  2020 	// For each URL, try to find its corresponding post ID.
       
  2021 	foreach ( $_POST['urls'] as $url ) {
       
  2022 		$post_id = attachment_url_to_postid( $url );
       
  2023 		if ( ! empty( $post_id ) ) {
       
  2024 			$post_ids[] = $post_id;
       
  2025 		}
       
  2026 	}
       
  2027 
       
  2028 	if ( empty( $post_ids ) ) {
       
  2029 		wp_send_json_error();
       
  2030 	}
       
  2031 
       
  2032 	$success = 0;
       
  2033 	// For each found attachment, set its thumbnail.
       
  2034 	foreach ( $post_ids as $post_id ) {
       
  2035 		if ( ! current_user_can( 'edit_post', $post_id ) ) {
       
  2036 			continue;
       
  2037 		}
       
  2038 
       
  2039 		if ( set_post_thumbnail( $post_id, $thumbnail_id ) ) {
       
  2040 			$success++;
       
  2041 		}
       
  2042 	}
       
  2043 
       
  2044 	if ( 0 === $success ) {
       
  2045 		wp_send_json_error();
       
  2046 	} else {
       
  2047 		wp_send_json_success();
       
  2048 	}
       
  2049 
       
  2050 	wp_send_json_error();
       
  2051 }
       
  2052 
       
  2053 /**
       
  2054  * Ajax handler for date formatting.
       
  2055  *
       
  2056  * @since 3.1.0
       
  2057  */
  1769 function wp_ajax_date_format() {
  2058 function wp_ajax_date_format() {
  1770 	wp_die( date_i18n( sanitize_option( 'date_format', $_POST['date'] ) ) );
  2059 	wp_die( date_i18n( sanitize_option( 'date_format', wp_unslash( $_POST['date'] ) ) ) );
  1771 }
  2060 }
  1772 
  2061 
       
  2062 /**
       
  2063  * Ajax handler for time formatting.
       
  2064  *
       
  2065  * @since 3.1.0
       
  2066  */
  1773 function wp_ajax_time_format() {
  2067 function wp_ajax_time_format() {
  1774 	wp_die( date_i18n( sanitize_option( 'time_format', $_POST['date'] ) ) );
  2068 	wp_die( date_i18n( sanitize_option( 'time_format', wp_unslash( $_POST['date'] ) ) ) );
  1775 }
  2069 }
  1776 
  2070 
       
  2071 /**
       
  2072  * Ajax handler for saving posts from the fullscreen editor.
       
  2073  *
       
  2074  * @since 3.1.0
       
  2075  */
  1777 function wp_ajax_wp_fullscreen_save_post() {
  2076 function wp_ajax_wp_fullscreen_save_post() {
  1778 	$post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
  2077 	$post_id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
  1779 
  2078 
  1780 	$post = $post_type = null;
  2079 	$post = null;
  1781 
  2080 
  1782 	if ( $post_id )
  2081 	if ( $post_id )
  1783 		$post = get_post( $post_id );
  2082 		$post = get_post( $post_id );
  1784 
  2083 
  1785 	if ( $post )
       
  1786 		$post_type = $post->post_type;
       
  1787 	elseif ( isset( $_POST['post_type'] ) && post_type_exists( $_POST['post_type'] ) )
       
  1788 		$post_type = $_POST['post_type'];
       
  1789 
       
  1790 	check_ajax_referer('update-post_' . $post_id, '_wpnonce');
  2084 	check_ajax_referer('update-post_' . $post_id, '_wpnonce');
  1791 
  2085 
  1792 	$post_id = edit_post();
  2086 	$post_id = edit_post();
  1793 
  2087 
  1794 	if ( is_wp_error($post_id) ) {
  2088 	if ( is_wp_error( $post_id ) ) {
  1795 		if ( $post_id->get_error_message() )
  2089 		wp_send_json_error();
  1796 			$message = $post_id->get_error_message();
       
  1797 		else
       
  1798 			$message = __('Save failed');
       
  1799 
       
  1800 		echo json_encode( array( 'message' => $message, 'last_edited' => '' ) );
       
  1801 		wp_die();
       
  1802 	} else {
       
  1803 		$message = __('Saved.');
       
  1804 	}
  2090 	}
  1805 
  2091 
  1806 	if ( $post ) {
  2092 	if ( $post ) {
  1807 		$last_date = mysql2date( get_option('date_format'), $post->post_modified );
  2093 		$last_date = mysql2date( get_option('date_format'), $post->post_modified );
  1808 		$last_time = mysql2date( get_option('time_format'), $post->post_modified );
  2094 		$last_time = mysql2date( get_option('time_format'), $post->post_modified );
  1809 	} else {
  2095 	} else {
  1810 		$last_date = date_i18n( get_option('date_format') );
  2096 		$last_date = date_i18n( get_option('date_format') );
  1811 		$last_time = date_i18n( get_option('time_format') );
  2097 		$last_time = date_i18n( get_option('time_format') );
  1812 	}
  2098 	}
  1813 
  2099 
  1814 	if ( $last_id = get_post_meta($post_id, '_edit_last', true) ) {
  2100 	if ( $last_id = get_post_meta( $post_id, '_edit_last', true ) ) {
  1815 		$last_user = get_userdata($last_id);
  2101 		$last_user = get_userdata( $last_id );
  1816 		$last_edited = sprintf( __('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), $last_date, $last_time );
  2102 		$last_edited = sprintf( __('Last edited by %1$s on %2$s at %3$s'), esc_html( $last_user->display_name ), $last_date, $last_time );
  1817 	} else {
  2103 	} else {
  1818 		$last_edited = sprintf( __('Last edited on %1$s at %2$s'), $last_date, $last_time );
  2104 		$last_edited = sprintf( __('Last edited on %1$s at %2$s'), $last_date, $last_time );
  1819 	}
  2105 	}
  1820 
  2106 
  1821 	echo json_encode( array( 'message' => $message, 'last_edited' => $last_edited ) );
  2107 	wp_send_json_success( array( 'last_edited' => $last_edited ) );
  1822 	wp_die();
  2108 }
  1823 }
  2109 
  1824 
  2110 /**
       
  2111  * Ajax handler for removing a post lock.
       
  2112  *
       
  2113  * @since 3.1.0
       
  2114  */
  1825 function wp_ajax_wp_remove_post_lock() {
  2115 function wp_ajax_wp_remove_post_lock() {
  1826 	if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) )
  2116 	if ( empty( $_POST['post_ID'] ) || empty( $_POST['active_post_lock'] ) )
  1827 		wp_die( 0 );
  2117 		wp_die( 0 );
  1828 	$post_id = (int) $_POST['post_ID'];
  2118 	$post_id = (int) $_POST['post_ID'];
  1829 	if ( ! $post = get_post( $post_id ) )
  2119 	if ( ! $post = get_post( $post_id ) )
  1841 	/**
  2131 	/**
  1842 	 * Filter the post lock window duration.
  2132 	 * Filter the post lock window duration.
  1843 	 *
  2133 	 *
  1844 	 * @since 3.3.0
  2134 	 * @since 3.3.0
  1845 	 *
  2135 	 *
  1846 	 * @param int $interval The interval in seconds the post lock duration should last, plus 5 seconds. Default 120.
  2136 	 * @param int $interval The interval in seconds the post lock duration
       
  2137 	 *                      should last, plus 5 seconds. Default 150.
  1847 	 */
  2138 	 */
  1848 	$new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', 120 ) + 5 ) . ':' . $active_lock[1];
  2139 	$new_lock = ( time() - apply_filters( 'wp_check_post_lock_window', 150 ) + 5 ) . ':' . $active_lock[1];
  1849 	update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) );
  2140 	update_post_meta( $post_id, '_edit_lock', $new_lock, implode( ':', $active_lock ) );
  1850 	wp_die( 1 );
  2141 	wp_die( 1 );
  1851 }
  2142 }
  1852 
  2143 
       
  2144 /**
       
  2145  * Ajax handler for dismissing a WordPress pointer.
       
  2146  *
       
  2147  * @since 3.1.0
       
  2148  */
  1853 function wp_ajax_dismiss_wp_pointer() {
  2149 function wp_ajax_dismiss_wp_pointer() {
  1854 	$pointer = $_POST['pointer'];
  2150 	$pointer = $_POST['pointer'];
  1855 	if ( $pointer != sanitize_key( $pointer ) )
  2151 	if ( $pointer != sanitize_key( $pointer ) )
  1856 		wp_die( 0 );
  2152 		wp_die( 0 );
  1857 
  2153 
  1868 	update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed );
  2164 	update_user_meta( get_current_user_id(), 'dismissed_wp_pointers', $dismissed );
  1869 	wp_die( 1 );
  2165 	wp_die( 1 );
  1870 }
  2166 }
  1871 
  2167 
  1872 /**
  2168 /**
  1873  * Get an attachment.
  2169  * Ajax handler for getting an attachment.
  1874  *
  2170  *
  1875  * @since 3.5.0
  2171  * @since 3.5.0
  1876  */
  2172  */
  1877 function wp_ajax_get_attachment() {
  2173 function wp_ajax_get_attachment() {
  1878 	if ( ! isset( $_REQUEST['id'] ) )
  2174 	if ( ! isset( $_REQUEST['id'] ) )
  1895 
  2191 
  1896 	wp_send_json_success( $attachment );
  2192 	wp_send_json_success( $attachment );
  1897 }
  2193 }
  1898 
  2194 
  1899 /**
  2195 /**
  1900  * Query for attachments.
  2196  * Ajax handler for querying attachments.
  1901  *
  2197  *
  1902  * @since 3.5.0
  2198  * @since 3.5.0
  1903  */
  2199  */
  1904 function wp_ajax_query_attachments() {
  2200 function wp_ajax_query_attachments() {
  1905 	if ( ! current_user_can( 'upload_files' ) )
  2201 	if ( ! current_user_can( 'upload_files' ) )
  1906 		wp_send_json_error();
  2202 		wp_send_json_error();
  1907 
  2203 
  1908 	$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
  2204 	$query = isset( $_REQUEST['query'] ) ? (array) $_REQUEST['query'] : array();
  1909 	$query = array_intersect_key( $query, array_flip( array(
  2205 	$keys = array(
  1910 		's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type',
  2206 		's', 'order', 'orderby', 'posts_per_page', 'paged', 'post_mime_type',
  1911 		'post_parent', 'post__in', 'post__not_in',
  2207 		'post_parent', 'post__in', 'post__not_in', 'year', 'monthnum'
  1912 	) ) );
  2208 	);
  1913 
  2209 	foreach ( get_taxonomies_for_attachments( 'objects' ) as $t ) {
       
  2210 		if ( $t->query_var && isset( $query[ $t->query_var ] ) ) {
       
  2211 			$keys[] = $t->query_var;
       
  2212 		}
       
  2213 	}
       
  2214 
       
  2215 	$query = array_intersect_key( $query, array_flip( $keys ) );
  1914 	$query['post_type'] = 'attachment';
  2216 	$query['post_type'] = 'attachment';
  1915 	$query['post_status'] = 'inherit';
  2217 	if ( MEDIA_TRASH
       
  2218 		&& ! empty( $_REQUEST['query']['post_status'] )
       
  2219 		&& 'trash' === $_REQUEST['query']['post_status'] ) {
       
  2220 		$query['post_status'] = 'trash';
       
  2221 	} else {
       
  2222 		$query['post_status'] = 'inherit';
       
  2223 	}
       
  2224 
  1916 	if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) )
  2225 	if ( current_user_can( get_post_type_object( 'attachment' )->cap->read_private_posts ) )
  1917 		$query['post_status'] .= ',private';
  2226 		$query['post_status'] .= ',private';
  1918 
  2227 
  1919 	/**
  2228 	/**
  1920 	 * Filter the arguments passed to WP_Query during an AJAX call for querying attachments.
  2229 	 * Filter the arguments passed to WP_Query during an AJAX
       
  2230 	 * call for querying attachments.
  1921 	 *
  2231 	 *
  1922 	 * @since 3.7.0
  2232 	 * @since 3.7.0
  1923 	 *
  2233 	 *
  1924 	 * @param array $query An array of query variables. @see WP_Query::parse_query()
  2234 	 * @see WP_Query::parse_query()
       
  2235 	 *
       
  2236 	 * @param array $query An array of query variables.
  1925 	 */
  2237 	 */
  1926 	$query = apply_filters( 'ajax_query_attachments_args', $query );
  2238 	$query = apply_filters( 'ajax_query_attachments_args', $query );
  1927 	$query = new WP_Query( $query );
  2239 	$query = new WP_Query( $query );
  1928 
  2240 
  1929 	$posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
  2241 	$posts = array_map( 'wp_prepare_attachment_for_js', $query->posts );
  1931 
  2243 
  1932 	wp_send_json_success( $posts );
  2244 	wp_send_json_success( $posts );
  1933 }
  2245 }
  1934 
  2246 
  1935 /**
  2247 /**
  1936  * Save attachment attributes.
  2248  * Ajax handler for updating attachment attributes.
  1937  *
  2249  *
  1938  * @since 3.5.0
  2250  * @since 3.5.0
  1939  */
  2251  */
  1940 function wp_ajax_save_attachment() {
  2252 function wp_ajax_save_attachment() {
  1941 	if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) )
  2253 	if ( ! isset( $_REQUEST['id'] ) || ! isset( $_REQUEST['changes'] ) )
  1953 	$post    = get_post( $id, ARRAY_A );
  2265 	$post    = get_post( $id, ARRAY_A );
  1954 
  2266 
  1955 	if ( 'attachment' != $post['post_type'] )
  2267 	if ( 'attachment' != $post['post_type'] )
  1956 		wp_send_json_error();
  2268 		wp_send_json_error();
  1957 
  2269 
       
  2270 	if ( isset( $changes['parent'] ) )
       
  2271 		$post['post_parent'] = $changes['parent'];
       
  2272 
  1958 	if ( isset( $changes['title'] ) )
  2273 	if ( isset( $changes['title'] ) )
  1959 		$post['post_title'] = $changes['title'];
  2274 		$post['post_title'] = $changes['title'];
  1960 
  2275 
  1961 	if ( isset( $changes['caption'] ) )
  2276 	if ( isset( $changes['caption'] ) )
  1962 		$post['post_excerpt'] = $changes['caption'];
  2277 		$post['post_excerpt'] = $changes['caption'];
  1963 
  2278 
  1964 	if ( isset( $changes['description'] ) )
  2279 	if ( isset( $changes['description'] ) )
  1965 		$post['post_content'] = $changes['description'];
  2280 		$post['post_content'] = $changes['description'];
       
  2281 
       
  2282 	if ( MEDIA_TRASH && isset( $changes['status'] ) )
       
  2283 		$post['post_status'] = $changes['status'];
  1966 
  2284 
  1967 	if ( isset( $changes['alt'] ) ) {
  2285 	if ( isset( $changes['alt'] ) ) {
  1968 		$alt = wp_unslash( $changes['alt'] );
  2286 		$alt = wp_unslash( $changes['alt'] );
  1969 		if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) {
  2287 		if ( $alt != get_post_meta( $id, '_wp_attachment_image_alt', true ) ) {
  1970 			$alt = wp_strip_all_tags( $alt, true );
  2288 			$alt = wp_strip_all_tags( $alt, true );
  1971 			update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) );
  2289 			update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) );
  1972 		}
  2290 		}
  1973 	}
  2291 	}
  1974 
  2292 
  1975 	wp_update_post( $post );
  2293 	if ( wp_attachment_is( 'audio', $post['ID'] ) ) {
       
  2294 		$changed = false;
       
  2295 		$id3data = wp_get_attachment_metadata( $post['ID'] );
       
  2296 		if ( ! is_array( $id3data ) ) {
       
  2297 			$changed = true;
       
  2298 			$id3data = array();
       
  2299 		}
       
  2300 		foreach ( wp_get_attachment_id3_keys( (object) $post, 'edit' ) as $key => $label ) {
       
  2301 			if ( isset( $changes[ $key ] ) ) {
       
  2302 				$changed = true;
       
  2303 				$id3data[ $key ] = sanitize_text_field( wp_unslash( $changes[ $key ] ) );
       
  2304 			}
       
  2305 		}
       
  2306 
       
  2307 		if ( $changed ) {
       
  2308 			wp_update_attachment_metadata( $id, $id3data );
       
  2309 		}
       
  2310 	}
       
  2311 
       
  2312 	if ( MEDIA_TRASH && isset( $changes['status'] ) && 'trash' === $changes['status'] ) {
       
  2313 		wp_delete_post( $id );
       
  2314 	} else {
       
  2315 		wp_update_post( $post );
       
  2316 	}
       
  2317 
  1976 	wp_send_json_success();
  2318 	wp_send_json_success();
  1977 }
  2319 }
  1978 
  2320 
  1979 /**
  2321 /**
  1980  * Save backwards compatible attachment attributes.
  2322  * Ajax handler for saving backwards compatible attachment attributes.
  1981  *
  2323  *
  1982  * @since 3.5.0
  2324  * @since 3.5.0
  1983  */
  2325  */
  1984 function wp_ajax_save_attachment_compat() {
  2326 function wp_ajax_save_attachment_compat() {
  1985 	if ( ! isset( $_REQUEST['id'] ) )
  2327 	if ( ! isset( $_REQUEST['id'] ) )
  2021 		wp_send_json_error();
  2363 		wp_send_json_error();
  2022 
  2364 
  2023 	wp_send_json_success( $attachment );
  2365 	wp_send_json_success( $attachment );
  2024 }
  2366 }
  2025 
  2367 
       
  2368 /**
       
  2369  * Ajax handler for saving the attachment order.
       
  2370  *
       
  2371  * @since 3.5.0
       
  2372  */
  2026 function wp_ajax_save_attachment_order() {
  2373 function wp_ajax_save_attachment_order() {
  2027 	if ( ! isset( $_REQUEST['post_id'] ) )
  2374 	if ( ! isset( $_REQUEST['post_id'] ) )
  2028 		wp_send_json_error();
  2375 		wp_send_json_error();
  2029 
  2376 
  2030 	if ( ! $post_id = absint( $_REQUEST['post_id'] ) )
  2377 	if ( ! $post_id = absint( $_REQUEST['post_id'] ) )
  2037 
  2384 
  2038 	$attachments = $_REQUEST['attachments'];
  2385 	$attachments = $_REQUEST['attachments'];
  2039 
  2386 
  2040 	if ( ! current_user_can( 'edit_post', $post_id ) )
  2387 	if ( ! current_user_can( 'edit_post', $post_id ) )
  2041 		wp_send_json_error();
  2388 		wp_send_json_error();
  2042 
       
  2043 	$post = get_post( $post_id, ARRAY_A );
       
  2044 
  2389 
  2045 	foreach ( $attachments as $attachment_id => $menu_order ) {
  2390 	foreach ( $attachments as $attachment_id => $menu_order ) {
  2046 		if ( ! current_user_can( 'edit_post', $attachment_id ) )
  2391 		if ( ! current_user_can( 'edit_post', $attachment_id ) )
  2047 			continue;
  2392 			continue;
  2048 		if ( ! $attachment = get_post( $attachment_id ) )
  2393 		if ( ! $attachment = get_post( $attachment_id ) )
  2055 
  2400 
  2056 	wp_send_json_success();
  2401 	wp_send_json_success();
  2057 }
  2402 }
  2058 
  2403 
  2059 /**
  2404 /**
       
  2405  * Ajax handler for sending an attachment to the editor.
       
  2406  *
  2060  * Generates the HTML to send an attachment to the editor.
  2407  * Generates the HTML to send an attachment to the editor.
  2061  * Backwards compatible with the media_send_to_editor filter and the chain
  2408  * Backwards compatible with the media_send_to_editor filter
  2062  * of filters that follow.
  2409  * and the chain of filters that follow.
  2063  *
  2410  *
  2064  * @since 3.5.0
  2411  * @since 3.5.0
  2065  */
  2412  */
  2066 function wp_ajax_send_attachment_to_editor() {
  2413 function wp_ajax_send_attachment_to_editor() {
  2067 	check_ajax_referer( 'media-send-to-editor', 'nonce' );
  2414 	check_ajax_referer( 'media-send-to-editor', 'nonce' );
  2082 			wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) );
  2429 			wp_update_post( array( 'ID' => $id, 'post_parent' => $insert_into_post_id ) );
  2083 		}
  2430 		}
  2084 	}
  2431 	}
  2085 
  2432 
  2086 	$rel = $url = '';
  2433 	$rel = $url = '';
  2087 	$html = $title = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';
  2434 	$html = isset( $attachment['post_title'] ) ? $attachment['post_title'] : '';
  2088 	if ( ! empty( $attachment['url'] ) ) {
  2435 	if ( ! empty( $attachment['url'] ) ) {
  2089 		$url = $attachment['url'];
  2436 		$url = $attachment['url'];
  2090 		if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url )
  2437 		if ( strpos( $url, 'attachment_id') || get_attachment_link( $id ) == $url )
  2091 			$rel = ' rel="attachment wp-att-' . $id . '"';
  2438 			$rel = ' rel="attachment wp-att-' . $id . '"';
  2092 		$html = '<a href="' . esc_url( $url ) . '"' . $rel . '>' . $html . '</a>';
  2439 		$html = '<a href="' . esc_url( $url ) . '"' . $rel . '>' . $html . '</a>';
  2096 
  2443 
  2097 	if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) {
  2444 	if ( 'image' === substr( $post->post_mime_type, 0, 5 ) ) {
  2098 		$align = isset( $attachment['align'] ) ? $attachment['align'] : 'none';
  2445 		$align = isset( $attachment['align'] ) ? $attachment['align'] : 'none';
  2099 		$size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
  2446 		$size = isset( $attachment['image-size'] ) ? $attachment['image-size'] : 'medium';
  2100 		$alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';
  2447 		$alt = isset( $attachment['image_alt'] ) ? $attachment['image_alt'] : '';
       
  2448 
       
  2449 		// No whitespace-only captions.
  2101 		$caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : '';
  2450 		$caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : '';
       
  2451 		if ( '' === trim( $caption ) ) {
       
  2452 			$caption = '';
       
  2453 		}
       
  2454 
  2102 		$title = ''; // We no longer insert title tags into <img> tags, as they are redundant.
  2455 		$title = ''; // We no longer insert title tags into <img> tags, as they are redundant.
  2103 		$html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt );
  2456 		$html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt );
  2104 	} elseif ( 'video' === substr( $post->post_mime_type, 0, 5 ) || 'audio' === substr( $post->post_mime_type, 0, 5 )  ) {
  2457 	} elseif ( wp_attachment_is( 'video', $post ) || wp_attachment_is( 'audio', $post )  ) {
  2105 		$html = stripslashes_deep( $_POST['html'] );
  2458 		$html = stripslashes_deep( $_POST['html'] );
  2106 	}
  2459 	}
  2107 
  2460 
  2108 	/** This filter is documented in wp-admin/includes/media.php */
  2461 	/** This filter is documented in wp-admin/includes/media.php */
  2109 	$html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );
  2462 	$html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );
  2110 
  2463 
  2111 	wp_send_json_success( $html );
  2464 	wp_send_json_success( $html );
  2112 }
  2465 }
  2113 
  2466 
  2114 /**
  2467 /**
       
  2468  * Ajax handler for sending a link to the editor.
       
  2469  *
  2115  * Generates the HTML to send a non-image embed link to the editor.
  2470  * Generates the HTML to send a non-image embed link to the editor.
  2116  *
  2471  *
  2117  * Backwards compatible with the following filters:
  2472  * Backwards compatible with the following filters:
  2118  * - file_send_to_editor_url
  2473  * - file_send_to_editor_url
  2119  * - audio_send_to_editor_url
  2474  * - audio_send_to_editor_url
  2120  * - video_send_to_editor_url
  2475  * - video_send_to_editor_url
  2121  *
  2476  *
  2122  * @since 3.5.0
  2477  * @since 3.5.0
  2123  */
  2478  */
  2124 function wp_ajax_send_link_to_editor() {
  2479 function wp_ajax_send_link_to_editor() {
       
  2480 	global $post, $wp_embed;
       
  2481 
  2125 	check_ajax_referer( 'media-send-to-editor', 'nonce' );
  2482 	check_ajax_referer( 'media-send-to-editor', 'nonce' );
  2126 
  2483 
  2127 	if ( ! $src = wp_unslash( $_POST['src'] ) )
  2484 	if ( ! $src = wp_unslash( $_POST['src'] ) )
  2128 		wp_send_json_error();
  2485 		wp_send_json_error();
  2129 
  2486 
  2131 		$src = 'http://' . $src;
  2488 		$src = 'http://' . $src;
  2132 
  2489 
  2133 	if ( ! $src = esc_url_raw( $src ) )
  2490 	if ( ! $src = esc_url_raw( $src ) )
  2134 		wp_send_json_error();
  2491 		wp_send_json_error();
  2135 
  2492 
  2136 	if ( ! $title = trim( wp_unslash( $_POST['title'] ) ) )
  2493 	if ( ! $link_text = trim( wp_unslash( $_POST['link_text'] ) ) )
  2137 		$title = wp_basename( $src );
  2494 		$link_text = wp_basename( $src );
  2138 
  2495 
  2139 	$html = '';
  2496 	$post = get_post( isset( $_POST['post_id'] ) ? $_POST['post_id'] : 0 );
  2140 	if ( $title )
  2497 
  2141 		$html = '<a href="' . esc_url( $src ) . '">' . $title . '</a>';
  2498 	// Ping WordPress for an embed.
       
  2499 	$check_embed = $wp_embed->run_shortcode( '[embed]'. $src .'[/embed]' );
       
  2500 
       
  2501 	// Fallback that WordPress creates when no oEmbed was found.
       
  2502 	$fallback = $wp_embed->maybe_make_link( $src );
       
  2503 
       
  2504 	if ( $check_embed !== $fallback ) {
       
  2505 		// TinyMCE view for [embed] will parse this
       
  2506 		$html = '[embed]' . $src . '[/embed]';
       
  2507 	} elseif ( $link_text ) {
       
  2508 		$html = '<a href="' . esc_url( $src ) . '">' . $link_text . '</a>';
       
  2509 	} else {
       
  2510 		$html = '';
       
  2511 	}
  2142 
  2512 
  2143 	// Figure out what filter to run:
  2513 	// Figure out what filter to run:
  2144 	$type = 'file';
  2514 	$type = 'file';
  2145 	if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) )
  2515 	if ( ( $ext = preg_replace( '/^.+?\.([^.]+)$/', '$1', $src ) ) && ( $ext_type = wp_ext2type( $ext ) )
  2146 		&& ( 'audio' == $ext_type || 'video' == $ext_type ) )
  2516 		&& ( 'audio' == $ext_type || 'video' == $ext_type ) )
  2147 			$type = $ext_type;
  2517 			$type = $ext_type;
  2148 
  2518 
  2149 	/** This filter is documented in wp-admin/includes/media.php */
  2519 	/** This filter is documented in wp-admin/includes/media.php */
  2150 	$html = apply_filters( $type . '_send_to_editor_url', $html, $src, $title );
  2520 	$html = apply_filters( $type . '_send_to_editor_url', $html, $src, $link_text );
  2151 
  2521 
  2152 	wp_send_json_success( $html );
  2522 	wp_send_json_success( $html );
  2153 }
  2523 }
  2154 
  2524 
  2155 /**
  2525 /**
  2156  * Heartbeat API (experimental)
  2526  * Ajax handler for the Heartbeat API.
  2157  *
  2527  *
  2158  * Runs when the user is logged in.
  2528  * Runs when the user is logged in.
       
  2529  *
       
  2530  * @since 3.6.0
  2159  */
  2531  */
  2160 function wp_ajax_heartbeat() {
  2532 function wp_ajax_heartbeat() {
  2161 	if ( empty( $_POST['_nonce'] ) )
  2533 	if ( empty( $_POST['_nonce'] ) )
  2162 		wp_send_json_error();
  2534 		wp_send_json_error();
  2163 
  2535 
  2167 		// User is logged in but nonces have expired.
  2539 		// User is logged in but nonces have expired.
  2168 		$response['nonces_expired'] = true;
  2540 		$response['nonces_expired'] = true;
  2169 		wp_send_json($response);
  2541 		wp_send_json($response);
  2170 	}
  2542 	}
  2171 
  2543 
  2172 	// screen_id is the same as $current_screen->id and the JS global 'pagenow'
  2544 	// screen_id is the same as $current_screen->id and the JS global 'pagenow'.
  2173 	if ( ! empty($_POST['screen_id']) )
  2545 	if ( ! empty($_POST['screen_id']) )
  2174 		$screen_id = sanitize_key($_POST['screen_id']);
  2546 		$screen_id = sanitize_key($_POST['screen_id']);
  2175 	else
  2547 	else
  2176 		$screen_id = 'front';
  2548 		$screen_id = 'front';
  2177 
  2549 
  2178 	if ( ! empty($_POST['data']) ) {
  2550 	if ( ! empty($_POST['data']) ) {
  2179 		$data = (array) $_POST['data'];
  2551 		$data = wp_unslash( (array) $_POST['data'] );
  2180 
  2552 
  2181 		/**
  2553 		/**
  2182 		 * Filter the Heartbeat response received.
  2554 		 * Filter the Heartbeat response received.
  2183 		 *
  2555 		 *
  2184 		 * @since 3.6.0
  2556 		 * @since 3.6.0
  2216 	$response['server_time'] = time();
  2588 	$response['server_time'] = time();
  2217 
  2589 
  2218 	wp_send_json($response);
  2590 	wp_send_json($response);
  2219 }
  2591 }
  2220 
  2592 
       
  2593 /**
       
  2594  * Ajax handler for getting revision diffs.
       
  2595  *
       
  2596  * @since 3.6.0
       
  2597  */
  2221 function wp_ajax_get_revision_diffs() {
  2598 function wp_ajax_get_revision_diffs() {
  2222 	require ABSPATH . 'wp-admin/includes/revision.php';
  2599 	require ABSPATH . 'wp-admin/includes/revision.php';
  2223 
  2600 
  2224 	if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) )
  2601 	if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) )
  2225 		wp_send_json_error();
  2602 		wp_send_json_error();
  2242 			'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ),
  2619 			'fields' => wp_get_revision_ui_diff( $post, $compare_from, $compare_to ),
  2243 		);
  2620 		);
  2244 	}
  2621 	}
  2245 	wp_send_json_success( $return );
  2622 	wp_send_json_success( $return );
  2246 }
  2623 }
       
  2624 
       
  2625 /**
       
  2626  * Ajax handler for auto-saving the selected color scheme for
       
  2627  * a user's own profile.
       
  2628  *
       
  2629  * @since 3.8.0
       
  2630  */
       
  2631 function wp_ajax_save_user_color_scheme() {
       
  2632 	global $_wp_admin_css_colors;
       
  2633 
       
  2634 	check_ajax_referer( 'save-color-scheme', 'nonce' );
       
  2635 
       
  2636 	$color_scheme = sanitize_key( $_POST['color_scheme'] );
       
  2637 
       
  2638 	if ( ! isset( $_wp_admin_css_colors[ $color_scheme ] ) ) {
       
  2639 		wp_send_json_error();
       
  2640 	}
       
  2641 
       
  2642 	$previous_color_scheme = get_user_meta( get_current_user_id(), 'admin_color', true );
       
  2643 	update_user_meta( get_current_user_id(), 'admin_color', $color_scheme );
       
  2644 
       
  2645 	wp_send_json_success( array(
       
  2646 		'previousScheme' => 'admin-color-' . $previous_color_scheme,
       
  2647 		'currentScheme'  => 'admin-color-' . $color_scheme
       
  2648 	) );
       
  2649 }
       
  2650 
       
  2651 /**
       
  2652  * Ajax handler for getting themes from themes_api().
       
  2653  *
       
  2654  * @since 3.9.0
       
  2655  */
       
  2656 function wp_ajax_query_themes() {
       
  2657 	global $themes_allowedtags, $theme_field_defaults;
       
  2658 
       
  2659 	if ( ! current_user_can( 'install_themes' ) ) {
       
  2660 		wp_send_json_error();
       
  2661 	}
       
  2662 
       
  2663 	$args = wp_parse_args( wp_unslash( $_REQUEST['request'] ), array(
       
  2664 		'per_page' => 20,
       
  2665 		'fields'   => $theme_field_defaults
       
  2666 	) );
       
  2667 
       
  2668 	$old_filter = isset( $args['browse'] ) ? $args['browse'] : 'search';
       
  2669 
       
  2670 	/** This filter is documented in wp-admin/includes/class-wp-theme-install-list-table.php */
       
  2671 	$args = apply_filters( 'install_themes_table_api_args_' . $old_filter, $args );
       
  2672 
       
  2673 	$api = themes_api( 'query_themes', $args );
       
  2674 
       
  2675 	if ( is_wp_error( $api ) ) {
       
  2676 		wp_send_json_error();
       
  2677 	}
       
  2678 
       
  2679 	$update_php = network_admin_url( 'update.php?action=install-theme' );
       
  2680 	foreach ( $api->themes as &$theme ) {
       
  2681 		$theme->install_url = add_query_arg( array(
       
  2682 			'theme'    => $theme->slug,
       
  2683 			'_wpnonce' => wp_create_nonce( 'install-theme_' . $theme->slug )
       
  2684 		), $update_php );
       
  2685 
       
  2686 		$theme->name        = wp_kses( $theme->name, $themes_allowedtags );
       
  2687 		$theme->author      = wp_kses( $theme->author, $themes_allowedtags );
       
  2688 		$theme->version     = wp_kses( $theme->version, $themes_allowedtags );
       
  2689 		$theme->description = wp_kses( $theme->description, $themes_allowedtags );
       
  2690 		$theme->num_ratings = sprintf( _n( '(based on %s rating)', '(based on %s ratings)', $theme->num_ratings ), number_format_i18n( $theme->num_ratings ) );
       
  2691 		$theme->preview_url = set_url_scheme( $theme->preview_url );
       
  2692 	}
       
  2693 
       
  2694 	wp_send_json_success( $api );
       
  2695 }
       
  2696 
       
  2697 /**
       
  2698  * Apply [embed] AJAX handlers to a string.
       
  2699  *
       
  2700  * @since 4.0.0
       
  2701  *
       
  2702  * @global WP_Post  $post     Global $post.
       
  2703  * @global WP_Embed $wp_embed Embed API instance.
       
  2704  */
       
  2705 function wp_ajax_parse_embed() {
       
  2706 	global $post, $wp_embed;
       
  2707 
       
  2708 	if ( ! $post = get_post( (int) $_POST['post_ID'] ) ) {
       
  2709 		wp_send_json_error();
       
  2710 	}
       
  2711 
       
  2712 	if ( empty( $_POST['shortcode'] ) || ! current_user_can( 'edit_post', $post->ID ) ) {
       
  2713 		wp_send_json_error();
       
  2714 	}
       
  2715 
       
  2716 	$shortcode = wp_unslash( $_POST['shortcode'] );
       
  2717 	$url = str_replace( '[embed]', '', str_replace( '[/embed]', '', $shortcode ) );
       
  2718 
       
  2719 	$parsed = false;
       
  2720 	setup_postdata( $post );
       
  2721 
       
  2722 	$wp_embed->return_false_on_fail = true;
       
  2723 
       
  2724 	if ( is_ssl() && preg_match( '%^\\[embed[^\\]]*\\]http://%i', $shortcode ) ) {
       
  2725 		// Admin is ssl and the user pasted non-ssl URL.
       
  2726 		// Check if the provider supports ssl embeds and use that for the preview.
       
  2727 		$ssl_shortcode = preg_replace( '%^(\\[embed[^\\]]*\\])http://%i', '$1https://', $shortcode );
       
  2728 		$parsed = $wp_embed->run_shortcode( $ssl_shortcode );
       
  2729 
       
  2730 		if ( ! $parsed ) {
       
  2731 			$no_ssl_support = true;
       
  2732 		}
       
  2733 	}
       
  2734 
       
  2735 	if ( ! $parsed ) {
       
  2736 		$parsed = $wp_embed->run_shortcode( $shortcode );
       
  2737 	}
       
  2738 
       
  2739 	if ( ! $parsed ) {
       
  2740 		wp_send_json_error( array(
       
  2741 			'type' => 'not-embeddable',
       
  2742 			'message' => sprintf( __( '%s failed to embed.' ), '<code>' . esc_html( $url ) . '</code>' ),
       
  2743 		) );
       
  2744 	}
       
  2745 
       
  2746 	if ( has_shortcode( $parsed, 'audio' ) || has_shortcode( $parsed, 'video' ) ) {
       
  2747 		$styles = '';
       
  2748 		$mce_styles = wpview_media_sandbox_styles();
       
  2749 		foreach ( $mce_styles as $style ) {
       
  2750 			$styles .= sprintf( '<link rel="stylesheet" href="%s"/>', $style );
       
  2751 		}
       
  2752 
       
  2753 		$html = do_shortcode( $parsed );
       
  2754 
       
  2755 		global $wp_scripts;
       
  2756 		if ( ! empty( $wp_scripts ) ) {
       
  2757 			$wp_scripts->done = array();
       
  2758 		}
       
  2759 		ob_start();
       
  2760 		wp_print_scripts( 'wp-mediaelement' );
       
  2761 		$scripts = ob_get_clean();
       
  2762 
       
  2763 		$parsed = $styles . $html . $scripts;
       
  2764 	}
       
  2765 
       
  2766 
       
  2767 	if ( ! empty( $no_ssl_support ) || ( is_ssl() && ( preg_match( '%<(iframe|script|embed) [^>]*src="http://%', $parsed ) ||
       
  2768 		preg_match( '%<link [^>]*href="http://%', $parsed ) ) ) ) {
       
  2769 		// Admin is ssl and the embed is not. Iframes, scripts, and other "active content" will be blocked.
       
  2770 		wp_send_json_error( array(
       
  2771 			'type' => 'not-ssl',
       
  2772 			'message' => __( 'This preview is unavailable in the editor.' ),
       
  2773 		) );
       
  2774 	}
       
  2775 
       
  2776 	wp_send_json_success( array(
       
  2777 		'body' => $parsed
       
  2778 	) );
       
  2779 }
       
  2780 
       
  2781 function wp_ajax_parse_media_shortcode() {
       
  2782 	global $post, $wp_scripts;
       
  2783 
       
  2784 	if ( empty( $_POST['shortcode'] ) ) {
       
  2785 		wp_send_json_error();
       
  2786 	}
       
  2787 
       
  2788 	$shortcode = wp_unslash( $_POST['shortcode'] );
       
  2789 
       
  2790 	if ( ! empty( $_POST['post_ID'] ) ) {
       
  2791 		$post = get_post( (int) $_POST['post_ID'] );
       
  2792 	}
       
  2793 
       
  2794 	// the embed shortcode requires a post
       
  2795 	if ( ! $post || ! current_user_can( 'edit_post', $post->ID ) ) {
       
  2796 		if ( 'embed' === $shortcode ) {
       
  2797 			wp_send_json_error();
       
  2798 		}
       
  2799 	} else {
       
  2800 		setup_postdata( $post );
       
  2801 	}
       
  2802 
       
  2803 	$parsed = do_shortcode( $shortcode  );
       
  2804 
       
  2805 	if ( empty( $parsed ) ) {
       
  2806 		wp_send_json_error( array(
       
  2807 			'type' => 'no-items',
       
  2808 			'message' => __( 'No items found.' ),
       
  2809 		) );
       
  2810 	}
       
  2811 
       
  2812 	$head = '';
       
  2813 	$styles = wpview_media_sandbox_styles();
       
  2814 
       
  2815 	foreach ( $styles as $style ) {
       
  2816 		$head .= '<link type="text/css" rel="stylesheet" href="' . $style . '">';
       
  2817 	}
       
  2818 
       
  2819 	if ( ! empty( $wp_scripts ) ) {
       
  2820 		$wp_scripts->done = array();
       
  2821 	}
       
  2822 
       
  2823 	ob_start();
       
  2824 
       
  2825 	echo $parsed;
       
  2826 
       
  2827 	if ( 'playlist' === $_REQUEST['type'] ) {
       
  2828 		wp_underscore_playlist_templates();
       
  2829 
       
  2830 		wp_print_scripts( 'wp-playlist' );
       
  2831 	} else {
       
  2832 		wp_print_scripts( array( 'froogaloop', 'wp-mediaelement' ) );
       
  2833 	}
       
  2834 
       
  2835 	wp_send_json_success( array(
       
  2836 		'head' => $head,
       
  2837 		'body' => ob_get_clean()
       
  2838 	) );
       
  2839 }
       
  2840 
       
  2841 /**
       
  2842  * AJAX handler for destroying multiple open sessions for a user.
       
  2843  *
       
  2844  * @since 4.1.0
       
  2845  */
       
  2846 function wp_ajax_destroy_sessions() {
       
  2847 
       
  2848 	$user = get_userdata( (int) $_POST['user_id'] );
       
  2849 	if ( $user ) {
       
  2850 		if ( ! current_user_can( 'edit_user', $user->ID ) ) {
       
  2851 			$user = false;
       
  2852 		} elseif ( ! wp_verify_nonce( $_POST['nonce'], 'update-user_' . $user->ID ) ) {
       
  2853 			$user = false;
       
  2854 		}
       
  2855 	}
       
  2856 
       
  2857 	if ( ! $user ) {
       
  2858 		wp_send_json_error( array(
       
  2859 			'message' => __( 'Could not log out user sessions. Please try again.' ),
       
  2860 		) );
       
  2861 	}
       
  2862 
       
  2863 	$sessions = WP_Session_Tokens::get_instance( $user->ID );
       
  2864 
       
  2865 	if ( $user->ID === get_current_user_id() ) {
       
  2866 		$sessions->destroy_others( wp_get_session_token() );
       
  2867 		$message = __( 'You are now logged out everywhere else.' );
       
  2868 	} else {
       
  2869 		$sessions->destroy_all();
       
  2870 		/* translators: 1: User's display name. */
       
  2871 		$message = sprintf( __( '%s has been logged out.' ), $user->display_name );
       
  2872 	}
       
  2873 
       
  2874 	wp_send_json_success( array( 'message' => $message ) );
       
  2875 }
       
  2876 
       
  2877 
       
  2878 /**
       
  2879  * AJAX handler for updating a plugin.
       
  2880  *
       
  2881  * @since 4.2.0
       
  2882  *
       
  2883  * @see Plugin_Upgrader
       
  2884  */
       
  2885 function wp_ajax_update_plugin() {
       
  2886 	$plugin = urldecode( $_POST['plugin'] );
       
  2887 
       
  2888 	$status = array(
       
  2889 		'update'     => 'plugin',
       
  2890 		'plugin'     => $plugin,
       
  2891 		'slug'       => sanitize_key( $_POST['slug'] ),
       
  2892 		'oldVersion' => '',
       
  2893 		'newVersion' => '',
       
  2894 	);
       
  2895 	$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
       
  2896 	if ( $plugin_data['Version'] ) {
       
  2897 		$status['oldVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
       
  2898 	}
       
  2899 
       
  2900 	if ( ! current_user_can( 'update_plugins' ) ) {
       
  2901 		$status['error'] = __( 'You do not have sufficient permissions to update plugins on this site.' );
       
  2902  		wp_send_json_error( $status );
       
  2903 	}
       
  2904 
       
  2905 	check_ajax_referer( 'updates' );
       
  2906 
       
  2907 	include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
       
  2908 
       
  2909 	$current = get_site_transient( 'update_plugins' );
       
  2910 	if ( empty( $current ) ) {
       
  2911 		wp_update_plugins();
       
  2912 	}
       
  2913 
       
  2914 	$upgrader = new Plugin_Upgrader( new Automatic_Upgrader_Skin() );
       
  2915 	$result = $upgrader->bulk_upgrade( array( $plugin ) );
       
  2916 
       
  2917 	if ( is_array( $result ) ) {
       
  2918 		$plugin_update_data = current( $result );
       
  2919 
       
  2920 		/*
       
  2921 		 * If the `update_plugins` site transient is empty (e.g. when you update
       
  2922 		 * two plugins in quick succession before the transient repopulates),
       
  2923 		 * this may be the return.
       
  2924 		 *
       
  2925 		 * Preferably something can be done to ensure `update_plugins` isn't empty.
       
  2926 		 * For now, surface some sort of error here.
       
  2927 		 */
       
  2928 		if ( $plugin_update_data === true ) {
       
  2929  			wp_send_json_error( $status );
       
  2930 		}
       
  2931 
       
  2932 		$plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
       
  2933 
       
  2934 		if ( $plugin_data['Version'] ) {
       
  2935 			$status['newVersion'] = sprintf( __( 'Version %s' ), $plugin_data['Version'] );
       
  2936 		}
       
  2937 
       
  2938 		wp_send_json_success( $status );
       
  2939 	} else if ( is_wp_error( $result ) ) {
       
  2940 		$status['error'] = $result->get_error_message();
       
  2941  		wp_send_json_error( $status );
       
  2942 	} else if ( is_bool( $result ) && ! $result ) {
       
  2943 		$status['errorCode'] = 'unable_to_connect_to_filesystem';
       
  2944 		$status['error'] = __( 'Unable to connect to the filesystem. Please confirm your credentials.' );
       
  2945 		wp_send_json_error( $status );
       
  2946 	}
       
  2947 }
       
  2948 
       
  2949 /**
       
  2950  * AJAX handler for saving a post from Press This.
       
  2951  *
       
  2952  * @since 4.2.0
       
  2953  */
       
  2954 function wp_ajax_press_this_save_post() {
       
  2955 	if ( empty( $GLOBALS['wp_press_this'] ) ) {
       
  2956 		include( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
       
  2957 	}
       
  2958 
       
  2959 	$GLOBALS['wp_press_this']->save_post();
       
  2960 }
       
  2961 
       
  2962 /**
       
  2963  * AJAX handler for creating new category from Press This.
       
  2964  *
       
  2965  * @since 4.2.0
       
  2966  */
       
  2967 function wp_ajax_press_this_add_category() {
       
  2968 	if ( empty( $GLOBALS['wp_press_this'] ) ) {
       
  2969 		include( ABSPATH . 'wp-admin/includes/class-wp-press-this.php' );
       
  2970 	}
       
  2971 
       
  2972 	$GLOBALS['wp_press_this']->add_category();
       
  2973 }