web/wp-includes/comment.php
changeset 194 32102edaa81b
parent 136 bde1974c263b
child 204 09a1c134465b
equal deleted inserted replaced
193:2f6f6f7551ca 194:32102edaa81b
    16  *
    16  *
    17  * If the number of links exceeds the amount in the administration, then the
    17  * If the number of links exceeds the amount in the administration, then the
    18  * check fails. If any of the parameter contents match the blacklist of words,
    18  * check fails. If any of the parameter contents match the blacklist of words,
    19  * then the check fails.
    19  * then the check fails.
    20  *
    20  *
    21  * If the comment is a trackback and part of the blogroll, then the trackback is
    21  * If the comment author was approved before, then the comment is
    22  * automatically whitelisted. If the comment author was approved before, then
    22  * automatically whitelisted.
    23  * the comment is automatically whitelisted.
       
    24  *
    23  *
    25  * If none of the checks fail, then the failback is to set the check to pass
    24  * If none of the checks fail, then the failback is to set the check to pass
    26  * (return true).
    25  * (return true).
    27  *
    26  *
    28  * @since 1.2.0
    27  * @since 1.2.0
    43 	global $wpdb;
    42 	global $wpdb;
    44 
    43 
    45 	if ( 1 == get_option('comment_moderation') )
    44 	if ( 1 == get_option('comment_moderation') )
    46 		return false; // If moderation is set to manual
    45 		return false; // If moderation is set to manual
    47 
    46 
    48 	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') )
    47 	$comment = apply_filters( 'comment_text', $comment );
    49 		return false; // Check # of external links
    48 
       
    49 	// Check # of external links
       
    50 	if ( $max_links = get_option( 'comment_max_links' ) ) {
       
    51 		$num_links = preg_match_all( '/<a [^>]*href/i', $comment, $out );
       
    52 		$num_links = apply_filters( 'comment_max_links_url', $num_links, $url ); // provide for counting of $url as a link
       
    53 		if ( $num_links >= $max_links )
       
    54 			return false;
       
    55 	}
    50 
    56 
    51 	$mod_keys = trim(get_option('moderation_keys'));
    57 	$mod_keys = trim(get_option('moderation_keys'));
    52 	if ( !empty($mod_keys) ) {
    58 	if ( !empty($mod_keys) ) {
    53 		$words = explode("\n", $mod_keys );
    59 		$words = explode("\n", $mod_keys );
    54 
    60 
    73 		}
    79 		}
    74 	}
    80 	}
    75 
    81 
    76 	// Comment whitelisting:
    82 	// Comment whitelisting:
    77 	if ( 1 == get_option('comment_whitelist')) {
    83 	if ( 1 == get_option('comment_whitelist')) {
    78 		if ( 'trackback' == $comment_type || 'pingback' == $comment_type ) { // check if domain is in blogroll
    84 		if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) {
    79 			$uri = parse_url($url);
       
    80 			$domain = $uri['host'];
       
    81 			$uri = parse_url( get_option('home') );
       
    82 			$home_domain = $uri['host'];
       
    83 			if ( $wpdb->get_var($wpdb->prepare("SELECT link_id FROM $wpdb->links WHERE link_url LIKE (%s) LIMIT 1", '%'.$domain.'%')) || $domain == $home_domain )
       
    84 				return true;
       
    85 			else
       
    86 				return false;
       
    87 		} elseif ( $author != '' && $email != '' ) {
       
    88 			// expected_slashed ($author, $email)
    85 			// expected_slashed ($author, $email)
    89 			$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");
    86 			$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");
    90 			if ( ( 1 == $ok_to_comment ) &&
    87 			if ( ( 1 == $ok_to_comment ) &&
    91 				( empty($mod_keys) || false === strpos( $email, $mod_keys) ) )
    88 				( empty($mod_keys) || false === strpos( $email, $mod_keys) ) )
    92 					return true;
    89 					return true;
   181  *
   178  *
   182  * @param mixed $args Optional. Array or string of options to override defaults.
   179  * @param mixed $args Optional. Array or string of options to override defaults.
   183  * @return array List of comments.
   180  * @return array List of comments.
   184  */
   181  */
   185 function get_comments( $args = '' ) {
   182 function get_comments( $args = '' ) {
   186 	global $wpdb;
   183 	$query = new WP_Comment_Query;
   187 
   184 	return $query->query( $args );
   188 	$defaults = array('status' => '', 'orderby' => 'comment_date_gmt', 'order' => 'DESC', 'number' => '', 'offset' => '', 'post_id' => 0);
   185 }
   189 
   186 
   190 	$args = wp_parse_args( $args, $defaults );
   187 /**
   191 	extract( $args, EXTR_SKIP );
   188  * WordPress Comment Query class.
   192 
   189  *
   193 	// $args can be whatever, only use the args defined in defaults to compute the key
   190  * @since 3.1.0
   194 	$key = md5( serialize( compact(array_keys($defaults)) )  );
   191  */
   195 	$last_changed = wp_cache_get('last_changed', 'comment');
   192 class WP_Comment_Query {
   196 	if ( !$last_changed ) {
   193 
   197 		$last_changed = time();
   194 	/**
   198 		wp_cache_set('last_changed', $last_changed, 'comment');
   195 	 * Execute the query
   199 	}
   196 	 *
   200 	$cache_key = "get_comments:$key:$last_changed";
   197 	 * @since 3.1.0
   201 
   198 	 *
   202 	if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) {
   199 	 * @param string|array $query_vars
   203 		return $cache;
   200 	 * @return int|array
   204 	}
   201 	 */
   205 
   202 	function query( $query_vars ) {
   206 	$post_id = absint($post_id);
   203 		global $wpdb;
   207 
   204 
   208 	if ( 'hold' == $status )
   205 		$defaults = array(
   209 		$approved = "comment_approved = '0'";
   206 			'author_email' => '',
   210 	elseif ( 'approve' == $status )
   207 			'ID' => '',
   211 		$approved = "comment_approved = '1'";
   208 			'karma' => '',
   212 	elseif ( 'spam' == $status )
   209 			'number' => '',
   213 		$approved = "comment_approved = 'spam'";
   210 			'offset' => '',
   214 	elseif ( 'trash' == $status )
   211 			'orderby' => '',
   215 		$approved = "comment_approved = 'trash'";
   212 			'order' => 'DESC',
   216 	else
   213 			'parent' => '',
   217 		$approved = "( comment_approved = '0' OR comment_approved = '1' )";
   214 			'post_ID' => '',
   218 
   215 			'post_id' => 0,
   219 	$order = ( 'ASC' == $order ) ? 'ASC' : 'DESC';
   216 			'post_author' => '',
   220 
   217 			'post_name' => '',
   221 	$orderby = 'comment_date_gmt';  // Hard code for now
   218 			'post_parent' => '',
   222 
   219 			'post_status' => '',
   223 	$number = absint($number);
   220 			'post_type' => '',
   224 	$offset = absint($offset);
   221 			'status' => '',
   225 
   222 			'type' => '',
   226 	if ( !empty($number) ) {
   223 			'user_id' => '',
   227 		if ( $offset )
   224 			'search' => '',
   228 			$number = 'LIMIT ' . $offset . ',' . $number;
   225 			'count' => false
       
   226 		);
       
   227 
       
   228 		$this->query_vars = wp_parse_args( $query_vars, $defaults );
       
   229 		do_action_ref_array( 'pre_get_comments', array( &$this ) );
       
   230 		extract( $this->query_vars, EXTR_SKIP );
       
   231 
       
   232 		// $args can be whatever, only use the args defined in defaults to compute the key
       
   233 		$key = md5( serialize( compact(array_keys($defaults)) )  );
       
   234 		$last_changed = wp_cache_get('last_changed', 'comment');
       
   235 		if ( !$last_changed ) {
       
   236 			$last_changed = time();
       
   237 			wp_cache_set('last_changed', $last_changed, 'comment');
       
   238 		}
       
   239 		$cache_key = "get_comments:$key:$last_changed";
       
   240 
       
   241 		if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) {
       
   242 			return $cache;
       
   243 		}
       
   244 
       
   245 		$post_id = absint($post_id);
       
   246 
       
   247 		if ( 'hold' == $status )
       
   248 			$approved = "comment_approved = '0'";
       
   249 		elseif ( 'approve' == $status )
       
   250 			$approved = "comment_approved = '1'";
       
   251 		elseif ( 'spam' == $status )
       
   252 			$approved = "comment_approved = 'spam'";
       
   253 		elseif ( 'trash' == $status )
       
   254 			$approved = "comment_approved = 'trash'";
   229 		else
   255 		else
   230 			$number = 'LIMIT ' . $number;
   256 			$approved = "( comment_approved = '0' OR comment_approved = '1' )";
   231 
   257 
   232 	} else {
   258 		$order = ( 'ASC' == strtoupper($order) ) ? 'ASC' : 'DESC';
   233 		$number = '';
   259 
   234 	}
   260 		if ( ! empty( $orderby ) ) {
   235 
   261 			$ordersby = is_array($orderby) ? $orderby : preg_split('/[,\s]/', $orderby);
   236 	if ( ! empty($post_id) )
   262 			$ordersby = array_intersect(
   237 		$post_where = $wpdb->prepare( 'comment_post_ID = %d AND', $post_id );
   263 				$ordersby,
   238 	else
   264 				array(
   239 		$post_where = '';
   265 					'comment_agent',
   240 
   266 					'comment_approved',
   241 	$comments = $wpdb->get_results( "SELECT * FROM $wpdb->comments WHERE $post_where $approved ORDER BY $orderby $order $number" );
   267 					'comment_author',
   242 	wp_cache_add( $cache_key, $comments, 'comment' );
   268 					'comment_author_email',
   243 
   269 					'comment_author_IP',
   244 	return $comments;
   270 					'comment_author_url',
       
   271 					'comment_content',
       
   272 					'comment_date',
       
   273 					'comment_date_gmt',
       
   274 					'comment_ID',
       
   275 					'comment_karma',
       
   276 					'comment_parent',
       
   277 					'comment_post_ID',
       
   278 					'comment_type',
       
   279 					'user_id',
       
   280 				)
       
   281 			);
       
   282 			$orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby);
       
   283 		} else {
       
   284 			$orderby = 'comment_date_gmt';
       
   285 		}
       
   286 
       
   287 		$number = absint($number);
       
   288 		$offset = absint($offset);
       
   289 
       
   290 		if ( !empty($number) ) {
       
   291 			if ( $offset )
       
   292 				$limits = 'LIMIT ' . $offset . ',' . $number;
       
   293 			else
       
   294 				$limits = 'LIMIT ' . $number;
       
   295 		} else {
       
   296 			$limits = '';
       
   297 		}
       
   298 
       
   299 		if ( $count )
       
   300 			$fields = 'COUNT(*)';
       
   301 		else
       
   302 			$fields = '*';
       
   303 
       
   304 		$join = '';
       
   305 		$where = $approved;
       
   306 
       
   307 		if ( ! empty($post_id) )
       
   308 			$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
       
   309 		if ( '' !== $author_email )
       
   310 			$where .= $wpdb->prepare( ' AND comment_author_email = %s', $author_email );
       
   311 		if ( '' !== $karma )
       
   312 			$where .= $wpdb->prepare( ' AND comment_karma = %d', $karma );
       
   313 		if ( 'comment' == $type ) {
       
   314 			$where .= " AND comment_type = ''";
       
   315 		} elseif( 'pings' == $type ) {
       
   316 			$where .= ' AND comment_type IN ("pingback", "trackback")';
       
   317 		} elseif ( ! empty( $type ) ) {
       
   318 			$where .= $wpdb->prepare( ' AND comment_type = %s', $type );
       
   319 		}
       
   320 		if ( '' !== $parent )
       
   321 			$where .= $wpdb->prepare( ' AND comment_parent = %d', $parent );
       
   322 		if ( '' !== $user_id )
       
   323 			$where .= $wpdb->prepare( ' AND user_id = %d', $user_id );
       
   324 		if ( '' !== $search )
       
   325 			$where .= $this->get_search_sql( $search, array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' ) );
       
   326 
       
   327 		$post_fields = array_filter( compact( array( 'post_author', 'post_name', 'post_parent', 'post_status', 'post_type', ) ) );
       
   328 		if ( ! empty( $post_fields ) ) {
       
   329 			$join = "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
       
   330 			foreach( $post_fields as $field_name => $field_value )
       
   331 				$where .= $wpdb->prepare( " AND {$wpdb->posts}.{$field_name} = %s", $field_value );
       
   332 		}
       
   333 
       
   334 		$pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits' );
       
   335 		$clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );
       
   336 		foreach ( $pieces as $piece )
       
   337 			$$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : '';
       
   338 
       
   339 		$query = "SELECT $fields FROM $wpdb->comments $join WHERE $where ORDER BY $orderby $order $limits";
       
   340 
       
   341 		if ( $count )
       
   342 			return $wpdb->get_var( $query );
       
   343 
       
   344 		$comments = $wpdb->get_results( $query );
       
   345 		$comments = apply_filters_ref_array( 'the_comments', array( $comments, &$this ) );
       
   346 
       
   347 		wp_cache_add( $cache_key, $comments, 'comment' );
       
   348 
       
   349 		return $comments;
       
   350 	}
       
   351 
       
   352 	/*
       
   353 	 * Used internally to generate an SQL string for searching across multiple columns
       
   354 	 *
       
   355 	 * @access protected
       
   356 	 * @since 3.1.0
       
   357 	 *
       
   358 	 * @param string $string
       
   359 	 * @param array $cols
       
   360 	 * @return string
       
   361 	 */
       
   362 	function get_search_sql( $string, $cols ) {
       
   363 		$string = esc_sql( like_escape( $string ) );
       
   364 
       
   365 		$searches = array();
       
   366 		foreach ( $cols as $col )
       
   367 			$searches[] = "$col LIKE '%$string%'";
       
   368 
       
   369 		return ' AND (' . implode(' OR ', $searches) . ')';
       
   370 	}
   245 }
   371 }
   246 
   372 
   247 /**
   373 /**
   248  * Retrieve all of the WordPress supported comment statuses.
   374  * Retrieve all of the WordPress supported comment statuses.
   249  *
   375  *
   265 		'spam'		=> _x('Spam', 'adjective'),
   391 		'spam'		=> _x('Spam', 'adjective'),
   266 	);
   392 	);
   267 
   393 
   268 	return $status;
   394 	return $status;
   269 }
   395 }
   270 
       
   271 
   396 
   272 /**
   397 /**
   273  * The date the last comment was modified.
   398  * The date the last comment was modified.
   274  *
   399  *
   275  * @since 1.5.0
   400  * @since 1.5.0
   369 //
   494 //
   370 
   495 
   371 /**
   496 /**
   372  * Add meta data field to a comment.
   497  * Add meta data field to a comment.
   373  *
   498  *
   374  * @since 2.9
   499  * @since 2.9.0
   375  * @uses add_metadata
   500  * @uses add_metadata
   376  * @link http://codex.wordpress.org/Function_Reference/add_comment_meta
   501  * @link http://codex.wordpress.org/Function_Reference/add_comment_meta
   377  *
   502  *
   378  * @param int $comment_id Comment ID.
   503  * @param int $comment_id Comment ID.
   379  * @param string $key Metadata name.
   504  * @param string $meta_key Metadata name.
   380  * @param mixed $value Metadata value.
   505  * @param mixed $meta_value Metadata value.
   381  * @param bool $unique Optional, default is false. Whether the same key should not be added.
   506  * @param bool $unique Optional, default is false. Whether the same key should not be added.
   382  * @return bool False for failure. True for success.
   507  * @return bool False for failure. True for success.
   383  */
   508  */
   384 function add_comment_meta($comment_id, $meta_key, $meta_value, $unique = false) {
   509 function add_comment_meta($comment_id, $meta_key, $meta_value, $unique = false) {
   385 	return add_metadata('comment', $comment_id, $meta_key, $meta_value, $unique);
   510 	return add_metadata('comment', $comment_id, $meta_key, $meta_value, $unique);
   390  *
   515  *
   391  * You can match based on the key, or key and value. Removing based on key and
   516  * You can match based on the key, or key and value. Removing based on key and
   392  * value, will keep from removing duplicate metadata with the same key. It also
   517  * value, will keep from removing duplicate metadata with the same key. It also
   393  * allows removing all metadata matching key, if needed.
   518  * allows removing all metadata matching key, if needed.
   394  *
   519  *
   395  * @since 2.9
   520  * @since 2.9.0
   396  * @uses delete_metadata
   521  * @uses delete_metadata
   397  * @link http://codex.wordpress.org/Function_Reference/delete_comment_meta
   522  * @link http://codex.wordpress.org/Function_Reference/delete_comment_meta
   398  *
   523  *
   399  * @param int $comment_id comment ID
   524  * @param int $comment_id comment ID
   400  * @param string $meta_key Metadata name.
   525  * @param string $meta_key Metadata name.
   406 }
   531 }
   407 
   532 
   408 /**
   533 /**
   409  * Retrieve comment meta field for a comment.
   534  * Retrieve comment meta field for a comment.
   410  *
   535  *
   411  * @since 2.9
   536  * @since 2.9.0
   412  * @uses get_metadata
   537  * @uses get_metadata
   413  * @link http://codex.wordpress.org/Function_Reference/get_comment_meta
   538  * @link http://codex.wordpress.org/Function_Reference/get_comment_meta
   414  *
   539  *
   415  * @param int $comment_id Comment ID.
   540  * @param int $comment_id Comment ID.
   416  * @param string $key The meta key to retrieve.
   541  * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
   417  * @param bool $single Whether to return a single value.
   542  * @param bool $single Whether to return a single value.
   418  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
   543  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
   419  *  is true.
   544  *  is true.
   420  */
   545  */
   421 function get_comment_meta($comment_id, $key, $single = false) {
   546 function get_comment_meta($comment_id, $key = '', $single = false) {
   422 	return get_metadata('comment', $comment_id, $key, $single);
   547 	return get_metadata('comment', $comment_id, $key, $single);
   423 }
   548 }
   424 
   549 
   425 /**
   550 /**
   426  * Update comment meta field based on comment ID.
   551  * Update comment meta field based on comment ID.
   428  * Use the $prev_value parameter to differentiate between meta fields with the
   553  * Use the $prev_value parameter to differentiate between meta fields with the
   429  * same key and comment ID.
   554  * same key and comment ID.
   430  *
   555  *
   431  * If the meta field for the comment does not exist, it will be added.
   556  * If the meta field for the comment does not exist, it will be added.
   432  *
   557  *
   433  * @since 2.9
   558  * @since 2.9.0
   434  * @uses update_metadata
   559  * @uses update_metadata
   435  * @link http://codex.wordpress.org/Function_Reference/update_comment_meta
   560  * @link http://codex.wordpress.org/Function_Reference/update_comment_meta
   436  *
   561  *
   437  * @param int $comment_id Comment ID.
   562  * @param int $comment_id Comment ID.
   438  * @param string $key Metadata key.
   563  * @param string $meta_key Metadata key.
   439  * @param mixed $value Metadata value.
   564  * @param mixed $meta_value Metadata value.
   440  * @param mixed $prev_value Optional. Previous value to check before removing.
   565  * @param mixed $prev_value Optional. Previous value to check before removing.
   441  * @return bool False on failure, true if success.
   566  * @return bool False on failure, true if success.
   442  */
   567  */
   443 function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') {
   568 function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') {
   444 	return update_metadata('comment', $comment_id, $meta_key, $meta_value, $prev_value);
   569 	return update_metadata('comment', $comment_id, $meta_key, $meta_value, $prev_value);
       
   570 }
       
   571 
       
   572 /**
       
   573  * Sets the cookies used to store an unauthenticated commentator's identity. Typically used
       
   574  * to recall previous comments by this commentator that are still held in moderation.
       
   575  *
       
   576  * @param object $comment Comment object.
       
   577  * @param object $user Comment author's object.
       
   578  *
       
   579  * @since 3.4.0
       
   580  */
       
   581 function wp_set_comment_cookies($comment, $user) {
       
   582 	if ( $user->exists() )
       
   583 		return;
       
   584 
       
   585 	$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
       
   586 	setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
       
   587 	setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
       
   588 	setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
   445 }
   589 }
   446 
   590 
   447 /**
   591 /**
   448  * Sanitizes the cookies sent to the user already.
   592  * Sanitizes the cookies sent to the user already.
   449  *
   593  *
   473 		$_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url;
   617 		$_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url;
   474 	}
   618 	}
   475 }
   619 }
   476 
   620 
   477 /**
   621 /**
   478  * Validates whether this comment is allowed to be made or not.
   622  * Validates whether this comment is allowed to be made.
   479  *
   623  *
   480  * @since 2.0.0
   624  * @since 2.0.0
   481  * @uses $wpdb
   625  * @uses $wpdb
   482  * @uses apply_filters() Calls 'pre_comment_approved' hook on the type of comment
   626  * @uses apply_filters() Calls 'pre_comment_approved' hook on the type of comment
       
   627  * @uses apply_filters() Calls 'comment_duplicate_trigger' hook on commentdata.
   483  * @uses do_action() Calls 'check_comment_flood' hook on $comment_author_IP, $comment_author_email, and $comment_date_gmt
   628  * @uses do_action() Calls 'check_comment_flood' hook on $comment_author_IP, $comment_author_email, and $comment_date_gmt
   484  *
   629  *
   485  * @param array $commentdata Contains information on the comment
   630  * @param array $commentdata Contains information on the comment
   486  * @return mixed Signifies the approval status (0|1|'spam')
   631  * @return mixed Signifies the approval status (0|1|'spam')
   487  */
   632  */
   494 	$dupe = "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = '$comment_post_ID' AND comment_approved != 'trash' AND ( comment_author = '$comment_author' ";
   639 	$dupe = "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = '$comment_post_ID' AND comment_approved != 'trash' AND ( comment_author = '$comment_author' ";
   495 	if ( $comment_author_email )
   640 	if ( $comment_author_email )
   496 		$dupe .= "OR comment_author_email = '$comment_author_email' ";
   641 		$dupe .= "OR comment_author_email = '$comment_author_email' ";
   497 	$dupe .= ") AND comment_content = '$comment_content' LIMIT 1";
   642 	$dupe .= ") AND comment_content = '$comment_content' LIMIT 1";
   498 	if ( $wpdb->get_var($dupe) ) {
   643 	if ( $wpdb->get_var($dupe) ) {
       
   644 		do_action( 'comment_duplicate_trigger', $commentdata );
   499 		if ( defined('DOING_AJAX') )
   645 		if ( defined('DOING_AJAX') )
   500 			die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
   646 			die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
   501 
   647 
   502 		wp_die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
   648 		wp_die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
   503 	}
   649 	}
   521 			$approved = 0;
   667 			$approved = 0;
   522 		if ( wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent) )
   668 		if ( wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent) )
   523 			$approved = 'spam';
   669 			$approved = 'spam';
   524 	}
   670 	}
   525 
   671 
   526 	$approved = apply_filters('pre_comment_approved', $approved);
   672 	$approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );
   527 	return $approved;
   673 	return $approved;
   528 }
   674 }
   529 
   675 
   530 /**
   676 /**
   531  * Check whether comment flooding is occurring.
   677  * Check whether comment flooding is occurring.
   555 		$flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment);
   701 		$flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment);
   556 		if ( $flood_die ) {
   702 		if ( $flood_die ) {
   557 			do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment);
   703 			do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment);
   558 
   704 
   559 			if ( defined('DOING_AJAX') )
   705 			if ( defined('DOING_AJAX') )
   560 				die( __('You are posting comments too quickly.  Slow down.') );
   706 				die( __('You are posting comments too quickly. Slow down.') );
   561 
   707 
   562 			wp_die( __('You are posting comments too quickly.  Slow down.'), '', array('response' => 403) );
   708 			wp_die( __('You are posting comments too quickly. Slow down.'), '', array('response' => 403) );
   563 		}
   709 		}
   564 	}
   710 	}
   565 }
   711 }
   566 
   712 
   567 /**
   713 /**
   593  * @since 2.7.0
   739  * @since 2.7.0
   594  * @uses get_query_var() Used to fill in the default for $per_page parameter.
   740  * @uses get_query_var() Used to fill in the default for $per_page parameter.
   595  * @uses get_option() Used to fill in defaults for parameters.
   741  * @uses get_option() Used to fill in defaults for parameters.
   596  * @uses Walker_Comment
   742  * @uses Walker_Comment
   597  *
   743  *
   598  * @param array $comments Optional array of comment objects.  Defaults to $wp_query->comments
   744  * @param array $comments Optional array of comment objects. Defaults to $wp_query->comments
   599  * @param int $per_page Optional comments per page.
   745  * @param int $per_page Optional comments per page.
   600  * @param boolean $threaded Optional control over flat or threaded comments.
   746  * @param boolean $threaded Optional control over flat or threaded comments.
   601  * @return int Number of comment pages.
   747  * @return int Number of comment pages.
   602  */
   748  */
   603 function get_comment_pages_count( $comments = null, $per_page = null, $threaded = null ) {
   749 function get_comment_pages_count( $comments = null, $per_page = null, $threaded = null ) {
   774 
   920 
   775 	$count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A );
   921 	$count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A );
   776 
   922 
   777 	$total = 0;
   923 	$total = 0;
   778 	$approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed');
   924 	$approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed');
   779 	$known_types = array_keys( $approved );
   925 	foreach ( (array) $count as $row ) {
   780 	foreach( (array) $count as $row_num => $row ) {
       
   781 		// Don't count post-trashed toward totals
   926 		// Don't count post-trashed toward totals
   782 		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] )
   927 		if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] )
   783 			$total += $row['num_comments'];
   928 			$total += $row['num_comments'];
   784 		if ( in_array( $row['comment_approved'], $known_types ) )
   929 		if ( isset( $approved[$row['comment_approved']] ) )
   785 			$stats[$approved[$row['comment_approved']]] = $row['num_comments'];
   930 			$stats[$approved[$row['comment_approved']]] = $row['num_comments'];
   786 	}
   931 	}
   787 
   932 
   788 	$stats['total_comments'] = $total;
   933 	$stats['total_comments'] = $total;
   789 	foreach ( $approved as $key ) {
   934 	foreach ( $approved as $key ) {
   796 
   941 
   797 	return $stats;
   942 	return $stats;
   798 }
   943 }
   799 
   944 
   800 /**
   945 /**
   801  * Removes comment ID and maybe updates post comment count.
   946  * Trashes or deletes a comment.
       
   947  *
       
   948  * The comment is moved to trash instead of permanently deleted unless trash is
       
   949  * disabled, item is already in the trash, or $force_delete is true.
   802  *
   950  *
   803  * The post comment count will be updated if the comment was approved and has a
   951  * The post comment count will be updated if the comment was approved and has a
   804  * post ID available.
   952  * post ID available.
   805  *
   953  *
   806  * @since 2.0.0
   954  * @since 2.0.0
   809  * @uses do_action() Calls 'deleted_comment' hook on comment ID after deletion, on success
   957  * @uses do_action() Calls 'deleted_comment' hook on comment ID after deletion, on success
   810  * @uses do_action() Calls 'wp_set_comment_status' hook on comment ID with 'delete' set for the second parameter
   958  * @uses do_action() Calls 'wp_set_comment_status' hook on comment ID with 'delete' set for the second parameter
   811  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
   959  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
   812  *
   960  *
   813  * @param int $comment_id Comment ID
   961  * @param int $comment_id Comment ID
       
   962  * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
   814  * @return bool False if delete comment query failure, true on success.
   963  * @return bool False if delete comment query failure, true on success.
   815  */
   964  */
   816 function wp_delete_comment($comment_id) {
   965 function wp_delete_comment($comment_id, $force_delete = false) {
   817 	global $wpdb;
   966 	global $wpdb;
   818 	if (!$comment = get_comment($comment_id))
   967 	if (!$comment = get_comment($comment_id))
   819 		return false;
   968 		return false;
   820 
   969 
   821 	if (wp_get_comment_status($comment_id) != 'trash' && wp_get_comment_status($comment_id) != 'spam' && EMPTY_TRASH_DAYS > 0)
   970 	if ( !$force_delete && EMPTY_TRASH_DAYS && !in_array( wp_get_comment_status($comment_id), array( 'trash', 'spam' ) ) )
   822 		return wp_trash_comment($comment_id);
   971 		return wp_trash_comment($comment_id);
   823 
   972 
   824 	do_action('delete_comment', $comment_id);
   973 	do_action('delete_comment', $comment_id);
   825 
   974 
   826 	// Move children up a level.
   975 	// Move children up a level.
   829 		$wpdb->update($wpdb->comments, array('comment_parent' => $comment->comment_parent), array('comment_parent' => $comment_id));
   978 		$wpdb->update($wpdb->comments, array('comment_parent' => $comment->comment_parent), array('comment_parent' => $comment_id));
   830 		clean_comment_cache($children);
   979 		clean_comment_cache($children);
   831 	}
   980 	}
   832 
   981 
   833 	// Delete metadata
   982 	// Delete metadata
   834 	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d ", $comment_id ) );
   983 	$meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d", $comment_id ) );
   835 	if ( !empty($meta_ids) ) {
   984 	foreach ( $meta_ids as $mid )
   836 		do_action( 'delete_commentmeta', $meta_ids );
   985 		delete_metadata_by_mid( 'comment', $mid );
   837 		$in_meta_ids = "'" . implode("', '", $meta_ids) . "'";
   986 
   838 		$wpdb->query( "DELETE FROM $wpdb->commentmeta WHERE meta_id IN ($in_meta_ids)" );
   987 	if ( ! $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $comment_id ) ) )
   839 		do_action( 'deleted_commentmeta', $meta_ids );
       
   840 	}
       
   841 
       
   842 	if ( ! $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment_id) ) )
       
   843 		return false;
   988 		return false;
   844 	do_action('deleted_comment', $comment_id);
   989 	do_action('deleted_comment', $comment_id);
   845 
   990 
   846 	$post_id = $comment->comment_post_ID;
   991 	$post_id = $comment->comment_post_ID;
   847 	if ( $post_id && $comment->comment_approved == 1 )
   992 	if ( $post_id && $comment->comment_approved == 1 )
   855 }
  1000 }
   856 
  1001 
   857 /**
  1002 /**
   858  * Moves a comment to the Trash
  1003  * Moves a comment to the Trash
   859  *
  1004  *
       
  1005  * If trash is disabled, comment is permanently deleted.
       
  1006  *
   860  * @since 2.9.0
  1007  * @since 2.9.0
   861  * @uses do_action() on 'trash_comment' before trashing
  1008  * @uses do_action() on 'trash_comment' before trashing
   862  * @uses do_action() on 'trashed_comment' after trashing
  1009  * @uses do_action() on 'trashed_comment' after trashing
       
  1010  * @uses wp_delete_comment() if trash is disabled
   863  *
  1011  *
   864  * @param int $comment_id Comment ID.
  1012  * @param int $comment_id Comment ID.
   865  * @return mixed False on failure
  1013  * @return mixed False on failure
   866  */
  1014  */
   867 function wp_trash_comment($comment_id) {
  1015 function wp_trash_comment($comment_id) {
   868 	if ( EMPTY_TRASH_DAYS == 0 )
  1016 	if ( !EMPTY_TRASH_DAYS )
   869 		return wp_delete_comment($comment_id);
  1017 		return wp_delete_comment($comment_id, true);
   870 
  1018 
   871 	if ( !$comment = get_comment($comment_id) )
  1019 	if ( !$comment = get_comment($comment_id) )
   872 		return false;
  1020 		return false;
   873 
  1021 
   874 	do_action('trash_comment', $comment_id);
  1022 	do_action('trash_comment', $comment_id);
   980 	if ( !$comment )
  1128 	if ( !$comment )
   981 		return false;
  1129 		return false;
   982 
  1130 
   983 	$approved = $comment->comment_approved;
  1131 	$approved = $comment->comment_approved;
   984 
  1132 
   985 	if ( $approved == NULL )
  1133 	if ( $approved == null )
   986 		return false;
  1134 		return false;
   987 	elseif ( $approved == '1' )
  1135 	elseif ( $approved == '1' )
   988 		return 'approved';
  1136 		return 'approved';
   989 	elseif ( $approved == '0' )
  1137 	elseif ( $approved == '0' )
   990 		return 'unapproved';
  1138 		return 'unapproved';
  1029 	if ( isset($comment_statuses[$old_status]) ) $old_status = $comment_statuses[$old_status];
  1177 	if ( isset($comment_statuses[$old_status]) ) $old_status = $comment_statuses[$old_status];
  1030 
  1178 
  1031 	// Call the hooks
  1179 	// Call the hooks
  1032 	if ( $new_status != $old_status ) {
  1180 	if ( $new_status != $old_status ) {
  1033 		do_action('transition_comment_status', $new_status, $old_status, $comment);
  1181 		do_action('transition_comment_status', $new_status, $old_status, $comment);
  1034 		do_action("comment_${old_status}_to_$new_status", $comment);
  1182 		do_action("comment_{$old_status}_to_{$new_status}", $comment);
  1035 	}
  1183 	}
  1036 	do_action("comment_${new_status}_$comment->comment_type", $comment->comment_ID, $comment);
  1184 	do_action("comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment);
  1037 }
  1185 }
  1038 
  1186 
  1039 /**
  1187 /**
  1040  * Get current commenter's name, email, and URL.
  1188  * Get current commenter's name, email, and URL.
  1041  *
  1189  *
  1061 
  1209 
  1062 	$comment_author_url = '';
  1210 	$comment_author_url = '';
  1063 	if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) )
  1211 	if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) )
  1064 		$comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH];
  1212 		$comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH];
  1065 
  1213 
  1066 	return compact('comment_author', 'comment_author_email', 'comment_author_url');
  1214 	return apply_filters('wp_get_current_commenter', compact('comment_author', 'comment_author_email', 'comment_author_url'));
  1067 }
  1215 }
  1068 
  1216 
  1069 /**
  1217 /**
  1070  * Inserts a comment to the database.
  1218  * Inserts a comment to the database.
  1071  *
  1219  *
  1135 function wp_filter_comment($commentdata) {
  1283 function wp_filter_comment($commentdata) {
  1136 	if ( isset($commentdata['user_ID']) )
  1284 	if ( isset($commentdata['user_ID']) )
  1137 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_ID']);
  1285 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_ID']);
  1138 	elseif ( isset($commentdata['user_id']) )
  1286 	elseif ( isset($commentdata['user_id']) )
  1139 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_id']);
  1287 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_id']);
  1140 	$commentdata['comment_agent']        = apply_filters('pre_comment_user_agent', $commentdata['comment_agent']);
  1288 	$commentdata['comment_agent']        = apply_filters('pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) );
  1141 	$commentdata['comment_author']       = apply_filters('pre_comment_author_name', $commentdata['comment_author']);
  1289 	$commentdata['comment_author']       = apply_filters('pre_comment_author_name', $commentdata['comment_author']);
  1142 	$commentdata['comment_content']      = apply_filters('pre_comment_content', $commentdata['comment_content']);
  1290 	$commentdata['comment_content']      = apply_filters('pre_comment_content', $commentdata['comment_content']);
  1143 	$commentdata['comment_author_IP']    = apply_filters('pre_comment_user_ip', $commentdata['comment_author_IP']);
  1291 	$commentdata['comment_author_IP']    = apply_filters('pre_comment_user_ip', $commentdata['comment_author_IP']);
  1144 	$commentdata['comment_author_url']   = apply_filters('pre_comment_author_url', $commentdata['comment_author_url']);
  1292 	$commentdata['comment_author_url']   = apply_filters('pre_comment_author_url', $commentdata['comment_author_url']);
  1145 	$commentdata['comment_author_email'] = apply_filters('pre_comment_author_email', $commentdata['comment_author_email']);
  1293 	$commentdata['comment_author_email'] = apply_filters('pre_comment_author_email', $commentdata['comment_author_email']);
  1171  * Filters new comment to ensure that the fields are sanitized and valid before
  1319  * Filters new comment to ensure that the fields are sanitized and valid before
  1172  * inserting comment into database. Calls 'comment_post' action with comment ID
  1320  * inserting comment into database. Calls 'comment_post' action with comment ID
  1173  * and whether comment is approved by WordPress. Also has 'preprocess_comment'
  1321  * and whether comment is approved by WordPress. Also has 'preprocess_comment'
  1174  * filter for processing the comment data before the function handles it.
  1322  * filter for processing the comment data before the function handles it.
  1175  *
  1323  *
       
  1324  * We use REMOTE_ADDR here directly. If you are behind a proxy, you should ensure
       
  1325  * that it is properly set, such as in wp-config.php, for your environment.
       
  1326  * See {@link http://core.trac.wordpress.org/ticket/9235}
       
  1327  *
  1176  * @since 1.5.0
  1328  * @since 1.5.0
  1177  * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing
  1329  * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing
  1178  * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved.
  1330  * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved.
  1179  * @uses wp_filter_comment() Used to filter comment before adding comment.
  1331  * @uses wp_filter_comment() Used to filter comment before adding comment.
  1180  * @uses wp_allow_comment() checks to see if comment is approved.
  1332  * @uses wp_allow_comment() checks to see if comment is approved.
  1214 		if ( '0' == $commentdata['comment_approved'] )
  1366 		if ( '0' == $commentdata['comment_approved'] )
  1215 			wp_notify_moderator($comment_ID);
  1367 			wp_notify_moderator($comment_ID);
  1216 
  1368 
  1217 		$post = &get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment
  1369 		$post = &get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment
  1218 
  1370 
  1219 		if ( get_option('comments_notify') && $commentdata['comment_approved'] && $post->post_author != $commentdata['user_id'] )
  1371 		if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) )
  1220 			wp_notify_postauthor($comment_ID, $commentdata['comment_type']);
  1372 			wp_notify_postauthor($comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' );
  1221 	}
  1373 	}
  1222 
  1374 
  1223 	return $comment_ID;
  1375 	return $comment_ID;
  1224 }
  1376 }
  1225 
  1377 
  1226 /**
  1378 /**
  1227  * Sets the status of a comment.
  1379  * Sets the status of a comment.
  1228  *
  1380  *
  1229  * The 'wp_set_comment_status' action is called after the comment is handled and
  1381  * The 'wp_set_comment_status' action is called after the comment is handled.
  1230  * will only be called, if the comment status is either 'hold', 'approve', or
  1382  * If the comment status is not in the list, then false is returned.
  1231  * 'spam'. If the comment status is not in the list, then false is returned and
       
  1232  * if the status is 'delete', then the comment is deleted without calling the
       
  1233  * action.
       
  1234  *
  1383  *
  1235  * @since 1.0.0
  1384  * @since 1.0.0
  1236  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
  1385  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
  1237  *
  1386  *
  1238  * @param int $comment_id Comment ID.
  1387  * @param int $comment_id Comment ID.
  1239  * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'delete'.
  1388  * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.
  1240  * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false.
  1389  * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false.
  1241  * @return bool False on failure or deletion and true on success.
  1390  * @return bool False on failure or deletion and true on success.
  1242  */
  1391  */
  1243 function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) {
  1392 function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) {
  1244 	global $wpdb;
  1393 	global $wpdb;
  1265 			break;
  1414 			break;
  1266 		default:
  1415 		default:
  1267 			return false;
  1416 			return false;
  1268 	}
  1417 	}
  1269 
  1418 
  1270 	$comment_old = wp_clone(get_comment($comment_id));
  1419 	$comment_old = clone get_comment($comment_id);
  1271 
  1420 
  1272 	if ( !$wpdb->update( $wpdb->comments, array('comment_approved' => $status), array('comment_ID' => $comment_id) ) ) {
  1421 	if ( !$wpdb->update( $wpdb->comments, array('comment_approved' => $status), array('comment_ID' => $comment_id) ) ) {
  1273 		if ( $wp_error )
  1422 		if ( $wp_error )
  1274 			return new WP_Error('db_update_error', __('Could not update comment status'), $wpdb->last_error);
  1423 			return new WP_Error('db_update_error', __('Could not update comment status'), $wpdb->last_error);
  1275 		else
  1424 		else
  1329 		$comment_approved = 0;
  1478 		$comment_approved = 0;
  1330 	else if ( 'approve' == $comment_approved )
  1479 	else if ( 'approve' == $comment_approved )
  1331 		$comment_approved = 1;
  1480 		$comment_approved = 1;
  1332 
  1481 
  1333 	$data = compact('comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt');
  1482 	$data = compact('comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt');
  1334 	$wpdb->update($wpdb->comments, $data, compact('comment_ID'));
  1483 	$rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) );
  1335 
       
  1336 	$rval = $wpdb->rows_affected;
       
  1337 
  1484 
  1338 	clean_comment_cache($comment_ID);
  1485 	clean_comment_cache($comment_ID);
  1339 	wp_update_comment_count($comment_post_ID);
  1486 	wp_update_comment_count($comment_post_ID);
  1340 	do_action('edit_comment', $comment_ID);
  1487 	do_action('edit_comment', $comment_ID);
  1341 	$comment = get_comment($comment_ID);
  1488 	$comment = get_comment($comment_ID);
  1430 
  1577 
  1431 	$old = (int) $post->comment_count;
  1578 	$old = (int) $post->comment_count;
  1432 	$new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) );
  1579 	$new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) );
  1433 	$wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
  1580 	$wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
  1434 
  1581 
  1435 	if ( 'page' == $post->post_type )
  1582 	clean_post_cache( $post );
  1436 		clean_page_cache( $post_id );
       
  1437 	else
       
  1438 		clean_post_cache( $post_id );
       
  1439 
  1583 
  1440 	do_action('wp_update_comment_count', $post_id, $new, $old);
  1584 	do_action('wp_update_comment_count', $post_id, $new, $old);
  1441 	do_action('edit_post', $post_id, $post);
  1585 	do_action('edit_post', $post_id, $post);
  1442 
  1586 
  1443 	return true;
  1587 	return true;
  1458  *
  1602  *
  1459  * @param string $url URL to ping.
  1603  * @param string $url URL to ping.
  1460  * @param int $deprecated Not Used.
  1604  * @param int $deprecated Not Used.
  1461  * @return bool|string False on failure, string containing URI on success.
  1605  * @return bool|string False on failure, string containing URI on success.
  1462  */
  1606  */
  1463 function discover_pingback_server_uri($url, $deprecated = 2048) {
  1607 function discover_pingback_server_uri( $url, $deprecated = '' ) {
       
  1608 	if ( !empty( $deprecated ) )
       
  1609 		_deprecated_argument( __FUNCTION__, '2.7' );
  1464 
  1610 
  1465 	$pingback_str_dquote = 'rel="pingback"';
  1611 	$pingback_str_dquote = 'rel="pingback"';
  1466 	$pingback_str_squote = 'rel=\'pingback\'';
  1612 	$pingback_str_squote = 'rel=\'pingback\'';
  1467 
  1613 
  1468 	/** @todo Should use Filter Extension or custom preg_match instead. */
  1614 	/** @todo Should use Filter Extension or custom preg_match instead. */
  1479 	$response = wp_remote_head( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) );
  1625 	$response = wp_remote_head( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) );
  1480 
  1626 
  1481 	if ( is_wp_error( $response ) )
  1627 	if ( is_wp_error( $response ) )
  1482 		return false;
  1628 		return false;
  1483 
  1629 
  1484 	if ( isset( $response['headers']['x-pingback'] ) )
  1630 	if ( wp_remote_retrieve_header( $response, 'x-pingback' ) )
  1485 		return $response['headers']['x-pingback'];
  1631 		return wp_remote_retrieve_header( $response, 'x-pingback' );
  1486 
  1632 
  1487 	// Not an (x)html, sgml, or xml page, no use going further.
  1633 	// Not an (x)html, sgml, or xml page, no use going further.
  1488 	if ( isset( $response['headers']['content-type'] ) && preg_match('#(image|audio|video|model)/#is', $response['headers']['content-type']) )
  1634 	if ( preg_match('#(image|audio|video|model)/#is', wp_remote_retrieve_header( $response, 'content-type' )) )
  1489 		return false;
  1635 		return false;
  1490 
  1636 
  1491 	// Now do a GET since we're going to look in the html headers (and we're sure its not a binary file)
  1637 	// Now do a GET since we're going to look in the html headers (and we're sure its not a binary file)
  1492 	$response = wp_remote_get( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) );
  1638 	$response = wp_remote_get( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) );
  1493 
  1639 
  1494 	if ( is_wp_error( $response ) )
  1640 	if ( is_wp_error( $response ) )
  1495 		return false;
  1641 		return false;
  1496 
  1642 
  1497 	$contents = $response['body'];
  1643 	$contents = wp_remote_retrieve_body( $response );
  1498 
  1644 
  1499 	$pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote);
  1645 	$pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote);
  1500 	$pingback_link_offset_squote = strpos($contents, $pingback_str_squote);
  1646 	$pingback_link_offset_squote = strpos($contents, $pingback_str_squote);
  1501 	if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) {
  1647 	if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) {
  1502 		$quote = ($pingback_link_offset_dquote) ? '"' : '\'';
  1648 		$quote = ($pingback_link_offset_dquote) ? '"' : '\'';
  1524  */
  1670  */
  1525 function do_all_pings() {
  1671 function do_all_pings() {
  1526 	global $wpdb;
  1672 	global $wpdb;
  1527 
  1673 
  1528 	// Do pingbacks
  1674 	// Do pingbacks
  1529 	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")) {
  1675 	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")) {
  1530 		$mid = $wpdb->get_var( "SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = {$ping->ID} AND meta_key = '_pingme' LIMIT 1");
  1676 		delete_metadata_by_mid( 'post', $ping->meta_id );
  1531 		do_action( 'delete_postmeta', $mid );
  1677 		pingback( $ping->post_content, $ping->ID );
  1532 		$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_id = %d", $mid ) );
       
  1533 		do_action( 'deleted_postmeta', $mid );
       
  1534 		pingback($ping->post_content, $ping->ID);
       
  1535 	}
  1678 	}
  1536 
  1679 
  1537 	// Do Enclosures
  1680 	// Do Enclosures
  1538 	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")) {
  1681 	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")) {
  1539 		$mid = $wpdb->get_var( $wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_encloseme'", $enclosure->ID) );
  1682 		delete_metadata_by_mid( 'post', $enclosure->meta_id );
  1540 		do_action( 'delete_postmeta', $mid );
  1683 		do_enclose( $enclosure->post_content, $enclosure->ID );
  1541 		$wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_id =  %d", $mid) );
       
  1542 		do_action( 'deleted_postmeta', $mid );
       
  1543 		do_enclose($enclosure->post_content, $enclosure->ID);
       
  1544 	}
  1684 	}
  1545 
  1685 
  1546 	// Do Trackbacks
  1686 	// Do Trackbacks
  1547 	$trackbacks = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE to_ping <> '' AND post_status = 'publish'");
  1687 	$trackbacks = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE to_ping <> '' AND post_status = 'publish'");
  1548 	if ( is_array($trackbacks) )
  1688 	if ( is_array($trackbacks) )
  1577 	else
  1717 	else
  1578 		$excerpt = apply_filters('the_excerpt', $post->post_excerpt);
  1718 		$excerpt = apply_filters('the_excerpt', $post->post_excerpt);
  1579 	$excerpt = str_replace(']]>', ']]&gt;', $excerpt);
  1719 	$excerpt = str_replace(']]>', ']]&gt;', $excerpt);
  1580 	$excerpt = wp_html_excerpt($excerpt, 252) . '...';
  1720 	$excerpt = wp_html_excerpt($excerpt, 252) . '...';
  1581 
  1721 
  1582 	$post_title = apply_filters('the_title', $post->post_title);
  1722 	$post_title = apply_filters('the_title', $post->post_title, $post->ID);
  1583 	$post_title = strip_tags($post_title);
  1723 	$post_title = strip_tags($post_title);
  1584 
  1724 
  1585 	if ( $to_ping ) {
  1725 	if ( $to_ping ) {
  1586 		foreach ( (array) $to_ping as $tb_ping ) {
  1726 		foreach ( (array) $to_ping as $tb_ping ) {
  1587 			$tb_ping = trim($tb_ping);
  1727 			$tb_ping = trim($tb_ping);
  1588 			if ( !in_array($tb_ping, $pinged) ) {
  1728 			if ( !in_array($tb_ping, $pinged) ) {
  1589 				trackback($tb_ping, $post_title, $excerpt, $post_id);
  1729 				trackback($tb_ping, $post_title, $excerpt, $post_id);
  1590 				$pinged[] = $tb_ping;
  1730 				$pinged[] = $tb_ping;
  1591 			} else {
  1731 			} else {
  1592 				$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = %d", $post_id) );
  1732 				$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $tb_ping, $post_id) );
  1593 			}
  1733 			}
  1594 		}
  1734 		}
  1595 	}
  1735 	}
  1596 }
  1736 }
  1597 
  1737 
  1627  * @param int $post_ID Post ID.
  1767  * @param int $post_ID Post ID.
  1628  */
  1768  */
  1629 function pingback($content, $post_ID) {
  1769 function pingback($content, $post_ID) {
  1630 	global $wp_version;
  1770 	global $wp_version;
  1631 	include_once(ABSPATH . WPINC . '/class-IXR.php');
  1771 	include_once(ABSPATH . WPINC . '/class-IXR.php');
       
  1772 	include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php');
  1632 
  1773 
  1633 	// original code by Mort (http://mort.mine.nu:8080)
  1774 	// original code by Mort (http://mort.mine.nu:8080)
  1634 	$post_links = array();
  1775 	$post_links = array();
  1635 
  1776 
  1636 	$pung = get_pung($post_ID);
  1777 	$pung = get_pung($post_ID);
  1660 		if ( !in_array($link_test, $pung) && (url_to_postid($link_test) != $post_ID) // If we haven't pung it already and it isn't a link to itself
  1801 		if ( !in_array($link_test, $pung) && (url_to_postid($link_test) != $post_ID) // If we haven't pung it already and it isn't a link to itself
  1661 				&& !is_local_attachment($link_test) ) : // Also, let's never ping local attachments.
  1802 				&& !is_local_attachment($link_test) ) : // Also, let's never ping local attachments.
  1662 			if ( $test = @parse_url($link_test) ) {
  1803 			if ( $test = @parse_url($link_test) ) {
  1663 				if ( isset($test['query']) )
  1804 				if ( isset($test['query']) )
  1664 					$post_links[] = $link_test;
  1805 					$post_links[] = $link_test;
  1665 				elseif ( ($test['path'] != '/') && ($test['path'] != '') )
  1806 				elseif ( isset( $test['path'] ) && ( $test['path'] != '/' ) && ( $test['path'] != '' ) )
  1666 					$post_links[] = $link_test;
  1807 					$post_links[] = $link_test;
  1667 			}
  1808 			}
  1668 		endif;
  1809 		endif;
  1669 	endforeach;
  1810 	endforeach;
  1670 
  1811 
  1671 	do_action_ref_array('pre_ping', array(&$post_links, &$pung));
  1812 	do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post_ID ) );
  1672 
  1813 
  1673 	foreach ( (array) $post_links as $pagelinkedto ) {
  1814 	foreach ( (array) $post_links as $pagelinkedto ) {
  1674 		$pingback_server_url = discover_pingback_server_uri($pagelinkedto, 2048);
  1815 		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
  1675 
  1816 
  1676 		if ( $pingback_server_url ) {
  1817 		if ( $pingback_server_url ) {
  1677 			@ set_time_limit( 60 );
  1818 			@ set_time_limit( 60 );
  1678 			 // Now, the RPC call
  1819 			 // Now, the RPC call
  1679 			$pagelinkedfrom = get_permalink($post_ID);
  1820 			$pagelinkedfrom = get_permalink($post_ID);
  1680 
  1821 
  1681 			// using a timeout of 3 seconds should be enough to cover slow servers
  1822 			// using a timeout of 3 seconds should be enough to cover slow servers
  1682 			$client = new IXR_Client($pingback_server_url);
  1823 			$client = new WP_HTTP_IXR_Client($pingback_server_url);
  1683 			$client->timeout = 3;
  1824 			$client->timeout = 3;
  1684 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom);
  1825 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom);
  1685 			// when set to true, this outputs debug messages by itself
  1826 			// when set to true, this outputs debug messages by itself
  1686 			$client->debug = false;
  1827 			$client->debug = false;
  1687 
  1828 
  1738 	$response = wp_remote_post($trackback_url, $options);
  1879 	$response = wp_remote_post($trackback_url, $options);
  1739 
  1880 
  1740 	if ( is_wp_error( $response ) )
  1881 	if ( is_wp_error( $response ) )
  1741 		return;
  1882 		return;
  1742 
  1883 
  1743 	$tb_url = addslashes( $trackback_url );
  1884 	$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', %s) WHERE ID = %d", $trackback_url, $ID) );
  1744 	$wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', '$tb_url') WHERE ID = %d", $ID) );
  1885 	return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $trackback_url, $ID) );
  1745 	return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_url', '')) WHERE ID = %d", $ID) );
       
  1746 }
  1886 }
  1747 
  1887 
  1748 /**
  1888 /**
  1749  * Send a pingback.
  1889  * Send a pingback.
  1750  *
  1890  *
  1756  * @param string $path Path to send the ping.
  1896  * @param string $path Path to send the ping.
  1757  */
  1897  */
  1758 function weblog_ping($server = '', $path = '') {
  1898 function weblog_ping($server = '', $path = '') {
  1759 	global $wp_version;
  1899 	global $wp_version;
  1760 	include_once(ABSPATH . WPINC . '/class-IXR.php');
  1900 	include_once(ABSPATH . WPINC . '/class-IXR.php');
       
  1901 	include_once(ABSPATH . WPINC . '/class-wp-http-ixr-client.php');
  1761 
  1902 
  1762 	// using a timeout of 3 seconds should be enough to cover slow servers
  1903 	// using a timeout of 3 seconds should be enough to cover slow servers
  1763 	$client = new IXR_Client($server, ((!strlen(trim($path)) || ('/' == $path)) ? false : $path));
  1904 	$client = new WP_HTTP_IXR_Client($server, ((!strlen(trim($path)) || ('/' == $path)) ? false : $path));
  1764 	$client->timeout = 3;
  1905 	$client->timeout = 3;
  1765 	$client->useragent .= ' -- WordPress/'.$wp_version;
  1906 	$client->useragent .= ' -- WordPress/'.$wp_version;
  1766 
  1907 
  1767 	// when set to true, this outputs debug messages by itself
  1908 	// when set to true, this outputs debug messages by itself
  1768 	$client->debug = false;
  1909 	$client->debug = false;
  1769 	$home = trailingslashit( get_option('home') );
  1910 	$home = trailingslashit( home_url() );
  1770 	if ( !$client->query('weblogUpdates.extendedPing', get_option('blogname'), $home, get_bloginfo('rss2_url') ) ) // then try a normal ping
  1911 	if ( !$client->query('weblogUpdates.extendedPing', get_option('blogname'), $home, get_bloginfo('rss2_url') ) ) // then try a normal ping
  1771 		$client->query('weblogUpdates.ping', get_option('blogname'), $home);
  1912 		$client->query('weblogUpdates.ping', get_option('blogname'), $home);
  1772 }
  1913 }
  1773 
  1914 
  1774 //
  1915 //
  1780  *
  1921  *
  1781  * @since 2.3.0
  1922  * @since 2.3.0
  1782  * @package WordPress
  1923  * @package WordPress
  1783  * @subpackage Cache
  1924  * @subpackage Cache
  1784  *
  1925  *
  1785  * @param int|array $id Comment ID or array of comment IDs to remove from cache
  1926  * @param int|array $ids Comment ID or array of comment IDs to remove from cache
  1786  */
  1927  */
  1787 function clean_comment_cache($ids) {
  1928 function clean_comment_cache($ids) {
  1788 	foreach ( (array) $ids as $id )
  1929 	foreach ( (array) $ids as $id )
  1789 		wp_cache_delete($id, 'comment');
  1930 		wp_cache_delete($id, 'comment');
       
  1931 
       
  1932 	wp_cache_set('last_changed', time(), 'comment');
  1790 }
  1933 }
  1791 
  1934 
  1792 /**
  1935 /**
  1793  * Updates the comment cache of given comments.
  1936  * Updates the comment cache of given comments.
  1794  *
  1937  *
  1810 //
  1953 //
  1811 // Internal
  1954 // Internal
  1812 //
  1955 //
  1813 
  1956 
  1814 /**
  1957 /**
  1815  * Close comments on old posts on the fly, without any extra DB queries.  Hooked to the_posts.
  1958  * Close comments on old posts on the fly, without any extra DB queries. Hooked to the_posts.
  1816  *
  1959  *
  1817  * @access private
  1960  * @access private
  1818  * @since 2.7.0
  1961  * @since 2.7.0
  1819  *
  1962  *
  1820  * @param object $posts Post data object.
  1963  * @param object $posts Post data object.
       
  1964  * @param object $query Query object.
  1821  * @return object
  1965  * @return object
  1822  */
  1966  */
  1823 function _close_comments_for_old_posts( $posts ) {
  1967 function _close_comments_for_old_posts( $posts, $query ) {
  1824 	if ( empty($posts) || !is_singular() || !get_option('close_comments_for_old_posts') )
  1968 	if ( empty( $posts ) || ! $query->is_singular() || ! get_option( 'close_comments_for_old_posts' ) )
  1825 		return $posts;
  1969 		return $posts;
  1826 
  1970 
  1827 	$days_old = (int) get_option('close_comments_days_old');
  1971 	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
  1828 	if ( !$days_old )
  1972 	if ( ! in_array( $posts[0]->post_type, $post_types ) )
       
  1973 		return $posts;
       
  1974 
       
  1975 	$days_old = (int) get_option( 'close_comments_days_old' );
       
  1976 	if ( ! $days_old )
  1829 		return $posts;
  1977 		return $posts;
  1830 
  1978 
  1831 	if ( time() - strtotime( $posts[0]->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) ) {
  1979 	if ( time() - strtotime( $posts[0]->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) ) {
  1832 		$posts[0]->comment_status = 'closed';
  1980 		$posts[0]->comment_status = 'closed';
  1833 		$posts[0]->ping_status = 'closed';
  1981 		$posts[0]->ping_status = 'closed';
  1835 
  1983 
  1836 	return $posts;
  1984 	return $posts;
  1837 }
  1985 }
  1838 
  1986 
  1839 /**
  1987 /**
  1840  * Close comments on an old post.  Hooked to comments_open and pings_open.
  1988  * Close comments on an old post. Hooked to comments_open and pings_open.
  1841  *
  1989  *
  1842  * @access private
  1990  * @access private
  1843  * @since 2.7.0
  1991  * @since 2.7.0
  1844  *
  1992  *
  1845  * @param bool $open Comments open or closed
  1993  * @param bool $open Comments open or closed
  1857 	if ( !$days_old )
  2005 	if ( !$days_old )
  1858 		return $open;
  2006 		return $open;
  1859 
  2007 
  1860 	$post = get_post($post_id);
  2008 	$post = get_post($post_id);
  1861 
  2009 
       
  2010 	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
       
  2011 	if ( ! in_array( $post->post_type, $post_types ) )
       
  2012 		return $open;
       
  2013 
  1862 	if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) )
  2014 	if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) )
  1863 		return false;
  2015 		return false;
  1864 
  2016 
  1865 	return $open;
  2017 	return $open;
  1866 }
  2018 }
  1867 
       
  1868 ?>