web/wp-includes/comment.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
child 204 09a1c134465b
--- a/web/wp-includes/comment.php	Thu Sep 16 15:45:36 2010 +0000
+++ b/web/wp-includes/comment.php	Mon Nov 19 18:26:13 2012 +0100
@@ -18,9 +18,8 @@
  * check fails. If any of the parameter contents match the blacklist of words,
  * then the check fails.
  *
- * If the comment is a trackback and part of the blogroll, then the trackback is
- * automatically whitelisted. If the comment author was approved before, then
- * the comment is automatically whitelisted.
+ * If the comment author was approved before, then the comment is
+ * automatically whitelisted.
  *
  * If none of the checks fail, then the failback is to set the check to pass
  * (return true).
@@ -45,8 +44,15 @@
 	if ( 1 == get_option('comment_moderation') )
 		return false; // If moderation is set to manual
 
-	if ( get_option('comment_max_links') && preg_match_all("/<[Aa][^>]*[Hh][Rr][Ee][Ff]=['\"]([^\"'>]+)[^>]*>/", apply_filters('comment_text',$comment), $out) >= get_option('comment_max_links') )
-		return false; // Check # of external links
+	$comment = apply_filters( 'comment_text', $comment );
+
+	// Check # of external links
+	if ( $max_links = get_option( 'comment_max_links' ) ) {
+		$num_links = preg_match_all( '/<a [^>]*href/i', $comment, $out );
+		$num_links = apply_filters( 'comment_max_links_url', $num_links, $url ); // provide for counting of $url as a link
+		if ( $num_links >= $max_links )
+			return false;
+	}
 
 	$mod_keys = trim(get_option('moderation_keys'));
 	if ( !empty($mod_keys) ) {
@@ -75,16 +81,7 @@
 
 	// Comment whitelisting:
 	if ( 1 == get_option('comment_whitelist')) {
-		if ( 'trackback' == $comment_type || 'pingback' == $comment_type ) { // check if domain is in blogroll
-			$uri = parse_url($url);
-			$domain = $uri['host'];
-			$uri = parse_url( get_option('home') );
-			$home_domain = $uri['host'];
-			if ( $wpdb->get_var($wpdb->prepare("SELECT link_id FROM $wpdb->links WHERE link_url LIKE (%s) LIMIT 1", '%'.$domain.'%')) || $domain == $home_domain )
-				return true;
-			else
-				return false;
-		} elseif ( $author != '' && $email != '' ) {
+		if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) {
 			// expected_slashed ($author, $email)
 			$ok_to_comment = $wpdb->get_var("SELECT comment_approved FROM $wpdb->comments WHERE comment_author = '$author' AND comment_author_email = '$email' and comment_approved = '1' LIMIT 1");
 			if ( ( 1 == $ok_to_comment ) &&
@@ -183,65 +180,194 @@
  * @return array List of comments.
  */
 function get_comments( $args = '' ) {
-	global $wpdb;
+	$query = new WP_Comment_Query;
+	return $query->query( $args );
+}
+
+/**
+ * WordPress Comment Query class.
+ *
+ * @since 3.1.0
+ */
+class WP_Comment_Query {
+
+	/**
+	 * Execute the query
+	 *
+	 * @since 3.1.0
+	 *
+	 * @param string|array $query_vars
+	 * @return int|array
+	 */
+	function query( $query_vars ) {
+		global $wpdb;
 
-	$defaults = array('status' => '', 'orderby' => 'comment_date_gmt', 'order' => 'DESC', 'number' => '', 'offset' => '', 'post_id' => 0);
+		$defaults = array(
+			'author_email' => '',
+			'ID' => '',
+			'karma' => '',
+			'number' => '',
+			'offset' => '',
+			'orderby' => '',
+			'order' => 'DESC',
+			'parent' => '',
+			'post_ID' => '',
+			'post_id' => 0,
+			'post_author' => '',
+			'post_name' => '',
+			'post_parent' => '',
+			'post_status' => '',
+			'post_type' => '',
+			'status' => '',
+			'type' => '',
+			'user_id' => '',
+			'search' => '',
+			'count' => false
+		);
+
+		$this->query_vars = wp_parse_args( $query_vars, $defaults );
+		do_action_ref_array( 'pre_get_comments', array( &$this ) );
+		extract( $this->query_vars, EXTR_SKIP );
 
-	$args = wp_parse_args( $args, $defaults );
-	extract( $args, EXTR_SKIP );
+		// $args can be whatever, only use the args defined in defaults to compute the key
+		$key = md5( serialize( compact(array_keys($defaults)) )  );
+		$last_changed = wp_cache_get('last_changed', 'comment');
+		if ( !$last_changed ) {
+			$last_changed = time();
+			wp_cache_set('last_changed', $last_changed, 'comment');
+		}
+		$cache_key = "get_comments:$key:$last_changed";
+
+		if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) {
+			return $cache;
+		}
+
+		$post_id = absint($post_id);
+
+		if ( 'hold' == $status )
+			$approved = "comment_approved = '0'";
+		elseif ( 'approve' == $status )
+			$approved = "comment_approved = '1'";
+		elseif ( 'spam' == $status )
+			$approved = "comment_approved = 'spam'";
+		elseif ( 'trash' == $status )
+			$approved = "comment_approved = 'trash'";
+		else
+			$approved = "( comment_approved = '0' OR comment_approved = '1' )";
+
+		$order = ( 'ASC' == strtoupper($order) ) ? 'ASC' : 'DESC';
 
-	// $args can be whatever, only use the args defined in defaults to compute the key
-	$key = md5( serialize( compact(array_keys($defaults)) )  );
-	$last_changed = wp_cache_get('last_changed', 'comment');
-	if ( !$last_changed ) {
-		$last_changed = time();
-		wp_cache_set('last_changed', $last_changed, 'comment');
-	}
-	$cache_key = "get_comments:$key:$last_changed";
+		if ( ! empty( $orderby ) ) {
+			$ordersby = is_array($orderby) ? $orderby : preg_split('/[,\s]/', $orderby);
+			$ordersby = array_intersect(
+				$ordersby,
+				array(
+					'comment_agent',
+					'comment_approved',
+					'comment_author',
+					'comment_author_email',
+					'comment_author_IP',
+					'comment_author_url',
+					'comment_content',
+					'comment_date',
+					'comment_date_gmt',
+					'comment_ID',
+					'comment_karma',
+					'comment_parent',
+					'comment_post_ID',
+					'comment_type',
+					'user_id',
+				)
+			);
+			$orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby);
+		} else {
+			$orderby = 'comment_date_gmt';
+		}
+
+		$number = absint($number);
+		$offset = absint($offset);
+
+		if ( !empty($number) ) {
+			if ( $offset )
+				$limits = 'LIMIT ' . $offset . ',' . $number;
+			else
+				$limits = 'LIMIT ' . $number;
+		} else {
+			$limits = '';
+		}
+
+		if ( $count )
+			$fields = 'COUNT(*)';
+		else
+			$fields = '*';
 
-	if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) {
-		return $cache;
+		$join = '';
+		$where = $approved;
+
+		if ( ! empty($post_id) )
+			$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
+		if ( '' !== $author_email )
+			$where .= $wpdb->prepare( ' AND comment_author_email = %s', $author_email );
+		if ( '' !== $karma )
+			$where .= $wpdb->prepare( ' AND comment_karma = %d', $karma );
+		if ( 'comment' == $type ) {
+			$where .= " AND comment_type = ''";
+		} elseif( 'pings' == $type ) {
+			$where .= ' AND comment_type IN ("pingback", "trackback")';
+		} elseif ( ! empty( $type ) ) {
+			$where .= $wpdb->prepare( ' AND comment_type = %s', $type );
+		}
+		if ( '' !== $parent )
+			$where .= $wpdb->prepare( ' AND comment_parent = %d', $parent );
+		if ( '' !== $user_id )
+			$where .= $wpdb->prepare( ' AND user_id = %d', $user_id );
+		if ( '' !== $search )
+			$where .= $this->get_search_sql( $search, array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' ) );
+
+		$post_fields = array_filter( compact( array( 'post_author', 'post_name', 'post_parent', 'post_status', 'post_type', ) ) );
+		if ( ! empty( $post_fields ) ) {
+			$join = "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
+			foreach( $post_fields as $field_name => $field_value )
+				$where .= $wpdb->prepare( " AND {$wpdb->posts}.{$field_name} = %s", $field_value );
+		}
+
+		$pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits' );
+		$clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );
+		foreach ( $pieces as $piece )
+			$$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : '';
+
+		$query = "SELECT $fields FROM $wpdb->comments $join WHERE $where ORDER BY $orderby $order $limits";
+
+		if ( $count )
+			return $wpdb->get_var( $query );
+
+		$comments = $wpdb->get_results( $query );
+		$comments = apply_filters_ref_array( 'the_comments', array( $comments, &$this ) );
+
+		wp_cache_add( $cache_key, $comments, 'comment' );
+
+		return $comments;
 	}
 
-	$post_id = absint($post_id);
-
-	if ( 'hold' == $status )
-		$approved = "comment_approved = '0'";
-	elseif ( 'approve' == $status )
-		$approved = "comment_approved = '1'";
-	elseif ( 'spam' == $status )
-		$approved = "comment_approved = 'spam'";
-	elseif ( 'trash' == $status )
-		$approved = "comment_approved = 'trash'";
-	else
-		$approved = "( comment_approved = '0' OR comment_approved = '1' )";
-
-	$order = ( 'ASC' == $order ) ? 'ASC' : 'DESC';
-
-	$orderby = 'comment_date_gmt';  // Hard code for now
-
-	$number = absint($number);
-	$offset = absint($offset);
+	/*
+	 * Used internally to generate an SQL string for searching across multiple columns
+	 *
+	 * @access protected
+	 * @since 3.1.0
+	 *
+	 * @param string $string
+	 * @param array $cols
+	 * @return string
+	 */
+	function get_search_sql( $string, $cols ) {
+		$string = esc_sql( like_escape( $string ) );
 
-	if ( !empty($number) ) {
-		if ( $offset )
-			$number = 'LIMIT ' . $offset . ',' . $number;
-		else
-			$number = 'LIMIT ' . $number;
-
-	} else {
-		$number = '';
-	}
+		$searches = array();
+		foreach ( $cols as $col )
+			$searches[] = "$col LIKE '%$string%'";
 
-	if ( ! empty($post_id) )
-		$post_where = $wpdb->prepare( 'comment_post_ID = %d AND', $post_id );
-	else
-		$post_where = '';
-
-	$comments = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE $post_where $approved ORDER BY $orderby $order $number" );
-	wp_cache_add( $cache_key, $comments, 'comment' );
-
-	return $comments;
+		return ' AND (' . implode(' OR ', $searches) . ')';
+	}
 }
 
 /**
@@ -268,7 +394,6 @@
 	return $status;
 }
 
-
 /**
  * The date the last comment was modified.
  *
@@ -371,13 +496,13 @@
 /**
  * Add meta data field to a comment.
  *
- * @since 2.9
+ * @since 2.9.0
  * @uses add_metadata
  * @link http://codex.wordpress.org/Function_Reference/add_comment_meta
  *
  * @param int $comment_id Comment ID.
- * @param string $key Metadata name.
- * @param mixed $value Metadata value.
+ * @param string $meta_key Metadata name.
+ * @param mixed $meta_value Metadata value.
  * @param bool $unique Optional, default is false. Whether the same key should not be added.
  * @return bool False for failure. True for success.
  */
@@ -392,7 +517,7 @@
  * value, will keep from removing duplicate metadata with the same key. It also
  * allows removing all metadata matching key, if needed.
  *
- * @since 2.9
+ * @since 2.9.0
  * @uses delete_metadata
  * @link http://codex.wordpress.org/Function_Reference/delete_comment_meta
  *
@@ -408,17 +533,17 @@
 /**
  * Retrieve comment meta field for a comment.
  *
- * @since 2.9
+ * @since 2.9.0
  * @uses get_metadata
  * @link http://codex.wordpress.org/Function_Reference/get_comment_meta
  *
  * @param int $comment_id Comment ID.
- * @param string $key The meta key to retrieve.
+ * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
  * @param bool $single Whether to return a single value.
  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
  *  is true.
  */
-function get_comment_meta($comment_id, $key, $single = false) {
+function get_comment_meta($comment_id, $key = '', $single = false) {
 	return get_metadata('comment', $comment_id, $key, $single);
 }
 
@@ -430,13 +555,13 @@
  *
  * If the meta field for the comment does not exist, it will be added.
  *
- * @since 2.9
+ * @since 2.9.0
  * @uses update_metadata
  * @link http://codex.wordpress.org/Function_Reference/update_comment_meta
  *
  * @param int $comment_id Comment ID.
- * @param string $key Metadata key.
- * @param mixed $value Metadata value.
+ * @param string $meta_key Metadata key.
+ * @param mixed $meta_value Metadata value.
  * @param mixed $prev_value Optional. Previous value to check before removing.
  * @return bool False on failure, true if success.
  */
@@ -445,6 +570,25 @@
 }
 
 /**
+ * Sets the cookies used to store an unauthenticated commentator's identity. Typically used
+ * to recall previous comments by this commentator that are still held in moderation.
+ *
+ * @param object $comment Comment object.
+ * @param object $user Comment author's object.
+ *
+ * @since 3.4.0
+ */
+function wp_set_comment_cookies($comment, $user) {
+	if ( $user->exists() )
+		return;
+
+	$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
+	setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
+	setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
+	setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
+}
+
+/**
  * Sanitizes the cookies sent to the user already.
  *
  * Will only do anything if the cookies have already been created for the user.
@@ -475,11 +619,12 @@
 }
 
 /**
- * Validates whether this comment is allowed to be made or not.
+ * Validates whether this comment is allowed to be made.
  *
  * @since 2.0.0
  * @uses $wpdb
  * @uses apply_filters() Calls 'pre_comment_approved' hook on the type of comment
+ * @uses apply_filters() Calls 'comment_duplicate_trigger' hook on commentdata.
  * @uses do_action() Calls 'check_comment_flood' hook on $comment_author_IP, $comment_author_email, and $comment_date_gmt
  *
  * @param array $commentdata Contains information on the comment
@@ -496,6 +641,7 @@
 		$dupe .= "OR comment_author_email = '$comment_author_email' ";
 	$dupe .= ") AND comment_content = '$comment_content' LIMIT 1";
 	if ( $wpdb->get_var($dupe) ) {
+		do_action( 'comment_duplicate_trigger', $commentdata );
 		if ( defined('DOING_AJAX') )
 			die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
 
@@ -523,7 +669,7 @@
 			$approved = 'spam';
 	}
 
-	$approved = apply_filters('pre_comment_approved', $approved);
+	$approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );
 	return $approved;
 }
 
@@ -557,9 +703,9 @@
 			do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment);
 
 			if ( defined('DOING_AJAX') )
-				die( __('You are posting comments too quickly.  Slow down.') );
+				die( __('You are posting comments too quickly. Slow down.') );
 
-			wp_die( __('You are posting comments too quickly.  Slow down.'), '', array('response' => 403) );
+			wp_die( __('You are posting comments too quickly. Slow down.'), '', array('response' => 403) );
 		}
 	}
 }
@@ -595,7 +741,7 @@
  * @uses get_option() Used to fill in defaults for parameters.
  * @uses Walker_Comment
  *
- * @param array $comments Optional array of comment objects.  Defaults to $wp_query->comments
+ * @param array $comments Optional array of comment objects. Defaults to $wp_query->comments
  * @param int $per_page Optional comments per page.
  * @param boolean $threaded Optional control over flat or threaded comments.
  * @return int Number of comment pages.
@@ -776,12 +922,11 @@
 
 	$total = 0;
 	$approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed');
-	$known_types = array_keys( $approved );
-	foreach( (array) $count as $row_num => $row ) {
+	foreach ( (array) $count as $row ) {
 		// Don't count post-trashed toward totals
 		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] )
 			$total += $row['num_comments'];
-		if ( in_array( $row['comment_approved'], $known_types ) )
+		if ( isset( $approved[$row['comment_approved']] ) )
 			$stats[$approved[$row['comment_approved']]] = $row['num_comments'];
 	}
 
@@ -798,7 +943,10 @@
 }
 
 /**
- * Removes comment ID and maybe updates post comment count.
+ * Trashes or deletes a comment.
+ *
+ * The comment is moved to trash instead of permanently deleted unless trash is
+ * disabled, item is already in the trash, or $force_delete is true.
  *
  * The post comment count will be updated if the comment was approved and has a
  * post ID available.
@@ -811,14 +959,15 @@
  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
  *
  * @param int $comment_id Comment ID
+ * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
  * @return bool False if delete comment query failure, true on success.
  */
-function wp_delete_comment($comment_id) {
+function wp_delete_comment($comment_id, $force_delete = false) {
 	global $wpdb;
 	if (!$comment = get_comment($comment_id))
 		return false;
 
-	if (wp_get_comment_status($comment_id) != 'trash' && wp_get_comment_status($comment_id) != 'spam' && EMPTY_TRASH_DAYS > 0)
+	if ( !$force_delete && EMPTY_TRASH_DAYS && !in_array( wp_get_comment_status($comment_id), array( 'trash', 'spam' ) ) )
 		return wp_trash_comment($comment_id);
 
 	do_action('delete_comment', $comment_id);
@@ -831,15 +980,11 @@
 	}
 
 	// Delete metadata
-	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d ", $comment_id ) );
-	if ( !empty($meta_ids) ) {
-		do_action( 'delete_commentmeta', $meta_ids );
-		$in_meta_ids = "'" . implode("', '", $meta_ids) . "'";
-		$wpdb->query( "DELETE FROM $wpdb->commentmeta WHERE meta_id IN ($in_meta_ids)" );
-		do_action( 'deleted_commentmeta', $meta_ids );
-	}
+	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d", $comment_id ) );
+	foreach ( $meta_ids as $mid )
+		delete_metadata_by_mid( 'comment', $mid );
 
-	if ( ! $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment_id) ) )
+	if ( ! $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $comment_id ) ) )
 		return false;
 	do_action('deleted_comment', $comment_id);
 
