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