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