@@ -857,16 +1002,19 @@
 /**
  * Moves a comment to the Trash
  *
+ * If trash is disabled, comment is permanently deleted.
+ *
  * @since 2.9.0
  * @uses do_action() on 'trash_comment' before trashing
  * @uses do_action() on 'trashed_comment' after trashing
+ * @uses wp_delete_comment() if trash is disabled
  *
  * @param int $comment_id Comment ID.
  * @return mixed False on failure
  */
 function wp_trash_comment($comment_id) {
-	if ( EMPTY_TRASH_DAYS == 0 )
-		return wp_delete_comment($comment_id);
+	if ( !EMPTY_TRASH_DAYS )
+		return wp_delete_comment($comment_id, true);
 
 	if ( !$comment = get_comment($comment_id) )
 		return false;
@@ -982,7 +1130,7 @@
 
 	$approved = $comment->comment_approved;
 
-	if ( $approved == NULL )
+	if ( $approved == null )
 		return false;
 	elseif ( $approved == '1' )
 		return 'approved';
@@ -1031,9 +1179,9 @@
 	// Call the hooks
 	if ( $new_status != $old_status ) {
 		do_action('transition_comment_status', $new_status, $old_status, $comment);
-		do_action("comment_${old_status}_to_$new_status", $comment);
+		do_action("comment_{$old_status}_to_{$new_status}", $comment);
 	}
-	do_action("comment_${new_status}_$comment->comment_type", $comment->comment_ID, $comment);
+	do_action("comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment);
 }
 
 /**
@@ -1063,7 +1211,7 @@
 	if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) )
 		$comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH];
 
-	return compact('comment_author', 'comment_author_email', 'comment_author_url');
+	return apply_filters('wp_get_current_commenter', compact('comment_author', 'comment_author_email', 'comment_author_url'));
 }
 
 /**
@@ -1137,7 +1285,7 @@
 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_ID']);
 	elseif ( isset($commentdata['user_id']) )
 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_id']);
-	$commentdata['comment_agent']        = apply_filters('pre_comment_user_agent', $commentdata['comment_agent']);
+	$commentdata['comment_agent']        = apply_filters('pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) );
 	$commentdata['comment_author']       = apply_filters('pre_comment_author_name', $commentdata['comment_author']);
 	$commentdata['comment_content']      = apply_filters('pre_comment_content', $commentdata['comment_content']);
 	$commentdata['comment_author_IP']    = apply_filters('pre_comment_user_ip', $commentdata['comment_author_IP']);
@@ -1173,6 +1321,10 @@
  * and whether comment is approved by WordPress. Also has 'preprocess_comment'
  * filter for processing the comment data before the function handles it.
  *
+ * We use REMOTE_ADDR here directly. If you are behind a proxy, you should ensure
+ * that it is properly set, such as in wp-config.php, for your environment.
+ * See {@link http://core.trac.wordpress.org/ticket/9235}
+ *
  * @since 1.5.0
  * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing
  * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved.
@@ -1216,8 +1368,8 @@
 
 		$post = &get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment
 
-		if ( get_option('comments_notify') && $commentdata['comment_approved'] && $post->post_author != $commentdata['user_id'] )
-			wp_notify_postauthor($comment_ID, $commentdata['comment_type']);
+		if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) )
+			wp_notify_postauthor($comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' );
 	}
 
 	return $comment_ID;
@@ -1226,17 +1378,14 @@
 /**
  * Sets the status of a comment.
  *
- * The 'wp_set_comment_status' action is called after the comment is handled and
- * will only be called, if the comment status is either 'hold', 'approve', or
- * 'spam'. If the comment status is not in the list, then false is returned and
- * if the status is 'delete', then the comment is deleted without calling the
- * action.
+ * The 'wp_set_comment_status' action is called after the comment is handled.
+ * If the comment status is not in the list, then false is returned.
  *
  * @since 1.0.0
  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
  *
  * @param int $comment_id Comment ID.
- * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'delete'.
+ * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.
  * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false.
  * @return bool False on failure or deletion and true on success.
  */
@@ -1267,7 +1416,7 @@
 			return false;
 	}
 
