wp/wp-includes/post.php
changeset 16 a86126ab1dd4
parent 9 177826044cd9
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Post
     6  * @subpackage Post
     7  */
     7  */
     8 
     8 
     9 //
     9 //
    10 // Post Type Registration
    10 // Post Type registration.
    11 //
    11 //
    12 
    12 
    13 /**
    13 /**
    14  * Creates the initial post types when 'init' action is fired.
    14  * Creates the initial post types when 'init' action is fired.
    15  *
    15  *
    28 			'_builtin'              => true, /* internal use only. don't use this when registering your own post type. */
    28 			'_builtin'              => true, /* internal use only. don't use this when registering your own post type. */
    29 			'_edit_link'            => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
    29 			'_edit_link'            => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
    30 			'capability_type'       => 'post',
    30 			'capability_type'       => 'post',
    31 			'map_meta_cap'          => true,
    31 			'map_meta_cap'          => true,
    32 			'menu_position'         => 5,
    32 			'menu_position'         => 5,
       
    33 			'menu_icon'             => 'dashicons-admin-post',
    33 			'hierarchical'          => false,
    34 			'hierarchical'          => false,
    34 			'rewrite'               => false,
    35 			'rewrite'               => false,
    35 			'query_var'             => false,
    36 			'query_var'             => false,
    36 			'delete_with_user'      => true,
    37 			'delete_with_user'      => true,
    37 			'supports'              => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats' ),
    38 			'supports'              => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats' ),
    52 			'_builtin'              => true, /* internal use only. don't use this when registering your own post type. */
    53 			'_builtin'              => true, /* internal use only. don't use this when registering your own post type. */
    53 			'_edit_link'            => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
    54 			'_edit_link'            => 'post.php?post=%d', /* internal use only. don't use this when registering your own post type. */
    54 			'capability_type'       => 'page',
    55 			'capability_type'       => 'page',
    55 			'map_meta_cap'          => true,
    56 			'map_meta_cap'          => true,
    56 			'menu_position'         => 20,
    57 			'menu_position'         => 20,
       
    58 			'menu_icon'             => 'dashicons-admin-page',
    57 			'hierarchical'          => true,
    59 			'hierarchical'          => true,
    58 			'rewrite'               => false,
    60 			'rewrite'               => false,
    59 			'query_var'             => false,
    61 			'query_var'             => false,
    60 			'delete_with_user'      => true,
    62 			'delete_with_user'      => true,
    61 			'supports'              => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'comments', 'revisions' ),
    63 			'supports'              => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'comments', 'revisions' ),
    83 			'capability_type'       => 'post',
    85 			'capability_type'       => 'post',
    84 			'capabilities'          => array(
    86 			'capabilities'          => array(
    85 				'create_posts' => 'upload_files',
    87 				'create_posts' => 'upload_files',
    86 			),
    88 			),
    87 			'map_meta_cap'          => true,
    89 			'map_meta_cap'          => true,
       
    90 			'menu_icon'             => 'dashicons-admin-media',
    88 			'hierarchical'          => false,
    91 			'hierarchical'          => false,
    89 			'rewrite'               => false,
    92 			'rewrite'               => false,
    90 			'query_var'             => false,
    93 			'query_var'             => false,
    91 			'show_in_nav_menus'     => false,
    94 			'show_in_nav_menus'     => false,
    92 			'delete_with_user'      => true,
    95 			'delete_with_user'      => true,
   310 		'publish',
   313 		'publish',
   311 		array(
   314 		array(
   312 			'label'       => _x( 'Published', 'post status' ),
   315 			'label'       => _x( 'Published', 'post status' ),
   313 			'public'      => true,
   316 			'public'      => true,
   314 			'_builtin'    => true, /* internal use only. */
   317 			'_builtin'    => true, /* internal use only. */
   315 			'label_count' => _n_noop( 'Published <span class="count">(%s)</span>', 'Published <span class="count">(%s)</span>' ),
   318 			/* translators: %s: Number of published posts. */
       
   319 			'label_count' => _n_noop(
       
   320 				'Published <span class="count">(%s)</span>',
       
   321 				'Published <span class="count">(%s)</span>'
       
   322 			),
   316 		)
   323 		)
   317 	);
   324 	);
   318 
   325 
   319 	register_post_status(
   326 	register_post_status(
   320 		'future',
   327 		'future',
   321 		array(
   328 		array(
   322 			'label'       => _x( 'Scheduled', 'post status' ),
   329 			'label'       => _x( 'Scheduled', 'post status' ),
   323 			'protected'   => true,
   330 			'protected'   => true,
   324 			'_builtin'    => true, /* internal use only. */
   331 			'_builtin'    => true, /* internal use only. */
   325 			'label_count' => _n_noop( 'Scheduled <span class="count">(%s)</span>', 'Scheduled <span class="count">(%s)</span>' ),
   332 			/* translators: %s: Number of scheduled posts. */
       
   333 			'label_count' => _n_noop(
       
   334 				'Scheduled <span class="count">(%s)</span>',
       
   335 				'Scheduled <span class="count">(%s)</span>'
       
   336 			),
   326 		)
   337 		)
   327 	);
   338 	);
   328 
   339 
   329 	register_post_status(
   340 	register_post_status(
   330 		'draft',
   341 		'draft',
   331 		array(
   342 		array(
   332 			'label'       => _x( 'Draft', 'post status' ),
   343 			'label'         => _x( 'Draft', 'post status' ),
   333 			'protected'   => true,
   344 			'protected'     => true,
   334 			'_builtin'    => true, /* internal use only. */
   345 			'_builtin'      => true, /* internal use only. */
   335 			'label_count' => _n_noop( 'Draft <span class="count">(%s)</span>', 'Drafts <span class="count">(%s)</span>' ),
   346 			/* translators: %s: Number of draft posts. */
       
   347 			'label_count'   => _n_noop(
       
   348 				'Draft <span class="count">(%s)</span>',
       
   349 				'Drafts <span class="count">(%s)</span>'
       
   350 			),
       
   351 			'date_floating' => true,
   336 		)
   352 		)
   337 	);
   353 	);
   338 
   354 
   339 	register_post_status(
   355 	register_post_status(
   340 		'pending',
   356 		'pending',
   341 		array(
   357 		array(
   342 			'label'       => _x( 'Pending', 'post status' ),
   358 			'label'         => _x( 'Pending', 'post status' ),
   343 			'protected'   => true,
   359 			'protected'     => true,
   344 			'_builtin'    => true, /* internal use only. */
   360 			'_builtin'      => true, /* internal use only. */
   345 			'label_count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>' ),
   361 			/* translators: %s: Number of pending posts. */
       
   362 			'label_count'   => _n_noop(
       
   363 				'Pending <span class="count">(%s)</span>',
       
   364 				'Pending <span class="count">(%s)</span>'
       
   365 			),
       
   366 			'date_floating' => true,
   346 		)
   367 		)
   347 	);
   368 	);
   348 
   369 
   349 	register_post_status(
   370 	register_post_status(
   350 		'private',
   371 		'private',
   351 		array(
   372 		array(
   352 			'label'       => _x( 'Private', 'post status' ),
   373 			'label'       => _x( 'Private', 'post status' ),
   353 			'private'     => true,
   374 			'private'     => true,
   354 			'_builtin'    => true, /* internal use only. */
   375 			'_builtin'    => true, /* internal use only. */
   355 			'label_count' => _n_noop( 'Private <span class="count">(%s)</span>', 'Private <span class="count">(%s)</span>' ),
   376 			/* translators: %s: Number of private posts. */
       
   377 			'label_count' => _n_noop(
       
   378 				'Private <span class="count">(%s)</span>',
       
   379 				'Private <span class="count">(%s)</span>'
       
   380 			),
   356 		)
   381 		)
   357 	);
   382 	);
   358 
   383 
   359 	register_post_status(
   384 	register_post_status(
   360 		'trash',
   385 		'trash',
   361 		array(
   386 		array(
   362 			'label'                     => _x( 'Trash', 'post status' ),
   387 			'label'                     => _x( 'Trash', 'post status' ),
   363 			'internal'                  => true,
   388 			'internal'                  => true,
   364 			'_builtin'                  => true, /* internal use only. */
   389 			'_builtin'                  => true, /* internal use only. */
   365 			'label_count'               => _n_noop( 'Trash <span class="count">(%s)</span>', 'Trash <span class="count">(%s)</span>' ),
   390 			/* translators: %s: Number of trashed posts. */
       
   391 			'label_count'               => _n_noop(
       
   392 				'Trash <span class="count">(%s)</span>',
       
   393 				'Trash <span class="count">(%s)</span>'
       
   394 			),
   366 			'show_in_admin_status_list' => true,
   395 			'show_in_admin_status_list' => true,
   367 		)
   396 		)
   368 	);
   397 	);
   369 
   398 
   370 	register_post_status(
   399 	register_post_status(
   371 		'auto-draft',
   400 		'auto-draft',
   372 		array(
   401 		array(
   373 			'label'    => 'auto-draft',
   402 			'label'         => 'auto-draft',
   374 			'internal' => true,
   403 			'internal'      => true,
   375 			'_builtin' => true, /* internal use only. */
   404 			'_builtin'      => true, /* internal use only. */
       
   405 			'date_floating' => true,
   376 		)
   406 		)
   377 	);
   407 	);
   378 
   408 
   379 	register_post_status(
   409 	register_post_status(
   380 		'inherit',
   410 		'inherit',
   390 		'request-pending',
   420 		'request-pending',
   391 		array(
   421 		array(
   392 			'label'               => _x( 'Pending', 'request status' ),
   422 			'label'               => _x( 'Pending', 'request status' ),
   393 			'internal'            => true,
   423 			'internal'            => true,
   394 			'_builtin'            => true, /* internal use only. */
   424 			'_builtin'            => true, /* internal use only. */
   395 			'label_count'         => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>' ),
   425 			/* translators: %s: Number of pending requests. */
       
   426 			'label_count'         => _n_noop(
       
   427 				'Pending <span class="count">(%s)</span>',
       
   428 				'Pending <span class="count">(%s)</span>'
       
   429 			),
   396 			'exclude_from_search' => false,
   430 			'exclude_from_search' => false,
   397 		)
   431 		)
   398 	);
   432 	);
   399 
   433 
   400 	register_post_status(
   434 	register_post_status(
   401 		'request-confirmed',
   435 		'request-confirmed',
   402 		array(
   436 		array(
   403 			'label'               => _x( 'Confirmed', 'request status' ),
   437 			'label'               => _x( 'Confirmed', 'request status' ),
   404 			'internal'            => true,
   438 			'internal'            => true,
   405 			'_builtin'            => true, /* internal use only. */
   439 			'_builtin'            => true, /* internal use only. */
   406 			'label_count'         => _n_noop( 'Confirmed <span class="count">(%s)</span>', 'Confirmed <span class="count">(%s)</span>' ),
   440 			/* translators: %s: Number of confirmed requests. */
       
   441 			'label_count'         => _n_noop(
       
   442 				'Confirmed <span class="count">(%s)</span>',
       
   443 				'Confirmed <span class="count">(%s)</span>'
       
   444 			),
   407 			'exclude_from_search' => false,
   445 			'exclude_from_search' => false,
   408 		)
   446 		)
   409 	);
   447 	);
   410 
   448 
   411 	register_post_status(
   449 	register_post_status(
   412 		'request-failed',
   450 		'request-failed',
   413 		array(
   451 		array(
   414 			'label'               => _x( 'Failed', 'request status' ),
   452 			'label'               => _x( 'Failed', 'request status' ),
   415 			'internal'            => true,
   453 			'internal'            => true,
   416 			'_builtin'            => true, /* internal use only. */
   454 			'_builtin'            => true, /* internal use only. */
   417 			'label_count'         => _n_noop( 'Failed <span class="count">(%s)</span>', 'Failed <span class="count">(%s)</span>' ),
   455 			/* translators: %s: Number of failed requests. */
       
   456 			'label_count'         => _n_noop(
       
   457 				'Failed <span class="count">(%s)</span>',
       
   458 				'Failed <span class="count">(%s)</span>'
       
   459 			),
   418 			'exclude_from_search' => false,
   460 			'exclude_from_search' => false,
   419 		)
   461 		)
   420 	);
   462 	);
   421 
   463 
   422 	register_post_status(
   464 	register_post_status(
   423 		'request-completed',
   465 		'request-completed',
   424 		array(
   466 		array(
   425 			'label'               => _x( 'Completed', 'request status' ),
   467 			'label'               => _x( 'Completed', 'request status' ),
   426 			'internal'            => true,
   468 			'internal'            => true,
   427 			'_builtin'            => true, /* internal use only. */
   469 			'_builtin'            => true, /* internal use only. */
   428 			'label_count'         => _n_noop( 'Completed <span class="count">(%s)</span>', 'Completed <span class="count">(%s)</span>' ),
   470 			/* translators: %s: Number of completed requests. */
       
   471 			'label_count'         => _n_noop(
       
   472 				'Completed <span class="count">(%s)</span>',
       
   473 				'Completed <span class="count">(%s)</span>'
       
   474 			),
   429 			'exclude_from_search' => false,
   475 			'exclude_from_search' => false,
   430 		)
   476 		)
   431 	);
   477 	);
   432 }
   478 }
   433 
   479 
   451  */
   497  */
   452 function get_attached_file( $attachment_id, $unfiltered = false ) {
   498 function get_attached_file( $attachment_id, $unfiltered = false ) {
   453 	$file = get_post_meta( $attachment_id, '_wp_attached_file', true );
   499 	$file = get_post_meta( $attachment_id, '_wp_attached_file', true );
   454 
   500 
   455 	// If the file is relative, prepend upload dir.
   501 	// If the file is relative, prepend upload dir.
   456 	if ( $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) && ( ( $uploads = wp_get_upload_dir() ) && false === $uploads['error'] ) ) {
   502 	if ( $file && 0 !== strpos( $file, '/' ) && ! preg_match( '|^.:\\\|', $file ) ) {
   457 		$file = $uploads['basedir'] . "/$file";
   503 		$uploads = wp_get_upload_dir();
       
   504 		if ( false === $uploads['error'] ) {
       
   505 			$file = $uploads['basedir'] . "/$file";
       
   506 		}
   458 	}
   507 	}
   459 
   508 
   460 	if ( $unfiltered ) {
   509 	if ( $unfiltered ) {
   461 		return $file;
   510 		return $file;
   462 	}
   511 	}
   464 	/**
   513 	/**
   465 	 * Filters the attached file based on the given ID.
   514 	 * Filters the attached file based on the given ID.
   466 	 *
   515 	 *
   467 	 * @since 2.1.0
   516 	 * @since 2.1.0
   468 	 *
   517 	 *
   469 	 * @param string $file          Path to attached file.
   518 	 * @param string|false $file          The file path to where the attached file should be, false otherwise.
   470 	 * @param int    $attachment_id Attachment ID.
   519 	 * @param int          $attachment_id Attachment ID.
   471 	 */
   520 	 */
   472 	return apply_filters( 'get_attached_file', $file, $attachment_id );
   521 	return apply_filters( 'get_attached_file', $file, $attachment_id );
   473 }
   522 }
   474 
   523 
   475 /**
   524 /**
   497 	 * @param string $file          Path to the attached file to update.
   546 	 * @param string $file          Path to the attached file to update.
   498 	 * @param int    $attachment_id Attachment ID.
   547 	 * @param int    $attachment_id Attachment ID.
   499 	 */
   548 	 */
   500 	$file = apply_filters( 'update_attached_file', $file, $attachment_id );
   549 	$file = apply_filters( 'update_attached_file', $file, $attachment_id );
   501 
   550 
   502 	if ( $file = _wp_relative_upload_path( $file ) ) {
   551 	$file = _wp_relative_upload_path( $file );
       
   552 	if ( $file ) {
   503 		return update_post_meta( $attachment_id, '_wp_attached_file', $file );
   553 		return update_post_meta( $attachment_id, '_wp_attached_file', $file );
   504 	} else {
   554 	} else {
   505 		return delete_post_meta( $attachment_id, '_wp_attached_file' );
   555 		return delete_post_meta( $attachment_id, '_wp_attached_file' );
   506 	}
   556 	}
   507 }
   557 }
   578  * @since 2.0.0
   628  * @since 2.0.0
   579  *
   629  *
   580  * @see get_posts()
   630  * @see get_posts()
   581  * @todo Check validity of description.
   631  * @todo Check validity of description.
   582  *
   632  *
   583  * @global WP_Post $post
   633  * @global WP_Post $post Global post object.
   584  *
   634  *
   585  * @param mixed  $args   Optional. User defined arguments for replacing the defaults. Default empty.
   635  * @param mixed  $args   Optional. User defined arguments for replacing the defaults. Default empty.
   586  * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
   636  * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
   587  *                       a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
   637  *                       correspond to a WP_Post object, an associative array, or a numeric array,
   588  * @return array Array of children, where the type of each element is determined by $output parameter.
   638  *                       respectively. Default OBJECT.
   589  *               Empty array on failure.
   639  * @return WP_Post[]|int[] Array of post objects or post IDs.
   590  */
   640  */
   591 function get_children( $args = '', $output = OBJECT ) {
   641 function get_children( $args = '', $output = OBJECT ) {
   592 	$kids = array();
   642 	$kids = array();
   593 	if ( empty( $args ) ) {
   643 	if ( empty( $args ) ) {
   594 		if ( isset( $GLOBALS['post'] ) ) {
   644 		if ( isset( $GLOBALS['post'] ) ) {
   607 		'post_type'   => 'any',
   657 		'post_type'   => 'any',
   608 		'post_status' => 'any',
   658 		'post_status' => 'any',
   609 		'post_parent' => 0,
   659 		'post_parent' => 0,
   610 	);
   660 	);
   611 
   661 
   612 	$r = wp_parse_args( $args, $defaults );
   662 	$parsed_args = wp_parse_args( $args, $defaults );
   613 
   663 
   614 	$children = get_posts( $r );
   664 	$children = get_posts( $parsed_args );
   615 
   665 
   616 	if ( ! $children ) {
   666 	if ( ! $children ) {
   617 		return $kids;
   667 		return $kids;
   618 	}
   668 	}
   619 
   669 
   620 	if ( ! empty( $r['fields'] ) ) {
   670 	if ( ! empty( $parsed_args['fields'] ) ) {
   621 		return $children;
   671 		return $children;
   622 	}
   672 	}
   623 
   673 
   624 	update_post_cache( $children );
   674 	update_post_cache( $children );
   625 
   675 
   626 	foreach ( $children as $key => $child ) {
   676 	foreach ( $children as $key => $child ) {
   627 		$kids[ $child->ID ] = $children[ $key ];
   677 		$kids[ $child->ID ] = $children[ $key ];
   628 	}
   678 	}
   629 
   679 
   630 	if ( $output == OBJECT ) {
   680 	if ( OBJECT == $output ) {
   631 		return $kids;
   681 		return $kids;
   632 	} elseif ( $output == ARRAY_A ) {
   682 	} elseif ( ARRAY_A == $output ) {
   633 		$weeuns = array();
   683 		$weeuns = array();
   634 		foreach ( (array) $kids as $kid ) {
   684 		foreach ( (array) $kids as $kid ) {
   635 			$weeuns[ $kid->ID ] = get_object_vars( $kids[ $kid->ID ] );
   685 			$weeuns[ $kid->ID ] = get_object_vars( $kids[ $kid->ID ] );
   636 		}
   686 		}
   637 		return $weeuns;
   687 		return $weeuns;
   638 	} elseif ( $output == ARRAY_N ) {
   688 	} elseif ( ARRAY_N == $output ) {
   639 		$babes = array();
   689 		$babes = array();
   640 		foreach ( (array) $kids as $kid ) {
   690 		foreach ( (array) $kids as $kid ) {
   641 			$babes[ $kid->ID ] = array_values( get_object_vars( $kids[ $kid->ID ] ) );
   691 			$babes[ $kid->ID ] = array_values( get_object_vars( $kids[ $kid->ID ] ) );
   642 		}
   692 		}
   643 		return $babes;
   693 		return $babes;
   658  * `<!--more-->` comment. The 'more_text' key has the custom "Read More" text.
   708  * `<!--more-->` comment. The 'more_text' key has the custom "Read More" text.
   659  *
   709  *
   660  * @since 1.0.0
   710  * @since 1.0.0
   661  *
   711  *
   662  * @param string $post Post content.
   712  * @param string $post Post content.
   663  * @return array Post before ('main'), after ('extended'), and custom read more ('more_text').
   713  * @return string[] {
       
   714  *     Extended entry info.
       
   715  *
       
   716  *     @type string $main      Content before the more tag.
       
   717  *     @type string $extended  Content after the more tag.
       
   718  *     @type string $more_text Custom read more text, or empty string.
       
   719  * }
   664  */
   720  */
   665 function get_extended( $post ) {
   721 function get_extended( $post ) {
   666 	//Match the new style more links.
   722 	// Match the new style more links.
   667 	if ( preg_match( '/<!--more(.*?)?-->/', $post, $matches ) ) {
   723 	if ( preg_match( '/<!--more(.*?)?-->/', $post, $matches ) ) {
   668 		list($main, $extended) = explode( $matches[0], $post, 2 );
   724 		list($main, $extended) = explode( $matches[0], $post, 2 );
   669 		$more_text             = $matches[1];
   725 		$more_text             = $matches[1];
   670 	} else {
   726 	} else {
   671 		$main      = $post;
   727 		$main      = $post;
   672 		$extended  = '';
   728 		$extended  = '';
   673 		$more_text = '';
   729 		$more_text = '';
   674 	}
   730 	}
   675 
   731 
   676 	//  leading and trailing whitespace.
   732 	// Leading and trailing whitespace.
   677 	$main      = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $main );
   733 	$main      = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $main );
   678 	$extended  = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $extended );
   734 	$extended  = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $extended );
   679 	$more_text = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $more_text );
   735 	$more_text = preg_replace( '/^[\s]*(.*)[\s]*$/', '\\1', $more_text );
   680 
   736 
   681 	return array(
   737 	return array(
   691  * See sanitize_post() for optional $filter values. Also, the parameter
   747  * See sanitize_post() for optional $filter values. Also, the parameter
   692  * `$post`, must be given as a variable, since it is passed by reference.
   748  * `$post`, must be given as a variable, since it is passed by reference.
   693  *
   749  *
   694  * @since 1.5.1
   750  * @since 1.5.1
   695  *
   751  *
   696  * @global WP_Post $post
   752  * @global WP_Post $post Global post object.
   697  *
   753  *
   698  * @param int|WP_Post|null $post   Optional. Post ID or post object. Defaults to global $post.
   754  * @param int|WP_Post|null $post   Optional. Post ID or post object. Defaults to global $post.
   699  * @param string           $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
   755  * @param string           $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
   700  *                                 a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
   756  *                                 correspond to a WP_Post object, an associative array, or a numeric array,
       
   757  *                                 respectively. Default OBJECT.
   701  * @param string           $filter Optional. Type of filter to apply. Accepts 'raw', 'edit', 'db',
   758  * @param string           $filter Optional. Type of filter to apply. Accepts 'raw', 'edit', 'db',
   702  *                                 or 'display'. Default 'raw'.
   759  *                                 or 'display'. Default 'raw'.
   703  * @return WP_Post|array|null Type corresponding to $output on success or null on failure.
   760  * @return WP_Post|array|null Type corresponding to $output on success or null on failure.
   704  *                            When $output is OBJECT, a `WP_Post` instance is returned.
   761  *                            When $output is OBJECT, a `WP_Post` instance is returned.
   705  */
   762  */
   712 		$_post = $post;
   769 		$_post = $post;
   713 	} elseif ( is_object( $post ) ) {
   770 	} elseif ( is_object( $post ) ) {
   714 		if ( empty( $post->filter ) ) {
   771 		if ( empty( $post->filter ) ) {
   715 			$_post = sanitize_post( $post, 'raw' );
   772 			$_post = sanitize_post( $post, 'raw' );
   716 			$_post = new WP_Post( $_post );
   773 			$_post = new WP_Post( $_post );
   717 		} elseif ( 'raw' == $post->filter ) {
   774 		} elseif ( 'raw' === $post->filter ) {
   718 			$_post = new WP_Post( $post );
   775 			$_post = new WP_Post( $post );
   719 		} else {
   776 		} else {
   720 			$_post = WP_Post::get_instance( $post->ID );
   777 			$_post = WP_Post::get_instance( $post->ID );
   721 		}
   778 		}
   722 	} else {
   779 	} else {
   727 		return null;
   784 		return null;
   728 	}
   785 	}
   729 
   786 
   730 	$_post = $_post->filter( $filter );
   787 	$_post = $_post->filter( $filter );
   731 
   788 
   732 	if ( $output == ARRAY_A ) {
   789 	if ( ARRAY_A == $output ) {
   733 		return $_post->to_array();
   790 		return $_post->to_array();
   734 	} elseif ( $output == ARRAY_N ) {
   791 	} elseif ( ARRAY_N == $output ) {
   735 		return array_values( $_post->to_array() );
   792 		return array_values( $_post->to_array() );
   736 	}
   793 	}
   737 
   794 
   738 	return $_post;
   795 	return $_post;
   739 }
   796 }
   742  * Retrieve ancestors of a post.
   799  * Retrieve ancestors of a post.
   743  *
   800  *
   744  * @since 2.5.0
   801  * @since 2.5.0
   745  *
   802  *
   746  * @param int|WP_Post $post Post ID or post object.
   803  * @param int|WP_Post $post Post ID or post object.
   747  * @return array Ancestor IDs or empty array if none are found.
   804  * @return int[] Ancestor IDs or empty array if none are found.
   748  */
   805  */
   749 function get_post_ancestors( $post ) {
   806 function get_post_ancestors( $post ) {
   750 	$post = get_post( $post );
   807 	$post = get_post( $post );
   751 
   808 
   752 	if ( ! $post || empty( $post->post_parent ) || $post->post_parent == $post->ID ) {
   809 	if ( ! $post || empty( $post->post_parent ) || $post->post_parent == $post->ID ) {
   753 		return array();
   810 		return array();
   754 	}
   811 	}
   755 
   812 
   756 	$ancestors = array();
   813 	$ancestors = array();
   757 
   814 
   758 	$id = $ancestors[] = $post->post_parent;
   815 	$id          = $post->post_parent;
       
   816 	$ancestors[] = $id;
   759 
   817 
   760 	while ( $ancestor = get_post( $id ) ) {
   818 	while ( $ancestor = get_post( $id ) ) {
   761 		// Loop detection: If the ancestor has been seen before, break.
   819 		// Loop detection: If the ancestor has been seen before, break.
   762 		if ( empty( $ancestor->post_parent ) || ( $ancestor->post_parent == $post->ID ) || in_array( $ancestor->post_parent, $ancestors ) ) {
   820 		if ( empty( $ancestor->post_parent ) || ( $ancestor->post_parent == $post->ID ) || in_array( $ancestor->post_parent, $ancestors, true ) ) {
   763 			break;
   821 			break;
   764 		}
   822 		}
   765 
   823 
   766 		$id = $ancestors[] = $ancestor->post_parent;
   824 		$id          = $ancestor->post_parent;
       
   825 		$ancestors[] = $id;
   767 	}
   826 	}
   768 
   827 
   769 	return $ancestors;
   828 	return $ancestors;
   770 }
   829 }
   771 
   830 
   840 
   899 
   841 	if ( ! is_object( $post ) ) {
   900 	if ( ! is_object( $post ) ) {
   842 		return false;
   901 		return false;
   843 	}
   902 	}
   844 
   903 
   845 	if ( 'attachment' == $post->post_type ) {
   904 	if ( 'attachment' === $post->post_type ) {
   846 		if ( 'private' == $post->post_status ) {
   905 		if ( 'private' === $post->post_status ) {
   847 			return 'private';
   906 			return 'private';
   848 		}
   907 		}
   849 
   908 
   850 		// Unattached attachments are assumed to be published.
   909 		// Unattached attachments are assumed to be published.
   851 		if ( ( 'inherit' == $post->post_status ) && ( 0 == $post->post_parent ) ) {
   910 		if ( ( 'inherit' === $post->post_status ) && ( 0 == $post->post_parent ) ) {
   852 			return 'publish';
   911 			return 'publish';
   853 		}
   912 		}
   854 
   913 
   855 		// Inherit status from the parent.
   914 		// Inherit status from the parent.
   856 		if ( $post->post_parent && ( $post->ID != $post->post_parent ) ) {
   915 		if ( $post->post_parent && ( $post->ID != $post->post_parent ) ) {
   857 			$parent_post_status = get_post_status( $post->post_parent );
   916 			$parent_post_status = get_post_status( $post->post_parent );
   858 			if ( 'trash' == $parent_post_status ) {
   917 			if ( 'trash' === $parent_post_status ) {
   859 				return get_post_meta( $post->post_parent, '_wp_trash_meta_status', true );
   918 				return get_post_meta( $post->post_parent, '_wp_trash_meta_status', true );
   860 			} else {
   919 			} else {
   861 				return $parent_post_status;
   920 				return $parent_post_status;
   862 			}
   921 			}
   863 		}
   922 		}
   880  * Posts have a limited set of valid status values, this provides the
   939  * Posts have a limited set of valid status values, this provides the
   881  * post_status values and descriptions.
   940  * post_status values and descriptions.
   882  *
   941  *
   883  * @since 2.5.0
   942  * @since 2.5.0
   884  *
   943  *
   885  * @return array List of post statuses.
   944  * @return string[] Array of post status labels keyed by their status.
   886  */
   945  */
   887 function get_post_statuses() {
   946 function get_post_statuses() {
   888 	$status = array(
   947 	$status = array(
   889 		'draft'   => __( 'Draft' ),
   948 		'draft'   => __( 'Draft' ),
   890 		'pending' => __( 'Pending Review' ),
   949 		'pending' => __( 'Pending Review' ),
   901  * Pages have a limited set of valid status values, this provides the
   960  * Pages have a limited set of valid status values, this provides the
   902  * post_status values and descriptions.
   961  * post_status values and descriptions.
   903  *
   962  *
   904  * @since 2.5.0
   963  * @since 2.5.0
   905  *
   964  *
   906  * @return array List of page statuses.
   965  * @return string[] Array of page status labels keyed by their status.
   907  */
   966  */
   908 function get_page_statuses() {
   967 function get_page_statuses() {
   909 	$status = array(
   968 	$status = array(
   910 		'draft'   => __( 'Draft' ),
   969 		'draft'   => __( 'Draft' ),
   911 		'private' => __( 'Private' ),
   970 		'private' => __( 'Private' ),
   923  *
   982  *
   924  * @return array
   983  * @return array
   925  */
   984  */
   926 function _wp_privacy_statuses() {
   985 function _wp_privacy_statuses() {
   927 	return array(
   986 	return array(
   928 		'request-pending'   => __( 'Pending' ),      // Pending confirmation from user.
   987 		'request-pending'   => _x( 'Pending', 'request status' ),      // Pending confirmation from user.
   929 		'request-confirmed' => __( 'Confirmed' ),    // User has confirmed the action.
   988 		'request-confirmed' => _x( 'Confirmed', 'request status' ),    // User has confirmed the action.
   930 		'request-failed'    => __( 'Failed' ),       // User failed to confirm the action.
   989 		'request-failed'    => _x( 'Failed', 'request status' ),       // User failed to confirm the action.
   931 		'request-completed' => __( 'Completed' ),    // Admin has handled the request.
   990 		'request-completed' => _x( 'Completed', 'request status' ),    // Admin has handled the request.
   932 	);
   991 	);
   933 }
   992 }
   934 
   993 
   935 /**
   994 /**
   936  * Register a post status. Do not use before init.
   995  * Register a post status. Do not use before init.
   940  * parameter), along with a string for the post status name.
   999  * parameter), along with a string for the post status name.
   941  *
  1000  *
   942  * Arguments prefixed with an _underscore shouldn't be used by plugins and themes.
  1001  * Arguments prefixed with an _underscore shouldn't be used by plugins and themes.
   943  *
  1002  *
   944  * @since 3.0.0
  1003  * @since 3.0.0
       
  1004  *
   945  * @global array $wp_post_statuses Inserts new post status object into the list
  1005  * @global array $wp_post_statuses Inserts new post status object into the list
   946  *
  1006  *
   947  * @param string $post_status Name of the post status.
  1007  * @param string       $post_status Name of the post status.
   948  * @param array|string $args {
  1008  * @param array|string $args {
   949  *     Optional. Array or string of post status arguments.
  1009  *     Optional. Array or string of post status arguments.
   950  *
  1010  *
   951  *     @type bool|string $label                     A descriptive name for the post status marked
  1011  *     @type bool|string $label                     A descriptive name for the post status marked
   952  *                                                  for translation. Defaults to value of $post_status.
  1012  *                                                  for translation. Defaults to value of $post_status.
   953  *     @type bool|array  $label_count               Descriptive text to use for nooped plurals.
  1013  *     @type bool|array  $label_count               Descriptive text to use for nooped plurals.
   954  *                                                  Default array of $label, twice
  1014  *                                                  Default array of $label, twice.
   955  *     @type bool        $exclude_from_search       Whether to exclude posts with this post status
  1015  *     @type bool        $exclude_from_search       Whether to exclude posts with this post status
   956  *                                                  from search results. Default is value of $internal.
  1016  *                                                  from search results. Default is value of $internal.
   957  *     @type bool        $_builtin                  Whether the status is built-in. Core-use only.
  1017  *     @type bool        $_builtin                  Whether the status is built-in. Core-use only.
   958  *                                                  Default false.
  1018  *                                                  Default false.
   959  *     @type bool        $public                    Whether posts of this status should be shown
  1019  *     @type bool        $public                    Whether posts of this status should be shown
   965  *     @type bool        $private                   Whether posts with this status should be private.
  1025  *     @type bool        $private                   Whether posts with this status should be private.
   966  *                                                  Default false.
  1026  *                                                  Default false.
   967  *     @type bool        $publicly_queryable        Whether posts with this status should be publicly-
  1027  *     @type bool        $publicly_queryable        Whether posts with this status should be publicly-
   968  *                                                  queryable. Default is value of $public.
  1028  *                                                  queryable. Default is value of $public.
   969  *     @type bool        $show_in_admin_all_list    Whether to include posts in the edit listing for
  1029  *     @type bool        $show_in_admin_all_list    Whether to include posts in the edit listing for
   970  *                                                  their post type. Default is value of $internal.
  1030  *                                                  their post type. Default is the opposite value
       
  1031  *                                                  of $internal.
   971  *     @type bool        $show_in_admin_status_list Show in the list of statuses with post counts at
  1032  *     @type bool        $show_in_admin_status_list Show in the list of statuses with post counts at
   972  *                                                  the top of the edit listings,
  1033  *                                                  the top of the edit listings,
   973  *                                                  e.g. All (12) | Published (9) | My Custom Status (2)
  1034  *                                                  e.g. All (12) | Published (9) | My Custom Status (2)
   974  *                                                  Default is value of $internal.
  1035  *                                                  Default is the opposite value of $internal.
       
  1036  *     @type bool        $date_floating             Whether the post has a floating creation date.
       
  1037  *                                                  Default to false.
   975  * }
  1038  * }
   976  * @return object
  1039  * @return object
   977  */
  1040  */
   978 function register_post_status( $post_status, $args = array() ) {
  1041 function register_post_status( $post_status, $args = array() ) {
   979 	global $wp_post_statuses;
  1042 	global $wp_post_statuses;
   993 		'protected'                 => null,
  1056 		'protected'                 => null,
   994 		'private'                   => null,
  1057 		'private'                   => null,
   995 		'publicly_queryable'        => null,
  1058 		'publicly_queryable'        => null,
   996 		'show_in_admin_status_list' => null,
  1059 		'show_in_admin_status_list' => null,
   997 		'show_in_admin_all_list'    => null,
  1060 		'show_in_admin_all_list'    => null,
       
  1061 		'date_floating'             => null,
   998 	);
  1062 	);
   999 	$args     = wp_parse_args( $args, $defaults );
  1063 	$args     = wp_parse_args( $args, $defaults );
  1000 	$args     = (object) $args;
  1064 	$args     = (object) $args;
  1001 
  1065 
  1002 	$post_status = sanitize_key( $post_status );
  1066 	$post_status = sanitize_key( $post_status );
  1035 		$args->show_in_admin_all_list = ! $args->internal;
  1099 		$args->show_in_admin_all_list = ! $args->internal;
  1036 	}
  1100 	}
  1037 
  1101 
  1038 	if ( null === $args->show_in_admin_status_list ) {
  1102 	if ( null === $args->show_in_admin_status_list ) {
  1039 		$args->show_in_admin_status_list = ! $args->internal;
  1103 		$args->show_in_admin_status_list = ! $args->internal;
       
  1104 	}
       
  1105 
       
  1106 	if ( null === $args->date_floating ) {
       
  1107 		$args->date_floating = false;
  1040 	}
  1108 	}
  1041 
  1109 
  1042 	if ( false === $args->label ) {
  1110 	if ( false === $args->label ) {
  1043 		$args->label = $post_status;
  1111 		$args->label = $post_status;
  1044 	}
  1112 	}
  1093  * @return array A list of post status names or objects.
  1161  * @return array A list of post status names or objects.
  1094  */
  1162  */
  1095 function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) {
  1163 function get_post_stati( $args = array(), $output = 'names', $operator = 'and' ) {
  1096 	global $wp_post_statuses;
  1164 	global $wp_post_statuses;
  1097 
  1165 
  1098 	$field = ( 'names' == $output ) ? 'name' : false;
  1166 	$field = ( 'names' === $output ) ? 'name' : false;
  1099 
  1167 
  1100 	return wp_filter_object_list( $wp_post_statuses, $args, $operator, $field );
  1168 	return wp_filter_object_list( $wp_post_statuses, $args, $operator, $field );
  1101 }
  1169 }
  1102 
  1170 
  1103 /**
  1171 /**
  1146  *
  1214  *
  1147  * @param int|WP_Post|null $post Optional. Post ID or post object. Default is global $post.
  1215  * @param int|WP_Post|null $post Optional. Post ID or post object. Default is global $post.
  1148  * @return string|false          Post type on success, false on failure.
  1216  * @return string|false          Post type on success, false on failure.
  1149  */
  1217  */
  1150 function get_post_type( $post = null ) {
  1218 function get_post_type( $post = null ) {
  1151 	if ( $post = get_post( $post ) ) {
  1219 	$post = get_post( $post );
       
  1220 	if ( $post ) {
  1152 		return $post->post_type;
  1221 		return $post->post_type;
  1153 	}
  1222 	}
  1154 
  1223 
  1155 	return false;
  1224 	return false;
  1156 }
  1225 }
  1197  * @return string[]|WP_Post_Type[] An array of post type names or objects.
  1266  * @return string[]|WP_Post_Type[] An array of post type names or objects.
  1198  */
  1267  */
  1199 function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) {
  1268 function get_post_types( $args = array(), $output = 'names', $operator = 'and' ) {
  1200 	global $wp_post_types;
  1269 	global $wp_post_types;
  1201 
  1270 
  1202 	$field = ( 'names' == $output ) ? 'name' : false;
  1271 	$field = ( 'names' === $output ) ? 'name' : false;
  1203 
  1272 
  1204 	return wp_filter_object_list( $wp_post_types, $args, $operator, $field );
  1273 	return wp_filter_object_list( $wp_post_types, $args, $operator, $field );
  1205 }
  1274 }
  1206 
  1275 
  1207 /**
  1276 /**
  1223  * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing
  1292  * @since 4.4.0 The `show_ui` argument is now enforced on the post type listing
  1224  *              screen and post editing screen.
  1293  *              screen and post editing screen.
  1225  * @since 4.6.0 Post type object returned is now an instance of `WP_Post_Type`.
  1294  * @since 4.6.0 Post type object returned is now an instance of `WP_Post_Type`.
  1226  * @since 4.7.0 Introduced `show_in_rest`, `rest_base` and `rest_controller_class`
  1295  * @since 4.7.0 Introduced `show_in_rest`, `rest_base` and `rest_controller_class`
  1227  *              arguments to register the post type in REST API.
  1296  *              arguments to register the post type in REST API.
  1228  *
  1297  * @since 5.3.0 The `supports` argument will now accept an array of arguments for a feature.
       
  1298  * .
  1229  * @global array $wp_post_types List of post types.
  1299  * @global array $wp_post_types List of post types.
  1230  *
  1300  *
  1231  * @param string $post_type Post type key. Must not exceed 20 characters and may
  1301  * @param string       $post_type Post type key. Must not exceed 20 characters and may
  1232  *                          only contain lowercase alphanumeric characters, dashes,
  1302  *                                only contain lowercase alphanumeric characters, dashes,
  1233  *                          and underscores. See sanitize_key().
  1303  *                                and underscores. See sanitize_key().
  1234  * @param array|string $args {
  1304  * @param array|string $args {
  1235  *     Array or string of arguments for registering a post type.
  1305  *     Array or string of arguments for registering a post type.
  1236  *
  1306  *
  1237  *     @type string      $label                 Name of the post type shown in the menu. Usually plural.
  1307  *     @type string      $label                 Name of the post type shown in the menu. Usually plural.
  1238  *                                              Default is value of $labels['name'].
  1308  *                                              Default is value of $labels['name'].
  1257  *                                              * ?{post_type_key}={single_post_slug}
  1327  *                                              * ?{post_type_key}={single_post_slug}
  1258  *                                              * ?{post_type_query_var}={single_post_slug}
  1328  *                                              * ?{post_type_query_var}={single_post_slug}
  1259  *                                              If not set, the default is inherited from $public.
  1329  *                                              If not set, the default is inherited from $public.
  1260  *     @type bool        $show_ui               Whether to generate and allow a UI for managing this post type in the
  1330  *     @type bool        $show_ui               Whether to generate and allow a UI for managing this post type in the
  1261  *                                              admin. Default is value of $public.
  1331  *                                              admin. Default is value of $public.
  1262  *     @type bool        $show_in_menu          Where to show the post type in the admin menu. To work, $show_ui
  1332  *     @type bool|string $show_in_menu          Where to show the post type in the admin menu. To work, $show_ui
  1263  *                                              must be true. If true, the post type is shown in its own top level
  1333  *                                              must be true. If true, the post type is shown in its own top level
  1264  *                                              menu. If false, no menu is shown. If a string of an existing top
  1334  *                                              menu. If false, no menu is shown. If a string of an existing top
  1265  *                                              level menu (eg. 'tools.php' or 'edit.php?post_type=page'), the post
  1335  *                                              level menu (eg. 'tools.php' or 'edit.php?post_type=page'), the post
  1266  *                                              type will be placed as a sub-menu of that.
  1336  *                                              type will be placed as a sub-menu of that.
  1267  *                                              Default is value of $show_ui.
  1337  *                                              Default is value of $show_ui.
  1268  *     @type bool        $show_in_nav_menus     Makes this post type available for selection in navigation menus.
  1338  *     @type bool        $show_in_nav_menus     Makes this post type available for selection in navigation menus.
  1269  *                                              Default is value $public.
  1339  *                                              Default is value of $public.
  1270  *     @type bool        $show_in_admin_bar     Makes this post type available via the admin bar. Default is value
  1340  *     @type bool        $show_in_admin_bar     Makes this post type available via the admin bar. Default is value
  1271  *                                              of $show_in_menu.
  1341  *                                              of $show_in_menu.
  1272  *     @type bool        $show_in_rest          Whether to add the post type route in the REST API 'wp/v2' namespace.
  1342  *     @type bool        $show_in_rest          Whether to include the post type in the REST API. Set this to true
       
  1343  *                                              for the post type to be available in the block editor.
  1273  *     @type string      $rest_base             To change the base url of REST API route. Default is $post_type.
  1344  *     @type string      $rest_base             To change the base url of REST API route. Default is $post_type.
  1274  *     @type string      $rest_controller_class REST API Controller class name. Default is 'WP_REST_Posts_Controller'.
  1345  *     @type string      $rest_controller_class REST API Controller class name. Default is 'WP_REST_Posts_Controller'.
  1275  *     @type int         $menu_position         The position in the menu order the post type should appear. To work,
  1346  *     @type int         $menu_position         The position in the menu order the post type should appear. To work,
  1276  *                                              $show_in_menu must be true. Default null (at the bottom).
  1347  *                                              $show_in_menu must be true. Default null (at the bottom).
  1277  *     @type string      $menu_icon             The url to the icon to be used for this menu. Pass a base64-encoded
  1348  *     @type string      $menu_icon             The url to the icon to be used for this menu. Pass a base64-encoded
  1293  *                                              add_post_type_support() directly. Core features include 'title',
  1364  *                                              add_post_type_support() directly. Core features include 'title',
  1294  *                                              'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt',
  1365  *                                              'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt',
  1295  *                                              'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'.
  1366  *                                              'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'.
  1296  *                                              Additionally, the 'revisions' feature dictates whether the post type
  1367  *                                              Additionally, the 'revisions' feature dictates whether the post type
  1297  *                                              will store revisions, and the 'comments' feature dictates whether the
  1368  *                                              will store revisions, and the 'comments' feature dictates whether the
  1298  *                                              comments count will show on the edit screen. Defaults is an array
  1369  *                                              comments count will show on the edit screen. A feature can also be
  1299  *                                              containing 'title' and 'editor'.
  1370  *                                              specified as an array of arguments to provide additional information
       
  1371  *                                              about supporting that feature.
       
  1372  *                                              Example: `array( 'my_feature', array( 'field' => 'value' ) )`.
       
  1373  *                                              Default is an array containing 'title' and 'editor'.
  1300  *     @type callable    $register_meta_box_cb  Provide a callback function that sets up the meta boxes for the
  1374  *     @type callable    $register_meta_box_cb  Provide a callback function that sets up the meta boxes for the
  1301  *                                              edit form. Do remove_meta_box() and add_meta_box() calls in the
  1375  *                                              edit form. Do remove_meta_box() and add_meta_box() calls in the
  1302  *                                              callback. Default null.
  1376  *                                              callback. Default null.
  1303  *     @type array       $taxonomies            An array of taxonomy identifiers that will be registered for the
  1377  *     @type array       $taxonomies            An array of taxonomy identifiers that will be registered for the
  1304  *                                              post type. Taxonomies can be registered later with register_taxonomy()
  1378  *                                              post type. Taxonomies can be registered later with register_taxonomy()
  1326  *                                              key. If false, a post type cannot be loaded at
  1400  *                                              key. If false, a post type cannot be loaded at
  1327  *                                              ?{query_var}={post_slug}. If specified as a string, the query
  1401  *                                              ?{query_var}={post_slug}. If specified as a string, the query
  1328  *                                              ?{query_var_string}={post_slug} will be valid.
  1402  *                                              ?{query_var_string}={post_slug} will be valid.
  1329  *     @type bool        $can_export            Whether to allow this post type to be exported. Default true.
  1403  *     @type bool        $can_export            Whether to allow this post type to be exported. Default true.
  1330  *     @type bool        $delete_with_user      Whether to delete posts of this type when deleting a user. If true,
  1404  *     @type bool        $delete_with_user      Whether to delete posts of this type when deleting a user. If true,
  1331  *                                              posts of this type belonging to the user will be moved to trash
  1405  *                                              posts of this type belonging to the user will be moved to Trash
  1332  *                                              when then user is deleted. If false, posts of this type belonging
  1406  *                                              when then user is deleted. If false, posts of this type belonging
  1333  *                                              to the user will *not* be trashed or deleted. If not set (the default),
  1407  *                                              to the user will *not* be trashed or deleted. If not set (the default),
  1334  *                                              posts are trashed if post_type_supports('author'). Otherwise posts
  1408  *                                              posts are trashed if post_type_supports('author'). Otherwise posts
  1335  *                                              are not trashed or deleted. Default null.
  1409  *                                              are not trashed or deleted. Default null.
  1336  *     @type bool        $_builtin              FOR INTERNAL USE ONLY! True if this post type is a native or
  1410  *     @type bool        $_builtin              FOR INTERNAL USE ONLY! True if this post type is a native or
  1337  *                                              "built-in" post_type. Default false.
  1411  *                                              "built-in" post_type. Default false.
  1338  *     @type string      $_edit_link            FOR INTERNAL USE ONLY! URL segment to use for edit link of
  1412  *     @type string      $_edit_link            FOR INTERNAL USE ONLY! URL segment to use for edit link of
  1339  *                                              this post type. Default 'post.php?post=%d'.
  1413  *                                              this post type. Default 'post.php?post=%d'.
  1340  * }
  1414  * }
  1341  * @return WP_Post_Type|WP_Error The registered post type object, or an error object.
  1415  * @return WP_Post_Type|WP_Error The registered post type object on success,
       
  1416  *                               WP_Error object on failure.
  1342  */
  1417  */
  1343 function register_post_type( $post_type, $args = array() ) {
  1418 function register_post_type( $post_type, $args = array() ) {
  1344 	global $wp_post_types;
  1419 	global $wp_post_types;
  1345 
  1420 
  1346 	if ( ! is_array( $wp_post_types ) ) {
  1421 	if ( ! is_array( $wp_post_types ) ) {
  1347 		$wp_post_types = array();
  1422 		$wp_post_types = array();
  1348 	}
  1423 	}
  1349 
  1424 
  1350 	// Sanitize post type name
  1425 	// Sanitize post type name.
  1351 	$post_type = sanitize_key( $post_type );
  1426 	$post_type = sanitize_key( $post_type );
  1352 
  1427 
  1353 	if ( empty( $post_type ) || strlen( $post_type ) > 20 ) {
  1428 	if ( empty( $post_type ) || strlen( $post_type ) > 20 ) {
  1354 		_doing_it_wrong( __FUNCTION__, __( 'Post type names must be between 1 and 20 characters in length.' ), '4.2.0' );
  1429 		_doing_it_wrong( __FUNCTION__, __( 'Post type names must be between 1 and 20 characters in length.' ), '4.2.0' );
  1355 		return new WP_Error( 'post_type_length_invalid', __( 'Post type names must be between 1 and 20 characters in length.' ) );
  1430 		return new WP_Error( 'post_type_length_invalid', __( 'Post type names must be between 1 and 20 characters in length.' ) );
  1435  * The capability_type argument can optionally be registered as an array, with
  1510  * The capability_type argument can optionally be registered as an array, with
  1436  * the first value being singular and the second plural, e.g. array('story, 'stories')
  1511  * the first value being singular and the second plural, e.g. array('story, 'stories')
  1437  * Otherwise, an 's' will be added to the value for the plural form. After
  1512  * Otherwise, an 's' will be added to the value for the plural form. After
  1438  * registration, capability_type will always be a string of the singular value.
  1513  * registration, capability_type will always be a string of the singular value.
  1439  *
  1514  *
  1440  * By default, seven keys are accepted as part of the capabilities array:
  1515  * By default, eight keys are accepted as part of the capabilities array:
  1441  *
  1516  *
  1442  * - edit_post, read_post, and delete_post are meta capabilities, which are then
  1517  * - edit_post, read_post, and delete_post are meta capabilities, which are then
  1443  *   generally mapped to corresponding primitive capabilities depending on the
  1518  *   generally mapped to corresponding primitive capabilities depending on the
  1444  *   context, which would be the post being edited/read/deleted and the user or
  1519  *   context, which would be the post being edited/read/deleted and the user or
  1445  *   role being checked. Thus these capabilities would generally not be granted
  1520  *   role being checked. Thus these capabilities would generally not be granted
  1447  *
  1522  *
  1448  * - edit_posts - Controls whether objects of this post type can be edited.
  1523  * - edit_posts - Controls whether objects of this post type can be edited.
  1449  * - edit_others_posts - Controls whether objects of this type owned by other users
  1524  * - edit_others_posts - Controls whether objects of this type owned by other users
  1450  *   can be edited. If the post type does not support an author, then this will
  1525  *   can be edited. If the post type does not support an author, then this will
  1451  *   behave like edit_posts.
  1526  *   behave like edit_posts.
       
  1527  * - delete_posts - Controls whether objects of this post type can be deleted.
  1452  * - publish_posts - Controls publishing objects of this post type.
  1528  * - publish_posts - Controls publishing objects of this post type.
  1453  * - read_private_posts - Controls whether private objects can be read.
  1529  * - read_private_posts - Controls whether private objects can be read.
  1454  *
  1530  *
  1455  * These four primitive capabilities are checked in core in various locations.
  1531  * These five primitive capabilities are checked in core in various locations.
  1456  * There are also seven other primitive capabilities which are not referenced
  1532  * There are also six other primitive capabilities which are not referenced
  1457  * directly in core, except in map_meta_cap(), which takes the three aforementioned
  1533  * directly in core, except in map_meta_cap(), which takes the three aforementioned
  1458  * meta capabilities and translates them into one or more primitive capabilities
  1534  * meta capabilities and translates them into one or more primitive capabilities
  1459  * that must then be checked against the user or role, depending on the context.
  1535  * that must then be checked against the user or role, depending on the context.
  1460  *
  1536  *
  1461  * - read - Controls whether objects of this post type can be read.
  1537  * - read - Controls whether objects of this post type can be read.
  1462  * - delete_posts - Controls whether objects of this post type can be deleted.
       
  1463  * - delete_private_posts - Controls whether private objects can be deleted.
  1538  * - delete_private_posts - Controls whether private objects can be deleted.
  1464  * - delete_published_posts - Controls whether published objects can be deleted.
  1539  * - delete_published_posts - Controls whether published objects can be deleted.
  1465  * - delete_others_posts - Controls whether objects owned by other users can be
  1540  * - delete_others_posts - Controls whether objects owned by other users can be
  1466  *   can be deleted. If the post type does not support an author, then this will
  1541  *   can be deleted. If the post type does not support an author, then this will
  1467  *   behave like delete_posts.
  1542  *   behave like delete_posts.
  1471  * These additional capabilities are only used in map_meta_cap(). Thus, they are
  1546  * These additional capabilities are only used in map_meta_cap(). Thus, they are
  1472  * only assigned by default if the post type is registered with the 'map_meta_cap'
  1547  * only assigned by default if the post type is registered with the 'map_meta_cap'
  1473  * argument set to true (default is false).
  1548  * argument set to true (default is false).
  1474  *
  1549  *
  1475  * @since 3.0.0
  1550  * @since 3.0.0
       
  1551  * @since 5.4.0 'delete_posts' is included in default capabilities.
  1476  *
  1552  *
  1477  * @see register_post_type()
  1553  * @see register_post_type()
  1478  * @see map_meta_cap()
  1554  * @see map_meta_cap()
  1479  *
  1555  *
  1480  * @param object $args Post type registration arguments.
  1556  * @param object $args Post type registration arguments.
  1487 
  1563 
  1488 	// Singular base for meta capabilities, plural base for primitive capabilities.
  1564 	// Singular base for meta capabilities, plural base for primitive capabilities.
  1489 	list( $singular_base, $plural_base ) = $args->capability_type;
  1565 	list( $singular_base, $plural_base ) = $args->capability_type;
  1490 
  1566 
  1491 	$default_capabilities = array(
  1567 	$default_capabilities = array(
  1492 		// Meta capabilities
  1568 		// Meta capabilities.
  1493 		'edit_post'          => 'edit_' . $singular_base,
  1569 		'edit_post'          => 'edit_' . $singular_base,
  1494 		'read_post'          => 'read_' . $singular_base,
  1570 		'read_post'          => 'read_' . $singular_base,
  1495 		'delete_post'        => 'delete_' . $singular_base,
  1571 		'delete_post'        => 'delete_' . $singular_base,
  1496 		// Primitive capabilities used outside of map_meta_cap():
  1572 		// Primitive capabilities used outside of map_meta_cap():
  1497 		'edit_posts'         => 'edit_' . $plural_base,
  1573 		'edit_posts'         => 'edit_' . $plural_base,
  1498 		'edit_others_posts'  => 'edit_others_' . $plural_base,
  1574 		'edit_others_posts'  => 'edit_others_' . $plural_base,
       
  1575 		'delete_posts'       => 'delete_' . $plural_base,
  1499 		'publish_posts'      => 'publish_' . $plural_base,
  1576 		'publish_posts'      => 'publish_' . $plural_base,
  1500 		'read_private_posts' => 'read_private_' . $plural_base,
  1577 		'read_private_posts' => 'read_private_' . $plural_base,
  1501 	);
  1578 	);
  1502 
  1579 
  1503 	// Primitive capabilities used within map_meta_cap():
  1580 	// Primitive capabilities used within map_meta_cap():
  1504 	if ( $args->map_meta_cap ) {
  1581 	if ( $args->map_meta_cap ) {
  1505 		$default_capabilities_for_mapping = array(
  1582 		$default_capabilities_for_mapping = array(
  1506 			'read'                   => 'read',
  1583 			'read'                   => 'read',
  1507 			'delete_posts'           => 'delete_' . $plural_base,
       
  1508 			'delete_private_posts'   => 'delete_private_' . $plural_base,
  1584 			'delete_private_posts'   => 'delete_private_' . $plural_base,
  1509 			'delete_published_posts' => 'delete_published_' . $plural_base,
  1585 			'delete_published_posts' => 'delete_published_' . $plural_base,
  1510 			'delete_others_posts'    => 'delete_others_' . $plural_base,
  1586 			'delete_others_posts'    => 'delete_others_' . $plural_base,
  1511 			'edit_private_posts'     => 'edit_private_' . $plural_base,
  1587 			'edit_private_posts'     => 'edit_private_' . $plural_base,
  1512 			'edit_published_posts'   => 'edit_published_' . $plural_base,
  1588 			'edit_published_posts'   => 'edit_published_' . $plural_base,
  1535  * @since 3.1.0
  1611  * @since 3.1.0
  1536  * @access private
  1612  * @access private
  1537  *
  1613  *
  1538  * @global array $post_type_meta_caps Used to store meta capabilities.
  1614  * @global array $post_type_meta_caps Used to store meta capabilities.
  1539  *
  1615  *
  1540  * @param array $capabilities Post type meta capabilities.
  1616  * @param string[] $capabilities Post type meta capabilities.
  1541  */
  1617  */
  1542 function _post_type_meta_capabilities( $capabilities = null ) {
  1618 function _post_type_meta_capabilities( $capabilities = null ) {
  1543 	global $post_type_meta_caps;
  1619 	global $post_type_meta_caps;
  1544 
  1620 
  1545 	foreach ( $capabilities as $core => $custom ) {
  1621 	foreach ( $capabilities as $core => $custom ) {
  1546 		if ( in_array( $core, array( 'read_post', 'delete_post', 'edit_post' ) ) ) {
  1622 		if ( in_array( $core, array( 'read_post', 'delete_post', 'edit_post' ), true ) ) {
  1547 			$post_type_meta_caps[ $custom ] = $core;
  1623 			$post_type_meta_caps[ $custom ] = $core;
  1548 		}
  1624 		}
  1549 	}
  1625 	}
  1550 }
  1626 }
  1551 
  1627 
  1556  *
  1632  *
  1557  * - `name` - General name for the post type, usually plural. The same and overridden
  1633  * - `name` - General name for the post type, usually plural. The same and overridden
  1558  *          by `$post_type_object->label`. Default is 'Posts' / 'Pages'.
  1634  *          by `$post_type_object->label`. Default is 'Posts' / 'Pages'.
  1559  * - `singular_name` - Name for one object of this post type. Default is 'Post' / 'Page'.
  1635  * - `singular_name` - Name for one object of this post type. Default is 'Post' / 'Page'.
  1560  * - `add_new` - Default is 'Add New' for both hierarchical and non-hierarchical types.
  1636  * - `add_new` - Default is 'Add New' for both hierarchical and non-hierarchical types.
  1561  *             When internationalizing this string, please use a {@link https://codex.wordpress.org/I18n_for_WordPress_Developers#Disambiguation_by_context gettext context}
  1637  *             When internationalizing this string, please use a {@link https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/#disambiguation-by-context gettext context}
  1562  *             matching your post type. Example: `_x( 'Add New', 'product', 'textdomain' );`.
  1638  *             matching your post type. Example: `_x( 'Add New', 'product', 'textdomain' );`.
  1563  * - `add_new_item` - Label for adding a new singular item. Default is 'Add New Post' / 'Add New Page'.
  1639  * - `add_new_item` - Label for adding a new singular item. Default is 'Add New Post' / 'Add New Page'.
  1564  * - `edit_item` - Label for editing a singular item. Default is 'Edit Post' / 'Edit Page'.
  1640  * - `edit_item` - Label for editing a singular item. Default is 'Edit Post' / 'Edit Page'.
  1565  * - `new_item` - Label for the new item page title. Default is 'New Post' / 'New Page'.
  1641  * - `new_item` - Label for the new item page title. Default is 'New Post' / 'New Page'.
  1566  * - `view_item` - Label for viewing a singular item. Default is 'View Post' / 'View Page'.
  1642  * - `view_item` - Label for viewing a singular item. Default is 'View Post' / 'View Page'.
  1567  * - `view_items` - Label for viewing post type archives. Default is 'View Posts' / 'View Pages'.
  1643  * - `view_items` - Label for viewing post type archives. Default is 'View Posts' / 'View Pages'.
  1568  * - `search_items` - Label for searching plural items. Default is 'Search Posts' / 'Search Pages'.
  1644  * - `search_items` - Label for searching plural items. Default is 'Search Posts' / 'Search Pages'.
  1569  * - `not_found` - Label used when no items are found. Default is 'No posts found' / 'No pages found'.
  1645  * - `not_found` - Label used when no items are found. Default is 'No posts found' / 'No pages found'.
  1570  * - `not_found_in_trash` - Label used when no items are in the trash. Default is 'No posts found in Trash' /
  1646  * - `not_found_in_trash` - Label used when no items are in the Trash. Default is 'No posts found in Trash' /
  1571  *                        'No pages found in Trash'.
  1647  *                        'No pages found in Trash'.
  1572  * - `parent_item_colon` - Label used to prefix parents of hierarchical items. Not used on non-hierarchical
  1648  * - `parent_item_colon` - Label used to prefix parents of hierarchical items. Not used on non-hierarchical
  1573  *                       post types. Default is 'Parent Page:'.
  1649  *                       post types. Default is 'Parent Page:'.
  1574  * - `all_items` - Label to signify all items in a submenu link. Default is 'All Posts' / 'All Pages'.
  1650  * - `all_items` - Label to signify all items in a submenu link. Default is 'All Posts' / 'All Pages'.
  1575  * - `archives` - Label for archives in nav menus. Default is 'Post Archives' / 'Page Archives'.
  1651  * - `archives` - Label for archives in nav menus. Default is 'Post Archives' / 'Page Archives'.
  1576  * - `attributes` - Label for the attributes meta box. Default is 'Post Attributes' / 'Page Attributes'.
  1652  * - `attributes` - Label for the attributes meta box. Default is 'Post Attributes' / 'Page Attributes'.
  1577  * - `insert_into_item` - Label for the media frame button. Default is 'Insert into post' / 'Insert into page'.
  1653  * - `insert_into_item` - Label for the media frame button. Default is 'Insert into post' / 'Insert into page'.
  1578  * - `uploaded_to_this_item` - Label for the media frame filter. Default is 'Uploaded to this post' /
  1654  * - `uploaded_to_this_item` - Label for the media frame filter. Default is 'Uploaded to this post' /
  1579  *                           'Uploaded to this page'.
  1655  *                           'Uploaded to this page'.
  1580  * - `featured_image` - Label for the Featured Image meta box title. Default is 'Featured Image'.
  1656  * - `featured_image` - Label for the featured image meta box title. Default is 'Featured image'.
  1581  * - `set_featured_image` - Label for setting the featured image. Default is 'Set featured image'.
  1657  * - `set_featured_image` - Label for setting the featured image. Default is 'Set featured image'.
  1582  * - `remove_featured_image` - Label for removing the featured image. Default is 'Remove featured image'.
  1658  * - `remove_featured_image` - Label for removing the featured image. Default is 'Remove featured image'.
  1583  * - `use_featured_image` - Label in the media frame for using a featured image. Default is 'Use as featured image'.
  1659  * - `use_featured_image` - Label in the media frame for using a featured image. Default is 'Use as featured image'.
  1584  * - `menu_name` - Label for the menu name. Default is the same as `name`.
  1660  * - `menu_name` - Label for the menu name. Default is the same as `name`.
  1585  * - `filter_items_list` - Label for the table views hidden heading. Default is 'Filter posts list' /
  1661  * - `filter_items_list` - Label for the table views hidden heading. Default is 'Filter posts list' /
  1633 		'all_items'                => array( __( 'All Posts' ), __( 'All Pages' ) ),
  1709 		'all_items'                => array( __( 'All Posts' ), __( 'All Pages' ) ),
  1634 		'archives'                 => array( __( 'Post Archives' ), __( 'Page Archives' ) ),
  1710 		'archives'                 => array( __( 'Post Archives' ), __( 'Page Archives' ) ),
  1635 		'attributes'               => array( __( 'Post Attributes' ), __( 'Page Attributes' ) ),
  1711 		'attributes'               => array( __( 'Post Attributes' ), __( 'Page Attributes' ) ),
  1636 		'insert_into_item'         => array( __( 'Insert into post' ), __( 'Insert into page' ) ),
  1712 		'insert_into_item'         => array( __( 'Insert into post' ), __( 'Insert into page' ) ),
  1637 		'uploaded_to_this_item'    => array( __( 'Uploaded to this post' ), __( 'Uploaded to this page' ) ),
  1713 		'uploaded_to_this_item'    => array( __( 'Uploaded to this post' ), __( 'Uploaded to this page' ) ),
  1638 		'featured_image'           => array( _x( 'Featured Image', 'post' ), _x( 'Featured Image', 'page' ) ),
  1714 		'featured_image'           => array( _x( 'Featured image', 'post' ), _x( 'Featured image', 'page' ) ),
  1639 		'set_featured_image'       => array( _x( 'Set featured image', 'post' ), _x( 'Set featured image', 'page' ) ),
  1715 		'set_featured_image'       => array( _x( 'Set featured image', 'post' ), _x( 'Set featured image', 'page' ) ),
  1640 		'remove_featured_image'    => array( _x( 'Remove featured image', 'post' ), _x( 'Remove featured image', 'page' ) ),
  1716 		'remove_featured_image'    => array( _x( 'Remove featured image', 'post' ), _x( 'Remove featured image', 'page' ) ),
  1641 		'use_featured_image'       => array( _x( 'Use as featured image', 'post' ), _x( 'Use as featured image', 'page' ) ),
  1717 		'use_featured_image'       => array( _x( 'Use as featured image', 'post' ), _x( 'Use as featured image', 'page' ) ),
  1642 		'filter_items_list'        => array( __( 'Filter posts list' ), __( 'Filter pages list' ) ),
  1718 		'filter_items_list'        => array( __( 'Filter posts list' ), __( 'Filter pages list' ) ),
  1643 		'items_list_navigation'    => array( __( 'Posts list navigation' ), __( 'Pages list navigation' ) ),
  1719 		'items_list_navigation'    => array( __( 'Posts list navigation' ), __( 'Pages list navigation' ) ),
  1732  */
  1808  */
  1733 function _add_post_type_submenus() {
  1809 function _add_post_type_submenus() {
  1734 	foreach ( get_post_types( array( 'show_ui' => true ) ) as $ptype ) {
  1810 	foreach ( get_post_types( array( 'show_ui' => true ) ) as $ptype ) {
  1735 		$ptype_obj = get_post_type_object( $ptype );
  1811 		$ptype_obj = get_post_type_object( $ptype );
  1736 		// Sub-menus only.
  1812 		// Sub-menus only.
  1737 		if ( ! $ptype_obj->show_in_menu || $ptype_obj->show_in_menu === true ) {
  1813 		if ( ! $ptype_obj->show_in_menu || true === $ptype_obj->show_in_menu ) {
  1738 			continue;
  1814 			continue;
  1739 		}
  1815 		}
  1740 		add_submenu_page( $ptype_obj->show_in_menu, $ptype_obj->labels->name, $ptype_obj->labels->all_items, $ptype_obj->cap->edit_posts, "edit.php?post_type=$ptype" );
  1816 		add_submenu_page( $ptype_obj->show_in_menu, $ptype_obj->labels->name, $ptype_obj->labels->all_items, $ptype_obj->cap->edit_posts, "edit.php?post_type=$ptype" );
  1741 	}
  1817 	}
  1742 }
  1818 }
  1743 
  1819 
  1744 /**
  1820 /**
  1745  * Register support of certain features for a post type.
  1821  * Registers support of certain features for a post type.
  1746  *
  1822  *
  1747  * All core features are directly associated with a functional area of the edit
  1823  * All core features are directly associated with a functional area of the edit
  1748  * screen, such as the editor or a meta box. Features include: 'title', 'editor',
  1824  * screen, such as the editor or a meta box. Features include: 'title', 'editor',
  1749  * 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes',
  1825  * 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', 'page-attributes',
  1750  * 'thumbnail', 'custom-fields', and 'post-formats'.
  1826  * 'thumbnail', 'custom-fields', and 'post-formats'.
  1751  *
  1827  *
  1752  * Additionally, the 'revisions' feature dictates whether the post type will
  1828  * Additionally, the 'revisions' feature dictates whether the post type will
  1753  * store revisions, and the 'comments' feature dictates whether the comments
  1829  * store revisions, and the 'comments' feature dictates whether the comments
  1754  * count will show on the edit screen.
  1830  * count will show on the edit screen.
  1755  *
  1831  *
       
  1832  * A third, optional parameter can also be passed along with a feature to provide
       
  1833  * additional information about supporting that feature.
       
  1834  *
       
  1835  * Example usage:
       
  1836  *
       
  1837  *     add_post_type_support( 'my_post_type', 'comments' );
       
  1838  *     add_post_type_support( 'my_post_type', array(
       
  1839  *         'author', 'excerpt',
       
  1840  *     ) );
       
  1841  *     add_post_type_support( 'my_post_type', 'my_feature', array(
       
  1842  *         'field' => 'value',
       
  1843  *     ) );
       
  1844  *
  1756  * @since 3.0.0
  1845  * @since 3.0.0
       
  1846  * @since 5.3.0 Formalized the existing and already documented `...$args` parameter
       
  1847  *              by adding it to the function signature.
  1757  *
  1848  *
  1758  * @global array $_wp_post_type_features
  1849  * @global array $_wp_post_type_features
  1759  *
  1850  *
  1760  * @param string       $post_type The post type for which to add the feature.
  1851  * @param string       $post_type The post type for which to add the feature.
  1761  * @param string|array $feature   The feature being added, accepts an array of
  1852  * @param string|array $feature   The feature being added, accepts an array of
  1762  *                                feature strings or a single string.
  1853  *                                feature strings or a single string.
  1763  */
  1854  * @param mixed        ...$args   Optional extra arguments to pass along with certain features.
  1764 function add_post_type_support( $post_type, $feature ) {
  1855  */
       
  1856 function add_post_type_support( $post_type, $feature, ...$args ) {
  1765 	global $_wp_post_type_features;
  1857 	global $_wp_post_type_features;
  1766 
  1858 
  1767 	$features = (array) $feature;
  1859 	$features = (array) $feature;
  1768 	foreach ( $features as $feature ) {
  1860 	foreach ( $features as $feature ) {
  1769 		if ( func_num_args() == 2 ) {
  1861 		if ( $args ) {
       
  1862 			$_wp_post_type_features[ $post_type ][ $feature ] = $args;
       
  1863 		} else {
  1770 			$_wp_post_type_features[ $post_type ][ $feature ] = true;
  1864 			$_wp_post_type_features[ $post_type ][ $feature ] = true;
  1771 		} else {
       
  1772 			$_wp_post_type_features[ $post_type ][ $feature ] = array_slice( func_get_args(), 2 );
       
  1773 		}
  1865 		}
  1774 	}
  1866 	}
  1775 }
  1867 }
  1776 
  1868 
  1777 /**
  1869 /**
  1837  * @param array|string $feature  Single feature or an array of features the post types should support.
  1929  * @param array|string $feature  Single feature or an array of features the post types should support.
  1838  * @param string       $operator Optional. The logical operation to perform. 'or' means
  1930  * @param string       $operator Optional. The logical operation to perform. 'or' means
  1839  *                               only one element from the array needs to match; 'and'
  1931  *                               only one element from the array needs to match; 'and'
  1840  *                               means all elements must match; 'not' means no elements may
  1932  *                               means all elements must match; 'not' means no elements may
  1841  *                               match. Default 'and'.
  1933  *                               match. Default 'and'.
  1842  * @return array A list of post type names.
  1934  * @return string[] A list of post type names.
  1843  */
  1935  */
  1844 function get_post_types_by_support( $feature, $operator = 'and' ) {
  1936 function get_post_types_by_support( $feature, $operator = 'and' ) {
  1845 	global $_wp_post_type_features;
  1937 	global $_wp_post_type_features;
  1846 
  1938 
  1847 	$features = array_fill_keys( (array) $feature, true );
  1939 	$features = array_fill_keys( (array) $feature, true );
  1934 		'meta_value'       => '',
  2026 		'meta_value'       => '',
  1935 		'post_type'        => 'post',
  2027 		'post_type'        => 'post',
  1936 		'suppress_filters' => true,
  2028 		'suppress_filters' => true,
  1937 	);
  2029 	);
  1938 
  2030 
  1939 	$r = wp_parse_args( $args, $defaults );
  2031 	$parsed_args = wp_parse_args( $args, $defaults );
  1940 	if ( empty( $r['post_status'] ) ) {
  2032 	if ( empty( $parsed_args['post_status'] ) ) {
  1941 		$r['post_status'] = ( 'attachment' == $r['post_type'] ) ? 'inherit' : 'publish';
  2033 		$parsed_args['post_status'] = ( 'attachment' === $parsed_args['post_type'] ) ? 'inherit' : 'publish';
  1942 	}
  2034 	}
  1943 	if ( ! empty( $r['numberposts'] ) && empty( $r['posts_per_page'] ) ) {
  2035 	if ( ! empty( $parsed_args['numberposts'] ) && empty( $parsed_args['posts_per_page'] ) ) {
  1944 		$r['posts_per_page'] = $r['numberposts'];
  2036 		$parsed_args['posts_per_page'] = $parsed_args['numberposts'];
  1945 	}
  2037 	}
  1946 	if ( ! empty( $r['category'] ) ) {
  2038 	if ( ! empty( $parsed_args['category'] ) ) {
  1947 		$r['cat'] = $r['category'];
  2039 		$parsed_args['cat'] = $parsed_args['category'];
  1948 	}
  2040 	}
  1949 	if ( ! empty( $r['include'] ) ) {
  2041 	if ( ! empty( $parsed_args['include'] ) ) {
  1950 		$incposts            = wp_parse_id_list( $r['include'] );
  2042 		$incposts                      = wp_parse_id_list( $parsed_args['include'] );
  1951 		$r['posts_per_page'] = count( $incposts );  // only the number of posts included
  2043 		$parsed_args['posts_per_page'] = count( $incposts );  // Only the number of posts included.
  1952 		$r['post__in']       = $incposts;
  2044 		$parsed_args['post__in']       = $incposts;
  1953 	} elseif ( ! empty( $r['exclude'] ) ) {
  2045 	} elseif ( ! empty( $parsed_args['exclude'] ) ) {
  1954 		$r['post__not_in'] = wp_parse_id_list( $r['exclude'] );
  2046 		$parsed_args['post__not_in'] = wp_parse_id_list( $parsed_args['exclude'] );
  1955 	}
  2047 	}
  1956 
  2048 
  1957 	$r['ignore_sticky_posts'] = true;
  2049 	$parsed_args['ignore_sticky_posts'] = true;
  1958 	$r['no_found_rows']       = true;
  2050 	$parsed_args['no_found_rows']       = true;
  1959 
  2051 
  1960 	$get_posts = new WP_Query;
  2052 	$get_posts = new WP_Query;
  1961 	return $get_posts->query( $r );
  2053 	return $get_posts->query( $parsed_args );
  1962 
  2054 
  1963 }
  2055 }
  1964 
  2056 
  1965 //
  2057 //
  1966 // Post meta functions
  2058 // Post meta functions.
  1967 //
  2059 //
  1968 
  2060 
  1969 /**
  2061 /**
  1970  * Adds a meta field to the given post.
  2062  * Adds a meta field to the given post.
  1971  *
  2063  *
  1999  *
  2091  *
  2000  * @since 1.5.0
  2092  * @since 1.5.0
  2001  *
  2093  *
  2002  * @param int    $post_id    Post ID.
  2094  * @param int    $post_id    Post ID.
  2003  * @param string $meta_key   Metadata name.
  2095  * @param string $meta_key   Metadata name.
  2004  * @param mixed  $meta_value Optional. Metadata value. Must be serializable if
  2096  * @param mixed  $meta_value Optional. Metadata value. If provided,
  2005  *                           non-scalar. Default empty.
  2097  *                           rows will only be removed that match the value.
       
  2098  *                           Must be serializable if non-scalar. Default empty.
  2006  * @return bool True on success, false on failure.
  2099  * @return bool True on success, false on failure.
  2007  */
  2100  */
  2008 function delete_post_meta( $post_id, $meta_key, $meta_value = '' ) {
  2101 function delete_post_meta( $post_id, $meta_key, $meta_value = '' ) {
  2009 	// Make sure meta is added to the post, not a revision.
  2102 	// Make sure meta is added to the post, not a revision.
  2010 	$the_post = wp_is_post_revision( $post_id );
  2103 	$the_post = wp_is_post_revision( $post_id );
  2019  * Retrieves a post meta field for the given post ID.
  2112  * Retrieves a post meta field for the given post ID.
  2020  *
  2113  *
  2021  * @since 1.5.0
  2114  * @since 1.5.0
  2022  *
  2115  *
  2023  * @param int    $post_id Post ID.
  2116  * @param int    $post_id Post ID.
  2024  * @param string $key     Optional. The meta key to retrieve. By default, returns
  2117  * @param string $key     Optional. The meta key to retrieve. By default,
  2025  *                        data for all keys. Default empty.
  2118  *                        returns data for all keys. Default empty.
  2026  * @param bool   $single  Optional. If true, returns only the first value for the specified meta key.
  2119  * @param bool   $single  Optional. Whether to return a single value.
  2027  *                        This parameter has no effect if $key is not specified. Default false.
  2120  *                        This parameter has no effect if $key is not specified.
  2028  * @return mixed Will be an array if $single is false. Will be value of the meta
  2121  *                        Default false.
  2029  *               field if $single is true.
  2122  * @return mixed An array if $single is false. The value of the meta field
       
  2123  *               if $single is true. False for an invalid $post_id.
  2030  */
  2124  */
  2031 function get_post_meta( $post_id, $key = '', $single = false ) {
  2125 function get_post_meta( $post_id, $key = '', $single = false ) {
  2032 	return get_metadata( 'post', $post_id, $key, $single );
  2126 	return get_metadata( 'post', $post_id, $key, $single );
  2033 }
  2127 }
  2034 
  2128 
  2046  *
  2140  *
  2047  * @param int    $post_id    Post ID.
  2141  * @param int    $post_id    Post ID.
  2048  * @param string $meta_key   Metadata key.
  2142  * @param string $meta_key   Metadata key.
  2049  * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
  2143  * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
  2050  * @param mixed  $prev_value Optional. Previous value to check before updating.
  2144  * @param mixed  $prev_value Optional. Previous value to check before updating.
  2051  * @return int|bool The new meta field ID if a field with the given key didn't exist and was
  2145  *                           If specified, only update existing metadata entries with
  2052  *                  therefore added, true on successful update, false on failure.
  2146  *                           this value. Otherwise, update all entries. Default empty.
       
  2147  * @return int|bool Meta ID if the key didn't exist, true on successful update,
       
  2148  *                  false on failure or if the value passed to the function
       
  2149  *                  is the same as the one that is already in the database.
  2053  */
  2150  */
  2054 function update_post_meta( $post_id, $meta_key, $meta_value, $prev_value = '' ) {
  2151 function update_post_meta( $post_id, $meta_key, $meta_value, $prev_value = '' ) {
  2055 	// Make sure meta is added to the post, not a revision.
  2152 	// Make sure meta is added to the post, not a revision.
  2056 	$the_post = wp_is_post_revision( $post_id );
  2153 	$the_post = wp_is_post_revision( $post_id );
  2057 	if ( $the_post ) {
  2154 	if ( $the_post ) {
  2141 
  2238 
  2142 	if ( ! is_array( $custom ) ) {
  2239 	if ( ! is_array( $custom ) ) {
  2143 		return;
  2240 		return;
  2144 	}
  2241 	}
  2145 
  2242 
  2146 	if ( $keys = array_keys( $custom ) ) {
  2243 	$keys = array_keys( $custom );
       
  2244 	if ( $keys ) {
  2147 		return $keys;
  2245 		return $keys;
  2148 	}
  2246 	}
  2149 }
  2247 }
  2150 
  2248 
  2151 /**
  2249 /**
  2192 		$post_id = get_the_ID();
  2290 		$post_id = get_the_ID();
  2193 	}
  2291 	}
  2194 
  2292 
  2195 	$stickies = get_option( 'sticky_posts' );
  2293 	$stickies = get_option( 'sticky_posts' );
  2196 
  2294 
  2197 	if ( ! is_array( $stickies ) ) {
  2295 	if ( is_array( $stickies ) ) {
  2198 		return false;
  2296 		$stickies  = array_map( 'intval', $stickies );
  2199 	}
  2297 		$is_sticky = in_array( $post_id, $stickies, true );
  2200 
  2298 	} else {
  2201 	if ( in_array( $post_id, $stickies ) ) {
  2299 		$is_sticky = false;
  2202 		return true;
  2300 	}
  2203 	}
  2301 
  2204 
  2302 	/**
  2205 	return false;
  2303 	 * Filters whether a post is sticky.
       
  2304 	 *
       
  2305 	 * @since 5.3.0
       
  2306 	 *
       
  2307 	 * @param bool $is_sticky Whether a post is sticky.
       
  2308 	 * @param int  $post_id   Post ID.
       
  2309 	 */
       
  2310 	return apply_filters( 'is_sticky', $is_sticky, $post_id );
  2206 }
  2311 }
  2207 
  2312 
  2208 /**
  2313 /**
  2209  * Sanitize every post field.
  2314  * Sanitize every post field.
  2210  *
  2315  *
  2250 	}
  2355 	}
  2251 	return $post;
  2356 	return $post;
  2252 }
  2357 }
  2253 
  2358 
  2254 /**
  2359 /**
  2255  * Sanitize post field based on context.
  2360  * Sanitizes a post field based on context.
  2256  *
  2361  *
  2257  * Possible context values are:  'raw', 'edit', 'db', 'display', 'attribute' and
  2362  * Possible context values are:  'raw', 'edit', 'db', 'display', 'attribute' and
  2258  * 'js'. The 'display' context is used by default. 'attribute' and 'js' contexts
  2363  * 'js'. The 'display' context is used by default. 'attribute' and 'js' contexts
  2259  * are treated like 'display' when calling filters.
  2364  * are treated like 'display' when calling filters.
  2260  *
  2365  *
  2262  * @since 4.4.0 Like `sanitize_post()`, `$context` defaults to 'display'.
  2367  * @since 4.4.0 Like `sanitize_post()`, `$context` defaults to 'display'.
  2263  *
  2368  *
  2264  * @param string $field   The Post Object field name.
  2369  * @param string $field   The Post Object field name.
  2265  * @param mixed  $value   The Post Object value.
  2370  * @param mixed  $value   The Post Object value.
  2266  * @param int    $post_id Post ID.
  2371  * @param int    $post_id Post ID.
  2267  * @param string $context Optional. How to sanitize post fields. Looks for 'raw', 'edit',
  2372  * @param string $context Optional. How to sanitize the field. Possible values are 'raw', 'edit',
  2268  *                        'db', 'display', 'attribute' and 'js'. Default 'display'.
  2373  *                        'db', 'display', 'attribute' and 'js'. Default 'display'.
  2269  * @return mixed Sanitized value.
  2374  * @return mixed Sanitized value.
  2270  */
  2375  */
  2271 function sanitize_post_field( $field, $value, $post_id, $context = 'display' ) {
  2376 function sanitize_post_field( $field, $value, $post_id, $context = 'display' ) {
  2272 	$int_fields = array( 'ID', 'post_parent', 'menu_order' );
  2377 	$int_fields = array( 'ID', 'post_parent', 'menu_order' );
  2273 	if ( in_array( $field, $int_fields ) ) {
  2378 	if ( in_array( $field, $int_fields, true ) ) {
  2274 		$value = (int) $value;
  2379 		$value = (int) $value;
  2275 	}
  2380 	}
  2276 
  2381 
  2277 	// Fields which contain arrays of integers.
  2382 	// Fields which contain arrays of integers.
  2278 	$array_int_fields = array( 'ancestors' );
  2383 	$array_int_fields = array( 'ancestors' );
  2279 	if ( in_array( $field, $array_int_fields ) ) {
  2384 	if ( in_array( $field, $array_int_fields, true ) ) {
  2280 		$value = array_map( 'absint', $value );
  2385 		$value = array_map( 'absint', $value );
  2281 		return $value;
  2386 		return $value;
  2282 	}
  2387 	}
  2283 
  2388 
  2284 	if ( 'raw' == $context ) {
  2389 	if ( 'raw' === $context ) {
  2285 		return $value;
  2390 		return $value;
  2286 	}
  2391 	}
  2287 
  2392 
  2288 	$prefixed = false;
  2393 	$prefixed = false;
  2289 	if ( false !== strpos( $field, 'post_' ) ) {
  2394 	if ( false !== strpos( $field, 'post_' ) ) {
  2290 		$prefixed        = true;
  2395 		$prefixed        = true;
  2291 		$field_no_prefix = str_replace( 'post_', '', $field );
  2396 		$field_no_prefix = str_replace( 'post_', '', $field );
  2292 	}
  2397 	}
  2293 
  2398 
  2294 	if ( 'edit' == $context ) {
  2399 	if ( 'edit' === $context ) {
  2295 		$format_to_edit = array( 'post_content', 'post_excerpt', 'post_title', 'post_password' );
  2400 		$format_to_edit = array( 'post_content', 'post_excerpt', 'post_title', 'post_password' );
  2296 
  2401 
  2297 		if ( $prefixed ) {
  2402 		if ( $prefixed ) {
  2298 
  2403 
  2299 			/**
  2404 			/**
  2323 			$value = apply_filters( "{$field_no_prefix}_edit_pre", $value, $post_id );
  2428 			$value = apply_filters( "{$field_no_prefix}_edit_pre", $value, $post_id );
  2324 		} else {
  2429 		} else {
  2325 			$value = apply_filters( "edit_post_{$field}", $value, $post_id );
  2430 			$value = apply_filters( "edit_post_{$field}", $value, $post_id );
  2326 		}
  2431 		}
  2327 
  2432 
  2328 		if ( in_array( $field, $format_to_edit ) ) {
  2433 		if ( in_array( $field, $format_to_edit, true ) ) {
  2329 			if ( 'post_content' == $field ) {
  2434 			if ( 'post_content' === $field ) {
  2330 				$value = format_to_edit( $value, user_can_richedit() );
  2435 				$value = format_to_edit( $value, user_can_richedit() );
  2331 			} else {
  2436 			} else {
  2332 				$value = format_to_edit( $value );
  2437 				$value = format_to_edit( $value );
  2333 			}
  2438 			}
  2334 		} else {
  2439 		} else {
  2335 			$value = esc_attr( $value );
  2440 			$value = esc_attr( $value );
  2336 		}
  2441 		}
  2337 	} elseif ( 'db' == $context ) {
  2442 	} elseif ( 'db' === $context ) {
  2338 		if ( $prefixed ) {
  2443 		if ( $prefixed ) {
  2339 
  2444 
  2340 			/**
  2445 			/**
  2341 			 * Filters the value of a specific post field before saving.
  2446 			 * Filters the value of a specific post field before saving.
  2342 			 *
  2447 			 *
  2389 			 * @since 2.3.0
  2494 			 * @since 2.3.0
  2390 			 *
  2495 			 *
  2391 			 * @param mixed  $value   Value of the prefixed post field.
  2496 			 * @param mixed  $value   Value of the prefixed post field.
  2392 			 * @param int    $post_id Post ID.
  2497 			 * @param int    $post_id Post ID.
  2393 			 * @param string $context Context for how to sanitize the field. Possible
  2498 			 * @param string $context Context for how to sanitize the field. Possible
  2394 			 *                        values include 'raw', 'edit', 'db', 'display',
  2499 			 *                        values include 'edit', 'display',
  2395 			 *                        'attribute' and 'js'.
  2500 			 *                        'attribute' and 'js'.
  2396 			 */
  2501 			 */
  2397 			$value = apply_filters( "{$field}", $value, $post_id, $context );
  2502 			$value = apply_filters( "{$field}", $value, $post_id, $context );
  2398 		} else {
  2503 		} else {
  2399 			$value = apply_filters( "post_{$field}", $value, $post_id, $context );
  2504 			$value = apply_filters( "post_{$field}", $value, $post_id, $context );
  2400 		}
  2505 		}
  2401 
  2506 
  2402 		if ( 'attribute' == $context ) {
  2507 		if ( 'attribute' === $context ) {
  2403 			$value = esc_attr( $value );
  2508 			$value = esc_attr( $value );
  2404 		} elseif ( 'js' == $context ) {
  2509 		} elseif ( 'js' === $context ) {
  2405 			$value = esc_js( $value );
  2510 			$value = esc_js( $value );
  2406 		}
  2511 		}
  2407 	}
  2512 	}
  2408 
  2513 
  2409 	return $value;
  2514 	return $value;
  2417  * @since 2.7.0
  2522  * @since 2.7.0
  2418  *
  2523  *
  2419  * @param int $post_id Post ID.
  2524  * @param int $post_id Post ID.
  2420  */
  2525  */
  2421 function stick_post( $post_id ) {
  2526 function stick_post( $post_id ) {
       
  2527 	$post_id  = (int) $post_id;
  2422 	$stickies = get_option( 'sticky_posts' );
  2528 	$stickies = get_option( 'sticky_posts' );
  2423 
  2529 
  2424 	if ( ! is_array( $stickies ) ) {
  2530 	if ( ! is_array( $stickies ) ) {
  2425 		$stickies = array( $post_id );
  2531 		$stickies = array();
  2426 	}
  2532 	}
  2427 
  2533 
  2428 	if ( ! in_array( $post_id, $stickies ) ) {
  2534 	$stickies = array_map( 'intval', $stickies );
       
  2535 
       
  2536 	if ( ! in_array( $post_id, $stickies, true ) ) {
  2429 		$stickies[] = $post_id;
  2537 		$stickies[] = $post_id;
  2430 	}
  2538 	}
  2431 
  2539 
  2432 	$updated = update_option( 'sticky_posts', $stickies );
  2540 	$updated = update_option( 'sticky_posts', $stickies );
  2433 
  2541 
  2451  * @since 2.7.0
  2559  * @since 2.7.0
  2452  *
  2560  *
  2453  * @param int $post_id Post ID.
  2561  * @param int $post_id Post ID.
  2454  */
  2562  */
  2455 function unstick_post( $post_id ) {
  2563 function unstick_post( $post_id ) {
       
  2564 	$post_id  = (int) $post_id;
  2456 	$stickies = get_option( 'sticky_posts' );
  2565 	$stickies = get_option( 'sticky_posts' );
  2457 
  2566 
  2458 	if ( ! is_array( $stickies ) ) {
  2567 	if ( ! is_array( $stickies ) ) {
  2459 		return;
  2568 		return;
  2460 	}
  2569 	}
  2461 
  2570 
  2462 	if ( ! in_array( $post_id, $stickies ) ) {
  2571 	$stickies = array_map( 'intval', $stickies );
       
  2572 
       
  2573 	if ( ! in_array( $post_id, $stickies, true ) ) {
  2463 		return;
  2574 		return;
  2464 	}
  2575 	}
  2465 
  2576 
  2466 	$offset = array_search( $post_id, $stickies );
  2577 	$offset = array_search( $post_id, $stickies, true );
  2467 	if ( false === $offset ) {
  2578 	if ( false === $offset ) {
  2468 		return;
  2579 		return;
  2469 	}
  2580 	}
  2470 
  2581 
  2471 	array_splice( $stickies, $offset, 1 );
  2582 	array_splice( $stickies, $offset, 1 );
  2494  * @param string $perm Optional. 'readable' or empty. Default empty.
  2605  * @param string $perm Optional. 'readable' or empty. Default empty.
  2495  * @return string The cache key.
  2606  * @return string The cache key.
  2496  */
  2607  */
  2497 function _count_posts_cache_key( $type = 'post', $perm = '' ) {
  2608 function _count_posts_cache_key( $type = 'post', $perm = '' ) {
  2498 	$cache_key = 'posts-' . $type;
  2609 	$cache_key = 'posts-' . $type;
  2499 	if ( 'readable' == $perm && is_user_logged_in() ) {
  2610 
       
  2611 	if ( 'readable' === $perm && is_user_logged_in() ) {
  2500 		$post_type_object = get_post_type_object( $type );
  2612 		$post_type_object = get_post_type_object( $type );
       
  2613 
  2501 		if ( $post_type_object && ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
  2614 		if ( $post_type_object && ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
  2502 			$cache_key .= '_' . $perm . '_' . get_current_user_id();
  2615 			$cache_key .= '_' . $perm . '_' . get_current_user_id();
  2503 		}
  2616 		}
  2504 	}
  2617 	}
       
  2618 
  2505 	return $cache_key;
  2619 	return $cache_key;
  2506 }
  2620 }
  2507 
  2621 
  2508 /**
  2622 /**
  2509  * Count number of posts of a post type and if user has permissions to view.
  2623  * Count number of posts of a post type and if user has permissions to view.
  2533 
  2647 
  2534 	$cache_key = _count_posts_cache_key( $type, $perm );
  2648 	$cache_key = _count_posts_cache_key( $type, $perm );
  2535 
  2649 
  2536 	$counts = wp_cache_get( $cache_key, 'counts' );
  2650 	$counts = wp_cache_get( $cache_key, 'counts' );
  2537 	if ( false !== $counts ) {
  2651 	if ( false !== $counts ) {
       
  2652 		// We may have cached this before every status was registered.
       
  2653 		foreach ( get_post_stati() as $status ) {
       
  2654 			if ( ! isset( $counts->{$status} ) ) {
       
  2655 				$counts->{$status} = 0;
       
  2656 			}
       
  2657 		}
       
  2658 
  2538 		/** This filter is documented in wp-includes/post.php */
  2659 		/** This filter is documented in wp-includes/post.php */
  2539 		return apply_filters( 'wp_count_posts', $counts, $type, $perm );
  2660 		return apply_filters( 'wp_count_posts', $counts, $type, $perm );
  2540 	}
  2661 	}
  2541 
  2662 
  2542 	$query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
  2663 	$query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
  2543 	if ( 'readable' == $perm && is_user_logged_in() ) {
  2664 
       
  2665 	if ( 'readable' === $perm && is_user_logged_in() ) {
  2544 		$post_type_object = get_post_type_object( $type );
  2666 		$post_type_object = get_post_type_object( $type );
  2545 		if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
  2667 		if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
  2546 			$query .= $wpdb->prepare(
  2668 			$query .= $wpdb->prepare(
  2547 				" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
  2669 				" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
  2548 				get_current_user_id()
  2670 				get_current_user_id()
  2549 			);
  2671 			);
  2550 		}
  2672 		}
  2551 	}
  2673 	}
       
  2674 
  2552 	$query .= ' GROUP BY post_status';
  2675 	$query .= ' GROUP BY post_status';
  2553 
  2676 
  2554 	$results = (array) $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
  2677 	$results = (array) $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
  2555 	$counts  = array_fill_keys( get_post_stati(), 0 );
  2678 	$counts  = array_fill_keys( get_post_stati(), 0 );
  2556 
  2679 
  2618 
  2741 
  2619 /**
  2742 /**
  2620  * Get default post mime types.
  2743  * Get default post mime types.
  2621  *
  2744  *
  2622  * @since 2.9.0
  2745  * @since 2.9.0
       
  2746  * @since 5.3.0 Added the 'Documents', 'Spreadsheets', and 'Archives' mime type groups.
  2623  *
  2747  *
  2624  * @return array List of post mime types.
  2748  * @return array List of post mime types.
  2625  */
  2749  */
  2626 function get_post_mime_types() {
  2750 function get_post_mime_types() {
  2627 	$post_mime_types = array(   //	array( adj, noun )
  2751 	$post_mime_types = array(   // array( adj, noun )
  2628 		'image' => array( __( 'Images' ), __( 'Manage Images' ), _n_noop( 'Image <span class="count">(%s)</span>', 'Images <span class="count">(%s)</span>' ) ),
  2752 		'image'       => array(
  2629 		'audio' => array( __( 'Audio' ), __( 'Manage Audio' ), _n_noop( 'Audio <span class="count">(%s)</span>', 'Audio <span class="count">(%s)</span>' ) ),
  2753 			__( 'Images' ),
  2630 		'video' => array( __( 'Video' ), __( 'Manage Video' ), _n_noop( 'Video <span class="count">(%s)</span>', 'Video <span class="count">(%s)</span>' ) ),
  2754 			__( 'Manage Images' ),
       
  2755 			/* translators: %s: Number of images. */
       
  2756 			_n_noop(
       
  2757 				'Image <span class="count">(%s)</span>',
       
  2758 				'Images <span class="count">(%s)</span>'
       
  2759 			),
       
  2760 		),
       
  2761 		'audio'       => array(
       
  2762 			__( 'Audio' ),
       
  2763 			__( 'Manage Audio' ),
       
  2764 			/* translators: %s: Number of audio files. */
       
  2765 			_n_noop(
       
  2766 				'Audio <span class="count">(%s)</span>',
       
  2767 				'Audio <span class="count">(%s)</span>'
       
  2768 			),
       
  2769 		),
       
  2770 		'video'       => array(
       
  2771 			__( 'Video' ),
       
  2772 			__( 'Manage Video' ),
       
  2773 			/* translators: %s: Number of video files. */
       
  2774 			_n_noop(
       
  2775 				'Video <span class="count">(%s)</span>',
       
  2776 				'Video <span class="count">(%s)</span>'
       
  2777 			),
       
  2778 		),
       
  2779 		'document'    => array(
       
  2780 			__( 'Documents' ),
       
  2781 			__( 'Manage Documents' ),
       
  2782 			/* translators: %s: Number of documents. */
       
  2783 			_n_noop(
       
  2784 				'Document <span class="count">(%s)</span>',
       
  2785 				'Documents <span class="count">(%s)</span>'
       
  2786 			),
       
  2787 		),
       
  2788 		'spreadsheet' => array(
       
  2789 			__( 'Spreadsheets' ),
       
  2790 			__( 'Manage Spreadsheets' ),
       
  2791 			/* translators: %s: Number of spreadsheets. */
       
  2792 			_n_noop(
       
  2793 				'Spreadsheet <span class="count">(%s)</span>',
       
  2794 				'Spreadsheets <span class="count">(%s)</span>'
       
  2795 			),
       
  2796 		),
       
  2797 		'archive'     => array(
       
  2798 			_x( 'Archives', 'file type group' ),
       
  2799 			__( 'Manage Archives' ),
       
  2800 			/* translators: %s: Number of archives. */
       
  2801 			_n_noop(
       
  2802 				'Archive <span class="count">(%s)</span>',
       
  2803 				'Archives <span class="count">(%s)</span>'
       
  2804 			),
       
  2805 		),
  2631 	);
  2806 	);
       
  2807 
       
  2808 	$ext_types  = wp_get_ext_types();
       
  2809 	$mime_types = wp_get_mime_types();
       
  2810 
       
  2811 	foreach ( $post_mime_types as $group => $labels ) {
       
  2812 		if ( in_array( $group, array( 'image', 'audio', 'video' ), true ) ) {
       
  2813 			continue;
       
  2814 		}
       
  2815 
       
  2816 		if ( ! isset( $ext_types[ $group ] ) ) {
       
  2817 			unset( $post_mime_types[ $group ] );
       
  2818 			continue;
       
  2819 		}
       
  2820 
       
  2821 		$group_mime_types = array();
       
  2822 		foreach ( $ext_types[ $group ] as $extension ) {
       
  2823 			foreach ( $mime_types as $exts => $mime ) {
       
  2824 				if ( preg_match( '!^(' . $exts . ')$!i', $extension ) ) {
       
  2825 					$group_mime_types[] = $mime;
       
  2826 					break;
       
  2827 				}
       
  2828 			}
       
  2829 		}
       
  2830 		$group_mime_types = implode( ',', array_unique( $group_mime_types ) );
       
  2831 
       
  2832 		$post_mime_types[ $group_mime_types ] = $labels;
       
  2833 		unset( $post_mime_types[ $group ] );
       
  2834 	}
  2632 
  2835 
  2633 	/**
  2836 	/**
  2634 	 * Filters the default list of post mime types.
  2837 	 * Filters the default list of post mime types.
  2635 	 *
  2838 	 *
  2636 	 * @since 2.5.0
  2839 	 * @since 2.5.0
  2667 	$wild       = '[-._a-z0-9]*';
  2870 	$wild       = '[-._a-z0-9]*';
  2668 
  2871 
  2669 	foreach ( (array) $wildcard_mime_types as $type ) {
  2872 	foreach ( (array) $wildcard_mime_types as $type ) {
  2670 		$mimes = array_map( 'trim', explode( ',', $type ) );
  2873 		$mimes = array_map( 'trim', explode( ',', $type ) );
  2671 		foreach ( $mimes as $mime ) {
  2874 		foreach ( $mimes as $mime ) {
  2672 			$regex                 = str_replace( '__wildcard__', $wild, preg_quote( str_replace( '*', '__wildcard__', $mime ) ) );
  2875 			$regex = str_replace( '__wildcard__', $wild, preg_quote( str_replace( '*', '__wildcard__', $mime ) ) );
       
  2876 
  2673 			$patternses[][ $type ] = "^$regex$";
  2877 			$patternses[][ $type ] = "^$regex$";
       
  2878 
  2674 			if ( false === strpos( $mime, '/' ) ) {
  2879 			if ( false === strpos( $mime, '/' ) ) {
  2675 				$patternses[][ $type ] = "^$regex/";
  2880 				$patternses[][ $type ] = "^$regex/";
  2676 				$patternses[][ $type ] = $regex;
  2881 				$patternses[][ $type ] = $regex;
  2677 			}
  2882 			}
  2678 		}
  2883 		}
  2680 	asort( $patternses );
  2885 	asort( $patternses );
  2681 
  2886 
  2682 	foreach ( $patternses as $patterns ) {
  2887 	foreach ( $patternses as $patterns ) {
  2683 		foreach ( $patterns as $type => $pattern ) {
  2888 		foreach ( $patterns as $type => $pattern ) {
  2684 			foreach ( (array) $real_mime_types as $real ) {
  2889 			foreach ( (array) $real_mime_types as $real ) {
  2685 				if ( preg_match( "#$pattern#", $real ) && ( empty( $matches[ $type ] ) || false === array_search( $real, $matches[ $type ] ) ) ) {
  2890 				if ( preg_match( "#$pattern#", $real )
       
  2891 					&& ( empty( $matches[ $type ] ) || false === array_search( $real, $matches[ $type ], true ) )
       
  2892 				) {
  2686 					$matches[ $type ][] = $real;
  2893 					$matches[ $type ][] = $real;
  2687 				}
  2894 				}
  2688 			}
  2895 			}
  2689 		}
  2896 		}
  2690 	}
  2897 	}
       
  2898 
  2691 	return $matches;
  2899 	return $matches;
  2692 }
  2900 }
  2693 
  2901 
  2694 /**
  2902 /**
  2695  * Convert MIME types into SQL.
  2903  * Convert MIME types into SQL.
  2730 			}
  2938 			}
  2731 		}
  2939 		}
  2732 
  2940 
  2733 		$mime_pattern = preg_replace( '/\*+/', '%', $mime_pattern );
  2941 		$mime_pattern = preg_replace( '/\*+/', '%', $mime_pattern );
  2734 
  2942 
  2735 		if ( in_array( $mime_type, $wildcards ) ) {
  2943 		if ( in_array( $mime_type, $wildcards, true ) ) {
  2736 			return '';
  2944 			return '';
  2737 		}
  2945 		}
  2738 
  2946 
  2739 		if ( false !== strpos( $mime_pattern, '%' ) ) {
  2947 		if ( false !== strpos( $mime_pattern, '%' ) ) {
  2740 			$wheres[] = empty( $table_alias ) ? "post_mime_type LIKE '$mime_pattern'" : "$table_alias.post_mime_type LIKE '$mime_pattern'";
  2948 			$wheres[] = empty( $table_alias ) ? "post_mime_type LIKE '$mime_pattern'" : "$table_alias.post_mime_type LIKE '$mime_pattern'";
  2741 		} else {
  2949 		} else {
  2742 			$wheres[] = empty( $table_alias ) ? "post_mime_type = '$mime_pattern'" : "$table_alias.post_mime_type = '$mime_pattern'";
  2950 			$wheres[] = empty( $table_alias ) ? "post_mime_type = '$mime_pattern'" : "$table_alias.post_mime_type = '$mime_pattern'";
  2743 		}
  2951 		}
  2744 	}
  2952 	}
       
  2953 
  2745 	if ( ! empty( $wheres ) ) {
  2954 	if ( ! empty( $wheres ) ) {
  2746 		$where = ' AND (' . join( ' OR ', $wheres ) . ') ';
  2955 		$where = ' AND (' . join( ' OR ', $wheres ) . ') ';
  2747 	}
  2956 	}
       
  2957 
  2748 	return $where;
  2958 	return $where;
  2749 }
  2959 }
  2750 
  2960 
  2751 /**
  2961 /**
  2752  * Trash or delete a post or page.
  2962  * Trash or delete a post or page.
  2753  *
  2963  *
  2754  * When the post and page is permanently deleted, everything that is tied to
  2964  * When the post and page is permanently deleted, everything that is tied to
  2755  * it is deleted also. This includes comments, post meta fields, and terms
  2965  * it is deleted also. This includes comments, post meta fields, and terms
  2756  * associated with the post.
  2966  * associated with the post.
  2757  *
  2967  *
  2758  * The post or page is moved to trash instead of permanently deleted unless
  2968  * The post or page is moved to Trash instead of permanently deleted unless
  2759  * trash is disabled, item is already in the trash, or $force_delete is true.
  2969  * Trash is disabled, item is already in the Trash, or $force_delete is true.
  2760  *
  2970  *
  2761  * @since 1.0.0
  2971  * @since 1.0.0
  2762  *
  2972  *
  2763  * @global wpdb $wpdb WordPress database abstraction object.
  2973  * @global wpdb $wpdb WordPress database abstraction object.
  2764  * @see wp_delete_attachment()
  2974  * @see wp_delete_attachment()
  2765  * @see wp_trash_post()
  2975  * @see wp_trash_post()
  2766  *
  2976  *
  2767  * @param int  $postid       Optional. Post ID. Default 0.
  2977  * @param int  $postid       Optional. Post ID. Default 0.
  2768  * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
  2978  * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
  2769  *                           Default false.
  2979  *                           Default false.
  2770  * @return WP_Post|false|null Post data on success, false or null on failure.
  2980  * @return WP_Post|false|null Post data on success, false or null on failure.
  2771  */
  2981  */
  2772 function wp_delete_post( $postid = 0, $force_delete = false ) {
  2982 function wp_delete_post( $postid = 0, $force_delete = false ) {
  2773 	global $wpdb;
  2983 	global $wpdb;
  2791 	/**
  3001 	/**
  2792 	 * Filters whether a post deletion should take place.
  3002 	 * Filters whether a post deletion should take place.
  2793 	 *
  3003 	 *
  2794 	 * @since 4.4.0
  3004 	 * @since 4.4.0
  2795 	 *
  3005 	 *
  2796 	 * @param bool    $delete       Whether to go forward with deletion.
  3006 	 * @param bool|null $delete       Whether to go forward with deletion.
  2797 	 * @param WP_Post $post         Post object.
  3007 	 * @param WP_Post   $post         Post object.
  2798 	 * @param bool    $force_delete Whether to bypass the trash.
  3008 	 * @param bool      $force_delete Whether to bypass the Trash.
  2799 	 */
  3009 	 */
  2800 	$check = apply_filters( 'pre_delete_post', null, $post, $force_delete );
  3010 	$check = apply_filters( 'pre_delete_post', null, $post, $force_delete );
  2801 	if ( null !== $check ) {
  3011 	if ( null !== $check ) {
  2802 		return $check;
  3012 		return $check;
  2803 	}
  3013 	}
  2804 
  3014 
  2805 	/**
  3015 	/**
  2806 	 * Fires before a post is deleted, at the start of wp_delete_post().
  3016 	 * Fires before a post is deleted, at the start of wp_delete_post().
  2807 	 *
  3017 	 *
  2808 	 * @since 3.2.0
  3018 	 * @since 3.2.0
       
  3019 	 * @since 5.5.0 Added the `$post` parameter.
  2809 	 *
  3020 	 *
  2810 	 * @see wp_delete_post()
  3021 	 * @see wp_delete_post()
  2811 	 *
  3022 	 *
  2812 	 * @param int $postid Post ID.
  3023 	 * @param int     $postid Post ID.
       
  3024 	 * @param WP_Post $post   Post object.
  2813 	 */
  3025 	 */
  2814 	do_action( 'before_delete_post', $postid );
  3026 	do_action( 'before_delete_post', $postid, $post );
  2815 
  3027 
  2816 	delete_post_meta( $postid, '_wp_trash_meta_status' );
  3028 	delete_post_meta( $postid, '_wp_trash_meta_status' );
  2817 	delete_post_meta( $postid, '_wp_trash_meta_time' );
  3029 	delete_post_meta( $postid, '_wp_trash_meta_time' );
  2818 
  3030 
  2819 	wp_delete_object_term_relationships( $postid, get_object_taxonomies( $post->post_type ) );
  3031 	wp_delete_object_term_relationships( $postid, get_object_taxonomies( $post->post_type ) );
  2856 
  3068 
  2857 	/**
  3069 	/**
  2858 	 * Fires immediately before a post is deleted from the database.
  3070 	 * Fires immediately before a post is deleted from the database.
  2859 	 *
  3071 	 *
  2860 	 * @since 1.2.0
  3072 	 * @since 1.2.0
  2861 	 *
  3073 	 * @since 5.5.0 Added the `$post` parameter.
  2862 	 * @param int $postid Post ID.
  3074 	 *
       
  3075 	 * @param int     $postid Post ID.
       
  3076 	 * @param WP_Post $post   Post object.
  2863 	 */
  3077 	 */
  2864 	do_action( 'delete_post', $postid );
  3078 	do_action( 'delete_post', $postid, $post );
       
  3079 
  2865 	$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $postid ) );
  3080 	$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $postid ) );
  2866 	if ( ! $result ) {
  3081 	if ( ! $result ) {
  2867 		return false;
  3082 		return false;
  2868 	}
  3083 	}
  2869 
  3084 
  2870 	/**
  3085 	/**
  2871 	 * Fires immediately after a post is deleted from the database.
  3086 	 * Fires immediately after a post is deleted from the database.
  2872 	 *
  3087 	 *
  2873 	 * @since 2.2.0
  3088 	 * @since 2.2.0
  2874 	 *
  3089 	 * @since 5.5.0 Added the `$post` parameter.
  2875 	 * @param int $postid Post ID.
  3090 	 *
       
  3091 	 * @param int     $postid Post ID.
       
  3092 	 * @param WP_Post $post   Post object.
  2876 	 */
  3093 	 */
  2877 	do_action( 'deleted_post', $postid );
  3094 	do_action( 'deleted_post', $postid, $post );
  2878 
  3095 
  2879 	clean_post_cache( $post );
  3096 	clean_post_cache( $post );
  2880 
  3097 
  2881 	if ( is_post_type_hierarchical( $post->post_type ) && $children ) {
  3098 	if ( is_post_type_hierarchical( $post->post_type ) && $children ) {
  2882 		foreach ( $children as $child ) {
  3099 		foreach ( $children as $child ) {
  2888 
  3105 
  2889 	/**
  3106 	/**
  2890 	 * Fires after a post is deleted, at the conclusion of wp_delete_post().
  3107 	 * Fires after a post is deleted, at the conclusion of wp_delete_post().
  2891 	 *
  3108 	 *
  2892 	 * @since 3.2.0
  3109 	 * @since 3.2.0
       
  3110 	 * @since 5.5.0 Added the `$post` parameter.
  2893 	 *
  3111 	 *
  2894 	 * @see wp_delete_post()
  3112 	 * @see wp_delete_post()
  2895 	 *
  3113 	 *
  2896 	 * @param int $postid Post ID.
  3114 	 * @param int     $postid Post ID.
       
  3115 	 * @param WP_Post $post   Post object.
  2897 	 */
  3116 	 */
  2898 	do_action( 'after_delete_post', $postid );
  3117 	do_action( 'after_delete_post', $postid, $post );
  2899 
  3118 
  2900 	return $post;
  3119 	return $post;
  2901 }
  3120 }
  2902 
  3121 
  2903 /**
  3122 /**
  2911  *
  3130  *
  2912  * @param int $post_id Post ID.
  3131  * @param int $post_id Post ID.
  2913  */
  3132  */
  2914 function _reset_front_page_settings_for_post( $post_id ) {
  3133 function _reset_front_page_settings_for_post( $post_id ) {
  2915 	$post = get_post( $post_id );
  3134 	$post = get_post( $post_id );
  2916 	if ( 'page' == $post->post_type ) {
  3135 
       
  3136 	if ( 'page' === $post->post_type ) {
  2917 		/*
  3137 		/*
  2918 		  * If the page is defined in option page_on_front or post_for_posts,
  3138 		 * If the page is defined in option page_on_front or post_for_posts,
  2919 		  * adjust the corresponding options.
  3139 		 * adjust the corresponding options.
  2920 		  */
  3140 		 */
  2921 		if ( get_option( 'page_on_front' ) == $post->ID ) {
  3141 		if ( get_option( 'page_on_front' ) == $post->ID ) {
  2922 			update_option( 'show_on_front', 'posts' );
  3142 			update_option( 'show_on_front', 'posts' );
  2923 			update_option( 'page_on_front', 0 );
  3143 			update_option( 'page_on_front', 0 );
  2924 		}
  3144 		}
  2925 		if ( get_option( 'page_for_posts' ) == $post->ID ) {
  3145 		if ( get_option( 'page_for_posts' ) == $post->ID ) {
  2926 			delete_option( 'page_for_posts', 0 );
  3146 			update_option( 'page_for_posts', 0 );
  2927 		}
  3147 		}
  2928 	}
  3148 	}
       
  3149 
  2929 	unstick_post( $post->ID );
  3150 	unstick_post( $post->ID );
  2930 }
  3151 }
  2931 
  3152 
  2932 /**
  3153 /**
  2933  * Move a post or page to the Trash
  3154  * Move a post or page to the Trash
  2934  *
  3155  *
  2935  * If trash is disabled, the post or page is permanently deleted.
  3156  * If Trash is disabled, the post or page is permanently deleted.
  2936  *
  3157  *
  2937  * @since 2.9.0
  3158  * @since 2.9.0
  2938  *
  3159  *
  2939  * @see wp_delete_post()
  3160  * @see wp_delete_post()
  2940  *
  3161  *
  2960 	/**
  3181 	/**
  2961 	 * Filters whether a post trashing should take place.
  3182 	 * Filters whether a post trashing should take place.
  2962 	 *
  3183 	 *
  2963 	 * @since 4.9.0
  3184 	 * @since 4.9.0
  2964 	 *
  3185 	 *
  2965 	 * @param bool    $trash Whether to go forward with trashing.
  3186 	 * @param bool|null $trash Whether to go forward with trashing.
  2966 	 * @param WP_Post $post  Post object.
  3187 	 * @param WP_Post   $post  Post object.
  2967 	 */
  3188 	 */
  2968 	$check = apply_filters( 'pre_trash_post', null, $post );
  3189 	$check = apply_filters( 'pre_trash_post', null, $post );
  2969 	if ( null !== $check ) {
  3190 	if ( null !== $check ) {
  2970 		return $check;
  3191 		return $check;
  2971 	}
  3192 	}
  2972 
  3193 
  2973 	/**
  3194 	/**
  2974 	 * Fires before a post is sent to the trash.
  3195 	 * Fires before a post is sent to the Trash.
  2975 	 *
  3196 	 *
  2976 	 * @since 3.3.0
  3197 	 * @since 3.3.0
  2977 	 *
  3198 	 *
  2978 	 * @param int $post_id Post ID.
  3199 	 * @param int $post_id Post ID.
  2979 	 */
  3200 	 */
  2980 	do_action( 'wp_trash_post', $post_id );
  3201 	do_action( 'wp_trash_post', $post_id );
  2981 
  3202 
  2982 	add_post_meta( $post_id, '_wp_trash_meta_status', $post->post_status );
  3203 	add_post_meta( $post_id, '_wp_trash_meta_status', $post->post_status );
  2983 	add_post_meta( $post_id, '_wp_trash_meta_time', time() );
  3204 	add_post_meta( $post_id, '_wp_trash_meta_time', time() );
  2984 
  3205 
  2985 	wp_update_post(
  3206 	$post_updated = wp_update_post(
  2986 		array(
  3207 		array(
  2987 			'ID'          => $post_id,
  3208 			'ID'          => $post_id,
  2988 			'post_status' => 'trash',
  3209 			'post_status' => 'trash',
  2989 		)
  3210 		)
  2990 	);
  3211 	);
  2991 
  3212 
       
  3213 	if ( ! $post_updated ) {
       
  3214 		return false;
       
  3215 	}
       
  3216 
  2992 	wp_trash_post_comments( $post_id );
  3217 	wp_trash_post_comments( $post_id );
  2993 
  3218 
  2994 	/**
  3219 	/**
  2995 	 * Fires after a post is sent to the trash.
  3220 	 * Fires after a post is sent to the Trash.
  2996 	 *
  3221 	 *
  2997 	 * @since 2.9.0
  3222 	 * @since 2.9.0
  2998 	 *
  3223 	 *
  2999 	 * @param int $post_id Post ID.
  3224 	 * @param int $post_id Post ID.
  3000 	 */
  3225 	 */
  3025 	/**
  3250 	/**
  3026 	 * Filters whether a post untrashing should take place.
  3251 	 * Filters whether a post untrashing should take place.
  3027 	 *
  3252 	 *
  3028 	 * @since 4.9.0
  3253 	 * @since 4.9.0
  3029 	 *
  3254 	 *
  3030 	 * @param bool    $untrash Whether to go forward with untrashing.
  3255 	 * @param bool|null $untrash Whether to go forward with untrashing.
  3031 	 * @param WP_Post $post    Post object.
  3256 	 * @param WP_Post   $post    Post object.
  3032 	 */
  3257 	 */
  3033 	$check = apply_filters( 'pre_untrash_post', null, $post );
  3258 	$check = apply_filters( 'pre_untrash_post', null, $post );
  3034 	if ( null !== $check ) {
  3259 	if ( null !== $check ) {
  3035 		return $check;
  3260 		return $check;
  3036 	}
  3261 	}
  3037 
  3262 
  3038 	/**
  3263 	/**
  3039 	 * Fires before a post is restored from the trash.
  3264 	 * Fires before a post is restored from the Trash.
  3040 	 *
  3265 	 *
  3041 	 * @since 2.9.0
  3266 	 * @since 2.9.0
  3042 	 *
  3267 	 *
  3043 	 * @param int $post_id Post ID.
  3268 	 * @param int $post_id Post ID.
  3044 	 */
  3269 	 */
  3047 	$post_status = get_post_meta( $post_id, '_wp_trash_meta_status', true );
  3272 	$post_status = get_post_meta( $post_id, '_wp_trash_meta_status', true );
  3048 
  3273 
  3049 	delete_post_meta( $post_id, '_wp_trash_meta_status' );
  3274 	delete_post_meta( $post_id, '_wp_trash_meta_status' );
  3050 	delete_post_meta( $post_id, '_wp_trash_meta_time' );
  3275 	delete_post_meta( $post_id, '_wp_trash_meta_time' );
  3051 
  3276 
  3052 	wp_update_post(
  3277 	$post_updated = wp_update_post(
  3053 		array(
  3278 		array(
  3054 			'ID'          => $post_id,
  3279 			'ID'          => $post_id,
  3055 			'post_status' => $post_status,
  3280 			'post_status' => $post_status,
  3056 		)
  3281 		)
  3057 	);
  3282 	);
  3058 
  3283 
       
  3284 	if ( ! $post_updated ) {
       
  3285 		return false;
       
  3286 	}
       
  3287 
  3059 	wp_untrash_post_comments( $post_id );
  3288 	wp_untrash_post_comments( $post_id );
  3060 
  3289 
  3061 	/**
  3290 	/**
  3062 	 * Fires after a post is restored from the trash.
  3291 	 * Fires after a post is restored from the Trash.
  3063 	 *
  3292 	 *
  3064 	 * @since 2.9.0
  3293 	 * @since 2.9.0
  3065 	 *
  3294 	 *
  3066 	 * @param int $post_id Post ID.
  3295 	 * @param int $post_id Post ID.
  3067 	 */
  3296 	 */
  3069 
  3298 
  3070 	return $post;
  3299 	return $post;
  3071 }
  3300 }
  3072 
  3301 
  3073 /**
  3302 /**
  3074  * Moves comments for a post to the trash.
  3303  * Moves comments for a post to the Trash.
  3075  *
  3304  *
  3076  * @since 2.9.0
  3305  * @since 2.9.0
  3077  *
  3306  *
  3078  * @global wpdb $wpdb WordPress database abstraction object.
  3307  * @global wpdb $wpdb WordPress database abstraction object.
  3079  *
  3308  *
  3089 	}
  3318 	}
  3090 
  3319 
  3091 	$post_id = $post->ID;
  3320 	$post_id = $post->ID;
  3092 
  3321 
  3093 	/**
  3322 	/**
  3094 	 * Fires before comments are sent to the trash.
  3323 	 * Fires before comments are sent to the Trash.
  3095 	 *
  3324 	 *
  3096 	 * @since 2.9.0
  3325 	 * @since 2.9.0
  3097 	 *
  3326 	 *
  3098 	 * @param int $post_id Post ID.
  3327 	 * @param int $post_id Post ID.
  3099 	 */
  3328 	 */
  3115 	$result = $wpdb->update( $wpdb->comments, array( 'comment_approved' => 'post-trashed' ), array( 'comment_post_ID' => $post_id ) );
  3344 	$result = $wpdb->update( $wpdb->comments, array( 'comment_approved' => 'post-trashed' ), array( 'comment_post_ID' => $post_id ) );
  3116 
  3345 
  3117 	clean_comment_cache( array_keys( $statuses ) );
  3346 	clean_comment_cache( array_keys( $statuses ) );
  3118 
  3347 
  3119 	/**
  3348 	/**
  3120 	 * Fires after comments are sent to the trash.
  3349 	 * Fires after comments are sent to the Trash.
  3121 	 *
  3350 	 *
  3122 	 * @since 2.9.0
  3351 	 * @since 2.9.0
  3123 	 *
  3352 	 *
  3124 	 * @param int   $post_id  Post ID.
  3353 	 * @param int   $post_id  Post ID.
  3125 	 * @param array $statuses Array of comment statuses.
  3354 	 * @param array $statuses Array of comment statuses.
  3128 
  3357 
  3129 	return $result;
  3358 	return $result;
  3130 }
  3359 }
  3131 
  3360 
  3132 /**
  3361 /**
  3133  * Restore comments for a post from the trash.
  3362  * Restore comments for a post from the Trash.
  3134  *
  3363  *
  3135  * @since 2.9.0
  3364  * @since 2.9.0
  3136  *
  3365  *
  3137  * @global wpdb $wpdb WordPress database abstraction object.
  3366  * @global wpdb $wpdb WordPress database abstraction object.
  3138  *
  3367  *
  3154 	if ( empty( $statuses ) ) {
  3383 	if ( empty( $statuses ) ) {
  3155 		return true;
  3384 		return true;
  3156 	}
  3385 	}
  3157 
  3386 
  3158 	/**
  3387 	/**
  3159 	 * Fires before comments are restored for a post from the trash.
  3388 	 * Fires before comments are restored for a post from the Trash.
  3160 	 *
  3389 	 *
  3161 	 * @since 2.9.0
  3390 	 * @since 2.9.0
  3162 	 *
  3391 	 *
  3163 	 * @param int $post_id Post ID.
  3392 	 * @param int $post_id Post ID.
  3164 	 */
  3393 	 */
  3170 		$group_by_status[ $comment_status ][] = $comment_id;
  3399 		$group_by_status[ $comment_status ][] = $comment_id;
  3171 	}
  3400 	}
  3172 
  3401 
  3173 	foreach ( $group_by_status as $status => $comments ) {
  3402 	foreach ( $group_by_status as $status => $comments ) {
  3174 		// Sanity check. This shouldn't happen.
  3403 		// Sanity check. This shouldn't happen.
  3175 		if ( 'post-trashed' == $status ) {
  3404 		if ( 'post-trashed' === $status ) {
  3176 			$status = '0';
  3405 			$status = '0';
  3177 		}
  3406 		}
  3178 		$comments_in = implode( ', ', array_map( 'intval', $comments ) );
  3407 		$comments_in = implode( ', ', array_map( 'intval', $comments ) );
  3179 		$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->comments SET comment_approved = %s WHERE comment_ID IN ($comments_in)", $status ) );
  3408 		$wpdb->query( $wpdb->prepare( "UPDATE $wpdb->comments SET comment_approved = %s WHERE comment_ID IN ($comments_in)", $status ) );
  3180 	}
  3409 	}
  3182 	clean_comment_cache( array_keys( $statuses ) );
  3411 	clean_comment_cache( array_keys( $statuses ) );
  3183 
  3412 
  3184 	delete_post_meta( $post_id, '_wp_trash_meta_comments_status' );
  3413 	delete_post_meta( $post_id, '_wp_trash_meta_comments_status' );
  3185 
  3414 
  3186 	/**
  3415 	/**
  3187 	 * Fires after comments are restored for a post from the trash.
  3416 	 * Fires after comments are restored for a post from the Trash.
  3188 	 *
  3417 	 *
  3189 	 * @since 2.9.0
  3418 	 * @since 2.9.0
  3190 	 *
  3419 	 *
  3191 	 * @param int $post_id Post ID.
  3420 	 * @param int $post_id Post ID.
  3192 	 */
  3421 	 */
  3207  *                       global $post. Default 0.
  3436  *                       global $post. Default 0.
  3208  * @param array $args    Optional. Category query parameters. Default empty array.
  3437  * @param array $args    Optional. Category query parameters. Default empty array.
  3209  *                       See WP_Term_Query::__construct() for supported arguments.
  3438  *                       See WP_Term_Query::__construct() for supported arguments.
  3210  * @return array|WP_Error List of categories. If the `$fields` argument passed via `$args` is 'all' or
  3439  * @return array|WP_Error List of categories. If the `$fields` argument passed via `$args` is 'all' or
  3211  *                        'all_with_object_id', an array of WP_Term objects will be returned. If `$fields`
  3440  *                        'all_with_object_id', an array of WP_Term objects will be returned. If `$fields`
  3212  *                        is 'ids', an array of category ids. If `$fields` is 'names', an array of category names.
  3441  *                        is 'ids', an array of category IDs. If `$fields` is 'names', an array of category names.
  3213  *                        WP_Error object if 'category' taxonomy doesn't exist.
  3442  *                        WP_Error object if 'category' taxonomy doesn't exist.
  3214  */
  3443  */
  3215 function wp_get_post_categories( $post_id = 0, $args = array() ) {
  3444 function wp_get_post_categories( $post_id = 0, $args = array() ) {
  3216 	$post_id = (int) $post_id;
  3445 	$post_id = (int) $post_id;
  3217 
  3446 
  3276  * @since 1.0.0
  3505  * @since 1.0.0
  3277  *
  3506  *
  3278  * @see get_posts()
  3507  * @see get_posts()
  3279  *
  3508  *
  3280  * @param array  $args   Optional. Arguments to retrieve posts. Default empty array.
  3509  * @param array  $args   Optional. Arguments to retrieve posts. Default empty array.
  3281  * @param string $output Optional. The required return type. One of OBJECT or ARRAY_A, which correspond to
  3510  * @param string $output Optional. The required return type. One of OBJECT or ARRAY_A, which
  3282  *                       a WP_Post object or an associative array, respectively. Default ARRAY_A.
  3511  *                       correspond to a WP_Post object or an associative array, respectively.
  3283  * @return array|false Array of recent posts, where the type of each element is determined by $output parameter.
  3512  *                       Default ARRAY_A.
  3284  *                     Empty array on failure.
  3513  * @return array|false Array of recent posts, where the type of each element is determined
       
  3514  *                     by the `$output` parameter. Empty array on failure.
  3285  */
  3515  */
  3286 function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) {
  3516 function wp_get_recent_posts( $args = array(), $output = ARRAY_A ) {
  3287 
  3517 
  3288 	if ( is_numeric( $args ) ) {
  3518 	if ( is_numeric( $args ) ) {
  3289 		_deprecated_argument( __FUNCTION__, '3.1.0', __( 'Passing an integer number of posts is deprecated. Pass an array of arguments instead.' ) );
  3519 		_deprecated_argument( __FUNCTION__, '3.1.0', __( 'Passing an integer number of posts is deprecated. Pass an array of arguments instead.' ) );
  3304 		'post_type'        => 'post',
  3534 		'post_type'        => 'post',
  3305 		'post_status'      => 'draft, publish, future, pending, private',
  3535 		'post_status'      => 'draft, publish, future, pending, private',
  3306 		'suppress_filters' => true,
  3536 		'suppress_filters' => true,
  3307 	);
  3537 	);
  3308 
  3538 
  3309 	$r = wp_parse_args( $args, $defaults );
  3539 	$parsed_args = wp_parse_args( $args, $defaults );
  3310 
  3540 
  3311 	$results = get_posts( $r );
  3541 	$results = get_posts( $parsed_args );
  3312 
  3542 
  3313 	// Backward compatibility. Prior to 3.1 expected posts to be returned in array.
  3543 	// Backward compatibility. Prior to 3.1 expected posts to be returned in array.
  3314 	if ( ARRAY_A == $output ) {
  3544 	if ( ARRAY_A == $output ) {
  3315 		foreach ( $results as $key => $result ) {
  3545 		foreach ( $results as $key => $result ) {
  3316 			$results[ $key ] = get_object_vars( $result );
  3546 			$results[ $key ] = get_object_vars( $result );
  3383  * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
  3613  * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
  3384  */
  3614  */
  3385 function wp_insert_post( $postarr, $wp_error = false ) {
  3615 function wp_insert_post( $postarr, $wp_error = false ) {
  3386 	global $wpdb;
  3616 	global $wpdb;
  3387 
  3617 
       
  3618 	// Capture original pre-sanitized array for passing into filters.
       
  3619 	$unsanitized_postarr = $postarr;
       
  3620 
  3388 	$user_id = get_current_user_id();
  3621 	$user_id = get_current_user_id();
  3389 
  3622 
  3390 	$defaults = array(
  3623 	$defaults = array(
  3391 		'post_author'           => $user_id,
  3624 		'post_author'           => $user_id,
  3392 		'post_content'          => '',
  3625 		'post_content'          => '',
  3422 		$update = true;
  3655 		$update = true;
  3423 
  3656 
  3424 		// Get the post ID and GUID.
  3657 		// Get the post ID and GUID.
  3425 		$post_ID     = $postarr['ID'];
  3658 		$post_ID     = $postarr['ID'];
  3426 		$post_before = get_post( $post_ID );
  3659 		$post_before = get_post( $post_ID );
       
  3660 
  3427 		if ( is_null( $post_before ) ) {
  3661 		if ( is_null( $post_before ) ) {
  3428 			if ( $wp_error ) {
  3662 			if ( $wp_error ) {
  3429 				return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
  3663 				return new WP_Error( 'invalid_post', __( 'Invalid post ID.' ) );
  3430 			}
  3664 			}
  3431 			return 0;
  3665 			return 0;
  3440 	$post_type = empty( $postarr['post_type'] ) ? 'post' : $postarr['post_type'];
  3674 	$post_type = empty( $postarr['post_type'] ) ? 'post' : $postarr['post_type'];
  3441 
  3675 
  3442 	$post_title   = $postarr['post_title'];
  3676 	$post_title   = $postarr['post_title'];
  3443 	$post_content = $postarr['post_content'];
  3677 	$post_content = $postarr['post_content'];
  3444 	$post_excerpt = $postarr['post_excerpt'];
  3678 	$post_excerpt = $postarr['post_excerpt'];
       
  3679 
  3445 	if ( isset( $postarr['post_name'] ) ) {
  3680 	if ( isset( $postarr['post_name'] ) ) {
  3446 		$post_name = $postarr['post_name'];
  3681 		$post_name = $postarr['post_name'];
  3447 	} elseif ( $update ) {
  3682 	} elseif ( $update ) {
  3448 		// For an update, don't modify the post_name if it wasn't supplied as an argument.
  3683 		// For an update, don't modify the post_name if it wasn't supplied as an argument.
  3449 		$post_name = $post_before->post_name;
  3684 		$post_name = $post_before->post_name;
  3460 	 *
  3695 	 *
  3461 	 * The post is considered "empty" if both:
  3696 	 * The post is considered "empty" if both:
  3462 	 * 1. The post type supports the title, editor, and excerpt fields
  3697 	 * 1. The post type supports the title, editor, and excerpt fields
  3463 	 * 2. The title, editor, and excerpt fields are all empty
  3698 	 * 2. The title, editor, and excerpt fields are all empty
  3464 	 *
  3699 	 *
  3465 	 * Returning a truthy value to the filter will effectively short-circuit
  3700 	 * Returning a truthy value from the filter will effectively short-circuit
  3466 	 * the new post being inserted, returning 0. If $wp_error is true, a WP_Error
  3701 	 * the new post being inserted and return 0. If $wp_error is true, a WP_Error
  3467 	 * will be returned instead.
  3702 	 * will be returned instead.
  3468 	 *
  3703 	 *
  3469 	 * @since 3.3.0
  3704 	 * @since 3.3.0
  3470 	 *
  3705 	 *
  3471 	 * @param bool  $maybe_empty Whether the post should be considered "empty".
  3706 	 * @param bool  $maybe_empty Whether the post should be considered "empty".
  3478 			return 0;
  3713 			return 0;
  3479 		}
  3714 		}
  3480 	}
  3715 	}
  3481 
  3716 
  3482 	$post_status = empty( $postarr['post_status'] ) ? 'draft' : $postarr['post_status'];
  3717 	$post_status = empty( $postarr['post_status'] ) ? 'draft' : $postarr['post_status'];
       
  3718 
  3483 	if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash', 'auto-draft' ), true ) ) {
  3719 	if ( 'attachment' === $post_type && ! in_array( $post_status, array( 'inherit', 'private', 'trash', 'auto-draft' ), true ) ) {
  3484 		$post_status = 'inherit';
  3720 		$post_status = 'inherit';
  3485 	}
  3721 	}
  3486 
  3722 
  3487 	if ( ! empty( $postarr['post_category'] ) ) {
  3723 	if ( ! empty( $postarr['post_category'] ) ) {
  3488 		// Filter out empty terms.
  3724 		// Filter out empty terms.
  3489 		$post_category = array_filter( $postarr['post_category'] );
  3725 		$post_category = array_filter( $postarr['post_category'] );
  3490 	}
  3726 	}
  3491 
  3727 
  3492 	// Make sure we set a valid category.
  3728 	// Make sure we set a valid category.
  3493 	if ( empty( $post_category ) || 0 == count( $post_category ) || ! is_array( $post_category ) ) {
  3729 	if ( empty( $post_category ) || 0 === count( $post_category ) || ! is_array( $post_category ) ) {
  3494 		// 'post' requires at least one category.
  3730 		// 'post' requires at least one category.
  3495 		if ( 'post' == $post_type && 'auto-draft' != $post_status ) {
  3731 		if ( 'post' === $post_type && 'auto-draft' !== $post_status ) {
  3496 			$post_category = array( get_option( 'default_category' ) );
  3732 			$post_category = array( get_option( 'default_category' ) );
  3497 		} else {
  3733 		} else {
  3498 			$post_category = array();
  3734 			$post_category = array();
  3499 		}
  3735 		}
  3500 	}
  3736 	}
  3515 	/*
  3751 	/*
  3516 	 * Create a valid post name. Drafts and pending posts are allowed to have
  3752 	 * Create a valid post name. Drafts and pending posts are allowed to have
  3517 	 * an empty post name.
  3753 	 * an empty post name.
  3518 	 */
  3754 	 */
  3519 	if ( empty( $post_name ) ) {
  3755 	if ( empty( $post_name ) ) {
  3520 		if ( ! in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) ) {
  3756 		if ( ! in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ), true ) ) {
  3521 			$post_name = sanitize_title( $post_title );
  3757 			$post_name = sanitize_title( $post_title );
  3522 		} else {
  3758 		} else {
  3523 			$post_name = '';
  3759 			$post_name = '';
  3524 		}
  3760 		}
  3525 	} else {
  3761 	} else {
  3526 		// On updates, we need to check to see if it's using the old, fixed sanitization context.
  3762 		// On updates, we need to check to see if it's using the old, fixed sanitization context.
  3527 		$check_name = sanitize_title( $post_name, '', 'old-save' );
  3763 		$check_name = sanitize_title( $post_name, '', 'old-save' );
       
  3764 
  3528 		if ( $update && strtolower( urlencode( $post_name ) ) == $check_name && get_post_field( 'post_name', $post_ID ) == $check_name ) {
  3765 		if ( $update && strtolower( urlencode( $post_name ) ) == $check_name && get_post_field( 'post_name', $post_ID ) == $check_name ) {
  3529 			$post_name = $check_name;
  3766 			$post_name = $check_name;
  3530 		} else { // new post, or slug has changed.
  3767 		} else { // new post, or slug has changed.
  3531 			$post_name = sanitize_title( $post_name );
  3768 			$post_name = sanitize_title( $post_name );
  3532 		}
  3769 		}
  3534 
  3771 
  3535 	/*
  3772 	/*
  3536 	 * If the post date is empty (due to having been new or a draft) and status
  3773 	 * If the post date is empty (due to having been new or a draft) and status
  3537 	 * is not 'draft' or 'pending', set date to now.
  3774 	 * is not 'draft' or 'pending', set date to now.
  3538 	 */
  3775 	 */
  3539 	if ( empty( $postarr['post_date'] ) || '0000-00-00 00:00:00' == $postarr['post_date'] ) {
  3776 	if ( empty( $postarr['post_date'] ) || '0000-00-00 00:00:00' === $postarr['post_date'] ) {
  3540 		if ( empty( $postarr['post_date_gmt'] ) || '0000-00-00 00:00:00' == $postarr['post_date_gmt'] ) {
  3777 		if ( empty( $postarr['post_date_gmt'] ) || '0000-00-00 00:00:00' === $postarr['post_date_gmt'] ) {
  3541 			$post_date = current_time( 'mysql' );
  3778 			$post_date = current_time( 'mysql' );
  3542 		} else {
  3779 		} else {
  3543 			$post_date = get_date_from_gmt( $postarr['post_date_gmt'] );
  3780 			$post_date = get_date_from_gmt( $postarr['post_date_gmt'] );
  3544 		}
  3781 		}
  3545 	} else {
  3782 	} else {
  3557 		} else {
  3794 		} else {
  3558 			return 0;
  3795 			return 0;
  3559 		}
  3796 		}
  3560 	}
  3797 	}
  3561 
  3798 
  3562 	if ( empty( $postarr['post_date_gmt'] ) || '0000-00-00 00:00:00' == $postarr['post_date_gmt'] ) {
  3799 	if ( empty( $postarr['post_date_gmt'] ) || '0000-00-00 00:00:00' === $postarr['post_date_gmt'] ) {
  3563 		if ( ! in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) ) {
  3800 		if ( ! in_array( $post_status, get_post_stati( array( 'date_floating' => true ) ), true ) ) {
  3564 			$post_date_gmt = get_gmt_from_date( $post_date );
  3801 			$post_date_gmt = get_gmt_from_date( $post_date );
  3565 		} else {
  3802 		} else {
  3566 			$post_date_gmt = '0000-00-00 00:00:00';
  3803 			$post_date_gmt = '0000-00-00 00:00:00';
  3567 		}
  3804 		}
  3568 	} else {
  3805 	} else {
  3569 		$post_date_gmt = $postarr['post_date_gmt'];
  3806 		$post_date_gmt = $postarr['post_date_gmt'];
  3570 	}
  3807 	}
  3571 
  3808 
  3572 	if ( $update || '0000-00-00 00:00:00' == $post_date ) {
  3809 	if ( $update || '0000-00-00 00:00:00' === $post_date ) {
  3573 		$post_modified     = current_time( 'mysql' );
  3810 		$post_modified     = current_time( 'mysql' );
  3574 		$post_modified_gmt = current_time( 'mysql', 1 );
  3811 		$post_modified_gmt = current_time( 'mysql', 1 );
  3575 	} else {
  3812 	} else {
  3576 		$post_modified     = $post_date;
  3813 		$post_modified     = $post_date;
  3577 		$post_modified_gmt = $post_date_gmt;
  3814 		$post_modified_gmt = $post_date_gmt;
  3578 	}
  3815 	}
  3579 
  3816 
  3580 	if ( 'attachment' !== $post_type ) {
  3817 	if ( 'attachment' !== $post_type ) {
  3581 		if ( 'publish' == $post_status ) {
  3818 		$now = gmdate( 'Y-m-d H:i:s' );
  3582 			$now = gmdate( 'Y-m-d H:i:59' );
  3819 
  3583 			if ( mysql2date( 'U', $post_date_gmt, false ) > mysql2date( 'U', $now, false ) ) {
  3820 		if ( 'publish' === $post_status ) {
       
  3821 			if ( strtotime( $post_date_gmt ) - strtotime( $now ) >= MINUTE_IN_SECONDS ) {
  3584 				$post_status = 'future';
  3822 				$post_status = 'future';
  3585 			}
  3823 			}
  3586 		} elseif ( 'future' == $post_status ) {
  3824 		} elseif ( 'future' === $post_status ) {
  3587 			$now = gmdate( 'Y-m-d H:i:59' );
  3825 			if ( strtotime( $post_date_gmt ) - strtotime( $now ) < MINUTE_IN_SECONDS ) {
  3588 			if ( mysql2date( 'U', $post_date_gmt, false ) <= mysql2date( 'U', $now, false ) ) {
       
  3589 				$post_status = 'publish';
  3826 				$post_status = 'publish';
  3590 			}
  3827 			}
  3591 		}
  3828 		}
  3592 	}
  3829 	}
  3593 
  3830 
  3619 	} else {
  3856 	} else {
  3620 		$menu_order = 0;
  3857 		$menu_order = 0;
  3621 	}
  3858 	}
  3622 
  3859 
  3623 	$post_password = isset( $postarr['post_password'] ) ? $postarr['post_password'] : '';
  3860 	$post_password = isset( $postarr['post_password'] ) ? $postarr['post_password'] : '';
  3624 	if ( 'private' == $post_status ) {
  3861 	if ( 'private' === $post_status ) {
  3625 		$post_password = '';
  3862 		$post_password = '';
  3626 	}
  3863 	}
  3627 
  3864 
  3628 	if ( isset( $postarr['post_parent'] ) ) {
  3865 	if ( isset( $postarr['post_parent'] ) ) {
  3629 		$post_parent = (int) $postarr['post_parent'];
  3866 		$post_parent = (int) $postarr['post_parent'];
  3654 	 * If the post is being untrashed and it has a desired slug stored in post meta,
  3891 	 * If the post is being untrashed and it has a desired slug stored in post meta,
  3655 	 * reassign it.
  3892 	 * reassign it.
  3656 	 */
  3893 	 */
  3657 	if ( 'trash' === $previous_status && 'trash' !== $post_status ) {
  3894 	if ( 'trash' === $previous_status && 'trash' !== $post_status ) {
  3658 		$desired_post_slug = get_post_meta( $post_ID, '_wp_desired_post_slug', true );
  3895 		$desired_post_slug = get_post_meta( $post_ID, '_wp_desired_post_slug', true );
       
  3896 
  3659 		if ( $desired_post_slug ) {
  3897 		if ( $desired_post_slug ) {
  3660 			delete_post_meta( $post_ID, '_wp_desired_post_slug' );
  3898 			delete_post_meta( $post_ID, '_wp_desired_post_slug' );
  3661 			$post_name = $desired_post_slug;
  3899 			$post_name = $desired_post_slug;
  3662 		}
  3900 		}
  3663 	}
  3901 	}
  3664 
  3902 
  3665 	// If a trashed post has the desired slug, change it and let this post have it.
  3903 	// If a trashed post has the desired slug, change it and let this post have it.
  3666 	if ( 'trash' !== $post_status && $post_name ) {
  3904 	if ( 'trash' !== $post_status && $post_name ) {
  3667 		wp_add_trashed_suffix_to_post_name_for_trashed_posts( $post_name, $post_ID );
  3905 		/**
       
  3906 		 * Filters whether or not to add a `__trashed` suffix to trashed posts that match the name of the updated post.
       
  3907 		 *
       
  3908 		 * @since 5.4.0
       
  3909 		 *
       
  3910 		 * @param bool   $add_trashed_suffix Whether to attempt to add the suffix.
       
  3911 		 * @param string $post_name          The name of the post being updated.
       
  3912 		 * @param int    $post_ID            Post ID.
       
  3913 		 */
       
  3914 		$add_trashed_suffix = apply_filters( 'add_trashed_suffix_to_trashed_posts', true, $post_name, $post_ID );
       
  3915 
       
  3916 		if ( $add_trashed_suffix ) {
       
  3917 			wp_add_trashed_suffix_to_post_name_for_trashed_posts( $post_name, $post_ID );
       
  3918 		}
  3668 	}
  3919 	}
  3669 
  3920 
  3670 	// When trashing an existing post, change its slug to allow non-trashed posts to use it.
  3921 	// When trashing an existing post, change its slug to allow non-trashed posts to use it.
  3671 	if ( 'trash' === $post_status && 'trash' !== $previous_status && 'new' !== $previous_status ) {
  3922 	if ( 'trash' === $post_status && 'trash' !== $previous_status && 'new' !== $previous_status ) {
  3672 		$post_name = wp_add_trashed_suffix_to_post_name_for_post( $post_ID );
  3923 		$post_name = wp_add_trashed_suffix_to_post_name_for_post( $post_ID );
  3683 	$emoji_fields = array( 'post_title', 'post_content', 'post_excerpt' );
  3934 	$emoji_fields = array( 'post_title', 'post_content', 'post_excerpt' );
  3684 
  3935 
  3685 	foreach ( $emoji_fields as $emoji_field ) {
  3936 	foreach ( $emoji_fields as $emoji_field ) {
  3686 		if ( isset( $data[ $emoji_field ] ) ) {
  3937 		if ( isset( $data[ $emoji_field ] ) ) {
  3687 			$charset = $wpdb->get_col_charset( $wpdb->posts, $emoji_field );
  3938 			$charset = $wpdb->get_col_charset( $wpdb->posts, $emoji_field );
       
  3939 
  3688 			if ( 'utf8' === $charset ) {
  3940 			if ( 'utf8' === $charset ) {
  3689 				$data[ $emoji_field ] = wp_encode_emoji( $data[ $emoji_field ] );
  3941 				$data[ $emoji_field ] = wp_encode_emoji( $data[ $emoji_field ] );
  3690 			}
  3942 			}
  3691 		}
  3943 		}
  3692 	}
  3944 	}
  3694 	if ( 'attachment' === $post_type ) {
  3946 	if ( 'attachment' === $post_type ) {
  3695 		/**
  3947 		/**
  3696 		 * Filters attachment post data before it is updated in or added to the database.
  3948 		 * Filters attachment post data before it is updated in or added to the database.
  3697 		 *
  3949 		 *
  3698 		 * @since 3.9.0
  3950 		 * @since 3.9.0
       
  3951 		 * @since 5.4.1 `$unsanitized_postarr` argument added.
  3699 		 *
  3952 		 *
  3700 		 * @param array $data    An array of sanitized attachment post data.
  3953 		 * @param array $data                An array of slashed, sanitized, and processed attachment post data.
  3701 		 * @param array $postarr An array of unsanitized attachment post data.
  3954 		 * @param array $postarr             An array of slashed and sanitized attachment post data, but not processed.
       
  3955 		 * @param array $unsanitized_postarr An array of slashed yet *unsanitized* and unprocessed attachment post data
       
  3956 		 *                                   as originally passed to wp_insert_post().
  3702 		 */
  3957 		 */
  3703 		$data = apply_filters( 'wp_insert_attachment_data', $data, $postarr );
  3958 		$data = apply_filters( 'wp_insert_attachment_data', $data, $postarr, $unsanitized_postarr );
  3704 	} else {
  3959 	} else {
  3705 		/**
  3960 		/**
  3706 		 * Filters slashed post data just before it is inserted into the database.
  3961 		 * Filters slashed post data just before it is inserted into the database.
  3707 		 *
  3962 		 *
  3708 		 * @since 2.7.0
  3963 		 * @since 2.7.0
       
  3964 		 * @since 5.4.1 `$unsanitized_postarr` argument added.
  3709 		 *
  3965 		 *
  3710 		 * @param array $data    An array of slashed post data.
  3966 		 * @param array $data                An array of slashed, sanitized, and processed post data.
  3711 		 * @param array $postarr An array of sanitized, but otherwise unmodified post data.
  3967 		 * @param array $postarr             An array of sanitized (and slashed) but otherwise unmodified post data.
       
  3968 		 * @param array $unsanitized_postarr An array of slashed yet *unsanitized* and unprocessed post data as
       
  3969 		 *                                   originally passed to wp_insert_post().
  3712 		 */
  3970 		 */
  3713 		$data = apply_filters( 'wp_insert_post_data', $data, $postarr );
  3971 		$data = apply_filters( 'wp_insert_post_data', $data, $postarr, $unsanitized_postarr );
  3714 	}
  3972 	}
       
  3973 
  3715 	$data  = wp_unslash( $data );
  3974 	$data  = wp_unslash( $data );
  3716 	$where = array( 'ID' => $post_ID );
  3975 	$where = array( 'ID' => $post_ID );
  3717 
  3976 
  3718 	if ( $update ) {
  3977 	if ( $update ) {
  3719 		/**
  3978 		/**
  3723 		 *
  3982 		 *
  3724 		 * @param int   $post_ID Post ID.
  3983 		 * @param int   $post_ID Post ID.
  3725 		 * @param array $data    Array of unslashed post data.
  3984 		 * @param array $data    Array of unslashed post data.
  3726 		 */
  3985 		 */
  3727 		do_action( 'pre_post_update', $post_ID, $data );
  3986 		do_action( 'pre_post_update', $post_ID, $data );
       
  3987 
  3728 		if ( false === $wpdb->update( $wpdb->posts, $data, $where ) ) {
  3988 		if ( false === $wpdb->update( $wpdb->posts, $data, $where ) ) {
  3729 			if ( $wp_error ) {
  3989 			if ( $wp_error ) {
  3730 				return new WP_Error( 'db_update_error', __( 'Could not update post in the database' ), $wpdb->last_error );
  3990 				if ( 'attachment' === $post_type ) {
       
  3991 					$message = __( 'Could not update attachment in the database.' );
       
  3992 				} else {
       
  3993 					$message = __( 'Could not update post in the database.' );
       
  3994 				}
       
  3995 
       
  3996 				return new WP_Error( 'db_update_error', $message, $wpdb->last_error );
  3731 			} else {
  3997 			} else {
  3732 				return 0;
  3998 				return 0;
  3733 			}
  3999 			}
  3734 		}
  4000 		}
  3735 	} else {
  4001 	} else {
  3736 		// If there is a suggested ID, use it if not already present.
  4002 		// If there is a suggested ID, use it if not already present.
  3737 		if ( ! empty( $import_id ) ) {
  4003 		if ( ! empty( $import_id ) ) {
  3738 			$import_id = (int) $import_id;
  4004 			$import_id = (int) $import_id;
       
  4005 
  3739 			if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID = %d", $import_id ) ) ) {
  4006 			if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE ID = %d", $import_id ) ) ) {
  3740 				$data['ID'] = $import_id;
  4007 				$data['ID'] = $import_id;
  3741 			}
  4008 			}
  3742 		}
  4009 		}
       
  4010 
  3743 		if ( false === $wpdb->insert( $wpdb->posts, $data ) ) {
  4011 		if ( false === $wpdb->insert( $wpdb->posts, $data ) ) {
  3744 			if ( $wp_error ) {
  4012 			if ( $wp_error ) {
  3745 				return new WP_Error( 'db_insert_error', __( 'Could not insert post into the database' ), $wpdb->last_error );
  4013 				if ( 'attachment' === $post_type ) {
       
  4014 					$message = __( 'Could not insert attachment into the database.' );
       
  4015 				} else {
       
  4016 					$message = __( 'Could not insert post into the database.' );
       
  4017 				}
       
  4018 
       
  4019 				return new WP_Error( 'db_insert_error', $message, $wpdb->last_error );
  3746 			} else {
  4020 			} else {
  3747 				return 0;
  4021 				return 0;
  3748 			}
  4022 			}
  3749 		}
  4023 		}
       
  4024 
  3750 		$post_ID = (int) $wpdb->insert_id;
  4025 		$post_ID = (int) $wpdb->insert_id;
  3751 
  4026 
  3752 		// Use the newly generated $post_ID.
  4027 		// Use the newly generated $post_ID.
  3753 		$where = array( 'ID' => $post_ID );
  4028 		$where = array( 'ID' => $post_ID );
  3754 	}
  4029 	}
  3755 
  4030 
  3756 	if ( empty( $data['post_name'] ) && ! in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) ) {
  4031 	if ( empty( $data['post_name'] ) && ! in_array( $data['post_status'], array( 'draft', 'pending', 'auto-draft' ), true ) ) {
  3757 		$data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_title'], $post_ID ), $post_ID, $data['post_status'], $post_type, $post_parent );
  4032 		$data['post_name'] = wp_unique_post_slug( sanitize_title( $data['post_title'], $post_ID ), $post_ID, $data['post_status'], $post_type, $post_parent );
       
  4033 
  3758 		$wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where );
  4034 		$wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where );
  3759 		clean_post_cache( $post_ID );
  4035 		clean_post_cache( $post_ID );
  3760 	}
  4036 	}
  3761 
  4037 
  3762 	if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
  4038 	if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
  3763 		wp_set_post_categories( $post_ID, $post_category );
  4039 		wp_set_post_categories( $post_ID, $post_category );
  3764 	}
  4040 	}
  3765 
  4041 
  3766 	if ( isset( $postarr['tags_input'] ) && is_object_in_taxonomy( $post_type, 'post_tag' ) ) {
  4042 	if ( isset( $postarr['tags_input'] ) && is_object_in_taxonomy( $post_type, 'post_tag' ) ) {
  3767 		wp_set_post_tags( $post_ID, $postarr['tags_input'] );
  4043 		wp_set_post_tags( $post_ID, $postarr['tags_input'] );
       
  4044 	}
       
  4045 
       
  4046 	// Add default term for all associated custom taxonomies.
       
  4047 	if ( 'auto-draft' !== $post_status ) {
       
  4048 		foreach ( get_object_taxonomies( $post_type, 'object' ) as $taxonomy => $tax_object ) {
       
  4049 
       
  4050 			if ( ! empty( $tax_object->default_term ) ) {
       
  4051 
       
  4052 				// Filter out empty terms.
       
  4053 				if ( isset( $postarr['tax_input'] ) && is_array( $postarr['tax_input'][ $taxonomy ] ) ) {
       
  4054 					$postarr['tax_input'][ $taxonomy ] = array_filter( $postarr['tax_input'][ $taxonomy ] );
       
  4055 				}
       
  4056 
       
  4057 				// Passed custom taxonomy list overwrites the existing list if not empty.
       
  4058 				$terms = wp_get_object_terms( $post_ID, $taxonomy, array( 'fields' => 'ids' ) );
       
  4059 				if ( ! empty( $terms ) && empty( $postarr['tax_input'][ $taxonomy ] ) ) {
       
  4060 					$postarr['tax_input'][ $taxonomy ] = $terms;
       
  4061 				}
       
  4062 
       
  4063 				if ( empty( $postarr['tax_input'][ $taxonomy ] ) ) {
       
  4064 					$default_term_id = get_option( 'default_term_' . $taxonomy );
       
  4065 					if ( ! empty( $default_term_id ) ) {
       
  4066 						$postarr['tax_input'][ $taxonomy ] = array( (int) $default_term_id );
       
  4067 					}
       
  4068 				}
       
  4069 			}
       
  4070 		}
  3768 	}
  4071 	}
  3769 
  4072 
  3770 	// New-style support for all custom taxonomies.
  4073 	// New-style support for all custom taxonomies.
  3771 	if ( ! empty( $postarr['tax_input'] ) ) {
  4074 	if ( ! empty( $postarr['tax_input'] ) ) {
  3772 		foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
  4075 		foreach ( $postarr['tax_input'] as $taxonomy => $tags ) {
  3773 			$taxonomy_obj = get_taxonomy( $taxonomy );
  4076 			$taxonomy_obj = get_taxonomy( $taxonomy );
       
  4077 
  3774 			if ( ! $taxonomy_obj ) {
  4078 			if ( ! $taxonomy_obj ) {
  3775 				/* translators: %s: taxonomy name */
  4079 				/* translators: %s: Taxonomy name. */
  3776 				_doing_it_wrong( __FUNCTION__, sprintf( __( 'Invalid taxonomy: %s.' ), $taxonomy ), '4.4.0' );
  4080 				_doing_it_wrong( __FUNCTION__, sprintf( __( 'Invalid taxonomy: %s.' ), $taxonomy ), '4.4.0' );
  3777 				continue;
  4081 				continue;
  3778 			}
  4082 			}
  3779 
  4083 
  3780 			// array = hierarchical, string = non-hierarchical.
  4084 			// array = hierarchical, string = non-hierarchical.
  3781 			if ( is_array( $tags ) ) {
  4085 			if ( is_array( $tags ) ) {
  3782 				$tags = array_filter( $tags );
  4086 				$tags = array_filter( $tags );
  3783 			}
  4087 			}
       
  4088 
  3784 			if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
  4089 			if ( current_user_can( $taxonomy_obj->cap->assign_terms ) ) {
  3785 				wp_set_post_terms( $post_ID, $tags, $taxonomy );
  4090 				wp_set_post_terms( $post_ID, $tags, $taxonomy );
  3786 			}
  4091 			}
  3787 		}
  4092 		}
  3788 	}
  4093 	}
  3794 	}
  4099 	}
  3795 
  4100 
  3796 	$current_guid = get_post_field( 'guid', $post_ID );
  4101 	$current_guid = get_post_field( 'guid', $post_ID );
  3797 
  4102 
  3798 	// Set GUID.
  4103 	// Set GUID.
  3799 	if ( ! $update && '' == $current_guid ) {
  4104 	if ( ! $update && '' === $current_guid ) {
  3800 		$wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_ID ) ), $where );
  4105 		$wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post_ID ) ), $where );
  3801 	}
  4106 	}
  3802 
  4107 
  3803 	if ( 'attachment' === $postarr['post_type'] ) {
  4108 	if ( 'attachment' === $postarr['post_type'] ) {
  3804 		if ( ! empty( $postarr['file'] ) ) {
  4109 		if ( ! empty( $postarr['file'] ) ) {
  3811 	}
  4116 	}
  3812 
  4117 
  3813 	// Set or remove featured image.
  4118 	// Set or remove featured image.
  3814 	if ( isset( $postarr['_thumbnail_id'] ) ) {
  4119 	if ( isset( $postarr['_thumbnail_id'] ) ) {
  3815 		$thumbnail_support = current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' ) || 'revision' === $post_type;
  4120 		$thumbnail_support = current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' ) || 'revision' === $post_type;
       
  4121 
  3816 		if ( ! $thumbnail_support && 'attachment' === $post_type && $post_mime_type ) {
  4122 		if ( ! $thumbnail_support && 'attachment' === $post_type && $post_mime_type ) {
  3817 			if ( wp_attachment_is( 'audio', $post_ID ) ) {
  4123 			if ( wp_attachment_is( 'audio', $post_ID ) ) {
  3818 				$thumbnail_support = post_type_supports( 'attachment:audio', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:audio' );
  4124 				$thumbnail_support = post_type_supports( 'attachment:audio', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:audio' );
  3819 			} elseif ( wp_attachment_is( 'video', $post_ID ) ) {
  4125 			} elseif ( wp_attachment_is( 'video', $post_ID ) ) {
  3820 				$thumbnail_support = post_type_supports( 'attachment:video', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:video' );
  4126 				$thumbnail_support = post_type_supports( 'attachment:video', 'thumbnail' ) || current_theme_supports( 'post-thumbnails', 'attachment:video' );
  3836 	$post = get_post( $post_ID );
  4142 	$post = get_post( $post_ID );
  3837 
  4143 
  3838 	if ( ! empty( $postarr['page_template'] ) ) {
  4144 	if ( ! empty( $postarr['page_template'] ) ) {
  3839 		$post->page_template = $postarr['page_template'];
  4145 		$post->page_template = $postarr['page_template'];
  3840 		$page_templates      = wp_get_theme()->get_page_templates( $post );
  4146 		$page_templates      = wp_get_theme()->get_page_templates( $post );
  3841 		if ( 'default' != $postarr['page_template'] && ! isset( $page_templates[ $postarr['page_template'] ] ) ) {
  4147 
       
  4148 		if ( 'default' !== $postarr['page_template'] && ! isset( $page_templates[ $postarr['page_template'] ] ) ) {
  3842 			if ( $wp_error ) {
  4149 			if ( $wp_error ) {
  3843 				return new WP_Error( 'invalid_page_template', __( 'Invalid page template.' ) );
  4150 				return new WP_Error( 'invalid_page_template', __( 'Invalid page template.' ) );
  3844 			}
  4151 			}
       
  4152 
  3845 			update_post_meta( $post_ID, '_wp_page_template', 'default' );
  4153 			update_post_meta( $post_ID, '_wp_page_template', 'default' );
  3846 		} else {
  4154 		} else {
  3847 			update_post_meta( $post_ID, '_wp_page_template', $postarr['page_template'] );
  4155 			update_post_meta( $post_ID, '_wp_page_template', $postarr['page_template'] );
  3848 		}
  4156 		}
  3849 	}
  4157 	}
  3858 			 * @since 2.0.0
  4166 			 * @since 2.0.0
  3859 			 *
  4167 			 *
  3860 			 * @param int $post_ID Attachment ID.
  4168 			 * @param int $post_ID Attachment ID.
  3861 			 */
  4169 			 */
  3862 			do_action( 'edit_attachment', $post_ID );
  4170 			do_action( 'edit_attachment', $post_ID );
       
  4171 
  3863 			$post_after = get_post( $post_ID );
  4172 			$post_after = get_post( $post_ID );
  3864 
  4173 
  3865 			/**
  4174 			/**
  3866 			 * Fires once an existing attachment has been updated.
  4175 			 * Fires once an existing attachment has been updated.
  3867 			 *
  4176 			 *
  3933 	 *
  4242 	 *
  3934 	 * @since 3.7.0
  4243 	 * @since 3.7.0
  3935 	 *
  4244 	 *
  3936 	 * @param int     $post_ID Post ID.
  4245 	 * @param int     $post_ID Post ID.
  3937 	 * @param WP_Post $post    Post object.
  4246 	 * @param WP_Post $post    Post object.
  3938 	 * @param bool    $update  Whether this is an existing post being updated or not.
  4247 	 * @param bool    $update  Whether this is an existing post being updated.
  3939 	 */
  4248 	 */
  3940 	do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );
  4249 	do_action( "save_post_{$post->post_type}", $post_ID, $post, $update );
  3941 
  4250 
  3942 	/**
  4251 	/**
  3943 	 * Fires once a post has been saved.
  4252 	 * Fires once a post has been saved.
  3944 	 *
  4253 	 *
  3945 	 * @since 1.5.0
  4254 	 * @since 1.5.0
  3946 	 *
  4255 	 *
  3947 	 * @param int     $post_ID Post ID.
  4256 	 * @param int     $post_ID Post ID.
  3948 	 * @param WP_Post $post    Post object.
  4257 	 * @param WP_Post $post    Post object.
  3949 	 * @param bool    $update  Whether this is an existing post being updated or not.
  4258 	 * @param bool    $update  Whether this is an existing post being updated.
  3950 	 */
  4259 	 */
  3951 	do_action( 'save_post', $post_ID, $post, $update );
  4260 	do_action( 'save_post', $post_ID, $post, $update );
  3952 
  4261 
  3953 	/**
  4262 	/**
  3954 	 * Fires once a post has been saved.
  4263 	 * Fires once a post has been saved.
  3955 	 *
  4264 	 *
  3956 	 * @since 2.0.0
  4265 	 * @since 2.0.0
  3957 	 *
  4266 	 *
  3958 	 * @param int     $post_ID Post ID.
  4267 	 * @param int     $post_ID Post ID.
  3959 	 * @param WP_Post $post    Post object.
  4268 	 * @param WP_Post $post    Post object.
  3960 	 * @param bool    $update  Whether this is an existing post being updated or not.
  4269 	 * @param bool    $update  Whether this is an existing post being updated.
  3961 	 */
  4270 	 */
  3962 	do_action( 'wp_insert_post', $post_ID, $post, $update );
  4271 	do_action( 'wp_insert_post', $post_ID, $post, $update );
  3963 
  4272 
  3964 	return $post_ID;
  4273 	return $post_ID;
  3965 }
  4274 }
  3973  * @since 1.0.0
  4282  * @since 1.0.0
  3974  *
  4283  *
  3975  * @param array|object $postarr  Optional. Post data. Arrays are expected to be escaped,
  4284  * @param array|object $postarr  Optional. Post data. Arrays are expected to be escaped,
  3976  *                               objects are not. Default array.
  4285  *                               objects are not. Default array.
  3977  * @param bool         $wp_error Optional. Allow return of WP_Error on failure. Default false.
  4286  * @param bool         $wp_error Optional. Allow return of WP_Error on failure. Default false.
  3978  * @return int|WP_Error The value 0 or WP_Error on failure. The post ID on success.
  4287  * @return int|WP_Error The post ID on success. The value 0 or WP_Error on failure.
  3979  */
  4288  */
  3980 function wp_update_post( $postarr = array(), $wp_error = false ) {
  4289 function wp_update_post( $postarr = array(), $wp_error = false ) {
  3981 	if ( is_object( $postarr ) ) {
  4290 	if ( is_object( $postarr ) ) {
  3982 		// Non-escaped post was passed.
  4291 		// Non-escaped post was passed.
  3983 		$postarr = get_object_vars( $postarr );
  4292 		$postarr = get_object_vars( $postarr );
  3997 	// Escape data pulled from DB.
  4306 	// Escape data pulled from DB.
  3998 	$post = wp_slash( $post );
  4307 	$post = wp_slash( $post );
  3999 
  4308 
  4000 	// Passed post category list overwrites existing category list if not empty.
  4309 	// Passed post category list overwrites existing category list if not empty.
  4001 	if ( isset( $postarr['post_category'] ) && is_array( $postarr['post_category'] )
  4310 	if ( isset( $postarr['post_category'] ) && is_array( $postarr['post_category'] )
  4002 			&& 0 != count( $postarr['post_category'] ) ) {
  4311 		&& count( $postarr['post_category'] ) > 0
       
  4312 	) {
  4003 		$post_cats = $postarr['post_category'];
  4313 		$post_cats = $postarr['post_category'];
  4004 	} else {
  4314 	} else {
  4005 		$post_cats = $post['post_category'];
  4315 		$post_cats = $post['post_category'];
  4006 	}
  4316 	}
  4007 
  4317 
  4008 	// Drafts shouldn't be assigned a date unless explicitly done so by the user.
  4318 	// Drafts shouldn't be assigned a date unless explicitly done so by the user.
  4009 	if ( isset( $post['post_status'] ) && in_array( $post['post_status'], array( 'draft', 'pending', 'auto-draft' ) ) && empty( $postarr['edit_date'] ) &&
  4319 	if ( isset( $post['post_status'] )
  4010 			( '0000-00-00 00:00:00' == $post['post_date_gmt'] ) ) {
  4320 		&& in_array( $post['post_status'], array( 'draft', 'pending', 'auto-draft' ), true )
       
  4321 		&& empty( $postarr['edit_date'] ) && ( '0000-00-00 00:00:00' === $post['post_date_gmt'] )
       
  4322 	) {
  4011 		$clear_date = true;
  4323 		$clear_date = true;
  4012 	} else {
  4324 	} else {
  4013 		$clear_date = false;
  4325 		$clear_date = false;
  4014 	}
  4326 	}
  4015 
  4327 
  4019 	if ( $clear_date ) {
  4331 	if ( $clear_date ) {
  4020 		$postarr['post_date']     = current_time( 'mysql' );
  4332 		$postarr['post_date']     = current_time( 'mysql' );
  4021 		$postarr['post_date_gmt'] = '';
  4333 		$postarr['post_date_gmt'] = '';
  4022 	}
  4334 	}
  4023 
  4335 
  4024 	if ( $postarr['post_type'] == 'attachment' ) {
  4336 	if ( 'attachment' === $postarr['post_type'] ) {
  4025 		return wp_insert_attachment( $postarr, false, 0, $wp_error );
  4337 		return wp_insert_attachment( $postarr, false, 0, $wp_error );
       
  4338 	}
       
  4339 
       
  4340 	// Discard 'tags_input' parameter if it's the same as existing post tags.
       
  4341 	if ( isset( $postarr['tags_input'] ) && is_object_in_taxonomy( $postarr['post_type'], 'post_tag' ) ) {
       
  4342 		$tags      = get_the_terms( $postarr['ID'], 'post_tag' );
       
  4343 		$tag_names = array();
       
  4344 
       
  4345 		if ( $tags && ! is_wp_error( $tags ) ) {
       
  4346 			$tag_names = wp_list_pluck( $tags, 'name' );
       
  4347 		}
       
  4348 
       
  4349 		if ( $postarr['tags_input'] === $tag_names ) {
       
  4350 			unset( $postarr['tags_input'] );
       
  4351 		}
  4026 	}
  4352 	}
  4027 
  4353 
  4028 	return wp_insert_post( $postarr, $wp_error );
  4354 	return wp_insert_post( $postarr, $wp_error );
  4029 }
  4355 }
  4030 
  4356 
  4038  * @param int|WP_Post $post Post ID or post object.
  4364  * @param int|WP_Post $post Post ID or post object.
  4039  */
  4365  */
  4040 function wp_publish_post( $post ) {
  4366 function wp_publish_post( $post ) {
  4041 	global $wpdb;
  4367 	global $wpdb;
  4042 
  4368 
  4043 	if ( ! $post = get_post( $post ) ) {
  4369 	$post = get_post( $post );
       
  4370 	if ( ! $post ) {
  4044 		return;
  4371 		return;
  4045 	}
  4372 	}
  4046 
  4373 
  4047 	if ( 'publish' == $post->post_status ) {
  4374 	if ( 'publish' === $post->post_status ) {
  4048 		return;
  4375 		return;
  4049 	}
  4376 	}
  4050 
  4377 
  4051 	$wpdb->update( $wpdb->posts, array( 'post_status' => 'publish' ), array( 'ID' => $post->ID ) );
  4378 	$wpdb->update( $wpdb->posts, array( 'post_status' => 'publish' ), array( 'ID' => $post->ID ) );
  4052 
  4379 
  4087 
  4414 
  4088 	if ( empty( $post ) ) {
  4415 	if ( empty( $post ) ) {
  4089 		return;
  4416 		return;
  4090 	}
  4417 	}
  4091 
  4418 
  4092 	if ( 'future' != $post->post_status ) {
  4419 	if ( 'future' !== $post->post_status ) {
  4093 		return;
  4420 		return;
  4094 	}
  4421 	}
  4095 
  4422 
  4096 	$time = strtotime( $post->post_date_gmt . ' GMT' );
  4423 	$time = strtotime( $post->post_date_gmt . ' GMT' );
  4097 
  4424 
  4098 	// Uh oh, someone jumped the gun!
  4425 	// Uh oh, someone jumped the gun!
  4099 	if ( $time > time() ) {
  4426 	if ( $time > time() ) {
  4100 		wp_clear_scheduled_hook( 'publish_future_post', array( $post_id ) ); // clear anything else in the system
  4427 		wp_clear_scheduled_hook( 'publish_future_post', array( $post_id ) ); // Clear anything else in the system.
  4101 		wp_schedule_single_event( $time, 'publish_future_post', array( $post_id ) );
  4428 		wp_schedule_single_event( $time, 'publish_future_post', array( $post_id ) );
  4102 		return;
  4429 		return;
  4103 	}
  4430 	}
  4104 
  4431 
  4105 	// wp_publish_post() returns no meaningful value.
  4432 	// wp_publish_post() returns no meaningful value.
  4109 /**
  4436 /**
  4110  * Computes a unique slug for the post, when given the desired slug and some post details.
  4437  * Computes a unique slug for the post, when given the desired slug and some post details.
  4111  *
  4438  *
  4112  * @since 2.8.0
  4439  * @since 2.8.0
  4113  *
  4440  *
  4114  * @global wpdb       $wpdb WordPress database abstraction object.
  4441  * @global wpdb       $wpdb       WordPress database abstraction object.
  4115  * @global WP_Rewrite $wp_rewrite
  4442  * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
  4116  *
  4443  *
  4117  * @param string $slug        The desired slug (post_name).
  4444  * @param string $slug        The desired slug (post_name).
  4118  * @param int    $post_ID     Post ID.
  4445  * @param int    $post_ID     Post ID.
  4119  * @param string $post_status No uniqueness checks are made if the post is still draft or pending.
  4446  * @param string $post_status No uniqueness checks are made if the post is still draft or pending.
  4120  * @param string $post_type   Post type.
  4447  * @param string $post_type   Post type.
  4121  * @param int    $post_parent Post parent ID.
  4448  * @param int    $post_parent Post parent ID.
  4122  * @return string Unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)
  4449  * @return string Unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)
  4123  */
  4450  */
  4124 function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent ) {
  4451 function wp_unique_post_slug( $slug, $post_ID, $post_status, $post_type, $post_parent ) {
  4125 	if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) || ( 'inherit' == $post_status && 'revision' == $post_type ) || 'user_request' === $post_type ) {
  4452 	if ( in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ), true )
       
  4453 		|| ( 'inherit' === $post_status && 'revision' === $post_type ) || 'user_request' === $post_type
       
  4454 	) {
  4126 		return $slug;
  4455 		return $slug;
  4127 	}
  4456 	}
  4128 
  4457 
  4129 	/**
  4458 	/**
  4130 	 * Filters the post slug before it is generated to be unique.
  4459 	 * Filters the post slug before it is generated to be unique.
  4132 	 * Returning a non-null value will short-circuit the
  4461 	 * Returning a non-null value will short-circuit the
  4133 	 * unique slug generation, returning the passed value instead.
  4462 	 * unique slug generation, returning the passed value instead.
  4134 	 *
  4463 	 *
  4135 	 * @since 5.1.0
  4464 	 * @since 5.1.0
  4136 	 *
  4465 	 *
  4137 	 * @param string $override_slug Short-circuit return value.
  4466 	 * @param string|null $override_slug Short-circuit return value.
  4138 	 * @param string $slug          The desired slug (post_name).
  4467 	 * @param string      $slug          The desired slug (post_name).
  4139 	 * @param int    $post_ID       Post ID.
  4468 	 * @param int         $post_ID       Post ID.
  4140 	 * @param string $post_status   The post status.
  4469 	 * @param string      $post_status   The post status.
  4141 	 * @param string $post_type     Post type.
  4470 	 * @param string      $post_type     Post type.
  4142 	 * @param int    $post_parent   Post parent ID.
  4471 	 * @param int         $post_parent   Post parent ID.
  4143 	 */
  4472 	 */
  4144 	$override_slug = apply_filters( 'pre_wp_unique_post_slug', null, $slug, $post_ID, $post_status, $post_type, $post_parent );
  4473 	$override_slug = apply_filters( 'pre_wp_unique_post_slug', null, $slug, $post_ID, $post_status, $post_type, $post_parent );
  4145 	if ( null !== $override_slug ) {
  4474 	if ( null !== $override_slug ) {
  4146 		return $override_slug;
  4475 		return $override_slug;
  4147 	}
  4476 	}
  4153 	$feeds = $wp_rewrite->feeds;
  4482 	$feeds = $wp_rewrite->feeds;
  4154 	if ( ! is_array( $feeds ) ) {
  4483 	if ( ! is_array( $feeds ) ) {
  4155 		$feeds = array();
  4484 		$feeds = array();
  4156 	}
  4485 	}
  4157 
  4486 
  4158 	if ( 'attachment' == $post_type ) {
  4487 	if ( 'attachment' === $post_type ) {
  4159 		// Attachment slugs must be unique across all types.
  4488 		// Attachment slugs must be unique across all types.
  4160 		$check_sql       = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
  4489 		$check_sql       = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
  4161 		$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) );
  4490 		$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_ID ) );
  4162 
  4491 
  4163 		/**
  4492 		/**
  4166 		 * @since 3.1.0
  4495 		 * @since 3.1.0
  4167 		 *
  4496 		 *
  4168 		 * @param bool   $bad_slug Whether the slug would be bad as an attachment slug.
  4497 		 * @param bool   $bad_slug Whether the slug would be bad as an attachment slug.
  4169 		 * @param string $slug     The post slug.
  4498 		 * @param string $slug     The post slug.
  4170 		 */
  4499 		 */
  4171 		if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || apply_filters( 'wp_unique_post_slug_is_bad_attachment_slug', false, $slug ) ) {
  4500 		$is_bad_attachment_slug = apply_filters( 'wp_unique_post_slug_is_bad_attachment_slug', false, $slug );
       
  4501 
       
  4502 		if ( $post_name_check
       
  4503 			|| in_array( $slug, $feeds, true ) || 'embed' === $slug
       
  4504 			|| $is_bad_attachment_slug
       
  4505 		) {
  4172 			$suffix = 2;
  4506 			$suffix = 2;
  4173 			do {
  4507 			do {
  4174 				$alt_post_name   = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  4508 				$alt_post_name   = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  4175 				$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_ID ) );
  4509 				$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_ID ) );
  4176 				$suffix++;
  4510 				$suffix++;
  4177 			} while ( $post_name_check );
  4511 			} while ( $post_name_check );
  4178 			$slug = $alt_post_name;
  4512 			$slug = $alt_post_name;
  4179 		}
  4513 		}
  4180 	} elseif ( is_post_type_hierarchical( $post_type ) ) {
  4514 	} elseif ( is_post_type_hierarchical( $post_type ) ) {
  4181 		if ( 'nav_menu_item' == $post_type ) {
  4515 		if ( 'nav_menu_item' === $post_type ) {
  4182 			return $slug;
  4516 			return $slug;
  4183 		}
  4517 		}
  4184 
  4518 
  4185 		/*
  4519 		/*
  4186 		 * Page slugs must be unique within their own trees. Pages are in a separate
  4520 		 * Page slugs must be unique within their own trees. Pages are in a separate
  4197 		 * @param bool   $bad_slug    Whether the post slug would be bad in a hierarchical post context.
  4531 		 * @param bool   $bad_slug    Whether the post slug would be bad in a hierarchical post context.
  4198 		 * @param string $slug        The post slug.
  4532 		 * @param string $slug        The post slug.
  4199 		 * @param string $post_type   Post type.
  4533 		 * @param string $post_type   Post type.
  4200 		 * @param int    $post_parent Post parent ID.
  4534 		 * @param int    $post_parent Post parent ID.
  4201 		 */
  4535 		 */
  4202 		if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || preg_match( "@^($wp_rewrite->pagination_base)?\d+$@", $slug ) || apply_filters( 'wp_unique_post_slug_is_bad_hierarchical_slug', false, $slug, $post_type, $post_parent ) ) {
  4536 		$is_bad_hierarchical_slug = apply_filters( 'wp_unique_post_slug_is_bad_hierarchical_slug', false, $slug, $post_type, $post_parent );
       
  4537 
       
  4538 		if ( $post_name_check
       
  4539 			|| in_array( $slug, $feeds, true ) || 'embed' === $slug
       
  4540 			|| preg_match( "@^($wp_rewrite->pagination_base)?\d+$@", $slug )
       
  4541 			|| $is_bad_hierarchical_slug
       
  4542 		) {
  4203 			$suffix = 2;
  4543 			$suffix = 2;
  4204 			do {
  4544 			do {
  4205 				$alt_post_name   = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  4545 				$alt_post_name   = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  4206 				$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID, $post_parent ) );
  4546 				$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID, $post_parent ) );
  4207 				$suffix++;
  4547 				$suffix++;
  4211 	} else {
  4551 	} else {
  4212 		// Post slugs must be unique across all posts.
  4552 		// Post slugs must be unique across all posts.
  4213 		$check_sql       = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
  4553 		$check_sql       = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
  4214 		$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );
  4554 		$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $slug, $post_type, $post_ID ) );
  4215 
  4555 
       
  4556 		$post = get_post( $post_ID );
       
  4557 
  4216 		// Prevent new post slugs that could result in URLs that conflict with date archives.
  4558 		// Prevent new post slugs that could result in URLs that conflict with date archives.
  4217 		$post                        = get_post( $post_ID );
       
  4218 		$conflicts_with_date_archive = false;
  4559 		$conflicts_with_date_archive = false;
  4219 		if ( 'post' === $post_type && ( ! $post || $post->post_name !== $slug ) && preg_match( '/^[0-9]+$/', $slug ) && $slug_num = intval( $slug ) ) {
  4560 		if ( 'post' === $post_type && ( ! $post || $post->post_name !== $slug ) && preg_match( '/^[0-9]+$/', $slug ) ) {
  4220 			$permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );
  4561 			$slug_num = intval( $slug );
  4221 			$postname_index = array_search( '%postname%', $permastructs );
  4562 
  4222 
  4563 			if ( $slug_num ) {
  4223 			/*
  4564 				$permastructs   = array_values( array_filter( explode( '/', get_option( 'permalink_structure' ) ) ) );
  4224 			 * Potential date clashes are as follows:
  4565 				$postname_index = array_search( '%postname%', $permastructs, true );
  4225 			 *
  4566 
  4226 			 * - Any integer in the first permastruct position could be a year.
  4567 				/*
  4227 			 * - An integer between 1 and 12 that follows 'year' conflicts with 'monthnum'.
  4568 				* Potential date clashes are as follows:
  4228 			 * - An integer between 1 and 31 that follows 'monthnum' conflicts with 'day'.
  4569 				*
  4229 			 */
  4570 				* - Any integer in the first permastruct position could be a year.
  4230 			if ( 0 === $postname_index ||
  4571 				* - An integer between 1 and 12 that follows 'year' conflicts with 'monthnum'.
  4231 				( $postname_index && '%year%' === $permastructs[ $postname_index - 1 ] && 13 > $slug_num ) ||
  4572 				* - An integer between 1 and 31 that follows 'monthnum' conflicts with 'day'.
  4232 				( $postname_index && '%monthnum%' === $permastructs[ $postname_index - 1 ] && 32 > $slug_num )
  4573 				*/
  4233 			) {
  4574 				if ( 0 === $postname_index ||
  4234 				$conflicts_with_date_archive = true;
  4575 					( $postname_index && '%year%' === $permastructs[ $postname_index - 1 ] && 13 > $slug_num ) ||
       
  4576 					( $postname_index && '%monthnum%' === $permastructs[ $postname_index - 1 ] && 32 > $slug_num )
       
  4577 				) {
       
  4578 					$conflicts_with_date_archive = true;
       
  4579 				}
  4235 			}
  4580 			}
  4236 		}
  4581 		}
  4237 
  4582 
  4238 		/**
  4583 		/**
  4239 		 * Filters whether the post slug would be bad as a flat slug.
  4584 		 * Filters whether the post slug would be bad as a flat slug.
  4242 		 *
  4587 		 *
  4243 		 * @param bool   $bad_slug  Whether the post slug would be bad as a flat slug.
  4588 		 * @param bool   $bad_slug  Whether the post slug would be bad as a flat slug.
  4244 		 * @param string $slug      The post slug.
  4589 		 * @param string $slug      The post slug.
  4245 		 * @param string $post_type Post type.
  4590 		 * @param string $post_type Post type.
  4246 		 */
  4591 		 */
  4247 		if ( $post_name_check || in_array( $slug, $feeds ) || 'embed' === $slug || $conflicts_with_date_archive || apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type ) ) {
  4592 		$is_bad_flat_slug = apply_filters( 'wp_unique_post_slug_is_bad_flat_slug', false, $slug, $post_type );
       
  4593 
       
  4594 		if ( $post_name_check
       
  4595 			|| in_array( $slug, $feeds, true ) || 'embed' === $slug
       
  4596 			|| $conflicts_with_date_archive
       
  4597 			|| $is_bad_flat_slug
       
  4598 		) {
  4248 			$suffix = 2;
  4599 			$suffix = 2;
  4249 			do {
  4600 			do {
  4250 				$alt_post_name   = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  4601 				$alt_post_name   = _truncate_post_slug( $slug, 200 - ( strlen( $suffix ) + 1 ) ) . "-$suffix";
  4251 				$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID ) );
  4602 				$post_name_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $alt_post_name, $post_type, $post_ID ) );
  4252 				$suffix++;
  4603 				$suffix++;
  4377 }
  4728 }
  4378 
  4729 
  4379 /**
  4730 /**
  4380  * Set categories for a post.
  4731  * Set categories for a post.
  4381  *
  4732  *
  4382  * If the post categories parameter is not set, then the default category is
  4733  * If no categories are provided, the default category is used.
  4383  * going used.
       
  4384  *
  4734  *
  4385  * @since 2.1.0
  4735  * @since 2.1.0
  4386  *
  4736  *
  4387  * @param int       $post_ID         Optional. The Post ID. Does not default to the ID
  4737  * @param int       $post_ID         Optional. The Post ID. Does not default to the ID
  4388  *                                   of the global $post. Default 0.
  4738  *                                   of the global $post. Default 0.
  4394  */
  4744  */
  4395 function wp_set_post_categories( $post_ID = 0, $post_categories = array(), $append = false ) {
  4745 function wp_set_post_categories( $post_ID = 0, $post_categories = array(), $append = false ) {
  4396 	$post_ID     = (int) $post_ID;
  4746 	$post_ID     = (int) $post_ID;
  4397 	$post_type   = get_post_type( $post_ID );
  4747 	$post_type   = get_post_type( $post_ID );
  4398 	$post_status = get_post_status( $post_ID );
  4748 	$post_status = get_post_status( $post_ID );
  4399 	// If $post_categories isn't already an array, make it one:
  4749 
       
  4750 	// If $post_categories isn't already an array, make it one.
  4400 	$post_categories = (array) $post_categories;
  4751 	$post_categories = (array) $post_categories;
       
  4752 
  4401 	if ( empty( $post_categories ) ) {
  4753 	if ( empty( $post_categories ) ) {
  4402 		if ( 'post' == $post_type && 'auto-draft' != $post_status ) {
  4754 		/**
       
  4755 		 * Filters post types (in addition to 'post') that require a default category.
       
  4756 		 *
       
  4757 		 * @since 5.5.0
       
  4758 		 *
       
  4759 		 * @param string[] $post_types An array of post type names. Default empty array.
       
  4760 		 */
       
  4761 		$default_category_post_types = apply_filters( 'default_category_post_types', array() );
       
  4762 
       
  4763 		// Regular posts always require a default category.
       
  4764 		$default_category_post_types = array_merge( $default_category_post_types, array( 'post' ) );
       
  4765 
       
  4766 		if ( in_array( $post_type, $default_category_post_types, true )
       
  4767 			&& is_object_in_taxonomy( $post_type, 'category' )
       
  4768 			&& 'auto-draft' !== $post_status
       
  4769 		) {
  4403 			$post_categories = array( get_option( 'default_category' ) );
  4770 			$post_categories = array( get_option( 'default_category' ) );
  4404 			$append          = false;
  4771 			$append          = false;
  4405 		} else {
  4772 		} else {
  4406 			$post_categories = array();
  4773 			$post_categories = array();
  4407 		}
  4774 		}
  4408 	} elseif ( 1 == count( $post_categories ) && '' == reset( $post_categories ) ) {
  4775 	} elseif ( 1 === count( $post_categories ) && '' === reset( $post_categories ) ) {
  4409 		return true;
  4776 		return true;
  4410 	}
  4777 	}
  4411 
  4778 
  4412 	return wp_set_post_terms( $post_ID, $post_categories, 'category', $append );
  4779 	return wp_set_post_terms( $post_ID, $post_categories, 'category', $append );
  4413 }
  4780 }
  4532  * Retrieve enclosures already enclosed for a post.
  4899  * Retrieve enclosures already enclosed for a post.
  4533  *
  4900  *
  4534  * @since 1.5.0
  4901  * @since 1.5.0
  4535  *
  4902  *
  4536  * @param int $post_id Post ID.
  4903  * @param int $post_id Post ID.
  4537  * @return array List of enclosures.
  4904  * @return string[] Array of enclosures for the given post.
  4538  */
  4905  */
  4539 function get_enclosed( $post_id ) {
  4906 function get_enclosed( $post_id ) {
  4540 	$custom_fields = get_post_custom( $post_id );
  4907 	$custom_fields = get_post_custom( $post_id );
  4541 	$pung          = array();
  4908 	$pung          = array();
  4542 	if ( ! is_array( $custom_fields ) ) {
  4909 	if ( ! is_array( $custom_fields ) ) {
  4543 		return $pung;
  4910 		return $pung;
  4544 	}
  4911 	}
  4545 
  4912 
  4546 	foreach ( $custom_fields as $key => $val ) {
  4913 	foreach ( $custom_fields as $key => $val ) {
  4547 		if ( 'enclosure' != $key || ! is_array( $val ) ) {
  4914 		if ( 'enclosure' !== $key || ! is_array( $val ) ) {
  4548 			continue;
  4915 			continue;
  4549 		}
  4916 		}
  4550 		foreach ( $val as $enc ) {
  4917 		foreach ( $val as $enc ) {
  4551 			$enclosure = explode( "\n", $enc );
  4918 			$enclosure = explode( "\n", $enc );
  4552 			$pung[]    = trim( $enclosure[0] );
  4919 			$pung[]    = trim( $enclosure[0] );
  4556 	/**
  4923 	/**
  4557 	 * Filters the list of enclosures already enclosed for the given post.
  4924 	 * Filters the list of enclosures already enclosed for the given post.
  4558 	 *
  4925 	 *
  4559 	 * @since 2.0.0
  4926 	 * @since 2.0.0
  4560 	 *
  4927 	 *
  4561 	 * @param array $pung    Array of enclosures for the given post.
  4928 	 * @param string[] $pung    Array of enclosures for the given post.
  4562 	 * @param int   $post_id Post ID.
  4929 	 * @param int      $post_id Post ID.
  4563 	 */
  4930 	 */
  4564 	return apply_filters( 'get_enclosed', $pung, $post_id );
  4931 	return apply_filters( 'get_enclosed', $pung, $post_id );
  4565 }
  4932 }
  4566 
  4933 
  4567 /**
  4934 /**
  4598  *
  4965  *
  4599  * @since 1.5.0
  4966  * @since 1.5.0
  4600  * @since 4.7.0 `$post_id` can be a WP_Post object.
  4967  * @since 4.7.0 `$post_id` can be a WP_Post object.
  4601  *
  4968  *
  4602  * @param int|WP_Post $post_id Post Object or ID
  4969  * @param int|WP_Post $post_id Post Object or ID
  4603  * @return array
  4970  * @return string[]|false List of URLs yet to ping.
  4604  */
  4971  */
  4605 function get_to_ping( $post_id ) {
  4972 function get_to_ping( $post_id ) {
  4606 	$post = get_post( $post_id );
  4973 	$post = get_post( $post_id );
  4607 
  4974 
  4608 	if ( ! $post ) {
  4975 	if ( ! $post ) {
  4615 	/**
  4982 	/**
  4616 	 * Filters the list of URLs yet to ping for the given post.
  4983 	 * Filters the list of URLs yet to ping for the given post.
  4617 	 *
  4984 	 *
  4618 	 * @since 2.0.0
  4985 	 * @since 2.0.0
  4619 	 *
  4986 	 *
  4620 	 * @param array $to_ping List of URLs yet to ping.
  4987 	 * @param string[] $to_ping List of URLs yet to ping.
  4621 	 */
  4988 	 */
  4622 	return apply_filters( 'get_to_ping', $to_ping );
  4989 	return apply_filters( 'get_to_ping', $to_ping );
  4623 }
  4990 }
  4624 
  4991 
  4625 /**
  4992 /**
  4649 		}
  5016 		}
  4650 	}
  5017 	}
  4651 }
  5018 }
  4652 
  5019 
  4653 //
  5020 //
  4654 // Page functions
  5021 // Page functions.
  4655 //
  5022 //
  4656 
  5023 
  4657 /**
  5024 /**
  4658  * Get a list of page IDs.
  5025  * Get a list of page IDs.
  4659  *
  5026  *
  4660  * @since 2.0.0
  5027  * @since 2.0.0
  4661  *
  5028  *
  4662  * @global wpdb $wpdb WordPress database abstraction object.
  5029  * @global wpdb $wpdb WordPress database abstraction object.
  4663  *
  5030  *
  4664  * @return array List of page IDs.
  5031  * @return string[] List of page IDs as strings.
  4665  */
  5032  */
  4666 function get_all_page_ids() {
  5033 function get_all_page_ids() {
  4667 	global $wpdb;
  5034 	global $wpdb;
  4668 
  5035 
  4669 	$page_ids = wp_cache_get( 'all_page_ids', 'posts' );
  5036 	$page_ids = wp_cache_get( 'all_page_ids', 'posts' );
  4681  * Use get_post() instead of get_page().
  5048  * Use get_post() instead of get_page().
  4682  *
  5049  *
  4683  * @since 1.5.1
  5050  * @since 1.5.1
  4684  * @deprecated 3.5.0 Use get_post()
  5051  * @deprecated 3.5.0 Use get_post()
  4685  *
  5052  *
  4686  * @param mixed  $page   Page object or page ID. Passed by reference.
  5053  * @param int|WP_Post $page   Page object or page ID. Passed by reference.
  4687  * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
  5054  * @param string      $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
  4688  *                       a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
  5055  *                            correspond to a WP_Post object, an associative array, or a numeric array,
  4689  * @param string $filter Optional. How the return value should be filtered. Accepts 'raw',
  5056  *                            respectively. Default OBJECT.
  4690  *                       'edit', 'db', 'display'. Default 'raw'.
  5057  * @param string      $filter Optional. How the return value should be filtered. Accepts 'raw',
  4691  * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
  5058  *                            'edit', 'db', 'display'. Default 'raw'.
       
  5059  * @return WP_Post|array|null WP_Post or array on success, null on failure.
  4692  */
  5060  */
  4693 function get_page( $page, $output = OBJECT, $filter = 'raw' ) {
  5061 function get_page( $page, $output = OBJECT, $filter = 'raw' ) {
  4694 	return get_post( $page, $output, $filter );
  5062 	return get_post( $page, $output, $filter );
  4695 }
  5063 }
  4696 
  5064 
  4700  * @since 2.1.0
  5068  * @since 2.1.0
  4701  *
  5069  *
  4702  * @global wpdb $wpdb WordPress database abstraction object.
  5070  * @global wpdb $wpdb WordPress database abstraction object.
  4703  *
  5071  *
  4704  * @param string       $page_path Page path.
  5072  * @param string       $page_path Page path.
  4705  * @param string       $output    Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
  5073  * @param string       $output    Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
  4706  *                                a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
  5074  *                                correspond to a WP_Post object, an associative array, or a numeric array,
       
  5075  *                                respectively. Default OBJECT.
  4707  * @param string|array $post_type Optional. Post type or array of post types. Default 'page'.
  5076  * @param string|array $post_type Optional. Post type or array of post types. Default 'page'.
  4708  * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
  5077  * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
  4709  */
  5078  */
  4710 function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
  5079 function get_page_by_path( $page_path, $output = OBJECT, $post_type = 'page' ) {
  4711 	global $wpdb;
  5080 	global $wpdb;
  4760 
  5129 
  4761 			/*
  5130 			/*
  4762 			 * Loop through the given path parts from right to left,
  5131 			 * Loop through the given path parts from right to left,
  4763 			 * ensuring each matches the post ancestry.
  5132 			 * ensuring each matches the post ancestry.
  4764 			 */
  5133 			 */
  4765 			while ( $p->post_parent != 0 && isset( $pages[ $p->post_parent ] ) ) {
  5134 			while ( 0 != $p->post_parent && isset( $pages[ $p->post_parent ] ) ) {
  4766 				$count++;
  5135 				$count++;
  4767 				$parent = $pages[ $p->post_parent ];
  5136 				$parent = $pages[ $p->post_parent ];
  4768 				if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] ) {
  5137 				if ( ! isset( $revparts[ $count ] ) || $parent->post_name != $revparts[ $count ] ) {
  4769 					break;
  5138 					break;
  4770 				}
  5139 				}
  4771 				$p = $parent;
  5140 				$p = $parent;
  4772 			}
  5141 			}
  4773 
  5142 
  4774 			if ( $p->post_parent == 0 && $count + 1 == count( $revparts ) && $p->post_name == $revparts[ $count ] ) {
  5143 			if ( 0 == $p->post_parent && count( $revparts ) == $count + 1 && $p->post_name == $revparts[ $count ] ) {
  4775 				$foundid = $page->ID;
  5144 				$foundid = $page->ID;
  4776 				if ( $page->post_type == $post_type ) {
  5145 				if ( $page->post_type == $post_type ) {
  4777 					break;
  5146 					break;
  4778 				}
  5147 				}
  4779 			}
  5148 			}
  4789 }
  5158 }
  4790 
  5159 
  4791 /**
  5160 /**
  4792  * Retrieve a page given its title.
  5161  * Retrieve a page given its title.
  4793  *
  5162  *
       
  5163  * If more than one post uses the same title, the post with the smallest ID will be returned.
       
  5164  * Be careful: in case of more than one post having the same title, it will check the oldest
       
  5165  * publication date, not the smallest ID.
       
  5166  *
       
  5167  * Because this function uses the MySQL '=' comparison, $page_title will usually be matched
       
  5168  * as case-insensitive with default collation.
       
  5169  *
  4794  * @since 2.1.0
  5170  * @since 2.1.0
       
  5171  * @since 3.0.0 The `$post_type` parameter was added.
  4795  *
  5172  *
  4796  * @global wpdb $wpdb WordPress database abstraction object.
  5173  * @global wpdb $wpdb WordPress database abstraction object.
  4797  *
  5174  *
  4798  * @param string       $page_title Page title
  5175  * @param string       $page_title Page title.
  4799  * @param string       $output     Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to
  5176  * @param string       $output     Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which
  4800  *                                 a WP_Post object, an associative array, or a numeric array, respectively. Default OBJECT.
  5177  *                                 correspond to a WP_Post object, an associative array, or a numeric array,
       
  5178  *                                 respectively. Default OBJECT.
  4801  * @param string|array $post_type  Optional. Post type or array of post types. Default 'page'.
  5179  * @param string|array $post_type  Optional. Post type or array of post types. Default 'page'.
  4802  * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
  5180  * @return WP_Post|array|null WP_Post (or array) on success, or null on failure.
  4803  */
  5181  */
  4804 function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) {
  5182 function get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) {
  4805 	global $wpdb;
  5183 	global $wpdb;
  4882  * It uses auxiliary structure to hold parent-children relationships and
  5260  * It uses auxiliary structure to hold parent-children relationships and
  4883  * runs in O(N) complexity
  5261  * runs in O(N) complexity
  4884  *
  5262  *
  4885  * @since 2.0.0
  5263  * @since 2.0.0
  4886  *
  5264  *
  4887  * @param array $pages   Posts array (passed by reference).
  5265  * @param WP_Post[] $pages   Posts array (passed by reference).
  4888  * @param int   $page_id Optional. Parent page ID. Default 0.
  5266  * @param int       $page_id Optional. Parent page ID. Default 0.
  4889  * @return array A list arranged by hierarchy. Children immediately follow their parents.
  5267  * @return string[] Array of post names keyed by ID and arranged by hierarchy. Children immediately follow their parents.
  4890  */
  5268  */
  4891 function get_page_hierarchy( &$pages, $page_id = 0 ) {
  5269 function get_page_hierarchy( &$pages, $page_id = 0 ) {
  4892 	if ( empty( $pages ) ) {
  5270 	if ( empty( $pages ) ) {
  4893 		return array();
  5271 		return array();
  4894 	}
  5272 	}
  4913  * @since 2.9.0
  5291  * @since 2.9.0
  4914  * @access private
  5292  * @access private
  4915  *
  5293  *
  4916  * @see _page_traverse_name()
  5294  * @see _page_traverse_name()
  4917  *
  5295  *
  4918  * @param int   $page_id   Page ID.
  5296  * @param int      $page_id  Page ID.
  4919  * @param array $children  Parent-children relations (passed by reference).
  5297  * @param array    $children Parent-children relations (passed by reference).
  4920  * @param array $result    Result (passed by reference).
  5298  * @param string[] $result   Array of page names keyed by ID (passed by reference).
  4921  */
  5299  */
  4922 function _page_traverse_name( $page_id, &$children, &$result ) {
  5300 function _page_traverse_name( $page_id, &$children, &$result ) {
  4923 	if ( isset( $children[ $page_id ] ) ) {
  5301 	if ( isset( $children[ $page_id ] ) ) {
  4924 		foreach ( (array) $children[ $page_id ] as $child ) {
  5302 		foreach ( (array) $children[ $page_id ] as $child ) {
  4925 			$result[ $child->ID ] = $child->post_name;
  5303 			$result[ $child->ID ] = $child->post_name;
  4932  * Build the URI path for a page.
  5310  * Build the URI path for a page.
  4933  *
  5311  *
  4934  * Sub pages will be in the "directory" under the parent page post name.
  5312  * Sub pages will be in the "directory" under the parent page post name.
  4935  *
  5313  *
  4936  * @since 1.5.0
  5314  * @since 1.5.0
  4937  * @since 4.6.0 Converted the `$page` parameter to optional.
  5315  * @since 4.6.0 The `$page` parameter was made optional.
  4938  *
  5316  *
  4939  * @param WP_Post|object|int $page Optional. Page ID or WP_Post object. Default is global $post.
  5317  * @param WP_Post|object|int $page Optional. Page ID or WP_Post object. Default is global $post.
  4940  * @return string|false Page URI, false on error.
  5318  * @return string|false Page URI, false on error.
  4941  */
  5319  */
  4942 function get_page_uri( $page = 0 ) {
  5320 function get_page_uri( $page = 0 ) {
  5029 		'offset'       => 0,
  5407 		'offset'       => 0,
  5030 		'post_type'    => 'page',
  5408 		'post_type'    => 'page',
  5031 		'post_status'  => 'publish',
  5409 		'post_status'  => 'publish',
  5032 	);
  5410 	);
  5033 
  5411 
  5034 	$r = wp_parse_args( $args, $defaults );
  5412 	$parsed_args = wp_parse_args( $args, $defaults );
  5035 
  5413 
  5036 	$number       = (int) $r['number'];
  5414 	$number       = (int) $parsed_args['number'];
  5037 	$offset       = (int) $r['offset'];
  5415 	$offset       = (int) $parsed_args['offset'];
  5038 	$child_of     = (int) $r['child_of'];
  5416 	$child_of     = (int) $parsed_args['child_of'];
  5039 	$hierarchical = $r['hierarchical'];
  5417 	$hierarchical = $parsed_args['hierarchical'];
  5040 	$exclude      = $r['exclude'];
  5418 	$exclude      = $parsed_args['exclude'];
  5041 	$meta_key     = $r['meta_key'];
  5419 	$meta_key     = $parsed_args['meta_key'];
  5042 	$meta_value   = $r['meta_value'];
  5420 	$meta_value   = $parsed_args['meta_value'];
  5043 	$parent       = $r['parent'];
  5421 	$parent       = $parsed_args['parent'];
  5044 	$post_status  = $r['post_status'];
  5422 	$post_status  = $parsed_args['post_status'];
  5045 
  5423 
  5046 	// Make sure the post type is hierarchical.
  5424 	// Make sure the post type is hierarchical.
  5047 	$hierarchical_post_types = get_post_types( array( 'hierarchical' => true ) );
  5425 	$hierarchical_post_types = get_post_types( array( 'hierarchical' => true ) );
  5048 	if ( ! in_array( $r['post_type'], $hierarchical_post_types ) ) {
  5426 	if ( ! in_array( $parsed_args['post_type'], $hierarchical_post_types, true ) ) {
  5049 		return false;
  5427 		return false;
  5050 	}
  5428 	}
  5051 
  5429 
  5052 	if ( $parent > 0 && ! $child_of ) {
  5430 	if ( $parent > 0 && ! $child_of ) {
  5053 		$hierarchical = false;
  5431 		$hierarchical = false;
  5060 	if ( array_diff( $post_status, get_post_stati() ) ) {
  5438 	if ( array_diff( $post_status, get_post_stati() ) ) {
  5061 		return false;
  5439 		return false;
  5062 	}
  5440 	}
  5063 
  5441 
  5064 	// $args can be whatever, only use the args defined in defaults to compute the key.
  5442 	// $args can be whatever, only use the args defined in defaults to compute the key.
  5065 	$key          = md5( serialize( wp_array_slice_assoc( $r, array_keys( $defaults ) ) ) );
  5443 	$key          = md5( serialize( wp_array_slice_assoc( $parsed_args, array_keys( $defaults ) ) ) );
  5066 	$last_changed = wp_cache_get_last_changed( 'posts' );
  5444 	$last_changed = wp_cache_get_last_changed( 'posts' );
  5067 
  5445 
  5068 	$cache_key = "get_pages:$key:$last_changed";
  5446 	$cache_key = "get_pages:$key:$last_changed";
  5069 	$cache     = wp_cache_get( $cache_key, 'posts' );
  5447 	$cache     = wp_cache_get( $cache_key, 'posts' );
  5070 	if ( false !== $cache ) {
  5448 	if ( false !== $cache ) {
  5071 		// Convert to WP_Post instances.
  5449 		// Convert to WP_Post instances.
  5072 		$pages = array_map( 'get_post', $cache );
  5450 		$pages = array_map( 'get_post', $cache );
  5073 		/** This filter is documented in wp-includes/post.php */
  5451 		/** This filter is documented in wp-includes/post.php */
  5074 		$pages = apply_filters( 'get_pages', $pages, $r );
  5452 		$pages = apply_filters( 'get_pages', $pages, $parsed_args );
  5075 		return $pages;
  5453 		return $pages;
  5076 	}
  5454 	}
  5077 
  5455 
  5078 	$inclusions = '';
  5456 	$inclusions = '';
  5079 	if ( ! empty( $r['include'] ) ) {
  5457 	if ( ! empty( $parsed_args['include'] ) ) {
  5080 		$child_of     = 0; //ignore child_of, parent, exclude, meta_key, and meta_value params if using include
  5458 		$child_of     = 0; // Ignore child_of, parent, exclude, meta_key, and meta_value params if using include.
  5081 		$parent       = -1;
  5459 		$parent       = -1;
  5082 		$exclude      = '';
  5460 		$exclude      = '';
  5083 		$meta_key     = '';
  5461 		$meta_key     = '';
  5084 		$meta_value   = '';
  5462 		$meta_value   = '';
  5085 		$hierarchical = false;
  5463 		$hierarchical = false;
  5086 		$incpages     = wp_parse_id_list( $r['include'] );
  5464 		$incpages     = wp_parse_id_list( $parsed_args['include'] );
  5087 		if ( ! empty( $incpages ) ) {
  5465 		if ( ! empty( $incpages ) ) {
  5088 			$inclusions = ' AND ID IN (' . implode( ',', $incpages ) . ')';
  5466 			$inclusions = ' AND ID IN (' . implode( ',', $incpages ) . ')';
  5089 		}
  5467 		}
  5090 	}
  5468 	}
  5091 
  5469 
  5096 			$exclusions = ' AND ID NOT IN (' . implode( ',', $expages ) . ')';
  5474 			$exclusions = ' AND ID NOT IN (' . implode( ',', $expages ) . ')';
  5097 		}
  5475 		}
  5098 	}
  5476 	}
  5099 
  5477 
  5100 	$author_query = '';
  5478 	$author_query = '';
  5101 	if ( ! empty( $r['authors'] ) ) {
  5479 	if ( ! empty( $parsed_args['authors'] ) ) {
  5102 		$post_authors = wp_parse_list( $r['authors'] );
  5480 		$post_authors = wp_parse_list( $parsed_args['authors'] );
  5103 
  5481 
  5104 		if ( ! empty( $post_authors ) ) {
  5482 		if ( ! empty( $post_authors ) ) {
  5105 			foreach ( $post_authors as $post_author ) {
  5483 			foreach ( $post_authors as $post_author ) {
  5106 				//Do we have an author id or an author login?
  5484 				// Do we have an author id or an author login?
  5107 				if ( 0 == intval( $post_author ) ) {
  5485 				if ( 0 == intval( $post_author ) ) {
  5108 					$post_author = get_user_by( 'login', $post_author );
  5486 					$post_author = get_user_by( 'login', $post_author );
  5109 					if ( empty( $post_author ) ) {
  5487 					if ( empty( $post_author ) ) {
  5110 						continue;
  5488 						continue;
  5111 					}
  5489 					}
  5113 						continue;
  5491 						continue;
  5114 					}
  5492 					}
  5115 					$post_author = $post_author->ID;
  5493 					$post_author = $post_author->ID;
  5116 				}
  5494 				}
  5117 
  5495 
  5118 				if ( '' == $author_query ) {
  5496 				if ( '' === $author_query ) {
  5119 					$author_query = $wpdb->prepare( ' post_author = %d ', $post_author );
  5497 					$author_query = $wpdb->prepare( ' post_author = %d ', $post_author );
  5120 				} else {
  5498 				} else {
  5121 					$author_query .= $wpdb->prepare( ' OR post_author = %d ', $post_author );
  5499 					$author_query .= $wpdb->prepare( ' OR post_author = %d ', $post_author );
  5122 				}
  5500 				}
  5123 			}
  5501 			}
  5124 			if ( '' != $author_query ) {
  5502 			if ( '' !== $author_query ) {
  5125 				$author_query = " AND ($author_query)";
  5503 				$author_query = " AND ($author_query)";
  5126 			}
  5504 			}
  5127 		}
  5505 		}
  5128 	}
  5506 	}
  5129 
  5507 
  5130 	$join  = '';
  5508 	$join  = '';
  5131 	$where = "$exclusions $inclusions ";
  5509 	$where = "$exclusions $inclusions ";
  5132 	if ( '' !== $meta_key || '' !== $meta_value ) {
  5510 	if ( '' !== $meta_key || '' !== $meta_value ) {
  5133 		$join = " LEFT JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )";
  5511 		$join = " LEFT JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )";
  5134 
  5512 
  5135 		// meta_key and meta_value might be slashed
  5513 		// meta_key and meta_value might be slashed.
  5136 		$meta_key   = wp_unslash( $meta_key );
  5514 		$meta_key   = wp_unslash( $meta_key );
  5137 		$meta_value = wp_unslash( $meta_value );
  5515 		$meta_value = wp_unslash( $meta_value );
  5138 		if ( '' !== $meta_key ) {
  5516 		if ( '' !== $meta_key ) {
  5139 			$where .= $wpdb->prepare( " AND $wpdb->postmeta.meta_key = %s", $meta_key );
  5517 			$where .= $wpdb->prepare( " AND $wpdb->postmeta.meta_key = %s", $meta_key );
  5140 		}
  5518 		}
  5150 		}
  5528 		}
  5151 	} elseif ( $parent >= 0 ) {
  5529 	} elseif ( $parent >= 0 ) {
  5152 		$where .= $wpdb->prepare( ' AND post_parent = %d ', $parent );
  5530 		$where .= $wpdb->prepare( ' AND post_parent = %d ', $parent );
  5153 	}
  5531 	}
  5154 
  5532 
  5155 	if ( 1 == count( $post_status ) ) {
  5533 	if ( 1 === count( $post_status ) ) {
  5156 		$where_post_type = $wpdb->prepare( 'post_type = %s AND post_status = %s', $r['post_type'], reset( $post_status ) );
  5534 		$where_post_type = $wpdb->prepare( 'post_type = %s AND post_status = %s', $parsed_args['post_type'], reset( $post_status ) );
  5157 	} else {
  5535 	} else {
  5158 		$post_status     = implode( "', '", $post_status );
  5536 		$post_status     = implode( "', '", $post_status );
  5159 		$where_post_type = $wpdb->prepare( "post_type = %s AND post_status IN ('$post_status')", $r['post_type'] );
  5537 		$where_post_type = $wpdb->prepare( "post_type = %s AND post_status IN ('$post_status')", $parsed_args['post_type'] );
  5160 	}
  5538 	}
  5161 
  5539 
  5162 	$orderby_array = array();
  5540 	$orderby_array = array();
  5163 	$allowed_keys  = array(
  5541 	$allowed_keys  = array(
  5164 		'author',
  5542 		'author',
  5179 		'ID',
  5557 		'ID',
  5180 		'rand',
  5558 		'rand',
  5181 		'comment_count',
  5559 		'comment_count',
  5182 	);
  5560 	);
  5183 
  5561 
  5184 	foreach ( explode( ',', $r['sort_column'] ) as $orderby ) {
  5562 	foreach ( explode( ',', $parsed_args['sort_column'] ) as $orderby ) {
  5185 		$orderby = trim( $orderby );
  5563 		$orderby = trim( $orderby );
  5186 		if ( ! in_array( $orderby, $allowed_keys ) ) {
  5564 		if ( ! in_array( $orderby, $allowed_keys, true ) ) {
  5187 			continue;
  5565 			continue;
  5188 		}
  5566 		}
  5189 
  5567 
  5190 		switch ( $orderby ) {
  5568 		switch ( $orderby ) {
  5191 			case 'menu_order':
  5569 			case 'menu_order':
  5210 		$orderby_array[] = $orderby;
  5588 		$orderby_array[] = $orderby;
  5211 
  5589 
  5212 	}
  5590 	}
  5213 	$sort_column = ! empty( $orderby_array ) ? implode( ',', $orderby_array ) : "$wpdb->posts.post_title";
  5591 	$sort_column = ! empty( $orderby_array ) ? implode( ',', $orderby_array ) : "$wpdb->posts.post_title";
  5214 
  5592 
  5215 	$sort_order = strtoupper( $r['sort_order'] );
  5593 	$sort_order = strtoupper( $parsed_args['sort_order'] );
  5216 	if ( '' !== $sort_order && ! in_array( $sort_order, array( 'ASC', 'DESC' ) ) ) {
  5594 	if ( '' !== $sort_order && ! in_array( $sort_order, array( 'ASC', 'DESC' ), true ) ) {
  5217 		$sort_order = 'ASC';
  5595 		$sort_order = 'ASC';
  5218 	}
  5596 	}
  5219 
  5597 
  5220 	$query  = "SELECT * FROM $wpdb->posts $join WHERE ($where_post_type) $where ";
  5598 	$query  = "SELECT * FROM $wpdb->posts $join WHERE ($where_post_type) $where ";
  5221 	$query .= $author_query;
  5599 	$query .= $author_query;
  5229 
  5607 
  5230 	if ( empty( $pages ) ) {
  5608 	if ( empty( $pages ) ) {
  5231 		wp_cache_set( $cache_key, array(), 'posts' );
  5609 		wp_cache_set( $cache_key, array(), 'posts' );
  5232 
  5610 
  5233 		/** This filter is documented in wp-includes/post.php */
  5611 		/** This filter is documented in wp-includes/post.php */
  5234 		$pages = apply_filters( 'get_pages', array(), $r );
  5612 		$pages = apply_filters( 'get_pages', array(), $parsed_args );
  5235 		return $pages;
  5613 		return $pages;
  5236 	}
  5614 	}
  5237 
  5615 
  5238 	// Sanitize before caching so it'll only get done once.
  5616 	// Sanitize before caching so it'll only get done once.
  5239 	$num_pages = count( $pages );
  5617 	$num_pages = count( $pages );
  5246 
  5624 
  5247 	if ( $child_of || $hierarchical ) {
  5625 	if ( $child_of || $hierarchical ) {
  5248 		$pages = get_page_children( $child_of, $pages );
  5626 		$pages = get_page_children( $child_of, $pages );
  5249 	}
  5627 	}
  5250 
  5628 
  5251 	if ( ! empty( $r['exclude_tree'] ) ) {
  5629 	if ( ! empty( $parsed_args['exclude_tree'] ) ) {
  5252 		$exclude = wp_parse_id_list( $r['exclude_tree'] );
  5630 		$exclude = wp_parse_id_list( $parsed_args['exclude_tree'] );
  5253 		foreach ( $exclude as $id ) {
  5631 		foreach ( $exclude as $id ) {
  5254 			$children = get_page_children( $id, $pages );
  5632 			$children = get_page_children( $id, $pages );
  5255 			foreach ( $children as $child ) {
  5633 			foreach ( $children as $child ) {
  5256 				$exclude[] = $child->ID;
  5634 				$exclude[] = $child->ID;
  5257 			}
  5635 			}
  5258 		}
  5636 		}
  5259 
  5637 
  5260 		$num_pages = count( $pages );
  5638 		$num_pages = count( $pages );
  5261 		for ( $i = 0; $i < $num_pages; $i++ ) {
  5639 		for ( $i = 0; $i < $num_pages; $i++ ) {
  5262 			if ( in_array( $pages[ $i ]->ID, $exclude ) ) {
  5640 			if ( in_array( $pages[ $i ]->ID, $exclude, true ) ) {
  5263 				unset( $pages[ $i ] );
  5641 				unset( $pages[ $i ] );
  5264 			}
  5642 			}
  5265 		}
  5643 		}
  5266 	}
  5644 	}
  5267 
  5645 
  5270 		$page_structure[] = $page->ID;
  5648 		$page_structure[] = $page->ID;
  5271 	}
  5649 	}
  5272 
  5650 
  5273 	wp_cache_set( $cache_key, $page_structure, 'posts' );
  5651 	wp_cache_set( $cache_key, $page_structure, 'posts' );
  5274 
  5652 
  5275 	// Convert to WP_Post instances
  5653 	// Convert to WP_Post instances.
  5276 	$pages = array_map( 'get_post', $pages );
  5654 	$pages = array_map( 'get_post', $pages );
  5277 
  5655 
  5278 	/**
  5656 	/**
  5279 	 * Filters the retrieved list of pages.
  5657 	 * Filters the retrieved list of pages.
  5280 	 *
  5658 	 *
  5281 	 * @since 2.1.0
  5659 	 * @since 2.1.0
  5282 	 *
  5660 	 *
  5283 	 * @param array $pages List of pages to retrieve.
  5661 	 * @param WP_Post[] $pages       Array of page objects.
  5284 	 * @param array $r     Array of get_pages() arguments.
  5662 	 * @param array     $parsed_args Array of get_pages() arguments.
  5285 	 */
  5663 	 */
  5286 	return apply_filters( 'get_pages', $pages, $r );
  5664 	return apply_filters( 'get_pages', $pages, $parsed_args );
  5287 }
  5665 }
  5288 
  5666 
  5289 //
  5667 //
  5290 // Attachment functions
  5668 // Attachment functions.
  5291 //
  5669 //
  5292 
  5670 
  5293 /**
  5671 /**
  5294  * Determines whether an attachment URI is local and really an attachment.
  5672  * Determines whether an attachment URI is local and really an attachment.
  5295  *
  5673  *
  5307 		return false;
  5685 		return false;
  5308 	}
  5686 	}
  5309 	if ( strpos( $url, home_url( '/?attachment_id=' ) ) !== false ) {
  5687 	if ( strpos( $url, home_url( '/?attachment_id=' ) ) !== false ) {
  5310 		return true;
  5688 		return true;
  5311 	}
  5689 	}
  5312 	if ( $id = url_to_postid( $url ) ) {
  5690 
       
  5691 	$id = url_to_postid( $url );
       
  5692 	if ( $id ) {
  5313 		$post = get_post( $id );
  5693 		$post = get_post( $id );
  5314 		if ( 'attachment' == $post->post_type ) {
  5694 		if ( 'attachment' === $post->post_type ) {
  5315 			return true;
  5695 			return true;
  5316 		}
  5696 		}
  5317 	}
  5697 	}
  5318 	return false;
  5698 	return false;
  5319 }
  5699 }
  5365  *
  5745  *
  5366  * When an attachment is permanently deleted, the file will also be removed.
  5746  * When an attachment is permanently deleted, the file will also be removed.
  5367  * Deletion removes all post meta fields, taxonomy, comments, etc. associated
  5747  * Deletion removes all post meta fields, taxonomy, comments, etc. associated
  5368  * with the attachment (except the main post).
  5748  * with the attachment (except the main post).
  5369  *
  5749  *
  5370  * The attachment is moved to the trash instead of permanently deleted unless trash
  5750  * The attachment is moved to the Trash instead of permanently deleted unless Trash
  5371  * for media is disabled, item is already in the trash, or $force_delete is true.
  5751  * for media is disabled, item is already in the Trash, or $force_delete is true.
  5372  *
  5752  *
  5373  * @since 2.0.0
  5753  * @since 2.0.0
  5374  *
  5754  *
  5375  * @global wpdb $wpdb WordPress database abstraction object.
  5755  * @global wpdb $wpdb WordPress database abstraction object.
  5376  *
  5756  *
  5377  * @param int  $post_id      Attachment ID.
  5757  * @param int  $post_id      Attachment ID.
  5378  * @param bool $force_delete Optional. Whether to bypass trash and force deletion.
  5758  * @param bool $force_delete Optional. Whether to bypass Trash and force deletion.
  5379  *                           Default false.
  5759  *                           Default false.
  5380  * @return WP_Post|false|null Post data on success, false or null on failure.
  5760  * @return WP_Post|false|null Post data on success, false or null on failure.
  5381  */
  5761  */
  5382 function wp_delete_attachment( $post_id, $force_delete = false ) {
  5762 function wp_delete_attachment( $post_id, $force_delete = false ) {
  5383 	global $wpdb;
  5763 	global $wpdb;
  5394 		return false;
  5774 		return false;
  5395 	}
  5775 	}
  5396 
  5776 
  5397 	if ( ! $force_delete && EMPTY_TRASH_DAYS && MEDIA_TRASH && 'trash' !== $post->post_status ) {
  5777 	if ( ! $force_delete && EMPTY_TRASH_DAYS && MEDIA_TRASH && 'trash' !== $post->post_status ) {
  5398 		return wp_trash_post( $post_id );
  5778 		return wp_trash_post( $post_id );
       
  5779 	}
       
  5780 
       
  5781 	/**
       
  5782 	 * Filters whether an attachment deletion should take place.
       
  5783 	 *
       
  5784 	 * @since 5.5.0
       
  5785 	 *
       
  5786 	 * @param bool|null $delete       Whether to go forward with deletion.
       
  5787 	 * @param WP_Post   $post         Post object.
       
  5788 	 * @param bool      $force_delete Whether to bypass the Trash.
       
  5789 	 */
       
  5790 	$check = apply_filters( 'pre_delete_attachment', null, $post, $force_delete );
       
  5791 	if ( null !== $check ) {
       
  5792 		return $check;
  5399 	}
  5793 	}
  5400 
  5794 
  5401 	delete_post_meta( $post_id, '_wp_trash_meta_status' );
  5795 	delete_post_meta( $post_id, '_wp_trash_meta_status' );
  5402 	delete_post_meta( $post_id, '_wp_trash_meta_time' );
  5796 	delete_post_meta( $post_id, '_wp_trash_meta_time' );
  5403 
  5797 
  5411 
  5805 
  5412 	/**
  5806 	/**
  5413 	 * Fires before an attachment is deleted, at the start of wp_delete_attachment().
  5807 	 * Fires before an attachment is deleted, at the start of wp_delete_attachment().
  5414 	 *
  5808 	 *
  5415 	 * @since 2.0.0
  5809 	 * @since 2.0.0
  5416 	 *
  5810 	 * @since 5.5.0 Added the `$post` parameter.
  5417 	 * @param int $post_id Attachment ID.
  5811 	 *
       
  5812 	 * @param int     $post_id Attachment ID.
       
  5813 	 * @param WP_Post $post    Post object.
  5418 	 */
  5814 	 */
  5419 	do_action( 'delete_attachment', $post_id );
  5815 	do_action( 'delete_attachment', $post_id, $post );
  5420 
  5816 
  5421 	wp_delete_object_term_relationships( $post_id, array( 'category', 'post_tag' ) );
  5817 	wp_delete_object_term_relationships( $post_id, array( 'category', 'post_tag' ) );
  5422 	wp_delete_object_term_relationships( $post_id, get_object_taxonomies( $post->post_type ) );
  5818 	wp_delete_object_term_relationships( $post_id, get_object_taxonomies( $post->post_type ) );
  5423 
  5819 
  5424 	// Delete all for any posts.
  5820 	// Delete all for any posts.
  5437 	foreach ( $post_meta_ids as $mid ) {
  5833 	foreach ( $post_meta_ids as $mid ) {
  5438 		delete_metadata_by_mid( 'post', $mid );
  5834 		delete_metadata_by_mid( 'post', $mid );
  5439 	}
  5835 	}
  5440 
  5836 
  5441 	/** This action is documented in wp-includes/post.php */
  5837 	/** This action is documented in wp-includes/post.php */
  5442 	do_action( 'delete_post', $post_id );
  5838 	do_action( 'delete_post', $post_id, $post );
  5443 	$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $post_id ) );
  5839 	$result = $wpdb->delete( $wpdb->posts, array( 'ID' => $post_id ) );
  5444 	if ( ! $result ) {
  5840 	if ( ! $result ) {
  5445 		return false;
  5841 		return false;
  5446 	}
  5842 	}
  5447 	/** This action is documented in wp-includes/post.php */
  5843 	/** This action is documented in wp-includes/post.php */
  5448 	do_action( 'deleted_post', $post_id );
  5844 	do_action( 'deleted_post', $post_id, $post );
  5449 
  5845 
  5450 	wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file );
  5846 	wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file );
  5451 
  5847 
  5452 	clean_post_cache( $post );
  5848 	clean_post_cache( $post );
  5453 
  5849 
  5473 
  5869 
  5474 	if ( ! empty( $meta['thumb'] ) ) {
  5870 	if ( ! empty( $meta['thumb'] ) ) {
  5475 		// Don't delete the thumb if another attachment uses it.
  5871 		// Don't delete the thumb if another attachment uses it.
  5476 		if ( ! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id ) ) ) {
  5872 		if ( ! $wpdb->get_row( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_wp_attachment_metadata' AND meta_value LIKE %s AND post_id <> %d", '%' . $wpdb->esc_like( $meta['thumb'] ) . '%', $post_id ) ) ) {
  5477 			$thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
  5873 			$thumbfile = str_replace( wp_basename( $file ), $meta['thumb'], $file );
       
  5874 
  5478 			if ( ! empty( $thumbfile ) ) {
  5875 			if ( ! empty( $thumbfile ) ) {
  5479 				$thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
  5876 				$thumbfile = path_join( $uploadpath['basedir'], $thumbfile );
  5480 				$thumbdir  = path_join( $uploadpath['basedir'], dirname( $file ) );
  5877 				$thumbdir  = path_join( $uploadpath['basedir'], dirname( $file ) );
  5481 
  5878 
  5482 				if ( ! wp_delete_file_from_directory( $thumbfile, $thumbdir ) ) {
  5879 				if ( ! wp_delete_file_from_directory( $thumbfile, $thumbdir ) ) {
  5487 	}
  5884 	}
  5488 
  5885 
  5489 	// Remove intermediate and backup images if there are any.
  5886 	// Remove intermediate and backup images if there are any.
  5490 	if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
  5887 	if ( isset( $meta['sizes'] ) && is_array( $meta['sizes'] ) ) {
  5491 		$intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
  5888 		$intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
       
  5889 
  5492 		foreach ( $meta['sizes'] as $size => $sizeinfo ) {
  5890 		foreach ( $meta['sizes'] as $size => $sizeinfo ) {
  5493 			$intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
  5891 			$intermediate_file = str_replace( wp_basename( $file ), $sizeinfo['file'], $file );
       
  5892 
  5494 			if ( ! empty( $intermediate_file ) ) {
  5893 			if ( ! empty( $intermediate_file ) ) {
  5495 				$intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
  5894 				$intermediate_file = path_join( $uploadpath['basedir'], $intermediate_file );
  5496 
  5895 
  5497 				if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
  5896 				if ( ! wp_delete_file_from_directory( $intermediate_file, $intermediate_dir ) ) {
  5498 					$deleted = false;
  5897 					$deleted = false;
  5499 				}
  5898 				}
  5500 			}
  5899 			}
  5501 		}
  5900 		}
  5502 	}
  5901 	}
  5503 
  5902 
       
  5903 	if ( ! empty( $meta['original_image'] ) ) {
       
  5904 		if ( empty( $intermediate_dir ) ) {
       
  5905 			$intermediate_dir = path_join( $uploadpath['basedir'], dirname( $file ) );
       
  5906 		}
       
  5907 
       
  5908 		$original_image = str_replace( wp_basename( $file ), $meta['original_image'], $file );
       
  5909 
       
  5910 		if ( ! empty( $original_image ) ) {
       
  5911 			$original_image = path_join( $uploadpath['basedir'], $original_image );
       
  5912 
       
  5913 			if ( ! wp_delete_file_from_directory( $original_image, $intermediate_dir ) ) {
       
  5914 				$deleted = false;
       
  5915 			}
       
  5916 		}
       
  5917 	}
       
  5918 
  5504 	if ( is_array( $backup_sizes ) ) {
  5919 	if ( is_array( $backup_sizes ) ) {
  5505 		$del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
  5920 		$del_dir = path_join( $uploadpath['basedir'], dirname( $meta['file'] ) );
       
  5921 
  5506 		foreach ( $backup_sizes as $size ) {
  5922 		foreach ( $backup_sizes as $size ) {
  5507 			$del_file = path_join( dirname( $meta['file'] ), $size['file'] );
  5923 			$del_file = path_join( dirname( $meta['file'] ), $size['file'] );
       
  5924 
  5508 			if ( ! empty( $del_file ) ) {
  5925 			if ( ! empty( $del_file ) ) {
  5509 				$del_file = path_join( $uploadpath['basedir'], $del_file );
  5926 				$del_file = path_join( $uploadpath['basedir'], $del_file );
  5510 
  5927 
  5511 				if ( ! wp_delete_file_from_directory( $del_file, $del_dir ) ) {
  5928 				if ( ! wp_delete_file_from_directory( $del_file, $del_dir ) ) {
  5512 					$deleted = false;
  5929 					$deleted = false;
  5521 
  5938 
  5522 	return $deleted;
  5939 	return $deleted;
  5523 }
  5940 }
  5524 
  5941 
  5525 /**
  5942 /**
  5526  * Retrieve attachment meta field for attachment ID.
  5943  * Retrieves attachment metadata for attachment ID.
  5527  *
  5944  *
  5528  * @since 2.1.0
  5945  * @since 2.1.0
  5529  *
  5946  *
  5530  * @param int  $attachment_id Attachment post ID. Defaults to global $post.
  5947  * @param int  $attachment_id Attachment post ID. Defaults to global $post.
  5531  * @param bool $unfiltered    Optional. If true, filters are not run. Default false.
  5948  * @param bool $unfiltered    Optional. If true, filters are not run. Default false.
  5532  * @return mixed Attachment meta field. False on failure.
  5949  * @return array|false {
       
  5950  *     Attachment metadata. False on failure.
       
  5951  *
       
  5952  *     @type int    $width      The width of the attachment.
       
  5953  *     @type int    $height     The height of the attachment.
       
  5954  *     @type string $file       The file path relative to `wp-content/uploads`.
       
  5955  *     @type array  $sizes      Keys are size slugs, each value is an array containing
       
  5956  *                              'file', 'width', 'height', and 'mime-type'.
       
  5957  *     @type array  $image_meta Image metadata.
       
  5958  * }
  5533  */
  5959  */
  5534 function wp_get_attachment_metadata( $attachment_id = 0, $unfiltered = false ) {
  5960 function wp_get_attachment_metadata( $attachment_id = 0, $unfiltered = false ) {
  5535 	$attachment_id = (int) $attachment_id;
  5961 	$attachment_id = (int) $attachment_id;
  5536 	if ( ! $post = get_post( $attachment_id ) ) {
  5962 
       
  5963 	$post = get_post( $attachment_id );
       
  5964 	if ( ! $post ) {
  5537 		return false;
  5965 		return false;
  5538 	}
  5966 	}
  5539 
  5967 
  5540 	$data = get_post_meta( $post->ID, '_wp_attachment_metadata', true );
  5968 	$data = get_post_meta( $post->ID, '_wp_attachment_metadata', true );
  5541 
  5969 
  5554 	 */
  5982 	 */
  5555 	return apply_filters( 'wp_get_attachment_metadata', $data, $post->ID );
  5983 	return apply_filters( 'wp_get_attachment_metadata', $data, $post->ID );
  5556 }
  5984 }
  5557 
  5985 
  5558 /**
  5986 /**
  5559  * Update metadata for an attachment.
  5987  * Updates metadata for an attachment.
  5560  *
  5988  *
  5561  * @since 2.1.0
  5989  * @since 2.1.0
  5562  *
  5990  *
  5563  * @param int   $attachment_id Attachment post ID.
  5991  * @param int   $attachment_id Attachment post ID.
  5564  * @param array $data          Attachment meta data.
  5992  * @param array $data          Attachment meta data.
  5565  * @return int|bool False if $post is invalid.
  5993  * @return int|bool False if $post is invalid.
  5566  */
  5994  */
  5567 function wp_update_attachment_metadata( $attachment_id, $data ) {
  5995 function wp_update_attachment_metadata( $attachment_id, $data ) {
  5568 	$attachment_id = (int) $attachment_id;
  5996 	$attachment_id = (int) $attachment_id;
  5569 	if ( ! $post = get_post( $attachment_id ) ) {
  5997 
       
  5998 	$post = get_post( $attachment_id );
       
  5999 	if ( ! $post ) {
  5570 		return false;
  6000 		return false;
  5571 	}
  6001 	}
  5572 
  6002 
  5573 	/**
  6003 	/**
  5574 	 * Filters the updated attachment meta data.
  6004 	 * Filters the updated attachment meta data.
  5576 	 * @since 2.1.0
  6006 	 * @since 2.1.0
  5577 	 *
  6007 	 *
  5578 	 * @param array $data          Array of updated attachment meta data.
  6008 	 * @param array $data          Array of updated attachment meta data.
  5579 	 * @param int   $attachment_id Attachment post ID.
  6009 	 * @param int   $attachment_id Attachment post ID.
  5580 	 */
  6010 	 */
  5581 	if ( $data = apply_filters( 'wp_update_attachment_metadata', $data, $post->ID ) ) {
  6011 	$data = apply_filters( 'wp_update_attachment_metadata', $data, $post->ID );
       
  6012 	if ( $data ) {
  5582 		return update_post_meta( $post->ID, '_wp_attachment_metadata', $data );
  6013 		return update_post_meta( $post->ID, '_wp_attachment_metadata', $data );
  5583 	} else {
  6014 	} else {
  5584 		return delete_post_meta( $post->ID, '_wp_attachment_metadata' );
  6015 		return delete_post_meta( $post->ID, '_wp_attachment_metadata' );
  5585 	}
  6016 	}
  5586 }
  6017 }
  5595  * @param int $attachment_id Optional. Attachment post ID. Defaults to global $post.
  6026  * @param int $attachment_id Optional. Attachment post ID. Defaults to global $post.
  5596  * @return string|false Attachment URL, otherwise false.
  6027  * @return string|false Attachment URL, otherwise false.
  5597  */
  6028  */
  5598 function wp_get_attachment_url( $attachment_id = 0 ) {
  6029 function wp_get_attachment_url( $attachment_id = 0 ) {
  5599 	$attachment_id = (int) $attachment_id;
  6030 	$attachment_id = (int) $attachment_id;
  5600 	if ( ! $post = get_post( $attachment_id ) ) {
  6031 
       
  6032 	$post = get_post( $attachment_id );
       
  6033 	if ( ! $post ) {
  5601 		return false;
  6034 		return false;
  5602 	}
  6035 	}
  5603 
  6036 
  5604 	if ( 'attachment' != $post->post_type ) {
  6037 	if ( 'attachment' !== $post->post_type ) {
  5605 		return false;
  6038 		return false;
  5606 	}
  6039 	}
  5607 
  6040 
  5608 	$url = '';
  6041 	$url = '';
  5609 	// Get attached file.
  6042 	// Get attached file.
  5610 	if ( $file = get_post_meta( $post->ID, '_wp_attached_file', true ) ) {
  6043 	$file = get_post_meta( $post->ID, '_wp_attached_file', true );
       
  6044 	if ( $file ) {
  5611 		// Get upload directory.
  6045 		// Get upload directory.
  5612 		if ( ( $uploads = wp_get_upload_dir() ) && false === $uploads['error'] ) {
  6046 		$uploads = wp_get_upload_dir();
       
  6047 		if ( $uploads && false === $uploads['error'] ) {
  5613 			// Check that the upload base exists in the file location.
  6048 			// Check that the upload base exists in the file location.
  5614 			if ( 0 === strpos( $file, $uploads['basedir'] ) ) {
  6049 			if ( 0 === strpos( $file, $uploads['basedir'] ) ) {
  5615 				// Replace file location with url location.
  6050 				// Replace file location with url location.
  5616 				$url = str_replace( $uploads['basedir'], $uploads['baseurl'], $file );
  6051 				$url = str_replace( $uploads['basedir'], $uploads['baseurl'], $file );
  5617 			} elseif ( false !== strpos( $file, 'wp-content/uploads' ) ) {
  6052 			} elseif ( false !== strpos( $file, 'wp-content/uploads' ) ) {
  5618 				// Get the directory name relative to the basedir (back compat for pre-2.7 uploads)
  6053 				// Get the directory name relative to the basedir (back compat for pre-2.7 uploads).
  5619 				$url = trailingslashit( $uploads['baseurl'] . '/' . _wp_get_attachment_relative_path( $file ) ) . wp_basename( $file );
  6054 				$url = trailingslashit( $uploads['baseurl'] . '/' . _wp_get_attachment_relative_path( $file ) ) . wp_basename( $file );
  5620 			} else {
  6055 			} else {
  5621 				// It's a newly-uploaded file, therefore $file is relative to the basedir.
  6056 				// It's a newly-uploaded file, therefore $file is relative to the basedir.
  5622 				$url = $uploads['baseurl'] . "/$file";
  6057 				$url = $uploads['baseurl'] . "/$file";
  5623 			}
  6058 			}
  5662  * @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`.
  6097  * @param int $post_id Optional. Attachment ID. Default is the ID of the global `$post`.
  5663  * @return string|false False on failure. Attachment caption on success.
  6098  * @return string|false False on failure. Attachment caption on success.
  5664  */
  6099  */
  5665 function wp_get_attachment_caption( $post_id = 0 ) {
  6100 function wp_get_attachment_caption( $post_id = 0 ) {
  5666 	$post_id = (int) $post_id;
  6101 	$post_id = (int) $post_id;
  5667 	if ( ! $post = get_post( $post_id ) ) {
  6102 	$post    = get_post( $post_id );
       
  6103 	if ( ! $post ) {
  5668 		return false;
  6104 		return false;
  5669 	}
  6105 	}
  5670 
  6106 
  5671 	if ( 'attachment' !== $post->post_type ) {
  6107 	if ( 'attachment' !== $post->post_type ) {
  5672 		return false;
  6108 		return false;
  5693  * @param int $post_id Optional. Attachment ID. Default 0.
  6129  * @param int $post_id Optional. Attachment ID. Default 0.
  5694  * @return string|false False on failure. Thumbnail file path on success.
  6130  * @return string|false False on failure. Thumbnail file path on success.
  5695  */
  6131  */
  5696 function wp_get_attachment_thumb_file( $post_id = 0 ) {
  6132 function wp_get_attachment_thumb_file( $post_id = 0 ) {
  5697 	$post_id = (int) $post_id;
  6133 	$post_id = (int) $post_id;
  5698 	if ( ! $post = get_post( $post_id ) ) {
  6134 	$post    = get_post( $post_id );
       
  6135 	if ( ! $post ) {
  5699 		return false;
  6136 		return false;
  5700 	}
  6137 	}
  5701 	if ( ! is_array( $imagedata = wp_get_attachment_metadata( $post->ID ) ) ) {
  6138 
       
  6139 	$imagedata = wp_get_attachment_metadata( $post->ID );
       
  6140 	if ( ! is_array( $imagedata ) ) {
  5702 		return false;
  6141 		return false;
  5703 	}
  6142 	}
  5704 
  6143 
  5705 	$file = get_attached_file( $post->ID );
  6144 	$file = get_attached_file( $post->ID );
  5706 
  6145 
  5707 	if ( ! empty( $imagedata['thumb'] ) && ( $thumbfile = str_replace( wp_basename( $file ), $imagedata['thumb'], $file ) ) && file_exists( $thumbfile ) ) {
  6146 	if ( ! empty( $imagedata['thumb'] ) ) {
  5708 		/**
  6147 		$thumbfile = str_replace( wp_basename( $file ), $imagedata['thumb'], $file );
  5709 		 * Filters the attachment thumbnail file path.
  6148 		if ( file_exists( $thumbfile ) ) {
  5710 		 *
  6149 			/**
  5711 		 * @since 2.1.0
  6150 			 * Filters the attachment thumbnail file path.
  5712 		 *
  6151 			 *
  5713 		 * @param string $thumbfile File path to the attachment thumbnail.
  6152 			 * @since 2.1.0
  5714 		 * @param int    $post_id   Attachment ID.
  6153 			 *
  5715 		 */
  6154 			 * @param string $thumbfile File path to the attachment thumbnail.
  5716 		return apply_filters( 'wp_get_attachment_thumb_file', $thumbfile, $post->ID );
  6155 			 * @param int    $post_id   Attachment ID.
       
  6156 			 */
       
  6157 			return apply_filters( 'wp_get_attachment_thumb_file', $thumbfile, $post->ID );
       
  6158 		}
  5717 	}
  6159 	}
  5718 	return false;
  6160 	return false;
  5719 }
  6161 }
  5720 
  6162 
  5721 /**
  6163 /**
  5726  * @param int $post_id Optional. Attachment ID. Default 0.
  6168  * @param int $post_id Optional. Attachment ID. Default 0.
  5727  * @return string|false False on failure. Thumbnail URL on success.
  6169  * @return string|false False on failure. Thumbnail URL on success.
  5728  */
  6170  */
  5729 function wp_get_attachment_thumb_url( $post_id = 0 ) {
  6171 function wp_get_attachment_thumb_url( $post_id = 0 ) {
  5730 	$post_id = (int) $post_id;
  6172 	$post_id = (int) $post_id;
  5731 	if ( ! $post = get_post( $post_id ) ) {
  6173 	$post    = get_post( $post_id );
       
  6174 	if ( ! $post ) {
  5732 		return false;
  6175 		return false;
  5733 	}
  6176 	}
  5734 	if ( ! $url = wp_get_attachment_url( $post->ID ) ) {
  6177 
       
  6178 	$url = wp_get_attachment_url( $post->ID );
       
  6179 	if ( ! $url ) {
  5735 		return false;
  6180 		return false;
  5736 	}
  6181 	}
  5737 
  6182 
  5738 	$sized = image_downsize( $post_id, 'thumbnail' );
  6183 	$sized = image_downsize( $post_id, 'thumbnail' );
  5739 	if ( $sized ) {
  6184 	if ( $sized ) {
  5740 		return $sized[0];
  6185 		return $sized[0];
  5741 	}
  6186 	}
  5742 
  6187 
  5743 	if ( ! $thumb = wp_get_attachment_thumb_file( $post->ID ) ) {
  6188 	$thumb = wp_get_attachment_thumb_file( $post->ID );
       
  6189 	if ( ! $thumb ) {
  5744 		return false;
  6190 		return false;
  5745 	}
  6191 	}
  5746 
  6192 
  5747 	$url = str_replace( wp_basename( $url ), wp_basename( $thumb ), $url );
  6193 	$url = str_replace( wp_basename( $url ), wp_basename( $thumb ), $url );
  5748 
  6194 
  5765  * @param string      $type Attachment type. Accepts 'image', 'audio', or 'video'.
  6211  * @param string      $type Attachment type. Accepts 'image', 'audio', or 'video'.
  5766  * @param int|WP_Post $post Optional. Attachment ID or object. Default is global $post.
  6212  * @param int|WP_Post $post Optional. Attachment ID or object. Default is global $post.
  5767  * @return bool True if one of the accepted types, false otherwise.
  6213  * @return bool True if one of the accepted types, false otherwise.
  5768  */
  6214  */
  5769 function wp_attachment_is( $type, $post = null ) {
  6215 function wp_attachment_is( $type, $post = null ) {
  5770 	if ( ! $post = get_post( $post ) ) {
  6216 	$post = get_post( $post );
       
  6217 	if ( ! $post ) {
  5771 		return false;
  6218 		return false;
  5772 	}
  6219 	}
  5773 
  6220 
  5774 	if ( ! $file = get_attached_file( $post->ID ) ) {
  6221 	$file = get_attached_file( $post->ID );
       
  6222 	if ( ! $file ) {
  5775 		return false;
  6223 		return false;
  5776 	}
  6224 	}
  5777 
  6225 
  5778 	if ( 0 === strpos( $post->post_mime_type, $type . '/' ) ) {
  6226 	if ( 0 === strpos( $post->post_mime_type, $type . '/' ) ) {
  5779 		return true;
  6227 		return true;
  5791 	}
  6239 	}
  5792 
  6240 
  5793 	switch ( $type ) {
  6241 	switch ( $type ) {
  5794 		case 'image':
  6242 		case 'image':
  5795 			$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );
  6243 			$image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );
  5796 			return in_array( $ext, $image_exts );
  6244 			return in_array( $ext, $image_exts, true );
  5797 
  6245 
  5798 		case 'audio':
  6246 		case 'audio':
  5799 			return in_array( $ext, wp_get_audio_extensions() );
  6247 			return in_array( $ext, wp_get_audio_extensions(), true );
  5800 
  6248 
  5801 		case 'video':
  6249 		case 'video':
  5802 			return in_array( $ext, wp_get_video_extensions() );
  6250 			return in_array( $ext, wp_get_video_extensions(), true );
  5803 
  6251 
  5804 		default:
  6252 		default:
  5805 			return $type === $ext;
  6253 			return $type === $ext;
  5806 	}
  6254 	}
  5807 }
  6255 }
  5823 function wp_attachment_is_image( $post = null ) {
  6271 function wp_attachment_is_image( $post = null ) {
  5824 	return wp_attachment_is( 'image', $post );
  6272 	return wp_attachment_is( 'image', $post );
  5825 }
  6273 }
  5826 
  6274 
  5827 /**
  6275 /**
  5828  * Retrieve the icon for a MIME type.
  6276  * Retrieve the icon for a MIME type or attachment.
  5829  *
  6277  *
  5830  * @since 2.1.0
  6278  * @since 2.1.0
  5831  *
  6279  *
  5832  * @param string|int $mime MIME type or attachment ID.
  6280  * @param string|int $mime MIME type or attachment ID.
  5833  * @return string|false Icon, false otherwise.
  6281  * @return string|false Icon, false otherwise.
  5840 	$post_id = 0;
  6288 	$post_id = 0;
  5841 	if ( empty( $icon ) ) {
  6289 	if ( empty( $icon ) ) {
  5842 		$post_mimes = array();
  6290 		$post_mimes = array();
  5843 		if ( is_numeric( $mime ) ) {
  6291 		if ( is_numeric( $mime ) ) {
  5844 			$mime = (int) $mime;
  6292 			$mime = (int) $mime;
  5845 			if ( $post = get_post( $mime ) ) {
  6293 			$post = get_post( $mime );
       
  6294 			if ( $post ) {
  5846 				$post_id = (int) $post->ID;
  6295 				$post_id = (int) $post->ID;
  5847 				$file    = get_attached_file( $post_id );
  6296 				$file    = get_attached_file( $post_id );
  5848 				$ext     = preg_replace( '/^.+?\.([^.]+)$/', '$1', $file );
  6297 				$ext     = preg_replace( '/^.+?\.([^.]+)$/', '$1', $file );
  5849 				if ( ! empty( $ext ) ) {
  6298 				if ( ! empty( $ext ) ) {
  5850 					$post_mimes[] = $ext;
  6299 					$post_mimes[] = $ext;
  5851 					if ( $ext_type = wp_ext2type( $ext ) ) {
  6300 					$ext_type     = wp_ext2type( $ext );
       
  6301 					if ( $ext_type ) {
  5852 						$post_mimes[] = $ext_type;
  6302 						$post_mimes[] = $ext_type;
  5853 					}
  6303 					}
  5854 				}
  6304 				}
  5855 				$mime = $post->post_mime_type;
  6305 				$mime = $post->post_mime_type;
  5856 			} else {
  6306 			} else {
  5880 			 * @param string $uri Icon directory URI.
  6330 			 * @param string $uri Icon directory URI.
  5881 			 */
  6331 			 */
  5882 			$icon_dir_uri = apply_filters( 'icon_dir_uri', includes_url( 'images/media' ) );
  6332 			$icon_dir_uri = apply_filters( 'icon_dir_uri', includes_url( 'images/media' ) );
  5883 
  6333 
  5884 			/**
  6334 			/**
  5885 			 * Filters the list of icon directory URIs.
  6335 			 * Filters the array of icon directory URIs.
  5886 			 *
  6336 			 *
  5887 			 * @since 2.5.0
  6337 			 * @since 2.5.0
  5888 			 *
  6338 			 *
  5889 			 * @param array $uris List of icon directory URIs.
  6339 			 * @param string[] $uris Array of icon directory URIs keyed by directory absolute path.
  5890 			 */
  6340 			 */
  5891 			$dirs       = apply_filters( 'icon_dirs', array( $icon_dir => $icon_dir_uri ) );
  6341 			$dirs       = apply_filters( 'icon_dirs', array( $icon_dir => $icon_dir_uri ) );
  5892 			$icon_files = array();
  6342 			$icon_files = array();
  5893 			while ( $dirs ) {
  6343 			while ( $dirs ) {
  5894 				$keys = array_keys( $dirs );
  6344 				$keys = array_keys( $dirs );
  5895 				$dir  = array_shift( $keys );
  6345 				$dir  = array_shift( $keys );
  5896 				$uri  = array_shift( $dirs );
  6346 				$uri  = array_shift( $dirs );
  5897 				if ( $dh = opendir( $dir ) ) {
  6347 				$dh   = opendir( $dir );
       
  6348 				if ( $dh ) {
  5898 					while ( false !== $file = readdir( $dh ) ) {
  6349 					while ( false !== $file = readdir( $dh ) ) {
  5899 						$file = wp_basename( $file );
  6350 						$file = wp_basename( $file );
  5900 						if ( substr( $file, 0, 1 ) == '.' ) {
  6351 						if ( '.' === substr( $file, 0, 1 ) ) {
  5901 							continue;
  6352 							continue;
  5902 						}
  6353 						}
  5903 						if ( ! in_array( strtolower( substr( $file, -4 ) ), array( '.png', '.gif', '.jpg' ) ) ) {
  6354 
       
  6355 						$ext = strtolower( substr( $file, -4 ) );
       
  6356 						if ( ! in_array( $ext, array( '.png', '.gif', '.jpg' ), true ) ) {
  5904 							if ( is_dir( "$dir/$file" ) ) {
  6357 							if ( is_dir( "$dir/$file" ) ) {
  5905 								$dirs[ "$dir/$file" ] = "$uri/$file";
  6358 								$dirs[ "$dir/$file" ] = "$uri/$file";
  5906 							}
  6359 							}
  5907 							continue;
  6360 							continue;
  5908 						}
  6361 						}
  5988 	}
  6441 	}
  5989 
  6442 
  5990 	$old_slugs = (array) get_post_meta( $post_id, '_wp_old_slug' );
  6443 	$old_slugs = (array) get_post_meta( $post_id, '_wp_old_slug' );
  5991 
  6444 
  5992 	// If we haven't added this old slug before, add it now.
  6445 	// If we haven't added this old slug before, add it now.
  5993 	if ( ! empty( $post_before->post_name ) && ! in_array( $post_before->post_name, $old_slugs ) ) {
  6446 	if ( ! empty( $post_before->post_name ) && ! in_array( $post_before->post_name, $old_slugs, true ) ) {
  5994 		add_post_meta( $post_id, '_wp_old_slug', $post_before->post_name );
  6447 		add_post_meta( $post_id, '_wp_old_slug', $post_before->post_name );
  5995 	}
  6448 	}
  5996 
  6449 
  5997 	// If the new slug was used previously, delete it from the list.
  6450 	// If the new slug was used previously, delete it from the list.
  5998 	if ( in_array( $post->post_name, $old_slugs ) ) {
  6451 	if ( in_array( $post->post_name, $old_slugs, true ) ) {
  5999 		delete_post_meta( $post_id, '_wp_old_slug', $post->post_name );
  6452 		delete_post_meta( $post_id, '_wp_old_slug', $post->post_name );
  6000 	}
  6453 	}
  6001 }
  6454 }
  6002 
  6455 
  6003 /**
  6456 /**
  6018  * @param int     $post_id     Post ID.
  6471  * @param int     $post_id     Post ID.
  6019  * @param WP_Post $post        The Post Object
  6472  * @param WP_Post $post        The Post Object
  6020  * @param WP_Post $post_before The Previous Post Object
  6473  * @param WP_Post $post_before The Previous Post Object
  6021  */
  6474  */
  6022 function wp_check_for_changed_dates( $post_id, $post, $post_before ) {
  6475 function wp_check_for_changed_dates( $post_id, $post, $post_before ) {
  6023 	$previous_date = date( 'Y-m-d', strtotime( $post_before->post_date ) );
  6476 	$previous_date = gmdate( 'Y-m-d', strtotime( $post_before->post_date ) );
  6024 	$new_date      = date( 'Y-m-d', strtotime( $post->post_date ) );
  6477 	$new_date      = gmdate( 'Y-m-d', strtotime( $post->post_date ) );
       
  6478 
  6025 	// Don't bother if it hasn't changed.
  6479 	// Don't bother if it hasn't changed.
  6026 	if ( $new_date == $previous_date ) {
  6480 	if ( $new_date == $previous_date ) {
  6027 		return;
  6481 		return;
  6028 	}
  6482 	}
       
  6483 
  6029 	// We're only concerned with published, non-hierarchical objects.
  6484 	// We're only concerned with published, non-hierarchical objects.
  6030 	if ( ! ( 'publish' === $post->post_status || ( 'attachment' === get_post_type( $post ) && 'inherit' === $post->post_status ) ) || is_post_type_hierarchical( $post->post_type ) ) {
  6485 	if ( ! ( 'publish' === $post->post_status || ( 'attachment' === get_post_type( $post ) && 'inherit' === $post->post_status ) ) || is_post_type_hierarchical( $post->post_type ) ) {
  6031 		return;
  6486 		return;
  6032 	}
  6487 	}
       
  6488 
  6033 	$old_dates = (array) get_post_meta( $post_id, '_wp_old_date' );
  6489 	$old_dates = (array) get_post_meta( $post_id, '_wp_old_date' );
       
  6490 
  6034 	// If we haven't added this old date before, add it now.
  6491 	// If we haven't added this old date before, add it now.
  6035 	if ( ! empty( $previous_date ) && ! in_array( $previous_date, $old_dates ) ) {
  6492 	if ( ! empty( $previous_date ) && ! in_array( $previous_date, $old_dates, true ) ) {
  6036 		add_post_meta( $post_id, '_wp_old_date', $previous_date );
  6493 		add_post_meta( $post_id, '_wp_old_date', $previous_date );
  6037 	}
  6494 	}
       
  6495 
  6038 	// If the new slug was used previously, delete it from the list.
  6496 	// If the new slug was used previously, delete it from the list.
  6039 	if ( in_array( $new_date, $old_dates ) ) {
  6497 	if ( in_array( $new_date, $old_dates, true ) ) {
  6040 		delete_post_meta( $post_id, '_wp_old_date', $new_date );
  6498 		delete_post_meta( $post_id, '_wp_old_date', $new_date );
  6041 	}
  6499 	}
  6042 }
  6500 }
  6043 
  6501 
  6044 /**
  6502 /**
  6066  * @since 4.3.0 Introduced the ability to pass an array of post types to `$post_type`.
  6524  * @since 4.3.0 Introduced the ability to pass an array of post types to `$post_type`.
  6067  *
  6525  *
  6068  * @see get_private_posts_cap_sql()
  6526  * @see get_private_posts_cap_sql()
  6069  * @global wpdb $wpdb WordPress database abstraction object.
  6527  * @global wpdb $wpdb WordPress database abstraction object.
  6070  *
  6528  *
  6071  * @param array|string   $post_type   Single post type or an array of post types.
  6529  * @param string|string[] $post_type   Single post type or an array of post types.
  6072  * @param bool           $full        Optional. Returns a full WHERE statement instead of just
  6530  * @param bool            $full        Optional. Returns a full WHERE statement instead of just
  6073  *                                    an 'andalso' term. Default true.
  6531  *                                     an 'andalso' term. Default true.
  6074  * @param int            $post_author Optional. Query posts having a single author ID. Default null.
  6532  * @param int             $post_author Optional. Query posts having a single author ID. Default null.
  6075  * @param bool           $public_only Optional. Only return public posts. Skips cap checks for
  6533  * @param bool            $public_only Optional. Only return public posts. Skips cap checks for
  6076  *                                    $current_user.  Default false.
  6534  *                                     $current_user.  Default false.
  6077  * @return string SQL WHERE code that can be added to a query.
  6535  * @return string SQL WHERE code that can be added to a query.
  6078  */
  6536  */
  6079 function get_posts_by_author_sql( $post_type, $full = true, $post_author = null, $public_only = false ) {
  6537 function get_posts_by_author_sql( $post_type, $full = true, $post_author = null, $public_only = false ) {
  6080 	global $wpdb;
  6538 	global $wpdb;
  6081 
  6539 
  6099 		 * @since 2.2.0
  6557 		 * @since 2.2.0
  6100 		 * @deprecated 3.2.0 The hook transitioned from "somewhat useless" to "totally useless".
  6558 		 * @deprecated 3.2.0 The hook transitioned from "somewhat useless" to "totally useless".
  6101 		 *
  6559 		 *
  6102 		 * @param string $cap Capability.
  6560 		 * @param string $cap Capability.
  6103 		 */
  6561 		 */
  6104 		if ( ! $cap = apply_filters( 'pub_priv_sql_capability', '' ) ) {
  6562 		$cap = apply_filters_deprecated( 'pub_priv_sql_capability', array( '' ), '3.2.0' );
       
  6563 		if ( ! $cap ) {
  6105 			$cap = current_user_can( $post_type_obj->cap->read_private_posts );
  6564 			$cap = current_user_can( $post_type_obj->cap->read_private_posts );
  6106 		}
  6565 		}
  6107 
  6566 
  6108 		// Only need to check the cap if $public_only is false.
  6567 		// Only need to check the cap if $public_only is false.
  6109 		$post_status_sql = "post_status = 'publish'";
  6568 		$post_status_sql = "post_status = 'publish'";
  6116 				$id = get_current_user_id();
  6575 				$id = get_current_user_id();
  6117 				if ( null === $post_author || ! $full ) {
  6576 				if ( null === $post_author || ! $full ) {
  6118 					$post_status_sql .= " OR post_status = 'private' AND post_author = $id";
  6577 					$post_status_sql .= " OR post_status = 'private' AND post_author = $id";
  6119 				} elseif ( $id == (int) $post_author ) {
  6578 				} elseif ( $id == (int) $post_author ) {
  6120 					$post_status_sql .= " OR post_status = 'private'";
  6579 					$post_status_sql .= " OR post_status = 'private'";
  6121 				} // else none
  6580 				} // Else none.
  6122 			} // else none
  6581 			} // Else none.
  6123 		}
  6582 		}
  6124 
  6583 
  6125 		$post_type_clauses[] = "( post_type = '" . $post_type . "' AND ( $post_status_sql ) )";
  6584 		$post_type_clauses[] = "( post_type = '" . $post_type . "' AND ( $post_status_sql ) )";
  6126 	}
  6585 	}
  6127 
  6586 
  6141 
  6600 
  6142 	return $sql;
  6601 	return $sql;
  6143 }
  6602 }
  6144 
  6603 
  6145 /**
  6604 /**
  6146  * Retrieve the date that the last post was published.
  6605  * Retrieves the most recent time that a post on the site was published.
  6147  *
  6606  *
  6148  * The server timezone is the default and is the difference between GMT and
  6607  * The server timezone is the default and is the difference between GMT and
  6149  * server time. The 'blog' value is the date when the last post was posted. The
  6608  * server time. The 'blog' value is the date when the last post was posted.
  6150  * 'gmt' is when the last post was posted in GMT formatted date.
  6609  * The 'gmt' is when the last post was posted in GMT formatted date.
  6151  *
  6610  *
  6152  * @since 0.71
  6611  * @since 0.71
  6153  * @since 4.4.0 The `$post_type` argument was added.
  6612  * @since 4.4.0 The `$post_type` argument was added.
  6154  *
  6613  *
  6155  * @param string $timezone  Optional. The timezone for the timestamp. Accepts 'server', 'blog', or 'gmt'.
  6614  * @param string $timezone  Optional. The timezone for the timestamp. Accepts 'server', 'blog', or 'gmt'.
  6156  *                          'server' uses the server's internal timezone.
  6615  *                          'server' uses the server's internal timezone.
  6157  *                          'blog' uses the `post_modified` field, which proxies to the timezone set for the site.
  6616  *                          'blog' uses the `post_date` field, which proxies to the timezone set for the site.
  6158  *                          'gmt' uses the `post_modified_gmt` field.
  6617  *                          'gmt' uses the `post_date_gmt` field.
  6159  *                          Default 'server'.
  6618  *                          Default 'server'.
  6160  * @param string $post_type Optional. The post type to check. Default 'any'.
  6619  * @param string $post_type Optional. The post type to check. Default 'any'.
  6161  * @return string The date of the last post.
  6620  * @return string The date of the last post, or false on failure.
  6162  */
  6621  */
  6163 function get_lastpostdate( $timezone = 'server', $post_type = 'any' ) {
  6622 function get_lastpostdate( $timezone = 'server', $post_type = 'any' ) {
       
  6623 	$lastpostdate = _get_last_post_time( $timezone, 'date', $post_type );
       
  6624 
  6164 	/**
  6625 	/**
  6165 	 * Filters the date the last post was published.
  6626 	 * Filters the most recent time that a post on the site was published.
  6166 	 *
  6627 	 *
  6167 	 * @since 2.3.0
  6628 	 * @since 2.3.0
  6168 	 *
  6629 	 * @since 5.5.0 Added the `$post_type` parameter.
  6169 	 * @param string $date     Date the last post was published.
  6630 	 *
  6170 	 * @param string $timezone Location to use for getting the post published date.
  6631 	 * @param string|false $lastpostdate The most recent time that a post was published,
  6171 	 *                         See get_lastpostdate() for accepted `$timezone` values.
  6632 	 *                                   in 'Y-m-d H:i:s' format. False on failure.
       
  6633 	 * @param string       $timezone     Location to use for getting the post published date.
       
  6634 	 *                                   See get_lastpostdate() for accepted `$timezone` values.
       
  6635 	 * @param string       $post_type    The post type to check.
  6172 	 */
  6636 	 */
  6173 	return apply_filters( 'get_lastpostdate', _get_last_post_time( $timezone, 'date', $post_type ), $timezone );
  6637 	return apply_filters( 'get_lastpostdate', $lastpostdate, $timezone, $post_type );
  6174 }
  6638 }
  6175 
  6639 
  6176 /**
  6640 /**
  6177  * Get the timestamp of the last time any post was modified.
  6641  * Get the most recent time that a post on the site was modified.
  6178  *
  6642  *
  6179  * The server timezone is the default and is the difference between GMT and
  6643  * The server timezone is the default and is the difference between GMT and
  6180  * server time. The 'blog' value is just when the last post was modified. The
  6644  * server time. The 'blog' value is just when the last post was modified.
  6181  * 'gmt' is when the last post was modified in GMT time.
  6645  * The 'gmt' is when the last post was modified in GMT time.
  6182  *
  6646  *
  6183  * @since 1.2.0
  6647  * @since 1.2.0
  6184  * @since 4.4.0 The `$post_type` argument was added.
  6648  * @since 4.4.0 The `$post_type` argument was added.
  6185  *
  6649  *
  6186  * @param string $timezone  Optional. The timezone for the timestamp. See get_lastpostdate()
  6650  * @param string $timezone  Optional. The timezone for the timestamp. See get_lastpostdate()
  6187  *                          for information on accepted values.
  6651  *                          for information on accepted values.
  6188  *                          Default 'server'.
  6652  *                          Default 'server'.
  6189  * @param string $post_type Optional. The post type to check. Default 'any'.
  6653  * @param string $post_type Optional. The post type to check. Default 'any'.
  6190  * @return string The timestamp.
  6654  * @return string The timestamp in 'Y-m-d H:i:s' format, or false on failure.
  6191  */
  6655  */
  6192 function get_lastpostmodified( $timezone = 'server', $post_type = 'any' ) {
  6656 function get_lastpostmodified( $timezone = 'server', $post_type = 'any' ) {
  6193 	/**
  6657 	/**
  6194 	 * Pre-filter the return value of get_lastpostmodified() before the query is run.
  6658 	 * Pre-filter the return value of get_lastpostmodified() before the query is run.
  6195 	 *
  6659 	 *
  6196 	 * @since 4.4.0
  6660 	 * @since 4.4.0
  6197 	 *
  6661 	 *
  6198 	 * @param string $lastpostmodified Date the last post was modified.
  6662 	 * @param string|false $lastpostmodified The most recent time that a post was modified,
  6199 	 *                                 Returning anything other than false will short-circuit the function.
  6663 	 *                                       in 'Y-m-d H:i:s' format, or false. Returning anything
  6200 	 * @param string $timezone         Location to use for getting the post modified date.
  6664 	 *                                       other than false will short-circuit the function.
  6201 	 *                                 See get_lastpostdate() for accepted `$timezone` values.
  6665 	 * @param string       $timezone         Location to use for getting the post modified date.
  6202 	 * @param string $post_type        The post type to check.
  6666 	 *                                       See get_lastpostdate() for accepted `$timezone` values.
       
  6667 	 * @param string       $post_type        The post type to check.
  6203 	 */
  6668 	 */
  6204 	$lastpostmodified = apply_filters( 'pre_get_lastpostmodified', false, $timezone, $post_type );
  6669 	$lastpostmodified = apply_filters( 'pre_get_lastpostmodified', false, $timezone, $post_type );
       
  6670 
  6205 	if ( false !== $lastpostmodified ) {
  6671 	if ( false !== $lastpostmodified ) {
  6206 		return $lastpostmodified;
  6672 		return $lastpostmodified;
  6207 	}
  6673 	}
  6208 
  6674 
  6209 	$lastpostmodified = _get_last_post_time( $timezone, 'modified', $post_type );
  6675 	$lastpostmodified = _get_last_post_time( $timezone, 'modified', $post_type );
  6210 
  6676 	$lastpostdate     = get_lastpostdate( $timezone, $post_type );
  6211 	$lastpostdate = get_lastpostdate( $timezone );
  6677 
  6212 	if ( $lastpostdate > $lastpostmodified ) {
  6678 	if ( $lastpostdate > $lastpostmodified ) {
  6213 		$lastpostmodified = $lastpostdate;
  6679 		$lastpostmodified = $lastpostdate;
  6214 	}
  6680 	}
  6215 
  6681 
  6216 	/**
  6682 	/**
  6217 	 * Filters the date the last post was modified.
  6683 	 * Filters the most recent time that a post on the site was modified.
  6218 	 *
  6684 	 *
  6219 	 * @since 2.3.0
  6685 	 * @since 2.3.0
  6220 	 *
  6686 	 * @since 5.5.0 Added the `$post_type` parameter.
  6221 	 * @param string $lastpostmodified Date the last post was modified.
  6687 	 *
  6222 	 * @param string $timezone         Location to use for getting the post modified date.
  6688 	 * @param string|false $lastpostmodified The most recent time that a post was modified,
  6223 	 *                                 See get_lastpostdate() for accepted `$timezone` values.
  6689 	 *                                       in 'Y-m-d H:i:s' format. False on failure.
       
  6690 	 * @param string       $timezone         Location to use for getting the post modified date.
       
  6691 	 *                                       See get_lastpostdate() for accepted `$timezone` values.
       
  6692 	 * @param string       $post_type        The post type to check.
  6224 	 */
  6693 	 */
  6225 	return apply_filters( 'get_lastpostmodified', $lastpostmodified, $timezone );
  6694 	return apply_filters( 'get_lastpostmodified', $lastpostmodified, $timezone, $post_type );
  6226 }
  6695 }
  6227 
  6696 
  6228 /**
  6697 /**
  6229  * Get the timestamp of the last time any post was modified or published.
  6698  * Gets the timestamp of the last time any post was modified or published.
  6230  *
  6699  *
  6231  * @since 3.1.0
  6700  * @since 3.1.0
  6232  * @since 4.4.0 The `$post_type` argument was added.
  6701  * @since 4.4.0 The `$post_type` argument was added.
  6233  * @access private
  6702  * @access private
  6234  *
  6703  *
  6236  *
  6705  *
  6237  * @param string $timezone  The timezone for the timestamp. See get_lastpostdate().
  6706  * @param string $timezone  The timezone for the timestamp. See get_lastpostdate().
  6238  *                          for information on accepted values.
  6707  *                          for information on accepted values.
  6239  * @param string $field     Post field to check. Accepts 'date' or 'modified'.
  6708  * @param string $field     Post field to check. Accepts 'date' or 'modified'.
  6240  * @param string $post_type Optional. The post type to check. Default 'any'.
  6709  * @param string $post_type Optional. The post type to check. Default 'any'.
  6241  * @return string|false The timestamp.
  6710  * @return string|false The timestamp in 'Y-m-d H:i:s' format, or false on failure.
  6242  */
  6711  */
  6243 function _get_last_post_time( $timezone, $field, $post_type = 'any' ) {
  6712 function _get_last_post_time( $timezone, $field, $post_type = 'any' ) {
  6244 	global $wpdb;
  6713 	global $wpdb;
  6245 
  6714 
  6246 	if ( ! in_array( $field, array( 'date', 'modified' ) ) ) {
  6715 	if ( ! in_array( $field, array( 'date', 'modified' ), true ) ) {
  6247 		return false;
  6716 		return false;
  6248 	}
  6717 	}
  6249 
  6718 
  6250 	$timezone = strtolower( $timezone );
  6719 	$timezone = strtolower( $timezone );
  6251 
  6720 
  6273 			break;
  6742 			break;
  6274 		case 'blog':
  6743 		case 'blog':
  6275 			$date = $wpdb->get_var( "SELECT post_{$field} FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
  6744 			$date = $wpdb->get_var( "SELECT post_{$field} FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
  6276 			break;
  6745 			break;
  6277 		case 'server':
  6746 		case 'server':
  6278 			$add_seconds_server = date( 'Z' );
  6747 			$add_seconds_server = gmdate( 'Z' );
  6279 			$date               = $wpdb->get_var( "SELECT DATE_ADD(post_{$field}_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
  6748 			$date               = $wpdb->get_var( "SELECT DATE_ADD(post_{$field}_gmt, INTERVAL '$add_seconds_server' SECOND) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY post_{$field}_gmt DESC LIMIT 1" );
  6280 			break;
  6749 			break;
  6281 	}
  6750 	}
  6282 
  6751 
  6283 	if ( $date ) {
  6752 	if ( $date ) {
  6292 /**
  6761 /**
  6293  * Updates posts in cache.
  6762  * Updates posts in cache.
  6294  *
  6763  *
  6295  * @since 1.5.1
  6764  * @since 1.5.1
  6296  *
  6765  *
  6297  * @param array $posts Array of post objects (passed by reference).
  6766  * @param WP_Post[] $posts Array of post objects (passed by reference).
  6298  */
  6767  */
  6299 function update_post_cache( &$posts ) {
  6768 function update_post_cache( &$posts ) {
  6300 	if ( ! $posts ) {
  6769 	if ( ! $posts ) {
  6301 		return;
  6770 		return;
  6302 	}
  6771 	}
  6348 	 * @param int     $post_id Post ID.
  6817 	 * @param int     $post_id Post ID.
  6349 	 * @param WP_Post $post    Post object.
  6818 	 * @param WP_Post $post    Post object.
  6350 	 */
  6819 	 */
  6351 	do_action( 'clean_post_cache', $post->ID, $post );
  6820 	do_action( 'clean_post_cache', $post->ID, $post );
  6352 
  6821 
  6353 	if ( 'page' == $post->post_type ) {
  6822 	if ( 'page' === $post->post_type ) {
  6354 		wp_cache_delete( 'all_page_ids', 'posts' );
  6823 		wp_cache_delete( 'all_page_ids', 'posts' );
  6355 
  6824 
  6356 		/**
  6825 		/**
  6357 		 * Fires immediately after the given page's cache is cleaned.
  6826 		 * Fires immediately after the given page's cache is cleaned.
  6358 		 *
  6827 		 *
  6369 /**
  6838 /**
  6370  * Call major cache updating functions for list of Post objects.
  6839  * Call major cache updating functions for list of Post objects.
  6371  *
  6840  *
  6372  * @since 1.5.0
  6841  * @since 1.5.0
  6373  *
  6842  *
  6374  * @param array  $posts             Array of Post objects
  6843  * @param WP_Post[] $posts             Array of Post objects
  6375  * @param string $post_type         Optional. Post type. Default 'post'.
  6844  * @param string    $post_type         Optional. Post type. Default 'post'.
  6376  * @param bool   $update_term_cache Optional. Whether to update the term cache. Default true.
  6845  * @param bool      $update_term_cache Optional. Whether to update the term cache. Default true.
  6377  * @param bool   $update_meta_cache Optional. Whether to update the meta cache. Default true.
  6846  * @param bool      $update_meta_cache Optional. Whether to update the meta cache. Default true.
  6378  */
  6847  */
  6379 function update_post_caches( &$posts, $post_type = 'post', $update_term_cache = true, $update_meta_cache = true ) {
  6848 function update_post_caches( &$posts, $post_type = 'post', $update_term_cache = true, $update_meta_cache = true ) {
  6380 	// No point in doing all this work if we didn't match any posts.
  6849 	// No point in doing all this work if we didn't match any posts.
  6381 	if ( ! $posts ) {
  6850 	if ( ! $posts ) {
  6382 		return;
  6851 		return;
  6394 	}
  6863 	}
  6395 
  6864 
  6396 	if ( $update_term_cache ) {
  6865 	if ( $update_term_cache ) {
  6397 		if ( is_array( $post_type ) ) {
  6866 		if ( is_array( $post_type ) ) {
  6398 			$ptypes = $post_type;
  6867 			$ptypes = $post_type;
  6399 		} elseif ( 'any' == $post_type ) {
  6868 		} elseif ( 'any' === $post_type ) {
  6400 			$ptypes = array();
  6869 			$ptypes = array();
  6401 			// Just use the post_types in the supplied posts.
  6870 			// Just use the post_types in the supplied posts.
  6402 			foreach ( $posts as $post ) {
  6871 			foreach ( $posts as $post ) {
  6403 				$ptypes[] = $post->post_type;
  6872 				$ptypes[] = $post->post_type;
  6404 			}
  6873 			}
  6424  * metadata cache for the posts. Therefore, the functions, which call this
  6893  * metadata cache for the posts. Therefore, the functions, which call this
  6425  * function, do not need to perform SQL queries on their own.
  6894  * function, do not need to perform SQL queries on their own.
  6426  *
  6895  *
  6427  * @since 2.1.0
  6896  * @since 2.1.0
  6428  *
  6897  *
  6429  * @param array $post_ids List of post IDs.
  6898  * @param int[] $post_ids Array of post IDs.
  6430  * @return array|false Returns false if there is nothing to update or an array
  6899  * @return array|false An array of metadata on success, false if there is nothing to update.
  6431  *                     of metadata.
       
  6432  */
  6900  */
  6433 function update_postmeta_cache( $post_ids ) {
  6901 function update_postmeta_cache( $post_ids ) {
  6434 	return update_meta_cache( 'post', $post_ids );
  6902 	return update_meta_cache( 'post', $post_ids );
  6435 }
  6903 }
  6436 
  6904 
  6474 	 */
  6942 	 */
  6475 	do_action( 'clean_attachment_cache', $id );
  6943 	do_action( 'clean_attachment_cache', $id );
  6476 }
  6944 }
  6477 
  6945 
  6478 //
  6946 //
  6479 // Hooks
  6947 // Hooks.
  6480 //
  6948 //
  6481 
  6949 
  6482 /**
  6950 /**
  6483  * Hook for managing future post transitions to published.
  6951  * Hook for managing future post transitions to published.
  6484  *
  6952  *
  6493  * @param WP_Post $post       Post object.
  6961  * @param WP_Post $post       Post object.
  6494  */
  6962  */
  6495 function _transition_post_status( $new_status, $old_status, $post ) {
  6963 function _transition_post_status( $new_status, $old_status, $post ) {
  6496 	global $wpdb;
  6964 	global $wpdb;
  6497 
  6965 
  6498 	if ( $old_status != 'publish' && $new_status == 'publish' ) {
  6966 	if ( 'publish' !== $old_status && 'publish' === $new_status ) {
  6499 		// Reset GUID if transitioning to publish and it is empty.
  6967 		// Reset GUID if transitioning to publish and it is empty.
  6500 		if ( '' == get_the_guid( $post->ID ) ) {
  6968 		if ( '' === get_the_guid( $post->ID ) ) {
  6501 			$wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post->ID ) ), array( 'ID' => $post->ID ) );
  6969 			$wpdb->update( $wpdb->posts, array( 'guid' => get_permalink( $post->ID ) ), array( 'ID' => $post->ID ) );
  6502 		}
  6970 		}
  6503 
  6971 
  6504 		/**
  6972 		/**
  6505 		 * Fires when a post's status is transitioned from private to published.
  6973 		 * Fires when a post's status is transitioned from private to published.
  6506 		 *
  6974 		 *
  6507 		 * @since 1.5.0
  6975 		 * @since 1.5.0
  6508 		 * @deprecated 2.3.0 Use 'private_to_publish' instead.
  6976 		 * @deprecated 2.3.0 Use {@see 'private_to_publish'} instead.
  6509 		 *
  6977 		 *
  6510 		 * @param int $post_id Post ID.
  6978 		 * @param int $post_id Post ID.
  6511 		 */
  6979 		 */
  6512 		do_action( 'private_to_published', $post->ID );
  6980 		do_action_deprecated( 'private_to_published', array( $post->ID ), '2.3.0', 'private_to_publish' );
  6513 	}
  6981 	}
  6514 
  6982 
  6515 	// If published posts changed clear the lastpostmodified cache.
  6983 	// If published posts changed clear the lastpostmodified cache.
  6516 	if ( 'publish' == $new_status || 'publish' == $old_status ) {
  6984 	if ( 'publish' === $new_status || 'publish' === $old_status ) {
  6517 		foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
  6985 		foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
  6518 			wp_cache_delete( "lastpostmodified:$timezone", 'timeinfo' );
  6986 			wp_cache_delete( "lastpostmodified:$timezone", 'timeinfo' );
  6519 			wp_cache_delete( "lastpostdate:$timezone", 'timeinfo' );
  6987 			wp_cache_delete( "lastpostdate:$timezone", 'timeinfo' );
  6520 			wp_cache_delete( "lastpostdate:$timezone:{$post->post_type}", 'timeinfo' );
  6988 			wp_cache_delete( "lastpostdate:$timezone:{$post->post_type}", 'timeinfo' );
  6521 		}
  6989 		}
  6573 	if ( defined( 'WP_IMPORTING' ) ) {
  7041 	if ( defined( 'WP_IMPORTING' ) ) {
  6574 		return;
  7042 		return;
  6575 	}
  7043 	}
  6576 
  7044 
  6577 	if ( get_option( 'default_pingback_flag' ) ) {
  7045 	if ( get_option( 'default_pingback_flag' ) ) {
  6578 		add_post_meta( $post_id, '_pingme', '1' );
  7046 		add_post_meta( $post_id, '_pingme', '1', true );
  6579 	}
  7047 	}
  6580 	add_post_meta( $post_id, '_encloseme', '1' );
  7048 	add_post_meta( $post_id, '_encloseme', '1', true );
       
  7049 
       
  7050 	$to_ping = get_to_ping( $post_id );
       
  7051 	if ( ! empty( $to_ping ) ) {
       
  7052 		add_post_meta( $post_id, '_trackbackme', '1' );
       
  7053 	}
  6581 
  7054 
  6582 	if ( ! wp_next_scheduled( 'do_pings' ) ) {
  7055 	if ( ! wp_next_scheduled( 'do_pings' ) ) {
  6583 		wp_schedule_single_event( time(), 'do_pings' );
  7056 		wp_schedule_single_event( time(), 'do_pings' );
  6584 	}
  7057 	}
  6585 }
  7058 }
  6588  * Returns the ID of the post's parent.
  7061  * Returns the ID of the post's parent.
  6589  *
  7062  *
  6590  * @since 3.1.0
  7063  * @since 3.1.0
  6591  *
  7064  *
  6592  * @param int|WP_Post $post Post ID or post object. Defaults to global $post.
  7065  * @param int|WP_Post $post Post ID or post object. Defaults to global $post.
  6593  * @return int|false Post parent ID (which can be 0 if there is no parent), or false if the post does not exist.
  7066  * @return int|false Post parent ID (which can be 0 if there is no parent),
       
  7067  *                   or false if the post does not exist.
  6594  */
  7068  */
  6595 function wp_get_post_parent_id( $post ) {
  7069 function wp_get_post_parent_id( $post ) {
  6596 	$post = get_post( $post );
  7070 	$post = get_post( $post );
  6597 	if ( ! $post || is_wp_error( $post ) ) {
  7071 	if ( ! $post || is_wp_error( $post ) ) {
  6598 		return false;
  7072 		return false;
  6629 	if ( $post_parent == $post_ID ) {
  7103 	if ( $post_parent == $post_ID ) {
  6630 		return 0;
  7104 		return 0;
  6631 	}
  7105 	}
  6632 
  7106 
  6633 	// Now look for larger loops.
  7107 	// Now look for larger loops.
  6634 	if ( ! $loop = wp_find_hierarchy_loop( 'wp_get_post_parent_id', $post_ID, $post_parent ) ) {
  7108 	$loop = wp_find_hierarchy_loop( 'wp_get_post_parent_id', $post_ID, $post_parent );
  6635 		return $post_parent; // No loop
  7109 	if ( ! $loop ) {
       
  7110 		return $post_parent; // No loop.
  6636 	}
  7111 	}
  6637 
  7112 
  6638 	// Setting $post_parent to the given value causes a loop.
  7113 	// Setting $post_parent to the given value causes a loop.
  6639 	if ( isset( $loop[ $post_ID ] ) ) {
  7114 	if ( isset( $loop[ $post_ID ] ) ) {
  6640 		return 0;
  7115 		return 0;
  6715  * @since 4.5.0
  7190  * @since 4.5.0
  6716  *
  7191  *
  6717  * @param array $posts Array of WP_Post objects.
  7192  * @param array $posts Array of WP_Post objects.
  6718  */
  7193  */
  6719 function wp_queue_posts_for_term_meta_lazyload( $posts ) {
  7194 function wp_queue_posts_for_term_meta_lazyload( $posts ) {
  6720 	$post_type_taxonomies = $term_ids = array();
  7195 	$post_type_taxonomies = array();
       
  7196 	$term_ids             = array();
  6721 	foreach ( $posts as $post ) {
  7197 	foreach ( $posts as $post ) {
  6722 		if ( ! ( $post instanceof WP_Post ) ) {
  7198 		if ( ! ( $post instanceof WP_Post ) ) {
  6723 			continue;
  7199 			continue;
  6724 		}
  7200 		}
  6725 
  7201 
  6766 		wp_update_term_count( $tt_ids, $taxonomy );
  7242 		wp_update_term_count( $tt_ids, $taxonomy );
  6767 	}
  7243 	}
  6768 }
  7244 }
  6769 
  7245 
  6770 /**
  7246 /**
  6771  * Adds any posts from the given ids to the cache that do not already exist in cache
  7247  * Adds any posts from the given IDs to the cache that do not already exist in cache
  6772  *
  7248  *
  6773  * @since 3.4.0
  7249  * @since 3.4.0
  6774  * @access private
  7250  * @access private
  6775  *
  7251  *
  6776  * @see update_post_caches()
  7252  * @see update_post_caches()
  6859  * @since 4.7.0
  7335  * @since 4.7.0
  6860  * @access private
  7336  * @access private
  6861  *
  7337  *
  6862  * @global wpdb $wpdb WordPress database abstraction object.
  7338  * @global wpdb $wpdb WordPress database abstraction object.
  6863  *
  7339  *
  6864  * @param array $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY,
  7340  * @param string[] $clauses An array including WHERE, GROUP BY, JOIN, ORDER BY,
  6865  *                       DISTINCT, fields (SELECT), and LIMITS clauses.
  7341  *                          DISTINCT, fields (SELECT), and LIMITS clauses.
  6866  * @return array The modified clauses.
  7342  * @return string[] The modified array of clauses.
  6867  */
  7343  */
  6868 function _filter_query_attachment_filenames( $clauses ) {
  7344 function _filter_query_attachment_filenames( $clauses ) {
  6869 	global $wpdb;
  7345 	global $wpdb;
  6870 	remove_filter( 'posts_clauses', __FUNCTION__ );
  7346 	remove_filter( 'posts_clauses', __FUNCTION__ );
  6871 
  7347 
  6906 	global $wpdb;
  7382 	global $wpdb;
  6907 
  7383 
  6908 	$types = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type ) );
  7384 	$types = $wpdb->get_col( $wpdb->prepare( "SELECT DISTINCT post_mime_type FROM $wpdb->posts WHERE post_type = %s", $type ) );
  6909 	return $types;
  7385 	return $types;
  6910 }
  7386 }
       
  7387 
       
  7388 /**
       
  7389  * Retrieves the path to an uploaded image file.
       
  7390  *
       
  7391  * Similar to `get_attached_file()` however some images may have been processed after uploading
       
  7392  * to make them suitable for web use. In this case the attached "full" size file is usually replaced
       
  7393  * with a scaled down version of the original image. This function always returns the path
       
  7394  * to the originally uploaded image file.
       
  7395  *
       
  7396  * @since 5.3.0
       
  7397  * @since 5.4.0 Added the `$unfiltered` parameter.
       
  7398  *
       
  7399  * @param int  $attachment_id Attachment ID.
       
  7400  * @param bool $unfiltered Optional. Passed through to `get_attached_file()`. Default false.
       
  7401  * @return string|false Path to the original image file or false if the attachment is not an image.
       
  7402  */
       
  7403 function wp_get_original_image_path( $attachment_id, $unfiltered = false ) {
       
  7404 	if ( ! wp_attachment_is_image( $attachment_id ) ) {
       
  7405 		return false;
       
  7406 	}
       
  7407 
       
  7408 	$image_meta = wp_get_attachment_metadata( $attachment_id );
       
  7409 	$image_file = get_attached_file( $attachment_id, $unfiltered );
       
  7410 
       
  7411 	if ( empty( $image_meta['original_image'] ) ) {
       
  7412 		$original_image = $image_file;
       
  7413 	} else {
       
  7414 		$original_image = path_join( dirname( $image_file ), $image_meta['original_image'] );
       
  7415 	}
       
  7416 
       
  7417 	/**
       
  7418 	 * Filters the path to the original image.
       
  7419 	 *
       
  7420 	 * @since 5.3.0
       
  7421 	 *
       
  7422 	 * @param string $original_image Path to original image file.
       
  7423 	 * @param int    $attachment_id  Attachment ID.
       
  7424 	 */
       
  7425 	return apply_filters( 'wp_get_original_image_path', $original_image, $attachment_id );
       
  7426 }
       
  7427 
       
  7428 /**
       
  7429  * Retrieve the URL to an original attachment image.
       
  7430  *
       
  7431  * Similar to `wp_get_attachment_url()` however some images may have been
       
  7432  * processed after uploading. In this case this function returns the URL
       
  7433  * to the originally uploaded image file.
       
  7434  *
       
  7435  * @since 5.3.0
       
  7436  *
       
  7437  * @param int $attachment_id Attachment post ID.
       
  7438  * @return string|false Attachment image URL, false on error or if the attachment is not an image.
       
  7439  */
       
  7440 function wp_get_original_image_url( $attachment_id ) {
       
  7441 	if ( ! wp_attachment_is_image( $attachment_id ) ) {
       
  7442 		return false;
       
  7443 	}
       
  7444 
       
  7445 	$image_url = wp_get_attachment_url( $attachment_id );
       
  7446 
       
  7447 	if ( empty( $image_url ) ) {
       
  7448 		return false;
       
  7449 	}
       
  7450 
       
  7451 	$image_meta = wp_get_attachment_metadata( $attachment_id );
       
  7452 
       
  7453 	if ( empty( $image_meta['original_image'] ) ) {
       
  7454 		$original_image_url = $image_url;
       
  7455 	} else {
       
  7456 		$original_image_url = path_join( dirname( $image_url ), $image_meta['original_image'] );
       
  7457 	}
       
  7458 
       
  7459 	/**
       
  7460 	 * Filters the URL to the original attachment image.
       
  7461 	 *
       
  7462 	 * @since 5.3.0
       
  7463 	 *
       
  7464 	 * @param string $original_image_url URL to original image.
       
  7465 	 * @param int    $attachment_id      Attachment ID.
       
  7466 	 */
       
  7467 	return apply_filters( 'wp_get_original_image_url', $original_image_url, $attachment_id );
       
  7468 }