wp/wp-admin/includes/post.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
equal deleted inserted replaced
20:7b1b88e27a20 21:48c4eec2b7e6
    70 		} else {
    70 		} else {
    71 			$post_data['post_author'] = (int) $post_data['user_ID'];
    71 			$post_data['post_author'] = (int) $post_data['user_ID'];
    72 		}
    72 		}
    73 	}
    73 	}
    74 
    74 
    75 	if ( isset( $post_data['user_ID'] ) && ( $post_data['post_author'] != $post_data['user_ID'] )
    75 	if ( isset( $post_data['user_ID'] ) && ( $post_data['post_author'] !== $post_data['user_ID'] )
    76 		&& ! current_user_can( $ptype->cap->edit_others_posts ) ) {
    76 		&& ! current_user_can( $ptype->cap->edit_others_posts ) ) {
    77 
    77 
    78 		if ( $update ) {
    78 		if ( $update ) {
    79 			if ( 'page' === $post_data['post_type'] ) {
    79 			if ( 'page' === $post_data['post_type'] ) {
    80 				return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to edit pages as this user.' ) );
    80 				return new WP_Error( 'edit_others_pages', __( 'Sorry, you are not allowed to edit pages as this user.' ) );
   133 		$post_data['post_status'] = $previous_status ? $previous_status : 'pending';
   133 		$post_data['post_status'] = $previous_status ? $previous_status : 'pending';
   134 	}
   134 	}
   135 
   135 
   136 	$published_statuses = array( 'publish', 'future' );
   136 	$published_statuses = array( 'publish', 'future' );
   137 
   137 
   138 	// Posts 'submitted for approval' are submitted to $_POST the same as if they were being published.
   138 	/*
   139 	// Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
   139 	 * Posts 'submitted for approval' are submitted to $_POST the same as if they were being published.
       
   140 	 * Change status from 'publish' to 'pending' if user lacks permissions to publish or to resave published posts.
       
   141 	 */
   140 	if ( isset( $post_data['post_status'] )
   142 	if ( isset( $post_data['post_status'] )
   141 		&& ( in_array( $post_data['post_status'], $published_statuses, true )
   143 		&& ( in_array( $post_data['post_status'], $published_statuses, true )
   142 		&& ! current_user_can( $ptype->cap->publish_posts ) )
   144 		&& ! current_user_can( $ptype->cap->publish_posts ) )
   143 	) {
   145 	) {
   144 		if ( ! in_array( $previous_status, $published_statuses, true ) || ! current_user_can( 'edit_post', $post_id ) ) {
   146 		if ( ! in_array( $previous_status, $published_statuses, true ) || ! current_user_can( 'edit_post', $post_id ) ) {
   161 	if ( ! isset( $post_data['ping_status'] ) ) {
   163 	if ( ! isset( $post_data['ping_status'] ) ) {
   162 		$post_data['ping_status'] = 'closed';
   164 		$post_data['ping_status'] = 'closed';
   163 	}
   165 	}
   164 
   166 
   165 	foreach ( array( 'aa', 'mm', 'jj', 'hh', 'mn' ) as $timeunit ) {
   167 	foreach ( array( 'aa', 'mm', 'jj', 'hh', 'mn' ) as $timeunit ) {
   166 		if ( ! empty( $post_data[ 'hidden_' . $timeunit ] ) && $post_data[ 'hidden_' . $timeunit ] != $post_data[ $timeunit ] ) {
   168 		if ( ! empty( $post_data[ 'hidden_' . $timeunit ] ) && $post_data[ 'hidden_' . $timeunit ] !== $post_data[ $timeunit ] ) {
   167 			$post_data['edit_date'] = '1';
   169 			$post_data['edit_date'] = '1';
   168 			break;
   170 			break;
   169 		}
   171 		}
   170 	}
   172 	}
   171 
   173 
   189 		$valid_date = wp_checkdate( $mm, $jj, $aa, $post_data['post_date'] );
   191 		$valid_date = wp_checkdate( $mm, $jj, $aa, $post_data['post_date'] );
   190 		if ( ! $valid_date ) {
   192 		if ( ! $valid_date ) {
   191 			return new WP_Error( 'invalid_date', __( 'Invalid date.' ) );
   193 			return new WP_Error( 'invalid_date', __( 'Invalid date.' ) );
   192 		}
   194 		}
   193 
   195 
   194 		$post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
   196 		/*
       
   197 		 * Only assign a post date if the user has explicitly set a new value.
       
   198 		 * See #59125 and #19907.
       
   199 		 */
       
   200 		$previous_date = $post_id ? get_post_field( 'post_date', $post_id ) : false;
       
   201 		if ( $previous_date && $previous_date !== $post_data['post_date'] ) {
       
   202 			$post_data['edit_date']     = true;
       
   203 			$post_data['post_date_gmt'] = get_gmt_from_date( $post_data['post_date'] );
       
   204 		} else {
       
   205 			$post_data['edit_date'] = false;
       
   206 			unset( $post_data['post_date'] );
       
   207 			unset( $post_data['post_date_gmt'] );
       
   208 		}
   195 	}
   209 	}
   196 
   210 
   197 	if ( isset( $post_data['post_category'] ) ) {
   211 	if ( isset( $post_data['post_category'] ) ) {
   198 		$category_object = get_taxonomy( 'category' );
   212 		$category_object = get_taxonomy( 'category' );
   199 		if ( ! current_user_can( $category_object->cap->assign_terms ) ) {
   213 		if ( ! current_user_can( $category_object->cap->assign_terms ) ) {
   250 	}
   264 	}
   251 
   265 
   252 	// Clear out any data in internal vars.
   266 	// Clear out any data in internal vars.
   253 	unset( $post_data['filter'] );
   267 	unset( $post_data['filter'] );
   254 
   268 
   255 	$post_ID = (int) $post_data['post_ID'];
   269 	$post_id = (int) $post_data['post_ID'];
   256 	$post    = get_post( $post_ID );
   270 	$post    = get_post( $post_id );
   257 
   271 
   258 	$post_data['post_type']      = $post->post_type;
   272 	$post_data['post_type']      = $post->post_type;
   259 	$post_data['post_mime_type'] = $post->post_mime_type;
   273 	$post_data['post_mime_type'] = $post->post_mime_type;
   260 
   274 
   261 	if ( ! empty( $post_data['post_status'] ) ) {
   275 	if ( ! empty( $post_data['post_status'] ) ) {
   265 			unset( $post_data['post_status'] );
   279 			unset( $post_data['post_status'] );
   266 		}
   280 		}
   267 	}
   281 	}
   268 
   282 
   269 	$ptype = get_post_type_object( $post_data['post_type'] );
   283 	$ptype = get_post_type_object( $post_data['post_type'] );
   270 	if ( ! current_user_can( 'edit_post', $post_ID ) ) {
   284 	if ( ! current_user_can( 'edit_post', $post_id ) ) {
   271 		if ( 'page' === $post_data['post_type'] ) {
   285 		if ( 'page' === $post_data['post_type'] ) {
   272 			wp_die( __( 'Sorry, you are not allowed to edit this page.' ) );
   286 			wp_die( __( 'Sorry, you are not allowed to edit this page.' ) );
   273 		} else {
   287 		} else {
   274 			wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
   288 			wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
   275 		}
   289 		}
   276 	}
   290 	}
   277 
   291 
   278 	if ( post_type_supports( $ptype->name, 'revisions' ) ) {
   292 	if ( post_type_supports( $ptype->name, 'revisions' ) ) {
   279 		$revisions = wp_get_post_revisions(
   293 		$revisions = wp_get_post_revisions(
   280 			$post_ID,
   294 			$post_id,
   281 			array(
   295 			array(
   282 				'order'          => 'ASC',
   296 				'order'          => 'ASC',
   283 				'posts_per_page' => 1,
   297 				'posts_per_page' => 1,
   284 			)
   298 			)
   285 		);
   299 		);
   286 		$revision  = current( $revisions );
   300 		$revision  = current( $revisions );
   287 
   301 
   288 		// Check if the revisions have been upgraded.
   302 		// Check if the revisions have been upgraded.
   289 		if ( $revisions && _wp_get_post_revision_version( $revision ) < 1 ) {
   303 		if ( $revisions && _wp_get_post_revision_version( $revision ) < 1 ) {
   290 			_wp_upgrade_revisions_of_post( $post, wp_get_post_revisions( $post_ID ) );
   304 			_wp_upgrade_revisions_of_post( $post, wp_get_post_revisions( $post_id ) );
   291 		}
   305 		}
   292 	}
   306 	}
   293 
   307 
   294 	if ( isset( $post_data['visibility'] ) ) {
   308 	if ( isset( $post_data['visibility'] ) ) {
   295 		switch ( $post_data['visibility'] ) {
   309 		switch ( $post_data['visibility'] ) {
   313 	}
   327 	}
   314 	$translated = _wp_get_allowed_postdata( $post_data );
   328 	$translated = _wp_get_allowed_postdata( $post_data );
   315 
   329 
   316 	// Post formats.
   330 	// Post formats.
   317 	if ( isset( $post_data['post_format'] ) ) {
   331 	if ( isset( $post_data['post_format'] ) ) {
   318 		set_post_format( $post_ID, $post_data['post_format'] );
   332 		set_post_format( $post_id, $post_data['post_format'] );
   319 	}
   333 	}
   320 
   334 
   321 	$format_meta_urls = array( 'url', 'link_url', 'quote_source_url' );
   335 	$format_meta_urls = array( 'url', 'link_url', 'quote_source_url' );
   322 	foreach ( $format_meta_urls as $format_meta_url ) {
   336 	foreach ( $format_meta_urls as $format_meta_url ) {
   323 		$keyed = '_format_' . $format_meta_url;
   337 		$keyed = '_format_' . $format_meta_url;
   324 		if ( isset( $post_data[ $keyed ] ) ) {
   338 		if ( isset( $post_data[ $keyed ] ) ) {
   325 			update_post_meta( $post_ID, $keyed, wp_slash( esc_url_raw( wp_unslash( $post_data[ $keyed ] ) ) ) );
   339 			update_post_meta( $post_id, $keyed, wp_slash( sanitize_url( wp_unslash( $post_data[ $keyed ] ) ) ) );
   326 		}
   340 		}
   327 	}
   341 	}
   328 
   342 
   329 	$format_keys = array( 'quote', 'quote_source_name', 'image', 'gallery', 'audio_embed', 'video_embed' );
   343 	$format_keys = array( 'quote', 'quote_source_name', 'image', 'gallery', 'audio_embed', 'video_embed' );
   330 
   344 
   331 	foreach ( $format_keys as $key ) {
   345 	foreach ( $format_keys as $key ) {
   332 		$keyed = '_format_' . $key;
   346 		$keyed = '_format_' . $key;
   333 		if ( isset( $post_data[ $keyed ] ) ) {
   347 		if ( isset( $post_data[ $keyed ] ) ) {
   334 			if ( current_user_can( 'unfiltered_html' ) ) {
   348 			if ( current_user_can( 'unfiltered_html' ) ) {
   335 				update_post_meta( $post_ID, $keyed, $post_data[ $keyed ] );
   349 				update_post_meta( $post_id, $keyed, $post_data[ $keyed ] );
   336 			} else {
   350 			} else {
   337 				update_post_meta( $post_ID, $keyed, wp_filter_post_kses( $post_data[ $keyed ] ) );
   351 				update_post_meta( $post_id, $keyed, wp_filter_post_kses( $post_data[ $keyed ] ) );
   338 			}
   352 			}
   339 		}
   353 		}
   340 	}
   354 	}
   341 
   355 
   342 	if ( 'attachment' === $post_data['post_type'] && preg_match( '#^(audio|video)/#', $post_data['post_mime_type'] ) ) {
   356 	if ( 'attachment' === $post_data['post_type'] && preg_match( '#^(audio|video)/#', $post_data['post_mime_type'] ) ) {
   343 		$id3data = wp_get_attachment_metadata( $post_ID );
   357 		$id3data = wp_get_attachment_metadata( $post_id );
   344 		if ( ! is_array( $id3data ) ) {
   358 		if ( ! is_array( $id3data ) ) {
   345 			$id3data = array();
   359 			$id3data = array();
   346 		}
   360 		}
   347 
   361 
   348 		foreach ( wp_get_attachment_id3_keys( $post, 'edit' ) as $key => $label ) {
   362 		foreach ( wp_get_attachment_id3_keys( $post, 'edit' ) as $key => $label ) {
   349 			if ( isset( $post_data[ 'id3_' . $key ] ) ) {
   363 			if ( isset( $post_data[ 'id3_' . $key ] ) ) {
   350 				$id3data[ $key ] = sanitize_text_field( wp_unslash( $post_data[ 'id3_' . $key ] ) );
   364 				$id3data[ $key ] = sanitize_text_field( wp_unslash( $post_data[ 'id3_' . $key ] ) );
   351 			}
   365 			}
   352 		}
   366 		}
   353 		wp_update_attachment_metadata( $post_ID, $id3data );
   367 		wp_update_attachment_metadata( $post_id, $id3data );
   354 	}
   368 	}
   355 
   369 
   356 	// Meta stuff.
   370 	// Meta stuff.
   357 	if ( isset( $post_data['meta'] ) && $post_data['meta'] ) {
   371 	if ( isset( $post_data['meta'] ) && $post_data['meta'] ) {
   358 		foreach ( $post_data['meta'] as $key => $value ) {
   372 		foreach ( $post_data['meta'] as $key => $value ) {
   359 			$meta = get_post_meta_by_id( $key );
   373 			$meta = get_post_meta_by_id( $key );
   360 			if ( ! $meta ) {
   374 			if ( ! $meta ) {
   361 				continue;
   375 				continue;
   362 			}
   376 			}
   363 			if ( $meta->post_id != $post_ID ) {
   377 
       
   378 			if ( (int) $meta->post_id !== $post_id ) {
   364 				continue;
   379 				continue;
   365 			}
   380 			}
   366 			if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'edit_post_meta', $post_ID, $meta->meta_key ) ) {
   381 
       
   382 			if ( is_protected_meta( $meta->meta_key, 'post' )
       
   383 				|| ! current_user_can( 'edit_post_meta', $post_id, $meta->meta_key )
       
   384 			) {
   367 				continue;
   385 				continue;
   368 			}
   386 			}
   369 			if ( is_protected_meta( $value['key'], 'post' ) || ! current_user_can( 'edit_post_meta', $post_ID, $value['key'] ) ) {
   387 
       
   388 			if ( is_protected_meta( $value['key'], 'post' )
       
   389 				|| ! current_user_can( 'edit_post_meta', $post_id, $value['key'] )
       
   390 			) {
   370 				continue;
   391 				continue;
   371 			}
   392 			}
       
   393 
   372 			update_meta( $key, $value['key'], $value['value'] );
   394 			update_meta( $key, $value['key'], $value['value'] );
   373 		}
   395 		}
   374 	}
   396 	}
   375 
   397 
   376 	if ( isset( $post_data['deletemeta'] ) && $post_data['deletemeta'] ) {
   398 	if ( isset( $post_data['deletemeta'] ) && $post_data['deletemeta'] ) {
   377 		foreach ( $post_data['deletemeta'] as $key => $value ) {
   399 		foreach ( $post_data['deletemeta'] as $key => $value ) {
   378 			$meta = get_post_meta_by_id( $key );
   400 			$meta = get_post_meta_by_id( $key );
   379 			if ( ! $meta ) {
   401 			if ( ! $meta ) {
   380 				continue;
   402 				continue;
   381 			}
   403 			}
   382 			if ( $meta->post_id != $post_ID ) {
   404 
       
   405 			if ( (int) $meta->post_id !== $post_id ) {
   383 				continue;
   406 				continue;
   384 			}
   407 			}
   385 			if ( is_protected_meta( $meta->meta_key, 'post' ) || ! current_user_can( 'delete_post_meta', $post_ID, $meta->meta_key ) ) {
   408 
       
   409 			if ( is_protected_meta( $meta->meta_key, 'post' )
       
   410 				|| ! current_user_can( 'delete_post_meta', $post_id, $meta->meta_key )
       
   411 			) {
   386 				continue;
   412 				continue;
   387 			}
   413 			}
       
   414 
   388 			delete_meta( $key );
   415 			delete_meta( $key );
   389 		}
   416 		}
   390 	}
   417 	}
   391 
   418 
   392 	// Attachment stuff.
   419 	// Attachment stuff.
   393 	if ( 'attachment' === $post_data['post_type'] ) {
   420 	if ( 'attachment' === $post_data['post_type'] ) {
   394 		if ( isset( $post_data['_wp_attachment_image_alt'] ) ) {
   421 		if ( isset( $post_data['_wp_attachment_image_alt'] ) ) {
   395 			$image_alt = wp_unslash( $post_data['_wp_attachment_image_alt'] );
   422 			$image_alt = wp_unslash( $post_data['_wp_attachment_image_alt'] );
   396 
   423 
   397 			if ( get_post_meta( $post_ID, '_wp_attachment_image_alt', true ) !== $image_alt ) {
   424 			if ( get_post_meta( $post_id, '_wp_attachment_image_alt', true ) !== $image_alt ) {
   398 				$image_alt = wp_strip_all_tags( $image_alt, true );
   425 				$image_alt = wp_strip_all_tags( $image_alt, true );
   399 
   426 
   400 				// update_post_meta() expects slashed.
   427 				// update_post_meta() expects slashed.
   401 				update_post_meta( $post_ID, '_wp_attachment_image_alt', wp_slash( $image_alt ) );
   428 				update_post_meta( $post_id, '_wp_attachment_image_alt', wp_slash( $image_alt ) );
   402 			}
   429 			}
   403 		}
   430 		}
   404 
   431 
   405 		$attachment_data = isset( $post_data['attachments'][ $post_ID ] ) ? $post_data['attachments'][ $post_ID ] : array();
   432 		$attachment_data = isset( $post_data['attachments'][ $post_id ] ) ? $post_data['attachments'][ $post_id ] : array();
   406 
   433 
   407 		/** This filter is documented in wp-admin/includes/media.php */
   434 		/** This filter is documented in wp-admin/includes/media.php */
   408 		$translated = apply_filters( 'attachment_fields_to_save', $translated, $attachment_data );
   435 		$translated = apply_filters( 'attachment_fields_to_save', $translated, $attachment_data );
   409 	}
   436 	}
   410 
   437 
   417 				$translated['tax_input'][ $taxonomy ] = call_user_func_array( $tax_object->meta_box_sanitize_cb, array( $taxonomy, $terms ) );
   444 				$translated['tax_input'][ $taxonomy ] = call_user_func_array( $tax_object->meta_box_sanitize_cb, array( $taxonomy, $terms ) );
   418 			}
   445 			}
   419 		}
   446 		}
   420 	}
   447 	}
   421 
   448 
   422 	add_meta( $post_ID );
   449 	add_meta( $post_id );
   423 
   450 
   424 	update_post_meta( $post_ID, '_edit_last', get_current_user_id() );
   451 	update_post_meta( $post_id, '_edit_last', get_current_user_id() );
   425 
   452 
   426 	$success = wp_update_post( $translated );
   453 	$success = wp_update_post( $translated );
   427 
   454 
   428 	// If the save failed, see if we can sanity check the main fields and try again.
   455 	// If the save failed, see if we can confidence check the main fields and try again.
   429 	if ( ! $success && is_callable( array( $wpdb, 'strip_invalid_text_for_column' ) ) ) {
   456 	if ( ! $success && is_callable( array( $wpdb, 'strip_invalid_text_for_column' ) ) ) {
   430 		$fields = array( 'post_title', 'post_content', 'post_excerpt' );
   457 		$fields = array( 'post_title', 'post_content', 'post_excerpt' );
   431 
   458 
   432 		foreach ( $fields as $field ) {
   459 		foreach ( $fields as $field ) {
   433 			if ( isset( $translated[ $field ] ) ) {
   460 			if ( isset( $translated[ $field ] ) ) {
   437 
   464 
   438 		wp_update_post( $translated );
   465 		wp_update_post( $translated );
   439 	}
   466 	}
   440 
   467 
   441 	// Now that we have an ID we can fix any attachment anchor hrefs.
   468 	// Now that we have an ID we can fix any attachment anchor hrefs.
   442 	_fix_attachment_links( $post_ID );
   469 	_fix_attachment_links( $post_id );
   443 
   470 
   444 	wp_set_post_lock( $post_ID );
   471 	wp_set_post_lock( $post_id );
   445 
   472 
   446 	if ( current_user_can( $ptype->cap->edit_others_posts ) && current_user_can( $ptype->cap->publish_posts ) ) {
   473 	if ( current_user_can( $ptype->cap->edit_others_posts ) && current_user_can( $ptype->cap->publish_posts ) ) {
   447 		if ( ! empty( $post_data['sticky'] ) ) {
   474 		if ( ! empty( $post_data['sticky'] ) ) {
   448 			stick_post( $post_ID );
   475 			stick_post( $post_id );
   449 		} else {
   476 		} else {
   450 			unstick_post( $post_ID );
   477 			unstick_post( $post_id );
   451 		}
   478 		}
   452 	}
   479 	}
   453 
   480 
   454 	return $post_ID;
   481 	return $post_id;
   455 }
   482 }
   456 
   483 
   457 /**
   484 /**
   458  * Processes the post data for the bulk editing of posts.
   485  * Processes the post data for the bulk editing of posts.
   459  *
   486  *
   487 		} else {
   514 		} else {
   488 			wp_die( __( 'Sorry, you are not allowed to edit posts.' ) );
   515 			wp_die( __( 'Sorry, you are not allowed to edit posts.' ) );
   489 		}
   516 		}
   490 	}
   517 	}
   491 
   518 
   492 	if ( -1 == $post_data['_status'] ) {
   519 	if ( '-1' === $post_data['_status'] ) {
   493 		$post_data['post_status'] = null;
   520 		$post_data['post_status'] = null;
   494 		unset( $post_data['post_status'] );
   521 		unset( $post_data['post_status'] );
   495 	} else {
   522 	} else {
   496 		$post_data['post_status'] = $post_data['_status'];
   523 		$post_data['post_status'] = $post_data['_status'];
   497 	}
   524 	}
   503 		if ( 'inherit' === $post_data['post_status'] ) {
   530 		if ( 'inherit' === $post_data['post_status'] ) {
   504 			unset( $post_data['post_status'] );
   531 			unset( $post_data['post_status'] );
   505 		}
   532 		}
   506 	}
   533 	}
   507 
   534 
   508 	$post_IDs = array_map( 'intval', (array) $post_data['post'] );
   535 	$post_ids = array_map( 'intval', (array) $post_data['post'] );
   509 
   536 
   510 	$reset = array(
   537 	$reset = array(
   511 		'post_author',
   538 		'post_author',
   512 		'post_status',
   539 		'post_status',
   513 		'post_password',
   540 		'post_password',
   521 		'sticky',
   548 		'sticky',
   522 		'post_format',
   549 		'post_format',
   523 	);
   550 	);
   524 
   551 
   525 	foreach ( $reset as $field ) {
   552 	foreach ( $reset as $field ) {
   526 		if ( isset( $post_data[ $field ] ) && ( '' === $post_data[ $field ] || -1 == $post_data[ $field ] ) ) {
   553 		if ( isset( $post_data[ $field ] ) && ( '' === $post_data[ $field ] || '-1' === $post_data[ $field ] ) ) {
   527 			unset( $post_data[ $field ] );
   554 			unset( $post_data[ $field ] );
   528 		}
   555 		}
   529 	}
   556 	}
   530 
   557 
   531 	if ( isset( $post_data['post_category'] ) ) {
   558 	if ( isset( $post_data['post_category'] ) ) {
   540 	if ( isset( $post_data['tax_input'] ) ) {
   567 	if ( isset( $post_data['tax_input'] ) ) {
   541 		foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
   568 		foreach ( $post_data['tax_input'] as $tax_name => $terms ) {
   542 			if ( empty( $terms ) ) {
   569 			if ( empty( $terms ) ) {
   543 				continue;
   570 				continue;
   544 			}
   571 			}
       
   572 
   545 			if ( is_taxonomy_hierarchical( $tax_name ) ) {
   573 			if ( is_taxonomy_hierarchical( $tax_name ) ) {
   546 				$tax_input[ $tax_name ] = array_map( 'absint', $terms );
   574 				$tax_input[ $tax_name ] = array_map( 'absint', $terms );
   547 			} else {
   575 			} else {
   548 				$comma = _x( ',', 'tag delimiter' );
   576 				$comma = _x( ',', 'tag delimiter' );
   549 				if ( ',' !== $comma ) {
   577 				if ( ',' !== $comma ) {
   574 	$updated          = array();
   602 	$updated          = array();
   575 	$skipped          = array();
   603 	$skipped          = array();
   576 	$locked           = array();
   604 	$locked           = array();
   577 	$shared_post_data = $post_data;
   605 	$shared_post_data = $post_data;
   578 
   606 
   579 	foreach ( $post_IDs as $post_ID ) {
   607 	foreach ( $post_ids as $post_id ) {
   580 		// Start with fresh post data with each iteration.
   608 		// Start with fresh post data with each iteration.
   581 		$post_data = $shared_post_data;
   609 		$post_data = $shared_post_data;
   582 
   610 
   583 		$post_type_object = get_post_type_object( get_post_type( $post_ID ) );
   611 		$post_type_object = get_post_type_object( get_post_type( $post_id ) );
   584 
   612 
   585 		if ( ! isset( $post_type_object )
   613 		if ( ! isset( $post_type_object )
   586 			|| ( isset( $children ) && in_array( $post_ID, $children, true ) )
   614 			|| ( isset( $children ) && in_array( $post_id, $children, true ) )
   587 			|| ! current_user_can( 'edit_post', $post_ID )
   615 			|| ! current_user_can( 'edit_post', $post_id )
   588 		) {
   616 		) {
   589 			$skipped[] = $post_ID;
   617 			$skipped[] = $post_id;
   590 			continue;
   618 			continue;
   591 		}
   619 		}
   592 
   620 
   593 		if ( wp_check_post_lock( $post_ID ) ) {
   621 		if ( wp_check_post_lock( $post_id ) ) {
   594 			$locked[] = $post_ID;
   622 			$locked[] = $post_id;
   595 			continue;
   623 			continue;
   596 		}
   624 		}
   597 
   625 
   598 		$post      = get_post( $post_ID );
   626 		$post      = get_post( $post_id );
   599 		$tax_names = get_object_taxonomies( $post );
   627 		$tax_names = get_object_taxonomies( $post );
       
   628 
   600 		foreach ( $tax_names as $tax_name ) {
   629 		foreach ( $tax_names as $tax_name ) {
   601 			$taxonomy_obj = get_taxonomy( $tax_name );
   630 			$taxonomy_obj = get_taxonomy( $tax_name );
       
   631 
       
   632 			if ( ! $taxonomy_obj->show_in_quick_edit ) {
       
   633 				continue;
       
   634 			}
       
   635 
   602 			if ( isset( $tax_input[ $tax_name ] ) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
   636 			if ( isset( $tax_input[ $tax_name ] ) && current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
   603 				$new_terms = $tax_input[ $tax_name ];
   637 				$new_terms = $tax_input[ $tax_name ];
   604 			} else {
   638 			} else {
   605 				$new_terms = array();
   639 				$new_terms = array();
   606 			}
   640 			}
   607 
   641 
   608 			if ( $taxonomy_obj->hierarchical ) {
   642 			if ( $taxonomy_obj->hierarchical ) {
   609 				$current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array( 'fields' => 'ids' ) );
   643 				$current_terms = (array) wp_get_object_terms( $post_id, $tax_name, array( 'fields' => 'ids' ) );
   610 			} else {
   644 			} else {
   611 				$current_terms = (array) wp_get_object_terms( $post_ID, $tax_name, array( 'fields' => 'names' ) );
   645 				$current_terms = (array) wp_get_object_terms( $post_id, $tax_name, array( 'fields' => 'names' ) );
   612 			}
   646 			}
   613 
   647 
   614 			$post_data['tax_input'][ $tax_name ] = array_merge( $current_terms, $new_terms );
   648 			$post_data['tax_input'][ $tax_name ] = array_merge( $current_terms, $new_terms );
   615 		}
   649 		}
   616 
   650 
   617 		if ( isset( $new_cats ) && in_array( 'category', $tax_names, true ) ) {
   651 		if ( isset( $new_cats ) && in_array( 'category', $tax_names, true ) ) {
   618 			$cats                       = (array) wp_get_post_categories( $post_ID );
   652 			$cats = (array) wp_get_post_categories( $post_id );
   619 			$post_data['post_category'] = array_unique( array_merge( $cats, $new_cats ) );
   653 
       
   654 			if (
       
   655 				isset( $post_data['indeterminate_post_category'] )
       
   656 				&& is_array( $post_data['indeterminate_post_category'] )
       
   657 			) {
       
   658 				$indeterminate_post_category = $post_data['indeterminate_post_category'];
       
   659 			} else {
       
   660 				$indeterminate_post_category = array();
       
   661 			}
       
   662 
       
   663 			$indeterminate_cats         = array_intersect( $cats, $indeterminate_post_category );
       
   664 			$determinate_cats           = array_diff( $new_cats, $indeterminate_post_category );
       
   665 			$post_data['post_category'] = array_unique( array_merge( $indeterminate_cats, $determinate_cats ) );
       
   666 
   620 			unset( $post_data['tax_input']['category'] );
   667 			unset( $post_data['tax_input']['category'] );
   621 		}
   668 		}
   622 
   669 
   623 		$post_data['post_ID']        = $post_ID;
   670 		$post_data['post_ID']        = $post_id;
   624 		$post_data['post_type']      = $post->post_type;
   671 		$post_data['post_type']      = $post->post_type;
   625 		$post_data['post_mime_type'] = $post->post_mime_type;
   672 		$post_data['post_mime_type'] = $post->post_mime_type;
   626 
   673 
   627 		foreach ( array( 'comment_status', 'ping_status', 'post_author' ) as $field ) {
   674 		foreach ( array( 'comment_status', 'ping_status', 'post_author' ) as $field ) {
   628 			if ( ! isset( $post_data[ $field ] ) ) {
   675 			if ( ! isset( $post_data[ $field ] ) ) {
   630 			}
   677 			}
   631 		}
   678 		}
   632 
   679 
   633 		$post_data = _wp_translate_postdata( true, $post_data );
   680 		$post_data = _wp_translate_postdata( true, $post_data );
   634 		if ( is_wp_error( $post_data ) ) {
   681 		if ( is_wp_error( $post_data ) ) {
   635 			$skipped[] = $post_ID;
   682 			$skipped[] = $post_id;
   636 			continue;
   683 			continue;
   637 		}
   684 		}
   638 		$post_data = _wp_get_allowed_postdata( $post_data );
   685 		$post_data = _wp_get_allowed_postdata( $post_data );
   639 
   686 
   640 		if ( isset( $shared_post_data['post_format'] ) ) {
   687 		if ( isset( $shared_post_data['post_format'] ) ) {
   641 			set_post_format( $post_ID, $shared_post_data['post_format'] );
   688 			set_post_format( $post_id, $shared_post_data['post_format'] );
   642 		}
   689 		}
   643 
   690 
   644 		// Prevent wp_insert_post() from overwriting post format with the old data.
   691 		// Prevent wp_insert_post() from overwriting post format with the old data.
   645 		unset( $post_data['tax_input']['post_format'] );
   692 		unset( $post_data['tax_input']['post_format'] );
       
   693 
       
   694 		// Reset post date of scheduled post to be published.
       
   695 		if (
       
   696 			in_array( $post->post_status, array( 'future', 'draft' ), true ) &&
       
   697 			'publish' === $post_data['post_status']
       
   698 		) {
       
   699 			$post_data['post_date']     = current_time( 'mysql' );
       
   700 			$post_data['post_date_gmt'] = '';
       
   701 		}
   646 
   702 
   647 		$post_id = wp_update_post( $post_data );
   703 		$post_id = wp_update_post( $post_data );
   648 		update_post_meta( $post_id, '_edit_last', get_current_user_id() );
   704 		update_post_meta( $post_id, '_edit_last', get_current_user_id() );
   649 		$updated[] = $post_id;
   705 		$updated[] = $post_id;
   650 
   706 
   651 		if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) {
   707 		if ( isset( $post_data['sticky'] ) && current_user_can( $ptype->cap->edit_others_posts ) ) {
   652 			if ( 'sticky' === $post_data['sticky'] ) {
   708 			if ( 'sticky' === $post_data['sticky'] ) {
   653 				stick_post( $post_ID );
   709 				stick_post( $post_id );
   654 			} else {
   710 			} else {
   655 				unstick_post( $post_ID );
   711 				unstick_post( $post_id );
   656 			}
   712 			}
   657 		}
   713 		}
   658 	}
   714 	}
       
   715 
       
   716 	/**
       
   717 	 * Fires after processing the post data for bulk edit.
       
   718 	 *
       
   719 	 * @since 6.3.0
       
   720 	 *
       
   721 	 * @param int[] $updated          An array of updated post IDs.
       
   722 	 * @param array $shared_post_data Associative array containing the post data.
       
   723 	 */
       
   724 	do_action( 'bulk_edit_posts', $updated, $shared_post_data );
   659 
   725 
   660 	return array(
   726 	return array(
   661 		'updated' => $updated,
   727 		'updated' => $updated,
   662 		'skipped' => $skipped,
   728 		'skipped' => $skipped,
   663 		'locked'  => $locked,
   729 		'locked'  => $locked,
   708 		// Schedule auto-draft cleanup.
   774 		// Schedule auto-draft cleanup.
   709 		if ( ! wp_next_scheduled( 'wp_scheduled_auto_draft_delete' ) ) {
   775 		if ( ! wp_next_scheduled( 'wp_scheduled_auto_draft_delete' ) ) {
   710 			wp_schedule_event( time(), 'daily', 'wp_scheduled_auto_draft_delete' );
   776 			wp_schedule_event( time(), 'daily', 'wp_scheduled_auto_draft_delete' );
   711 		}
   777 		}
   712 	} else {
   778 	} else {
   713 		$post                 = new stdClass;
   779 		$post                 = new stdClass();
   714 		$post->ID             = 0;
   780 		$post->ID             = 0;
   715 		$post->post_author    = '';
   781 		$post->post_author    = '';
   716 		$post->post_date      = '';
   782 		$post->post_date      = '';
   717 		$post->post_date_gmt  = '';
   783 		$post->post_date_gmt  = '';
   718 		$post->post_password  = '';
   784 		$post->post_password  = '';
   879 		return $translated;
   945 		return $translated;
   880 	}
   946 	}
   881 	$translated = _wp_get_allowed_postdata( $translated );
   947 	$translated = _wp_get_allowed_postdata( $translated );
   882 
   948 
   883 	// Create the post.
   949 	// Create the post.
   884 	$post_ID = wp_insert_post( $translated );
   950 	$post_id = wp_insert_post( $translated );
   885 	if ( is_wp_error( $post_ID ) ) {
   951 	if ( is_wp_error( $post_id ) ) {
   886 		return $post_ID;
   952 		return $post_id;
   887 	}
   953 	}
   888 
   954 
   889 	if ( empty( $post_ID ) ) {
   955 	if ( empty( $post_id ) ) {
   890 		return 0;
   956 		return 0;
   891 	}
   957 	}
   892 
   958 
   893 	add_meta( $post_ID );
   959 	add_meta( $post_id );
   894 
   960 
   895 	add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID );
   961 	add_post_meta( $post_id, '_edit_last', $GLOBALS['current_user']->ID );
   896 
   962 
   897 	// Now that we have an ID we can fix any attachment anchor hrefs.
   963 	// Now that we have an ID we can fix any attachment anchor hrefs.
   898 	_fix_attachment_links( $post_ID );
   964 	_fix_attachment_links( $post_id );
   899 
   965 
   900 	wp_set_post_lock( $post_ID );
   966 	wp_set_post_lock( $post_id );
   901 
   967 
   902 	return $post_ID;
   968 	return $post_id;
   903 }
   969 }
   904 
   970 
   905 /**
   971 /**
   906  * Calls wp_write_post() and handles the errors.
   972  * Calls wp_write_post() and handles the errors.
   907  *
   973  *
   925 /**
   991 /**
   926  * Adds post meta data defined in the `$_POST` superglobal for a post with given ID.
   992  * Adds post meta data defined in the `$_POST` superglobal for a post with given ID.
   927  *
   993  *
   928  * @since 1.2.0
   994  * @since 1.2.0
   929  *
   995  *
   930  * @param int $post_ID
   996  * @param int $post_id
   931  * @return int|bool
   997  * @return int|bool
   932  */
   998  */
   933 function add_meta( $post_ID ) {
   999 function add_meta( $post_id ) {
   934 	$post_ID = (int) $post_ID;
  1000 	$post_id = (int) $post_id;
   935 
  1001 
   936 	$metakeyselect = isset( $_POST['metakeyselect'] ) ? wp_unslash( trim( $_POST['metakeyselect'] ) ) : '';
  1002 	$metakeyselect = isset( $_POST['metakeyselect'] ) ? wp_unslash( trim( $_POST['metakeyselect'] ) ) : '';
   937 	$metakeyinput  = isset( $_POST['metakeyinput'] ) ? wp_unslash( trim( $_POST['metakeyinput'] ) ) : '';
  1003 	$metakeyinput  = isset( $_POST['metakeyinput'] ) ? wp_unslash( trim( $_POST['metakeyinput'] ) ) : '';
   938 	$metavalue     = isset( $_POST['metavalue'] ) ? $_POST['metavalue'] : '';
  1004 	$metavalue     = isset( $_POST['metavalue'] ) ? $_POST['metavalue'] : '';
   939 	if ( is_string( $metavalue ) ) {
  1005 	if ( is_string( $metavalue ) ) {
   951 
  1017 
   952 		if ( $metakeyinput ) {
  1018 		if ( $metakeyinput ) {
   953 			$metakey = $metakeyinput; // Default.
  1019 			$metakey = $metakeyinput; // Default.
   954 		}
  1020 		}
   955 
  1021 
   956 		if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_ID, $metakey ) ) {
  1022 		if ( is_protected_meta( $metakey, 'post' ) || ! current_user_can( 'add_post_meta', $post_id, $metakey ) ) {
   957 			return false;
  1023 			return false;
   958 		}
  1024 		}
   959 
  1025 
   960 		$metakey = wp_slash( $metakey );
  1026 		$metakey = wp_slash( $metakey );
   961 
  1027 
   962 		return add_post_meta( $post_ID, $metakey, $metavalue );
  1028 		return add_post_meta( $post_id, $metakey, $metavalue );
   963 	}
  1029 	}
   964 
  1030 
   965 	return false;
  1031 	return false;
   966 }
  1032 }
   967 
  1033 
   988  */
  1054  */
   989 function get_meta_keys() {
  1055 function get_meta_keys() {
   990 	global $wpdb;
  1056 	global $wpdb;
   991 
  1057 
   992 	$keys = $wpdb->get_col(
  1058 	$keys = $wpdb->get_col(
   993 		"
  1059 		"SELECT meta_key
   994 			SELECT meta_key
  1060 		FROM $wpdb->postmeta
   995 			FROM $wpdb->postmeta
  1061 		GROUP BY meta_key
   996 			GROUP BY meta_key
  1062 		ORDER BY meta_key"
   997 			ORDER BY meta_key"
       
   998 	);
  1063 	);
   999 
  1064 
  1000 	return $keys;
  1065 	return $keys;
  1001 }
  1066 }
  1002 
  1067 
  1017  *
  1082  *
  1018  * @since 1.2.0
  1083  * @since 1.2.0
  1019  *
  1084  *
  1020  * @global wpdb $wpdb WordPress database abstraction object.
  1085  * @global wpdb $wpdb WordPress database abstraction object.
  1021  *
  1086  *
  1022  * @param int $postid A post ID.
  1087  * @param int $post_id A post ID.
  1023  * @return array[] {
  1088  * @return array[] {
  1024  *     Array of meta data arrays for the given post ID.
  1089  *     Array of meta data arrays for the given post ID.
  1025  *
  1090  *
  1026  *     @type array ...$0 {
  1091  *     @type array ...$0 {
  1027  *         Associative array of meta data.
  1092  *         Associative array of meta data.
  1031  *         @type string $meta_id    Meta ID as a numeric string.
  1096  *         @type string $meta_id    Meta ID as a numeric string.
  1032  *         @type string $post_id    Post ID as a numeric string.
  1097  *         @type string $post_id    Post ID as a numeric string.
  1033  *     }
  1098  *     }
  1034  * }
  1099  * }
  1035  */
  1100  */
  1036 function has_meta( $postid ) {
  1101 function has_meta( $post_id ) {
  1037 	global $wpdb;
  1102 	global $wpdb;
  1038 
  1103 
  1039 	return $wpdb->get_results(
  1104 	return $wpdb->get_results(
  1040 		$wpdb->prepare(
  1105 		$wpdb->prepare(
  1041 			"SELECT meta_key, meta_value, meta_id, post_id
  1106 			"SELECT meta_key, meta_value, meta_id, post_id
  1042 			FROM $wpdb->postmeta WHERE post_id = %d
  1107 			FROM $wpdb->postmeta WHERE post_id = %d
  1043 			ORDER BY meta_key,meta_id",
  1108 			ORDER BY meta_key,meta_id",
  1044 			$postid
  1109 			$post_id
  1045 		),
  1110 		),
  1046 		ARRAY_A
  1111 		ARRAY_A
  1047 	);
  1112 	);
  1048 }
  1113 }
  1049 
  1114 
  1072  * Replaces hrefs of attachment anchors with up-to-date permalinks.
  1137  * Replaces hrefs of attachment anchors with up-to-date permalinks.
  1073  *
  1138  *
  1074  * @since 2.3.0
  1139  * @since 2.3.0
  1075  * @access private
  1140  * @access private
  1076  *
  1141  *
  1077  * @param int|object $post Post ID or post object.
  1142  * @param int|WP_Post $post Post ID or post object.
  1078  * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success.
  1143  * @return void|int|WP_Error Void if nothing fixed. 0 or WP_Error on update failure. The post ID on update success.
  1079  */
  1144  */
  1080 function _fix_attachment_links( $post ) {
  1145 function _fix_attachment_links( $post ) {
  1081 	$post    = get_post( $post, ARRAY_A );
  1146 	$post    = get_post( $post, ARRAY_A );
  1082 	$content = $post['post_content'];
  1147 	$content = $post['post_content'];
  1104 
  1169 
  1105 		$quote  = $url_match[1]; // The quote (single or double).
  1170 		$quote  = $url_match[1]; // The quote (single or double).
  1106 		$url_id = (int) $url_match[2];
  1171 		$url_id = (int) $url_match[2];
  1107 		$rel_id = (int) $rel_match[1];
  1172 		$rel_id = (int) $rel_match[1];
  1108 
  1173 
  1109 		if ( ! $url_id || ! $rel_id || $url_id != $rel_id || strpos( $url_match[0], $site_url ) === false ) {
  1174 		if ( ! $url_id || ! $rel_id || $url_id != $rel_id || ! str_contains( $url_match[0], $site_url ) ) {
  1110 			continue;
  1175 			continue;
  1111 		}
  1176 		}
  1112 
  1177 
  1113 		$link    = $link_matches[0][ $key ];
  1178 		$link    = $link_matches[0][ $key ];
  1114 		$replace = str_replace( $url_match[0], 'href=' . $quote . get_attachment_link( $url_id ) . $quote, $link );
  1179 		$replace = str_replace( $url_match[0], 'href=' . $quote . get_attachment_link( $url_id ) . $quote, $link );
  1132  *
  1197  *
  1133  * @param string $type The post_type you want the statuses for. Default 'post'.
  1198  * @param string $type The post_type you want the statuses for. Default 'post'.
  1134  * @return string[] An array of all the statuses for the supplied post type.
  1199  * @return string[] An array of all the statuses for the supplied post type.
  1135  */
  1200  */
  1136 function get_available_post_statuses( $type = 'post' ) {
  1201 function get_available_post_statuses( $type = 'post' ) {
  1137 	$stati = wp_count_posts( $type );
  1202 	$statuses = wp_count_posts( $type );
  1138 
  1203 
  1139 	return array_keys( get_object_vars( $stati ) );
  1204 	return array_keys( get_object_vars( $statuses ) );
  1140 }
  1205 }
  1141 
  1206 
  1142 /**
  1207 /**
  1143  * Runs the query to fetch the posts for listing on the edit posts page.
  1208  * Runs the query to fetch the posts for listing on the edit posts page.
  1144  *
  1209  *
  1150  */
  1215  */
  1151 function wp_edit_posts_query( $q = false ) {
  1216 function wp_edit_posts_query( $q = false ) {
  1152 	if ( false === $q ) {
  1217 	if ( false === $q ) {
  1153 		$q = $_GET;
  1218 		$q = $_GET;
  1154 	}
  1219 	}
  1155 	$q['m']     = isset( $q['m'] ) ? (int) $q['m'] : 0;
  1220 
  1156 	$q['cat']   = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
  1221 	$q['m']   = isset( $q['m'] ) ? (int) $q['m'] : 0;
  1157 	$post_stati = get_post_stati();
  1222 	$q['cat'] = isset( $q['cat'] ) ? (int) $q['cat'] : 0;
       
  1223 
       
  1224 	$post_statuses = get_post_stati();
  1158 
  1225 
  1159 	if ( isset( $q['post_type'] ) && in_array( $q['post_type'], get_post_types(), true ) ) {
  1226 	if ( isset( $q['post_type'] ) && in_array( $q['post_type'], get_post_types(), true ) ) {
  1160 		$post_type = $q['post_type'];
  1227 		$post_type = $q['post_type'];
  1161 	} else {
  1228 	} else {
  1162 		$post_type = 'post';
  1229 		$post_type = 'post';
  1164 
  1231 
  1165 	$avail_post_stati = get_available_post_statuses( $post_type );
  1232 	$avail_post_stati = get_available_post_statuses( $post_type );
  1166 	$post_status      = '';
  1233 	$post_status      = '';
  1167 	$perm             = '';
  1234 	$perm             = '';
  1168 
  1235 
  1169 	if ( isset( $q['post_status'] ) && in_array( $q['post_status'], $post_stati, true ) ) {
  1236 	if ( isset( $q['post_status'] ) && in_array( $q['post_status'], $post_statuses, true ) ) {
  1170 		$post_status = $q['post_status'];
  1237 		$post_status = $q['post_status'];
  1171 		$perm        = 'readable';
  1238 		$perm        = 'readable';
  1172 	}
  1239 	}
  1173 
  1240 
  1174 	$orderby = '';
  1241 	$orderby = '';
  1300 		$q['author'] = get_current_user_id();
  1367 		$q['author'] = get_current_user_id();
  1301 	}
  1368 	}
  1302 
  1369 
  1303 	// Filter query clauses to include filenames.
  1370 	// Filter query clauses to include filenames.
  1304 	if ( isset( $q['s'] ) ) {
  1371 	if ( isset( $q['s'] ) ) {
  1305 		add_filter( 'posts_clauses', '_filter_query_attachment_filenames' );
  1372 		add_filter( 'wp_allow_query_attachment_by_filename', '__return_true' );
  1306 	}
  1373 	}
  1307 
  1374 
  1308 	return $q;
  1375 	return $q;
  1309 }
  1376 }
  1310 
  1377 
  1335  * @param string $box_id    Meta box ID (used in the 'id' attribute for the meta box).
  1402  * @param string $box_id    Meta box ID (used in the 'id' attribute for the meta box).
  1336  * @param string $screen_id The screen on which the meta box is shown.
  1403  * @param string $screen_id The screen on which the meta box is shown.
  1337  * @return string Space-separated string of class names.
  1404  * @return string Space-separated string of class names.
  1338  */
  1405  */
  1339 function postbox_classes( $box_id, $screen_id ) {
  1406 function postbox_classes( $box_id, $screen_id ) {
  1340 	if ( isset( $_GET['edit'] ) && $_GET['edit'] == $box_id ) {
  1407 	if ( isset( $_GET['edit'] ) && $_GET['edit'] === $box_id ) {
  1341 		$classes = array( '' );
  1408 		$classes = array( '' );
  1342 	} elseif ( get_user_option( 'closedpostboxes_' . $screen_id ) ) {
  1409 	} elseif ( get_user_option( 'closedpostboxes_' . $screen_id ) ) {
  1343 		$closed = get_user_option( 'closedpostboxes_' . $screen_id );
  1410 		$closed = get_user_option( 'closedpostboxes_' . $screen_id );
  1344 		if ( ! is_array( $closed ) ) {
  1411 		if ( ! is_array( $closed ) ) {
  1345 			$classes = array( '' );
  1412 			$classes = array( '' );
  1368 /**
  1435 /**
  1369  * Returns a sample permalink based on the post name.
  1436  * Returns a sample permalink based on the post name.
  1370  *
  1437  *
  1371  * @since 2.5.0
  1438  * @since 2.5.0
  1372  *
  1439  *
  1373  * @param int|WP_Post $id    Post ID or post object.
  1440  * @param int|WP_Post $post  Post ID or post object.
  1374  * @param string|null $title Optional. Title to override the post's current title
  1441  * @param string|null $title Optional. Title to override the post's current title
  1375  *                           when generating the post name. Default null.
  1442  *                           when generating the post name. Default null.
  1376  * @param string|null $name  Optional. Name to override the post name. Default null.
  1443  * @param string|null $name  Optional. Name to override the post name. Default null.
  1377  * @return array {
  1444  * @return array {
  1378  *     Array containing the sample permalink with placeholder for the post name, and the post name.
  1445  *     Array containing the sample permalink with placeholder for the post name, and the post name.
  1379  *
  1446  *
  1380  *     @type string $0 The permalink with placeholder for the post name.
  1447  *     @type string $0 The permalink with placeholder for the post name.
  1381  *     @type string $1 The post name.
  1448  *     @type string $1 The post name.
  1382  * }
  1449  * }
  1383  */
  1450  */
  1384 function get_sample_permalink( $id, $title = null, $name = null ) {
  1451 function get_sample_permalink( $post, $title = null, $name = null ) {
  1385 	$post = get_post( $id );
  1452 	$post = get_post( $post );
       
  1453 
  1386 	if ( ! $post ) {
  1454 	if ( ! $post ) {
  1387 		return array( '', '' );
  1455 		return array( '', '' );
  1388 	}
  1456 	}
  1389 
  1457 
  1390 	$ptype = get_post_type_object( $post->post_type );
  1458 	$ptype = get_post_type_object( $post->post_type );
  1391 
  1459 
  1392 	$original_status = $post->post_status;
  1460 	$original_status = $post->post_status;
  1393 	$original_date   = $post->post_date;
  1461 	$original_date   = $post->post_date;
  1394 	$original_name   = $post->post_name;
  1462 	$original_name   = $post->post_name;
       
  1463 	$original_filter = $post->filter;
  1395 
  1464 
  1396 	// Hack: get_permalink() would return plain permalink for drafts, so we will fake that our post is published.
  1465 	// Hack: get_permalink() would return plain permalink for drafts, so we will fake that our post is published.
  1397 	if ( in_array( $post->post_status, array( 'draft', 'pending', 'future' ), true ) ) {
  1466 	if ( in_array( $post->post_status, array( 'auto-draft', 'draft', 'pending', 'future' ), true ) ) {
  1398 		$post->post_status = 'publish';
  1467 		$post->post_status = 'publish';
  1399 		$post->post_name   = sanitize_title( $post->post_name ? $post->post_name : $post->post_title, $post->ID );
  1468 		$post->post_name   = sanitize_title( $post->post_name ? $post->post_name : $post->post_title, $post->ID );
  1400 	}
  1469 	}
  1401 
  1470 
  1402 	// If the user wants to set a new name -- override the current one.
  1471 	/*
  1403 	// Note: if empty name is supplied -- use the title instead, see #6072.
  1472 	 * If the user wants to set a new name -- override the current one.
       
  1473 	 * Note: if empty name is supplied -- use the title instead, see #6072.
       
  1474 	 */
  1404 	if ( ! is_null( $name ) ) {
  1475 	if ( ! is_null( $name ) ) {
  1405 		$post->post_name = sanitize_title( $name ? $name : $title, $post->ID );
  1476 		$post->post_name = sanitize_title( $name ? $name : $title, $post->ID );
  1406 	}
  1477 	}
  1407 
  1478 
  1408 	$post->post_name = wp_unique_post_slug( $post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent );
  1479 	$post->post_name = wp_unique_post_slug( $post->post_name, $post->ID, $post->post_status, $post->post_type, $post->post_parent );
  1434 	/** This filter is documented in wp-admin/edit-tag-form.php */
  1505 	/** This filter is documented in wp-admin/edit-tag-form.php */
  1435 	$permalink         = array( $permalink, apply_filters( 'editable_slug', $post->post_name, $post ) );
  1506 	$permalink         = array( $permalink, apply_filters( 'editable_slug', $post->post_name, $post ) );
  1436 	$post->post_status = $original_status;
  1507 	$post->post_status = $original_status;
  1437 	$post->post_date   = $original_date;
  1508 	$post->post_date   = $original_date;
  1438 	$post->post_name   = $original_name;
  1509 	$post->post_name   = $original_name;
  1439 	unset( $post->filter );
  1510 	$post->filter      = $original_filter;
  1440 
  1511 
  1441 	/**
  1512 	/**
  1442 	 * Filters the sample permalink.
  1513 	 * Filters the sample permalink.
  1443 	 *
  1514 	 *
  1444 	 * @since 4.4.0
  1515 	 * @since 4.4.0
  1460 /**
  1531 /**
  1461  * Returns the HTML of the sample permalink slug editor.
  1532  * Returns the HTML of the sample permalink slug editor.
  1462  *
  1533  *
  1463  * @since 2.5.0
  1534  * @since 2.5.0
  1464  *
  1535  *
  1465  * @param int|WP_Post $id        Post ID or post object.
  1536  * @param int|WP_Post $post      Post ID or post object.
  1466  * @param string|null $new_title Optional. New title. Default null.
  1537  * @param string|null $new_title Optional. New title. Default null.
  1467  * @param string|null $new_slug  Optional. New slug. Default null.
  1538  * @param string|null $new_slug  Optional. New slug. Default null.
  1468  * @return string The HTML of the sample permalink slug editor.
  1539  * @return string The HTML of the sample permalink slug editor.
  1469  */
  1540  */
  1470 function get_sample_permalink_html( $id, $new_title = null, $new_slug = null ) {
  1541 function get_sample_permalink_html( $post, $new_title = null, $new_slug = null ) {
  1471 	$post = get_post( $id );
  1542 	$post = get_post( $post );
       
  1543 
  1472 	if ( ! $post ) {
  1544 	if ( ! $post ) {
  1473 		return '';
  1545 		return '';
  1474 	}
  1546 	}
  1475 
  1547 
  1476 	list($permalink, $post_name) = get_sample_permalink( $post->ID, $new_title, $new_slug );
  1548 	list($permalink, $post_name) = get_sample_permalink( $post->ID, $new_title, $new_slug );
  1491 			}
  1563 			}
  1492 		}
  1564 		}
  1493 	}
  1565 	}
  1494 
  1566 
  1495 	// Permalinks without a post/page name placeholder don't have anything to edit.
  1567 	// Permalinks without a post/page name placeholder don't have anything to edit.
  1496 	if ( false === strpos( $permalink, '%postname%' ) && false === strpos( $permalink, '%pagename%' ) ) {
  1568 	if ( ! str_contains( $permalink, '%postname%' ) && ! str_contains( $permalink, '%pagename%' ) ) {
  1497 		$return = '<strong>' . __( 'Permalink:' ) . "</strong>\n";
  1569 		$return = '<strong>' . __( 'Permalink:' ) . "</strong>\n";
  1498 
  1570 
  1499 		if ( false !== $view_link ) {
  1571 		if ( false !== $view_link ) {
  1500 			$display_link = urldecode( $view_link );
  1572 			$display_link = urldecode( $view_link );
  1501 			$return      .= '<a id="sample-permalink" href="' . esc_url( $view_link ) . '"' . $preview_target . '>' . esc_html( $display_link ) . "</a>\n";
  1573 			$return      .= '<a id="sample-permalink" href="' . esc_url( $view_link ) . '"' . $preview_target . '>' . esc_html( $display_link ) . "</a>\n";
  1503 			$return .= '<span id="sample-permalink">' . $permalink . "</span>\n";
  1575 			$return .= '<span id="sample-permalink">' . $permalink . "</span>\n";
  1504 		}
  1576 		}
  1505 
  1577 
  1506 		// Encourage a pretty permalink setting.
  1578 		// Encourage a pretty permalink setting.
  1507 		if ( ! get_option( 'permalink_structure' ) && current_user_can( 'manage_options' )
  1579 		if ( ! get_option( 'permalink_structure' ) && current_user_can( 'manage_options' )
  1508 			&& ! ( 'page' === get_option( 'show_on_front' ) && get_option( 'page_on_front' ) == $id )
  1580 			&& ! ( 'page' === get_option( 'show_on_front' ) && (int) get_option( 'page_on_front' ) === $post->ID )
  1509 		) {
  1581 		) {
  1510 			$return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button button-small">' . __( 'Change Permalink Structure' ) . "</a></span>\n";
  1582 			$return .= '<span id="change-permalinks"><a href="options-permalink.php" class="button button-small">' . __( 'Change Permalink Structure' ) . "</a></span>\n";
  1511 		}
  1583 		}
  1512 	} else {
  1584 	} else {
  1513 		if ( mb_strlen( $post_name ) > 34 ) {
  1585 		if ( mb_strlen( $post_name ) > 34 ) {
  1530 	 * Filters the sample permalink HTML markup.
  1602 	 * Filters the sample permalink HTML markup.
  1531 	 *
  1603 	 *
  1532 	 * @since 2.9.0
  1604 	 * @since 2.9.0
  1533 	 * @since 4.4.0 Added `$post` parameter.
  1605 	 * @since 4.4.0 Added `$post` parameter.
  1534 	 *
  1606 	 *
  1535 	 * @param string  $return    Sample permalink HTML markup.
  1607 	 * @param string      $return    Sample permalink HTML markup.
  1536 	 * @param int     $post_id   Post ID.
  1608 	 * @param int         $post_id   Post ID.
  1537 	 * @param string  $new_title New sample permalink title.
  1609 	 * @param string|null $new_title New sample permalink title.
  1538 	 * @param string  $new_slug  New sample permalink slug.
  1610 	 * @param string|null $new_slug  New sample permalink slug.
  1539 	 * @param WP_Post $post      Post object.
  1611 	 * @param WP_Post     $post      Post object.
  1540 	 */
  1612 	 */
  1541 	$return = apply_filters( 'get_sample_permalink_html', $return, $post->ID, $new_title, $new_slug, $post );
  1613 	$return = apply_filters( 'get_sample_permalink_html', $return, $post->ID, $new_title, $new_slug, $post );
  1542 
  1614 
  1543 	return $return;
  1615 	return $return;
  1544 }
  1616 }
  1620 /**
  1692 /**
  1621  * Determines whether the post is currently being edited by another user.
  1693  * Determines whether the post is currently being edited by another user.
  1622  *
  1694  *
  1623  * @since 2.5.0
  1695  * @since 2.5.0
  1624  *
  1696  *
  1625  * @param int|WP_Post $post_id ID or object of the post to check for editing.
  1697  * @param int|WP_Post $post ID or object of the post to check for editing.
  1626  * @return int|false ID of the user with lock. False if the post does not exist, post is not locked,
  1698  * @return int|false ID of the user with lock. False if the post does not exist, post is not locked,
  1627  *                   the user with lock does not exist, or the post is locked by current user.
  1699  *                   the user with lock does not exist, or the post is locked by current user.
  1628  */
  1700  */
  1629 function wp_check_post_lock( $post_id ) {
  1701 function wp_check_post_lock( $post ) {
  1630 	$post = get_post( $post_id );
  1702 	$post = get_post( $post );
       
  1703 
  1631 	if ( ! $post ) {
  1704 	if ( ! $post ) {
  1632 		return false;
  1705 		return false;
  1633 	}
  1706 	}
  1634 
  1707 
  1635 	$lock = get_post_meta( $post->ID, '_edit_lock', true );
  1708 	$lock = get_post_meta( $post->ID, '_edit_lock', true );
       
  1709 
  1636 	if ( ! $lock ) {
  1710 	if ( ! $lock ) {
  1637 		return false;
  1711 		return false;
  1638 	}
  1712 	}
  1639 
  1713 
  1640 	$lock = explode( ':', $lock );
  1714 	$lock = explode( ':', $lock );
  1641 	$time = $lock[0];
  1715 	$time = $lock[0];
  1642 	$user = isset( $lock[1] ) ? $lock[1] : get_post_meta( $post->ID, '_edit_last', true );
  1716 	$user = isset( $lock[1] ) ? (int) $lock[1] : (int) get_post_meta( $post->ID, '_edit_last', true );
  1643 
  1717 
  1644 	if ( ! get_userdata( $user ) ) {
  1718 	if ( ! get_userdata( $user ) ) {
  1645 		return false;
  1719 		return false;
  1646 	}
  1720 	}
  1647 
  1721 
  1648 	/** This filter is documented in wp-admin/includes/ajax-actions.php */
  1722 	/** This filter is documented in wp-admin/includes/ajax-actions.php */
  1649 	$time_window = apply_filters( 'wp_check_post_lock_window', 150 );
  1723 	$time_window = apply_filters( 'wp_check_post_lock_window', 150 );
  1650 
  1724 
  1651 	if ( $time && $time > time() - $time_window && get_current_user_id() != $user ) {
  1725 	if ( $time && $time > time() - $time_window && get_current_user_id() !== $user ) {
  1652 		return $user;
  1726 		return $user;
  1653 	}
  1727 	}
  1654 
  1728 
  1655 	return false;
  1729 	return false;
  1656 }
  1730 }
  1658 /**
  1732 /**
  1659  * Marks the post as currently being edited by the current user.
  1733  * Marks the post as currently being edited by the current user.
  1660  *
  1734  *
  1661  * @since 2.5.0
  1735  * @since 2.5.0
  1662  *
  1736  *
  1663  * @param int|WP_Post $post_id ID or object of the post being edited.
  1737  * @param int|WP_Post $post ID or object of the post being edited.
  1664  * @return array|false {
  1738  * @return array|false {
  1665  *     Array of the lock time and user ID. False if the post does not exist, or there
  1739  *     Array of the lock time and user ID. False if the post does not exist, or there
  1666  *     is no current user.
  1740  *     is no current user.
  1667  *
  1741  *
  1668  *     @type int $0 The current time as a Unix timestamp.
  1742  *     @type int $0 The current time as a Unix timestamp.
  1669  *     @type int $1 The ID of the current user.
  1743  *     @type int $1 The ID of the current user.
  1670  * }
  1744  * }
  1671  */
  1745  */
  1672 function wp_set_post_lock( $post_id ) {
  1746 function wp_set_post_lock( $post ) {
  1673 	$post = get_post( $post_id );
  1747 	$post = get_post( $post );
       
  1748 
  1674 	if ( ! $post ) {
  1749 	if ( ! $post ) {
  1675 		return false;
  1750 		return false;
  1676 	}
  1751 	}
  1677 
  1752 
  1678 	$user_id = get_current_user_id();
  1753 	$user_id = get_current_user_id();
  1679 	if ( 0 == $user_id ) {
  1754 
       
  1755 	if ( 0 === $user_id ) {
  1680 		return false;
  1756 		return false;
  1681 	}
  1757 	}
  1682 
  1758 
  1683 	$now  = time();
  1759 	$now  = time();
  1684 	$lock = "$now:$user_id";
  1760 	$lock = "$now:$user_id";
  1693  *
  1769  *
  1694  * @since 2.8.5
  1770  * @since 2.8.5
  1695  */
  1771  */
  1696 function _admin_notice_post_locked() {
  1772 function _admin_notice_post_locked() {
  1697 	$post = get_post();
  1773 	$post = get_post();
       
  1774 
  1698 	if ( ! $post ) {
  1775 	if ( ! $post ) {
  1699 		return;
  1776 		return;
  1700 	}
  1777 	}
  1701 
  1778 
  1702 	$user    = null;
  1779 	$user    = null;
  1703 	$user_id = wp_check_post_lock( $post->ID );
  1780 	$user_id = wp_check_post_lock( $post->ID );
       
  1781 
  1704 	if ( $user_id ) {
  1782 	if ( $user_id ) {
  1705 		$user = get_userdata( $user_id );
  1783 		$user = get_userdata( $user_id );
  1706 	}
  1784 	}
  1707 
  1785 
  1708 	if ( $user ) {
  1786 	if ( $user ) {
  1725 	} else {
  1803 	} else {
  1726 		$locked = false;
  1804 		$locked = false;
  1727 	}
  1805 	}
  1728 
  1806 
  1729 	$sendback = wp_get_referer();
  1807 	$sendback = wp_get_referer();
  1730 	if ( $locked && $sendback && false === strpos( $sendback, 'post.php' ) && false === strpos( $sendback, 'post-new.php' ) ) {
  1808 	if ( $locked && $sendback && ! str_contains( $sendback, 'post.php' ) && ! str_contains( $sendback, 'post-new.php' ) ) {
  1731 
  1809 
  1732 		$sendback_text = __( 'Go back' );
  1810 		$sendback_text = __( 'Go back' );
  1733 	} else {
  1811 	} else {
  1734 		$sendback = admin_url( 'edit.php' );
  1812 		$sendback = admin_url( 'edit.php' );
  1735 
  1813 
  1749 	<?php
  1827 	<?php
  1750 
  1828 
  1751 	if ( $locked ) {
  1829 	if ( $locked ) {
  1752 		$query_args = array();
  1830 		$query_args = array();
  1753 		if ( get_post_type_object( $post->post_type )->public ) {
  1831 		if ( get_post_type_object( $post->post_type )->public ) {
  1754 			if ( 'publish' === $post->post_status || $user->ID != $post->post_author ) {
  1832 			if ( 'publish' === $post->post_status || $user->ID !== (int) $post->post_author ) {
  1755 				// Latest content is in autosave.
  1833 				// Latest content is in autosave.
  1756 				$nonce                       = wp_create_nonce( 'post_preview_' . $post->ID );
  1834 				$nonce                       = wp_create_nonce( 'post_preview_' . $post->ID );
  1757 				$query_args['preview_id']    = $post->ID;
  1835 				$query_args['preview_id']    = $post->ID;
  1758 				$query_args['preview_nonce'] = $nonce;
  1836 				$query_args['preview_nonce'] = $nonce;
  1759 			}
  1837 			}
  1900 
  1978 
  1901 		/**
  1979 		/**
  1902 		 * Fires before an autosave is stored.
  1980 		 * Fires before an autosave is stored.
  1903 		 *
  1981 		 *
  1904 		 * @since 4.1.0
  1982 		 * @since 4.1.0
       
  1983 		 * @since 6.4.0 The `$is_update` parameter was added to indicate if the autosave is being updated or was newly created.
  1905 		 *
  1984 		 *
  1906 		 * @param array $new_autosave Post array - the autosave that is about to be saved.
  1985 		 * @param array $new_autosave Post array - the autosave that is about to be saved.
       
  1986 		 * @param bool  $is_update    Whether this is an existing autosave.
  1907 		 */
  1987 		 */
  1908 		do_action( 'wp_creating_autosave', $new_autosave );
  1988 		do_action( 'wp_creating_autosave', $new_autosave, true );
  1909 
       
  1910 		return wp_update_post( $new_autosave );
  1989 		return wp_update_post( $new_autosave );
  1911 	}
  1990 	}
  1912 
  1991 
  1913 	// _wp_put_post_revision() expects unescaped.
  1992 	// _wp_put_post_revision() expects unescaped.
  1914 	$post_data = wp_unslash( $post_data );
  1993 	$post_data = wp_unslash( $post_data );
  1915 
  1994 
  1916 	// Otherwise create the new autosave as a special post revision.
  1995 	// Otherwise create the new autosave as a special post revision.
  1917 	return _wp_put_post_revision( $post_data, true );
  1996 	$revision = _wp_put_post_revision( $post_data, true );
       
  1997 
       
  1998 	if ( ! is_wp_error( $revision ) && 0 !== $revision ) {
       
  1999 
       
  2000 		/** This action is documented in wp-admin/includes/post.php */
       
  2001 		do_action( 'wp_creating_autosave', get_post( $revision, ARRAY_A ), false );
       
  2002 	}
       
  2003 
       
  2004 	return $revision;
       
  2005 }
       
  2006 
       
  2007 /**
       
  2008  * Autosave the revisioned meta fields.
       
  2009  *
       
  2010  * Iterates through the revisioned meta fields and checks each to see if they are set,
       
  2011  * and have a changed value. If so, the meta value is saved and attached to the autosave.
       
  2012  *
       
  2013  * @since 6.4.0
       
  2014  *
       
  2015  * @param array $new_autosave The new post data being autosaved.
       
  2016  */
       
  2017 function wp_autosave_post_revisioned_meta_fields( $new_autosave ) {
       
  2018 	/*
       
  2019 	 * The post data arrives as either $_POST['data']['wp_autosave'] or the $_POST
       
  2020 	 * itself. This sets $posted_data to the correct variable.
       
  2021 	 *
       
  2022 	 * Ignoring sanitization to avoid altering meta. Ignoring the nonce check because
       
  2023 	 * this is hooked on inner core hooks where a valid nonce was already checked.
       
  2024 	 */
       
  2025 	$posted_data = isset( $_POST['data']['wp_autosave'] ) ? $_POST['data']['wp_autosave'] : $_POST;
       
  2026 
       
  2027 	$post_type = get_post_type( $new_autosave['post_parent'] );
       
  2028 
       
  2029 	/*
       
  2030 	 * Go thru the revisioned meta keys and save them as part of the autosave, if
       
  2031 	 * the meta key is part of the posted data, the meta value is not blank and
       
  2032 	 * the the meta value has changes from the last autosaved value.
       
  2033 	 */
       
  2034 	foreach ( wp_post_revision_meta_keys( $post_type ) as $meta_key ) {
       
  2035 
       
  2036 		if (
       
  2037 		isset( $posted_data[ $meta_key ] ) &&
       
  2038 		get_post_meta( $new_autosave['ID'], $meta_key, true ) !== wp_unslash( $posted_data[ $meta_key ] )
       
  2039 		) {
       
  2040 			/*
       
  2041 			 * Use the underlying delete_metadata() and add_metadata() functions
       
  2042 			 * vs delete_post_meta() and add_post_meta() to make sure we're working
       
  2043 			 * with the actual revision meta.
       
  2044 			 */
       
  2045 			delete_metadata( 'post', $new_autosave['ID'], $meta_key );
       
  2046 
       
  2047 			/*
       
  2048 			 * One last check to ensure meta value not empty().
       
  2049 			 */
       
  2050 			if ( ! empty( $posted_data[ $meta_key ] ) ) {
       
  2051 				/*
       
  2052 				 * Add the revisions meta data to the autosave.
       
  2053 				 */
       
  2054 				add_metadata( 'post', $new_autosave['ID'], $meta_key, $posted_data[ $meta_key ] );
       
  2055 			}
       
  2056 		}
       
  2057 	}
  1918 }
  2058 }
  1919 
  2059 
  1920 /**
  2060 /**
  1921  * Saves a draft or manually autosaves for the purpose of showing a post preview.
  2061  * Saves a draft or manually autosaves for the purpose of showing a post preview.
  1922  *
  2062  *
  1924  *
  2064  *
  1925  * @return string URL to redirect to show the preview.
  2065  * @return string URL to redirect to show the preview.
  1926  */
  2066  */
  1927 function post_preview() {
  2067 function post_preview() {
  1928 
  2068 
  1929 	$post_ID     = (int) $_POST['post_ID'];
  2069 	$post_id     = (int) $_POST['post_ID'];
  1930 	$_POST['ID'] = $post_ID;
  2070 	$_POST['ID'] = $post_id;
  1931 
  2071 
  1932 	$post = get_post( $post_ID );
  2072 	$post = get_post( $post_id );
       
  2073 
  1933 	if ( ! $post ) {
  2074 	if ( ! $post ) {
  1934 		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
  2075 		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
  1935 	}
  2076 	}
  1936 
  2077 
  1937 	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
  2078 	if ( ! current_user_can( 'edit_post', $post->ID ) ) {
  1938 		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
  2079 		wp_die( __( 'Sorry, you are not allowed to edit this post.' ) );
  1939 	}
  2080 	}
  1940 
  2081 
  1941 	$is_autosave = false;
  2082 	$is_autosave = false;
  1942 
  2083 
  1943 	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author
  2084 	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() === (int) $post->post_author
  1944 		&& ( 'draft' === $post->post_status || 'auto-draft' === $post->post_status )
  2085 		&& ( 'draft' === $post->post_status || 'auto-draft' === $post->post_status )
  1945 	) {
  2086 	) {
  1946 		$saved_post_id = edit_post();
  2087 		$saved_post_id = edit_post();
  1947 	} else {
  2088 	} else {
  1948 		$is_autosave = true;
  2089 		$is_autosave = true;
  2013 
  2154 
  2014 	if ( 'page' !== $post_data['post_type'] && ! empty( $post_data['catslist'] ) ) {
  2155 	if ( 'page' !== $post_data['post_type'] && ! empty( $post_data['catslist'] ) ) {
  2015 		$post_data['post_category'] = explode( ',', $post_data['catslist'] );
  2156 		$post_data['post_category'] = explode( ',', $post_data['catslist'] );
  2016 	}
  2157 	}
  2017 
  2158 
  2018 	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author
  2159 	if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() === (int) $post->post_author
  2019 		&& ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status )
  2160 		&& ( 'auto-draft' === $post->post_status || 'draft' === $post->post_status )
  2020 	) {
  2161 	) {
  2021 		// Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked.
  2162 		// Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked.
  2022 		return edit_post( wp_slash( $post_data ) );
  2163 		return edit_post( wp_slash( $post_data ) );
  2023 	} else {
  2164 	} else {
  2024 		// Non-drafts or other users' drafts are not overwritten.
  2165 		/*
  2025 		// The autosave is stored in a special post revision for each user.
  2166 		 * Non-drafts or other users' drafts are not overwritten.
       
  2167 		 * The autosave is stored in a special post revision for each user.
       
  2168 		 */
  2026 		return wp_create_post_autosave( wp_slash( $post_data ) );
  2169 		return wp_create_post_autosave( wp_slash( $post_data ) );
  2027 	}
  2170 	}
  2028 }
  2171 }
  2029 
  2172 
  2030 /**
  2173 /**
  2036  */
  2179  */
  2037 function redirect_post( $post_id = '' ) {
  2180 function redirect_post( $post_id = '' ) {
  2038 	if ( isset( $_POST['save'] ) || isset( $_POST['publish'] ) ) {
  2181 	if ( isset( $_POST['save'] ) || isset( $_POST['publish'] ) ) {
  2039 		$status = get_post_status( $post_id );
  2182 		$status = get_post_status( $post_id );
  2040 
  2183 
  2041 		if ( isset( $_POST['publish'] ) ) {
  2184 		switch ( $status ) {
  2042 			switch ( $status ) {
  2185 			case 'pending':
  2043 				case 'pending':
  2186 				$message = 8;
  2044 					$message = 8;
  2187 				break;
  2045 					break;
  2188 			case 'future':
  2046 				case 'future':
  2189 				$message = 9;
  2047 					$message = 9;
  2190 				break;
  2048 					break;
  2191 			case 'draft':
  2049 				default:
  2192 				$message = 10;
  2050 					$message = 6;
  2193 				break;
  2051 			}
  2194 			default:
  2052 		} else {
  2195 				$message = isset( $_POST['publish'] ) ? 6 : 1;
  2053 			$message = 'draft' === $status ? 10 : 1;
  2196 				break;
  2054 		}
  2197 		}
  2055 
  2198 
  2056 		$location = add_query_arg( 'message', $message, get_edit_post_link( $post_id, 'url' ) );
  2199 		$location = add_query_arg( 'message', $message, get_edit_post_link( $post_id, 'url' ) );
  2057 	} elseif ( isset( $_POST['addmeta'] ) && $_POST['addmeta'] ) {
  2200 	} elseif ( isset( $_POST['addmeta'] ) && $_POST['addmeta'] ) {
  2058 		$location = add_query_arg( 'message', 2, wp_get_referer() );
  2201 		$location = add_query_arg( 'message', 2, wp_get_referer() );
  2140 
  2283 
  2141 	return $clean_terms;
  2284 	return $clean_terms;
  2142 }
  2285 }
  2143 
  2286 
  2144 /**
  2287 /**
  2145  * Returns whether the post can be edited in the block editor.
       
  2146  *
       
  2147  * @since 5.0.0
       
  2148  *
       
  2149  * @param int|WP_Post $post Post ID or WP_Post object.
       
  2150  * @return bool Whether the post can be edited in the block editor.
       
  2151  */
       
  2152 function use_block_editor_for_post( $post ) {
       
  2153 	$post = get_post( $post );
       
  2154 
       
  2155 	if ( ! $post ) {
       
  2156 		return false;
       
  2157 	}
       
  2158 
       
  2159 	// We're in the meta box loader, so don't use the block editor.
       
  2160 	if ( isset( $_GET['meta-box-loader'] ) ) {
       
  2161 		check_admin_referer( 'meta-box-loader', 'meta-box-loader-nonce' );
       
  2162 		return false;
       
  2163 	}
       
  2164 
       
  2165 	$use_block_editor = use_block_editor_for_post_type( $post->post_type );
       
  2166 
       
  2167 	/**
       
  2168 	 * Filters whether a post is able to be edited in the block editor.
       
  2169 	 *
       
  2170 	 * @since 5.0.0
       
  2171 	 *
       
  2172 	 * @param bool    $use_block_editor Whether the post can be edited or not.
       
  2173 	 * @param WP_Post $post             The post being checked.
       
  2174 	 */
       
  2175 	return apply_filters( 'use_block_editor_for_post', $use_block_editor, $post );
       
  2176 }
       
  2177 
       
  2178 /**
       
  2179  * Returns whether a post type is compatible with the block editor.
       
  2180  *
       
  2181  * The block editor depends on the REST API, and if the post type is not shown in the
       
  2182  * REST API, then it won't work with the block editor.
       
  2183  *
       
  2184  * @since 5.0.0
       
  2185  *
       
  2186  * @param string $post_type The post type.
       
  2187  * @return bool Whether the post type can be edited with the block editor.
       
  2188  */
       
  2189 function use_block_editor_for_post_type( $post_type ) {
       
  2190 	if ( ! post_type_exists( $post_type ) ) {
       
  2191 		return false;
       
  2192 	}
       
  2193 
       
  2194 	if ( ! post_type_supports( $post_type, 'editor' ) ) {
       
  2195 		return false;
       
  2196 	}
       
  2197 
       
  2198 	$post_type_object = get_post_type_object( $post_type );
       
  2199 	if ( $post_type_object && ! $post_type_object->show_in_rest ) {
       
  2200 		return false;
       
  2201 	}
       
  2202 
       
  2203 	/**
       
  2204 	 * Filters whether a post is able to be edited in the block editor.
       
  2205 	 *
       
  2206 	 * @since 5.0.0
       
  2207 	 *
       
  2208 	 * @param bool   $use_block_editor  Whether the post type can be edited or not. Default true.
       
  2209 	 * @param string $post_type         The post type being checked.
       
  2210 	 */
       
  2211 	return apply_filters( 'use_block_editor_for_post_type', true, $post_type );
       
  2212 }
       
  2213 
       
  2214 /**
       
  2215  * Prepares server-registered blocks for the block editor.
  2288  * Prepares server-registered blocks for the block editor.
  2216  *
  2289  *
  2217  * Returns an associative array of registered block data keyed by block name. Data includes properties
  2290  * Returns an associative array of registered block data keyed by block name. Data includes properties
  2218  * of a block relevant for client registration.
  2291  * of a block relevant for client registration.
  2219  *
  2292  *
  2220  * @since 5.0.0
  2293  * @since 5.0.0
       
  2294  * @since 6.3.0 Added `selectors` field.
       
  2295  * @since 6.4.0 Added `block_hooks` field.
  2221  *
  2296  *
  2222  * @return array An associative array of registered block data.
  2297  * @return array An associative array of registered block data.
  2223  */
  2298  */
  2224 function get_block_editor_server_block_settings() {
  2299 function get_block_editor_server_block_settings() {
  2225 	$block_registry = WP_Block_Type_Registry::get_instance();
  2300 	$block_registry = WP_Block_Type_Registry::get_instance();
  2230 		'description'      => 'description',
  2305 		'description'      => 'description',
  2231 		'icon'             => 'icon',
  2306 		'icon'             => 'icon',
  2232 		'attributes'       => 'attributes',
  2307 		'attributes'       => 'attributes',
  2233 		'provides_context' => 'providesContext',
  2308 		'provides_context' => 'providesContext',
  2234 		'uses_context'     => 'usesContext',
  2309 		'uses_context'     => 'usesContext',
       
  2310 		'block_hooks'      => 'blockHooks',
       
  2311 		'selectors'        => 'selectors',
  2235 		'supports'         => 'supports',
  2312 		'supports'         => 'supports',
  2236 		'category'         => 'category',
  2313 		'category'         => 'category',
  2237 		'styles'           => 'styles',
  2314 		'styles'           => 'styles',
  2238 		'textdomain'       => 'textdomain',
  2315 		'textdomain'       => 'textdomain',
  2239 		'parent'           => 'parent',
  2316 		'parent'           => 'parent',
  2240 		'ancestor'         => 'ancestor',
  2317 		'ancestor'         => 'ancestor',
  2241 		'keywords'         => 'keywords',
  2318 		'keywords'         => 'keywords',
  2242 		'example'          => 'example',
  2319 		'example'          => 'example',
  2243 		'variations'       => 'variations',
  2320 		'variations'       => 'variations',
       
  2321 		'allowed_blocks'   => 'allowedBlocks',
  2244 	);
  2322 	);
  2245 
  2323 
  2246 	foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
  2324 	foreach ( $block_registry->get_all_registered() as $block_name => $block_type ) {
  2247 		foreach ( $fields_to_pick as $field => $key ) {
  2325 		foreach ( $fields_to_pick as $field => $key ) {
  2248 			if ( ! isset( $block_type->{ $field } ) ) {
  2326 			if ( ! isset( $block_type->{ $field } ) ) {
  2262 
  2340 
  2263 /**
  2341 /**
  2264  * Renders the meta boxes forms.
  2342  * Renders the meta boxes forms.
  2265  *
  2343  *
  2266  * @since 5.0.0
  2344  * @since 5.0.0
       
  2345  *
       
  2346  * @global WP_Post   $post           Global post object.
       
  2347  * @global WP_Screen $current_screen WordPress current screen object.
       
  2348  * @global array     $wp_meta_boxes  Global meta box state.
  2267  */
  2349  */
  2268 function the_block_editor_meta_boxes() {
  2350 function the_block_editor_meta_boxes() {
  2269 	global $post, $current_screen, $wp_meta_boxes;
  2351 	global $post, $current_screen, $wp_meta_boxes;
  2270 
  2352 
  2271 	// Handle meta box state.
  2353 	// Handle meta box state.
  2324 				continue;
  2406 				continue;
  2325 			}
  2407 			}
  2326 
  2408 
  2327 			$meta_boxes = (array) $wp_meta_boxes[ $current_screen->id ][ $location ][ $priority ];
  2409 			$meta_boxes = (array) $wp_meta_boxes[ $current_screen->id ][ $location ][ $priority ];
  2328 			foreach ( $meta_boxes as $meta_box ) {
  2410 			foreach ( $meta_boxes as $meta_box ) {
  2329 				if ( false == $meta_box || ! $meta_box['title'] ) {
  2411 				if ( false === $meta_box || ! $meta_box['title'] ) {
  2330 					continue;
  2412 					continue;
  2331 				}
  2413 				}
  2332 
  2414 
  2333 				// If a meta box is just here for back compat, don't show it in the block editor.
  2415 				// If a meta box is just here for back compat, don't show it in the block editor.
  2334 				if ( isset( $meta_box['args']['__back_compat_meta_box'] ) && $meta_box['args']['__back_compat_meta_box'] ) {
  2416 				if ( isset( $meta_box['args']['__back_compat_meta_box'] ) && $meta_box['args']['__back_compat_meta_box'] ) {
  2387 		} )( jQuery );";
  2469 		} )( jQuery );";
  2388 		wp_enqueue_script( 'wp-lists' );
  2470 		wp_enqueue_script( 'wp-lists' );
  2389 		wp_add_inline_script( 'wp-lists', $script );
  2471 		wp_add_inline_script( 'wp-lists', $script );
  2390 	}
  2472 	}
  2391 
  2473 
       
  2474 	/*
       
  2475 	 * Refresh nonces used by the meta box loader.
       
  2476 	 *
       
  2477 	 * The logic is very similar to that provided by post.js for the classic editor.
       
  2478 	 */
       
  2479 	$script = "( function( $ ) {
       
  2480 		var check, timeout;
       
  2481 
       
  2482 		function schedule() {
       
  2483 			check = false;
       
  2484 			window.clearTimeout( timeout );
       
  2485 			timeout = window.setTimeout( function() { check = true; }, 300000 );
       
  2486 		}
       
  2487 
       
  2488 		$( document ).on( 'heartbeat-send.wp-refresh-nonces', function( e, data ) {
       
  2489 			var post_id, \$authCheck = $( '#wp-auth-check-wrap' );
       
  2490 
       
  2491 			if ( check || ( \$authCheck.length && ! \$authCheck.hasClass( 'hidden' ) ) ) {
       
  2492 				if ( ( post_id = $( '#post_ID' ).val() ) && $( '#_wpnonce' ).val() ) {
       
  2493 					data['wp-refresh-metabox-loader-nonces'] = {
       
  2494 						post_id: post_id
       
  2495 					};
       
  2496 				}
       
  2497 			}
       
  2498 		}).on( 'heartbeat-tick.wp-refresh-nonces', function( e, data ) {
       
  2499 			var nonces = data['wp-refresh-metabox-loader-nonces'];
       
  2500 
       
  2501 			if ( nonces ) {
       
  2502 				if ( nonces.replace ) {
       
  2503 					if ( nonces.replace.metabox_loader_nonce && window._wpMetaBoxUrl && wp.url ) {
       
  2504 						window._wpMetaBoxUrl= wp.url.addQueryArgs( window._wpMetaBoxUrl, { 'meta-box-loader-nonce': nonces.replace.metabox_loader_nonce } );
       
  2505 					}
       
  2506 
       
  2507 					if ( nonces.replace._wpnonce ) {
       
  2508 						$( '#_wpnonce' ).val( nonces.replace._wpnonce );
       
  2509 					}
       
  2510 				}
       
  2511 			}
       
  2512 		}).ready( function() {
       
  2513 			schedule();
       
  2514 		});
       
  2515 	} )( jQuery );";
       
  2516 	wp_add_inline_script( 'heartbeat', $script );
       
  2517 
  2392 	// Reset meta box data.
  2518 	// Reset meta box data.
  2393 	$wp_meta_boxes = $_original_meta_boxes;
  2519 	$wp_meta_boxes = $_original_meta_boxes;
  2394 }
  2520 }
  2395 
  2521 
  2396 /**
  2522 /**
  2426 	$classic_output = ob_get_clean();
  2552 	$classic_output = ob_get_clean();
  2427 
  2553 
  2428 	$classic_elements = wp_html_split( $classic_output );
  2554 	$classic_elements = wp_html_split( $classic_output );
  2429 	$hidden_inputs    = '';
  2555 	$hidden_inputs    = '';
  2430 	foreach ( $classic_elements as $element ) {
  2556 	foreach ( $classic_elements as $element ) {
  2431 		if ( 0 !== strpos( $element, '<input ' ) ) {
  2557 		if ( ! str_starts_with( $element, '<input ' ) ) {
  2432 			continue;
  2558 			continue;
  2433 		}
  2559 		}
  2434 
  2560 
  2435 		if ( preg_match( '/\stype=[\'"]hidden[\'"]\s/', $element ) ) {
  2561 		if ( preg_match( '/\stype=[\'"]hidden[\'"]\s/', $element ) ) {
  2436 			echo $element;
  2562 			echo $element;