-	$comment_old = wp_clone(get_comment($comment_id));
+	$comment_old = clone get_comment($comment_id);
 
 	if ( !$wpdb->update( $wpdb->comments, array('comment_approved' => $status), array('comment_ID' => $comment_id) ) ) {
 		if ( $wp_error )
@@ -1331,9 +1480,7 @@
 		$comment_approved = 1;
 
 	$data = compact('comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt');
-	$wpdb->update($wpdb->comments, $data, compact('comment_ID'));
-
-	$rval = $wpdb->rows_affected;
+	$rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) );
 
 	clean_comment_cache($comment_ID);
 	wp_update_comment_count($comment_post_ID);
@@ -1432,10 +1579,7 @@
 	$new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) );
 	$wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
 
-	if ( 'page' == $post->post_type )
-		clean_page_cache( $post_id );
-	else
-		clean_post_cache( $post_id );
+	clean_post_cache( $post );
 
 	do_action('wp_update_comment_count', $post_id, $new, $old);
 	do_action('edit_post', $post_id, $post);
@@ -1460,7 +1604,9 @@
  * @param int $deprecated Not Used.
  * @return bool|string False on failure, string containing URI on success.
  */
-function discover_pingback_server_uri($url, $deprecated = 2048) {
+function discover_pingback_server_uri( $url, $deprecated = '' ) {
+	if ( !empty( $deprecated ) )
+		_deprecated_argument( __FUNCTION__, '2.7' );
 
 	$pingback_str_dquote = 'rel="pingback"';
 	$pingback_str_squote = 'rel=\'pingback\'';
@@ -1481,11 +1627,11 @@
 	if ( is_wp_error( $response ) )
 		return false;
 
-	if ( isset( $response['headers']['x-pingback'] ) )
-		return $response['headers']['x-pingback'];
+	if ( wp_remote_retrieve_header( $response, 'x-pingback' ) )
+		return wp_remote_retrieve_header( $response, 'x-pingback' );
 
 	// Not an (x)html, sgml, or xml page, no use going further.
-	if ( isset( $response['headers']['content-type'] ) && preg_match('#(image|audio|video|model)/#is', $response['headers']['content-type']) )
+	if ( preg_match('#(image|audio|video|model)/#is', wp_remote_retrieve_header( $response, 'content-type' )) )
 		return false;
 
 	// Now do a GET since we're going to look in the html headers (and we're sure its not a binary file)
@@ -1494,7 +1640,7 @@
 	if ( is_wp_error( $response ) )
 		return false;
 
-	$contents = $response['body'];
+	$contents = wp_remote_retrieve_body( $response );
 
 	$pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote);
 	$pingback_link_offset_squote = strpos($contents, $pingback_str_squote);
@@ -1526,21 +1672,15 @@
 	global $wpdb;
 
 	// Do pingbacks
-	while ($ping = $wpdb->get_row("SELECT * FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1")) {
-		$mid = $wpdb->get_var( "SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = {$ping->ID} AND meta_key = '_pingme' LIMIT 1");
-		do_action( 'delete_postmeta', $mid );
-		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_id = %d", $mid ) );
-		do_action( 'deleted_postmeta', $mid );
-		pingback($ping->post_content, $ping->ID);
+	while ($ping = $wpdb->get_row("SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1")) {
+		delete_metadata_by_mid( 'post', $ping->meta_id );
+		pingback( $ping->post_content, $ping->ID );
 	}
 
 	// Do Enclosures
-	while ($enclosure = $wpdb->get_row("SELECT * FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1")) {
-		$mid = $wpdb->get_var( $wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_encloseme'", $enclosure->ID) );
-		do_action( 'delete_postmeta', $mid );
-		$wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_id =  %d", $mid) );
-		do_action( 'deleted_postmeta', $mid );
-		do_enclose($enclosure->post_content, $enclosure->ID);
+	while ($enclosure = $wpdb->get_row("SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1")) {
+		delete_metadata_by_mid( 'post', $enclosure->meta_id );
+		do_enclose( $enclosure->post_content, $enclosure->ID );
 	}
 
 	// Do Trackbacks
@@ -1579,7 +1719,7 @@
 	$excerpt = str_replace(']]>', ']]&gt;', $excerpt);
 	$excerpt = wp_html_excerpt($excerpt, 252) . '...';
 
-	$post_title = apply_filters('the_title', $post->post_title);
+	$post_title = apply_filters('the_title', $post->post_title, $post->ID);
 	$post_title = strip_tags($post_title);
 
 	if ( $to_ping ) {
@@ -1589,7 +1729,7 @@
 				trackback($tb_ping, $post_title, $excerpt, $post_id);
 				$pinged[] = $tb_ping;
 			} else {
-				$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = %d", $post_id) );
+				$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $tb_ping, $post_id) );
 			}
 		}
 	}
