wp/wp-includes/comment.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     5  * @package WordPress
     5  * @package WordPress
     6  * @subpackage Comment
     6  * @subpackage Comment
     7  */
     7  */
     8 
     8 
     9 /**
     9 /**
    10  * Checks whether a comment passes internal checks to be allowed to add.
    10  * Check whether a comment passes internal checks to be allowed to add.
    11  *
    11  *
    12  * If comment moderation is set in the administration, then all comments,
    12  * If manual comment moderation is set in the administration, then all checks,
    13  * regardless of their type and whitelist will be set to false. If the number of
    13  * regardless of their type and whitelist, will fail and the function will
    14  * links exceeds the amount in the administration, then the check fails. If any
    14  * return false.
    15  * of the parameter contents match the blacklist of words, then the check fails.
       
    16  *
    15  *
    17  * If the number of links exceeds the amount in the administration, then the
    16  * 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,
    17  * check fails. If any of the parameter contents match the blacklist of words,
    19  * then the check fails.
    18  * then the check fails.
    20  *
    19  *
    21  * If the comment author was approved before, then the comment is
    20  * If the comment author was approved before, then the comment is automatically
    22  * automatically whitelisted.
    21  * whitelisted.
    23  *
    22  *
    24  * If none of the checks fail, then the failback is to set the check to pass
    23  * If all checks pass, the function will return true.
    25  * (return true).
       
    26  *
    24  *
    27  * @since 1.2.0
    25  * @since 1.2.0
    28  * @uses $wpdb
    26  *
    29  *
    27  * @global wpdb $wpdb WordPress database abstraction object.
    30  * @param string $author Comment Author's name
    28  *
    31  * @param string $email Comment Author's email
    29  * @param string $author       Comment author name.
    32  * @param string $url Comment Author's URL
    30  * @param string $email        Comment author email.
    33  * @param string $comment Comment contents
    31  * @param string $url          Comment author URL.
    34  * @param string $user_ip Comment Author's IP address
    32  * @param string $comment      Content of the comment.
    35  * @param string $user_agent Comment Author's User Agent
    33  * @param string $user_ip      Comment author IP address.
    36  * @param string $comment_type Comment type, either user submitted comment,
    34  * @param string $user_agent   Comment author User-Agent.
    37  *		trackback, or pingback
    35  * @param string $comment_type Comment type, either user-submitted comment,
    38  * @return bool Whether the checks passed (true) and the comments should be
    36  *		                       trackback, or pingback.
    39  *		displayed or set to moderated
    37  * @return bool If all checks pass, true, otherwise false.
    40  */
    38  */
    41 function check_comment($author, $email, $url, $comment, $user_ip, $user_agent, $comment_type) {
    39 function check_comment($author, $email, $url, $comment, $user_ip, $user_agent, $comment_type) {
    42 	global $wpdb;
    40 	global $wpdb;
    43 
    41 
       
    42 	// If manual moderation is enabled, skip all checks and return false.
    44 	if ( 1 == get_option('comment_moderation') )
    43 	if ( 1 == get_option('comment_moderation') )
    45 		return false; // If moderation is set to manual
    44 		return false;
    46 
    45 
       
    46 	/** This filter is documented in wp-includes/comment-template.php */
    47 	$comment = apply_filters( 'comment_text', $comment );
    47 	$comment = apply_filters( 'comment_text', $comment );
    48 
    48 
    49 	// Check # of external links
    49 	// Check for the number of external links if a max allowed number is set.
    50 	if ( $max_links = get_option( 'comment_max_links' ) ) {
    50 	if ( $max_links = get_option( 'comment_max_links' ) ) {
    51 		$num_links = preg_match_all( '/<a [^>]*href/i', $comment, $out );
    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
    52 
       
    53 		/**
       
    54 		 * Filter the maximum number of links allowed in a comment.
       
    55 		 *
       
    56 		 * @since 3.0.0
       
    57 		 *
       
    58 		 * @param int    $num_links The number of links allowed.
       
    59 		 * @param string $url       Comment author's URL. Included in allowed links total.
       
    60 		 */
       
    61 		$num_links = apply_filters( 'comment_max_links_url', $num_links, $url );
       
    62 
       
    63 		/*
       
    64 		 * If the number of links in the comment exceeds the allowed amount,
       
    65 		 * fail the check by returning false.
       
    66 		 */
    53 		if ( $num_links >= $max_links )
    67 		if ( $num_links >= $max_links )
    54 			return false;
    68 			return false;
    55 	}
    69 	}
    56 
    70 
    57 	$mod_keys = trim(get_option('moderation_keys'));
    71 	$mod_keys = trim(get_option('moderation_keys'));
       
    72 
       
    73 	// If moderation 'keys' (keywords) are set, process them.
    58 	if ( !empty($mod_keys) ) {
    74 	if ( !empty($mod_keys) ) {
    59 		$words = explode("\n", $mod_keys );
    75 		$words = explode("\n", $mod_keys );
    60 
    76 
    61 		foreach ( (array) $words as $word) {
    77 		foreach ( (array) $words as $word) {
    62 			$word = trim($word);
    78 			$word = trim($word);
    63 
    79 
    64 			// Skip empty lines
    80 			// Skip empty lines.
    65 			if ( empty($word) )
    81 			if ( empty($word) )
    66 				continue;
    82 				continue;
    67 
    83 
    68 			// Do some escaping magic so that '#' chars in the
    84 			/*
    69 			// spam words don't break things:
    85 			 * Do some escaping magic so that '#' (number of) characters in the spam
       
    86 			 * words don't break things:
       
    87 			 */
    70 			$word = preg_quote($word, '#');
    88 			$word = preg_quote($word, '#');
    71 
    89 
       
    90 			/*
       
    91 			 * Check the comment fields for moderation keywords. If any are found,
       
    92 			 * fail the check for the given field by returning false.
       
    93 			 */
    72 			$pattern = "#$word#i";
    94 			$pattern = "#$word#i";
    73 			if ( preg_match($pattern, $author) ) return false;
    95 			if ( preg_match($pattern, $author) ) return false;
    74 			if ( preg_match($pattern, $email) ) return false;
    96 			if ( preg_match($pattern, $email) ) return false;
    75 			if ( preg_match($pattern, $url) ) return false;
    97 			if ( preg_match($pattern, $url) ) return false;
    76 			if ( preg_match($pattern, $comment) ) return false;
    98 			if ( preg_match($pattern, $comment) ) return false;
    77 			if ( preg_match($pattern, $user_ip) ) return false;
    99 			if ( preg_match($pattern, $user_ip) ) return false;
    78 			if ( preg_match($pattern, $user_agent) ) return false;
   100 			if ( preg_match($pattern, $user_agent) ) return false;
    79 		}
   101 		}
    80 	}
   102 	}
    81 
   103 
    82 	// Comment whitelisting:
   104 	/*
       
   105 	 * Check if the option to approve comments by previously-approved authors is enabled.
       
   106 	 *
       
   107 	 * If it is enabled, check whether the comment author has a previously-approved comment,
       
   108 	 * as well as whether there are any moderation keywords (if set) present in the author
       
   109 	 * email address. If both checks pass, return true. Otherwise, return false.
       
   110 	 */
    83 	if ( 1 == get_option('comment_whitelist')) {
   111 	if ( 1 == get_option('comment_whitelist')) {
    84 		if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) {
   112 		if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) {
    85 			// expected_slashed ($author, $email)
   113 			// expected_slashed ($author, $email)
    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");
   114 			$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");
    87 			if ( ( 1 == $ok_to_comment ) &&
   115 			if ( ( 1 == $ok_to_comment ) &&
    98 
   126 
    99 /**
   127 /**
   100  * Retrieve the approved comments for post $post_id.
   128  * Retrieve the approved comments for post $post_id.
   101  *
   129  *
   102  * @since 2.0.0
   130  * @since 2.0.0
   103  * @uses $wpdb
   131  * @since 4.1.0 Refactored to leverage {@see WP_Comment_Query} over a direct query.
   104  *
   132  *
   105  * @param int $post_id The ID of the post
   133  * @param  int   $post_id The ID of the post.
   106  * @return array $comments The approved comments
   134  * @param  array $args    Optional. See {@see WP_Comment_Query::query()} for information
   107  */
   135  *                        on accepted arguments.
   108 function get_approved_comments($post_id) {
   136  * @return int|array $comments The approved comments, or number of comments if `$count`
   109 	global $wpdb;
   137  *                             argument is true.
   110 	return $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1' ORDER BY comment_date", $post_id));
   138  */
       
   139 function get_approved_comments( $post_id, $args = array() ) {
       
   140 	if ( ! $post_id ) {
       
   141 		return array();
       
   142 	}
       
   143 
       
   144 	$defaults = array(
       
   145 		'status'  => 1,
       
   146 		'post_id' => $post_id,
       
   147 		'order'   => 'ASC',
       
   148 	);
       
   149 	$r = wp_parse_args( $args, $defaults );
       
   150 
       
   151 	$query = new WP_Comment_Query;
       
   152 	return $query->query( $r );
   111 }
   153 }
   112 
   154 
   113 /**
   155 /**
   114  * Retrieves comment data given a comment ID or comment object.
   156  * Retrieves comment data given a comment ID or comment object.
   115  *
   157  *
   116  * If an object is passed then the comment data will be cached and then returned
   158  * If an object is passed then the comment data will be cached and then returned
   117  * after being passed through a filter. If the comment is empty, then the global
   159  * after being passed through a filter. If the comment is empty, then the global
   118  * comment variable will be used, if it is set.
   160  * comment variable will be used, if it is set.
   119  *
   161  *
   120  * @since 2.0.0
   162  * @since 2.0.0
   121  * @uses $wpdb
   163  *
       
   164  * @global wpdb $wpdb WordPress database abstraction object.
   122  *
   165  *
   123  * @param object|string|int $comment Comment to retrieve.
   166  * @param object|string|int $comment Comment to retrieve.
   124  * @param string $output Optional. OBJECT or ARRAY_A or ARRAY_N constants.
   167  * @param string $output Optional. OBJECT or ARRAY_A or ARRAY_N constants.
   125  * @return object|array|null Depends on $output value.
   168  * @return object|array|null Depends on $output value.
   126  */
   169  */
   127 function get_comment(&$comment, $output = OBJECT) {
   170 function get_comment(&$comment, $output = OBJECT) {
   128 	global $wpdb;
   171 	global $wpdb;
   129 	$null = null;
       
   130 
   172 
   131 	if ( empty($comment) ) {
   173 	if ( empty($comment) ) {
   132 		if ( isset($GLOBALS['comment']) )
   174 		if ( isset($GLOBALS['comment']) )
   133 			$_comment = & $GLOBALS['comment'];
   175 			$_comment = & $GLOBALS['comment'];
   134 		else
   176 		else
   140 		if ( isset($GLOBALS['comment']) && ($GLOBALS['comment']->comment_ID == $comment) ) {
   182 		if ( isset($GLOBALS['comment']) && ($GLOBALS['comment']->comment_ID == $comment) ) {
   141 			$_comment = & $GLOBALS['comment'];
   183 			$_comment = & $GLOBALS['comment'];
   142 		} elseif ( ! $_comment = wp_cache_get($comment, 'comment') ) {
   184 		} elseif ( ! $_comment = wp_cache_get($comment, 'comment') ) {
   143 			$_comment = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment));
   185 			$_comment = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment));
   144 			if ( ! $_comment )
   186 			if ( ! $_comment )
   145 				return $null;
   187 				return null;
   146 			wp_cache_add($_comment->comment_ID, $_comment, 'comment');
   188 			wp_cache_add($_comment->comment_ID, $_comment, 'comment');
   147 		}
   189 		}
   148 	}
   190 	}
   149 
   191 
   150 	$_comment = apply_filters('get_comment', $_comment);
   192 	/**
       
   193 	 * Fires after a comment is retrieved.
       
   194 	 *
       
   195 	 * @since 2.3.0
       
   196 	 *
       
   197 	 * @param mixed $_comment Comment data.
       
   198 	 */
       
   199 	$_comment = apply_filters( 'get_comment', $_comment );
   151 
   200 
   152 	if ( $output == OBJECT ) {
   201 	if ( $output == OBJECT ) {
   153 		return $_comment;
   202 		return $_comment;
   154 	} elseif ( $output == ARRAY_A ) {
   203 	} elseif ( $output == ARRAY_A ) {
   155 		$__comment = get_object_vars($_comment);
   204 		$__comment = get_object_vars($_comment);
   165 /**
   214 /**
   166  * Retrieve a list of comments.
   215  * Retrieve a list of comments.
   167  *
   216  *
   168  * The comment list can be for the blog as a whole or for an individual post.
   217  * The comment list can be for the blog as a whole or for an individual post.
   169  *
   218  *
   170  * The list of comment arguments are 'status', 'orderby', 'comment_date_gmt',
       
   171  * 'order', 'number', 'offset', and 'post_id'.
       
   172  *
       
   173  * @since 2.7.0
   219  * @since 2.7.0
   174  * @uses $wpdb
   220  *
   175  *
   221  * @param string|array $args Optional. Array or string of arguments. See {@see WP_Comment_Query::parse_query()}
   176  * @param mixed $args Optional. Array or string of options to override defaults.
   222  *                           for information on accepted arguments. Default empty.
   177  * @return array List of comments.
   223  * @return int|array List of comments or number of found comments if `$count` argument is true.
   178  */
   224  */
   179 function get_comments( $args = '' ) {
   225 function get_comments( $args = '' ) {
   180 	$query = new WP_Comment_Query;
   226 	$query = new WP_Comment_Query;
   181 	return $query->query( $args );
   227 	return $query->query( $args );
   182 }
   228 }
   183 
   229 
   184 /**
   230 /**
   185  * WordPress Comment Query class.
   231  * WordPress Comment Query class.
   186  *
   232  *
       
   233  * See WP_Comment_Query::__construct() for accepted arguments.
       
   234  *
   187  * @since 3.1.0
   235  * @since 3.1.0
   188  */
   236  */
   189 class WP_Comment_Query {
   237 class WP_Comment_Query {
       
   238 	/**
       
   239 	 * SQL for database query.
       
   240 	 *
       
   241 	 * @since 4.0.1
       
   242 	 * @access public
       
   243 	 * @var string
       
   244 	 */
       
   245 	public $request;
       
   246 
   190 	/**
   247 	/**
   191 	 * Metadata query container
   248 	 * Metadata query container
   192 	 *
   249 	 *
   193 	 * @since 3.5.0
   250 	 * @since 3.5.0
   194 	 * @access public
   251 	 * @access public
   195 	 * @var object WP_Meta_Query
   252 	 * @var object WP_Meta_Query
   196 	 */
   253 	 */
   197 	var $meta_query = false;
   254 	public $meta_query = false;
   198 
   255 
   199 	/**
   256 	/**
   200 	 * Date query container
   257 	 * Date query container
   201 	 *
   258 	 *
   202 	 * @since 3.7.0
   259 	 * @since 3.7.0
   203 	 * @access public
   260 	 * @access public
   204 	 * @var object WP_Date_Query
   261 	 * @var object WP_Date_Query
   205 	 */
   262 	 */
   206 	var $date_query = false;
   263 	public $date_query = false;
   207 
   264 
   208 	/**
   265 	/**
   209 	 * Execute the query
   266 	 * Query vars set by the user.
   210 	 *
   267 	 *
   211 	 * @since 3.1.0
   268 	 * @since 3.1.0
   212 	 *
   269 	 * @access public
   213 	 * @param string|array $query_vars
   270 	 * @var array
   214 	 * @return int|array
   271 	 */
   215 	 */
   272 	public $query_vars;
   216 	function query( $query_vars ) {
   273 
   217 		global $wpdb;
   274 	/**
   218 
   275 	 * Default values for query vars.
   219 		$defaults = array(
   276 	 *
       
   277 	 * @since 4.2.0
       
   278 	 * @access public
       
   279 	 * @var array
       
   280 	 */
       
   281 	public $query_var_defaults;
       
   282 
       
   283 	/**
       
   284 	 * List of comments located by the query.
       
   285 	 *
       
   286 	 * @since 4.0.0
       
   287 	 * @access public
       
   288 	 * @var array
       
   289 	 */
       
   290 	public $comments;
       
   291 
       
   292 	/**
       
   293 	 * Make private/protected methods readable for backwards compatibility.
       
   294 	 *
       
   295 	 * @since 4.0.0
       
   296 	 * @access public
       
   297 	 *
       
   298 	 * @param callable $name      Method to call.
       
   299 	 * @param array    $arguments Arguments to pass when calling.
       
   300 	 * @return mixed|bool Return value of the callback, false otherwise.
       
   301 	 */
       
   302 	public function __call( $name, $arguments ) {
       
   303 		if ( 'get_search_sql' === $name ) {
       
   304 			return call_user_func_array( array( $this, $name ), $arguments );
       
   305 		}
       
   306 		return false;
       
   307 	}
       
   308 
       
   309 	/**
       
   310 	 * Constructor.
       
   311 	 *
       
   312 	 * Sets up the comment query, based on the query vars passed.
       
   313 	 *
       
   314 	 * @since  4.2.0
       
   315 	 * @access public
       
   316 	 *
       
   317 	 * @param string|array $query {
       
   318 	 *     Optional. Array or query string of comment query parameters. Default empty.
       
   319 	 *
       
   320 	 *     @type string       $author_email        Comment author email address. Default empty.
       
   321 	 *     @type array        $author__in          Array of author IDs to include comments for. Default empty.
       
   322 	 *     @type array        $author__not_in      Array of author IDs to exclude comments for. Default empty.
       
   323 	 *     @type array        $comment__in         Array of comment IDs to include. Default empty.
       
   324 	 *     @type array        $comment__not_in     Array of comment IDs to exclude. Default empty.
       
   325 	 *     @type bool         $count               Whether to return a comment count (true) or array of comment
       
   326 	 *                                             objects (false). Default false.
       
   327 	 *     @type array        $date_query          Date query clauses to limit comments by. See WP_Date_Query.
       
   328 	 *                                             Default null.
       
   329 	 *     @type string       $fields              Comment fields to return. Accepts 'ids' for comment IDs only or
       
   330 	 *                                             empty for all fields. Default empty.
       
   331 	 *     @type int          $ID                  Currently unused.
       
   332 	 *     @type array        $include_unapproved  Array of IDs or email addresses of users whose unapproved comments
       
   333 	 *                                             will be returned by the query regardless of `$status`. Default empty.
       
   334 	 *     @type int          $karma               Karma score to retrieve matching comments for. Default empty.
       
   335 	 *     @type string       $meta_key            Include comments with a matching comment meta key. Default empty.
       
   336 	 *     @type string       $meta_value          Include comments with a matching comment meta value. Requires
       
   337 	 *                                             `$meta_key` to be set. Default empty.
       
   338 	 *     @type array        $meta_query          Meta query clauses to limit retrieved comments by.
       
   339 	 *                                             See WP_Meta_Query. Default empty.
       
   340 	 *     @type int          $number              Maximum number of comments to retrieve. Default null (no limit).
       
   341 	 *     @type int          $offset              Number of comments to offset the query. Used to build LIMIT clause.
       
   342 	 *                                             Default 0.
       
   343 	 *     @type string|array $orderby             Comment status or array of statuses. To use 'meta_value' or
       
   344 	 *                                             'meta_value_num', `$meta_key` must also be defined. To sort by
       
   345 	 *                                             a specific `$meta_query` clause, use that clause's array key.
       
   346 	 *                                             Accepts 'comment_agent', 'comment_approved', 'comment_author',
       
   347 	 *                                             'comment_author_email', 'comment_author_IP',
       
   348 	 *                                             'comment_author_url', 'comment_content', 'comment_date',
       
   349 	 *                                             'comment_date_gmt', 'comment_ID', 'comment_karma',
       
   350 	 *                                             'comment_parent', 'comment_post_ID', 'comment_type', 'user_id',
       
   351 	 *                                             'meta_value', 'meta_value_num', the value of $meta_key, and the
       
   352 	 *                                             array keys of `$meta_query`. Also accepts false, an empty array,
       
   353 	 *                                             or 'none' to disable `ORDER BY` clause.
       
   354 	 *                                             Default: 'comment_date_gmt'.
       
   355 	 *     @type string       $order               How to order retrieved comments. Accepts 'ASC', 'DESC'.
       
   356 	 *                                             Default: 'DESC'.
       
   357 	 *     @type int          $parent              Parent ID of comment to retrieve children of. Default empty.
       
   358 	 *     @type array        $post_author__in     Array of author IDs to retrieve comments for. Default empty.
       
   359 	 *     @type array        $post_author__not_in Array of author IDs *not* to retrieve comments for. Default empty.
       
   360 	 *     @type int          $post_ID             Currently unused.
       
   361 	 *     @type int          $post_id             Limit results to those affiliated with a given post ID. Default 0.
       
   362 	 *     @type array        $post__in            Array of post IDs to include affiliated comments for. Default empty.
       
   363 	 *     @type array        $post__not_in        Array of post IDs to exclude affiliated comments for. Default empty.
       
   364 	 *     @type int          $post_author         Comment author ID to limit results by. Default empty.
       
   365 	 *     @type string       $post_status         Post status to retrieve affiliated comments for. Default empty.
       
   366 	 *     @type string       $post_type           Post type to retrieve affiliated comments for. Default empty.
       
   367 	 *     @type string       $post_name           Post name to retrieve affiliated comments for. Default empty.
       
   368 	 *     @type int          $post_parent         Post parent ID to retrieve affiliated comments for. Default empty.
       
   369 	 *     @type string       $search              Search term(s) to retrieve matching comments for. Default empty.
       
   370 	 *     @type string       $status              Comment status to limit results by. Accepts 'hold'
       
   371 	 *                                             (`comment_status=0`), 'approve' (`comment_status=1`), 'all', or a
       
   372 	 *                                             custom comment status. Default 'all'.
       
   373 	 *     @type string|array $type                Include comments of a given type, or array of types. Accepts
       
   374 	 *                                             'comment', 'pings' (includes 'pingback' and 'trackback'), or any
       
   375 	 *                                             custom type string. Default empty.
       
   376 	 *     @type array        $type__in            Include comments from a given array of comment types. Default empty.
       
   377 	 *     @type array        $type__not_in        Exclude comments from a given array of comment types. Default empty.
       
   378 	 *     @type int          $user_id             Include comments for a specific user ID. Default empty.
       
   379 	 * }
       
   380 	 * @return WP_Comment_Query WP_Comment_Query instance.
       
   381 	 */
       
   382 	public function __construct( $query = '' ) {
       
   383 		$this->query_var_defaults = array(
   220 			'author_email' => '',
   384 			'author_email' => '',
       
   385 			'author__in' => '',
       
   386 			'author__not_in' => '',
       
   387 			'include_unapproved' => '',
       
   388 			'fields' => '',
   221 			'ID' => '',
   389 			'ID' => '',
       
   390 			'comment__in' => '',
       
   391 			'comment__not_in' => '',
   222 			'karma' => '',
   392 			'karma' => '',
   223 			'number' => '',
   393 			'number' => '',
   224 			'offset' => '',
   394 			'offset' => '',
   225 			'orderby' => '',
   395 			'orderby' => '',
   226 			'order' => 'DESC',
   396 			'order' => 'DESC',
   227 			'parent' => '',
   397 			'parent' => '',
       
   398 			'post_author__in' => '',
       
   399 			'post_author__not_in' => '',
   228 			'post_ID' => '',
   400 			'post_ID' => '',
   229 			'post_id' => 0,
   401 			'post_id' => 0,
       
   402 			'post__in' => '',
       
   403 			'post__not_in' => '',
   230 			'post_author' => '',
   404 			'post_author' => '',
   231 			'post_name' => '',
   405 			'post_name' => '',
   232 			'post_parent' => '',
   406 			'post_parent' => '',
   233 			'post_status' => '',
   407 			'post_status' => '',
   234 			'post_type' => '',
   408 			'post_type' => '',
   235 			'status' => '',
   409 			'status' => 'all',
   236 			'type' => '',
   410 			'type' => '',
       
   411 			'type__in' => '',
       
   412 			'type__not_in' => '',
   237 			'user_id' => '',
   413 			'user_id' => '',
   238 			'search' => '',
   414 			'search' => '',
   239 			'count' => false,
   415 			'count' => false,
   240 			'meta_key' => '',
   416 			'meta_key' => '',
   241 			'meta_value' => '',
   417 			'meta_value' => '',
   242 			'meta_query' => '',
   418 			'meta_query' => '',
   243 			'date_query' => null, // See WP_Date_Query
   419 			'date_query' => null, // See WP_Date_Query
   244 		);
   420 		);
   245 
   421 
       
   422 		if ( ! empty( $query ) ) {
       
   423 			$this->query( $query );
       
   424 		}
       
   425 	}
       
   426 
       
   427 	/**
       
   428 	 * Parse arguments passed to the comment query with default query parameters.
       
   429 	 *
       
   430 	 * @since  4.2.0 Extracted from WP_Comment_Query::query().
       
   431 	 *
       
   432 	 * @access public
       
   433 	 *
       
   434 	 * @param string|array $query WP_Comment_Query arguments. See WP_Comment_Query::__construct()
       
   435 	 */
       
   436 	public function parse_query( $query = '' ) {
       
   437 		if ( empty( $query ) ) {
       
   438 			$query = $this->query_vars;
       
   439 		}
       
   440 
       
   441 		$this->query_vars = wp_parse_args( $query, $this->query_var_defaults );
       
   442 		do_action_ref_array( 'parse_comment_query', array( &$this ) );
       
   443 	}
       
   444 
       
   445 	/**
       
   446 	 * Sets up the WordPress query for retrieving comments.
       
   447 	 *
       
   448 	 * @since 3.1.0
       
   449 	 * @since 4.1.0 Introduced 'comment__in', 'comment__not_in', 'post_author__in',
       
   450 	 *              'post_author__not_in', 'author__in', 'author__not_in', 'post__in',
       
   451 	 *              'post__not_in', 'include_unapproved', 'type__in', and 'type__not_in'
       
   452 	 *              arguments to $query_vars.
       
   453 	 * @since 4.2.0 Moved parsing to WP_Comment_Query::parse_query().
       
   454 	 * @access public
       
   455 	 *
       
   456 	 * @param string|array $query Array or URL query string of parameters.
       
   457 	 * @return array List of comments.
       
   458 	 */
       
   459 	public function query( $query ) {
       
   460 		$this->query_vars = wp_parse_args( $query );
       
   461 		return $this->get_comments();
       
   462 	}
       
   463 
       
   464 	/**
       
   465 	 * Get a list of comments matching the query vars.
       
   466 	 *
       
   467 	 * @since 4.2.0
       
   468 	 * @access public
       
   469 	 *
       
   470 	 * @global wpdb $wpdb WordPress database abstraction object.
       
   471 	 *
       
   472 	 * @return array The list of comments.
       
   473 	 */
       
   474 	public function get_comments() {
       
   475 		global $wpdb;
       
   476 
   246 		$groupby = '';
   477 		$groupby = '';
   247 
   478 
   248 		$this->query_vars = wp_parse_args( $query_vars, $defaults );
   479 		$this->parse_query();
   249 
   480 
   250 		// Parse meta query
   481 		// Parse meta query
   251 		$this->meta_query = new WP_Meta_Query();
   482 		$this->meta_query = new WP_Meta_Query();
   252 		$this->meta_query->parse_query_vars( $this->query_vars );
   483 		$this->meta_query->parse_query_vars( $this->query_vars );
   253 
   484 
       
   485 		if ( ! empty( $this->meta_query->queries ) ) {
       
   486 			$meta_query_clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
       
   487 		}
       
   488 
       
   489 		/**
       
   490 		 * Fires before comments are retrieved.
       
   491 		 *
       
   492 		 * @since 3.1.0
       
   493 		 *
       
   494 		 * @param WP_Comment_Query &$this Current instance of WP_Comment_Query, passed by reference.
       
   495 		 */
   254 		do_action_ref_array( 'pre_get_comments', array( &$this ) );
   496 		do_action_ref_array( 'pre_get_comments', array( &$this ) );
   255 		extract( $this->query_vars, EXTR_SKIP );
   497 
   256 
   498 		// $args can include anything. Only use the args defined in the query_var_defaults to compute the key.
   257 		// $args can be whatever, only use the args defined in defaults to compute the key
   499 		$key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) );
   258 		$key = md5( serialize( compact(array_keys($defaults)) )  );
       
   259 		$last_changed = wp_cache_get( 'last_changed', 'comment' );
   500 		$last_changed = wp_cache_get( 'last_changed', 'comment' );
   260 		if ( ! $last_changed ) {
   501 		if ( ! $last_changed ) {
   261 			$last_changed = microtime();
   502 			$last_changed = microtime();
   262 			wp_cache_set( 'last_changed', $last_changed, 'comment' );
   503 			wp_cache_set( 'last_changed', $last_changed, 'comment' );
   263 		}
   504 		}
   264 		$cache_key = "get_comments:$key:$last_changed";
   505 		$cache_key = "get_comments:$key:$last_changed";
   265 
   506 
   266 		if ( $cache = wp_cache_get( $cache_key, 'comment' ) )
   507 		if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) {
   267 			return $cache;
   508 			$this->comments = $cache;
   268 
   509 			return $this->comments;
   269 		$post_id = absint($post_id);
   510 		}
   270 
   511 
   271 		if ( 'hold' == $status )
   512 		$where = array();
   272 			$approved = "comment_approved = '0'";
   513 
   273 		elseif ( 'approve' == $status )
   514 		// Assemble clauses related to 'comment_approved'.
   274 			$approved = "comment_approved = '1'";
   515 		$approved_clauses = array();
   275 		elseif ( ! empty( $status ) && 'all' != $status )
   516 
   276 			$approved = $wpdb->prepare( "comment_approved = %s", $status );
   517 		// 'status' accepts an array or a comma-separated string.
   277 		else
   518 		$status_clauses = array();
   278 			$approved = "( comment_approved = '0' OR comment_approved = '1' )";
   519 		$statuses = $this->query_vars['status'];
   279 
   520 		if ( ! is_array( $statuses ) ) {
   280 		$order = ( 'ASC' == strtoupper($order) ) ? 'ASC' : 'DESC';
   521 			$statuses = preg_split( '/[\s,]+/', $statuses );
   281 
   522 		}
   282 		if ( ! empty( $orderby ) ) {
   523 
   283 			$ordersby = is_array($orderby) ? $orderby : preg_split('/[,\s]/', $orderby);
   524 		// 'any' overrides other statuses.
   284 			$allowed_keys = array(
   525 		if ( ! in_array( 'any', $statuses ) ) {
   285 				'comment_agent',
   526 			foreach ( $statuses as $status ) {
   286 				'comment_approved',
   527 				switch ( $status ) {
   287 				'comment_author',
   528 					case 'hold' :
   288 				'comment_author_email',
   529 						$status_clauses[] = "comment_approved = '0'";
   289 				'comment_author_IP',
   530 						break;
   290 				'comment_author_url',
   531 
   291 				'comment_content',
   532 					case 'approve' :
   292 				'comment_date',
   533 						$status_clauses[] = "comment_approved = '1'";
   293 				'comment_date_gmt',
   534 						break;
   294 				'comment_ID',
   535 
   295 				'comment_karma',
   536 					case 'all' :
   296 				'comment_parent',
   537 					case '' :
   297 				'comment_post_ID',
   538 						$status_clauses[] = "( comment_approved = '0' OR comment_approved = '1' )";
   298 				'comment_type',
   539 						break;
   299 				'user_id',
   540 
   300 			);
   541 					default :
   301 			if ( ! empty( $this->query_vars['meta_key'] ) ) {
   542 						$status_clauses[] = $wpdb->prepare( "comment_approved = %s", $status );
   302 				$allowed_keys[] = $this->query_vars['meta_key'];
   543 						break;
   303 				$allowed_keys[] = 'meta_value';
       
   304 				$allowed_keys[] = 'meta_value_num';
       
   305 			}
       
   306 			$ordersby = array_intersect( $ordersby, $allowed_keys );
       
   307 			foreach ( $ordersby as $key => $value ) {
       
   308 				if ( $value == $this->query_vars['meta_key'] || $value == 'meta_value' ) {
       
   309 					$ordersby[ $key ] = "$wpdb->commentmeta.meta_value";
       
   310 				} elseif ( $value == 'meta_value_num' ) {
       
   311 					$ordersby[ $key ] = "$wpdb->commentmeta.meta_value+0";
       
   312 				}
   544 				}
   313 			}
   545 			}
   314 			$orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby);
   546 
       
   547 			if ( ! empty( $status_clauses ) ) {
       
   548 				$approved_clauses[] = '( ' . implode( ' OR ', $status_clauses ) . ' )';
       
   549 			}
       
   550 		}
       
   551 
       
   552 		// User IDs or emails whose unapproved comments are included, regardless of $status.
       
   553 		if ( ! empty( $this->query_vars['include_unapproved'] ) ) {
       
   554 			$include_unapproved = $this->query_vars['include_unapproved'];
       
   555 
       
   556 			// Accepts arrays or comma-separated strings.
       
   557 			if ( ! is_array( $include_unapproved ) ) {
       
   558 				$include_unapproved = preg_split( '/[\s,]+/', $include_unapproved );
       
   559 			}
       
   560 
       
   561 			$unapproved_ids = $unapproved_emails = array();
       
   562 			foreach ( $include_unapproved as $unapproved_identifier ) {
       
   563 				// Numeric values are assumed to be user ids.
       
   564 				if ( is_numeric( $unapproved_identifier ) ) {
       
   565 					$approved_clauses[] = $wpdb->prepare( "( user_id = %d AND comment_approved = '0' )", $unapproved_identifier );
       
   566 
       
   567 				// Otherwise we match against email addresses.
       
   568 				} else {
       
   569 					$approved_clauses[] = $wpdb->prepare( "( comment_author_email = %s AND comment_approved = '0' )", $unapproved_identifier );
       
   570 				}
       
   571 			}
       
   572 		}
       
   573 
       
   574 		// Collapse comment_approved clauses into a single OR-separated clause.
       
   575 		if ( ! empty( $approved_clauses ) ) {
       
   576 			if ( 1 === count( $approved_clauses ) ) {
       
   577 				$where[] = $approved_clauses[0];
       
   578 			} else {
       
   579 				$where[] = '( ' . implode( ' OR ', $approved_clauses ) . ' )';
       
   580 			}
       
   581 		}
       
   582 
       
   583 		$order = ( 'ASC' == strtoupper( $this->query_vars['order'] ) ) ? 'ASC' : 'DESC';
       
   584 
       
   585 		// Disable ORDER BY with 'none', an empty array, or boolean false.
       
   586 		if ( in_array( $this->query_vars['orderby'], array( 'none', array(), false ), true ) ) {
       
   587 			$orderby = '';
       
   588 		} elseif ( ! empty( $this->query_vars['orderby'] ) ) {
       
   589 			$ordersby = is_array( $this->query_vars['orderby'] ) ?
       
   590 				$this->query_vars['orderby'] :
       
   591 				preg_split( '/[,\s]/', $this->query_vars['orderby'] );
       
   592 
       
   593 			$orderby_array = array();
       
   594 			$found_orderby_comment_ID = false;
       
   595 			foreach ( $ordersby as $_key => $_value ) {
       
   596 				if ( ! $_value ) {
       
   597 					continue;
       
   598 				}
       
   599 
       
   600 				if ( is_int( $_key ) ) {
       
   601 					$_orderby = $_value;
       
   602 					$_order = $order;
       
   603 				} else {
       
   604 					$_orderby = $_key;
       
   605 					$_order = $_value;
       
   606 				}
       
   607 
       
   608 				if ( ! $found_orderby_comment_ID && 'comment_ID' === $_orderby ) {
       
   609 					$found_orderby_comment_ID = true;
       
   610 				}
       
   611 
       
   612 				$parsed = $this->parse_orderby( $_orderby );
       
   613 
       
   614 				if ( ! $parsed ) {
       
   615 					continue;
       
   616 				}
       
   617 
       
   618 				$orderby_array[] = $parsed . ' ' . $this->parse_order( $_order );
       
   619 			}
       
   620 
       
   621 			// If no valid clauses were found, order by comment_date_gmt.
       
   622 			if ( empty( $orderby_array ) ) {
       
   623 				$orderby_array[] = "$wpdb->comments.comment_date_gmt $order";
       
   624 			}
       
   625 
       
   626 			// To ensure determinate sorting, always include a comment_ID clause.
       
   627 			if ( ! $found_orderby_comment_ID ) {
       
   628 				$comment_ID_order = '';
       
   629 
       
   630 				// Inherit order from comment_date or comment_date_gmt, if available.
       
   631 				foreach ( $orderby_array as $orderby_clause ) {
       
   632 					if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) {
       
   633 						$comment_ID_order = $match[1];
       
   634 						break;
       
   635 					}
       
   636 				}
       
   637 
       
   638 				// If no date-related order is available, use the date from the first available clause.
       
   639 				if ( ! $comment_ID_order ) {
       
   640 					foreach ( $orderby_array as $orderby_clause ) {
       
   641 						if ( false !== strpos( 'ASC', $orderby_clause ) ) {
       
   642 							$comment_ID_order = 'ASC';
       
   643 						} else {
       
   644 							$comment_ID_order = 'DESC';
       
   645 						}
       
   646 
       
   647 						break;
       
   648 					}
       
   649 				}
       
   650 
       
   651 				// Default to DESC.
       
   652 				if ( ! $comment_ID_order ) {
       
   653 					$comment_ID_order = 'DESC';
       
   654 				}
       
   655 
       
   656 				$orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order";
       
   657 			}
       
   658 
       
   659 			$orderby = implode( ', ', $orderby_array );
   315 		} else {
   660 		} else {
   316 			$orderby = 'comment_date_gmt';
   661 			$orderby = "$wpdb->comments.comment_date_gmt $order";
   317 		}
   662 		}
   318 
   663 
   319 		$number = absint($number);
   664 		$number = absint( $this->query_vars['number'] );
   320 		$offset = absint($offset);
   665 		$offset = absint( $this->query_vars['offset'] );
   321 
   666 
   322 		if ( !empty($number) ) {
   667 		if ( ! empty( $number ) ) {
   323 			if ( $offset )
   668 			if ( $offset ) {
   324 				$limits = 'LIMIT ' . $offset . ',' . $number;
   669 				$limits = 'LIMIT ' . $offset . ',' . $number;
   325 			else
   670 			} else {
   326 				$limits = 'LIMIT ' . $number;
   671 				$limits = 'LIMIT ' . $number;
       
   672 			}
   327 		} else {
   673 		} else {
   328 			$limits = '';
   674 			$limits = '';
   329 		}
   675 		}
   330 
   676 
   331 		if ( $count )
   677 		if ( $this->query_vars['count'] ) {
   332 			$fields = 'COUNT(*)';
   678 			$fields = 'COUNT(*)';
   333 		else
   679 		} else {
   334 			$fields = '*';
   680 			switch ( strtolower( $this->query_vars['fields'] ) ) {
       
   681 				case 'ids':
       
   682 					$fields = "$wpdb->comments.comment_ID";
       
   683 					break;
       
   684 				default:
       
   685 					$fields = "*";
       
   686 					break;
       
   687 			}
       
   688 		}
   335 
   689 
   336 		$join = '';
   690 		$join = '';
   337 		$where = $approved;
   691 
   338 
   692 		$post_id = absint( $this->query_vars['post_id'] );
   339 		if ( ! empty($post_id) )
   693 		if ( ! empty( $post_id ) ) {
   340 			$where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id );
   694 			$where[] = $wpdb->prepare( 'comment_post_ID = %d', $post_id );
   341 		if ( '' !== $author_email )
   695 		}
   342 			$where .= $wpdb->prepare( ' AND comment_author_email = %s', $author_email );
   696 
   343 		if ( '' !== $karma )
   697 		// Parse comment IDs for an IN clause.
   344 			$where .= $wpdb->prepare( ' AND comment_karma = %d', $karma );
   698 		if ( ! empty( $this->query_vars['comment__in'] ) ) {
   345 		if ( 'comment' == $type ) {
   699 			$where[] = 'comment_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__in'] ) ) . ' )';
   346 			$where .= " AND comment_type = ''";
   700 		}
   347 		} elseif( 'pings' == $type ) {
   701 
   348 			$where .= ' AND comment_type IN ("pingback", "trackback")';
   702 		// Parse comment IDs for a NOT IN clause.
   349 		} elseif ( ! empty( $type ) ) {
   703 		if ( ! empty( $this->query_vars['comment__not_in'] ) ) {
   350 			$where .= $wpdb->prepare( ' AND comment_type = %s', $type );
   704 			$where[] = 'comment_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['comment__not_in'] ) ) . ' )';
   351 		}
   705 		}
   352 		if ( '' !== $parent )
   706 
   353 			$where .= $wpdb->prepare( ' AND comment_parent = %d', $parent );
   707 		// Parse comment post IDs for an IN clause.
   354 		if ( '' !== $user_id )
   708 		if ( ! empty( $this->query_vars['post__in'] ) ) {
   355 			$where .= $wpdb->prepare( ' AND user_id = %d', $user_id );
   709 			$where[] = 'comment_post_ID IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__in'] ) ) . ' )';
   356 		if ( '' !== $search )
   710 		}
   357 			$where .= $this->get_search_sql( $search, array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' ) );
   711 
   358 
   712 		// Parse comment post IDs for a NOT IN clause.
   359 		$post_fields = array_filter( compact( array( 'post_author', 'post_name', 'post_parent', 'post_status', 'post_type', ) ) );
   713 		if ( ! empty( $this->query_vars['post__not_in'] ) ) {
       
   714 			$where[] = 'comment_post_ID NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post__not_in'] ) ) . ' )';
       
   715 		}
       
   716 
       
   717 		if ( '' !== $this->query_vars['author_email'] ) {
       
   718 			$where[] = $wpdb->prepare( 'comment_author_email = %s', $this->query_vars['author_email'] );
       
   719 		}
       
   720 
       
   721 		if ( '' !== $this->query_vars['karma'] ) {
       
   722 			$where[] = $wpdb->prepare( 'comment_karma = %d', $this->query_vars['karma'] );
       
   723 		}
       
   724 
       
   725 		// Filtering by comment_type: 'type', 'type__in', 'type__not_in'.
       
   726 		$raw_types = array(
       
   727 			'IN' => array_merge( (array) $this->query_vars['type'], (array) $this->query_vars['type__in'] ),
       
   728 			'NOT IN' => (array) $this->query_vars['type__not_in'],
       
   729 		);
       
   730 
       
   731 		$comment_types = array();
       
   732 		foreach ( $raw_types as $operator => $_raw_types ) {
       
   733 			$_raw_types = array_unique( $_raw_types );
       
   734 
       
   735 			foreach ( $_raw_types as $type ) {
       
   736 				switch ( $type ) {
       
   737 					// An empty translates to 'all', for backward compatibility
       
   738 					case '':
       
   739 					case 'all' :
       
   740 						break;
       
   741 
       
   742 					case 'comment':
       
   743 					case 'comments':
       
   744 						$comment_types[ $operator ][] = "''";
       
   745 						break;
       
   746 
       
   747 					case 'pings':
       
   748 						$comment_types[ $operator ][] = "'pingback'";
       
   749 						$comment_types[ $operator ][] = "'trackback'";
       
   750 						break;
       
   751 
       
   752 					default:
       
   753 						$comment_types[ $operator ][] = $wpdb->prepare( '%s', $type );
       
   754 						break;
       
   755 				}
       
   756 			}
       
   757 
       
   758 			if ( ! empty( $comment_types[ $operator ] ) ) {
       
   759 				$types_sql = implode( ', ', $comment_types[ $operator ] );
       
   760 				$where[] = "comment_type $operator ($types_sql)";
       
   761 			}
       
   762 		}
       
   763 
       
   764 		if ( '' !== $this->query_vars['parent'] ) {
       
   765 			$where[] = $wpdb->prepare( 'comment_parent = %d', $this->query_vars['parent'] );
       
   766 		}
       
   767 
       
   768 		if ( is_array( $this->query_vars['user_id'] ) ) {
       
   769 			$where[] = 'user_id IN (' . implode( ',', array_map( 'absint', $this->query_vars['user_id'] ) ) . ')';
       
   770 		} elseif ( '' !== $this->query_vars['user_id'] ) {
       
   771 			$where[] = $wpdb->prepare( 'user_id = %d', $this->query_vars['user_id'] );
       
   772 		}
       
   773 
       
   774 		if ( '' !== $this->query_vars['search'] ) {
       
   775 			$search_sql = $this->get_search_sql(
       
   776 				$this->query_vars['search'],
       
   777 				array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content' )
       
   778 			);
       
   779 
       
   780 			// Strip leading 'AND'.
       
   781 			$where[] = preg_replace( '/^\s*AND\s*/', '', $search_sql );
       
   782 		}
       
   783 
       
   784 		// If any post-related query vars are passed, join the posts table.
       
   785 		$join_posts_table = false;
       
   786 		$plucked = wp_array_slice_assoc( $this->query_vars, array( 'post_author', 'post_name', 'post_parent', 'post_status', 'post_type' ) );
       
   787 		$post_fields = array_filter( $plucked );
       
   788 
   360 		if ( ! empty( $post_fields ) ) {
   789 		if ( ! empty( $post_fields ) ) {
       
   790 			$join_posts_table = true;
       
   791 			foreach ( $post_fields as $field_name => $field_value ) {
       
   792 				// $field_value may be an array.
       
   793 				$esses = array_fill( 0, count( (array) $field_value ), '%s' );
       
   794 				$where[] = $wpdb->prepare( " {$wpdb->posts}.{$field_name} IN (" . implode( ',', $esses ) . ')', $field_value );
       
   795 			}
       
   796 		}
       
   797 
       
   798 		// Comment author IDs for an IN clause.
       
   799 		if ( ! empty( $this->query_vars['author__in'] ) ) {
       
   800 			$where[] = 'user_id IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__in'] ) ) . ' )';
       
   801 		}
       
   802 
       
   803 		// Comment author IDs for a NOT IN clause.
       
   804 		if ( ! empty( $this->query_vars['author__not_in'] ) ) {
       
   805 			$where[] = 'user_id NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['author__not_in'] ) ) . ' )';
       
   806 		}
       
   807 
       
   808 		// Post author IDs for an IN clause.
       
   809 		if ( ! empty( $this->query_vars['post_author__in'] ) ) {
       
   810 			$join_posts_table = true;
       
   811 			$where[] = 'post_author IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__in'] ) ) . ' )';
       
   812 		}
       
   813 
       
   814 		// Post author IDs for a NOT IN clause.
       
   815 		if ( ! empty( $this->query_vars['post_author__not_in'] ) ) {
       
   816 			$join_posts_table = true;
       
   817 			$where[] = 'post_author NOT IN ( ' . implode( ',', wp_parse_id_list( $this->query_vars['post_author__not_in'] ) ) . ' )';
       
   818 		}
       
   819 
       
   820 		if ( $join_posts_table ) {
   361 			$join = "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
   821 			$join = "JOIN $wpdb->posts ON $wpdb->posts.ID = $wpdb->comments.comment_post_ID";
   362 			foreach( $post_fields as $field_name => $field_value )
   822 		}
   363 				$where .= $wpdb->prepare( " AND {$wpdb->posts}.{$field_name} = %s", $field_value );
   823 
   364 		}
   824 		if ( ! empty( $meta_query_clauses ) ) {
   365 
   825 			$join .= $meta_query_clauses['join'];
   366 		if ( ! empty( $this->meta_query->queries ) ) {
   826 
   367 			$clauses = $this->meta_query->get_sql( 'comment', $wpdb->comments, 'comment_ID', $this );
   827 			// Strip leading 'AND'.
   368 			$join .= $clauses['join'];
   828 			$where[] = preg_replace( '/^\s*AND\s*/', '', $meta_query_clauses['where'] );
   369 			$where .= $clauses['where'];
   829 
   370 			$groupby = "{$wpdb->comments}.comment_ID";
   830 			if ( ! $this->query_vars['count'] ) {
   371 		}
   831 				$groupby = "{$wpdb->comments}.comment_ID";
   372 
   832 			}
       
   833 		}
       
   834 
       
   835 		$date_query = $this->query_vars['date_query'];
   373 		if ( ! empty( $date_query ) && is_array( $date_query ) ) {
   836 		if ( ! empty( $date_query ) && is_array( $date_query ) ) {
   374 			$date_query_object = new WP_Date_Query( $date_query, 'comment_date' );
   837 			$date_query_object = new WP_Date_Query( $date_query, 'comment_date' );
   375 			$where .= $date_query_object->get_sql();
   838 			$where[] = preg_replace( '/^\s*AND\s*/', '', $date_query_object->get_sql() );
   376 		}
   839 		}
   377 
   840 
   378 		$pieces = array( 'fields', 'join', 'where', 'orderby', 'order', 'limits', 'groupby' );
   841 		$where = implode( ' AND ', $where );
       
   842 
       
   843 		$pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' );
       
   844 		/**
       
   845 		 * Filter the comment query clauses.
       
   846 		 *
       
   847 		 * @since 3.1.0
       
   848 		 *
       
   849 		 * @param array            $pieces A compacted array of comment query clauses.
       
   850 		 * @param WP_Comment_Query &$this  Current instance of WP_Comment_Query, passed by reference.
       
   851 		 */
   379 		$clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );
   852 		$clauses = apply_filters_ref_array( 'comments_clauses', array( compact( $pieces ), &$this ) );
   380 		foreach ( $pieces as $piece )
   853 
   381 			$$piece = isset( $clauses[ $piece ] ) ? $clauses[ $piece ] : '';
   854 		$fields = isset( $clauses[ 'fields' ] ) ? $clauses[ 'fields' ] : '';
   382 
   855 		$join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : '';
   383 		if ( $groupby )
   856 		$where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : '';
       
   857 		$orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : '';
       
   858 		$limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : '';
       
   859 		$groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : '';
       
   860 
       
   861 		if ( $where ) {
       
   862 			$where = 'WHERE ' . $where;
       
   863 		}
       
   864 
       
   865 		if ( $groupby ) {
   384 			$groupby = 'GROUP BY ' . $groupby;
   866 			$groupby = 'GROUP BY ' . $groupby;
   385 
   867 		}
   386 		$query = "SELECT $fields FROM $wpdb->comments $join WHERE $where $groupby ORDER BY $orderby $order $limits";
   868 
   387 
   869 		if ( $orderby ) {
   388 		if ( $count )
   870 			$orderby = "ORDER BY $orderby";
   389 			return $wpdb->get_var( $query );
   871 		}
   390 
   872 
   391 		$comments = $wpdb->get_results( $query );
   873 		$this->request = "SELECT $fields FROM $wpdb->comments $join $where $groupby $orderby $limits";
   392 		$comments = apply_filters_ref_array( 'the_comments', array( $comments, &$this ) );
   874 
       
   875 		if ( $this->query_vars['count'] ) {
       
   876 			return $wpdb->get_var( $this->request );
       
   877 		}
       
   878 
       
   879 		if ( 'ids' == $this->query_vars['fields'] ) {
       
   880 			$this->comments = $wpdb->get_col( $this->request );
       
   881 			return array_map( 'intval', $this->comments );
       
   882 		}
       
   883 
       
   884 		$results = $wpdb->get_results( $this->request );
       
   885 		/**
       
   886 		 * Filter the comment query results.
       
   887 		 *
       
   888 		 * @since 3.1.0
       
   889 		 *
       
   890 		 * @param array            $results  An array of comments.
       
   891 		 * @param WP_Comment_Query &$this    Current instance of WP_Comment_Query, passed by reference.
       
   892 		 */
       
   893 		$comments = apply_filters_ref_array( 'the_comments', array( $results, &$this ) );
   393 
   894 
   394 		wp_cache_add( $cache_key, $comments, 'comment' );
   895 		wp_cache_add( $cache_key, $comments, 'comment' );
   395 
   896 
   396 		return $comments;
   897 		$this->comments = $comments;
   397 	}
   898 		return $this->comments;
   398 
   899 	}
   399 	/*
   900 
       
   901 	/**
   400 	 * Used internally to generate an SQL string for searching across multiple columns
   902 	 * Used internally to generate an SQL string for searching across multiple columns
   401 	 *
   903 	 *
   402 	 * @access protected
   904 	 * @access protected
   403 	 * @since 3.1.0
   905 	 * @since 3.1.0
   404 	 *
   906 	 *
   405 	 * @param string $string
   907 	 * @param string $string
   406 	 * @param array $cols
   908 	 * @param array $cols
   407 	 * @return string
   909 	 * @return string
   408 	 */
   910 	 */
   409 	function get_search_sql( $string, $cols ) {
   911 	protected function get_search_sql( $string, $cols ) {
   410 		$string = esc_sql( like_escape( $string ) );
   912 		global $wpdb;
       
   913 
       
   914 		$like = '%' . $wpdb->esc_like( $string ) . '%';
   411 
   915 
   412 		$searches = array();
   916 		$searches = array();
   413 		foreach ( $cols as $col )
   917 		foreach ( $cols as $col ) {
   414 			$searches[] = "$col LIKE '%$string%'";
   918 			$searches[] = $wpdb->prepare( "$col LIKE %s", $like );
       
   919 		}
   415 
   920 
   416 		return ' AND (' . implode(' OR ', $searches) . ')';
   921 		return ' AND (' . implode(' OR ', $searches) . ')';
       
   922 	}
       
   923 
       
   924 	/**
       
   925 	 * Parse and sanitize 'orderby' keys passed to the comment query.
       
   926 	 *
       
   927 	 * @since 4.2.0
       
   928 	 * @access protected
       
   929 	 *
       
   930 	 * @global wpdb $wpdb WordPress database abstraction object.
       
   931 	 *
       
   932 	 * @param string $orderby Alias for the field to order by.
       
   933 	 * @return string|bool Value to used in the ORDER clause. False otherwise.
       
   934 	 */
       
   935 	protected function parse_orderby( $orderby ) {
       
   936 		global $wpdb;
       
   937 
       
   938 		$allowed_keys = array(
       
   939 			'comment_agent',
       
   940 			'comment_approved',
       
   941 			'comment_author',
       
   942 			'comment_author_email',
       
   943 			'comment_author_IP',
       
   944 			'comment_author_url',
       
   945 			'comment_content',
       
   946 			'comment_date',
       
   947 			'comment_date_gmt',
       
   948 			'comment_ID',
       
   949 			'comment_karma',
       
   950 			'comment_parent',
       
   951 			'comment_post_ID',
       
   952 			'comment_type',
       
   953 			'user_id',
       
   954 		);
       
   955 
       
   956 		if ( ! empty( $this->query_vars['meta_key'] ) ) {
       
   957 			$allowed_keys[] = $this->query_vars['meta_key'];
       
   958 			$allowed_keys[] = 'meta_value';
       
   959 			$allowed_keys[] = 'meta_value_num';
       
   960 		}
       
   961 
       
   962 		$meta_query_clauses = $this->meta_query->get_clauses();
       
   963 		if ( $meta_query_clauses ) {
       
   964 			$allowed_keys = array_merge( $allowed_keys, array_keys( $meta_query_clauses ) );
       
   965 		}
       
   966 
       
   967 		$parsed = false;
       
   968 		if ( $orderby == $this->query_vars['meta_key'] || $orderby == 'meta_value' ) {
       
   969 			$parsed = "$wpdb->commentmeta.meta_value";
       
   970 		} else if ( $orderby == 'meta_value_num' ) {
       
   971 			$parsed = "$wpdb->commentmeta.meta_value+0";
       
   972 		} else if ( in_array( $orderby, $allowed_keys ) ) {
       
   973 
       
   974 			if ( isset( $meta_query_clauses[ $orderby ] ) ) {
       
   975 				$meta_clause = $meta_query_clauses[ $orderby ];
       
   976 				$parsed = sprintf( "CAST(%s.meta_value AS %s)", esc_sql( $meta_clause['alias'] ), esc_sql( $meta_clause['cast'] ) );
       
   977 			} else {
       
   978 				$parsed = "$wpdb->comments.$orderby";
       
   979 			}
       
   980 		}
       
   981 
       
   982 		return $parsed;
       
   983 	}
       
   984 
       
   985 	/**
       
   986 	 * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
       
   987 	 *
       
   988 	 * @since 4.2.0
       
   989 	 * @access protected
       
   990 	 *
       
   991 	 * @param string $order The 'order' query variable.
       
   992 	 * @return string The sanitized 'order' query variable.
       
   993 	 */
       
   994 	protected function parse_order( $order ) {
       
   995 		if ( ! is_string( $order ) || empty( $order ) ) {
       
   996 			return 'DESC';
       
   997 		}
       
   998 
       
   999 		if ( 'ASC' === strtoupper( $order ) ) {
       
  1000 			return 'ASC';
       
  1001 		} else {
       
  1002 			return 'DESC';
       
  1003 		}
   417 	}
  1004 	}
   418 }
  1005 }
   419 
  1006 
   420 /**
  1007 /**
   421  * Retrieve all of the WordPress supported comment statuses.
  1008  * Retrieve all of the WordPress supported comment statuses.
   422  *
  1009  *
   423  * Comments have a limited set of valid status values, this provides the comment
  1010  * Comments have a limited set of valid status values, this provides the comment
   424  * status values and descriptions.
  1011  * status values and descriptions.
   425  *
  1012  *
   426  * @package WordPress
       
   427  * @subpackage Post
       
   428  * @since 2.7.0
  1013  * @since 2.7.0
   429  *
  1014  *
   430  * @return array List of comment statuses.
  1015  * @return array List of comment statuses.
   431  */
  1016  */
   432 function get_comment_statuses() {
  1017 function get_comment_statuses() {
   443 
  1028 
   444 /**
  1029 /**
   445  * The date the last comment was modified.
  1030  * The date the last comment was modified.
   446  *
  1031  *
   447  * @since 1.5.0
  1032  * @since 1.5.0
   448  * @uses $wpdb
  1033  *
       
  1034  * @global wpdb $wpdb WordPress database abstraction object.
   449  *
  1035  *
   450  * @param string $timezone Which timezone to use in reference to 'gmt', 'blog',
  1036  * @param string $timezone Which timezone to use in reference to 'gmt', 'blog',
   451  *		or 'server' locations.
  1037  *		or 'server' locations.
   452  * @return string Last comment modified date.
  1038  * @return string Last comment modified date.
   453  */
  1039  */
   483  * A lot like {@link wp_count_comments()}, in that they both return comment
  1069  * A lot like {@link wp_count_comments()}, in that they both return comment
   484  * stats (albeit with different types). The {@link wp_count_comments()} actual
  1070  * stats (albeit with different types). The {@link wp_count_comments()} actual
   485  * caches, but this function does not.
  1071  * caches, but this function does not.
   486  *
  1072  *
   487  * @since 2.0.0
  1073  * @since 2.0.0
   488  * @uses $wpdb
  1074  *
       
  1075  * @global wpdb $wpdb WordPress database abstraction object.
   489  *
  1076  *
   490  * @param int $post_id Optional. Comment amount in post if > 0, else total comments blog wide.
  1077  * @param int $post_id Optional. Comment amount in post if > 0, else total comments blog wide.
   491  * @return array The amount of spam, approved, awaiting moderation, and total comments.
  1078  * @return array The amount of spam, approved, awaiting moderation, and total comments.
   492  */
  1079  */
   493 function get_comment_count( $post_id = 0 ) {
  1080 function get_comment_count( $post_id = 0 ) {
   542 
  1129 
   543 /**
  1130 /**
   544  * Add meta data field to a comment.
  1131  * Add meta data field to a comment.
   545  *
  1132  *
   546  * @since 2.9.0
  1133  * @since 2.9.0
   547  * @uses add_metadata
  1134  * @link https://codex.wordpress.org/Function_Reference/add_comment_meta
   548  * @link http://codex.wordpress.org/Function_Reference/add_comment_meta
       
   549  *
  1135  *
   550  * @param int $comment_id Comment ID.
  1136  * @param int $comment_id Comment ID.
   551  * @param string $meta_key Metadata name.
  1137  * @param string $meta_key Metadata name.
   552  * @param mixed $meta_value Metadata value.
  1138  * @param mixed $meta_value Metadata value.
   553  * @param bool $unique Optional, default is false. Whether the same key should not be added.
  1139  * @param bool $unique Optional, default is false. Whether the same key should not be added.
   563  * You can match based on the key, or key and value. Removing based on key and
  1149  * You can match based on the key, or key and value. Removing based on key and
   564  * value, will keep from removing duplicate metadata with the same key. It also
  1150  * value, will keep from removing duplicate metadata with the same key. It also
   565  * allows removing all metadata matching key, if needed.
  1151  * allows removing all metadata matching key, if needed.
   566  *
  1152  *
   567  * @since 2.9.0
  1153  * @since 2.9.0
   568  * @uses delete_metadata
  1154  * @link https://codex.wordpress.org/Function_Reference/delete_comment_meta
   569  * @link http://codex.wordpress.org/Function_Reference/delete_comment_meta
       
   570  *
  1155  *
   571  * @param int $comment_id comment ID
  1156  * @param int $comment_id comment ID
   572  * @param string $meta_key Metadata name.
  1157  * @param string $meta_key Metadata name.
   573  * @param mixed $meta_value Optional. Metadata value.
  1158  * @param mixed $meta_value Optional. Metadata value.
   574  * @return bool True on success, false on failure.
  1159  * @return bool True on success, false on failure.
   579 
  1164 
   580 /**
  1165 /**
   581  * Retrieve comment meta field for a comment.
  1166  * Retrieve comment meta field for a comment.
   582  *
  1167  *
   583  * @since 2.9.0
  1168  * @since 2.9.0
   584  * @uses get_metadata
  1169  * @link https://codex.wordpress.org/Function_Reference/get_comment_meta
   585  * @link http://codex.wordpress.org/Function_Reference/get_comment_meta
       
   586  *
  1170  *
   587  * @param int $comment_id Comment ID.
  1171  * @param int $comment_id Comment ID.
   588  * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
  1172  * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.
   589  * @param bool $single Whether to return a single value.
  1173  * @param bool $single Whether to return a single value.
   590  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
  1174  * @return mixed Will be an array if $single is false. Will be value of meta data field if $single
   601  * same key and comment ID.
  1185  * same key and comment ID.
   602  *
  1186  *
   603  * If the meta field for the comment does not exist, it will be added.
  1187  * If the meta field for the comment does not exist, it will be added.
   604  *
  1188  *
   605  * @since 2.9.0
  1189  * @since 2.9.0
   606  * @uses update_metadata
  1190  * @link https://codex.wordpress.org/Function_Reference/update_comment_meta
   607  * @link http://codex.wordpress.org/Function_Reference/update_comment_meta
       
   608  *
  1191  *
   609  * @param int $comment_id Comment ID.
  1192  * @param int $comment_id Comment ID.
   610  * @param string $meta_key Metadata key.
  1193  * @param string $meta_key Metadata key.
   611  * @param mixed $meta_value Metadata value.
  1194  * @param mixed $meta_value Metadata value.
   612  * @param mixed $prev_value Optional. Previous value to check before removing.
  1195  * @param mixed $prev_value Optional. Previous value to check before removing.
   613  * @return bool True on success, false on failure.
  1196  * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
   614  */
  1197  */
   615 function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') {
  1198 function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') {
   616 	return update_metadata('comment', $comment_id, $meta_key, $meta_value, $prev_value);
  1199 	return update_metadata('comment', $comment_id, $meta_key, $meta_value, $prev_value);
   617 }
  1200 }
   618 
  1201 
   627  */
  1210  */
   628 function wp_set_comment_cookies($comment, $user) {
  1211 function wp_set_comment_cookies($comment, $user) {
   629 	if ( $user->exists() )
  1212 	if ( $user->exists() )
   630 		return;
  1213 		return;
   631 
  1214 
   632 	$comment_cookie_lifetime = apply_filters('comment_cookie_lifetime', 30000000);
  1215 	/**
   633 	setcookie('comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
  1216 	 * Filter the lifetime of the comment cookie in seconds.
   634 	setcookie('comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
  1217 	 *
   635 	setcookie('comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN);
  1218 	 * @since 2.8.0
       
  1219 	 *
       
  1220 	 * @param int $seconds Comment cookie lifetime. Default 30000000.
       
  1221 	 */
       
  1222 	$comment_cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
       
  1223 	$secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) );
       
  1224 	setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, $secure );
       
  1225 	setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, $secure );
       
  1226 	setcookie( 'comment_author_url_' . COOKIEHASH, esc_url($comment->comment_author_url), time() + $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, $secure );
   636 }
  1227 }
   637 
  1228 
   638 /**
  1229 /**
   639  * Sanitizes the cookies sent to the user already.
  1230  * Sanitizes the cookies sent to the user already.
   640  *
  1231  *
   642  * Mostly used after cookies had been sent to use elsewhere.
  1233  * Mostly used after cookies had been sent to use elsewhere.
   643  *
  1234  *
   644  * @since 2.0.4
  1235  * @since 2.0.4
   645  */
  1236  */
   646 function sanitize_comment_cookies() {
  1237 function sanitize_comment_cookies() {
   647 	if ( isset($_COOKIE['comment_author_'.COOKIEHASH]) ) {
  1238 	if ( isset( $_COOKIE['comment_author_' . COOKIEHASH] ) ) {
   648 		$comment_author = apply_filters('pre_comment_author_name', $_COOKIE['comment_author_'.COOKIEHASH]);
  1239 		/**
       
  1240 		 * Filter the comment author's name cookie before it is set.
       
  1241 		 *
       
  1242 		 * When this filter hook is evaluated in wp_filter_comment(),
       
  1243 		 * the comment author's name string is passed.
       
  1244 		 *
       
  1245 		 * @since 1.5.0
       
  1246 		 *
       
  1247 		 * @param string $author_cookie The comment author name cookie.
       
  1248 		 */
       
  1249 		$comment_author = apply_filters( 'pre_comment_author_name', $_COOKIE['comment_author_' . COOKIEHASH] );
   649 		$comment_author = wp_unslash($comment_author);
  1250 		$comment_author = wp_unslash($comment_author);
   650 		$comment_author = esc_attr($comment_author);
  1251 		$comment_author = esc_attr($comment_author);
   651 		$_COOKIE['comment_author_'.COOKIEHASH] = $comment_author;
  1252 		$_COOKIE['comment_author_' . COOKIEHASH] = $comment_author;
   652 	}
  1253 	}
   653 
  1254 
   654 	if ( isset($_COOKIE['comment_author_email_'.COOKIEHASH]) ) {
  1255 	if ( isset( $_COOKIE['comment_author_email_' . COOKIEHASH] ) ) {
   655 		$comment_author_email = apply_filters('pre_comment_author_email', $_COOKIE['comment_author_email_'.COOKIEHASH]);
  1256 		/**
       
  1257 		 * Filter the comment author's email cookie before it is set.
       
  1258 		 *
       
  1259 		 * When this filter hook is evaluated in wp_filter_comment(),
       
  1260 		 * the comment author's email string is passed.
       
  1261 		 *
       
  1262 		 * @since 1.5.0
       
  1263 		 *
       
  1264 		 * @param string $author_email_cookie The comment author email cookie.
       
  1265 		 */
       
  1266 		$comment_author_email = apply_filters( 'pre_comment_author_email', $_COOKIE['comment_author_email_' . COOKIEHASH] );
   656 		$comment_author_email = wp_unslash($comment_author_email);
  1267 		$comment_author_email = wp_unslash($comment_author_email);
   657 		$comment_author_email = esc_attr($comment_author_email);
  1268 		$comment_author_email = esc_attr($comment_author_email);
   658 		$_COOKIE['comment_author_email_'.COOKIEHASH] = $comment_author_email;
  1269 		$_COOKIE['comment_author_email_'.COOKIEHASH] = $comment_author_email;
   659 	}
  1270 	}
   660 
  1271 
   661 	if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) ) {
  1272 	if ( isset( $_COOKIE['comment_author_url_' . COOKIEHASH] ) ) {
   662 		$comment_author_url = apply_filters('pre_comment_author_url', $_COOKIE['comment_author_url_'.COOKIEHASH]);
  1273 		/**
       
  1274 		 * Filter the comment author's URL cookie before it is set.
       
  1275 		 *
       
  1276 		 * When this filter hook is evaluated in wp_filter_comment(),
       
  1277 		 * the comment author's URL string is passed.
       
  1278 		 *
       
  1279 		 * @since 1.5.0
       
  1280 		 *
       
  1281 		 * @param string $author_url_cookie The comment author URL cookie.
       
  1282 		 */
       
  1283 		$comment_author_url = apply_filters( 'pre_comment_author_url', $_COOKIE['comment_author_url_' . COOKIEHASH] );
   663 		$comment_author_url = wp_unslash($comment_author_url);
  1284 		$comment_author_url = wp_unslash($comment_author_url);
   664 		$_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url;
  1285 		$_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url;
   665 	}
  1286 	}
   666 }
  1287 }
   667 
  1288 
   668 /**
  1289 /**
   669  * Validates whether this comment is allowed to be made.
  1290  * Validates whether this comment is allowed to be made.
   670  *
  1291  *
   671  * @since 2.0.0
  1292  * @since 2.0.0
   672  * @uses $wpdb
  1293  *
   673  * @uses apply_filters() Calls 'pre_comment_approved' hook on the type of comment
  1294  * @global wpdb $wpdb WordPress database abstraction object.
   674  * @uses apply_filters() Calls 'comment_duplicate_trigger' hook on commentdata.
       
   675  * @uses do_action() Calls 'check_comment_flood' hook on $comment_author_IP, $comment_author_email, and $comment_date_gmt
       
   676  *
  1295  *
   677  * @param array $commentdata Contains information on the comment
  1296  * @param array $commentdata Contains information on the comment
   678  * @return mixed Signifies the approval status (0|1|'spam')
  1297  * @return mixed Signifies the approval status (0|1|'spam')
   679  */
  1298  */
   680 function wp_allow_comment($commentdata) {
  1299 function wp_allow_comment( $commentdata ) {
   681 	global $wpdb;
  1300 	global $wpdb;
   682 	extract($commentdata, EXTR_SKIP);
       
   683 
  1301 
   684 	// Simple duplicate check
  1302 	// Simple duplicate check
   685 	// expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content)
  1303 	// expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content)
   686 	$dupe = $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = %s AND comment_approved != 'trash' AND ( comment_author = %s ", wp_unslash( $comment_post_ID ), wp_unslash( $comment_parent ), wp_unslash( $comment_author ) );
  1304 	$dupe = $wpdb->prepare(
   687 	if ( $comment_author_email )
  1305 		"SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = %s AND comment_approved != 'trash' AND ( comment_author = %s ",
   688 		$dupe .= $wpdb->prepare( "OR comment_author_email = %s ", wp_unslash( $comment_author_email ) );
  1306 		wp_unslash( $commentdata['comment_post_ID'] ),
   689 	$dupe .= $wpdb->prepare( ") AND comment_content = %s LIMIT 1", wp_unslash( $comment_content ) );
  1307 		wp_unslash( $commentdata['comment_parent'] ),
   690 	if ( $wpdb->get_var($dupe) ) {
  1308 		wp_unslash( $commentdata['comment_author'] )
       
  1309 	);
       
  1310 	if ( $commentdata['comment_author_email'] ) {
       
  1311 		$dupe .= $wpdb->prepare(
       
  1312 			"OR comment_author_email = %s ",
       
  1313 			wp_unslash( $commentdata['comment_author_email'] )
       
  1314 		);
       
  1315 	}
       
  1316 	$dupe .= $wpdb->prepare(
       
  1317 		") AND comment_content = %s LIMIT 1",
       
  1318 		wp_unslash( $commentdata['comment_content'] )
       
  1319 	);
       
  1320 	if ( $wpdb->get_var( $dupe ) ) {
       
  1321 		/**
       
  1322 		 * Fires immediately after a duplicate comment is detected.
       
  1323 		 *
       
  1324 		 * @since 3.0.0
       
  1325 		 *
       
  1326 		 * @param array $commentdata Comment data.
       
  1327 		 */
   691 		do_action( 'comment_duplicate_trigger', $commentdata );
  1328 		do_action( 'comment_duplicate_trigger', $commentdata );
   692 		if ( defined('DOING_AJAX') )
  1329 		if ( defined( 'DOING_AJAX' ) ) {
   693 			die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
  1330 			die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
   694 
  1331 		}
   695 		wp_die( __('Duplicate comment detected; it looks as though you&#8217;ve already said that!') );
  1332 		wp_die( __( 'Duplicate comment detected; it looks as though you&#8217;ve already said that!' ), 409 );
   696 	}
  1333 	}
   697 
  1334 
   698 	do_action( 'check_comment_flood', $comment_author_IP, $comment_author_email, $comment_date_gmt );
  1335 	/**
   699 
  1336 	 * Fires immediately before a comment is marked approved.
   700 	if ( ! empty( $user_id ) ) {
  1337 	 *
   701 		$user = get_userdata( $user_id );
  1338 	 * Allows checking for comment flooding.
   702 		$post_author = $wpdb->get_var($wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1", $comment_post_ID));
  1339 	 *
   703 	}
  1340 	 * @since 2.3.0
   704 
  1341 	 *
   705 	if ( isset( $user ) && ( $user_id == $post_author || $user->has_cap( 'moderate_comments' ) ) ) {
  1342 	 * @param string $comment_author_IP    Comment author's IP address.
       
  1343 	 * @param string $comment_author_email Comment author's email.
       
  1344 	 * @param string $comment_date_gmt     GMT date the comment was posted.
       
  1345 	 */
       
  1346 	do_action(
       
  1347 		'check_comment_flood',
       
  1348 		$commentdata['comment_author_IP'],
       
  1349 		$commentdata['comment_author_email'],
       
  1350 		$commentdata['comment_date_gmt']
       
  1351 	);
       
  1352 
       
  1353 	if ( ! empty( $commentdata['user_id'] ) ) {
       
  1354 		$user = get_userdata( $commentdata['user_id'] );
       
  1355 		$post_author = $wpdb->get_var( $wpdb->prepare(
       
  1356 			"SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1",
       
  1357 			$commentdata['comment_post_ID']
       
  1358 		) );
       
  1359 	}
       
  1360 
       
  1361 	if ( isset( $user ) && ( $commentdata['user_id'] == $post_author || $user->has_cap( 'moderate_comments' ) ) ) {
   706 		// The author and the admins get respect.
  1362 		// The author and the admins get respect.
   707 		$approved = 1;
  1363 		$approved = 1;
   708 	 } else {
  1364 	} else {
   709 		// Everyone else's comments will be checked.
  1365 		// Everyone else's comments will be checked.
   710 		if ( check_comment($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent, $comment_type) )
  1366 		if ( check_comment(
       
  1367 			$commentdata['comment_author'],
       
  1368 			$commentdata['comment_author_email'],
       
  1369 			$commentdata['comment_author_url'],
       
  1370 			$commentdata['comment_content'],
       
  1371 			$commentdata['comment_author_IP'],
       
  1372 			$commentdata['comment_agent'],
       
  1373 			$commentdata['comment_type']
       
  1374 		) ) {
   711 			$approved = 1;
  1375 			$approved = 1;
   712 		else
  1376 		} else {
   713 			$approved = 0;
  1377 			$approved = 0;
   714 		if ( wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent) )
  1378 		}
       
  1379 
       
  1380 		if ( wp_blacklist_check(
       
  1381 			$commentdata['comment_author'],
       
  1382 			$commentdata['comment_author_email'],
       
  1383 			$commentdata['comment_author_url'],
       
  1384 			$commentdata['comment_content'],
       
  1385 			$commentdata['comment_author_IP'],
       
  1386 			$commentdata['comment_agent']
       
  1387 		) ) {
   715 			$approved = 'spam';
  1388 			$approved = 'spam';
   716 	}
  1389 		}
   717 
  1390 	}
       
  1391 
       
  1392 	/**
       
  1393 	 * Filter a comment's approval status before it is set.
       
  1394 	 *
       
  1395 	 * @since 2.1.0
       
  1396 	 *
       
  1397 	 * @param bool|string $approved    The approval status. Accepts 1, 0, or 'spam'.
       
  1398 	 * @param array       $commentdata Comment data.
       
  1399 	 */
   718 	$approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );
  1400 	$approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );
   719 	return $approved;
  1401 	return $approved;
   720 }
  1402 }
   721 
  1403 
   722 /**
  1404 /**
   724  *
  1406  *
   725  * Won't run, if current user can manage options, so to not block
  1407  * Won't run, if current user can manage options, so to not block
   726  * administrators.
  1408  * administrators.
   727  *
  1409  *
   728  * @since 2.3.0
  1410  * @since 2.3.0
   729  * @uses $wpdb
  1411  *
   730  * @uses apply_filters() Calls 'comment_flood_filter' filter with first
  1412  * @global wpdb $wpdb WordPress database abstraction object.
   731  *		parameter false, last comment timestamp, new comment timestamp.
       
   732  * @uses do_action() Calls 'comment_flood_trigger' action with parameters with
       
   733  *		last comment timestamp and new comment timestamp.
       
   734  *
  1413  *
   735  * @param string $ip Comment IP.
  1414  * @param string $ip Comment IP.
   736  * @param string $email Comment author email address.
  1415  * @param string $email Comment author email address.
   737  * @param string $date MySQL time string.
  1416  * @param string $date MySQL time string.
   738  */
  1417  */
   742 		return; // don't throttle admins
  1421 		return; // don't throttle admins
   743 	$hour_ago = gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS );
  1422 	$hour_ago = gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS );
   744 	if ( $lasttime = $wpdb->get_var( $wpdb->prepare( "SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( `comment_author_IP` = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1", $hour_ago, $ip, $email ) ) ) {
  1423 	if ( $lasttime = $wpdb->get_var( $wpdb->prepare( "SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( `comment_author_IP` = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1", $hour_ago, $ip, $email ) ) ) {
   745 		$time_lastcomment = mysql2date('U', $lasttime, false);
  1424 		$time_lastcomment = mysql2date('U', $lasttime, false);
   746 		$time_newcomment  = mysql2date('U', $date, false);
  1425 		$time_newcomment  = mysql2date('U', $date, false);
   747 		$flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment);
  1426 		/**
       
  1427 		 * Filter the comment flood status.
       
  1428 		 *
       
  1429 		 * @since 2.1.0
       
  1430 		 *
       
  1431 		 * @param bool $bool             Whether a comment flood is occurring. Default false.
       
  1432 		 * @param int  $time_lastcomment Timestamp of when the last comment was posted.
       
  1433 		 * @param int  $time_newcomment  Timestamp of when the new comment was posted.
       
  1434 		 */
       
  1435 		$flood_die = apply_filters( 'comment_flood_filter', false, $time_lastcomment, $time_newcomment );
   748 		if ( $flood_die ) {
  1436 		if ( $flood_die ) {
   749 			do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment);
  1437 			/**
       
  1438 			 * Fires before the comment flood message is triggered.
       
  1439 			 *
       
  1440 			 * @since 1.5.0
       
  1441 			 *
       
  1442 			 * @param int $time_lastcomment Timestamp of when the last comment was posted.
       
  1443 			 * @param int $time_newcomment  Timestamp of when the new comment was posted.
       
  1444 			 */
       
  1445 			do_action( 'comment_flood_trigger', $time_lastcomment, $time_newcomment );
   750 
  1446 
   751 			if ( defined('DOING_AJAX') )
  1447 			if ( defined('DOING_AJAX') )
   752 				die( __('You are posting comments too quickly. Slow down.') );
  1448 				die( __('You are posting comments too quickly. Slow down.') );
   753 
  1449 
   754 			wp_die( __('You are posting comments too quickly. Slow down.'), '', array('response' => 403) );
  1450 			wp_die( __( 'You are posting comments too quickly. Slow down.' ), 429 );
   755 		}
  1451 		}
   756 	}
  1452 	}
   757 }
  1453 }
   758 
  1454 
   759 /**
  1455 /**
   781 
  1477 
   782 /**
  1478 /**
   783  * Calculate the total number of comment pages.
  1479  * Calculate the total number of comment pages.
   784  *
  1480  *
   785  * @since 2.7.0
  1481  * @since 2.7.0
   786  * @uses get_query_var() Used to fill in the default for $per_page parameter.
  1482  *
   787  * @uses get_option() Used to fill in defaults for parameters.
       
   788  * @uses Walker_Comment
  1483  * @uses Walker_Comment
   789  *
  1484  *
   790  * @param array $comments Optional array of comment objects. Defaults to $wp_query->comments
  1485  * @param array $comments Optional array of comment objects. Defaults to $wp_query->comments
   791  * @param int $per_page Optional comments per page.
  1486  * @param int $per_page Optional comments per page.
   792  * @param boolean $threaded Optional control over flat or threaded comments.
  1487  * @param boolean $threaded Optional control over flat or threaded comments.
   796 	global $wp_query;
  1491 	global $wp_query;
   797 
  1492 
   798 	if ( null === $comments && null === $per_page && null === $threaded && !empty($wp_query->max_num_comment_pages) )
  1493 	if ( null === $comments && null === $per_page && null === $threaded && !empty($wp_query->max_num_comment_pages) )
   799 		return $wp_query->max_num_comment_pages;
  1494 		return $wp_query->max_num_comment_pages;
   800 
  1495 
   801 	if ( !$comments || !is_array($comments) )
  1496 	if ( ( ! $comments || ! is_array( $comments ) ) && ! empty( $wp_query->comments )  )
   802 		$comments = $wp_query->comments;
  1497 		$comments = $wp_query->comments;
   803 
  1498 
   804 	if ( empty($comments) )
  1499 	if ( empty($comments) )
   805 		return 0;
  1500 		return 0;
   806 
  1501 
   829 
  1524 
   830 /**
  1525 /**
   831  * Calculate what page number a comment will appear on for comment paging.
  1526  * Calculate what page number a comment will appear on for comment paging.
   832  *
  1527  *
   833  * @since 2.7.0
  1528  * @since 2.7.0
   834  * @uses get_comment() Gets the full comment of the $comment_ID parameter.
       
   835  * @uses get_option() Get various settings to control function and defaults.
       
   836  * @uses get_page_of_comment() Used to loop up to top level comment.
       
   837  *
  1529  *
   838  * @param int $comment_ID Comment ID.
  1530  * @param int $comment_ID Comment ID.
   839  * @param array $args Optional args.
  1531  * @param array $args Optional args.
   840  * @return int|null Comment page number or null on error.
  1532  * @return int|null Comment page number or null on error.
   841  */
  1533  */
   889 
  1581 
   890 /**
  1582 /**
   891  * Does comment contain blacklisted characters or words.
  1583  * Does comment contain blacklisted characters or words.
   892  *
  1584  *
   893  * @since 1.5.0
  1585  * @since 1.5.0
   894  * @uses do_action() Calls 'wp_blacklist_check' hook for all parameters.
       
   895  *
  1586  *
   896  * @param string $author The author of the comment
  1587  * @param string $author The author of the comment
   897  * @param string $email The email of the comment
  1588  * @param string $email The email of the comment
   898  * @param string $url The url used in the comment
  1589  * @param string $url The url used in the comment
   899  * @param string $comment The comment content
  1590  * @param string $comment The comment content
   900  * @param string $user_ip The comment author IP address
  1591  * @param string $user_ip The comment author IP address
   901  * @param string $user_agent The author's browser user agent
  1592  * @param string $user_agent The author's browser user agent
   902  * @return bool True if comment contains blacklisted content, false if comment does not
  1593  * @return bool True if comment contains blacklisted content, false if comment does not
   903  */
  1594  */
   904 function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_agent) {
  1595 function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_agent) {
   905 	do_action('wp_blacklist_check', $author, $email, $url, $comment, $user_ip, $user_agent);
  1596 	/**
       
  1597 	 * Fires before the comment is tested for blacklisted characters or words.
       
  1598 	 *
       
  1599 	 * @since 1.5.0
       
  1600 	 *
       
  1601 	 * @param string $author     Comment author.
       
  1602 	 * @param string $email      Comment author's email.
       
  1603 	 * @param string $url        Comment author's URL.
       
  1604 	 * @param string $comment    Comment content.
       
  1605 	 * @param string $user_ip    Comment author's IP address.
       
  1606 	 * @param string $user_agent Comment author's browser user agent.
       
  1607 	 */
       
  1608 	do_action( 'wp_blacklist_check', $author, $email, $url, $comment, $user_ip, $user_agent );
   906 
  1609 
   907 	$mod_keys = trim( get_option('blacklist_keys') );
  1610 	$mod_keys = trim( get_option('blacklist_keys') );
   908 	if ( '' == $mod_keys )
  1611 	if ( '' == $mod_keys )
   909 		return false; // If moderation keys are empty
  1612 		return false; // If moderation keys are empty
   910 	$words = explode("\n", $mod_keys );
  1613 	$words = explode("\n", $mod_keys );
   952 function wp_count_comments( $post_id = 0 ) {
  1655 function wp_count_comments( $post_id = 0 ) {
   953 	global $wpdb;
  1656 	global $wpdb;
   954 
  1657 
   955 	$post_id = (int) $post_id;
  1658 	$post_id = (int) $post_id;
   956 
  1659 
   957 	$stats = apply_filters('wp_count_comments', array(), $post_id);
  1660 	/**
       
  1661 	 * Filter the comments count for a given post.
       
  1662 	 *
       
  1663 	 * @since 2.7.0
       
  1664 	 *
       
  1665 	 * @param array $count   An empty array.
       
  1666 	 * @param int   $post_id The post ID.
       
  1667 	 */
       
  1668 	$stats = apply_filters( 'wp_count_comments', array(), $post_id );
   958 	if ( !empty($stats) )
  1669 	if ( !empty($stats) )
   959 		return $stats;
  1670 		return $stats;
   960 
  1671 
   961 	$count = wp_cache_get("comments-{$post_id}", 'counts');
  1672 	$count = wp_cache_get("comments-{$post_id}", 'counts');
   962 
  1673 
   999  *
  1710  *
  1000  * The post comment count will be updated if the comment was approved and has a
  1711  * The post comment count will be updated if the comment was approved and has a
  1001  * post ID available.
  1712  * post ID available.
  1002  *
  1713  *
  1003  * @since 2.0.0
  1714  * @since 2.0.0
  1004  * @uses $wpdb
  1715  *
  1005  * @uses do_action() Calls 'delete_comment' hook on comment ID
  1716  * @global wpdb $wpdb WordPress database abstraction object.
  1006  * @uses do_action() Calls 'deleted_comment' hook on comment ID after deletion, on success
       
  1007  * @uses do_action() Calls 'wp_set_comment_status' hook on comment ID with 'delete' set for the second parameter
       
  1008  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
       
  1009  *
  1717  *
  1010  * @param int $comment_id Comment ID
  1718  * @param int $comment_id Comment ID
  1011  * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
  1719  * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.
  1012  * @return bool True on success, false on failure.
  1720  * @return bool True on success, false on failure.
  1013  */
  1721  */
  1017 		return false;
  1725 		return false;
  1018 
  1726 
  1019 	if ( !$force_delete && EMPTY_TRASH_DAYS && !in_array( wp_get_comment_status($comment_id), array( 'trash', 'spam' ) ) )
  1727 	if ( !$force_delete && EMPTY_TRASH_DAYS && !in_array( wp_get_comment_status($comment_id), array( 'trash', 'spam' ) ) )
  1020 		return wp_trash_comment($comment_id);
  1728 		return wp_trash_comment($comment_id);
  1021 
  1729 
  1022 	do_action('delete_comment', $comment_id);
  1730 	/**
       
  1731 	 * Fires immediately before a comment is deleted from the database.
       
  1732 	 *
       
  1733 	 * @since 1.2.0
       
  1734 	 *
       
  1735 	 * @param int $comment_id The comment ID.
       
  1736 	 */
       
  1737 	do_action( 'delete_comment', $comment_id );
  1023 
  1738 
  1024 	// Move children up a level.
  1739 	// Move children up a level.
  1025 	$children = $wpdb->get_col( $wpdb->prepare("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent = %d", $comment_id) );
  1740 	$children = $wpdb->get_col( $wpdb->prepare("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent = %d", $comment_id) );
  1026 	if ( !empty($children) ) {
  1741 	if ( !empty($children) ) {
  1027 		$wpdb->update($wpdb->comments, array('comment_parent' => $comment->comment_parent), array('comment_parent' => $comment_id));
  1742 		$wpdb->update($wpdb->comments, array('comment_parent' => $comment->comment_parent), array('comment_parent' => $comment_id));
  1033 	foreach ( $meta_ids as $mid )
  1748 	foreach ( $meta_ids as $mid )
  1034 		delete_metadata_by_mid( 'comment', $mid );
  1749 		delete_metadata_by_mid( 'comment', $mid );
  1035 
  1750 
  1036 	if ( ! $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $comment_id ) ) )
  1751 	if ( ! $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $comment_id ) ) )
  1037 		return false;
  1752 		return false;
  1038 	do_action('deleted_comment', $comment_id);
  1753 
       
  1754 	/**
       
  1755 	 * Fires immediately after a comment is deleted from the database.
       
  1756 	 *
       
  1757 	 * @since 2.9.0
       
  1758 	 *
       
  1759 	 * @param int $comment_id The comment ID.
       
  1760 	 */
       
  1761 	do_action( 'deleted_comment', $comment_id );
  1039 
  1762 
  1040 	$post_id = $comment->comment_post_ID;
  1763 	$post_id = $comment->comment_post_ID;
  1041 	if ( $post_id && $comment->comment_approved == 1 )
  1764 	if ( $post_id && $comment->comment_approved == 1 )
  1042 		wp_update_comment_count($post_id);
  1765 		wp_update_comment_count($post_id);
  1043 
  1766 
  1044 	clean_comment_cache($comment_id);
  1767 	clean_comment_cache($comment_id);
  1045 
  1768 
  1046 	do_action('wp_set_comment_status', $comment_id, 'delete');
  1769 	/** This action is documented in wp-includes/comment.php */
       
  1770 	do_action( 'wp_set_comment_status', $comment_id, 'delete' );
       
  1771 
  1047 	wp_transition_comment_status('delete', $comment->comment_approved, $comment);
  1772 	wp_transition_comment_status('delete', $comment->comment_approved, $comment);
  1048 	return true;
  1773 	return true;
  1049 }
  1774 }
  1050 
  1775 
  1051 /**
  1776 /**
  1052  * Moves a comment to the Trash
  1777  * Moves a comment to the Trash
  1053  *
  1778  *
  1054  * If trash is disabled, comment is permanently deleted.
  1779  * If trash is disabled, comment is permanently deleted.
  1055  *
  1780  *
  1056  * @since 2.9.0
  1781  * @since 2.9.0
  1057  * @uses do_action() on 'trash_comment' before trashing
       
  1058  * @uses do_action() on 'trashed_comment' after trashing
       
  1059  * @uses wp_delete_comment() if trash is disabled
       
  1060  *
  1782  *
  1061  * @param int $comment_id Comment ID.
  1783  * @param int $comment_id Comment ID.
  1062  * @return bool True on success, false on failure.
  1784  * @return bool True on success, false on failure.
  1063  */
  1785  */
  1064 function wp_trash_comment($comment_id) {
  1786 function wp_trash_comment($comment_id) {
  1066 		return wp_delete_comment($comment_id, true);
  1788 		return wp_delete_comment($comment_id, true);
  1067 
  1789 
  1068 	if ( !$comment = get_comment($comment_id) )
  1790 	if ( !$comment = get_comment($comment_id) )
  1069 		return false;
  1791 		return false;
  1070 
  1792 
  1071 	do_action('trash_comment', $comment_id);
  1793 	/**
       
  1794 	 * Fires immediately before a comment is sent to the Trash.
       
  1795 	 *
       
  1796 	 * @since 2.9.0
       
  1797 	 *
       
  1798 	 * @param int $comment_id The comment ID.
       
  1799 	 */
       
  1800 	do_action( 'trash_comment', $comment_id );
  1072 
  1801 
  1073 	if ( wp_set_comment_status($comment_id, 'trash') ) {
  1802 	if ( wp_set_comment_status($comment_id, 'trash') ) {
  1074 		add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved);
  1803 		add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved);
  1075 		add_comment_meta($comment_id, '_wp_trash_meta_time', time() );
  1804 		add_comment_meta($comment_id, '_wp_trash_meta_time', time() );
  1076 		do_action('trashed_comment', $comment_id);
  1805 
       
  1806 		/**
       
  1807 		 * Fires immediately after a comment is sent to Trash.
       
  1808 		 *
       
  1809 		 * @since 2.9.0
       
  1810 		 *
       
  1811 		 * @param int $comment_id The comment ID.
       
  1812 		 */
       
  1813 		do_action( 'trashed_comment', $comment_id );
  1077 		return true;
  1814 		return true;
  1078 	}
  1815 	}
  1079 
  1816 
  1080 	return false;
  1817 	return false;
  1081 }
  1818 }
  1082 
  1819 
  1083 /**
  1820 /**
  1084  * Removes a comment from the Trash
  1821  * Removes a comment from the Trash
  1085  *
  1822  *
  1086  * @since 2.9.0
  1823  * @since 2.9.0
  1087  * @uses do_action() on 'untrash_comment' before untrashing
       
  1088  * @uses do_action() on 'untrashed_comment' after untrashing
       
  1089  *
  1824  *
  1090  * @param int $comment_id Comment ID.
  1825  * @param int $comment_id Comment ID.
  1091  * @return bool True on success, false on failure.
  1826  * @return bool True on success, false on failure.
  1092  */
  1827  */
  1093 function wp_untrash_comment($comment_id) {
  1828 function wp_untrash_comment($comment_id) {
  1094 	if ( ! (int)$comment_id )
  1829 	if ( ! (int)$comment_id )
  1095 		return false;
  1830 		return false;
  1096 
  1831 
  1097 	do_action('untrash_comment', $comment_id);
  1832 	/**
       
  1833 	 * Fires immediately before a comment is restored from the Trash.
       
  1834 	 *
       
  1835 	 * @since 2.9.0
       
  1836 	 *
       
  1837 	 * @param int $comment_id The comment ID.
       
  1838 	 */
       
  1839 	do_action( 'untrash_comment', $comment_id );
  1098 
  1840 
  1099 	$status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true);
  1841 	$status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true);
  1100 	if ( empty($status) )
  1842 	if ( empty($status) )
  1101 		$status = '0';
  1843 		$status = '0';
  1102 
  1844 
  1103 	if ( wp_set_comment_status($comment_id, $status) ) {
  1845 	if ( wp_set_comment_status($comment_id, $status) ) {
  1104 		delete_comment_meta($comment_id, '_wp_trash_meta_time');
  1846 		delete_comment_meta($comment_id, '_wp_trash_meta_time');
  1105 		delete_comment_meta($comment_id, '_wp_trash_meta_status');
  1847 		delete_comment_meta($comment_id, '_wp_trash_meta_status');
  1106 		do_action('untrashed_comment', $comment_id);
  1848 		/**
       
  1849 		 * Fires immediately after a comment is restored from the Trash.
       
  1850 		 *
       
  1851 		 * @since 2.9.0
       
  1852 		 *
       
  1853 		 * @param int $comment_id The comment ID.
       
  1854 		 */
       
  1855 		do_action( 'untrashed_comment', $comment_id );
  1107 		return true;
  1856 		return true;
  1108 	}
  1857 	}
  1109 
  1858 
  1110 	return false;
  1859 	return false;
  1111 }
  1860 }
  1112 
  1861 
  1113 /**
  1862 /**
  1114  * Marks a comment as Spam
  1863  * Marks a comment as Spam
  1115  *
  1864  *
  1116  * @since 2.9.0
  1865  * @since 2.9.0
  1117  * @uses do_action() on 'spam_comment' before spamming
       
  1118  * @uses do_action() on 'spammed_comment' after spamming
       
  1119  *
  1866  *
  1120  * @param int $comment_id Comment ID.
  1867  * @param int $comment_id Comment ID.
  1121  * @return bool True on success, false on failure.
  1868  * @return bool True on success, false on failure.
  1122  */
  1869  */
  1123 function wp_spam_comment($comment_id) {
  1870 function wp_spam_comment($comment_id) {
  1124 	if ( !$comment = get_comment($comment_id) )
  1871 	if ( !$comment = get_comment($comment_id) )
  1125 		return false;
  1872 		return false;
  1126 
  1873 
  1127 	do_action('spam_comment', $comment_id);
  1874 	/**
       
  1875 	 * Fires immediately before a comment is marked as Spam.
       
  1876 	 *
       
  1877 	 * @since 2.9.0
       
  1878 	 *
       
  1879 	 * @param int $comment_id The comment ID.
       
  1880 	 */
       
  1881 	do_action( 'spam_comment', $comment_id );
  1128 
  1882 
  1129 	if ( wp_set_comment_status($comment_id, 'spam') ) {
  1883 	if ( wp_set_comment_status($comment_id, 'spam') ) {
  1130 		add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved);
  1884 		add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved);
  1131 		do_action('spammed_comment', $comment_id);
  1885 		/**
       
  1886 		 * Fires immediately after a comment is marked as Spam.
       
  1887 		 *
       
  1888 		 * @since 2.9.0
       
  1889 		 *
       
  1890 		 * @param int $comment_id The comment ID.
       
  1891 		 */
       
  1892 		do_action( 'spammed_comment', $comment_id );
  1132 		return true;
  1893 		return true;
  1133 	}
  1894 	}
  1134 
  1895 
  1135 	return false;
  1896 	return false;
  1136 }
  1897 }
  1137 
  1898 
  1138 /**
  1899 /**
  1139  * Removes a comment from the Spam
  1900  * Removes a comment from the Spam
  1140  *
  1901  *
  1141  * @since 2.9.0
  1902  * @since 2.9.0
  1142  * @uses do_action() on 'unspam_comment' before unspamming
       
  1143  * @uses do_action() on 'unspammed_comment' after unspamming
       
  1144  *
  1903  *
  1145  * @param int $comment_id Comment ID.
  1904  * @param int $comment_id Comment ID.
  1146  * @return bool True on success, false on failure.
  1905  * @return bool True on success, false on failure.
  1147  */
  1906  */
  1148 function wp_unspam_comment($comment_id) {
  1907 function wp_unspam_comment($comment_id) {
  1149 	if ( ! (int)$comment_id )
  1908 	if ( ! (int)$comment_id )
  1150 		return false;
  1909 		return false;
  1151 
  1910 
  1152 	do_action('unspam_comment', $comment_id);
  1911 	/**
       
  1912 	 * Fires immediately before a comment is unmarked as Spam.
       
  1913 	 *
       
  1914 	 * @since 2.9.0
       
  1915 	 *
       
  1916 	 * @param int $comment_id The comment ID.
       
  1917 	 */
       
  1918 	do_action( 'unspam_comment', $comment_id );
  1153 
  1919 
  1154 	$status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true);
  1920 	$status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true);
  1155 	if ( empty($status) )
  1921 	if ( empty($status) )
  1156 		$status = '0';
  1922 		$status = '0';
  1157 
  1923 
  1158 	if ( wp_set_comment_status($comment_id, $status) ) {
  1924 	if ( wp_set_comment_status($comment_id, $status) ) {
  1159 		delete_comment_meta($comment_id, '_wp_trash_meta_status');
  1925 		delete_comment_meta($comment_id, '_wp_trash_meta_status');
  1160 		do_action('unspammed_comment', $comment_id);
  1926 		/**
       
  1927 		 * Fires immediately after a comment is unmarked as Spam.
       
  1928 		 *
       
  1929 		 * @since 2.9.0
       
  1930 		 *
       
  1931 		 * @param int $comment_id The comment ID.
       
  1932 		 */
       
  1933 		do_action( 'unspammed_comment', $comment_id );
  1161 		return true;
  1934 		return true;
  1162 	}
  1935 	}
  1163 
  1936 
  1164 	return false;
  1937 	return false;
  1165 }
  1938 }
  1168  * The status of a comment by ID.
  1941  * The status of a comment by ID.
  1169  *
  1942  *
  1170  * @since 1.0.0
  1943  * @since 1.0.0
  1171  *
  1944  *
  1172  * @param int $comment_id Comment ID
  1945  * @param int $comment_id Comment ID
  1173  * @return string|bool Status might be 'trash', 'approved', 'unapproved', 'spam'. False on failure.
  1946  * @return false|string Status might be 'trash', 'approved', 'unapproved', 'spam'. False on failure.
  1174  */
  1947  */
  1175 function wp_get_comment_status($comment_id) {
  1948 function wp_get_comment_status($comment_id) {
  1176 	$comment = get_comment($comment_id);
  1949 	$comment = get_comment($comment_id);
  1177 	if ( !$comment )
  1950 	if ( !$comment )
  1178 		return false;
  1951 		return false;
  1212  * @param string $new_status New comment status.
  1985  * @param string $new_status New comment status.
  1213  * @param string $old_status Previous comment status.
  1986  * @param string $old_status Previous comment status.
  1214  * @param object $comment Comment data.
  1987  * @param object $comment Comment data.
  1215  */
  1988  */
  1216 function wp_transition_comment_status($new_status, $old_status, $comment) {
  1989 function wp_transition_comment_status($new_status, $old_status, $comment) {
  1217 	// Translate raw statuses to human readable formats for the hooks
  1990 	/*
  1218 	// This is not a complete list of comment status, it's only the ones that need to be renamed
  1991 	 * Translate raw statuses to human readable formats for the hooks.
       
  1992 	 * This is not a complete list of comment status, it's only the ones
       
  1993 	 * that need to be renamed
       
  1994 	 */
  1219 	$comment_statuses = array(
  1995 	$comment_statuses = array(
  1220 		0         => 'unapproved',
  1996 		0         => 'unapproved',
  1221 		'hold'    => 'unapproved', // wp_set_comment_status() uses "hold"
  1997 		'hold'    => 'unapproved', // wp_set_comment_status() uses "hold"
  1222 		1         => 'approved',
  1998 		1         => 'approved',
  1223 		'approve' => 'approved', // wp_set_comment_status() uses "approve"
  1999 		'approve' => 'approved', // wp_set_comment_status() uses "approve"
  1225 	if ( isset($comment_statuses[$new_status]) ) $new_status = $comment_statuses[$new_status];
  2001 	if ( isset($comment_statuses[$new_status]) ) $new_status = $comment_statuses[$new_status];
  1226 	if ( isset($comment_statuses[$old_status]) ) $old_status = $comment_statuses[$old_status];
  2002 	if ( isset($comment_statuses[$old_status]) ) $old_status = $comment_statuses[$old_status];
  1227 
  2003 
  1228 	// Call the hooks
  2004 	// Call the hooks
  1229 	if ( $new_status != $old_status ) {
  2005 	if ( $new_status != $old_status ) {
  1230 		do_action('transition_comment_status', $new_status, $old_status, $comment);
  2006 		/**
  1231 		do_action("comment_{$old_status}_to_{$new_status}", $comment);
  2007 		 * Fires when the comment status is in transition.
  1232 	}
  2008 		 *
  1233 	do_action("comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment);
  2009 		 * @since 2.7.0
       
  2010 		 *
       
  2011 		 * @param int|string $new_status The new comment status.
       
  2012 		 * @param int|string $old_status The old comment status.
       
  2013 		 * @param object     $comment    The comment data.
       
  2014 		 */
       
  2015 		do_action( 'transition_comment_status', $new_status, $old_status, $comment );
       
  2016 		/**
       
  2017 		 * Fires when the comment status is in transition from one specific status to another.
       
  2018 		 *
       
  2019 		 * The dynamic portions of the hook name, `$old_status`, and `$new_status`,
       
  2020 		 * refer to the old and new comment statuses, respectively.
       
  2021 		 *
       
  2022 		 * @since 2.7.0
       
  2023 		 *
       
  2024 		 * @param object $comment Comment object.
       
  2025 		 */
       
  2026 		do_action( "comment_{$old_status}_to_{$new_status}", $comment );
       
  2027 	}
       
  2028 	/**
       
  2029 	 * Fires when the status of a specific comment type is in transition.
       
  2030 	 *
       
  2031 	 * The dynamic portions of the hook name, `$new_status`, and `$comment->comment_type`,
       
  2032 	 * refer to the new comment status, and the type of comment, respectively.
       
  2033 	 *
       
  2034 	 * Typical comment types include an empty string (standard comment), 'pingback',
       
  2035 	 * or 'trackback'.
       
  2036 	 *
       
  2037 	 * @since 2.7.0
       
  2038 	 *
       
  2039 	 * @param int $comment_ID The comment ID.
       
  2040 	 * @param obj $comment    Comment object.
       
  2041 	 */
       
  2042 	do_action( "comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment );
  1234 }
  2043 }
  1235 
  2044 
  1236 /**
  2045 /**
  1237  * Get current commenter's name, email, and URL.
  2046  * Get current commenter's name, email, and URL.
  1238  *
  2047  *
  1258 
  2067 
  1259 	$comment_author_url = '';
  2068 	$comment_author_url = '';
  1260 	if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) )
  2069 	if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) )
  1261 		$comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH];
  2070 		$comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH];
  1262 
  2071 
  1263 	return apply_filters('wp_get_current_commenter', compact('comment_author', 'comment_author_email', 'comment_author_url'));
  2072 	/**
       
  2073 	 * Filter the current commenter's name, email, and URL.
       
  2074 	 *
       
  2075 	 * @since 3.1.0
       
  2076 	 *
       
  2077 	 * @param string $comment_author       Comment author's name.
       
  2078 	 * @param string $comment_author_email Comment author's email.
       
  2079 	 * @param string $comment_author_url   Comment author's URL.
       
  2080 	 */
       
  2081 	return apply_filters( 'wp_get_current_commenter', compact('comment_author', 'comment_author_email', 'comment_author_url') );
  1264 }
  2082 }
  1265 
  2083 
  1266 /**
  2084 /**
  1267  * Inserts a comment to the database.
  2085  * Inserts a comment to the database.
  1268  *
  2086  *
  1269  * The available comment data key names are 'comment_author_IP', 'comment_date',
  2087  * The available comment data key names are 'comment_author_IP', 'comment_date',
  1270  * 'comment_date_gmt', 'comment_parent', 'comment_approved', and 'user_id'.
  2088  * 'comment_date_gmt', 'comment_parent', 'comment_approved', and 'user_id'.
  1271  *
  2089  *
  1272  * @since 2.0.0
  2090  * @since 2.0.0
  1273  * @uses $wpdb
  2091  *
       
  2092  * @global wpdb $wpdb WordPress database abstraction object.
  1274  *
  2093  *
  1275  * @param array $commentdata Contains information on the comment.
  2094  * @param array $commentdata Contains information on the comment.
  1276  * @return int The new comment's ID.
  2095  * @return int|bool The new comment's ID on success, false on failure.
  1277  */
  2096  */
  1278 function wp_insert_comment($commentdata) {
  2097 function wp_insert_comment( $commentdata ) {
  1279 	global $wpdb;
  2098 	global $wpdb;
  1280 	extract(wp_unslash($commentdata), EXTR_SKIP);
  2099 	$data = wp_unslash( $commentdata );
  1281 
  2100 
  1282 	if ( ! isset($comment_author_IP) )
  2101 	$comment_author       = ! isset( $data['comment_author'] )       ? '' : $data['comment_author'];
  1283 		$comment_author_IP = '';
  2102 	$comment_author_email = ! isset( $data['comment_author_email'] ) ? '' : $data['comment_author_email'];
  1284 	if ( ! isset($comment_date) )
  2103 	$comment_author_url   = ! isset( $data['comment_author_url'] )   ? '' : $data['comment_author_url'];
  1285 		$comment_date = current_time('mysql');
  2104 	$comment_author_IP    = ! isset( $data['comment_author_IP'] )    ? '' : $data['comment_author_IP'];
  1286 	if ( ! isset($comment_date_gmt) )
  2105 
  1287 		$comment_date_gmt = get_gmt_from_date($comment_date);
  2106 	$comment_date     = ! isset( $data['comment_date'] )     ? current_time( 'mysql' )            : $data['comment_date'];
  1288 	if ( ! isset($comment_parent) )
  2107 	$comment_date_gmt = ! isset( $data['comment_date_gmt'] ) ? get_gmt_from_date( $comment_date ) : $data['comment_date_gmt'];
  1289 		$comment_parent = 0;
  2108 
  1290 	if ( ! isset($comment_approved) )
  2109 	$comment_post_ID  = ! isset( $data['comment_post_ID'] )  ? '' : $data['comment_post_ID'];
  1291 		$comment_approved = 1;
  2110 	$comment_content  = ! isset( $data['comment_content'] )  ? '' : $data['comment_content'];
  1292 	if ( ! isset($comment_karma) )
  2111 	$comment_karma    = ! isset( $data['comment_karma'] )    ? 0  : $data['comment_karma'];
  1293 		$comment_karma = 0;
  2112 	$comment_approved = ! isset( $data['comment_approved'] ) ? 1  : $data['comment_approved'];
  1294 	if ( ! isset($user_id) )
  2113 	$comment_agent    = ! isset( $data['comment_agent'] )    ? '' : $data['comment_agent'];
  1295 		$user_id = 0;
  2114 	$comment_type     = ! isset( $data['comment_type'] )     ? '' : $data['comment_type'];
  1296 	if ( ! isset($comment_type) )
  2115 	$comment_parent   = ! isset( $data['comment_parent'] )   ? 0  : $data['comment_parent'];
  1297 		$comment_type = '';
  2116 
  1298 
  2117 	$user_id  = ! isset( $data['user_id'] ) ? 0 : $data['user_id'];
  1299 	$data = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_karma', 'comment_approved', 'comment_agent', 'comment_type', 'comment_parent', 'user_id');
  2118 
  1300 	$wpdb->insert($wpdb->comments, $data);
  2119 	$compacted = compact( 'comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_karma', 'comment_approved', 'comment_agent', 'comment_type', 'comment_parent', 'user_id' );
       
  2120 	if ( ! $wpdb->insert( $wpdb->comments, $compacted ) ) {
       
  2121 		return false;
       
  2122 	}
  1301 
  2123 
  1302 	$id = (int) $wpdb->insert_id;
  2124 	$id = (int) $wpdb->insert_id;
  1303 
  2125 
  1304 	if ( $comment_approved == 1 )
  2126 	if ( $comment_approved == 1 ) {
  1305 		wp_update_comment_count($comment_post_ID);
  2127 		wp_update_comment_count( $comment_post_ID );
  1306 
  2128 	}
  1307 	$comment = get_comment($id);
  2129 	$comment = get_comment( $id );
  1308 	do_action('wp_insert_comment', $id, $comment);
  2130 
       
  2131 	/**
       
  2132 	 * Fires immediately after a comment is inserted into the database.
       
  2133 	 *
       
  2134 	 * @since 2.8.0
       
  2135 	 *
       
  2136 	 * @param int $id      The comment ID.
       
  2137 	 * @param obj $comment Comment object.
       
  2138 	 */
       
  2139 	do_action( 'wp_insert_comment', $id, $comment );
  1309 
  2140 
  1310 	wp_cache_set( 'last_changed', microtime(), 'comment' );
  2141 	wp_cache_set( 'last_changed', microtime(), 'comment' );
  1311 
  2142 
  1312 	return $id;
  2143 	return $id;
  1313 }
  2144 }
  1318  * Sets the comment data 'filtered' field to true when finished. This can be
  2149  * Sets the comment data 'filtered' field to true when finished. This can be
  1319  * checked as to whether the comment should be filtered and to keep from
  2150  * checked as to whether the comment should be filtered and to keep from
  1320  * filtering the same comment more than once.
  2151  * filtering the same comment more than once.
  1321  *
  2152  *
  1322  * @since 2.0.0
  2153  * @since 2.0.0
  1323  * @uses apply_filters() Calls 'pre_user_id' hook on comment author's user ID
       
  1324  * @uses apply_filters() Calls 'pre_comment_user_agent' hook on comment author's user agent
       
  1325  * @uses apply_filters() Calls 'pre_comment_author_name' hook on comment author's name
       
  1326  * @uses apply_filters() Calls 'pre_comment_content' hook on the comment's content
       
  1327  * @uses apply_filters() Calls 'pre_comment_user_ip' hook on comment author's IP
       
  1328  * @uses apply_filters() Calls 'pre_comment_author_url' hook on comment author's URL
       
  1329  * @uses apply_filters() Calls 'pre_comment_author_email' hook on comment author's email address
       
  1330  *
  2154  *
  1331  * @param array $commentdata Contains information on the comment.
  2155  * @param array $commentdata Contains information on the comment.
  1332  * @return array Parsed comment information.
  2156  * @return array Parsed comment information.
  1333  */
  2157  */
  1334 function wp_filter_comment($commentdata) {
  2158 function wp_filter_comment($commentdata) {
  1335 	if ( isset($commentdata['user_ID']) )
  2159 	if ( isset( $commentdata['user_ID'] ) ) {
  1336 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_ID']);
  2160 		/**
  1337 	elseif ( isset($commentdata['user_id']) )
  2161 		 * Filter the comment author's user id before it is set.
  1338 		$commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_id']);
  2162 		 *
  1339 	$commentdata['comment_agent']        = apply_filters('pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) );
  2163 		 * The first time this filter is evaluated, 'user_ID' is checked
  1340 	$commentdata['comment_author']       = apply_filters('pre_comment_author_name', $commentdata['comment_author']);
  2164 		 * (for back-compat), followed by the standard 'user_id' value.
  1341 	$commentdata['comment_content']      = apply_filters('pre_comment_content', $commentdata['comment_content']);
  2165 		 *
  1342 	$commentdata['comment_author_IP']    = apply_filters('pre_comment_user_ip', $commentdata['comment_author_IP']);
  2166 		 * @since 1.5.0
  1343 	$commentdata['comment_author_url']   = apply_filters('pre_comment_author_url', $commentdata['comment_author_url']);
  2167 		 *
  1344 	$commentdata['comment_author_email'] = apply_filters('pre_comment_author_email', $commentdata['comment_author_email']);
  2168 		 * @param int $user_ID The comment author's user ID.
       
  2169 		 */
       
  2170 		$commentdata['user_id'] = apply_filters( 'pre_user_id', $commentdata['user_ID'] );
       
  2171 	} elseif ( isset( $commentdata['user_id'] ) ) {
       
  2172 		/** This filter is documented in wp-includes/comment.php */
       
  2173 		$commentdata['user_id'] = apply_filters( 'pre_user_id', $commentdata['user_id'] );
       
  2174 	}
       
  2175 
       
  2176 	/**
       
  2177 	 * Filter the comment author's browser user agent before it is set.
       
  2178 	 *
       
  2179 	 * @since 1.5.0
       
  2180 	 *
       
  2181 	 * @param int $comment_agent The comment author's browser user agent.
       
  2182 	 */
       
  2183 	$commentdata['comment_agent'] = apply_filters( 'pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) );
       
  2184 	/** This filter is documented in wp-includes/comment.php */
       
  2185 	$commentdata['comment_author'] = apply_filters( 'pre_comment_author_name', $commentdata['comment_author'] );
       
  2186 	/**
       
  2187 	 * Filter the comment content before it is set.
       
  2188 	 *
       
  2189 	 * @since 1.5.0
       
  2190 	 *
       
  2191 	 * @param int $comment_content The comment content.
       
  2192 	 */
       
  2193 	$commentdata['comment_content'] = apply_filters( 'pre_comment_content', $commentdata['comment_content'] );
       
  2194 	/**
       
  2195 	 * Filter the comment author's IP before it is set.
       
  2196 	 *
       
  2197 	 * @since 1.5.0
       
  2198 	 *
       
  2199 	 * @param int $comment_author_ip The comment author's IP.
       
  2200 	 */
       
  2201 	$commentdata['comment_author_IP'] = apply_filters( 'pre_comment_user_ip', $commentdata['comment_author_IP'] );
       
  2202 	/** This filter is documented in wp-includes/comment.php */
       
  2203 	$commentdata['comment_author_url'] = apply_filters( 'pre_comment_author_url', $commentdata['comment_author_url'] );
       
  2204 	/** This filter is documented in wp-includes/comment.php */
       
  2205 	$commentdata['comment_author_email'] = apply_filters( 'pre_comment_author_email', $commentdata['comment_author_email'] );
  1345 	$commentdata['filtered'] = true;
  2206 	$commentdata['filtered'] = true;
  1346 	return $commentdata;
  2207 	return $commentdata;
  1347 }
  2208 }
  1348 
  2209 
  1349 /**
  2210 /**
  1350  * Whether comment should be blocked because of comment flood.
  2211  * Whether a comment should be blocked because of comment flood.
  1351  *
  2212  *
  1352  * @since 2.1.0
  2213  * @since 2.1.0
  1353  *
  2214  *
  1354  * @param bool $block Whether plugin has already blocked comment.
  2215  * @param bool $block Whether plugin has already blocked comment.
  1355  * @param int $time_lastcomment Timestamp for last comment.
  2216  * @param int $time_lastcomment Timestamp for last comment.
  1372  * and whether comment is approved by WordPress. Also has 'preprocess_comment'
  2233  * and whether comment is approved by WordPress. Also has 'preprocess_comment'
  1373  * filter for processing the comment data before the function handles it.
  2234  * filter for processing the comment data before the function handles it.
  1374  *
  2235  *
  1375  * We use REMOTE_ADDR here directly. If you are behind a proxy, you should ensure
  2236  * We use REMOTE_ADDR here directly. If you are behind a proxy, you should ensure
  1376  * that it is properly set, such as in wp-config.php, for your environment.
  2237  * that it is properly set, such as in wp-config.php, for your environment.
  1377  * See {@link http://core.trac.wordpress.org/ticket/9235}
  2238  * See {@link https://core.trac.wordpress.org/ticket/9235}
  1378  *
  2239  *
  1379  * @since 1.5.0
  2240  * @since 1.5.0
  1380  * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing
       
  1381  * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved.
       
  1382  * @uses wp_filter_comment() Used to filter comment before adding comment.
       
  1383  * @uses wp_allow_comment() checks to see if comment is approved.
       
  1384  * @uses wp_insert_comment() Does the actual comment insertion to the database.
       
  1385  *
       
  1386  * @param array $commentdata Contains information on the comment.
  2241  * @param array $commentdata Contains information on the comment.
  1387  * @return int The ID of the comment after adding.
  2242  * @return int|bool The ID of the comment on success, false on failure.
  1388  */
  2243  */
  1389 function wp_new_comment( $commentdata ) {
  2244 function wp_new_comment( $commentdata ) {
  1390 	$commentdata = apply_filters('preprocess_comment', $commentdata);
  2245 	global $wpdb;
       
  2246 
       
  2247 	if ( isset( $commentdata['user_ID'] ) ) {
       
  2248 		$commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID'];
       
  2249 	}
       
  2250 
       
  2251 	$prefiltered_user_id = ( isset( $commentdata['user_id'] ) ) ? (int) $commentdata['user_id'] : 0;
       
  2252 
       
  2253 	/**
       
  2254 	 * Filter a comment's data before it is sanitized and inserted into the database.
       
  2255 	 *
       
  2256 	 * @since 1.5.0
       
  2257 	 *
       
  2258 	 * @param array $commentdata Comment data.
       
  2259 	 */
       
  2260 	$commentdata = apply_filters( 'preprocess_comment', $commentdata );
  1391 
  2261 
  1392 	$commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID'];
  2262 	$commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID'];
  1393 	if ( isset($commentdata['user_ID']) )
  2263 	if ( isset( $commentdata['user_ID'] ) && $prefiltered_user_id !== (int) $commentdata['user_ID'] ) {
  1394 		$commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID'];
  2264 		$commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID'];
  1395 	elseif ( isset($commentdata['user_id']) )
  2265 	} elseif ( isset( $commentdata['user_id'] ) ) {
  1396 		$commentdata['user_id'] = (int) $commentdata['user_id'];
  2266 		$commentdata['user_id'] = (int) $commentdata['user_id'];
       
  2267 	}
  1397 
  2268 
  1398 	$commentdata['comment_parent'] = isset($commentdata['comment_parent']) ? absint($commentdata['comment_parent']) : 0;
  2269 	$commentdata['comment_parent'] = isset($commentdata['comment_parent']) ? absint($commentdata['comment_parent']) : 0;
  1399 	$parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status($commentdata['comment_parent']) : '';
  2270 	$parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status($commentdata['comment_parent']) : '';
  1400 	$commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0;
  2271 	$commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0;
  1401 
  2272 
  1402 	$commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '',$_SERVER['REMOTE_ADDR'] );
  2273 	$commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '',$_SERVER['REMOTE_ADDR'] );
  1403 	$commentdata['comment_agent']     = isset( $_SERVER['HTTP_USER_AGENT'] ) ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : '';
  2274 	$commentdata['comment_agent']     = isset( $_SERVER['HTTP_USER_AGENT'] ) ? substr( $_SERVER['HTTP_USER_AGENT'], 0, 254 ) : '';
  1404 
  2275 
  1405 	$commentdata['comment_date']     = current_time('mysql');
  2276 	if ( empty( $commentdata['comment_date'] ) ) {
  1406 	$commentdata['comment_date_gmt'] = current_time('mysql', 1);
  2277 		$commentdata['comment_date'] = current_time('mysql');
       
  2278 	}
       
  2279 
       
  2280 	if ( empty( $commentdata['comment_date_gmt'] ) ) {
       
  2281 		$commentdata['comment_date_gmt'] = current_time( 'mysql', 1 );
       
  2282 	}
  1407 
  2283 
  1408 	$commentdata = wp_filter_comment($commentdata);
  2284 	$commentdata = wp_filter_comment($commentdata);
  1409 
  2285 
  1410 	$commentdata['comment_approved'] = wp_allow_comment($commentdata);
  2286 	$commentdata['comment_approved'] = wp_allow_comment($commentdata);
  1411 
  2287 
  1412 	$comment_ID = wp_insert_comment($commentdata);
  2288 	$comment_ID = wp_insert_comment($commentdata);
  1413 
  2289 	if ( ! $comment_ID ) {
  1414 	do_action('comment_post', $comment_ID, $commentdata['comment_approved']);
  2290 		$fields = array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content' );
       
  2291 
       
  2292 		foreach( $fields as $field ) {
       
  2293 			if ( isset( $commentdata[ $field ] ) ) {
       
  2294 				$commentdata[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->comments, $field, $commentdata[ $field ] );
       
  2295 			}
       
  2296 		}
       
  2297 
       
  2298 		$commentdata = wp_filter_comment( $commentdata );
       
  2299 
       
  2300 		$commentdata['comment_approved'] = wp_allow_comment( $commentdata );
       
  2301 
       
  2302 		$comment_ID = wp_insert_comment( $commentdata );
       
  2303 		if ( ! $comment_ID ) {
       
  2304 			return false;
       
  2305 		}
       
  2306 	}
       
  2307 
       
  2308 	/**
       
  2309 	 * Fires immediately after a comment is inserted into the database.
       
  2310 	 *
       
  2311 	 * @since 1.2.0
       
  2312 	 *
       
  2313 	 * @param int $comment_ID       The comment ID.
       
  2314 	 * @param int $comment_approved 1 (true) if the comment is approved, 0 (false) if not.
       
  2315 	 */
       
  2316 	do_action( 'comment_post', $comment_ID, $commentdata['comment_approved'] );
  1415 
  2317 
  1416 	if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching
  2318 	if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching
  1417 		if ( '0' == $commentdata['comment_approved'] )
  2319 		if ( '0' == $commentdata['comment_approved'] ) {
  1418 			wp_notify_moderator($comment_ID);
  2320 			wp_notify_moderator( $comment_ID );
  1419 
  2321 		}
  1420 		$post = get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment
  2322 
  1421 
  2323 		// wp_notify_postauthor() checks if notifying the author of their own comment.
  1422 		if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) )
  2324 		// By default, it won't, but filters can override this.
  1423 			wp_notify_postauthor($comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' );
  2325 		if ( get_option( 'comments_notify' ) && $commentdata['comment_approved'] ) {
       
  2326 			wp_notify_postauthor( $comment_ID );
       
  2327 		}
  1424 	}
  2328 	}
  1425 
  2329 
  1426 	return $comment_ID;
  2330 	return $comment_ID;
  1427 }
  2331 }
  1428 
  2332 
  1431  *
  2335  *
  1432  * The 'wp_set_comment_status' action is called after the comment is handled.
  2336  * The 'wp_set_comment_status' action is called after the comment is handled.
  1433  * If the comment status is not in the list, then false is returned.
  2337  * If the comment status is not in the list, then false is returned.
  1434  *
  2338  *
  1435  * @since 1.0.0
  2339  * @since 1.0.0
  1436  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
       
  1437  *
  2340  *
  1438  * @param int $comment_id Comment ID.
  2341  * @param int $comment_id Comment ID.
  1439  * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.
  2342  * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.
  1440  * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false.
  2343  * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false.
  1441  * @return bool|WP_Error True on success, false or WP_Error on failure.
  2344  * @return bool|WP_Error True on success, false or WP_Error on failure.
  1442  */
  2345  */
  1443 function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) {
  2346 function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) {
  1444 	global $wpdb;
  2347 	global $wpdb;
  1445 
  2348 
  1446 	$status = '0';
       
  1447 	switch ( $comment_status ) {
  2349 	switch ( $comment_status ) {
  1448 		case 'hold':
  2350 		case 'hold':
  1449 		case '0':
  2351 		case '0':
  1450 			$status = '0';
  2352 			$status = '0';
  1451 			break;
  2353 			break;
  1452 		case 'approve':
  2354 		case 'approve':
  1453 		case '1':
  2355 		case '1':
  1454 			$status = '1';
  2356 			$status = '1';
  1455 			if ( get_option('comments_notify') ) {
  2357 			if ( get_option('comments_notify') ) {
  1456 				$comment = get_comment($comment_id);
  2358 				wp_notify_postauthor( $comment_id );
  1457 				wp_notify_postauthor($comment_id, $comment->comment_type);
       
  1458 			}
  2359 			}
  1459 			break;
  2360 			break;
  1460 		case 'spam':
  2361 		case 'spam':
  1461 			$status = 'spam';
  2362 			$status = 'spam';
  1462 			break;
  2363 			break;
  1478 
  2379 
  1479 	clean_comment_cache($comment_id);
  2380 	clean_comment_cache($comment_id);
  1480 
  2381 
  1481 	$comment = get_comment($comment_id);
  2382 	$comment = get_comment($comment_id);
  1482 
  2383 
  1483 	do_action('wp_set_comment_status', $comment_id, $comment_status);
  2384 	/**
       
  2385 	 * Fires immediately before transitioning a comment's status from one to another
       
  2386 	 * in the database.
       
  2387 	 *
       
  2388 	 * @since 1.5.0
       
  2389 	 *
       
  2390 	 * @param int         $comment_id     Comment ID.
       
  2391 	 * @param string|bool $comment_status Current comment status. Possible values include
       
  2392 	 *                                    'hold', 'approve', 'spam', 'trash', or false.
       
  2393 	 */
       
  2394 	do_action( 'wp_set_comment_status', $comment_id, $comment_status );
       
  2395 
  1484 	wp_transition_comment_status($comment_status, $comment_old->comment_approved, $comment);
  2396 	wp_transition_comment_status($comment_status, $comment_old->comment_approved, $comment);
  1485 
  2397 
  1486 	wp_update_comment_count($comment->comment_post_ID);
  2398 	wp_update_comment_count($comment->comment_post_ID);
  1487 
  2399 
  1488 	return true;
  2400 	return true;
  1492  * Updates an existing comment in the database.
  2404  * Updates an existing comment in the database.
  1493  *
  2405  *
  1494  * Filters the comment and makes sure certain fields are valid before updating.
  2406  * Filters the comment and makes sure certain fields are valid before updating.
  1495  *
  2407  *
  1496  * @since 2.0.0
  2408  * @since 2.0.0
  1497  * @uses $wpdb
  2409  *
  1498  * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object
  2410  * @global wpdb $wpdb WordPress database abstraction object.
  1499  *
  2411  *
  1500  * @param array $commentarr Contains information on the comment.
  2412  * @param array $commentarr Contains information on the comment.
  1501  * @return int Comment was updated if value is 1, or was not updated if value is 0.
  2413  * @return int Comment was updated if value is 1, or was not updated if value is 0.
  1502  */
  2414  */
  1503 function wp_update_comment($commentarr) {
  2415 function wp_update_comment($commentarr) {
  1504 	global $wpdb;
  2416 	global $wpdb;
  1505 
  2417 
  1506 	// First, get all of the original fields
  2418 	// First, get all of the original fields
  1507 	$comment = get_comment($commentarr['comment_ID'], ARRAY_A);
  2419 	$comment = get_comment($commentarr['comment_ID'], ARRAY_A);
  1508 	if ( empty( $comment ) )
  2420 	if ( empty( $comment ) ) {
  1509 		return 0;
  2421 		return 0;
       
  2422 	}
       
  2423 
       
  2424 	// Make sure that the comment post ID is valid (if specified).
       
  2425 	if ( isset( $commentarr['comment_post_ID'] ) && ! get_post( $commentarr['comment_post_ID'] ) ) {
       
  2426 		return 0;
       
  2427 	}
  1510 
  2428 
  1511 	// Escape data pulled from DB.
  2429 	// Escape data pulled from DB.
  1512 	$comment = wp_slash($comment);
  2430 	$comment = wp_slash($comment);
  1513 
  2431 
  1514 	$old_status = $comment['comment_approved'];
  2432 	$old_status = $comment['comment_approved'];
  1517 	$commentarr = array_merge($comment, $commentarr);
  2435 	$commentarr = array_merge($comment, $commentarr);
  1518 
  2436 
  1519 	$commentarr = wp_filter_comment( $commentarr );
  2437 	$commentarr = wp_filter_comment( $commentarr );
  1520 
  2438 
  1521 	// Now extract the merged array.
  2439 	// Now extract the merged array.
  1522 	extract(wp_unslash($commentarr), EXTR_SKIP);
  2440 	$data = wp_unslash( $commentarr );
  1523 
  2441 
  1524 	$comment_content = apply_filters('comment_save_pre', $comment_content);
  2442 	/**
  1525 
  2443 	 * Filter the comment content before it is updated in the database.
  1526 	$comment_date_gmt = get_gmt_from_date($comment_date);
  2444 	 *
  1527 
  2445 	 * @since 1.5.0
  1528 	if ( !isset($comment_approved) )
  2446 	 *
  1529 		$comment_approved = 1;
  2447 	 * @param string $comment_content The comment data.
  1530 	else if ( 'hold' == $comment_approved )
  2448 	 */
  1531 		$comment_approved = 0;
  2449 	$data['comment_content'] = apply_filters( 'comment_save_pre', $data['comment_content'] );
  1532 	else if ( 'approve' == $comment_approved )
  2450 
  1533 		$comment_approved = 1;
  2451 	$data['comment_date_gmt'] = get_gmt_from_date( $data['comment_date'] );
  1534 
  2452 
  1535 	$data = compact( 'comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt', 'comment_parent' );
  2453 	if ( ! isset( $data['comment_approved'] ) ) {
       
  2454 		$data['comment_approved'] = 1;
       
  2455 	} elseif ( 'hold' == $data['comment_approved'] ) {
       
  2456 		$data['comment_approved'] = 0;
       
  2457 	} elseif ( 'approve' == $data['comment_approved'] ) {
       
  2458 		$data['comment_approved'] = 1;
       
  2459 	}
       
  2460 
       
  2461 	$comment_ID = $data['comment_ID'];
       
  2462 	$comment_post_ID = $data['comment_post_ID'];
       
  2463 	$keys = array( 'comment_post_ID', 'comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt', 'comment_type', 'comment_parent', 'user_id' );
       
  2464 	$data = wp_array_slice_assoc( $data, $keys );
  1536 	$rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) );
  2465 	$rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) );
  1537 
  2466 
  1538 	clean_comment_cache($comment_ID);
  2467 	clean_comment_cache( $comment_ID );
  1539 	wp_update_comment_count($comment_post_ID);
  2468 	wp_update_comment_count( $comment_post_ID );
  1540 	do_action('edit_comment', $comment_ID);
  2469 	/**
       
  2470 	 * Fires immediately after a comment is updated in the database.
       
  2471 	 *
       
  2472 	 * The hook also fires immediately before comment status transition hooks are fired.
       
  2473 	 *
       
  2474 	 * @since 1.2.0
       
  2475 	 *
       
  2476 	 * @param int $comment_ID The comment ID.
       
  2477 	 */
       
  2478 	do_action( 'edit_comment', $comment_ID );
  1541 	$comment = get_comment($comment_ID);
  2479 	$comment = get_comment($comment_ID);
  1542 	wp_transition_comment_status($comment->comment_approved, $old_status, $comment);
  2480 	wp_transition_comment_status($comment->comment_approved, $old_status, $comment);
  1543 	return $rval;
  2481 	return $rval;
  1544 }
  2482 }
  1545 
  2483 
  1553  *
  2491  *
  1554  * @since 2.5.0
  2492  * @since 2.5.0
  1555  * @staticvar bool $_defer
  2493  * @staticvar bool $_defer
  1556  *
  2494  *
  1557  * @param bool $defer
  2495  * @param bool $defer
  1558  * @return unknown
  2496  * @return bool
  1559  */
  2497  */
  1560 function wp_defer_comment_counting($defer=null) {
  2498 function wp_defer_comment_counting($defer=null) {
  1561 	static $_defer = false;
  2499 	static $_defer = false;
  1562 
  2500 
  1563 	if ( is_bool($defer) ) {
  2501 	if ( is_bool($defer) ) {
  1584  * @since 2.1.0
  2522  * @since 2.1.0
  1585  * @see wp_update_comment_count_now() For what could cause a false return value
  2523  * @see wp_update_comment_count_now() For what could cause a false return value
  1586  *
  2524  *
  1587  * @param int $post_id Post ID
  2525  * @param int $post_id Post ID
  1588  * @param bool $do_deferred Whether to process previously deferred post comment counts
  2526  * @param bool $do_deferred Whether to process previously deferred post comment counts
  1589  * @return bool True on success, false on failure
  2527  * @return bool|null True on success, false on failure
  1590  */
  2528  */
  1591 function wp_update_comment_count($post_id, $do_deferred=false) {
  2529 function wp_update_comment_count($post_id, $do_deferred=false) {
  1592 	static $_deferred = array();
  2530 	static $_deferred = array();
  1593 
  2531 
  1594 	if ( $do_deferred ) {
  2532 	if ( $do_deferred ) {
  1611 
  2549 
  1612 /**
  2550 /**
  1613  * Updates the comment count for the post.
  2551  * Updates the comment count for the post.
  1614  *
  2552  *
  1615  * @since 2.5.0
  2553  * @since 2.5.0
  1616  * @uses $wpdb
  2554  *
  1617  * @uses do_action() Calls 'wp_update_comment_count' hook on $post_id, $new, and $old
  2555  * @global wpdb $wpdb WordPress database abstraction object.
  1618  * @uses do_action() Calls 'edit_posts' hook on $post_id and $post
       
  1619  *
  2556  *
  1620  * @param int $post_id Post ID
  2557  * @param int $post_id Post ID
  1621  * @return bool True on success, false on '0' $post_id or if post with ID does not exist.
  2558  * @return bool True on success, false on '0' $post_id or if post with ID does not exist.
  1622  */
  2559  */
  1623 function wp_update_comment_count_now($post_id) {
  2560 function wp_update_comment_count_now($post_id) {
  1632 	$new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) );
  2569 	$new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) );
  1633 	$wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
  2570 	$wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) );
  1634 
  2571 
  1635 	clean_post_cache( $post );
  2572 	clean_post_cache( $post );
  1636 
  2573 
  1637 	do_action('wp_update_comment_count', $post_id, $new, $old);
  2574 	/**
  1638 	do_action('edit_post', $post_id, $post);
  2575 	 * Fires immediately after a post's comment count is updated in the database.
       
  2576 	 *
       
  2577 	 * @since 2.3.0
       
  2578 	 *
       
  2579 	 * @param int $post_id Post ID.
       
  2580 	 * @param int $new     The new comment count.
       
  2581 	 * @param int $old     The old comment count.
       
  2582 	 */
       
  2583 	do_action( 'wp_update_comment_count', $post_id, $new, $old );
       
  2584 	/** This action is documented in wp-includes/post.php */
       
  2585 	do_action( 'edit_post', $post_id, $post );
  1639 
  2586 
  1640 	return true;
  2587 	return true;
  1641 }
  2588 }
  1642 
  2589 
  1643 //
  2590 //
  1653  *
  2600  *
  1654  * @since 1.5.0
  2601  * @since 1.5.0
  1655  *
  2602  *
  1656  * @param string $url URL to ping.
  2603  * @param string $url URL to ping.
  1657  * @param int $deprecated Not Used.
  2604  * @param int $deprecated Not Used.
  1658  * @return bool|string False on failure, string containing URI on success.
  2605  * @return false|string False on failure, string containing URI on success.
  1659  */
  2606  */
  1660 function discover_pingback_server_uri( $url, $deprecated = '' ) {
  2607 function discover_pingback_server_uri( $url, $deprecated = '' ) {
  1661 	if ( !empty( $deprecated ) )
  2608 	if ( !empty( $deprecated ) )
  1662 		_deprecated_argument( __FUNCTION__, '2.7' );
  2609 		_deprecated_argument( __FUNCTION__, '2.7' );
  1663 
  2610 
  1717 
  2664 
  1718 /**
  2665 /**
  1719  * Perform all pingbacks, enclosures, trackbacks, and send to pingback services.
  2666  * Perform all pingbacks, enclosures, trackbacks, and send to pingback services.
  1720  *
  2667  *
  1721  * @since 2.1.0
  2668  * @since 2.1.0
  1722  * @uses $wpdb
  2669  *
       
  2670  * @global wpdb $wpdb WordPress database abstraction object.
  1723  */
  2671  */
  1724 function do_all_pings() {
  2672 function do_all_pings() {
  1725 	global $wpdb;
  2673 	global $wpdb;
  1726 
  2674 
  1727 	// Do pingbacks
  2675 	// Do pingbacks
  1748 
  2696 
  1749 /**
  2697 /**
  1750  * Perform trackbacks.
  2698  * Perform trackbacks.
  1751  *
  2699  *
  1752  * @since 1.5.0
  2700  * @since 1.5.0
  1753  * @uses $wpdb
  2701  *
       
  2702  * @global wpdb $wpdb WordPress database abstraction object.
  1754  *
  2703  *
  1755  * @param int $post_id Post ID to do trackbacks on.
  2704  * @param int $post_id Post ID to do trackbacks on.
  1756  */
  2705  */
  1757 function do_trackbacks($post_id) {
  2706 function do_trackbacks($post_id) {
  1758 	global $wpdb;
  2707 	global $wpdb;
  1763 	if ( empty($to_ping) ) {
  2712 	if ( empty($to_ping) ) {
  1764 		$wpdb->update($wpdb->posts, array('to_ping' => ''), array('ID' => $post_id) );
  2713 		$wpdb->update($wpdb->posts, array('to_ping' => ''), array('ID' => $post_id) );
  1765 		return;
  2714 		return;
  1766 	}
  2715 	}
  1767 
  2716 
  1768 	if ( empty($post->post_excerpt) )
  2717 	if ( empty($post->post_excerpt) ) {
  1769 		$excerpt = apply_filters('the_content', $post->post_content, $post->ID);
  2718 		/** This filter is documented in wp-includes/post-template.php */
  1770 	else
  2719 		$excerpt = apply_filters( 'the_content', $post->post_content, $post->ID );
  1771 		$excerpt = apply_filters('the_excerpt', $post->post_excerpt);
  2720 	} else {
       
  2721 		/** This filter is documented in wp-includes/post-template.php */
       
  2722 		$excerpt = apply_filters( 'the_excerpt', $post->post_excerpt );
       
  2723 	}
       
  2724 
  1772 	$excerpt = str_replace(']]>', ']]&gt;', $excerpt);
  2725 	$excerpt = str_replace(']]>', ']]&gt;', $excerpt);
  1773 	$excerpt = wp_html_excerpt($excerpt, 252, '&#8230;');
  2726 	$excerpt = wp_html_excerpt($excerpt, 252, '&#8230;');
  1774 
  2727 
  1775 	/** This filter is documented in wp-includes/post-template.php */
  2728 	/** This filter is documented in wp-includes/post-template.php */
  1776 	$post_title = apply_filters('the_title', $post->post_title, $post->ID);
  2729 	$post_title = apply_filters( 'the_title', $post->post_title, $post->ID );
  1777 	$post_title = strip_tags($post_title);
  2730 	$post_title = strip_tags($post_title);
  1778 
  2731 
  1779 	if ( $to_ping ) {
  2732 	if ( $to_ping ) {
  1780 		foreach ( (array) $to_ping as $tb_ping ) {
  2733 		foreach ( (array) $to_ping as $tb_ping ) {
  1781 			$tb_ping = trim($tb_ping);
  2734 			$tb_ping = trim($tb_ping);
  1792 /**
  2745 /**
  1793  * Sends pings to all of the ping site services.
  2746  * Sends pings to all of the ping site services.
  1794  *
  2747  *
  1795  * @since 1.2.0
  2748  * @since 1.2.0
  1796  *
  2749  *
  1797  * @param int $post_id Post ID. Not actually used.
  2750  * @param int $post_id Post ID.
  1798  * @return int Same as Post ID from parameter
  2751  * @return int Same as Post ID from parameter
  1799  */
  2752  */
  1800 function generic_ping($post_id = 0) {
  2753 function generic_ping( $post_id = 0 ) {
  1801 	$services = get_option('ping_sites');
  2754 	$services = get_option('ping_sites');
  1802 
  2755 
  1803 	$services = explode("\n", $services);
  2756 	$services = explode("\n", $services);
  1804 	foreach ( (array) $services as $service ) {
  2757 	foreach ( (array) $services as $service ) {
  1805 		$service = trim($service);
  2758 		$service = trim($service);
  1813 /**
  2766 /**
  1814  * Pings back the links found in a post.
  2767  * Pings back the links found in a post.
  1815  *
  2768  *
  1816  * @since 0.71
  2769  * @since 0.71
  1817  * @uses $wp_version
  2770  * @uses $wp_version
  1818  * @uses IXR_Client
       
  1819  *
  2771  *
  1820  * @param string $content Post content to check for links.
  2772  * @param string $content Post content to check for links.
  1821  * @param int $post_ID Post ID.
  2773  * @param int $post_ID Post ID.
  1822  */
  2774  */
  1823 function pingback($content, $post_ID) {
  2775 function pingback($content, $post_ID) {
  1854 			}
  2806 			}
  1855 		endif;
  2807 		endif;
  1856 	endforeach;
  2808 	endforeach;
  1857 
  2809 
  1858 	$post_links = array_unique( $post_links );
  2810 	$post_links = array_unique( $post_links );
       
  2811 	/**
       
  2812 	 * Fires just before pinging back links found in a post.
       
  2813 	 *
       
  2814 	 * @since 2.0.0
       
  2815 	 *
       
  2816 	 * @param array &$post_links An array of post links to be checked, passed by reference.
       
  2817 	 * @param array &$pung       Whether a link has already been pinged, passed by reference.
       
  2818 	 * @param int   $post_ID     The post ID.
       
  2819 	 */
  1859 	do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post_ID ) );
  2820 	do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post_ID ) );
  1860 
  2821 
  1861 	foreach ( (array) $post_links as $pagelinkedto ) {
  2822 	foreach ( (array) $post_links as $pagelinkedto ) {
  1862 		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
  2823 		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
  1863 
  2824 
  1864 		if ( $pingback_server_url ) {
  2825 		if ( $pingback_server_url ) {
  1865 			@ set_time_limit( 60 );
  2826 			@ set_time_limit( 60 );
  1866 			 // Now, the RPC call
  2827 			// Now, the RPC call
  1867 			$pagelinkedfrom = get_permalink($post_ID);
  2828 			$pagelinkedfrom = get_permalink($post_ID);
  1868 
  2829 
  1869 			// using a timeout of 3 seconds should be enough to cover slow servers
  2830 			// using a timeout of 3 seconds should be enough to cover slow servers
  1870 			$client = new WP_HTTP_IXR_Client($pingback_server_url);
  2831 			$client = new WP_HTTP_IXR_Client($pingback_server_url);
  1871 			$client->timeout = 3;
  2832 			$client->timeout = 3;
  1872 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom);
  2833 			/**
       
  2834 			 * Filter the user agent sent when pinging-back a URL.
       
  2835 			 *
       
  2836 			 * @since 2.9.0
       
  2837 			 *
       
  2838 			 * @param string $concat_useragent    The user agent concatenated with ' -- WordPress/'
       
  2839 			 *                                    and the WordPress version.
       
  2840 			 * @param string $useragent           The useragent.
       
  2841 			 * @param string $pingback_server_url The server URL being linked to.
       
  2842 			 * @param string $pagelinkedto        URL of page linked to.
       
  2843 			 * @param string $pagelinkedfrom      URL of page linked from.
       
  2844 			 */
       
  2845 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom );
  1873 			// when set to true, this outputs debug messages by itself
  2846 			// when set to true, this outputs debug messages by itself
  1874 			$client->debug = false;
  2847 			$client->debug = false;
  1875 
  2848 
  1876 			if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto) || ( isset($client->error->code) && 48 == $client->error->code ) ) // Already registered
  2849 			if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto) || ( isset($client->error->code) && 48 == $client->error->code ) ) // Already registered
  1877 				add_ping( $post_ID, $pagelinkedto );
  2850 				add_ping( $post_ID, $pagelinkedto );
  1898  * Send a Trackback.
  2871  * Send a Trackback.
  1899  *
  2872  *
  1900  * Updates database when sending trackback to prevent duplicates.
  2873  * Updates database when sending trackback to prevent duplicates.
  1901  *
  2874  *
  1902  * @since 0.71
  2875  * @since 0.71
  1903  * @uses $wpdb
  2876  *
       
  2877  * @global wpdb $wpdb WordPress database abstraction object.
  1904  *
  2878  *
  1905  * @param string $trackback_url URL to send trackbacks.
  2879  * @param string $trackback_url URL to send trackbacks.
  1906  * @param string $title Title of post.
  2880  * @param string $title Title of post.
  1907  * @param string $excerpt Excerpt of post.
  2881  * @param string $excerpt Excerpt of post.
  1908  * @param int $ID Post ID.
  2882  * @param int $ID Post ID.
  1935 /**
  2909 /**
  1936  * Send a pingback.
  2910  * Send a pingback.
  1937  *
  2911  *
  1938  * @since 1.2.0
  2912  * @since 1.2.0
  1939  * @uses $wp_version
  2913  * @uses $wp_version
  1940  * @uses IXR_Client
       
  1941  *
  2914  *
  1942  * @param string $server Host of blog to connect to.
  2915  * @param string $server Host of blog to connect to.
  1943  * @param string $path Path to send the ping.
  2916  * @param string $path Path to send the ping.
  1944  */
  2917  */
  1945 function weblog_ping($server = '', $path = '') {
  2918 function weblog_ping($server = '', $path = '') {
  1996 
  2969 
  1997 /**
  2970 /**
  1998  * Removes comment ID from the comment cache.
  2971  * Removes comment ID from the comment cache.
  1999  *
  2972  *
  2000  * @since 2.3.0
  2973  * @since 2.3.0
  2001  * @package WordPress
       
  2002  * @subpackage Cache
       
  2003  *
  2974  *
  2004  * @param int|array $ids Comment ID or array of comment IDs to remove from cache
  2975  * @param int|array $ids Comment ID or array of comment IDs to remove from cache
  2005  */
  2976  */
  2006 function clean_comment_cache($ids) {
  2977 function clean_comment_cache($ids) {
  2007 	foreach ( (array) $ids as $id )
  2978 	foreach ( (array) $ids as $id )
  2016  * Will add the comments in $comments to the cache. If comment ID already exists
  2987  * Will add the comments in $comments to the cache. If comment ID already exists
  2017  * in the comment cache then it will not be updated. The comment is added to the
  2988  * in the comment cache then it will not be updated. The comment is added to the
  2018  * cache using the comment group with the key using the ID of the comments.
  2989  * cache using the comment group with the key using the ID of the comments.
  2019  *
  2990  *
  2020  * @since 2.3.0
  2991  * @since 2.3.0
  2021  * @package WordPress
       
  2022  * @subpackage Cache
       
  2023  *
  2992  *
  2024  * @param array $comments Array of comment row objects
  2993  * @param array $comments Array of comment row objects
  2025  */
  2994  */
  2026 function update_comment_cache($comments) {
  2995 function update_comment_cache($comments) {
  2027 	foreach ( (array) $comments as $comment )
  2996 	foreach ( (array) $comments as $comment )
  2044  */
  3013  */
  2045 function _close_comments_for_old_posts( $posts, $query ) {
  3014 function _close_comments_for_old_posts( $posts, $query ) {
  2046 	if ( empty( $posts ) || ! $query->is_singular() || ! get_option( 'close_comments_for_old_posts' ) )
  3015 	if ( empty( $posts ) || ! $query->is_singular() || ! get_option( 'close_comments_for_old_posts' ) )
  2047 		return $posts;
  3016 		return $posts;
  2048 
  3017 
       
  3018 	/**
       
  3019 	 * Filter the list of post types to automatically close comments for.
       
  3020 	 *
       
  3021 	 * @since 3.2.0
       
  3022 	 *
       
  3023 	 * @param array $post_types An array of registered post types. Default array with 'post'.
       
  3024 	 */
  2049 	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
  3025 	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
  2050 	if ( ! in_array( $posts[0]->post_type, $post_types ) )
  3026 	if ( ! in_array( $posts[0]->post_type, $post_types ) )
  2051 		return $posts;
  3027 		return $posts;
  2052 
  3028 
  2053 	$days_old = (int) get_option( 'close_comments_days_old' );
  3029 	$days_old = (int) get_option( 'close_comments_days_old' );
  2083 	if ( !$days_old )
  3059 	if ( !$days_old )
  2084 		return $open;
  3060 		return $open;
  2085 
  3061 
  2086 	$post = get_post($post_id);
  3062 	$post = get_post($post_id);
  2087 
  3063 
       
  3064 	/** This filter is documented in wp-includes/comment.php */
  2088 	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
  3065 	$post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );
  2089 	if ( ! in_array( $post->post_type, $post_types ) )
  3066 	if ( ! in_array( $post->post_type, $post_types ) )
  2090 		return $open;
  3067 		return $open;
  2091 
  3068 
  2092 	if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * DAY_IN_SECONDS ) )
  3069 	if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * DAY_IN_SECONDS ) )