web/wp-includes/post.php
branchwordpress
changeset 132 4d4862461b8d
parent 109 03b0d1493584
equal deleted inserted replaced
131:a4642baaf829 132:4d4862461b8d
     4  *
     4  *
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Post
     6  * @subpackage Post
     7  * @since 1.5.0
     7  * @since 1.5.0
     8  */
     8  */
       
     9 
       
    10 //
       
    11 // Post Type Registration
       
    12 //
       
    13 
       
    14 /**
       
    15  * Creates the initial post types when 'init' action is fired.
       
    16  */
       
    17 function create_initial_post_types() {
       
    18 	register_post_type( 'post', array('exclude_from_search' => false) );
       
    19 	register_post_type( 'page', array('exclude_from_search' => false) );
       
    20 	register_post_type( 'attachment', array('exclude_from_search' => false) );
       
    21 	register_post_type( 'revision', array('exclude_from_search' => true) );
       
    22 }
       
    23 add_action( 'init', 'create_initial_post_types', 0 ); // highest priority
     9 
    24 
    10 /**
    25 /**
    11  * Retrieve attached file path based on attachment ID.
    26  * Retrieve attached file path based on attachment ID.
    12  *
    27  *
    13  * You can optionally send it through the 'get_attached_file' filter, but by
    28  * You can optionally send it through the 'get_attached_file' filter, but by
    51 function update_attached_file( $attachment_id, $file ) {
    66 function update_attached_file( $attachment_id, $file ) {
    52 	if ( !get_post( $attachment_id ) )
    67 	if ( !get_post( $attachment_id ) )
    53 		return false;
    68 		return false;
    54 
    69 
    55 	$file = apply_filters( 'update_attached_file', $file, $attachment_id );
    70 	$file = apply_filters( 'update_attached_file', $file, $attachment_id );
    56 
    71 	$file = _wp_relative_upload_path($file);
    57 	// Make the file path relative to the upload dir
       
    58 	if ( ($uploads = wp_upload_dir()) && false === $uploads['error'] ) { // Get upload directory
       
    59 		if ( 0 === strpos($file, $uploads['basedir']) ) {// Check that the upload base exists in the file path
       
    60 				$file = str_replace($uploads['basedir'], '', $file); // Remove upload dir from the file path
       
    61 				$file = ltrim($file, '/');
       
    62 		}
       
    63 	}
       
    64 
    72 
    65 	return update_post_meta( $attachment_id, '_wp_attached_file', $file );
    73 	return update_post_meta( $attachment_id, '_wp_attached_file', $file );
       
    74 }
       
    75 
       
    76 /**
       
    77  * Return relative path to an uploaded file.
       
    78  *
       
    79  * The path is relative to the current upload dir.
       
    80  *
       
    81  * @since 2.9
       
    82  * @uses apply_filters() Calls '_wp_relative_upload_path' on file path.
       
    83  *
       
    84  * @param string $path Full path to the file
       
    85  * @return string relative path on success, unchanged path on failure.
       
    86  */
       
    87 function _wp_relative_upload_path( $path ) {
       
    88 	$new_path = $path;
       
    89 
       
    90 	if ( ($uploads = wp_upload_dir()) && false === $uploads['error'] ) {
       
    91 		if ( 0 === strpos($new_path, $uploads['basedir']) ) {
       
    92 				$new_path = str_replace($uploads['basedir'], '', $new_path);
       
    93 				$new_path = ltrim($new_path, '/');
       
    94 		}
       
    95 	}
       
    96 
       
    97 	return apply_filters( '_wp_relative_upload_path', $new_path, $path );
    66 }
    98 }
    67 
    99 
    68 /**
   100 /**
    69  * Retrieve all children of the post parent ID.
   101  * Retrieve all children of the post parent ID.
    70  *
   102  *
   112  * @param mixed $args Optional. User defined arguments for replacing the defaults.
   144  * @param mixed $args Optional. User defined arguments for replacing the defaults.
   113  * @param string $output Optional. Constant for return type, either OBJECT (default), ARRAY_A, ARRAY_N.
   145  * @param string $output Optional. Constant for return type, either OBJECT (default), ARRAY_A, ARRAY_N.
   114  * @return array|bool False on failure and the type will be determined by $output parameter.
   146  * @return array|bool False on failure and the type will be determined by $output parameter.
   115  */
   147  */
   116 function &get_children($args = '', $output = OBJECT) {
   148 function &get_children($args = '', $output = OBJECT) {
       
   149 	$kids = array();
   117 	if ( empty( $args ) ) {
   150 	if ( empty( $args ) ) {
   118 		if ( isset( $GLOBALS['post'] ) ) {
   151 		if ( isset( $GLOBALS['post'] ) ) {
   119 			$args = array('post_parent' => (int) $GLOBALS['post']->post_parent );
   152 			$args = array('post_parent' => (int) $GLOBALS['post']->post_parent );
   120 		} else {
   153 		} else {
   121 			return false;
   154 			return $kids;
   122 		}
   155 		}
   123 	} elseif ( is_object( $args ) ) {
   156 	} elseif ( is_object( $args ) ) {
   124 		$args = array('post_parent' => (int) $args->post_parent );
   157 		$args = array('post_parent' => (int) $args->post_parent );
   125 	} elseif ( is_numeric( $args ) ) {
   158 	} elseif ( is_numeric( $args ) ) {
   126 		$args = array('post_parent' => (int) $args);
   159 		$args = array('post_parent' => (int) $args);
   132 	);
   165 	);
   133 
   166 
   134 	$r = wp_parse_args( $args, $defaults );
   167 	$r = wp_parse_args( $args, $defaults );
   135 
   168 
   136 	$children = get_posts( $r );
   169 	$children = get_posts( $r );
   137 	if ( !$children ) {
   170 
   138 		$kids = false;
   171 	if ( !$children )
   139 		return $kids;
   172 		return $kids;
   140 	}
       
   141 
   173 
   142 	update_post_cache($children);
   174 	update_post_cache($children);
   143 
   175 
   144 	foreach ( $children as $key => $child )
   176 	foreach ( $children as $key => $child )
   145 		$kids[$child->ID] =& $children[$key];
   177 		$kids[$child->ID] =& $children[$key];
   215 			$_post = & $GLOBALS['post'];
   247 			$_post = & $GLOBALS['post'];
   216 		else
   248 		else
   217 			return $null;
   249 			return $null;
   218 	} elseif ( is_object($post) && empty($post->filter) ) {
   250 	} elseif ( is_object($post) && empty($post->filter) ) {
   219 		_get_post_ancestors($post);
   251 		_get_post_ancestors($post);
   220 		wp_cache_add($post->ID, $post, 'posts');
   252 		$_post = sanitize_post($post, 'raw');
   221 		$_post = &$post;
   253 		wp_cache_add($post->ID, $_post, 'posts');
   222 	} else {
   254 	} else {
   223 		if ( is_object($post) )
   255 		if ( is_object($post) )
   224 			$post = $post->ID;
   256 			$post = $post->ID;
   225 		$post = (int) $post;
   257 		$post = (int) $post;
   226 		if ( ! $_post = wp_cache_get($post, 'posts') ) {
   258 		if ( ! $_post = wp_cache_get($post, 'posts') ) {
   227 			$_post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $post));
   259 			$_post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d LIMIT 1", $post));
   228 			if ( ! $_post )
   260 			if ( ! $_post )
   229 				return $null;
   261 				return $null;
   230 			_get_post_ancestors($_post);
   262 			_get_post_ancestors($_post);
       
   263 			$_post = sanitize_post($_post, 'raw');
   231 			wp_cache_add($_post->ID, $_post, 'posts');
   264 			wp_cache_add($_post->ID, $_post, 'posts');
   232 		}
   265 		}
   233 	}
   266 	}
   234 
   267 
   235 	$_post = sanitize_post($_post, $filter);
   268 	if ($filter != 'raw')
       
   269 		$_post = sanitize_post($_post, $filter);
   236 
   270 
   237 	if ( $output == OBJECT ) {
   271 	if ( $output == OBJECT ) {
   238 		return $_post;
   272 		return $_post;
   239 	} elseif ( $output == ARRAY_A ) {
   273 	} elseif ( $output == ARRAY_A ) {
   240 		$__post = get_object_vars($_post);
   274 		$__post = get_object_vars($_post);
   403 
   437 
   404 	if ( is_object($post) )
   438 	if ( is_object($post) )
   405 		return $post->post_type;
   439 		return $post->post_type;
   406 
   440 
   407 	return false;
   441 	return false;
       
   442 }
       
   443 
       
   444 /**
       
   445  * Get a list of all registered post type objects.
       
   446  *
       
   447  * @package WordPress
       
   448  * @subpackage Post
       
   449  * @since 2.9.0
       
   450  * @uses $wp_post_types
       
   451  * @see register_post_type
       
   452  * @see get_post_types
       
   453  *
       
   454  * @param array|string $args An array of key => value arguments to match against the post types.
       
   455  *  Only post types having attributes that match all arguments are returned.
       
   456  * @param string $output The type of output to return, either post type 'names' or 'objects'. 'names' is the default.
       
   457  * @return array A list of post type names or objects
       
   458  */
       
   459 function get_post_types( $args = array(), $output = 'names' ) {
       
   460 	global $wp_post_types;
       
   461 
       
   462 	$do_names = false;
       
   463 	if ( 'names' == $output )
       
   464 		$do_names = true;
       
   465 
       
   466 	$post_types = array();
       
   467 	foreach ( (array) $wp_post_types as $post_type ) {
       
   468 		if ( empty($args) ) {
       
   469 			if ( $do_names )
       
   470 				$post_types[] = $post_type->name;
       
   471 			else
       
   472 				$post_types[] = $post_type;
       
   473 		} elseif ( array_intersect_assoc((array) $post_type, $args) ) {
       
   474 			if ( $do_names )
       
   475 				$post_types[] = $post_type->name;
       
   476 			else
       
   477 				$post_types[] = $post_type;
       
   478 		}
       
   479 	}
       
   480 
       
   481 	return $post_types;
       
   482 }
       
   483 
       
   484 /**
       
   485  * Register a post type. Do not use before init.
       
   486  *
       
   487  * A simple function for creating or modifying a post type based on the
       
   488  * parameters given. The function will accept an array (second optional
       
   489  * parameter), along with a string for the post type name.
       
   490  *
       
   491  *
       
   492  * Optional $args contents:
       
   493  *
       
   494  * exclude_from_search - Whether to exclude posts with this post type from search results. Defaults to true.
       
   495  *
       
   496  * @package WordPress
       
   497  * @subpackage Post
       
   498  * @since 2.9.0
       
   499  * @uses $wp_post_types Inserts new post type object into the list
       
   500  *
       
   501  * @param string $post_type Name of the post type.
       
   502  * @param array|string $args See above description.
       
   503  */
       
   504 function register_post_type($post_type, $args = array()) {
       
   505 	global $wp_post_types;
       
   506 
       
   507 	if (!is_array($wp_post_types))
       
   508 		$wp_post_types = array();
       
   509 
       
   510 	$defaults = array('exclude_from_search' => true);
       
   511 	$args = wp_parse_args($args, $defaults);
       
   512 
       
   513 	$post_type = sanitize_user($post_type, true);
       
   514 	$args['name'] = $post_type;
       
   515 	$wp_post_types[$post_type] = (object) $args;
   408 }
   516 }
   409 
   517 
   410 /**
   518 /**
   411  * Updates the post type for the post ID.
   519  * Updates the post type for the post ID.
   412  *
   520  *
   509  * @param mixed $value Metadata value.
   617  * @param mixed $value Metadata value.
   510  * @param bool $unique Optional, default is false. Whether the same key should not be added.
   618  * @param bool $unique Optional, default is false. Whether the same key should not be added.
   511  * @return bool False for failure. True for success.
   619  * @return bool False for failure. True for success.
   512  */
   620  */
   513 function add_post_meta($post_id, $meta_key, $meta_value, $unique = false) {
   621 function add_post_meta($post_id, $meta_key, $meta_value, $unique = false) {
   514 	if ( !$meta_key )
       
   515 		return false;
       
   516 
       
   517 	global $wpdb;
       
   518 
       
   519 	// make sure meta is added to the post, not a revision
   622 	// make sure meta is added to the post, not a revision
   520 	if ( $the_post = wp_is_post_revision($post_id) )
   623 	if ( $the_post = wp_is_post_revision($post_id) )
   521 		$post_id = $the_post;
   624 		$post_id = $the_post;
   522 
   625 
   523 	// expected_slashed ($meta_key)
   626 	return add_metadata('post', $post_id, $meta_key, $meta_value, $unique);
   524 	$meta_key = stripslashes($meta_key);
       
   525 
       
   526 	if ( $unique && $wpdb->get_var( $wpdb->prepare( "SELECT meta_key FROM $wpdb->postmeta WHERE meta_key = %s AND post_id = %d", $meta_key, $post_id ) ) )
       
   527 		return false;
       
   528 
       
   529 	$meta_value = maybe_serialize( stripslashes_deep($meta_value) );
       
   530 
       
   531 	$wpdb->insert( $wpdb->postmeta, compact( 'post_id', 'meta_key', 'meta_value' ) );
       
   532 
       
   533 	wp_cache_delete($post_id, 'post_meta');
       
   534 
       
   535 	return true;
       
   536 }
   627 }
   537 
   628 
   538 /**
   629 /**
   539  * Remove metadata matching criteria from a post.
   630  * Remove metadata matching criteria from a post.
   540  *
   631  *
   550  * @param string $meta_key Metadata name.
   641  * @param string $meta_key Metadata name.
   551  * @param mixed $meta_value Optional. Metadata value.
   642  * @param mixed $meta_value Optional. Metadata value.
   552  * @return bool False for failure. True for success.
   643  * @return bool False for failure. True for success.
   553  */
   644  */
   554 function delete_post_meta($post_id, $meta_key, $meta_value = '') {
   645 function delete_post_meta($post_id, $meta_key, $meta_value = '') {
   555 	global $wpdb;
       
   556 
       
   557 	// make sure meta is added to the post, not a revision
   646 	// make sure meta is added to the post, not a revision
   558 	if ( $the_post = wp_is_post_revision($post_id) )
   647 	if ( $the_post = wp_is_post_revision($post_id) )
   559 		$post_id = $the_post;
   648 		$post_id = $the_post;
   560 
   649 
   561 	// expected_slashed ($meta_key, $meta_value)
   650 	return delete_metadata('post', $post_id, $meta_key, $meta_value);
   562 	$meta_key = stripslashes( $meta_key );
       
   563 	$meta_value = maybe_serialize( stripslashes_deep($meta_value) );
       
   564 
       
   565 	if ( !$meta_key )
       
   566 		return false;
       
   567 
       
   568 	if ( empty( $meta_value ) )
       
   569 		$meta_id = $wpdb->get_var( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s", $post_id, $meta_key ) );
       
   570 	else
       
   571 		$meta_id = $wpdb->get_var( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s AND meta_value = %s", $post_id, $meta_key, $meta_value ) );
       
   572 
       
   573 	if ( !$meta_id )
       
   574 		return false;
       
   575 
       
   576 	if ( empty( $meta_value ) )
       
   577 		$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s", $post_id, $meta_key ) );
       
   578 	else
       
   579 		$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE post_id = %d AND meta_key = %s AND meta_value = %s", $post_id, $meta_key, $meta_value ) );
       
   580 
       
   581 	wp_cache_delete($post_id, 'post_meta');
       
   582 
       
   583 	return true;
       
   584 }
   651 }
   585 
   652 
   586 /**
   653 /**
   587  * Retrieve post meta field for a post.
   654  * Retrieve post meta field for a post.
   588  *
   655  *
   595  * @param bool $single Whether to return a single value.
   662  * @param bool $single Whether to return a single value.
   596  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
   663  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
   597  *  is true.
   664  *  is true.
   598  */
   665  */
   599 function get_post_meta($post_id, $key, $single = false) {
   666 function get_post_meta($post_id, $key, $single = false) {
   600 	if ( !$key )
   667 	return get_metadata('post', $post_id, $key, $single);
   601 		return '';
       
   602 
       
   603 	$post_id = (int) $post_id;
       
   604 
       
   605 	$meta_cache = wp_cache_get($post_id, 'post_meta');
       
   606 
       
   607 	if ( !$meta_cache ) {
       
   608 		update_postmeta_cache($post_id);
       
   609 		$meta_cache = wp_cache_get($post_id, 'post_meta');
       
   610 	}
       
   611 
       
   612 	if ( isset($meta_cache[$key]) ) {
       
   613 		if ( $single ) {
       
   614 			return maybe_unserialize( $meta_cache[$key][0] );
       
   615 		} else {
       
   616 			return array_map('maybe_unserialize', $meta_cache[$key]);
       
   617 		}
       
   618 	}
       
   619 
       
   620 	return '';
       
   621 }
   668 }
   622 
   669 
   623 /**
   670 /**
   624  * Update post meta field based on post ID.
   671  * Update post meta field based on post ID.
   625  *
   672  *
   637  * @param mixed $value Metadata value.
   684  * @param mixed $value Metadata value.
   638  * @param mixed $prev_value Optional. Previous value to check before removing.
   685  * @param mixed $prev_value Optional. Previous value to check before removing.
   639  * @return bool False on failure, true if success.
   686  * @return bool False on failure, true if success.
   640  */
   687  */
   641 function update_post_meta($post_id, $meta_key, $meta_value, $prev_value = '') {
   688 function update_post_meta($post_id, $meta_key, $meta_value, $prev_value = '') {
   642 	global $wpdb;
       
   643 
       
   644 	// make sure meta is added to the post, not a revision
   689 	// make sure meta is added to the post, not a revision
   645 	if ( $the_post = wp_is_post_revision($post_id) )
   690 	if ( $the_post = wp_is_post_revision($post_id) )
   646 		$post_id = $the_post;
   691 		$post_id = $the_post;
   647 
   692 
   648 	// expected_slashed ($meta_key)
   693 	return update_metadata('post', $post_id, $meta_key, $meta_value, $prev_value);
   649 	$meta_key = stripslashes($meta_key);
       
   650 
       
   651 	if ( !$meta_key )
       
   652 		return false;
       
   653 
       
   654 	if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT meta_key FROM $wpdb->postmeta WHERE meta_key = %s AND post_id = %d", $meta_key, $post_id ) ) ) {
       
   655 		return add_post_meta($post_id, $meta_key, $meta_value);
       
   656 	}
       
   657 
       
   658 	$meta_value = maybe_serialize( stripslashes_deep($meta_value) );
       
   659 
       
   660 	$data  = compact( 'meta_value' );
       
   661 	$where = compact( 'meta_key', 'post_id' );
       
   662 
       
   663 	if ( !empty( $prev_value ) ) {
       
   664 		$prev_value = maybe_serialize($prev_value);
       
   665 		$where['meta_value'] = $prev_value;
       
   666 	}
       
   667 
       
   668 	$wpdb->update( $wpdb->postmeta, $data, $where );
       
   669 	wp_cache_delete($post_id, 'post_meta');
       
   670 	return true;
       
   671 }
   694 }
   672 
   695 
   673 /**
   696 /**
   674  * Delete everything from post meta matching meta key.
   697  * Delete everything from post meta matching meta key.
   675  *
   698  *
   684 		return false;
   707 		return false;
   685 
   708 
   686 	global $wpdb;
   709 	global $wpdb;
   687 	$post_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_id FROM $wpdb->postmeta WHERE meta_key = %s", $post_meta_key));
   710 	$post_ids = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT post_id FROM $wpdb->postmeta WHERE meta_key = %s", $post_meta_key));
   688 	if ( $post_ids ) {
   711 	if ( $post_ids ) {
   689 		$wpdb->query($wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_key = %s", $post_meta_key));
   712 		$postmetaids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = %s", $post_meta_key ) );
       
   713 		$in = implode( ',', array_fill(1, count($postmetaids), '%d'));
       
   714 		do_action( 'delete_postmeta', $postmetaids );
       
   715 		$wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->postmeta WHERE meta_id IN($in)", $postmetaids ));
       
   716 		do_action( 'deleted_postmeta', $postmetaids );
   690 		foreach ( $post_ids as $post_id )
   717 		foreach ( $post_ids as $post_id )
   691 			wp_cache_delete($post_id, 'post_meta');
   718 			wp_cache_delete($post_id, 'post_meta');
   692 		return true;
   719 		return true;
   693 	}
   720 	}
   694 	return false;
   721 	return false;
   808  * @param string $context Optional, default is 'display'. How to sanitize post fields.
   835  * @param string $context Optional, default is 'display'. How to sanitize post fields.
   809  * @return object|array The now sanitized Post Object or Array (will be the same type as $post)
   836  * @return object|array The now sanitized Post Object or Array (will be the same type as $post)
   810  */
   837  */
   811 function sanitize_post($post, $context = 'display') {
   838 function sanitize_post($post, $context = 'display') {
   812 	if ( is_object($post) ) {
   839 	if ( is_object($post) ) {
       
   840 		// Check if post already filtered for this context
       
   841 		if ( isset($post->filter) && $context == $post->filter )
       
   842 			return $post;
   813 		if ( !isset($post->ID) )
   843 		if ( !isset($post->ID) )
   814 			$post->ID = 0;
   844 			$post->ID = 0;
   815 		foreach ( array_keys(get_object_vars($post)) as $field )
   845 		foreach ( array_keys(get_object_vars($post)) as $field )
   816 			$post->$field = sanitize_post_field($field, $post->$field, $post->ID, $context);
   846 			$post->$field = sanitize_post_field($field, $post->$field, $post->ID, $context);
   817 		$post->filter = $context;
   847 		$post->filter = $context;
   818 	} else {
   848 	} else {
       
   849 		// Check if post already filtered for this context
       
   850 		if ( isset($post['filter']) && $context == $post['filter'] )
       
   851 			return $post;
   819 		if ( !isset($post['ID']) )
   852 		if ( !isset($post['ID']) )
   820 			$post['ID'] = 0;
   853 			$post['ID'] = 0;
   821 		foreach ( array_keys($post) as $field )
   854 		foreach ( array_keys($post) as $field )
   822 			$post[$field] = sanitize_post_field($field, $post[$field], $post['ID'], $context);
   855 			$post[$field] = sanitize_post_field($field, $post[$field], $post['ID'], $context);
   823 		$post['filter'] = $context;
   856 		$post['filter'] = $context;
   996 	if ( false !== $count )
  1029 	if ( false !== $count )
   997 		return $count;
  1030 		return $count;
   998 
  1031 
   999 	$count = $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
  1032 	$count = $wpdb->get_results( $wpdb->prepare( $query, $type ), ARRAY_A );
  1000 
  1033 
  1001 	$stats = array( 'publish' => 0, 'private' => 0, 'draft' => 0, 'pending' => 0, 'future' => 0 );
  1034 	$stats = array( 'publish' => 0, 'private' => 0, 'draft' => 0, 'pending' => 0, 'future' => 0, 'trash' => 0 );
  1002 	foreach( (array) $count as $row_num => $row ) {
  1035 	foreach( (array) $count as $row_num => $row ) {
  1003 		$stats[$row['post_status']] = $row['num_posts'];
  1036 		$stats[$row['post_status']] = $row['num_posts'];
  1004 	}
  1037 	}
  1005 
  1038 
  1006 	$stats = (object) $stats;
  1039 	$stats = (object) $stats;
  1025  */
  1058  */
  1026 function wp_count_attachments( $mime_type = '' ) {
  1059 function wp_count_attachments( $mime_type = '' ) {
  1027 	global $wpdb;
  1060 	global $wpdb;
  1028 
  1061 
  1029 	$and = wp_post_mime_type_where( $mime_type );
  1062 	$and = wp_post_mime_type_where( $mime_type );
  1030 	$count = $wpdb->get_results( "SELECT post_mime_type, COUNT( * ) AS num_posts FROM $wpdb->posts WHERE post_type = 'attachment' $and GROUP BY post_mime_type", ARRAY_A );
  1063 	$count = $wpdb->get_results( "SELECT post_mime_type, COUNT( * ) AS num_posts FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' $and GROUP BY post_mime_type", ARRAY_A );
  1031 
  1064 
  1032 	$stats = array( );
  1065 	$stats = array( );
  1033 	foreach( (array) $count as $row ) {
  1066 	foreach( (array) $count as $row ) {
  1034 		$stats[$row['post_mime_type']] = $row['num_posts'];
  1067 		$stats[$row['post_mime_type']] = $row['num_posts'];
  1035 	}
  1068 	}
       
  1069 	$stats['trash'] = $wpdb->get_var( "SELECT COUNT( * ) FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status = 'trash' $and");
  1036 
  1070 
  1037 	return (object) $stats;
  1071 	return (object) $stats;
  1038 }
  1072 }
  1039 
  1073 
  1040 /**
  1074 /**
  1130  * @uses do_action() on 'delete_post' before deletion unless post type is 'attachment'.
  1164  * @uses do_action() on 'delete_post' before deletion unless post type is 'attachment'.
  1131  * @uses do_action() on 'deleted_post' after deletion unless post type is 'attachment'.
  1165  * @uses do_action() on 'deleted_post' after deletion unless post type is 'attachment'.
  1132  * @uses wp_delete_attachment() if post type is 'attachment'.
  1166  * @uses wp_delete_attachment() if post type is 'attachment'.
  1133  *
  1167  *
  1134  * @param int $postid Post ID.
  1168  * @param int $postid Post ID.
       
  1169  * @param bool $force_delete Whether to bypass trash and force deletion
  1135  * @return mixed False on failure
  1170  * @return mixed False on failure
  1136  */
  1171  */
  1137 function wp_delete_post($postid = 0) {
  1172 function wp_delete_post( $postid = 0, $force_delete = false ) {
  1138 	global $wpdb, $wp_rewrite;
  1173 	global $wpdb, $wp_rewrite;
  1139 
  1174 
  1140 	if ( !$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $postid)) )
  1175 	if ( !$post = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $postid)) )
  1141 		return $post;
  1176 		return $post;
  1142 
  1177 
  1143 	if ( 'attachment' == $post->post_type )
  1178 	if ( !$force_delete && ( $post->post_type == 'post' || $post->post_type == 'page') && get_post_status( $postid ) != 'trash' && EMPTY_TRASH_DAYS > 0 )
  1144 		return wp_delete_attachment($postid);
  1179 			return wp_trash_post($postid);
       
  1180 
       
  1181 	if ( $post->post_type == 'attachment' )
       
  1182 		return wp_delete_attachment( $postid, $force_delete );
  1145 
  1183 
  1146 	do_action('delete_post', $postid);
  1184 	do_action('delete_post', $postid);
  1147 
  1185 
  1148 	/** @todo delete for pluggable post taxonomies too */
  1186 	delete_post_meta($postid,'_wp_trash_meta_status');
  1149 	wp_delete_object_term_relationships($postid, array('category', 'post_tag'));
  1187 	delete_post_meta($postid,'_wp_trash_meta_time');
       
  1188 
       
  1189 	wp_delete_object_term_relationships($postid, get_object_taxonomies($post->post_type));
  1150 
  1190 
  1151 	$parent_data = array( 'post_parent' => $post->post_parent );
  1191 	$parent_data = array( 'post_parent' => $post->post_parent );
  1152 	$parent_where = array( 'post_parent' => $postid );
  1192 	$parent_where = array( 'post_parent' => $postid );
  1153 
  1193 
  1154 	if ( 'page' == $post->post_type) {
  1194 	if ( 'page' == $post->post_type) {
  1178 		wp_delete_post_revision( $revision_id );
  1218 		wp_delete_post_revision( $revision_id );
  1179 
  1219 
  1180 	// Point all attachments to this post up one level
  1220 	// Point all attachments to this post up one level
  1181 	$wpdb->update( $wpdb->posts, $parent_data, $parent_where + array( 'post_type' => 'attachment' ) );
  1221 	$wpdb->update( $wpdb->posts, $parent_data, $parent_where + array( 'post_type' => 'attachment' ) );
  1182 
  1222 
  1183 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->comments WHERE comment_post_ID = %d", $postid ));
  1223 	$comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d", $postid ));
  1184 
  1224 	if ( ! empty($comment_ids) ) {
  1185 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE post_id = %d", $postid ));
  1225 		do_action( 'delete_comment', $comment_ids );
  1186 
  1226 		$in_comment_ids = "'" . implode("', '", $comment_ids) . "'";
       
  1227 		$wpdb->query( "DELETE FROM $wpdb->comments WHERE comment_ID IN($in_comment_ids)" );
       
  1228 		do_action( 'deleted_comment', $comment_ids );
       
  1229 	}
       
  1230 
       
  1231 	$post_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d ", $postid ));
       
  1232 	if ( !empty($post_meta_ids) ) {
       
  1233 		do_action( 'delete_postmeta', $post_meta_ids );
       
  1234 		$in_post_meta_ids = "'" . implode("', '", $post_meta_ids) . "'";
       
  1235 		$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_id IN($in_post_meta_ids)" );
       
  1236 		do_action( 'deleted_postmeta', $post_meta_ids );
       
  1237 	}
       
  1238 
       
  1239 	do_action( 'delete_post', $postid );
  1187 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE ID = %d", $postid ));
  1240 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE ID = %d", $postid ));
       
  1241 	do_action( 'deleted_post', $postid );
  1188 
  1242 
  1189 	if ( 'page' == $post->post_type ) {
  1243 	if ( 'page' == $post->post_type ) {
  1190 		clean_page_cache($postid);
  1244 		clean_page_cache($postid);
  1191 
  1245 
  1192 		foreach ( (array) $children as $child )
  1246 		foreach ( (array) $children as $child )
  1200 	wp_clear_scheduled_hook('publish_future_post', $postid);
  1254 	wp_clear_scheduled_hook('publish_future_post', $postid);
  1201 
  1255 
  1202 	do_action('deleted_post', $postid);
  1256 	do_action('deleted_post', $postid);
  1203 
  1257 
  1204 	return $post;
  1258 	return $post;
       
  1259 }
       
  1260 
       
  1261 /**
       
  1262  * Moves a post or page to the Trash
       
  1263  *
       
  1264  * @since 2.9.0
       
  1265  * @uses do_action() on 'trash_post' before trashing
       
  1266  * @uses do_action() on 'trashed_post' after trashing
       
  1267  *
       
  1268  * @param int $postid Post ID.
       
  1269  * @return mixed False on failure
       
  1270  */
       
  1271 function wp_trash_post($post_id = 0) {
       
  1272 	if ( EMPTY_TRASH_DAYS == 0 )
       
  1273 		return wp_delete_post($post_id);
       
  1274 
       
  1275 	if ( !$post = wp_get_single_post($post_id, ARRAY_A) )
       
  1276 		return $post;
       
  1277 
       
  1278 	if ( $post['post_status'] == 'trash' )
       
  1279 		return false;
       
  1280 
       
  1281 	do_action('trash_post', $post_id);
       
  1282 
       
  1283 	add_post_meta($post_id,'_wp_trash_meta_status', $post['post_status']);
       
  1284 	add_post_meta($post_id,'_wp_trash_meta_time', time());
       
  1285 
       
  1286 	$post['post_status'] = 'trash';
       
  1287 	wp_insert_post($post);
       
  1288 
       
  1289 	wp_trash_post_comments($post_id);
       
  1290 
       
  1291 	do_action('trashed_post', $post_id);
       
  1292 
       
  1293 	return $post;
       
  1294 }
       
  1295 
       
  1296 /**
       
  1297  * Restores a post or page from the Trash
       
  1298  *
       
  1299  * @since 2.9.0
       
  1300  * @uses do_action() on 'untrash_post' before undeletion
       
  1301  * @uses do_action() on 'untrashed_post' after undeletion
       
  1302  *
       
  1303  * @param int $postid Post ID.
       
  1304  * @return mixed False on failure
       
  1305  */
       
  1306 function wp_untrash_post($post_id = 0) {
       
  1307 	if ( !$post = wp_get_single_post($post_id, ARRAY_A) )
       
  1308 		return $post;
       
  1309 
       
  1310 	if ( $post['post_status'] != 'trash' )
       
  1311 		return false;
       
  1312 
       
  1313 	do_action('untrash_post', $post_id);
       
  1314 
       
  1315 	$post_status = get_post_meta($post_id, '_wp_trash_meta_status', true);
       
  1316 
       
  1317 	$post['post_status'] = $post_status;
       
  1318 
       
  1319 	delete_post_meta($post_id, '_wp_trash_meta_status');
       
  1320 	delete_post_meta($post_id, '_wp_trash_meta_time');
       
  1321 
       
  1322 	wp_insert_post($post);
       
  1323 
       
  1324 	wp_untrash_post_comments($post_id);
       
  1325 
       
  1326 	do_action('untrashed_post', $post_id);
       
  1327 
       
  1328 	return $post;
       
  1329 }
       
  1330 
       
  1331 /**
       
  1332  * Moves comments for a post to the trash
       
  1333  *
       
  1334  * @since 2.9.0
       
  1335  * @uses do_action() on 'trash_post_comments' before trashing
       
  1336  * @uses do_action() on 'trashed_post_comments' after trashing
       
  1337  *
       
  1338  * @param int $post Post ID or object.
       
  1339  * @return mixed False on failure
       
  1340  */
       
  1341 function wp_trash_post_comments($post = null) {
       
  1342 	global $wpdb;
       
  1343 
       
  1344 	$post = get_post($post);
       
  1345 	if ( empty($post) )
       
  1346 		return;
       
  1347 
       
  1348 	$post_id = $post->ID;
       
  1349 
       
  1350 	do_action('trash_post_comments', $post_id);
       
  1351 
       
  1352 	$comments = $wpdb->get_results( $wpdb->prepare("SELECT comment_ID, comment_approved FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id) );
       
  1353 	if ( empty($comments) )
       
  1354 		return;
       
  1355 
       
  1356 	// Cache current status for each comment
       
  1357 	$statuses = array();
       
  1358 	foreach ( $comments as $comment )
       
  1359 		$statuses[$comment->comment_ID] = $comment->comment_approved;
       
  1360 	add_post_meta($post_id, '_wp_trash_meta_comments_status', $statuses);
       
  1361 
       
  1362 	// Set status for all comments to post-trashed
       
  1363 	$result = $wpdb->update($wpdb->comments, array('comment_approved' => 'post-trashed'), array('comment_post_ID' => $post_id));
       
  1364 
       
  1365 	clean_comment_cache( array_keys($statuses) );
       
  1366 
       
  1367 	do_action('trashed_post_comments', $post_id, $statuses);
       
  1368 
       
  1369 	return $result;
       
  1370 }
       
  1371 
       
  1372 /**
       
  1373  * Restore comments for a post from the trash
       
  1374  *
       
  1375  * @since 2.9.0
       
  1376  * @uses do_action() on 'untrash_post_comments' before trashing
       
  1377  * @uses do_action() on 'untrashed_post_comments' after trashing
       
  1378  *
       
  1379  * @param int $post Post ID or object.
       
  1380  * @return mixed False on failure
       
  1381  */
       
  1382 function wp_untrash_post_comments($post = null) {
       
  1383 	global $wpdb;
       
  1384 
       
  1385 	$post = get_post($post);
       
  1386 	if ( empty($post) )
       
  1387 		return;
       
  1388 
       
  1389 	$post_id = $post->ID;
       
  1390 
       
  1391 	$statuses = get_post_meta($post_id, '_wp_trash_meta_comments_status', true);
       
  1392 
       
  1393 	if ( empty($statuses) )
       
  1394 		return true;
       
  1395 
       
  1396 	do_action('untrash_post_comments', $post_id);
       
  1397 
       
  1398 	// Restore each comment to its original status
       
  1399 	$group_by_status = array();
       
  1400 	foreach ( $statuses as $comment_id => $comment_status )
       
  1401 		$group_by_status[$comment_status][] = $comment_id;
       
  1402 
       
  1403 	foreach ( $group_by_status as $status => $comments ) {
       
  1404 		// Sanity check. This shouldn't happen.
       
  1405 		if ( 'post-trashed' == $status )
       
  1406 			$status = '0';
       
  1407 		$comments_in = implode( "', '", $comments );
       
  1408 		$wpdb->query( "UPDATE $wpdb->comments SET comment_approved = '$status' WHERE comment_ID IN ('" . $comments_in . "')" );
       
  1409 	}
       
  1410 
       
  1411 	clean_comment_cache( array_keys($statuses) );
       
  1412 
       
  1413 	delete_post_meta($post_id, '_wp_trash_meta_comments_status');
       
  1414 
       
  1415 	do_action('untrashed_post_comments', $post_id);
  1205 }
  1416 }
  1206 
  1417 
  1207 /**
  1418 /**
  1208  * Retrieve the list of categories for a post.
  1419  * Retrieve the list of categories for a post.
  1209  *
  1420  *
  1290 function wp_get_recent_posts($num = 10) {
  1501 function wp_get_recent_posts($num = 10) {
  1291 	global $wpdb;
  1502 	global $wpdb;
  1292 
  1503 
  1293 	// Set the limit clause, if we got a limit
  1504 	// Set the limit clause, if we got a limit
  1294 	$num = (int) $num;
  1505 	$num = (int) $num;
  1295 	if ($num) {
  1506 	if ( $num ) {
  1296 		$limit = "LIMIT $num";
  1507 		$limit = "LIMIT $num";
  1297 	}
  1508 	}
  1298 
  1509 
  1299 	$sql = "SELECT * FROM $wpdb->posts WHERE post_type = 'post' ORDER BY post_date DESC $limit";
  1510 	$sql = "SELECT * FROM $wpdb->posts WHERE post_type = 'post' AND post_status IN ( 'draft', 'publish', 'future', 'pending', 'private' ) ORDER BY post_date DESC $limit";
  1300 	$result = $wpdb->get_results($sql,ARRAY_A);
  1511 	$result = $wpdb->get_results($sql, ARRAY_A);
  1301 
  1512 
  1302 	return $result ? $result : array();
  1513 	return $result ? $result : array();
  1303 }
  1514 }
  1304 
  1515 
  1305 /**
  1516 /**
  1396 		$previous_status = get_post_field('post_status', $ID);
  1607 		$previous_status = get_post_field('post_status', $ID);
  1397 	} else {
  1608 	} else {
  1398 		$previous_status = 'new';
  1609 		$previous_status = 'new';
  1399 	}
  1610 	}
  1400 
  1611 
  1401 	if ( ('' == $post_content) && ('' == $post_title) && ('' == $post_excerpt) ) {
  1612 	if ( ('' == $post_content) && ('' == $post_title) && ('' == $post_excerpt) && ('attachment' != $post_type) ) {
  1402 		if ( $wp_error )
  1613 		if ( $wp_error )
  1403 			return new WP_Error('empty_content', __('Content, title, and excerpt are empty.'));
  1614 			return new WP_Error('empty_content', __('Content, title, and excerpt are empty.'));
  1404 		else
  1615 		else
  1405 			return 0;
  1616 			return 0;
  1406 	}
  1617 	}
  1727 
  1938 
  1728 
  1939 
  1729 /**
  1940 /**
  1730  * Given the desired slug and some post details computes a unique slug for the post.
  1941  * Given the desired slug and some post details computes a unique slug for the post.
  1731  *
  1942  *
       
  1943  * @global wpdb $wpdb 
       
  1944  * @global WP_Rewrite $wp_rewrite 
  1732  * @param string $slug the desired slug (post_name)
  1945  * @param string $slug the desired slug (post_name)
  1733  * @param integer $post_ID
  1946  * @param integer $post_ID
  1734  * @param string $post_status no uniqueness checks are made if the post is still draft or pending
  1947  * @param string $post_status no uniqueness checks are made if the post is still draft or pending
  1735  * @param string $post_type
  1948  * @param string $post_type
  1736  * @param integer $post_parent
  1949  * @param integer $post_parent
  1737  * @return string unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)
  1950  * @return string unique slug for the post, based on $post_name (with a -1, -2, etc. suffix)
  1738  */
  1951  */
  1739 function wp_unique_post_slug($slug, $post_ID, $post_status, $post_type, $post_parent) {
  1952 function wp_unique_post_slug($slug, $post_ID, $post_status, $post_type, $post_parent) {
  1740 	if ( in_array( $post_status, array( 'draft', 'pending' ) ) )
  1953 	if ( in_array( $post_status, array( 'draft', 'pending' ) ) )
  1741 		return $slug;
  1954 		return $slug;
  1742 	
  1955 
  1743 	global $wpdb, $wp_rewrite;
  1956 	global $wpdb, $wp_rewrite;
       
  1957 
       
  1958 	$feeds = $wp_rewrite->feeds;
       
  1959 	if ( !is_array($feeds) )
       
  1960 		$feeds = array();
       
  1961 
  1744 	$hierarchical_post_types = apply_filters('hierarchical_post_types', array('page'));
  1962 	$hierarchical_post_types = apply_filters('hierarchical_post_types', array('page'));
  1745 	if ( 'attachment' == $post_type ) {
  1963 	if ( 'attachment' == $post_type ) {
  1746 		// Attachment slugs must be unique across all types.
  1964 		// Attachment slugs must be unique across all types.
  1747 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
  1965 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
  1748 		$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $slug, $post_ID));
  1966 		$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $slug, $post_ID));
  1749 		
  1967 
  1750 		if ( $post_name_check || in_array($slug, $wp_rewrite->feeds) ) {
  1968 		if ( $post_name_check || in_array($slug, $feeds) ) {
  1751 			$suffix = 2;
  1969 			$suffix = 2;
  1752 			do {
  1970 			do {
  1753 				$alt_post_name = substr($slug, 0, 200-(strlen($suffix)+1)). "-$suffix";
  1971 				$alt_post_name = substr($slug, 0, 200-(strlen($suffix)+1)). "-$suffix";
  1754 				$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $alt_post_name, $post_ID));
  1972 				$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $alt_post_name, $post_ID));
  1755 				$suffix++;
  1973 				$suffix++;
  1757 			$slug = $alt_post_name;
  1975 			$slug = $alt_post_name;
  1758 		}
  1976 		}
  1759 	} elseif ( in_array($post_type, $hierarchical_post_types) ) {
  1977 	} elseif ( in_array($post_type, $hierarchical_post_types) ) {
  1760 		// Page slugs must be unique within their own trees.  Pages are in a
  1978 		// Page slugs must be unique within their own trees.  Pages are in a
  1761 		// separate namespace than posts so page slugs are allowed to overlap post slugs.
  1979 		// separate namespace than posts so page slugs are allowed to overlap post slugs.
  1762 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type IN ( '" . implode("', '", $wpdb->escape($hierarchical_post_types)) . "' ) AND ID != %d AND post_parent = %d LIMIT 1";
  1980 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type IN ( '" . implode("', '", esc_sql($hierarchical_post_types)) . "' ) AND ID != %d AND post_parent = %d LIMIT 1";
  1763 		$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $slug, $post_ID, $post_parent));
  1981 		$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $slug, $post_ID, $post_parent));
  1764 		
  1982 
  1765 		if ( $post_name_check || in_array($slug, $wp_rewrite->feeds) ) {
  1983 		if ( $post_name_check || in_array($slug, $feeds) ) {
  1766 			$suffix = 2;
  1984 			$suffix = 2;
  1767 			do {
  1985 			do {
  1768 				$alt_post_name = substr($slug, 0, 200-(strlen($suffix)+1)). "-$suffix";
  1986 				$alt_post_name = substr($slug, 0, 200-(strlen($suffix)+1)). "-$suffix";
  1769 				$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $alt_post_name, $post_ID, $post_parent));
  1987 				$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $alt_post_name, $post_ID, $post_parent));
  1770 				$suffix++;
  1988 				$suffix++;
  1773 		}
  1991 		}
  1774 	} else {
  1992 	} else {
  1775 		// Post slugs must be unique across all posts.
  1993 		// Post slugs must be unique across all posts.
  1776 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
  1994 		$check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND post_type = %s AND ID != %d LIMIT 1";
  1777 		$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $slug, $post_type, $post_ID));
  1995 		$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $slug, $post_type, $post_ID));
  1778 		
  1996 
  1779 		if ( $post_name_check || in_array($slug, $wp_rewrite->feeds) ) {
  1997 		if ( $post_name_check || in_array($slug, $wp_rewrite->feeds) ) {
  1780 			$suffix = 2;
  1998 			$suffix = 2;
  1781 			do {
  1999 			do {
  1782 				$alt_post_name = substr($slug, 0, 200-(strlen($suffix)+1)). "-$suffix";
  2000 				$alt_post_name = substr($slug, 0, 200-(strlen($suffix)+1)). "-$suffix";
  1783 				$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $alt_post_name, $post_type, $post_ID));
  2001 				$post_name_check = $wpdb->get_var($wpdb->prepare($check_sql, $alt_post_name, $post_type, $post_ID));
  2059  * @param string $filter How the return value should be filtered.
  2277  * @param string $filter How the return value should be filtered.
  2060  * @return mixed Page data.
  2278  * @return mixed Page data.
  2061  */
  2279  */
  2062 function &get_page(&$page, $output = OBJECT, $filter = 'raw') {
  2280 function &get_page(&$page, $output = OBJECT, $filter = 'raw') {
  2063 	if ( empty($page) ) {
  2281 	if ( empty($page) ) {
  2064 		if ( isset( $GLOBALS['page'] ) && isset( $GLOBALS['page']->ID ) ) {
  2282 		if ( isset( $GLOBALS['post'] ) && isset( $GLOBALS['post']->ID ) ) {
  2065 			return get_post($GLOBALS['page'], $output, $filter);
  2283 			return get_post($GLOBALS['post'], $output, $filter);
  2066 		} else {
  2284 		} else {
  2067 			$page = null;
  2285 			$page = null;
  2068 			return $page;
  2286 			return $page;
  2069 		}
  2287 		}
  2070 	}
  2288 	}
  2160 }
  2378 }
  2161 
  2379 
  2162 /**
  2380 /**
  2163  * Order the pages with children under parents in a flat list.
  2381  * Order the pages with children under parents in a flat list.
  2164  *
  2382  *
       
  2383  * It uses auxiliary structure to hold parent-children relationships and
       
  2384  * runs in O(N) complexity
       
  2385  *
  2165  * @since 2.0.0
  2386  * @since 2.0.0
  2166  *
  2387  *
  2167  * @param array $posts Posts array.
  2388  * @param array $posts Posts array.
  2168  * @param int $parent Parent page ID.
  2389  * @param int $parent Parent page ID.
  2169  * @return array A list arranged by hierarchy. Children immediately follow their parents.
  2390  * @return array A list arranged by hierarchy. Children immediately follow their parents.
  2170  */
  2391  */
  2171 function get_page_hierarchy($posts, $parent = 0) {
  2392 function &get_page_hierarchy( &$pages, $page_id = 0 ) {
  2172 	$result = array ( );
  2393 
  2173 	if ($posts) { foreach ( (array) $posts as $post) {
  2394 	if ( empty( $pages ) ) {
  2174 		if ($post->post_parent == $parent) {
  2395 		$return = array();
  2175 			$result[$post->ID] = $post->post_name;
  2396 		return $return;
  2176 			$children = get_page_hierarchy($posts, $post->ID);
  2397 	}
  2177 			$result += $children; //append $children to $result
  2398 
  2178 		}
  2399 	$children = array();
  2179 	} }
  2400 	foreach ( (array) $pages as $p ) {
       
  2401 
       
  2402 		$parent_id = intval( $p->post_parent );
       
  2403 		$children[ $parent_id ][] = $p;
       
  2404 	 }
       
  2405 
       
  2406 	 $result = array();
       
  2407 	 _page_traverse_name( $page_id, $children, $result );
       
  2408 
  2180 	return $result;
  2409 	return $result;
       
  2410 }
       
  2411 
       
  2412 /**
       
  2413  * function to traverse and return all the nested children post names of a root page.
       
  2414  * $children contains parent-chilren relations
       
  2415  *
       
  2416  */
       
  2417 function _page_traverse_name( $page_id, &$children, &$result ){
       
  2418 
       
  2419 	if ( isset( $children[ $page_id ] ) ){
       
  2420 
       
  2421 		foreach( (array)$children[ $page_id ] as $child ) {
       
  2422 
       
  2423 			$result[ $child->ID ] = $child->post_name;
       
  2424 			_page_traverse_name( $child->ID, $children, $result );
       
  2425 		}
       
  2426 	}
  2181 }
  2427 }
  2182 
  2428 
  2183 /**
  2429 /**
  2184  * Builds URI for a page.
  2430  * Builds URI for a page.
  2185  *
  2431  *
  2340 	if ( empty($pages) ) {
  2586 	if ( empty($pages) ) {
  2341 		$pages = apply_filters('get_pages', array(), $r);
  2587 		$pages = apply_filters('get_pages', array(), $r);
  2342 		return $pages;
  2588 		return $pages;
  2343 	}
  2589 	}
  2344 
  2590 
       
  2591 	// Sanitize before caching so it'll only get done once
       
  2592 	$num_pages = count($pages);
       
  2593 	for ($i = 0; $i < $num_pages; $i++) {
       
  2594 		$pages[$i] = sanitize_post($pages[$i], 'raw');
       
  2595 	}
       
  2596 
  2345 	// Update cache.
  2597 	// Update cache.
  2346 	update_page_cache($pages);
  2598 	update_page_cache($pages);
  2347 
  2599 
  2348 	if ( $child_of || $hierarchical )
  2600 	if ( $child_of || $hierarchical )
  2349 		$pages = & get_page_children($child_of, $pages);
  2601 		$pages = & get_page_children($child_of, $pages);
  2350 
  2602 
  2351 	if ( !empty($exclude_tree) ) {
  2603 	if ( !empty($exclude_tree) ) {
  2352 		$exclude = array();
       
  2353 
       
  2354 		$exclude = (int) $exclude_tree;
  2604 		$exclude = (int) $exclude_tree;
  2355 		$children = get_page_children($exclude, $pages);
  2605 		$children = get_page_children($exclude, $pages);
  2356 		$excludes = array();
  2606 		$excludes = array();
  2357 		foreach ( $children as $child )
  2607 		foreach ( $children as $child )
  2358 			$excludes[] = $child->ID;
  2608 			$excludes[] = $child->ID;
  2359 		$excludes[] = $exclude;
  2609 		$excludes[] = $exclude;
  2360 		$total = count($pages);
  2610 		$num_pages = count($pages);
  2361 		for ( $i = 0; $i < $total; $i++ ) {
  2611 		for ( $i = 0; $i < $num_pages; $i++ ) {
  2362 			if ( in_array($pages[$i]->ID, $excludes) )
  2612 			if ( in_array($pages[$i]->ID, $excludes) )
  2363 				unset($pages[$i]);
  2613 				unset($pages[$i]);
  2364 		}
  2614 		}
  2365 	}
  2615 	}
  2366 
  2616 
  2553 	if ( $file )
  2803 	if ( $file )
  2554 		update_attached_file( $post_ID, $file );
  2804 		update_attached_file( $post_ID, $file );
  2555 
  2805 
  2556 	clean_post_cache($post_ID);
  2806 	clean_post_cache($post_ID);
  2557 
  2807 
       
  2808 	if ( isset($post_parent) && $post_parent < 0 )
       
  2809 		add_post_meta($post_ID, '_wp_attachment_temp_parent', $post_parent, true);
       
  2810 
  2558 	if ( $update) {
  2811 	if ( $update) {
  2559 		do_action('edit_attachment', $post_ID);
  2812 		do_action('edit_attachment', $post_ID);
  2560 	} else {
  2813 	} else {
  2561 		do_action('add_attachment', $post_ID);
  2814 		do_action('add_attachment', $post_ID);
  2562 	}
  2815 	}
  2574  * @since 2.0.0
  2827  * @since 2.0.0
  2575  * @uses $wpdb
  2828  * @uses $wpdb
  2576  * @uses do_action() Calls 'delete_attachment' hook on Attachment ID.
  2829  * @uses do_action() Calls 'delete_attachment' hook on Attachment ID.
  2577  *
  2830  *
  2578  * @param int $postid Attachment ID.
  2831  * @param int $postid Attachment ID.
       
  2832  * @param bool $force_delete Whether to bypass trash and force deletion
  2579  * @return mixed False on failure. Post data on success.
  2833  * @return mixed False on failure. Post data on success.
  2580  */
  2834  */
  2581 function wp_delete_attachment($postid) {
  2835 function wp_delete_attachment( $post_id, $force_delete = false ) {
  2582 	global $wpdb;
  2836 	global $wpdb;
  2583 
  2837 
  2584 	if ( !$post = $wpdb->get_row(  $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE ID = %d", $postid)) )
  2838 	if ( !$post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) ) )
  2585 		return $post;
  2839 		return $post;
  2586 
  2840 
  2587 	if ( 'attachment' != $post->post_type )
  2841 	if ( 'attachment' != $post->post_type )
  2588 		return false;
  2842 		return false;
  2589 
  2843 
  2590 	$meta = wp_get_attachment_metadata( $postid );
  2844 	if ( !$force_delete && EMPTY_TRASH_DAYS && MEDIA_TRASH && 'trash' != $post->post_status )
  2591 	$file = get_attached_file( $postid );
  2845 		return wp_trash_post( $post_id );
  2592 
  2846 
  2593 	do_action('delete_attachment', $postid);
  2847 	delete_post_meta($post_id, '_wp_trash_meta_status');
  2594 
  2848 	delete_post_meta($post_id, '_wp_trash_meta_time');
  2595 	/** @todo Delete for pluggable post taxonomies too */
  2849 
  2596 	wp_delete_object_term_relationships($postid, array('category', 'post_tag'));
  2850 	$meta = wp_get_attachment_metadata( $post_id );
  2597 
  2851 	$backup_sizes = get_post_meta( $post->ID, '_wp_attachment_backup_sizes', true );
  2598 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->comments WHERE comment_post_ID = %d", $postid ));
  2852 	$file = get_attached_file( $post_id );
  2599 
  2853 
  2600 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE post_id = %d ", $postid ));
  2854 	do_action('delete_attachment', $post_id);
  2601 
  2855 
  2602 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE ID = %d", $postid ));
  2856 	wp_delete_object_term_relationships($post_id, array('category', 'post_tag'));
  2603 
  2857 	wp_delete_object_term_relationships($post_id, get_object_taxonomies($post->post_type));
  2604 	$uploadPath = wp_upload_dir();
  2858 
       
  2859 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key = '_thumbnail_id' AND meta_value = %d", $post_id ));
       
  2860 
       
  2861 	$comment_ids = $wpdb->get_col( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d", $post_id ));
       
  2862 	if ( ! empty($comment_ids) ) {
       
  2863 		do_action( 'delete_comment', $comment_ids );
       
  2864 		$in_comment_ids = "'" . implode("', '", $comment_ids) . "'";
       
  2865 		$wpdb->query( "DELETE FROM $wpdb->comments WHERE comment_ID IN($in_comment_ids)" );
       
  2866 		do_action( 'deleted_comment', $comment_ids );
       
  2867 	}
       
  2868 
       
  2869 	$post_meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE post_id = %d ", $post_id ));
       
  2870 	if ( !empty($post_meta_ids) ) {
       
  2871 		do_action( 'delete_postmeta', $post_meta_ids );
       
  2872 		$in_post_meta_ids = "'" . implode("', '", $post_meta_ids) . "'";
       
  2873 		$wpdb->query( "DELETE FROM $wpdb->postmeta WHERE meta_id IN($in_post_meta_ids)" );
       
  2874 		do_action( 'deleted_postmeta', $post_meta_ids );
       
  2875 	}
       
  2876 
       
  2877 	do_action( 'delete_post', $post_id );
       
  2878 	$wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->posts WHERE ID = %d", $post_id ));
       
  2879 	do_action( 'deleted_post', $post_id );
       
  2880 
       
  2881 	$uploadpath = wp_upload_dir();
  2605 
  2882 
  2606 	if ( ! empty($meta['thumb']) ) {
  2883 	if ( ! empty($meta['thumb']) ) {
  2607 		// Don't delete the thumb if another attachment uses it
  2884 		// Don't delete the thumb if another attachment uses it
  2608 		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", '%'.$meta['thumb'].'%', $postid)) ) {
  2885 		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", '%' . $meta['thumb'] . '%', $post_id)) ) {
  2609 			$thumbfile = str_replace(basename($file), $meta['thumb'], $file);
  2886 			$thumbfile = str_replace(basename($file), $meta['thumb'], $file);
  2610 			$thumbfile = apply_filters('wp_delete_file', $thumbfile);
  2887 			$thumbfile = apply_filters('wp_delete_file', $thumbfile);
  2611 			@ unlink( path_join($uploadPath['basedir'], $thumbfile) );
  2888 			@ unlink( path_join($uploadpath['basedir'], $thumbfile) );
  2612 		}
  2889 		}
  2613 	}
  2890 	}
  2614 
  2891 
  2615 	// remove intermediate images if there are any
  2892 	// remove intermediate and backup images if there are any
  2616 	$sizes = apply_filters('intermediate_image_sizes', array('thumbnail', 'medium', 'large'));
  2893 	$sizes = apply_filters('intermediate_image_sizes', array('thumbnail', 'medium', 'large'));
  2617 	foreach ( $sizes as $size ) {
  2894 	foreach ( $sizes as $size ) {
  2618 		if ( $intermediate = image_get_intermediate_size($postid, $size) ) {
  2895 		if ( $intermediate = image_get_intermediate_size($post_id, $size) ) {
  2619 			$intermediate_file = apply_filters('wp_delete_file', $intermediate['path']);
  2896 			$intermediate_file = apply_filters('wp_delete_file', $intermediate['path']);
  2620 			@ unlink( path_join($uploadPath['basedir'], $intermediate_file) );
  2897 			@ unlink( path_join($uploadpath['basedir'], $intermediate_file) );
       
  2898 		}
       
  2899 	}
       
  2900 
       
  2901 	if ( is_array($backup_sizes) ) {
       
  2902 		foreach ( $backup_sizes as $size ) {
       
  2903 			$del_file = path_join( dirname($meta['file']), $size['file'] );
       
  2904 			$del_file = apply_filters('wp_delete_file', $del_file);
       
  2905             @ unlink( path_join($uploadpath['basedir'], $del_file) );
  2621 		}
  2906 		}
  2622 	}
  2907 	}
  2623 
  2908 
  2624 	$file = apply_filters('wp_delete_file', $file);
  2909 	$file = apply_filters('wp_delete_file', $file);
  2625 
  2910 
  2626 	if ( ! empty($file) )
  2911 	if ( ! empty($file) )
  2627 		@ unlink($file);
  2912 		@ unlink($file);
  2628 
  2913 
  2629 	clean_post_cache($postid);
  2914 	clean_post_cache($post_id);
  2630 
  2915 
  2631 	return $post;
  2916 	return $post;
  2632 }
  2917 }
  2633 
  2918 
  2634 /**
  2919 /**
  2644 	$post_id = (int) $post_id;
  2929 	$post_id = (int) $post_id;
  2645 	if ( !$post =& get_post( $post_id ) )
  2930 	if ( !$post =& get_post( $post_id ) )
  2646 		return false;
  2931 		return false;
  2647 
  2932 
  2648 	$data = get_post_meta( $post->ID, '_wp_attachment_metadata', true );
  2933 	$data = get_post_meta( $post->ID, '_wp_attachment_metadata', true );
       
  2934 
  2649 	if ( $unfiltered )
  2935 	if ( $unfiltered )
  2650 		return $data;
  2936 		return $data;
       
  2937 
  2651 	return apply_filters( 'wp_get_attachment_metadata', $data, $post->ID );
  2938 	return apply_filters( 'wp_get_attachment_metadata', $data, $post->ID );
  2652 }
  2939 }
  2653 
  2940 
  2654 /**
  2941 /**
  2655  * Update metadata for an attachment.
  2942  * Update metadata for an attachment.
  3195  *
  3482  *
  3196  * @param array $post_ids List of post IDs.
  3483  * @param array $post_ids List of post IDs.
  3197  * @return bool|array Returns false if there is nothing to update or an array of metadata.
  3484  * @return bool|array Returns false if there is nothing to update or an array of metadata.
  3198  */
  3485  */
  3199 function update_postmeta_cache($post_ids) {
  3486 function update_postmeta_cache($post_ids) {
  3200 	global $wpdb;
  3487 	return update_meta_cache('post', $post_ids);
  3201 
       
  3202 	if ( empty( $post_ids ) )
       
  3203 		return false;
       
  3204 
       
  3205 	if ( !is_array($post_ids) ) {
       
  3206 		$post_ids = preg_replace('|[^0-9,]|', '', $post_ids);
       
  3207 		$post_ids = explode(',', $post_ids);
       
  3208 	}
       
  3209 
       
  3210 	$post_ids = array_map('intval', $post_ids);
       
  3211 
       
  3212 	$ids = array();
       
  3213 	foreach ( (array) $post_ids as $id ) {
       
  3214 		if ( false === wp_cache_get($id, 'post_meta') )
       
  3215 			$ids[] = $id;
       
  3216 	}
       
  3217 
       
  3218 	if ( empty( $ids ) )
       
  3219 		return false;
       
  3220 
       
  3221 	// Get post-meta info
       
  3222 	$id_list = join(',', $ids);
       
  3223 	$cache = array();
       
  3224 	if ( $meta_list = $wpdb->get_results("SELECT post_id, meta_key, meta_value FROM $wpdb->postmeta WHERE post_id IN ($id_list)", ARRAY_A) ) {
       
  3225 		foreach ( (array) $meta_list as $metarow) {
       
  3226 			$mpid = (int) $metarow['post_id'];
       
  3227 			$mkey = $metarow['meta_key'];
       
  3228 			$mval = $metarow['meta_value'];
       
  3229 
       
  3230 			// Force subkeys to be array type:
       
  3231 			if ( !isset($cache[$mpid]) || !is_array($cache[$mpid]) )
       
  3232 				$cache[$mpid] = array();
       
  3233 			if ( !isset($cache[$mpid][$mkey]) || !is_array($cache[$mpid][$mkey]) )
       
  3234 				$cache[$mpid][$mkey] = array();
       
  3235 
       
  3236 			// Add a value to the current pid/key:
       
  3237 			$cache[$mpid][$mkey][] = $mval;
       
  3238 		}
       
  3239 	}
       
  3240 
       
  3241 	foreach ( (array) $ids as $id ) {
       
  3242 		if ( ! isset($cache[$id]) )
       
  3243 			$cache[$id] = array();
       
  3244 	}
       
  3245 
       
  3246 	foreach ( (array) array_keys($cache) as $post)
       
  3247 		wp_cache_set($post, $cache[$post], 'post_meta');
       
  3248 
       
  3249 	return $cache;
       
  3250 }
  3488 }
  3251 
  3489 
  3252 //
  3490 //
  3253 // Hooks
  3491 // Hooks
  3254 //
  3492 //
  3318 
  3556 
  3319 	if ( defined('WP_IMPORTING') )
  3557 	if ( defined('WP_IMPORTING') )
  3320 		return;
  3558 		return;
  3321 
  3559 
  3322 	$data = array( 'post_id' => $post_id, 'meta_value' => '1' );
  3560 	$data = array( 'post_id' => $post_id, 'meta_value' => '1' );
  3323 	if ( get_option('default_pingback_flag') )
  3561 	if ( get_option('default_pingback_flag') ) {
  3324 		$wpdb->insert( $wpdb->postmeta, $data + array( 'meta_key' => '_pingme' ) );
  3562 		$wpdb->insert( $wpdb->postmeta, $data + array( 'meta_key' => '_pingme' ) );
       
  3563 		do_action( 'added_postmeta', $wpdb->insert_id, $post_id, '_pingme', 1 );
       
  3564 	}
  3325 	$wpdb->insert( $wpdb->postmeta, $data + array( 'meta_key' => '_encloseme' ) );
  3565 	$wpdb->insert( $wpdb->postmeta, $data + array( 'meta_key' => '_encloseme' ) );
       
  3566 	do_action( 'added_postmeta', $wpdb->insert_id, $post_id, '_encloseme', 1 );
       
  3567 
  3326 	wp_schedule_single_event(time(), 'do_pings');
  3568 	wp_schedule_single_event(time(), 'do_pings');
  3327 }
  3569 }
  3328 
  3570 
  3329 /**
  3571 /**
  3330  * Hook used to prevent page/post cache and rewrite rules from staying dirty.
  3572  * Hook used to prevent page/post cache and rewrite rules from staying dirty.
  3463  * @param int $post_id The ID of the post to save as a revision.
  3705  * @param int $post_id The ID of the post to save as a revision.
  3464  * @return mixed Null or 0 if error, new revision ID, if success.
  3706  * @return mixed Null or 0 if error, new revision ID, if success.
  3465  */
  3707  */
  3466 function wp_save_post_revision( $post_id ) {
  3708 function wp_save_post_revision( $post_id ) {
  3467 	// We do autosaves manually with wp_create_post_autosave()
  3709 	// We do autosaves manually with wp_create_post_autosave()
  3468 	if ( @constant( 'DOING_AUTOSAVE' ) )
  3710 	if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
  3469 		return;
  3711 		return;
  3470 
  3712 
  3471 	// WP_POST_REVISIONS = 0, false
  3713 	// WP_POST_REVISIONS = 0, false
  3472 	if ( !constant('WP_POST_REVISIONS') )
  3714 	if ( !constant('WP_POST_REVISIONS') )
  3473 		return;
  3715 		return;