@@ -1629,6 +1769,7 @@
 function pingback($content, $post_ID) {
 	global $wp_version;
 	include_once(ABSPATH . WPINC . '/class-IXR.php');
+	include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php');
 
 	// original code by Mort (http://mort.mine.nu:8080)
 	$post_links = array();
@@ -1662,16 +1803,16 @@
 			if ( $test = @parse_url($link_test) ) {
 				if ( isset($test['query']) )
 					$post_links[] = $link_test;
-				elseif ( ($test['path'] != '/') && ($test['path'] != '') )
+				elseif ( isset( $test['path'] ) && ( $test['path'] != '/' ) && ( $test['path'] != '' ) )
 					$post_links[] = $link_test;
 			}
 		endif;
 	endforeach;
 
-	do_action_ref_array('pre_ping', array(&$post_links, &$pung));
+	do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post_ID ) );
 
 	foreach ( (array) $post_links as $pagelinkedto ) {
-		$pingback_server_url = discover_pingback_server_uri($pagelinkedto, 2048);
+		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
 
 		if ( $pingback_server_url ) {
 			@ set_time_limit( 60 );
@@ -1679,7 +1820,7 @@
 			$pagelinkedfrom = get_permalink($post_ID);
 
 			// using a timeout of 3 seconds should be enough to cover slow servers
-			$client = new IXR_Client($pingback_server_url);
+			$client = new WP_HTTP_IXR_Client($pingback_server_url);
 			$client->timeout = 3;
 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom);
 			// when set to true, this outputs debug messages by itself
@@ -1740,9 +1881,8 @@
 	if ( is_wp_error( $response ) )
 		return;
 
-	$tb_url = addslashes( $trackback_url );
-	$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', '$tb_url') WHERE ID = %d", $ID) );
-	return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_url', '')) WHERE ID = %d", $ID) );
+	$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', %s) WHERE ID = %d", $trackback_url, $ID) );
+	return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $trackback_url, $ID) );
 }
 
 /**
@@ -1758,15 +1898,16 @@
 function weblog_ping($server = '', $path = '') {
 	global $wp_version;
 	include_once(ABSPATH . WPINC . '/class-IXR.php');
+	include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php');
 
 	// using a timeout of 3 seconds should be enough to cover slow servers
-	$client = new IXR_Client($server, ((!strlen(trim($path)) || ('/' == $path)) ? false : $path));
+	$client = new WP_HTTP_IXR_Client($server, ((!strlen(trim($path)) || ('/' == $path)) ? false : $path));
 	$client->timeout = 3;
 	$client->useragent .= ' -- WordPress/'.$wp_version;
 
 	// when set to true, this outputs debug messages by itself
 	$client->debug = false;
-	$home = trailingslashit( get_option('home') );
+	$home = trailingslashit( home_url() );
 	if ( !$client->query('weblogUpdates.extendedPing', get_option('blogname'), $home, get_bloginfo('rss2_url') ) ) // then try a normal ping
 		$client->query('weblogUpdates.ping', get_option('blogname'), $home);
 }
@@ -1782,11 +1923,13 @@
  * @package WordPress
  * @subpackage Cache
  *
- * @param int|array $id Comment ID or array of comment IDs to remove from cache
+ * @param int|array $ids Comment ID or array of comment IDs to remove from cache
  */
 function clean_comment_cache($ids) {
 	foreach ( (array) $ids as $id )
 		wp_cache_delete($id, 'comment');
+
+	wp_cache_set('last_changed', time(), 'comment');
 }
 
 /**
@@ -1812,20 +1955,25 @@
 //
 
 /**
- * Close comments on old posts on the fly, without any extra DB queries.  Hooked to the_posts.
+ * Close comments on old posts on the fly, without any extra DB queries. Hooked to the_posts.
  *
  * @access private
  * @since 2.7.0
  *
  * @param object $posts Post data object.
+ * @param object $query Query object.
  * @return object
  */
-function _close_comments_for_old_posts( $posts ) {
-	if ( empty($posts) || !is_singular() || !get_option('close_comments_for_old_posts') )
+function _close_comments_for_old_posts( $posts, $query ) {
+	if ( empty( $posts ) || ! $query->is_singular() || ! get_option( 'close_comments_for_old_posts' ) )
 		return $posts;
 
-	$days_old = (int) get_option('close_comments_days_old');
-	if ( !$days_old )
+	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
+	if ( ! in_array( $posts[0]->post_type, $post_types ) )
+		return $posts;
+
+	$days_old = (int) get_option( 'close_comments_days_old' );
+	if ( ! $days_old )
 		return $posts;
 
 	if ( time() - strtotime( $posts[0]->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) ) {
@@ -1837,7 +1985,7 @@
 }
 
 /**
- * Close comments on an old post.  Hooked to comments_open and pings_open.
+ * Close comments on an old post. Hooked to comments_open and pings_open.
  *
  * @access private
  * @since 2.7.0
@@ -1859,10 +2007,12 @@
 
 	$post = get_post($post_id);
 
+	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
+	if ( ! in_array( $post->post_type, $post_types ) )
+		return $open;
+
 	if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) )
 		return false;
 
 	return $open;
 }
-
-?>