| [ Index ] |
PHP Cross Reference of WordPress (Trunk) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Manages WordPress comments 4 * 5 * @package WordPress 6 * @subpackage Comment 7 */ 8 9 /** 10 * Checks whether a comment passes internal checks to be allowed to add. 11 * 12 * If comment moderation is set in the administration, then all comments, 13 * regardless of their type and whitelist will be set to false. If the number of 14 * links exceeds the amount in the administration, then the check fails. If any 15 * of the parameter contents match the blacklist of words, then the check fails. 16 * 17 * If the number of links exceeds the amount in the administration, then the 18 * check fails. If any of the parameter contents match the blacklist of words, 19 * then the check fails. 20 * 21 * If the comment is a trackback and part of the blogroll, then the trackback is 22 * automatically whitelisted. If the comment author was approved before, then 23 * the comment is automatically whitelisted. 24 * 25 * If none of the checks fail, then the failback is to set the check to pass 26 * (return true). 27 * 28 * @since 1.2.0 29 * @uses $wpdb 30 * 31 * @param string $author Comment Author's name 32 * @param string $email Comment Author's email 33 * @param string $url Comment Author's URL 34 * @param string $comment Comment contents 35 * @param string $user_ip Comment Author's IP address 36 * @param string $user_agent Comment Author's User Agent 37 * @param string $comment_type Comment type, either user submitted comment, 38 * trackback, or pingback 39 * @return bool Whether the checks passed (true) and the comments should be 40 * displayed or set to moderated 41 */ 42 function check_comment($author, $email, $url, $comment, $user_ip, $user_agent, $comment_type) { 43 global $wpdb; 44 45 if ( 1 == get_option('comment_moderation') ) 46 return false; // If moderation is set to manual 47 48 // Check # of external links 49 if ( $max_links = get_option( 'comment_max_links' ) ) { 50 $num_links = preg_match_all( '/<a [^>]*href/i', apply_filters( 'comment_text', $comment ), $out ); 51 $num_links = apply_filters( 'comment_max_links_url', $num_links, $url ); // provide for counting of $url as a link 52 if ( $num_links >= $max_links ) 53 return false; 54 } 55 56 $mod_keys = trim(get_option('moderation_keys')); 57 if ( !empty($mod_keys) ) { 58 $words = explode("\n", $mod_keys ); 59 60 foreach ( (array) $words as $word) { 61 $word = trim($word); 62 63 // Skip empty lines 64 if ( empty($word) ) 65 continue; 66 67 // Do some escaping magic so that '#' chars in the 68 // spam words don't break things: 69 $word = preg_quote($word, '#'); 70 71 $pattern = "#$word#i"; 72 if ( preg_match($pattern, $author) ) return false; 73 if ( preg_match($pattern, $email) ) return false; 74 if ( preg_match($pattern, $url) ) return false; 75 if ( preg_match($pattern, $comment) ) return false; 76 if ( preg_match($pattern, $user_ip) ) return false; 77 if ( preg_match($pattern, $user_agent) ) return false; 78 } 79 } 80 81 // Comment whitelisting: 82 if ( 1 == get_option('comment_whitelist')) { 83 if ( 'trackback' == $comment_type || 'pingback' == $comment_type ) { // check if domain is in blogroll 84 $uri = parse_url($url); 85 $domain = $uri['host']; 86 $uri = parse_url( home_url() ); 87 $home_domain = $uri['host']; 88 if ( $wpdb->get_var($wpdb->prepare("SELECT link_id FROM $wpdb->links WHERE link_url LIKE (%s) LIMIT 1", '%'.$domain.'%')) || $domain == $home_domain ) 89 return true; 90 else 91 return false; 92 } elseif ( $author != '' && $email != '' ) { 93 // expected_slashed ($author, $email) 94 $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"); 95 if ( ( 1 == $ok_to_comment ) && 96 ( empty($mod_keys) || false === strpos( $email, $mod_keys) ) ) 97 return true; 98 else 99 return false; 100 } else { 101 return false; 102 } 103 } 104 return true; 105 } 106 107 /** 108 * Retrieve the approved comments for post $post_id. 109 * 110 * @since 2.0.0 111 * @uses $wpdb 112 * 113 * @param int $post_id The ID of the post 114 * @return array $comments The approved comments 115 */ 116 function get_approved_comments($post_id) { 117 global $wpdb; 118 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)); 119 } 120 121 /** 122 * Retrieves comment data given a comment ID or comment object. 123 * 124 * If an object is passed then the comment data will be cached and then returned 125 * after being passed through a filter. If the comment is empty, then the global 126 * comment variable will be used, if it is set. 127 * 128 * If the comment is empty, then the global comment variable will be used, if it 129 * is set. 130 * 131 * @since 2.0.0 132 * @uses $wpdb 133 * 134 * @param object|string|int $comment Comment to retrieve. 135 * @param string $output Optional. OBJECT or ARRAY_A or ARRAY_N constants. 136 * @return object|array|null Depends on $output value. 137 */ 138 function &get_comment(&$comment, $output = OBJECT) { 139 global $wpdb; 140 $null = null; 141 142 if ( empty($comment) ) { 143 if ( isset($GLOBALS['comment']) ) 144 $_comment = & $GLOBALS['comment']; 145 else 146 $_comment = null; 147 } elseif ( is_object($comment) ) { 148 wp_cache_add($comment->comment_ID, $comment, 'comment'); 149 $_comment = $comment; 150 } else { 151 if ( isset($GLOBALS['comment']) && ($GLOBALS['comment']->comment_ID == $comment) ) { 152 $_comment = & $GLOBALS['comment']; 153 } elseif ( ! $_comment = wp_cache_get($comment, 'comment') ) { 154 $_comment = $wpdb->get_row($wpdb->prepare("SELECT * FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment)); 155 if ( ! $_comment ) 156 return $null; 157 wp_cache_add($_comment->comment_ID, $_comment, 'comment'); 158 } 159 } 160 161 $_comment = apply_filters('get_comment', $_comment); 162 163 if ( $output == OBJECT ) { 164 return $_comment; 165 } elseif ( $output == ARRAY_A ) { 166 $__comment = get_object_vars($_comment); 167 return $__comment; 168 } elseif ( $output == ARRAY_N ) { 169 $__comment = array_values(get_object_vars($_comment)); 170 return $__comment; 171 } else { 172 return $_comment; 173 } 174 } 175 176 /** 177 * Retrieve a list of comments. 178 * 179 * The comment list can be for the blog as a whole or for an individual post. 180 * 181 * The list of comment arguments are 'status', 'orderby', 'comment_date_gmt', 182 * 'order', 'number', 'offset', and 'post_id'. 183 * 184 * @since 2.7.0 185 * @uses $wpdb 186 * 187 * @param mixed $args Optional. Array or string of options to override defaults. 188 * @return array List of comments. 189 */ 190 function get_comments( $args = '' ) { 191 global $wpdb; 192 193 $defaults = array( 194 'author_email' => '', 195 'ID' => '', 196 'karma' => '', 197 'number' => '', 198 'offset' => '', 199 'orderby' => '', 200 'order' => 'DESC', 201 'parent' => '', 202 'post_ID' => '', 203 'post_id' => 0, 204 'status' => '', 205 'type' => '', 206 'user_id' => '', 207 'search' => '', 208 'count' => false 209 ); 210 211 $args = wp_parse_args( $args, $defaults ); 212 extract( $args, EXTR_SKIP ); 213 214 // $args can be whatever, only use the args defined in defaults to compute the key 215 $key = md5( serialize( compact(array_keys($defaults)) ) ); 216 $last_changed = wp_cache_get('last_changed', 'comment'); 217 if ( !$last_changed ) { 218 $last_changed = time(); 219 wp_cache_set('last_changed', $last_changed, 'comment'); 220 } 221 $cache_key = "get_comments:$key:$last_changed"; 222 223 if ( $cache = wp_cache_get( $cache_key, 'comment' ) ) { 224 return $cache; 225 } 226 227 $post_id = absint($post_id); 228 229 if ( 'hold' == $status ) 230 $approved = "comment_approved = '0'"; 231 elseif ( 'approve' == $status ) 232 $approved = "comment_approved = '1'"; 233 elseif ( 'spam' == $status ) 234 $approved = "comment_approved = 'spam'"; 235 elseif ( 'trash' == $status ) 236 $approved = "comment_approved = 'trash'"; 237 else 238 $approved = "( comment_approved = '0' OR comment_approved = '1' )"; 239 240 $order = ( 'ASC' == strtoupper($order) ) ? 'ASC' : 'DESC'; 241 242 if ( ! empty( $orderby ) ) { 243 $ordersby = is_array($orderby) ? $orderby : preg_split('/[,\s]/', $orderby); 244 $ordersby = array_intersect( 245 $ordersby, 246 array( 247 'comment_agent', 248 'comment_approved', 249 'comment_author', 250 'comment_author_email', 251 'comment_author_IP', 252 'comment_author_url', 253 'comment_content', 254 'comment_date', 255 'comment_date_gmt', 256 'comment_ID', 257 'comment_karma', 258 'comment_parent', 259 'comment_post_ID', 260 'comment_type', 261 'user_id', 262 ) 263 ); 264 $orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby); 265 } else { 266 $orderby = 'comment_date_gmt'; 267 } 268 269 $number = absint($number); 270 $offset = absint($offset); 271 272 if ( !empty($number) ) { 273 if ( $offset ) 274 $limit = 'LIMIT ' . $offset . ',' . $number; 275 else 276 $limit = 'LIMIT ' . $number; 277 } else { 278 $limit = ''; 279 } 280 281 $post_where = "WHERE $approved"; 282 283 if ( ! empty($post_id) ) 284 $post_where .= $wpdb->prepare( ' AND comment_post_ID = %d', $post_id ); 285 if ( '' !== $author_email ) 286 $post_where .= $wpdb->prepare( 'AND comment_author_email = %s', $author_email ); 287 if ( '' !== $karma ) 288 $post_where .= $wpdb->prepare( 'AND comment_karma = %d', $karma ); 289 if ( 'comment' == $type ) 290 $post_where .= " AND comment_type = ''"; 291 elseif ( ! empty( $type ) ) 292 $post_where .= $wpdb->prepare( ' AND comment_type = %s', $type ); 293 if ( '' !== $parent ) 294 $post_where .= $wpdb->prepare( ' AND comment_parent = %d', $parent ); 295 if ( '' !== $user_id ) 296 $post_where .= $wpdb->prepare( ' AND user_id = %d', $user_id ); 297 if ( '' !== $search ) 298 $post_where .= _wp_search_sql($search, array('comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_content')); 299 300 if ( $count ) 301 return $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->comments $post_where ORDER BY $orderby $order $limit" ); 302 303 $comments = $wpdb->get_results( "SELECT * FROM $wpdb->comments $post_where ORDER BY $orderby $order $limit" ); 304 305 wp_cache_add( $cache_key, $comments, 'comment' ); 306 307 return $comments; 308 } 309 310 /** 311 * Retrieve all of the WordPress supported comment statuses. 312 * 313 * Comments have a limited set of valid status values, this provides the comment 314 * status values and descriptions. 315 * 316 * @package WordPress 317 * @subpackage Post 318 * @since 2.7.0 319 * 320 * @return array List of comment statuses. 321 */ 322 function get_comment_statuses( ) { 323 $status = array( 324 'hold' => __('Unapproved'), 325 /* translators: comment status */ 326 'approve' => _x('Approved', 'adjective'), 327 /* translators: comment status */ 328 'spam' => _x('Spam', 'adjective'), 329 ); 330 331 return $status; 332 } 333 334 335 /** 336 * The date the last comment was modified. 337 * 338 * @since 1.5.0 339 * @uses $wpdb 340 * @global array $cache_lastcommentmodified 341 * 342 * @param string $timezone Which timezone to use in reference to 'gmt', 'blog', 343 * or 'server' locations. 344 * @return string Last comment modified date. 345 */ 346 function get_lastcommentmodified($timezone = 'server') { 347 global $cache_lastcommentmodified, $wpdb; 348 349 if ( isset($cache_lastcommentmodified[$timezone]) ) 350 return $cache_lastcommentmodified[$timezone]; 351 352 $add_seconds_server = date('Z'); 353 354 switch ( strtolower($timezone)) { 355 case 'gmt': 356 $lastcommentmodified = $wpdb->get_var("SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); 357 break; 358 case 'blog': 359 $lastcommentmodified = $wpdb->get_var("SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1"); 360 break; 361 case 'server': 362 $lastcommentmodified = $wpdb->get_var($wpdb->prepare("SELECT DATE_ADD(comment_date_gmt, INTERVAL %s SECOND) FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1", $add_seconds_server)); 363 break; 364 } 365 366 $cache_lastcommentmodified[$timezone] = $lastcommentmodified; 367 368 return $lastcommentmodified; 369 } 370 371 /** 372 * The amount of comments in a post or total comments. 373 * 374 * A lot like {@link wp_count_comments()}, in that they both return comment 375 * stats (albeit with different types). The {@link wp_count_comments()} actual 376 * caches, but this function does not. 377 * 378 * @since 2.0.0 379 * @uses $wpdb 380 * 381 * @param int $post_id Optional. Comment amount in post if > 0, else total comments blog wide. 382 * @return array The amount of spam, approved, awaiting moderation, and total comments. 383 */ 384 function get_comment_count( $post_id = 0 ) { 385 global $wpdb; 386 387 $post_id = (int) $post_id; 388 389 $where = ''; 390 if ( $post_id > 0 ) { 391 $where = $wpdb->prepare("WHERE comment_post_ID = %d", $post_id); 392 } 393 394 $totals = (array) $wpdb->get_results(" 395 SELECT comment_approved, COUNT( * ) AS total 396 FROM {$wpdb->comments} 397 {$where} 398 GROUP BY comment_approved 399 ", ARRAY_A); 400 401 $comment_count = array( 402 "approved" => 0, 403 "awaiting_moderation" => 0, 404 "spam" => 0, 405 "total_comments" => 0 406 ); 407 408 foreach ( $totals as $row ) { 409 switch ( $row['comment_approved'] ) { 410 case 'spam': 411 $comment_count['spam'] = $row['total']; 412 $comment_count["total_comments"] += $row['total']; 413 break; 414 case 1: 415 $comment_count['approved'] = $row['total']; 416 $comment_count['total_comments'] += $row['total']; 417 break; 418 case 0: 419 $comment_count['awaiting_moderation'] = $row['total']; 420 $comment_count['total_comments'] += $row['total']; 421 break; 422 default: 423 break; 424 } 425 } 426 427 return $comment_count; 428 } 429 430 // 431 // Comment meta functions 432 // 433 434 /** 435 * Add meta data field to a comment. 436 * 437 * @since 2.9.0 438 * @uses add_metadata 439 * @link http://codex.wordpress.org/Function_Reference/add_comment_meta 440 * 441 * @param int $comment_id Comment ID. 442 * @param string $meta_key Metadata name. 443 * @param mixed $meta_value Metadata value. 444 * @param bool $unique Optional, default is false. Whether the same key should not be added. 445 * @return bool False for failure. True for success. 446 */ 447 function add_comment_meta($comment_id, $meta_key, $meta_value, $unique = false) { 448 return add_metadata('comment', $comment_id, $meta_key, $meta_value, $unique); 449 } 450 451 /** 452 * Remove metadata matching criteria from a comment. 453 * 454 * You can match based on the key, or key and value. Removing based on key and 455 * value, will keep from removing duplicate metadata with the same key. It also 456 * allows removing all metadata matching key, if needed. 457 * 458 * @since 2.9.0 459 * @uses delete_metadata 460 * @link http://codex.wordpress.org/Function_Reference/delete_comment_meta 461 * 462 * @param int $comment_id comment ID 463 * @param string $meta_key Metadata name. 464 * @param mixed $meta_value Optional. Metadata value. 465 * @return bool False for failure. True for success. 466 */ 467 function delete_comment_meta($comment_id, $meta_key, $meta_value = '') { 468 return delete_metadata('comment', $comment_id, $meta_key, $meta_value); 469 } 470 471 /** 472 * Retrieve comment meta field for a comment. 473 * 474 * @since 2.9.0 475 * @uses get_metadata 476 * @link http://codex.wordpress.org/Function_Reference/get_comment_meta 477 * 478 * @param int $comment_id Comment ID. 479 * @param string $key The meta key to retrieve. 480 * @param bool $single Whether to return a single value. 481 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single 482 * is true. 483 */ 484 function get_comment_meta($comment_id, $key, $single = false) { 485 return get_metadata('comment', $comment_id, $key, $single); 486 } 487 488 /** 489 * Update comment meta field based on comment ID. 490 * 491 * Use the $prev_value parameter to differentiate between meta fields with the 492 * same key and comment ID. 493 * 494 * If the meta field for the comment does not exist, it will be added. 495 * 496 * @since 2.9.0 497 * @uses update_metadata 498 * @link http://codex.wordpress.org/Function_Reference/update_comment_meta 499 * 500 * @param int $comment_id Comment ID. 501 * @param string $meta_key Metadata key. 502 * @param mixed $meta_value Metadata value. 503 * @param mixed $prev_value Optional. Previous value to check before removing. 504 * @return bool False on failure, true if success. 505 */ 506 function update_comment_meta($comment_id, $meta_key, $meta_value, $prev_value = '') { 507 return update_metadata('comment', $comment_id, $meta_key, $meta_value, $prev_value); 508 } 509 510 /** 511 * Sanitizes the cookies sent to the user already. 512 * 513 * Will only do anything if the cookies have already been created for the user. 514 * Mostly used after cookies had been sent to use elsewhere. 515 * 516 * @since 2.0.4 517 */ 518 function sanitize_comment_cookies() { 519 if ( isset($_COOKIE['comment_author_'.COOKIEHASH]) ) { 520 $comment_author = apply_filters('pre_comment_author_name', $_COOKIE['comment_author_'.COOKIEHASH]); 521 $comment_author = stripslashes($comment_author); 522 $comment_author = esc_attr($comment_author); 523 $_COOKIE['comment_author_'.COOKIEHASH] = $comment_author; 524 } 525 526 if ( isset($_COOKIE['comment_author_email_'.COOKIEHASH]) ) { 527 $comment_author_email = apply_filters('pre_comment_author_email', $_COOKIE['comment_author_email_'.COOKIEHASH]); 528 $comment_author_email = stripslashes($comment_author_email); 529 $comment_author_email = esc_attr($comment_author_email); 530 $_COOKIE['comment_author_email_'.COOKIEHASH] = $comment_author_email; 531 } 532 533 if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) ) { 534 $comment_author_url = apply_filters('pre_comment_author_url', $_COOKIE['comment_author_url_'.COOKIEHASH]); 535 $comment_author_url = stripslashes($comment_author_url); 536 $_COOKIE['comment_author_url_'.COOKIEHASH] = $comment_author_url; 537 } 538 } 539 540 /** 541 * Validates whether this comment is allowed to be made. 542 * 543 * @since 2.0.0 544 * @uses $wpdb 545 * @uses apply_filters() Calls 'pre_comment_approved' hook on the type of comment 546 * @uses apply_filters() Calls 'comment_duplicate_trigger' hook on commentdata. 547 * @uses do_action() Calls 'check_comment_flood' hook on $comment_author_IP, $comment_author_email, and $comment_date_gmt 548 * 549 * @param array $commentdata Contains information on the comment 550 * @return mixed Signifies the approval status (0|1|'spam') 551 */ 552 function wp_allow_comment($commentdata) { 553 global $wpdb; 554 extract($commentdata, EXTR_SKIP); 555 556 // Simple duplicate check 557 // expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content) 558 $dupe = "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = '$comment_post_ID' AND comment_approved != 'trash' AND ( comment_author = '$comment_author' "; 559 if ( $comment_author_email ) 560 $dupe .= "OR comment_author_email = '$comment_author_email' "; 561 $dupe .= ") AND comment_content = '$comment_content' LIMIT 1"; 562 if ( $wpdb->get_var($dupe) ) { 563 do_action( 'comment_duplicate_trigger', $commentdata ); 564 if ( defined('DOING_AJAX') ) 565 die( __('Duplicate comment detected; it looks as though you’ve already said that!') ); 566 567 wp_die( __('Duplicate comment detected; it looks as though you’ve already said that!') ); 568 } 569 570 do_action( 'check_comment_flood', $comment_author_IP, $comment_author_email, $comment_date_gmt ); 571 572 if ( isset($user_id) && $user_id) { 573 $userdata = get_userdata($user_id); 574 $user = new WP_User($user_id); 575 $post_author = $wpdb->get_var($wpdb->prepare("SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1", $comment_post_ID)); 576 } 577 578 if ( isset($userdata) && ( $user_id == $post_author || $user->has_cap('moderate_comments') ) ) { 579 // The author and the admins get respect. 580 $approved = 1; 581 } else { 582 // Everyone else's comments will be checked. 583 if ( check_comment($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent, $comment_type) ) 584 $approved = 1; 585 else 586 $approved = 0; 587 if ( wp_blacklist_check($comment_author, $comment_author_email, $comment_author_url, $comment_content, $comment_author_IP, $comment_agent) ) 588 $approved = 'spam'; 589 } 590 591 $approved = apply_filters( 'pre_comment_approved', $approved, $commentdata ); 592 return $approved; 593 } 594 595 /** 596 * Check whether comment flooding is occurring. 597 * 598 * Won't run, if current user can manage options, so to not block 599 * administrators. 600 * 601 * @since 2.3.0 602 * @uses $wpdb 603 * @uses apply_filters() Calls 'comment_flood_filter' filter with first 604 * parameter false, last comment timestamp, new comment timestamp. 605 * @uses do_action() Calls 'comment_flood_trigger' action with parameters with 606 * last comment timestamp and new comment timestamp. 607 * 608 * @param string $ip Comment IP. 609 * @param string $email Comment author email address. 610 * @param string $date MySQL time string. 611 */ 612 function check_comment_flood_db( $ip, $email, $date ) { 613 global $wpdb; 614 if ( current_user_can( 'manage_options' ) ) 615 return; // don't throttle admins 616 $hour_ago = gmdate( 'Y-m-d H:i:s', time() - 3600 ); 617 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 ) ) ) { 618 $time_lastcomment = mysql2date('U', $lasttime, false); 619 $time_newcomment = mysql2date('U', $date, false); 620 $flood_die = apply_filters('comment_flood_filter', false, $time_lastcomment, $time_newcomment); 621 if ( $flood_die ) { 622 do_action('comment_flood_trigger', $time_lastcomment, $time_newcomment); 623 624 if ( defined('DOING_AJAX') ) 625 die( __('You are posting comments too quickly. Slow down.') ); 626 627 wp_die( __('You are posting comments too quickly. Slow down.'), '', array('response' => 403) ); 628 } 629 } 630 } 631 632 /** 633 * Separates an array of comments into an array keyed by comment_type. 634 * 635 * @since 2.7.0 636 * 637 * @param array $comments Array of comments 638 * @return array Array of comments keyed by comment_type. 639 */ 640 function &separate_comments(&$comments) { 641 $comments_by_type = array('comment' => array(), 'trackback' => array(), 'pingback' => array(), 'pings' => array()); 642 $count = count($comments); 643 for ( $i = 0; $i < $count; $i++ ) { 644 $type = $comments[$i]->comment_type; 645 if ( empty($type) ) 646 $type = 'comment'; 647 $comments_by_type[$type][] = &$comments[$i]; 648 if ( 'trackback' == $type || 'pingback' == $type ) 649 $comments_by_type['pings'][] = &$comments[$i]; 650 } 651 652 return $comments_by_type; 653 } 654 655 /** 656 * Calculate the total number of comment pages. 657 * 658 * @since 2.7.0 659 * @uses get_query_var() Used to fill in the default for $per_page parameter. 660 * @uses get_option() Used to fill in defaults for parameters. 661 * @uses Walker_Comment 662 * 663 * @param array $comments Optional array of comment objects. Defaults to $wp_query->comments 664 * @param int $per_page Optional comments per page. 665 * @param boolean $threaded Optional control over flat or threaded comments. 666 * @return int Number of comment pages. 667 */ 668 function get_comment_pages_count( $comments = null, $per_page = null, $threaded = null ) { 669 global $wp_query; 670 671 if ( null === $comments && null === $per_page && null === $threaded && !empty($wp_query->max_num_comment_pages) ) 672 return $wp_query->max_num_comment_pages; 673 674 if ( !$comments || !is_array($comments) ) 675 $comments = $wp_query->comments; 676 677 if ( empty($comments) ) 678 return 0; 679 680 if ( !isset($per_page) ) 681 $per_page = (int) get_query_var('comments_per_page'); 682 if ( 0 === $per_page ) 683 $per_page = (int) get_option('comments_per_page'); 684 if ( 0 === $per_page ) 685 return 1; 686 687 if ( !isset($threaded) ) 688 $threaded = get_option('thread_comments'); 689 690 if ( $threaded ) { 691 $walker = new Walker_Comment; 692 $count = ceil( $walker->get_number_of_root_elements( $comments ) / $per_page ); 693 } else { 694 $count = ceil( count( $comments ) / $per_page ); 695 } 696 697 return $count; 698 } 699 700 /** 701 * Calculate what page number a comment will appear on for comment paging. 702 * 703 * @since 2.7.0 704 * @uses get_comment() Gets the full comment of the $comment_ID parameter. 705 * @uses get_option() Get various settings to control function and defaults. 706 * @uses get_page_of_comment() Used to loop up to top level comment. 707 * 708 * @param int $comment_ID Comment ID. 709 * @param array $args Optional args. 710 * @return int|null Comment page number or null on error. 711 */ 712 function get_page_of_comment( $comment_ID, $args = array() ) { 713 global $wpdb; 714 715 if ( !$comment = get_comment( $comment_ID ) ) 716 return; 717 718 $defaults = array( 'type' => 'all', 'page' => '', 'per_page' => '', 'max_depth' => '' ); 719 $args = wp_parse_args( $args, $defaults ); 720 721 if ( '' === $args['per_page'] && get_option('page_comments') ) 722 $args['per_page'] = get_query_var('comments_per_page'); 723 if ( empty($args['per_page']) ) { 724 $args['per_page'] = 0; 725 $args['page'] = 0; 726 } 727 if ( $args['per_page'] < 1 ) 728 return 1; 729 730 if ( '' === $args['max_depth'] ) { 731 if ( get_option('thread_comments') ) 732 $args['max_depth'] = get_option('thread_comments_depth'); 733 else 734 $args['max_depth'] = -1; 735 } 736 737 // Find this comment's top level parent if threading is enabled 738 if ( $args['max_depth'] > 1 && 0 != $comment->comment_parent ) 739 return get_page_of_comment( $comment->comment_parent, $args ); 740 741 $allowedtypes = array( 742 'comment' => '', 743 'pingback' => 'pingback', 744 'trackback' => 'trackback', 745 ); 746 747 $comtypewhere = ( 'all' != $args['type'] && isset($allowedtypes[$args['type']]) ) ? " AND comment_type = '" . $allowedtypes[$args['type']] . "'" : ''; 748 749 // Count comments older than this one 750 $oldercoms = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(comment_ID) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = 0 AND comment_approved = '1' AND comment_date_gmt < '%s'" . $comtypewhere, $comment->comment_post_ID, $comment->comment_date_gmt ) ); 751 752 // No older comments? Then it's page #1. 753 if ( 0 == $oldercoms ) 754 return 1; 755 756 // Divide comments older than this one by comments per page to get this comment's page number 757 return ceil( ( $oldercoms + 1 ) / $args['per_page'] ); 758 } 759 760 /** 761 * Does comment contain blacklisted characters or words. 762 * 763 * @since 1.5.0 764 * @uses do_action() Calls 'wp_blacklist_check' hook for all parameters. 765 * 766 * @param string $author The author of the comment 767 * @param string $email The email of the comment 768 * @param string $url The url used in the comment 769 * @param string $comment The comment content 770 * @param string $user_ip The comment author IP address 771 * @param string $user_agent The author's browser user agent 772 * @return bool True if comment contains blacklisted content, false if comment does not 773 */ 774 function wp_blacklist_check($author, $email, $url, $comment, $user_ip, $user_agent) { 775 do_action('wp_blacklist_check', $author, $email, $url, $comment, $user_ip, $user_agent); 776 777 $mod_keys = trim( get_option('blacklist_keys') ); 778 if ( '' == $mod_keys ) 779 return false; // If moderation keys are empty 780 $words = explode("\n", $mod_keys ); 781 782 foreach ( (array) $words as $word ) { 783 $word = trim($word); 784 785 // Skip empty lines 786 if ( empty($word) ) { continue; } 787 788 // Do some escaping magic so that '#' chars in the 789 // spam words don't break things: 790 $word = preg_quote($word, '#'); 791 792 $pattern = "#$word#i"; 793 if ( 794 preg_match($pattern, $author) 795 || preg_match($pattern, $email) 796 || preg_match($pattern, $url) 797 || preg_match($pattern, $comment) 798 || preg_match($pattern, $user_ip) 799 || preg_match($pattern, $user_agent) 800 ) 801 return true; 802 } 803 return false; 804 } 805 806 /** 807 * Retrieve total comments for blog or single post. 808 * 809 * The properties of the returned object contain the 'moderated', 'approved', 810 * and spam comments for either the entire blog or single post. Those properties 811 * contain the amount of comments that match the status. The 'total_comments' 812 * property contains the integer of total comments. 813 * 814 * The comment stats are cached and then retrieved, if they already exist in the 815 * cache. 816 * 817 * @since 2.5.0 818 * 819 * @param int $post_id Optional. Post ID. 820 * @return object Comment stats. 821 */ 822 function wp_count_comments( $post_id = 0 ) { 823 global $wpdb; 824 825 $post_id = (int) $post_id; 826 827 $stats = apply_filters('wp_count_comments', array(), $post_id); 828 if ( !empty($stats) ) 829 return $stats; 830 831 $count = wp_cache_get("comments-{$post_id}", 'counts'); 832 833 if ( false !== $count ) 834 return $count; 835 836 $where = ''; 837 if ( $post_id > 0 ) 838 $where = $wpdb->prepare( "WHERE comment_post_ID = %d", $post_id ); 839 840 $count = $wpdb->get_results( "SELECT comment_approved, COUNT( * ) AS num_comments FROM {$wpdb->comments} {$where} GROUP BY comment_approved", ARRAY_A ); 841 842 $total = 0; 843 $approved = array('0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed'); 844 $known_types = array_keys( $approved ); 845 foreach ( (array) $count as $row ) { 846 // Don't count post-trashed toward totals 847 if ( 'post-trashed' != $row['comment_approved'] && 'trash' != $row['comment_approved'] ) 848 $total += $row['num_comments']; 849 if ( in_array( $row['comment_approved'], $known_types ) ) 850 $stats[$approved[$row['comment_approved']]] = $row['num_comments']; 851 } 852 853 $stats['total_comments'] = $total; 854 foreach ( $approved as $key ) { 855 if ( empty($stats[$key]) ) 856 $stats[$key] = 0; 857 } 858 859 $stats = (object) $stats; 860 wp_cache_set("comments-{$post_id}", $stats, 'counts'); 861 862 return $stats; 863 } 864 865 /** 866 * Trashes or deletes a comment. 867 * 868 * The comment is moved to trash instead of permanently deleted unless trash is 869 * disabled, item is already in the trash, or $force_delete is true. 870 * 871 * The post comment count will be updated if the comment was approved and has a 872 * post ID available. 873 * 874 * @since 2.0.0 875 * @uses $wpdb 876 * @uses do_action() Calls 'delete_comment' hook on comment ID 877 * @uses do_action() Calls 'deleted_comment' hook on comment ID after deletion, on success 878 * @uses do_action() Calls 'wp_set_comment_status' hook on comment ID with 'delete' set for the second parameter 879 * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object 880 * 881 * @param int $comment_id Comment ID 882 * @param bool $force_delete Whether to bypass trash and force deletion. Default is false. 883 * @return bool False if delete comment query failure, true on success. 884 */ 885 function wp_delete_comment($comment_id, $force_delete = false) { 886 global $wpdb; 887 if (!$comment = get_comment($comment_id)) 888 return false; 889 890 if ( !$force_delete && EMPTY_TRASH_DAYS && !in_array( wp_get_comment_status($comment_id), array( 'trash', 'spam' ) ) ) 891 return wp_trash_comment($comment_id); 892 893 do_action('delete_comment', $comment_id); 894 895 // Move children up a level. 896 $children = $wpdb->get_col( $wpdb->prepare("SELECT comment_ID FROM $wpdb->comments WHERE comment_parent = %d", $comment_id) ); 897 if ( !empty($children) ) { 898 $wpdb->update($wpdb->comments, array('comment_parent' => $comment->comment_parent), array('comment_parent' => $comment_id)); 899 clean_comment_cache($children); 900 } 901 902 // Delete metadata 903 $meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d ", $comment_id ) ); 904 if ( !empty($meta_ids) ) { 905 do_action( 'delete_commentmeta', $meta_ids ); 906 $in_meta_ids = "'" . implode("', '", $meta_ids) . "'"; 907 $wpdb->query( "DELETE FROM $wpdb->commentmeta WHERE meta_id IN ($in_meta_ids)" ); 908 do_action( 'deleted_commentmeta', $meta_ids ); 909 } 910 911 if ( ! $wpdb->query( $wpdb->prepare("DELETE FROM $wpdb->comments WHERE comment_ID = %d LIMIT 1", $comment_id) ) ) 912 return false; 913 do_action('deleted_comment', $comment_id); 914 915 $post_id = $comment->comment_post_ID; 916 if ( $post_id && $comment->comment_approved == 1 ) 917 wp_update_comment_count($post_id); 918 919 clean_comment_cache($comment_id); 920 921 do_action('wp_set_comment_status', $comment_id, 'delete'); 922 wp_transition_comment_status('delete', $comment->comment_approved, $comment); 923 return true; 924 } 925 926 /** 927 * Moves a comment to the Trash 928 * 929 * If trash is disabled, comment is permanently deleted. 930 * 931 * @since 2.9.0 932 * @uses do_action() on 'trash_comment' before trashing 933 * @uses do_action() on 'trashed_comment' after trashing 934 * @uses wp_delete_comment() if trash is disabled 935 * 936 * @param int $comment_id Comment ID. 937 * @return mixed False on failure 938 */ 939 function wp_trash_comment($comment_id) { 940 if ( !EMPTY_TRASH_DAYS ) 941 return wp_delete_comment($comment_id, true); 942 943 if ( !$comment = get_comment($comment_id) ) 944 return false; 945 946 do_action('trash_comment', $comment_id); 947 948 if ( wp_set_comment_status($comment_id, 'trash') ) { 949 add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved); 950 add_comment_meta($comment_id, '_wp_trash_meta_time', time() ); 951 do_action('trashed_comment', $comment_id); 952 return true; 953 } 954 955 return false; 956 } 957 958 /** 959 * Removes a comment from the Trash 960 * 961 * @since 2.9.0 962 * @uses do_action() on 'untrash_comment' before untrashing 963 * @uses do_action() on 'untrashed_comment' after untrashing 964 * 965 * @param int $comment_id Comment ID. 966 * @return mixed False on failure 967 */ 968 function wp_untrash_comment($comment_id) { 969 if ( ! (int)$comment_id ) 970 return false; 971 972 do_action('untrash_comment', $comment_id); 973 974 $status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true); 975 if ( empty($status) ) 976 $status = '0'; 977 978 if ( wp_set_comment_status($comment_id, $status) ) { 979 delete_comment_meta($comment_id, '_wp_trash_meta_time'); 980 delete_comment_meta($comment_id, '_wp_trash_meta_status'); 981 do_action('untrashed_comment', $comment_id); 982 return true; 983 } 984 985 return false; 986 } 987 988 /** 989 * Marks a comment as Spam 990 * 991 * @since 2.9.0 992 * @uses do_action() on 'spam_comment' before spamming 993 * @uses do_action() on 'spammed_comment' after spamming 994 * 995 * @param int $comment_id Comment ID. 996 * @return mixed False on failure 997 */ 998 function wp_spam_comment($comment_id) { 999 if ( !$comment = get_comment($comment_id) ) 1000 return false; 1001 1002 do_action('spam_comment', $comment_id); 1003 1004 if ( wp_set_comment_status($comment_id, 'spam') ) { 1005 add_comment_meta($comment_id, '_wp_trash_meta_status', $comment->comment_approved); 1006 do_action('spammed_comment', $comment_id); 1007 return true; 1008 } 1009 1010 return false; 1011 } 1012 1013 /** 1014 * Removes a comment from the Spam 1015 * 1016 * @since 2.9.0 1017 * @uses do_action() on 'unspam_comment' before unspamming 1018 * @uses do_action() on 'unspammed_comment' after unspamming 1019 * 1020 * @param int $comment_id Comment ID. 1021 * @return mixed False on failure 1022 */ 1023 function wp_unspam_comment($comment_id) { 1024 if ( ! (int)$comment_id ) 1025 return false; 1026 1027 do_action('unspam_comment', $comment_id); 1028 1029 $status = (string) get_comment_meta($comment_id, '_wp_trash_meta_status', true); 1030 if ( empty($status) ) 1031 $status = '0'; 1032 1033 if ( wp_set_comment_status($comment_id, $status) ) { 1034 delete_comment_meta($comment_id, '_wp_trash_meta_status'); 1035 do_action('unspammed_comment', $comment_id); 1036 return true; 1037 } 1038 1039 return false; 1040 } 1041 1042 /** 1043 * The status of a comment by ID. 1044 * 1045 * @since 1.0.0 1046 * 1047 * @param int $comment_id Comment ID 1048 * @return string|bool Status might be 'trash', 'approved', 'unapproved', 'spam'. False on failure. 1049 */ 1050 function wp_get_comment_status($comment_id) { 1051 $comment = get_comment($comment_id); 1052 if ( !$comment ) 1053 return false; 1054 1055 $approved = $comment->comment_approved; 1056 1057 if ( $approved == NULL ) 1058 return false; 1059 elseif ( $approved == '1' ) 1060 return 'approved'; 1061 elseif ( $approved == '0' ) 1062 return 'unapproved'; 1063 elseif ( $approved == 'spam' ) 1064 return 'spam'; 1065 elseif ( $approved == 'trash' ) 1066 return 'trash'; 1067 else 1068 return false; 1069 } 1070 1071 /** 1072 * Call hooks for when a comment status transition occurs. 1073 * 1074 * Calls hooks for comment status transitions. If the new comment status is not the same 1075 * as the previous comment status, then two hooks will be ran, the first is 1076 * 'transition_comment_status' with new status, old status, and comment data. The 1077 * next action called is 'comment_OLDSTATUS_to_NEWSTATUS' the NEWSTATUS is the 1078 * $new_status parameter and the OLDSTATUS is $old_status parameter; it has the 1079 * comment data. 1080 * 1081 * The final action will run whether or not the comment statuses are the same. The 1082 * action is named 'comment_NEWSTATUS_COMMENTTYPE', NEWSTATUS is from the $new_status 1083 * parameter and COMMENTTYPE is comment_type comment data. 1084 * 1085 * @since 2.7.0 1086 * 1087 * @param string $new_status New comment status. 1088 * @param string $old_status Previous comment status. 1089 * @param object $comment Comment data. 1090 */ 1091 function wp_transition_comment_status($new_status, $old_status, $comment) { 1092 // Translate raw statuses to human readable formats for the hooks 1093 // This is not a complete list of comment status, it's only the ones that need to be renamed 1094 $comment_statuses = array( 1095 0 => 'unapproved', 1096 'hold' => 'unapproved', // wp_set_comment_status() uses "hold" 1097 1 => 'approved', 1098 'approve' => 'approved', // wp_set_comment_status() uses "approve" 1099 ); 1100 if ( isset($comment_statuses[$new_status]) ) $new_status = $comment_statuses[$new_status]; 1101 if ( isset($comment_statuses[$old_status]) ) $old_status = $comment_statuses[$old_status]; 1102 1103 // Call the hooks 1104 if ( $new_status != $old_status ) { 1105 do_action('transition_comment_status', $new_status, $old_status, $comment); 1106 do_action("comment_$old_status}_to_$new_status", $comment); 1107 } 1108 do_action("comment_$new_status}_$comment->comment_type", $comment->comment_ID, $comment); 1109 } 1110 1111 /** 1112 * Get current commenter's name, email, and URL. 1113 * 1114 * Expects cookies content to already be sanitized. User of this function might 1115 * wish to recheck the returned array for validity. 1116 * 1117 * @see sanitize_comment_cookies() Use to sanitize cookies 1118 * 1119 * @since 2.0.4 1120 * 1121 * @return array Comment author, email, url respectively. 1122 */ 1123 function wp_get_current_commenter() { 1124 // Cookies should already be sanitized. 1125 1126 $comment_author = ''; 1127 if ( isset($_COOKIE['comment_author_'.COOKIEHASH]) ) 1128 $comment_author = $_COOKIE['comment_author_'.COOKIEHASH]; 1129 1130 $comment_author_email = ''; 1131 if ( isset($_COOKIE['comment_author_email_'.COOKIEHASH]) ) 1132 $comment_author_email = $_COOKIE['comment_author_email_'.COOKIEHASH]; 1133 1134 $comment_author_url = ''; 1135 if ( isset($_COOKIE['comment_author_url_'.COOKIEHASH]) ) 1136 $comment_author_url = $_COOKIE['comment_author_url_'.COOKIEHASH]; 1137 1138 return compact('comment_author', 'comment_author_email', 'comment_author_url'); 1139 } 1140 1141 /** 1142 * Inserts a comment to the database. 1143 * 1144 * The available comment data key names are 'comment_author_IP', 'comment_date', 1145 * 'comment_date_gmt', 'comment_parent', 'comment_approved', and 'user_id'. 1146 * 1147 * @since 2.0.0 1148 * @uses $wpdb 1149 * 1150 * @param array $commentdata Contains information on the comment. 1151 * @return int The new comment's ID. 1152 */ 1153 function wp_insert_comment($commentdata) { 1154 global $wpdb; 1155 extract(stripslashes_deep($commentdata), EXTR_SKIP); 1156 1157 if ( ! isset($comment_author_IP) ) 1158 $comment_author_IP = ''; 1159 if ( ! isset($comment_date) ) 1160 $comment_date = current_time('mysql'); 1161 if ( ! isset($comment_date_gmt) ) 1162 $comment_date_gmt = get_gmt_from_date($comment_date); 1163 if ( ! isset($comment_parent) ) 1164 $comment_parent = 0; 1165 if ( ! isset($comment_approved) ) 1166 $comment_approved = 1; 1167 if ( ! isset($comment_karma) ) 1168 $comment_karma = 0; 1169 if ( ! isset($user_id) ) 1170 $user_id = 0; 1171 if ( ! isset($comment_type) ) 1172 $comment_type = ''; 1173 1174 $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'); 1175 $wpdb->insert($wpdb->comments, $data); 1176 1177 $id = (int) $wpdb->insert_id; 1178 1179 if ( $comment_approved == 1 ) 1180 wp_update_comment_count($comment_post_ID); 1181 1182 $comment = get_comment($id); 1183 do_action('wp_insert_comment', $id, $comment); 1184 1185 return $id; 1186 } 1187 1188 /** 1189 * Filters and sanitizes comment data. 1190 * 1191 * Sets the comment data 'filtered' field to true when finished. This can be 1192 * checked as to whether the comment should be filtered and to keep from 1193 * filtering the same comment more than once. 1194 * 1195 * @since 2.0.0 1196 * @uses apply_filters() Calls 'pre_user_id' hook on comment author's user ID 1197 * @uses apply_filters() Calls 'pre_comment_user_agent' hook on comment author's user agent 1198 * @uses apply_filters() Calls 'pre_comment_author_name' hook on comment author's name 1199 * @uses apply_filters() Calls 'pre_comment_content' hook on the comment's content 1200 * @uses apply_filters() Calls 'pre_comment_user_ip' hook on comment author's IP 1201 * @uses apply_filters() Calls 'pre_comment_author_url' hook on comment author's URL 1202 * @uses apply_filters() Calls 'pre_comment_author_email' hook on comment author's email address 1203 * 1204 * @param array $commentdata Contains information on the comment. 1205 * @return array Parsed comment information. 1206 */ 1207 function wp_filter_comment($commentdata) { 1208 if ( isset($commentdata['user_ID']) ) 1209 $commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_ID']); 1210 elseif ( isset($commentdata['user_id']) ) 1211 $commentdata['user_id'] = apply_filters('pre_user_id', $commentdata['user_id']); 1212 $commentdata['comment_agent'] = apply_filters('pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) ); 1213 $commentdata['comment_author'] = apply_filters('pre_comment_author_name', $commentdata['comment_author']); 1214 $commentdata['comment_content'] = apply_filters('pre_comment_content', $commentdata['comment_content']); 1215 $commentdata['comment_author_IP'] = apply_filters('pre_comment_user_ip', $commentdata['comment_author_IP']); 1216 $commentdata['comment_author_url'] = apply_filters('pre_comment_author_url', $commentdata['comment_author_url']); 1217 $commentdata['comment_author_email'] = apply_filters('pre_comment_author_email', $commentdata['comment_author_email']); 1218 $commentdata['filtered'] = true; 1219 return $commentdata; 1220 } 1221 1222 /** 1223 * Whether comment should be blocked because of comment flood. 1224 * 1225 * @since 2.1.0 1226 * 1227 * @param bool $block Whether plugin has already blocked comment. 1228 * @param int $time_lastcomment Timestamp for last comment. 1229 * @param int $time_newcomment Timestamp for new comment. 1230 * @return bool Whether comment should be blocked. 1231 */ 1232 function wp_throttle_comment_flood($block, $time_lastcomment, $time_newcomment) { 1233 if ( $block ) // a plugin has already blocked... we'll let that decision stand 1234 return $block; 1235 if ( ($time_newcomment - $time_lastcomment) < 15 ) 1236 return true; 1237 return false; 1238 } 1239 1240 /** 1241 * Adds a new comment to the database. 1242 * 1243 * Filters new comment to ensure that the fields are sanitized and valid before 1244 * inserting comment into database. Calls 'comment_post' action with comment ID 1245 * and whether comment is approved by WordPress. Also has 'preprocess_comment' 1246 * filter for processing the comment data before the function handles it. 1247 * 1248 * We use REMOTE_ADDR here directly. If you are behind a proxy, you should ensure 1249 * that it is properly set, such as in wp-config.php, for your environment. 1250 * See {@link http://core.trac.wordpress.org/ticket/9235} 1251 * 1252 * @since 1.5.0 1253 * @uses apply_filters() Calls 'preprocess_comment' hook on $commentdata parameter array before processing 1254 * @uses do_action() Calls 'comment_post' hook on $comment_ID returned from adding the comment and if the comment was approved. 1255 * @uses wp_filter_comment() Used to filter comment before adding comment. 1256 * @uses wp_allow_comment() checks to see if comment is approved. 1257 * @uses wp_insert_comment() Does the actual comment insertion to the database. 1258 * 1259 * @param array $commentdata Contains information on the comment. 1260 * @return int The ID of the comment after adding. 1261 */ 1262 function wp_new_comment( $commentdata ) { 1263 $commentdata = apply_filters('preprocess_comment', $commentdata); 1264 1265 $commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID']; 1266 if ( isset($commentdata['user_ID']) ) 1267 $commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID']; 1268 elseif ( isset($commentdata['user_id']) ) 1269 $commentdata['user_id'] = (int) $commentdata['user_id']; 1270 1271 $commentdata['comment_parent'] = isset($commentdata['comment_parent']) ? absint($commentdata['comment_parent']) : 0; 1272 $parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status($commentdata['comment_parent']) : ''; 1273 $commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0; 1274 1275 $commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '',$_SERVER['REMOTE_ADDR'] ); 1276 $commentdata['comment_agent'] = substr($_SERVER['HTTP_USER_AGENT'], 0, 254); 1277 1278 $commentdata['comment_date'] = current_time('mysql'); 1279 $commentdata['comment_date_gmt'] = current_time('mysql', 1); 1280 1281 $commentdata = wp_filter_comment($commentdata); 1282 1283 $commentdata['comment_approved'] = wp_allow_comment($commentdata); 1284 1285 $comment_ID = wp_insert_comment($commentdata); 1286 1287 do_action('comment_post', $comment_ID, $commentdata['comment_approved']); 1288 1289 if ( 'spam' !== $commentdata['comment_approved'] ) { // If it's spam save it silently for later crunching 1290 if ( '0' == $commentdata['comment_approved'] ) 1291 wp_notify_moderator($comment_ID); 1292 1293 $post = &get_post($commentdata['comment_post_ID']); // Don't notify if it's your own comment 1294 1295 if ( get_option('comments_notify') && $commentdata['comment_approved'] && ( ! isset( $commentdata['user_id'] ) || $post->post_author != $commentdata['user_id'] ) ) 1296 wp_notify_postauthor($comment_ID, isset( $commentdata['comment_type'] ) ? $commentdata['comment_type'] : '' ); 1297 } 1298 1299 return $comment_ID; 1300 } 1301 1302 /** 1303 * Sets the status of a comment. 1304 * 1305 * The 'wp_set_comment_status' action is called after the comment is handled and 1306 * will only be called, if the comment status is either 'hold', 'approve', or 1307 * 'spam'. If the comment status is not in the list, then false is returned and 1308 * if the status is 'delete', then the comment is deleted without calling the 1309 * action. 1310 * 1311 * @since 1.0.0 1312 * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object 1313 * 1314 * @param int $comment_id Comment ID. 1315 * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'delete'. 1316 * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false. 1317 * @return bool False on failure or deletion and true on success. 1318 */ 1319 function wp_set_comment_status($comment_id, $comment_status, $wp_error = false) { 1320 global $wpdb; 1321 1322 $status = '0'; 1323 switch ( $comment_status ) { 1324 case 'hold': 1325 case '0': 1326 $status = '0'; 1327 break; 1328 case 'approve': 1329 case '1': 1330 $status = '1'; 1331 if ( get_option('comments_notify') ) { 1332 $comment = get_comment($comment_id); 1333 wp_notify_postauthor($comment_id, $comment->comment_type); 1334 } 1335 break; 1336 case 'spam': 1337 $status = 'spam'; 1338 break; 1339 case 'trash': 1340 $status = 'trash'; 1341 break; 1342 default: 1343 return false; 1344 } 1345 1346 $comment_old = wp_clone(get_comment($comment_id)); 1347 1348 if ( !$wpdb->update( $wpdb->comments, array('comment_approved' => $status), array('comment_ID' => $comment_id) ) ) { 1349 if ( $wp_error ) 1350 return new WP_Error('db_update_error', __('Could not update comment status'), $wpdb->last_error); 1351 else 1352 return false; 1353 } 1354 1355 clean_comment_cache($comment_id); 1356 1357 $comment = get_comment($comment_id); 1358 1359 do_action('wp_set_comment_status', $comment_id, $comment_status); 1360 wp_transition_comment_status($comment_status, $comment_old->comment_approved, $comment); 1361 1362 wp_update_comment_count($comment->comment_post_ID); 1363 1364 return true; 1365 } 1366 1367 /** 1368 * Updates an existing comment in the database. 1369 * 1370 * Filters the comment and makes sure certain fields are valid before updating. 1371 * 1372 * @since 2.0.0 1373 * @uses $wpdb 1374 * @uses wp_transition_comment_status() Passes new and old comment status along with $comment object 1375 * 1376 * @param array $commentarr Contains information on the comment. 1377 * @return int Comment was updated if value is 1, or was not updated if value is 0. 1378 */ 1379 function wp_update_comment($commentarr) { 1380 global $wpdb; 1381 1382 // First, get all of the original fields 1383 $comment = get_comment($commentarr['comment_ID'], ARRAY_A); 1384 1385 // Escape data pulled from DB. 1386 $comment = esc_sql($comment); 1387 1388 $old_status = $comment['comment_approved']; 1389 1390 // Merge old and new fields with new fields overwriting old ones. 1391 $commentarr = array_merge($comment, $commentarr); 1392 1393 $commentarr = wp_filter_comment( $commentarr ); 1394 1395 // Now extract the merged array. 1396 extract(stripslashes_deep($commentarr), EXTR_SKIP); 1397 1398 $comment_content = apply_filters('comment_save_pre', $comment_content); 1399 1400 $comment_date_gmt = get_gmt_from_date($comment_date); 1401 1402 if ( !isset($comment_approved) ) 1403 $comment_approved = 1; 1404 else if ( 'hold' == $comment_approved ) 1405 $comment_approved = 0; 1406 else if ( 'approve' == $comment_approved ) 1407 $comment_approved = 1; 1408 1409 $data = compact('comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt'); 1410 $rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) ); 1411 1412 clean_comment_cache($comment_ID); 1413 wp_update_comment_count($comment_post_ID); 1414 do_action('edit_comment', $comment_ID); 1415 $comment = get_comment($comment_ID); 1416 wp_transition_comment_status($comment->comment_approved, $old_status, $comment); 1417 return $rval; 1418 } 1419 1420 /** 1421 * Whether to defer comment counting. 1422 * 1423 * When setting $defer to true, all post comment counts will not be updated 1424 * until $defer is set to false. When $defer is set to false, then all 1425 * previously deferred updated post comment counts will then be automatically 1426 * updated without having to call wp_update_comment_count() after. 1427 * 1428 * @since 2.5.0 1429 * @staticvar bool $_defer 1430 * 1431 * @param bool $defer 1432 * @return unknown 1433 */ 1434 function wp_defer_comment_counting($defer=null) { 1435 static $_defer = false; 1436 1437 if ( is_bool($defer) ) { 1438 $_defer = $defer; 1439 // flush any deferred counts 1440 if ( !$defer ) 1441 wp_update_comment_count( null, true ); 1442 } 1443 1444 return $_defer; 1445 } 1446 1447 /** 1448 * Updates the comment count for post(s). 1449 * 1450 * When $do_deferred is false (is by default) and the comments have been set to 1451 * be deferred, the post_id will be added to a queue, which will be updated at a 1452 * later date and only updated once per post ID. 1453 * 1454 * If the comments have not be set up to be deferred, then the post will be 1455 * updated. When $do_deferred is set to true, then all previous deferred post 1456 * IDs will be updated along with the current $post_id. 1457 * 1458 * @since 2.1.0 1459 * @see wp_update_comment_count_now() For what could cause a false return value 1460 * 1461 * @param int $post_id Post ID 1462 * @param bool $do_deferred Whether to process previously deferred post comment counts 1463 * @return bool True on success, false on failure 1464 */ 1465 function wp_update_comment_count($post_id, $do_deferred=false) { 1466 static $_deferred = array(); 1467 1468 if ( $do_deferred ) { 1469 $_deferred = array_unique($_deferred); 1470 foreach ( $_deferred as $i => $_post_id ) { 1471 wp_update_comment_count_now($_post_id); 1472 unset( $_deferred[$i] ); /** @todo Move this outside of the foreach and reset $_deferred to an array instead */ 1473 } 1474 } 1475 1476 if ( wp_defer_comment_counting() ) { 1477 $_deferred[] = $post_id; 1478 return true; 1479 } 1480 elseif ( $post_id ) { 1481 return wp_update_comment_count_now($post_id); 1482 } 1483 1484 } 1485 1486 /** 1487 * Updates the comment count for the post. 1488 * 1489 * @since 2.5.0 1490 * @uses $wpdb 1491 * @uses do_action() Calls 'wp_update_comment_count' hook on $post_id, $new, and $old 1492 * @uses do_action() Calls 'edit_posts' hook on $post_id and $post 1493 * 1494 * @param int $post_id Post ID 1495 * @return bool False on '0' $post_id or if post with ID does not exist. True on success. 1496 */ 1497 function wp_update_comment_count_now($post_id) { 1498 global $wpdb; 1499 $post_id = (int) $post_id; 1500 if ( !$post_id ) 1501 return false; 1502 if ( !$post = get_post($post_id) ) 1503 return false; 1504 1505 $old = (int) $post->comment_count; 1506 $new = (int) $wpdb->get_var( $wpdb->prepare("SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id) ); 1507 $wpdb->update( $wpdb->posts, array('comment_count' => $new), array('ID' => $post_id) ); 1508 1509 if ( 'page' == $post->post_type ) 1510 clean_page_cache( $post_id ); 1511 else 1512 clean_post_cache( $post_id ); 1513 1514 do_action('wp_update_comment_count', $post_id, $new, $old); 1515 do_action('edit_post', $post_id, $post); 1516 1517 return true; 1518 } 1519 1520 // 1521 // Ping and trackback functions. 1522 // 1523 1524 /** 1525 * Finds a pingback server URI based on the given URL. 1526 * 1527 * Checks the HTML for the rel="pingback" link and x-pingback headers. It does 1528 * a check for the x-pingback headers first and returns that, if available. The 1529 * check for the rel="pingback" has more overhead than just the header. 1530 * 1531 * @since 1.5.0 1532 * 1533 * @param string $url URL to ping. 1534 * @param int $deprecated Not Used. 1535 * @return bool|string False on failure, string containing URI on success. 1536 */ 1537 function discover_pingback_server_uri( $url, $deprecated = '' ) { 1538 if ( !empty( $deprecated ) ) 1539 _deprecated_argument( __FUNCTION__, '2.7' ); 1540 1541 $pingback_str_dquote = 'rel="pingback"'; 1542 $pingback_str_squote = 'rel=\'pingback\''; 1543 1544 /** @todo Should use Filter Extension or custom preg_match instead. */ 1545 $parsed_url = parse_url($url); 1546 1547 if ( ! isset( $parsed_url['host'] ) ) // Not an URL. This should never happen. 1548 return false; 1549 1550 //Do not search for a pingback server on our own uploads 1551 $uploads_dir = wp_upload_dir(); 1552 if ( 0 === strpos($url, $uploads_dir['baseurl']) ) 1553 return false; 1554 1555 $response = wp_remote_head( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) ); 1556 1557 if ( is_wp_error( $response ) ) 1558 return false; 1559 1560 if ( isset( $response['headers']['x-pingback'] ) ) 1561 return $response['headers']['x-pingback']; 1562 1563 // Not an (x)html, sgml, or xml page, no use going further. 1564 if ( isset( $response['headers']['content-type'] ) && preg_match('#(image|audio|video|model)/#is', $response['headers']['content-type']) ) 1565 return false; 1566 1567 // Now do a GET since we're going to look in the html headers (and we're sure its not a binary file) 1568 $response = wp_remote_get( $url, array( 'timeout' => 2, 'httpversion' => '1.0' ) ); 1569 1570 if ( is_wp_error( $response ) ) 1571 return false; 1572 1573 $contents = $response['body']; 1574 1575 $pingback_link_offset_dquote = strpos($contents, $pingback_str_dquote); 1576 $pingback_link_offset_squote = strpos($contents, $pingback_str_squote); 1577 if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) { 1578 $quote = ($pingback_link_offset_dquote) ? '"' : '\''; 1579 $pingback_link_offset = ($quote=='"') ? $pingback_link_offset_dquote : $pingback_link_offset_squote; 1580 $pingback_href_pos = @strpos($contents, 'href=', $pingback_link_offset); 1581 $pingback_href_start = $pingback_href_pos+6; 1582 $pingback_href_end = @strpos($contents, $quote, $pingback_href_start); 1583 $pingback_server_url_len = $pingback_href_end - $pingback_href_start; 1584 $pingback_server_url = substr($contents, $pingback_href_start, $pingback_server_url_len); 1585 1586 // We may find rel="pingback" but an incomplete pingback URL 1587 if ( $pingback_server_url_len > 0 ) { // We got it! 1588 return $pingback_server_url; 1589 } 1590 } 1591 1592 return false; 1593 } 1594 1595 /** 1596 * Perform all pingbacks, enclosures, trackbacks, and send to pingback services. 1597 * 1598 * @since 2.1.0 1599 * @uses $wpdb 1600 */ 1601 function do_all_pings() { 1602 global $wpdb; 1603 1604 // Do pingbacks 1605 while ($ping = $wpdb->get_row("SELECT * FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1")) { 1606 $mid = $wpdb->get_var( "SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = {$ping->ID} AND meta_key = '_pingme' LIMIT 1"); 1607 do_action( 'delete_postmeta', $mid ); 1608 $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_id = %d", $mid ) ); 1609 do_action( 'deleted_postmeta', $mid ); 1610 pingback($ping->post_content, $ping->ID); 1611 } 1612 1613 // Do Enclosures 1614 while ($enclosure = $wpdb->get_row("SELECT * FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1")) { 1615 $mid = $wpdb->get_var( $wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = '_encloseme'", $enclosure->ID) ); 1616 do_action( 'delete_postmeta', $mid ); 1617 $wpdb->query( $wpdb->prepare("DELETE FROM {$wpdb->postmeta} WHERE meta_id = %d", $mid) ); 1618 do_action( 'deleted_postmeta', $mid ); 1619 do_enclose($enclosure->post_content, $enclosure->ID); 1620 } 1621 1622 // Do Trackbacks 1623 $trackbacks = $wpdb->get_col("SELECT ID FROM $wpdb->posts WHERE to_ping <> '' AND post_status = 'publish'"); 1624 if ( is_array($trackbacks) ) 1625 foreach ( $trackbacks as $trackback ) 1626 do_trackbacks($trackback); 1627 1628 //Do Update Services/Generic Pings 1629 generic_ping(); 1630 } 1631 1632 /** 1633 * Perform trackbacks. 1634 * 1635 * @since 1.5.0 1636 * @uses $wpdb 1637 * 1638 * @param int $post_id Post ID to do trackbacks on. 1639 */ 1640 function do_trackbacks($post_id) { 1641 global $wpdb; 1642 1643 $post = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE ID = %d", $post_id) ); 1644 $to_ping = get_to_ping($post_id); 1645 $pinged = get_pung($post_id); 1646 if ( empty($to_ping) ) { 1647 $wpdb->update($wpdb->posts, array('to_ping' => ''), array('ID' => $post_id) ); 1648 return; 1649 } 1650 1651 if ( empty($post->post_excerpt) ) 1652 $excerpt = apply_filters('the_content', $post->post_content); 1653 else 1654 $excerpt = apply_filters('the_excerpt', $post->post_excerpt); 1655 $excerpt = str_replace(']]>', ']]>', $excerpt); 1656 $excerpt = wp_html_excerpt($excerpt, 252) . '...'; 1657 1658 $post_title = apply_filters('the_title', $post->post_title); 1659 $post_title = strip_tags($post_title); 1660 1661 if ( $to_ping ) { 1662 foreach ( (array) $to_ping as $tb_ping ) { 1663 $tb_ping = trim($tb_ping); 1664 if ( !in_array($tb_ping, $pinged) ) { 1665 trackback($tb_ping, $post_title, $excerpt, $post_id); 1666 $pinged[] = $tb_ping; 1667 } else { 1668 $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_ping', '')) WHERE ID = %d", $post_id) ); 1669 } 1670 } 1671 } 1672 } 1673 1674 /** 1675 * Sends pings to all of the ping site services. 1676 * 1677 * @since 1.2.0 1678 * 1679 * @param int $post_id Post ID. Not actually used. 1680 * @return int Same as Post ID from parameter 1681 */ 1682 function generic_ping($post_id = 0) { 1683 $services = get_option('ping_sites'); 1684 1685 $services = explode("\n", $services); 1686 foreach ( (array) $services as $service ) { 1687 $service = trim($service); 1688 if ( '' != $service ) 1689 weblog_ping($service); 1690 } 1691 1692 return $post_id; 1693 } 1694 1695 /** 1696 * Pings back the links found in a post. 1697 * 1698 * @since 0.71 1699 * @uses $wp_version 1700 * @uses IXR_Client 1701 * 1702 * @param string $content Post content to check for links. 1703 * @param int $post_ID Post ID. 1704 */ 1705 function pingback($content, $post_ID) { 1706 global $wp_version; 1707 include_once (ABSPATH . WPINC . '/class-IXR.php'); 1708 1709 // original code by Mort (http://mort.mine.nu:8080) 1710 $post_links = array(); 1711 1712 $pung = get_pung($post_ID); 1713 1714 // Variables 1715 $ltrs = '\w'; 1716 $gunk = '/#~:.?+=&%@!\-'; 1717 $punc = '.:?\-'; 1718 $any = $ltrs . $gunk . $punc; 1719 1720 // Step 1 1721 // Parsing the post, external links (if any) are stored in the $post_links array 1722 // This regexp comes straight from phpfreaks.com 1723 // http://www.phpfreaks.com/quickcode/Extract_All_URLs_on_a_Page/15.php 1724 preg_match_all("{\b http : [$any] +? (?= [$punc] * [^$any] | $)}x", $content, $post_links_temp); 1725 1726 // Step 2. 1727 // Walking thru the links array 1728 // first we get rid of links pointing to sites, not to specific files 1729 // Example: 1730 // http://dummy-weblog.org 1731 // http://dummy-weblog.org/ 1732 // http://dummy-weblog.org/post.php 1733 // We don't wanna ping first and second types, even if they have a valid <link/> 1734 1735 foreach ( (array) $post_links_temp[0] as $link_test ) : 1736 if ( !in_array($link_test, $pung) && (url_to_postid($link_test) != $post_ID) // If we haven't pung it already and it isn't a link to itself 1737 && !is_local_attachment($link_test) ) : // Also, let's never ping local attachments. 1738 if ( $test = @parse_url($link_test) ) { 1739 if ( isset($test['query']) ) 1740 $post_links[] = $link_test; 1741 elseif ( ($test['path'] != '/') && ($test['path'] != '') ) 1742 $post_links[] = $link_test; 1743 } 1744 endif; 1745 endforeach; 1746 1747 do_action_ref_array('pre_ping', array(&$post_links, &$pung)); 1748 1749 foreach ( (array) $post_links as $pagelinkedto ) { 1750 $pingback_server_url = discover_pingback_server_uri($pagelinkedto, 2048); 1751 1752 if ( $pingback_server_url ) { 1753 @ set_time_limit( 60 ); 1754 // Now, the RPC call 1755 $pagelinkedfrom = get_permalink($post_ID); 1756 1757 // using a timeout of 3 seconds should be enough to cover slow servers 1758 $client = new IXR_Client($pingback_server_url); 1759 $client->timeout = 3; 1760 $client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . $wp_version, $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom); 1761 // when set to true, this outputs debug messages by itself 1762 $client->debug = false; 1763 1764 if ( $client->query('pingback.ping', $pagelinkedfrom, $pagelinkedto) || ( isset($client->error->code) && 48 == $client->error->code ) ) // Already registered 1765 add_ping( $post_ID, $pagelinkedto ); 1766 } 1767 } 1768 } 1769 1770 /** 1771 * Check whether blog is public before returning sites. 1772 * 1773 * @since 2.1.0 1774 * 1775 * @param mixed $sites Will return if blog is public, will not return if not public. 1776 * @return mixed Empty string if blog is not public, returns $sites, if site is public. 1777 */ 1778 function privacy_ping_filter($sites) { 1779 if ( '0' != get_option('blog_public') ) 1780 return $sites; 1781 else 1782 return ''; 1783 } 1784 1785 /** 1786 * Send a Trackback. 1787 * 1788 * Updates database when sending trackback to prevent duplicates. 1789 * 1790 * @since 0.71 1791 * @uses $wpdb 1792 * 1793 * @param string $trackback_url URL to send trackbacks. 1794 * @param string $title Title of post. 1795 * @param string $excerpt Excerpt of post. 1796 * @param int $ID Post ID. 1797 * @return mixed Database query from update. 1798 */ 1799 function trackback($trackback_url, $title, $excerpt, $ID) { 1800 global $wpdb; 1801 1802 if ( empty($trackback_url) ) 1803 return; 1804 1805 $options = array(); 1806 $options['timeout'] = 4; 1807 $options['body'] = array( 1808 'title' => $title, 1809 'url' => get_permalink($ID), 1810 'blog_name' => get_option('blogname'), 1811 'excerpt' => $excerpt 1812 ); 1813 1814 $response = wp_remote_post($trackback_url, $options); 1815 1816 if ( is_wp_error( $response ) ) 1817 return; 1818 1819 $tb_url = addslashes( $trackback_url ); 1820 $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', '$tb_url') WHERE ID = %d", $ID) ); 1821 return $wpdb->query( $wpdb->prepare("UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, '$tb_url', '')) WHERE ID = %d", $ID) ); 1822 } 1823 1824 /** 1825 * Send a pingback. 1826 * 1827 * @since 1.2.0 1828 * @uses $wp_version 1829 * @uses IXR_Client 1830 * 1831 * @param string $server Host of blog to connect to. 1832 * @param string $path Path to send the ping. 1833 */ 1834 function weblog_ping($server = '', $path = '') { 1835 global $wp_version; 1836 include_once (ABSPATH . WPINC . '/class-IXR.php'); 1837 1838 // using a timeout of 3 seconds should be enough to cover slow servers 1839 $client = new IXR_Client($server, ((!strlen(trim($path)) || ('/' == $path)) ? false : $path)); 1840 $client->timeout = 3; 1841 $client->useragent .= ' -- WordPress/'.$wp_version; 1842 1843 // when set to true, this outputs debug messages by itself 1844 $client->debug = false; 1845 $home = trailingslashit( home_url() ); 1846 if ( !$client->query('weblogUpdates.extendedPing', get_option('blogname'), $home, get_bloginfo('rss2_url') ) ) // then try a normal ping 1847 $client->query('weblogUpdates.ping', get_option('blogname'), $home); 1848 } 1849 1850 // 1851 // Cache 1852 // 1853 1854 /** 1855 * Removes comment ID from the comment cache. 1856 * 1857 * @since 2.3.0 1858 * @package WordPress 1859 * @subpackage Cache 1860 * 1861 * @param int|array $ids Comment ID or array of comment IDs to remove from cache 1862 */ 1863 function clean_comment_cache($ids) { 1864 foreach ( (array) $ids as $id ) 1865 wp_cache_delete($id, 'comment'); 1866 1867 wp_cache_set('last_changed', time(), 'comment'); 1868 } 1869 1870 /** 1871 * Updates the comment cache of given comments. 1872 * 1873 * Will add the comments in $comments to the cache. If comment ID already exists 1874 * in the comment cache then it will not be updated. The comment is added to the 1875 * cache using the comment group with the key using the ID of the comments. 1876 * 1877 * @since 2.3.0 1878 * @package WordPress 1879 * @subpackage Cache 1880 * 1881 * @param array $comments Array of comment row objects 1882 */ 1883 function update_comment_cache($comments) { 1884 foreach ( (array) $comments as $comment ) 1885 wp_cache_add($comment->comment_ID, $comment, 'comment'); 1886 } 1887 1888 // 1889 // Internal 1890 // 1891 1892 /** 1893 * Close comments on old posts on the fly, without any extra DB queries. Hooked to the_posts. 1894 * 1895 * @access private 1896 * @since 2.7.0 1897 * 1898 * @param object $posts Post data object. 1899 * @return object 1900 */ 1901 function _close_comments_for_old_posts( $posts ) { 1902 if ( empty($posts) || !is_singular() || !get_option('close_comments_for_old_posts') ) 1903 return $posts; 1904 1905 $days_old = (int) get_option('close_comments_days_old'); 1906 if ( !$days_old ) 1907 return $posts; 1908 1909 if ( time() - strtotime( $posts[0]->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) ) { 1910 $posts[0]->comment_status = 'closed'; 1911 $posts[0]->ping_status = 'closed'; 1912 } 1913 1914 return $posts; 1915 } 1916 1917 /** 1918 * Close comments on an old post. Hooked to comments_open and pings_open. 1919 * 1920 * @access private 1921 * @since 2.7.0 1922 * 1923 * @param bool $open Comments open or closed 1924 * @param int $post_id Post ID 1925 * @return bool $open 1926 */ 1927 function _close_comments_for_old_post( $open, $post_id ) { 1928 if ( ! $open ) 1929 return $open; 1930 1931 if ( !get_option('close_comments_for_old_posts') ) 1932 return $open; 1933 1934 $days_old = (int) get_option('close_comments_days_old'); 1935 if ( !$days_old ) 1936 return $open; 1937 1938 $post = get_post($post_id); 1939 1940 if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * 24 * 60 * 60 ) ) 1941 return false; 1942 1943 return $open; 1944 } 1945 1946 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Sep 9 03:37:14 2010 | Cross-referenced by PHPXref 0.7 |