Best Cucumber Common Library code snippet using Comment
comment.php
Source:comment.php
1<?php2/**3 * Core Comment API4 *5 * @package WordPress6 * @subpackage Comment7 */8/**9 * Check whether a comment passes internal checks to be allowed to add.10 *11 * If manual comment moderation is set in the administration, then all checks,12 * regardless of their type and whitelist, will fail and the function will13 * return false.14 *15 * If the number of links exceeds the amount in the administration, then the16 * check fails. If any of the parameter contents match the blacklist of words,17 * then the check fails.18 *19 * If the comment author was approved before, then the comment is automatically20 * whitelisted.21 *22 * If all checks pass, the function will return true.23 *24 * @since 1.2.025 *26 * @global wpdb $wpdb WordPress database abstraction object.27 *28 * @param string $author Comment author name.29 * @param string $email Comment author email.30 * @param string $url Comment author URL.31 * @param string $comment Content of the comment.32 * @param string $user_ip Comment author IP address.33 * @param string $user_agent Comment author User-Agent.34 * @param string $comment_type Comment type, either user-submitted comment,35 * trackback, or pingback.36 * @return bool If all checks pass, true, otherwise false.37 */38function check_comment( $author, $email, $url, $comment, $user_ip, $user_agent, $comment_type ) {39 global $wpdb;40 // If manual moderation is enabled, skip all checks and return false.41 if ( 1 == get_option( 'comment_moderation' ) ) {42 return false;43 }44 /** This filter is documented in wp-includes/comment-template.php */45 $comment = apply_filters( 'comment_text', $comment, null, array() );46 // Check for the number of external links if a max allowed number is set.47 if ( $max_links = get_option( 'comment_max_links' ) ) {48 $num_links = preg_match_all( '/<a [^>]*href/i', $comment, $out );49 /**50 * Filters the number of links found in a comment.51 *52 * @since 3.0.053 * @since 4.7.0 Added the `$comment` parameter.54 *55 * @param int $num_links The number of links found.56 * @param string $url Comment author's URL. Included in allowed links total.57 * @param string $comment Content of the comment.58 */59 $num_links = apply_filters( 'comment_max_links_url', $num_links, $url, $comment );60 /*61 * If the number of links in the comment exceeds the allowed amount,62 * fail the check by returning false.63 */64 if ( $num_links >= $max_links ) {65 return false;66 }67 }68 $mod_keys = trim( get_option( 'moderation_keys' ) );69 // If moderation 'keys' (keywords) are set, process them.70 if ( ! empty( $mod_keys ) ) {71 $words = explode( "\n", $mod_keys );72 foreach ( (array) $words as $word ) {73 $word = trim( $word );74 // Skip empty lines.75 if ( empty( $word ) ) {76 continue;77 }78 /*79 * Do some escaping magic so that '#' (number of) characters in the spam80 * words don't break things:81 */82 $word = preg_quote( $word, '#' );83 /*84 * Check the comment fields for moderation keywords. If any are found,85 * fail the check for the given field by returning false.86 */87 $pattern = "#$word#i";88 if ( preg_match( $pattern, $author ) ) {89 return false;90 }91 if ( preg_match( $pattern, $email ) ) {92 return false;93 }94 if ( preg_match( $pattern, $url ) ) {95 return false;96 }97 if ( preg_match( $pattern, $comment ) ) {98 return false;99 }100 if ( preg_match( $pattern, $user_ip ) ) {101 return false;102 }103 if ( preg_match( $pattern, $user_agent ) ) {104 return false;105 }106 }107 }108 /*109 * Check if the option to approve comments by previously-approved authors is enabled.110 *111 * If it is enabled, check whether the comment author has a previously-approved comment,112 * as well as whether there are any moderation keywords (if set) present in the author113 * email address. If both checks pass, return true. Otherwise, return false.114 */115 if ( 1 == get_option( 'comment_whitelist' ) ) {116 if ( 'trackback' != $comment_type && 'pingback' != $comment_type && $author != '' && $email != '' ) {117 $comment_user = get_user_by( 'email', wp_unslash( $email ) );118 if ( ! empty( $comment_user->ID ) ) {119 $ok_to_comment = $wpdb->get_var( $wpdb->prepare( "SELECT comment_approved FROM $wpdb->comments WHERE user_id = %d AND comment_approved = '1' LIMIT 1", $comment_user->ID ) );120 } else {121 // expected_slashed ($author, $email)122 $ok_to_comment = $wpdb->get_var( $wpdb->prepare( "SELECT comment_approved FROM $wpdb->comments WHERE comment_author = %s AND comment_author_email = %s and comment_approved = '1' LIMIT 1", $author, $email ) );123 }124 if ( ( 1 == $ok_to_comment ) &&125 ( empty( $mod_keys ) || false === strpos( $email, $mod_keys ) ) ) {126 return true;127 } else {128 return false;129 }130 } else {131 return false;132 }133 }134 return true;135}136/**137 * Retrieve the approved comments for post $post_id.138 *139 * @since 2.0.0140 * @since 4.1.0 Refactored to leverage WP_Comment_Query over a direct query.141 *142 * @param int $post_id The ID of the post.143 * @param array $args Optional. See WP_Comment_Query::__construct() for information on accepted arguments.144 * @return int|array $comments The approved comments, or number of comments if `$count`145 * argument is true.146 */147function get_approved_comments( $post_id, $args = array() ) {148 if ( ! $post_id ) {149 return array();150 }151 $defaults = array(152 'status' => 1,153 'post_id' => $post_id,154 'order' => 'ASC',155 );156 $r = wp_parse_args( $args, $defaults );157 $query = new WP_Comment_Query;158 return $query->query( $r );159}160/**161 * Retrieves comment data given a comment ID or comment object.162 *163 * If an object is passed then the comment data will be cached and then returned164 * after being passed through a filter. If the comment is empty, then the global165 * comment variable will be used, if it is set.166 *167 * @since 2.0.0168 *169 * @global WP_Comment $comment170 *171 * @param WP_Comment|string|int $comment Comment to retrieve.172 * @param string $output Optional. The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond to173 * a WP_Comment object, an associative array, or a numeric array, respectively. Default OBJECT.174 * @return WP_Comment|array|null Depends on $output value.175 */176function get_comment( &$comment = null, $output = OBJECT ) {177 if ( empty( $comment ) && isset( $GLOBALS['comment'] ) ) {178 $comment = $GLOBALS['comment'];179 }180 if ( $comment instanceof WP_Comment ) {181 $_comment = $comment;182 } elseif ( is_object( $comment ) ) {183 $_comment = new WP_Comment( $comment );184 } else {185 $_comment = WP_Comment::get_instance( $comment );186 }187 if ( ! $_comment ) {188 return null;189 }190 /**191 * Fires after a comment is retrieved.192 *193 * @since 2.3.0194 *195 * @param mixed $_comment Comment data.196 */197 $_comment = apply_filters( 'get_comment', $_comment );198 if ( $output == OBJECT ) {199 return $_comment;200 } elseif ( $output == ARRAY_A ) {201 return $_comment->to_array();202 } elseif ( $output == ARRAY_N ) {203 return array_values( $_comment->to_array() );204 }205 return $_comment;206}207/**208 * Retrieve a list of comments.209 *210 * The comment list can be for the blog as a whole or for an individual post.211 *212 * @since 2.7.0213 *214 * @param string|array $args Optional. Array or string of arguments. See WP_Comment_Query::__construct()215 * for information on accepted arguments. Default empty.216 * @return int|array List of comments or number of found comments if `$count` argument is true.217 */218function get_comments( $args = '' ) {219 $query = new WP_Comment_Query;220 return $query->query( $args );221}222/**223 * Retrieve all of the WordPress supported comment statuses.224 *225 * Comments have a limited set of valid status values, this provides the comment226 * status values and descriptions.227 *228 * @since 2.7.0229 *230 * @return array List of comment statuses.231 */232function get_comment_statuses() {233 $status = array(234 'hold' => __( 'Unapproved' ),235 'approve' => _x( 'Approved', 'comment status' ),236 'spam' => _x( 'Spam', 'comment status' ),237 'trash' => _x( 'Trash', 'comment status' ),238 );239 return $status;240}241/**242 * Gets the default comment status for a post type.243 *244 * @since 4.3.0245 *246 * @param string $post_type Optional. Post type. Default 'post'.247 * @param string $comment_type Optional. Comment type. Default 'comment'.248 * @return string Expected return value is 'open' or 'closed'.249 */250function get_default_comment_status( $post_type = 'post', $comment_type = 'comment' ) {251 switch ( $comment_type ) {252 case 'pingback':253 case 'trackback':254 $supports = 'trackbacks';255 $option = 'ping';256 break;257 default:258 $supports = 'comments';259 $option = 'comment';260 }261 // Set the status.262 if ( 'page' === $post_type ) {263 $status = 'closed';264 } elseif ( post_type_supports( $post_type, $supports ) ) {265 $status = get_option( "default_{$option}_status" );266 } else {267 $status = 'closed';268 }269 /**270 * Filters the default comment status for the given post type.271 *272 * @since 4.3.0273 *274 * @param string $status Default status for the given post type,275 * either 'open' or 'closed'.276 * @param string $post_type Post type. Default is `post`.277 * @param string $comment_type Type of comment. Default is `comment`.278 */279 return apply_filters( 'get_default_comment_status', $status, $post_type, $comment_type );280}281/**282 * The date the last comment was modified.283 *284 * @since 1.5.0285 * @since 4.7.0 Replaced caching the modified date in a local static variable286 * with the Object Cache API.287 *288 * @global wpdb $wpdb WordPress database abstraction object.289 *290 * @param string $timezone Which timezone to use in reference to 'gmt', 'blog', or 'server' locations.291 * @return string|false Last comment modified date on success, false on failure.292 */293function get_lastcommentmodified( $timezone = 'server' ) {294 global $wpdb;295 $timezone = strtolower( $timezone );296 $key = "lastcommentmodified:$timezone";297 $comment_modified_date = wp_cache_get( $key, 'timeinfo' );298 if ( false !== $comment_modified_date ) {299 return $comment_modified_date;300 }301 switch ( $timezone ) {302 case 'gmt':303 $comment_modified_date = $wpdb->get_var( "SELECT comment_date_gmt FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1" );304 break;305 case 'blog':306 $comment_modified_date = $wpdb->get_var( "SELECT comment_date FROM $wpdb->comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1" );307 break;308 case 'server':309 $add_seconds_server = date( 'Z' );310 $comment_modified_date = $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 ) );311 break;312 }313 if ( $comment_modified_date ) {314 wp_cache_set( $key, $comment_modified_date, 'timeinfo' );315 return $comment_modified_date;316 }317 return false;318}319/**320 * The amount of comments in a post or total comments.321 *322 * A lot like wp_count_comments(), in that they both return comment stats (albeit with different types).323 * The wp_count_comments() actually caches, but this function does not.324 *325 * @since 2.0.0326 *327 * @global wpdb $wpdb WordPress database abstraction object.328 *329 * @param int $post_id Optional. Comment amount in post if > 0, else total comments blog wide.330 * @return array The amount of spam, approved, awaiting moderation, and total comments.331 */332function get_comment_count( $post_id = 0 ) {333 global $wpdb;334 $post_id = (int) $post_id;335 $where = '';336 if ( $post_id > 0 ) {337 $where = $wpdb->prepare( 'WHERE comment_post_ID = %d', $post_id );338 }339 $totals = (array) $wpdb->get_results(340 "341 SELECT comment_approved, COUNT( * ) AS total342 FROM {$wpdb->comments}343 {$where}344 GROUP BY comment_approved345 ",346 ARRAY_A347 );348 $comment_count = array(349 'approved' => 0,350 'awaiting_moderation' => 0,351 'spam' => 0,352 'trash' => 0,353 'post-trashed' => 0,354 'total_comments' => 0,355 'all' => 0,356 );357 foreach ( $totals as $row ) {358 switch ( $row['comment_approved'] ) {359 case 'trash':360 $comment_count['trash'] = $row['total'];361 break;362 case 'post-trashed':363 $comment_count['post-trashed'] = $row['total'];364 break;365 case 'spam':366 $comment_count['spam'] = $row['total'];367 $comment_count['total_comments'] += $row['total'];368 break;369 case '1':370 $comment_count['approved'] = $row['total'];371 $comment_count['total_comments'] += $row['total'];372 $comment_count['all'] += $row['total'];373 break;374 case '0':375 $comment_count['awaiting_moderation'] = $row['total'];376 $comment_count['total_comments'] += $row['total'];377 $comment_count['all'] += $row['total'];378 break;379 default:380 break;381 }382 }383 return $comment_count;384}385//386// Comment meta functions387//388/**389 * Add meta data field to a comment.390 *391 * @since 2.9.0392 * @link https://codex.wordpress.org/Function_Reference/add_comment_meta393 *394 * @param int $comment_id Comment ID.395 * @param string $meta_key Metadata name.396 * @param mixed $meta_value Metadata value.397 * @param bool $unique Optional, default is false. Whether the same key should not be added.398 * @return int|bool Meta ID on success, false on failure.399 */400function add_comment_meta( $comment_id, $meta_key, $meta_value, $unique = false ) {401 return add_metadata( 'comment', $comment_id, $meta_key, $meta_value, $unique );402}403/**404 * Remove metadata matching criteria from a comment.405 *406 * You can match based on the key, or key and value. Removing based on key and407 * value, will keep from removing duplicate metadata with the same key. It also408 * allows removing all metadata matching key, if needed.409 *410 * @since 2.9.0411 * @link https://codex.wordpress.org/Function_Reference/delete_comment_meta412 *413 * @param int $comment_id comment ID414 * @param string $meta_key Metadata name.415 * @param mixed $meta_value Optional. Metadata value.416 * @return bool True on success, false on failure.417 */418function delete_comment_meta( $comment_id, $meta_key, $meta_value = '' ) {419 return delete_metadata( 'comment', $comment_id, $meta_key, $meta_value );420}421/**422 * Retrieve comment meta field for a comment.423 *424 * @since 2.9.0425 * @link https://codex.wordpress.org/Function_Reference/get_comment_meta426 *427 * @param int $comment_id Comment ID.428 * @param string $key Optional. The meta key to retrieve. By default, returns data for all keys.429 * @param bool $single Whether to return a single value.430 * @return mixed Will be an array if $single is false. Will be value of meta data field if $single431 * is true.432 */433function get_comment_meta( $comment_id, $key = '', $single = false ) {434 return get_metadata( 'comment', $comment_id, $key, $single );435}436/**437 * Update comment meta field based on comment ID.438 *439 * Use the $prev_value parameter to differentiate between meta fields with the440 * same key and comment ID.441 *442 * If the meta field for the comment does not exist, it will be added.443 *444 * @since 2.9.0445 * @link https://codex.wordpress.org/Function_Reference/update_comment_meta446 *447 * @param int $comment_id Comment ID.448 * @param string $meta_key Metadata key.449 * @param mixed $meta_value Metadata value.450 * @param mixed $prev_value Optional. Previous value to check before removing.451 * @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.452 */453function update_comment_meta( $comment_id, $meta_key, $meta_value, $prev_value = '' ) {454 return update_metadata( 'comment', $comment_id, $meta_key, $meta_value, $prev_value );455}456/**457 * Queues comments for metadata lazy-loading.458 *459 * @since 4.5.0460 *461 * @param WP_Comment[] $comments Array of comment objects.462 */463function wp_queue_comments_for_comment_meta_lazyload( $comments ) {464 // Don't use `wp_list_pluck()` to avoid by-reference manipulation.465 $comment_ids = array();466 if ( is_array( $comments ) ) {467 foreach ( $comments as $comment ) {468 if ( $comment instanceof WP_Comment ) {469 $comment_ids[] = $comment->comment_ID;470 }471 }472 }473 if ( $comment_ids ) {474 $lazyloader = wp_metadata_lazyloader();475 $lazyloader->queue_objects( 'comment', $comment_ids );476 }477}478/**479 * Sets the cookies used to store an unauthenticated commentator's identity. Typically used480 * to recall previous comments by this commentator that are still held in moderation.481 *482 * @since 3.4.0483 * @since 4.9.6 The `$cookies_consent` parameter was added.484 *485 * @param WP_Comment $comment Comment object.486 * @param WP_User $user Comment author's user object. The user may not exist.487 * @param boolean $cookies_consent Optional. Comment author's consent to store cookies. Default true.488 */489function wp_set_comment_cookies( $comment, $user, $cookies_consent = true ) {490 // If the user already exists, or the user opted out of cookies, don't set cookies.491 if ( $user->exists() ) {492 return;493 }494 if ( false === $cookies_consent ) {495 // Remove any existing cookies.496 $past = time() - YEAR_IN_SECONDS;497 setcookie( 'comment_author_' . COOKIEHASH, ' ', $past, COOKIEPATH, COOKIE_DOMAIN );498 setcookie( 'comment_author_email_' . COOKIEHASH, ' ', $past, COOKIEPATH, COOKIE_DOMAIN );499 setcookie( 'comment_author_url_' . COOKIEHASH, ' ', $past, COOKIEPATH, COOKIE_DOMAIN );500 return;501 }502 /**503 * Filters the lifetime of the comment cookie in seconds.504 *505 * @since 2.8.0506 *507 * @param int $seconds Comment cookie lifetime. Default 30000000.508 */509 $comment_cookie_lifetime = time() + apply_filters( 'comment_cookie_lifetime', 30000000 );510 $secure = ( 'https' === parse_url( home_url(), PHP_URL_SCHEME ) );511 setcookie( 'comment_author_' . COOKIEHASH, $comment->comment_author, $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, $secure );512 setcookie( 'comment_author_email_' . COOKIEHASH, $comment->comment_author_email, $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, $secure );513 setcookie( 'comment_author_url_' . COOKIEHASH, esc_url( $comment->comment_author_url ), $comment_cookie_lifetime, COOKIEPATH, COOKIE_DOMAIN, $secure );514}515/**516 * Sanitizes the cookies sent to the user already.517 *518 * Will only do anything if the cookies have already been created for the user.519 * Mostly used after cookies had been sent to use elsewhere.520 *521 * @since 2.0.4522 */523function sanitize_comment_cookies() {524 if ( isset( $_COOKIE[ 'comment_author_' . COOKIEHASH ] ) ) {525 /**526 * Filters the comment author's name cookie before it is set.527 *528 * When this filter hook is evaluated in wp_filter_comment(),529 * the comment author's name string is passed.530 *531 * @since 1.5.0532 *533 * @param string $author_cookie The comment author name cookie.534 */535 $comment_author = apply_filters( 'pre_comment_author_name', $_COOKIE[ 'comment_author_' . COOKIEHASH ] );536 $comment_author = wp_unslash( $comment_author );537 $comment_author = esc_attr( $comment_author );538 $_COOKIE[ 'comment_author_' . COOKIEHASH ] = $comment_author;539 }540 if ( isset( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] ) ) {541 /**542 * Filters the comment author's email cookie before it is set.543 *544 * When this filter hook is evaluated in wp_filter_comment(),545 * the comment author's email string is passed.546 *547 * @since 1.5.0548 *549 * @param string $author_email_cookie The comment author email cookie.550 */551 $comment_author_email = apply_filters( 'pre_comment_author_email', $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] );552 $comment_author_email = wp_unslash( $comment_author_email );553 $comment_author_email = esc_attr( $comment_author_email );554 $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] = $comment_author_email;555 }556 if ( isset( $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] ) ) {557 /**558 * Filters the comment author's URL cookie before it is set.559 *560 * When this filter hook is evaluated in wp_filter_comment(),561 * the comment author's URL string is passed.562 *563 * @since 1.5.0564 *565 * @param string $author_url_cookie The comment author URL cookie.566 */567 $comment_author_url = apply_filters( 'pre_comment_author_url', $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] );568 $comment_author_url = wp_unslash( $comment_author_url );569 $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] = $comment_author_url;570 }571}572/**573 * Validates whether this comment is allowed to be made.574 *575 * @since 2.0.0576 * @since 4.7.0 The `$avoid_die` parameter was added, allowing the function to577 * return a WP_Error object instead of dying.578 *579 * @global wpdb $wpdb WordPress database abstraction object.580 *581 * @param array $commentdata Contains information on the comment.582 * @param bool $avoid_die When true, a disallowed comment will result in the function583 * returning a WP_Error object, rather than executing wp_die().584 * Default false.585 * @return int|string|WP_Error Allowed comments return the approval status (0|1|'spam').586 * If `$avoid_die` is true, disallowed comments return a WP_Error.587 */588function wp_allow_comment( $commentdata, $avoid_die = false ) {589 global $wpdb;590 // Simple duplicate check591 // expected_slashed ($comment_post_ID, $comment_author, $comment_author_email, $comment_content)592 $dupe = $wpdb->prepare(593 "SELECT comment_ID FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_parent = %s AND comment_approved != 'trash' AND ( comment_author = %s ",594 wp_unslash( $commentdata['comment_post_ID'] ),595 wp_unslash( $commentdata['comment_parent'] ),596 wp_unslash( $commentdata['comment_author'] )597 );598 if ( $commentdata['comment_author_email'] ) {599 $dupe .= $wpdb->prepare(600 'AND comment_author_email = %s ',601 wp_unslash( $commentdata['comment_author_email'] )602 );603 }604 $dupe .= $wpdb->prepare(605 ') AND comment_content = %s LIMIT 1',606 wp_unslash( $commentdata['comment_content'] )607 );608 $dupe_id = $wpdb->get_var( $dupe );609 /**610 * Filters the ID, if any, of the duplicate comment found when creating a new comment.611 *612 * Return an empty value from this filter to allow what WP considers a duplicate comment.613 *614 * @since 4.4.0615 *616 * @param int $dupe_id ID of the comment identified as a duplicate.617 * @param array $commentdata Data for the comment being created.618 */619 $dupe_id = apply_filters( 'duplicate_comment_id', $dupe_id, $commentdata );620 if ( $dupe_id ) {621 /**622 * Fires immediately after a duplicate comment is detected.623 *624 * @since 3.0.0625 *626 * @param array $commentdata Comment data.627 */628 do_action( 'comment_duplicate_trigger', $commentdata );629 /**630 * Filters duplicate comment error message.631 *632 * @since 5.2.0633 *634 * @param string $comment_duplicate_message Duplicate comment error message.635 */636 $comment_duplicate_message = apply_filters( 'comment_duplicate_message', __( 'Duplicate comment detected; it looks as though you’ve already said that!' ) );637 if ( true === $avoid_die ) {638 return new WP_Error( 'comment_duplicate', $comment_duplicate_message, 409 );639 } else {640 if ( wp_doing_ajax() ) {641 die( $comment_duplicate_message );642 }643 wp_die( $comment_duplicate_message, 409 );644 }645 }646 /**647 * Fires immediately before a comment is marked approved.648 *649 * Allows checking for comment flooding.650 *651 * @since 2.3.0652 * @since 4.7.0 The `$avoid_die` parameter was added.653 *654 * @param string $comment_author_IP Comment author's IP address.655 * @param string $comment_author_email Comment author's email.656 * @param string $comment_date_gmt GMT date the comment was posted.657 * @param bool $avoid_die Whether to prevent executing wp_die()658 * or die() if a comment flood is occurring.659 */660 do_action(661 'check_comment_flood',662 $commentdata['comment_author_IP'],663 $commentdata['comment_author_email'],664 $commentdata['comment_date_gmt'],665 $avoid_die666 );667 /**668 * Filters whether a comment is part of a comment flood.669 *670 * The default check is wp_check_comment_flood(). See check_comment_flood_db().671 *672 * @since 4.7.0673 *674 * @param bool $is_flood Is a comment flooding occurring? Default false.675 * @param string $comment_author_IP Comment author's IP address.676 * @param string $comment_author_email Comment author's email.677 * @param string $comment_date_gmt GMT date the comment was posted.678 * @param bool $avoid_die Whether to prevent executing wp_die()679 * or die() if a comment flood is occurring.680 */681 $is_flood = apply_filters(682 'wp_is_comment_flood',683 false,684 $commentdata['comment_author_IP'],685 $commentdata['comment_author_email'],686 $commentdata['comment_date_gmt'],687 $avoid_die688 );689 if ( $is_flood ) {690 /** This filter is documented in wp-includes/comment-template.php */691 $comment_flood_message = apply_filters( 'comment_flood_message', __( 'You are posting comments too quickly. Slow down.' ) );692 return new WP_Error( 'comment_flood', $comment_flood_message, 429 );693 }694 if ( ! empty( $commentdata['user_id'] ) ) {695 $user = get_userdata( $commentdata['user_id'] );696 $post_author = $wpdb->get_var(697 $wpdb->prepare(698 "SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1",699 $commentdata['comment_post_ID']700 )701 );702 }703 if ( isset( $user ) && ( $commentdata['user_id'] == $post_author || $user->has_cap( 'moderate_comments' ) ) ) {704 // The author and the admins get respect.705 $approved = 1;706 } else {707 // Everyone else's comments will be checked.708 if ( check_comment(709 $commentdata['comment_author'],710 $commentdata['comment_author_email'],711 $commentdata['comment_author_url'],712 $commentdata['comment_content'],713 $commentdata['comment_author_IP'],714 $commentdata['comment_agent'],715 $commentdata['comment_type']716 ) ) {717 $approved = 1;718 } else {719 $approved = 0;720 }721 if ( wp_blacklist_check(722 $commentdata['comment_author'],723 $commentdata['comment_author_email'],724 $commentdata['comment_author_url'],725 $commentdata['comment_content'],726 $commentdata['comment_author_IP'],727 $commentdata['comment_agent']728 ) ) {729 $approved = EMPTY_TRASH_DAYS ? 'trash' : 'spam';730 }731 }732 /**733 * Filters a comment's approval status before it is set.734 *735 * @since 2.1.0736 * @since 4.9.0 Returning a WP_Error value from the filter will shortcircuit comment insertion and737 * allow skipping further processing.738 *739 * @param bool|string|WP_Error $approved The approval status. Accepts 1, 0, 'spam' or WP_Error.740 * @param array $commentdata Comment data.741 */742 $approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );743 return $approved;744}745/**746 * Hooks WP's native database-based comment-flood check.747 *748 * This wrapper maintains backward compatibility with plugins that expect to749 * be able to unhook the legacy check_comment_flood_db() function from750 * 'check_comment_flood' using remove_action().751 *752 * @since 2.3.0753 * @since 4.7.0 Converted to be an add_filter() wrapper.754 */755function check_comment_flood_db() {756 add_filter( 'wp_is_comment_flood', 'wp_check_comment_flood', 10, 5 );757}758/**759 * Checks whether comment flooding is occurring.760 *761 * Won't run, if current user can manage options, so to not block762 * administrators.763 *764 * @since 4.7.0765 *766 * @global wpdb $wpdb WordPress database abstraction object.767 *768 * @param bool $is_flood Is a comment flooding occurring?769 * @param string $ip Comment author's IP address.770 * @param string $email Comment author's email address.771 * @param string $date MySQL time string.772 * @param bool $avoid_die When true, a disallowed comment will result in the function773 * returning a WP_Error object, rather than executing wp_die().774 * Default false.775 * @return bool Whether comment flooding is occurring.776 */777function wp_check_comment_flood( $is_flood, $ip, $email, $date, $avoid_die = false ) {778 global $wpdb;779 // Another callback has declared a flood. Trust it.780 if ( true === $is_flood ) {781 return $is_flood;782 }783 // don't throttle admins or moderators784 if ( current_user_can( 'manage_options' ) || current_user_can( 'moderate_comments' ) ) {785 return false;786 }787 $hour_ago = gmdate( 'Y-m-d H:i:s', time() - HOUR_IN_SECONDS );788 if ( is_user_logged_in() ) {789 $user = get_current_user_id();790 $check_column = '`user_id`';791 } else {792 $user = $ip;793 $check_column = '`comment_author_IP`';794 }795 $sql = $wpdb->prepare(796 "SELECT `comment_date_gmt` FROM `$wpdb->comments` WHERE `comment_date_gmt` >= %s AND ( $check_column = %s OR `comment_author_email` = %s ) ORDER BY `comment_date_gmt` DESC LIMIT 1",797 $hour_ago,798 $user,799 $email800 );801 $lasttime = $wpdb->get_var( $sql );802 if ( $lasttime ) {803 $time_lastcomment = mysql2date( 'U', $lasttime, false );804 $time_newcomment = mysql2date( 'U', $date, false );805 /**806 * Filters the comment flood status.807 *808 * @since 2.1.0809 *810 * @param bool $bool Whether a comment flood is occurring. Default false.811 * @param int $time_lastcomment Timestamp of when the last comment was posted.812 * @param int $time_newcomment Timestamp of when the new comment was posted.813 */814 $flood_die = apply_filters( 'comment_flood_filter', false, $time_lastcomment, $time_newcomment );815 if ( $flood_die ) {816 /**817 * Fires before the comment flood message is triggered.818 *819 * @since 1.5.0820 *821 * @param int $time_lastcomment Timestamp of when the last comment was posted.822 * @param int $time_newcomment Timestamp of when the new comment was posted.823 */824 do_action( 'comment_flood_trigger', $time_lastcomment, $time_newcomment );825 if ( true === $avoid_die ) {826 return true;827 } else {828 /**829 * Filters the comment flood error message.830 *831 * @since 5.2.0832 *833 * @param string $comment_flood_message Comment flood error message.834 */835 $comment_flood_message = apply_filters( 'comment_flood_message', __( 'You are posting comments too quickly. Slow down.' ) );836 if ( wp_doing_ajax() ) {837 die( $comment_flood_message );838 }839 wp_die( $comment_flood_message, 429 );840 }841 }842 }843 return false;844}845/**846 * Separates an array of comments into an array keyed by comment_type.847 *848 * @since 2.7.0849 *850 * @param WP_Comment[] $comments Array of comments851 * @return WP_Comment[] Array of comments keyed by comment_type.852 */853function separate_comments( &$comments ) {854 $comments_by_type = array(855 'comment' => array(),856 'trackback' => array(),857 'pingback' => array(),858 'pings' => array(),859 );860 $count = count( $comments );861 for ( $i = 0; $i < $count; $i++ ) {862 $type = $comments[ $i ]->comment_type;863 if ( empty( $type ) ) {864 $type = 'comment';865 }866 $comments_by_type[ $type ][] = &$comments[ $i ];867 if ( 'trackback' == $type || 'pingback' == $type ) {868 $comments_by_type['pings'][] = &$comments[ $i ];869 }870 }871 return $comments_by_type;872}873/**874 * Calculate the total number of comment pages.875 *876 * @since 2.7.0877 *878 * @uses Walker_Comment879 *880 * @global WP_Query $wp_query881 *882 * @param WP_Comment[] $comments Optional. Array of WP_Comment objects. Defaults to $wp_query->comments.883 * @param int $per_page Optional. Comments per page.884 * @param bool $threaded Optional. Control over flat or threaded comments.885 * @return int Number of comment pages.886 */887function get_comment_pages_count( $comments = null, $per_page = null, $threaded = null ) {888 global $wp_query;889 if ( null === $comments && null === $per_page && null === $threaded && ! empty( $wp_query->max_num_comment_pages ) ) {890 return $wp_query->max_num_comment_pages;891 }892 if ( ( ! $comments || ! is_array( $comments ) ) && ! empty( $wp_query->comments ) ) {893 $comments = $wp_query->comments;894 }895 if ( empty( $comments ) ) {896 return 0;897 }898 if ( ! get_option( 'page_comments' ) ) {899 return 1;900 }901 if ( ! isset( $per_page ) ) {902 $per_page = (int) get_query_var( 'comments_per_page' );903 }904 if ( 0 === $per_page ) {905 $per_page = (int) get_option( 'comments_per_page' );906 }907 if ( 0 === $per_page ) {908 return 1;909 }910 if ( ! isset( $threaded ) ) {911 $threaded = get_option( 'thread_comments' );912 }913 if ( $threaded ) {914 $walker = new Walker_Comment;915 $count = ceil( $walker->get_number_of_root_elements( $comments ) / $per_page );916 } else {917 $count = ceil( count( $comments ) / $per_page );918 }919 return $count;920}921/**922 * Calculate what page number a comment will appear on for comment paging.923 *924 * @since 2.7.0925 *926 * @global wpdb $wpdb WordPress database abstraction object.927 *928 * @param int $comment_ID Comment ID.929 * @param array $args {930 * Array of optional arguments.931 * @type string $type Limit paginated comments to those matching a given type. Accepts 'comment',932 * 'trackback', 'pingback', 'pings' (trackbacks and pingbacks), or 'all'.933 * Default is 'all'.934 * @type int $per_page Per-page count to use when calculating pagination. Defaults to the value of the935 * 'comments_per_page' option.936 * @type int|string $max_depth If greater than 1, comment page will be determined for the top-level parent of937 * `$comment_ID`. Defaults to the value of the 'thread_comments_depth' option.938 * } *939 * @return int|null Comment page number or null on error.940 */941function get_page_of_comment( $comment_ID, $args = array() ) {942 global $wpdb;943 $page = null;944 if ( ! $comment = get_comment( $comment_ID ) ) {945 return;946 }947 $defaults = array(948 'type' => 'all',949 'page' => '',950 'per_page' => '',951 'max_depth' => '',952 );953 $args = wp_parse_args( $args, $defaults );954 $original_args = $args;955 // Order of precedence: 1. `$args['per_page']`, 2. 'comments_per_page' query_var, 3. 'comments_per_page' option.956 if ( get_option( 'page_comments' ) ) {957 if ( '' === $args['per_page'] ) {958 $args['per_page'] = get_query_var( 'comments_per_page' );959 }960 if ( '' === $args['per_page'] ) {961 $args['per_page'] = get_option( 'comments_per_page' );962 }963 }964 if ( empty( $args['per_page'] ) ) {965 $args['per_page'] = 0;966 $args['page'] = 0;967 }968 if ( $args['per_page'] < 1 ) {969 $page = 1;970 }971 if ( null === $page ) {972 if ( '' === $args['max_depth'] ) {973 if ( get_option( 'thread_comments' ) ) {974 $args['max_depth'] = get_option( 'thread_comments_depth' );975 } else {976 $args['max_depth'] = -1;977 }978 }979 // Find this comment's top level parent if threading is enabled980 if ( $args['max_depth'] > 1 && 0 != $comment->comment_parent ) {981 return get_page_of_comment( $comment->comment_parent, $args );982 }983 $comment_args = array(984 'type' => $args['type'],985 'post_id' => $comment->comment_post_ID,986 'fields' => 'ids',987 'count' => true,988 'status' => 'approve',989 'parent' => 0,990 'date_query' => array(991 array(992 'column' => "$wpdb->comments.comment_date_gmt",993 'before' => $comment->comment_date_gmt,994 ),995 ),996 );997 $comment_query = new WP_Comment_Query();998 $older_comment_count = $comment_query->query( $comment_args );999 // No older comments? Then it's page #1.1000 if ( 0 == $older_comment_count ) {1001 $page = 1;1002 // Divide comments older than this one by comments per page to get this comment's page number1003 } else {1004 $page = ceil( ( $older_comment_count + 1 ) / $args['per_page'] );1005 }1006 }1007 /**1008 * Filters the calculated page on which a comment appears.1009 *1010 * @since 4.4.01011 * @since 4.7.0 Introduced the `$comment_ID` parameter.1012 *1013 * @param int $page Comment page.1014 * @param array $args {1015 * Arguments used to calculate pagination. These include arguments auto-detected by the function,1016 * based on query vars, system settings, etc. For pristine arguments passed to the function,1017 * see `$original_args`.1018 *1019 * @type string $type Type of comments to count.1020 * @type int $page Calculated current page.1021 * @type int $per_page Calculated number of comments per page.1022 * @type int $max_depth Maximum comment threading depth allowed.1023 * }1024 * @param array $original_args {1025 * Array of arguments passed to the function. Some or all of these may not be set.1026 *1027 * @type string $type Type of comments to count.1028 * @type int $page Current comment page.1029 * @type int $per_page Number of comments per page.1030 * @type int $max_depth Maximum comment threading depth allowed.1031 * }1032 * @param int $comment_ID ID of the comment.1033 */1034 return apply_filters( 'get_page_of_comment', (int) $page, $args, $original_args, $comment_ID );1035}1036/**1037 * Retrieves the maximum character lengths for the comment form fields.1038 *1039 * @since 4.5.01040 *1041 * @global wpdb $wpdb WordPress database abstraction object.1042 *1043 * @return array Maximum character length for the comment form fields.1044 */1045function wp_get_comment_fields_max_lengths() {1046 global $wpdb;1047 $lengths = array(1048 'comment_author' => 245,1049 'comment_author_email' => 100,1050 'comment_author_url' => 200,1051 'comment_content' => 65525,1052 );1053 if ( $wpdb->is_mysql ) {1054 foreach ( $lengths as $column => $length ) {1055 $col_length = $wpdb->get_col_length( $wpdb->comments, $column );1056 $max_length = 0;1057 // No point if we can't get the DB column lengths1058 if ( is_wp_error( $col_length ) ) {1059 break;1060 }1061 if ( ! is_array( $col_length ) && (int) $col_length > 0 ) {1062 $max_length = (int) $col_length;1063 } elseif ( is_array( $col_length ) && isset( $col_length['length'] ) && intval( $col_length['length'] ) > 0 ) {1064 $max_length = (int) $col_length['length'];1065 if ( ! empty( $col_length['type'] ) && 'byte' === $col_length['type'] ) {1066 $max_length = $max_length - 10;1067 }1068 }1069 if ( $max_length > 0 ) {1070 $lengths[ $column ] = $max_length;1071 }1072 }1073 }1074 /**1075 * Filters the lengths for the comment form fields.1076 *1077 * @since 4.5.01078 *1079 * @param array $lengths Associative array `'field_name' => 'maximum length'`.1080 */1081 return apply_filters( 'wp_get_comment_fields_max_lengths', $lengths );1082}1083/**1084 * Compares the lengths of comment data against the maximum character limits.1085 *1086 * @since 4.7.01087 *1088 * @param array $comment_data Array of arguments for inserting a comment.1089 * @return WP_Error|true WP_Error when a comment field exceeds the limit,1090 * otherwise true.1091 */1092function wp_check_comment_data_max_lengths( $comment_data ) {1093 $max_lengths = wp_get_comment_fields_max_lengths();1094 if ( isset( $comment_data['comment_author'] ) && mb_strlen( $comment_data['comment_author'], '8bit' ) > $max_lengths['comment_author'] ) {1095 return new WP_Error( 'comment_author_column_length', __( '<strong>ERROR</strong>: your name is too long.' ), 200 );1096 }1097 if ( isset( $comment_data['comment_author_email'] ) && strlen( $comment_data['comment_author_email'] ) > $max_lengths['comment_author_email'] ) {1098 return new WP_Error( 'comment_author_email_column_length', __( '<strong>ERROR</strong>: your email address is too long.' ), 200 );1099 }1100 if ( isset( $comment_data['comment_author_url'] ) && strlen( $comment_data['comment_author_url'] ) > $max_lengths['comment_author_url'] ) {1101 return new WP_Error( 'comment_author_url_column_length', __( '<strong>ERROR</strong>: your url is too long.' ), 200 );1102 }1103 if ( isset( $comment_data['comment_content'] ) && mb_strlen( $comment_data['comment_content'], '8bit' ) > $max_lengths['comment_content'] ) {1104 return new WP_Error( 'comment_content_column_length', __( '<strong>ERROR</strong>: your comment is too long.' ), 200 );1105 }1106 return true;1107}1108/**1109 * Does comment contain blacklisted characters or words.1110 *1111 * @since 1.5.01112 *1113 * @param string $author The author of the comment1114 * @param string $email The email of the comment1115 * @param string $url The url used in the comment1116 * @param string $comment The comment content1117 * @param string $user_ip The comment author's IP address1118 * @param string $user_agent The author's browser user agent1119 * @return bool True if comment contains blacklisted content, false if comment does not1120 */1121function wp_blacklist_check( $author, $email, $url, $comment, $user_ip, $user_agent ) {1122 /**1123 * Fires before the comment is tested for blacklisted characters or words.1124 *1125 * @since 1.5.01126 *1127 * @param string $author Comment author.1128 * @param string $email Comment author's email.1129 * @param string $url Comment author's URL.1130 * @param string $comment Comment content.1131 * @param string $user_ip Comment author's IP address.1132 * @param string $user_agent Comment author's browser user agent.1133 */1134 do_action( 'wp_blacklist_check', $author, $email, $url, $comment, $user_ip, $user_agent );1135 $mod_keys = trim( get_option( 'blacklist_keys' ) );1136 if ( '' == $mod_keys ) {1137 return false; // If moderation keys are empty1138 }1139 // Ensure HTML tags are not being used to bypass the blacklist.1140 $comment_without_html = wp_strip_all_tags( $comment );1141 $words = explode( "\n", $mod_keys );1142 foreach ( (array) $words as $word ) {1143 $word = trim( $word );1144 // Skip empty lines1145 if ( empty( $word ) ) {1146 continue; }1147 // Do some escaping magic so that '#' chars in the1148 // spam words don't break things:1149 $word = preg_quote( $word, '#' );1150 $pattern = "#$word#i";1151 if ( preg_match( $pattern, $author )1152 || preg_match( $pattern, $email )1153 || preg_match( $pattern, $url )1154 || preg_match( $pattern, $comment )1155 || preg_match( $pattern, $comment_without_html )1156 || preg_match( $pattern, $user_ip )1157 || preg_match( $pattern, $user_agent )1158 ) {1159 return true;1160 }1161 }1162 return false;1163}1164/**1165 * Retrieve total comments for blog or single post.1166 *1167 * The properties of the returned object contain the 'moderated', 'approved',1168 * and spam comments for either the entire blog or single post. Those properties1169 * contain the amount of comments that match the status. The 'total_comments'1170 * property contains the integer of total comments.1171 *1172 * The comment stats are cached and then retrieved, if they already exist in the1173 * cache.1174 *1175 * @since 2.5.01176 *1177 * @param int $post_id Optional. Post ID.1178 * @return object|array Comment stats.1179 */1180function wp_count_comments( $post_id = 0 ) {1181 $post_id = (int) $post_id;1182 /**1183 * Filters the comments count for a given post.1184 *1185 * @since 2.7.01186 *1187 * @param array $count An empty array.1188 * @param int $post_id The post ID.1189 */1190 $filtered = apply_filters( 'wp_count_comments', array(), $post_id );1191 if ( ! empty( $filtered ) ) {1192 return $filtered;1193 }1194 $count = wp_cache_get( "comments-{$post_id}", 'counts' );1195 if ( false !== $count ) {1196 return $count;1197 }1198 $stats = get_comment_count( $post_id );1199 $stats['moderated'] = $stats['awaiting_moderation'];1200 unset( $stats['awaiting_moderation'] );1201 $stats_object = (object) $stats;1202 wp_cache_set( "comments-{$post_id}", $stats_object, 'counts' );1203 return $stats_object;1204}1205/**1206 * Trashes or deletes a comment.1207 *1208 * The comment is moved to trash instead of permanently deleted unless trash is1209 * disabled, item is already in the trash, or $force_delete is true.1210 *1211 * The post comment count will be updated if the comment was approved and has a1212 * post ID available.1213 *1214 * @since 2.0.01215 *1216 * @global wpdb $wpdb WordPress database abstraction object.1217 *1218 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.1219 * @param bool $force_delete Whether to bypass trash and force deletion. Default is false.1220 * @return bool True on success, false on failure.1221 */1222function wp_delete_comment( $comment_id, $force_delete = false ) {1223 global $wpdb;1224 if ( ! $comment = get_comment( $comment_id ) ) {1225 return false;1226 }1227 if ( ! $force_delete && EMPTY_TRASH_DAYS && ! in_array( wp_get_comment_status( $comment ), array( 'trash', 'spam' ) ) ) {1228 return wp_trash_comment( $comment_id );1229 }1230 /**1231 * Fires immediately before a comment is deleted from the database.1232 *1233 * @since 1.2.01234 * @since 4.9.0 Added the `$comment` parameter.1235 *1236 * @param int $comment_id The comment ID.1237 * @param WP_Comment $comment The comment to be deleted.1238 */1239 do_action( 'delete_comment', $comment->comment_ID, $comment );1240 // Move children up a level.1241 $children = $wpdb->get_col( $wpdb->prepare( "SELECT comment_ID FROM $wpdb->comments WHERE comment_parent = %d", $comment->comment_ID ) );1242 if ( ! empty( $children ) ) {1243 $wpdb->update( $wpdb->comments, array( 'comment_parent' => $comment->comment_parent ), array( 'comment_parent' => $comment->comment_ID ) );1244 clean_comment_cache( $children );1245 }1246 // Delete metadata1247 $meta_ids = $wpdb->get_col( $wpdb->prepare( "SELECT meta_id FROM $wpdb->commentmeta WHERE comment_id = %d", $comment->comment_ID ) );1248 foreach ( $meta_ids as $mid ) {1249 delete_metadata_by_mid( 'comment', $mid );1250 }1251 if ( ! $wpdb->delete( $wpdb->comments, array( 'comment_ID' => $comment->comment_ID ) ) ) {1252 return false;1253 }1254 /**1255 * Fires immediately after a comment is deleted from the database.1256 *1257 * @since 2.9.01258 * @since 4.9.0 Added the `$comment` parameter.1259 *1260 * @param int $comment_id The comment ID.1261 * @param WP_Comment $comment The deleted comment.1262 */1263 do_action( 'deleted_comment', $comment->comment_ID, $comment );1264 $post_id = $comment->comment_post_ID;1265 if ( $post_id && $comment->comment_approved == 1 ) {1266 wp_update_comment_count( $post_id );1267 }1268 clean_comment_cache( $comment->comment_ID );1269 /** This action is documented in wp-includes/comment.php */1270 do_action( 'wp_set_comment_status', $comment->comment_ID, 'delete' );1271 wp_transition_comment_status( 'delete', $comment->comment_approved, $comment );1272 return true;1273}1274/**1275 * Moves a comment to the Trash1276 *1277 * If trash is disabled, comment is permanently deleted.1278 *1279 * @since 2.9.01280 *1281 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.1282 * @return bool True on success, false on failure.1283 */1284function wp_trash_comment( $comment_id ) {1285 if ( ! EMPTY_TRASH_DAYS ) {1286 return wp_delete_comment( $comment_id, true );1287 }1288 if ( ! $comment = get_comment( $comment_id ) ) {1289 return false;1290 }1291 /**1292 * Fires immediately before a comment is sent to the Trash.1293 *1294 * @since 2.9.01295 * @since 4.9.0 Added the `$comment` parameter.1296 *1297 * @param int $comment_id The comment ID.1298 * @param WP_Comment $comment The comment to be trashed.1299 */1300 do_action( 'trash_comment', $comment->comment_ID, $comment );1301 if ( wp_set_comment_status( $comment, 'trash' ) ) {1302 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_status' );1303 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_time' );1304 add_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', $comment->comment_approved );1305 add_comment_meta( $comment->comment_ID, '_wp_trash_meta_time', time() );1306 /**1307 * Fires immediately after a comment is sent to Trash.1308 *1309 * @since 2.9.01310 * @since 4.9.0 Added the `$comment` parameter.1311 *1312 * @param int $comment_id The comment ID.1313 * @param WP_Comment $comment The trashed comment.1314 */1315 do_action( 'trashed_comment', $comment->comment_ID, $comment );1316 return true;1317 }1318 return false;1319}1320/**1321 * Removes a comment from the Trash1322 *1323 * @since 2.9.01324 *1325 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.1326 * @return bool True on success, false on failure.1327 */1328function wp_untrash_comment( $comment_id ) {1329 $comment = get_comment( $comment_id );1330 if ( ! $comment ) {1331 return false;1332 }1333 /**1334 * Fires immediately before a comment is restored from the Trash.1335 *1336 * @since 2.9.01337 * @since 4.9.0 Added the `$comment` parameter.1338 *1339 * @param int $comment_id The comment ID.1340 * @param WP_Comment $comment The comment to be untrashed.1341 */1342 do_action( 'untrash_comment', $comment->comment_ID, $comment );1343 $status = (string) get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true );1344 if ( empty( $status ) ) {1345 $status = '0';1346 }1347 if ( wp_set_comment_status( $comment, $status ) ) {1348 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_time' );1349 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_status' );1350 /**1351 * Fires immediately after a comment is restored from the Trash.1352 *1353 * @since 2.9.01354 * @since 4.9.0 Added the `$comment` parameter.1355 *1356 * @param int $comment_id The comment ID.1357 * @param WP_Comment $comment The untrashed comment.1358 */1359 do_action( 'untrashed_comment', $comment->comment_ID, $comment );1360 return true;1361 }1362 return false;1363}1364/**1365 * Marks a comment as Spam1366 *1367 * @since 2.9.01368 *1369 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.1370 * @return bool True on success, false on failure.1371 */1372function wp_spam_comment( $comment_id ) {1373 $comment = get_comment( $comment_id );1374 if ( ! $comment ) {1375 return false;1376 }1377 /**1378 * Fires immediately before a comment is marked as Spam.1379 *1380 * @since 2.9.01381 * @since 4.9.0 Added the `$comment` parameter.1382 *1383 * @param int $comment_id The comment ID.1384 * @param WP_Comment $comment The comment to be marked as spam.1385 */1386 do_action( 'spam_comment', $comment->comment_ID, $comment );1387 if ( wp_set_comment_status( $comment, 'spam' ) ) {1388 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_status' );1389 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_time' );1390 add_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', $comment->comment_approved );1391 add_comment_meta( $comment->comment_ID, '_wp_trash_meta_time', time() );1392 /**1393 * Fires immediately after a comment is marked as Spam.1394 *1395 * @since 2.9.01396 * @since 4.9.0 Added the `$comment` parameter.1397 *1398 * @param int $comment_id The comment ID.1399 * @param WP_Comment $comment The comment marked as spam.1400 */1401 do_action( 'spammed_comment', $comment->comment_ID, $comment );1402 return true;1403 }1404 return false;1405}1406/**1407 * Removes a comment from the Spam1408 *1409 * @since 2.9.01410 *1411 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.1412 * @return bool True on success, false on failure.1413 */1414function wp_unspam_comment( $comment_id ) {1415 $comment = get_comment( $comment_id );1416 if ( ! $comment ) {1417 return false;1418 }1419 /**1420 * Fires immediately before a comment is unmarked as Spam.1421 *1422 * @since 2.9.01423 * @since 4.9.0 Added the `$comment` parameter.1424 *1425 * @param int $comment_id The comment ID.1426 * @param WP_Comment $comment The comment to be unmarked as spam.1427 */1428 do_action( 'unspam_comment', $comment->comment_ID, $comment );1429 $status = (string) get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true );1430 if ( empty( $status ) ) {1431 $status = '0';1432 }1433 if ( wp_set_comment_status( $comment, $status ) ) {1434 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_status' );1435 delete_comment_meta( $comment->comment_ID, '_wp_trash_meta_time' );1436 /**1437 * Fires immediately after a comment is unmarked as Spam.1438 *1439 * @since 2.9.01440 * @since 4.9.0 Added the `$comment` parameter.1441 *1442 * @param int $comment_id The comment ID.1443 * @param WP_Comment $comment The comment unmarked as spam.1444 */1445 do_action( 'unspammed_comment', $comment->comment_ID, $comment );1446 return true;1447 }1448 return false;1449}1450/**1451 * The status of a comment by ID.1452 *1453 * @since 1.0.01454 *1455 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object1456 * @return false|string Status might be 'trash', 'approved', 'unapproved', 'spam'. False on failure.1457 */1458function wp_get_comment_status( $comment_id ) {1459 $comment = get_comment( $comment_id );1460 if ( ! $comment ) {1461 return false;1462 }1463 $approved = $comment->comment_approved;1464 if ( $approved == null ) {1465 return false;1466 } elseif ( $approved == '1' ) {1467 return 'approved';1468 } elseif ( $approved == '0' ) {1469 return 'unapproved';1470 } elseif ( $approved == 'spam' ) {1471 return 'spam';1472 } elseif ( $approved == 'trash' ) {1473 return 'trash';1474 } else {1475 return false;1476 }1477}1478/**1479 * Call hooks for when a comment status transition occurs.1480 *1481 * Calls hooks for comment status transitions. If the new comment status is not the same1482 * as the previous comment status, then two hooks will be ran, the first is1483 * {@see 'transition_comment_status'} with new status, old status, and comment data. The1484 * next action called is {@see comment_$old_status_to_$new_status'}. It has the1485 * comment data.1486 *1487 * The final action will run whether or not the comment statuses are the same. The1488 * action is named {@see 'comment_$new_status_$comment->comment_type'}.1489 *1490 * @since 2.7.01491 *1492 * @param string $new_status New comment status.1493 * @param string $old_status Previous comment status.1494 * @param object $comment Comment data.1495 */1496function wp_transition_comment_status( $new_status, $old_status, $comment ) {1497 /*1498 * Translate raw statuses to human readable formats for the hooks.1499 * This is not a complete list of comment status, it's only the ones1500 * that need to be renamed1501 */1502 $comment_statuses = array(1503 0 => 'unapproved',1504 'hold' => 'unapproved', // wp_set_comment_status() uses "hold"1505 1 => 'approved',1506 'approve' => 'approved', // wp_set_comment_status() uses "approve"1507 );1508 if ( isset( $comment_statuses[ $new_status ] ) ) {1509 $new_status = $comment_statuses[ $new_status ];1510 }1511 if ( isset( $comment_statuses[ $old_status ] ) ) {1512 $old_status = $comment_statuses[ $old_status ];1513 }1514 // Call the hooks1515 if ( $new_status != $old_status ) {1516 /**1517 * Fires when the comment status is in transition.1518 *1519 * @since 2.7.01520 *1521 * @param int|string $new_status The new comment status.1522 * @param int|string $old_status The old comment status.1523 * @param object $comment The comment data.1524 */1525 do_action( 'transition_comment_status', $new_status, $old_status, $comment );1526 /**1527 * Fires when the comment status is in transition from one specific status to another.1528 *1529 * The dynamic portions of the hook name, `$old_status`, and `$new_status`,1530 * refer to the old and new comment statuses, respectively.1531 *1532 * @since 2.7.01533 *1534 * @param WP_Comment $comment Comment object.1535 */1536 do_action( "comment_{$old_status}_to_{$new_status}", $comment );1537 }1538 /**1539 * Fires when the status of a specific comment type is in transition.1540 *1541 * The dynamic portions of the hook name, `$new_status`, and `$comment->comment_type`,1542 * refer to the new comment status, and the type of comment, respectively.1543 *1544 * Typical comment types include an empty string (standard comment), 'pingback',1545 * or 'trackback'.1546 *1547 * @since 2.7.01548 *1549 * @param int $comment_ID The comment ID.1550 * @param WP_Comment $comment Comment object.1551 */1552 do_action( "comment_{$new_status}_{$comment->comment_type}", $comment->comment_ID, $comment );1553}1554/**1555 * Clear the lastcommentmodified cached value when a comment status is changed.1556 *1557 * Deletes the lastcommentmodified cache key when a comment enters or leaves1558 * 'approved' status.1559 *1560 * @since 4.7.01561 * @access private1562 *1563 * @param string $new_status The new comment status.1564 * @param string $old_status The old comment status.1565 */1566function _clear_modified_cache_on_transition_comment_status( $new_status, $old_status ) {1567 if ( 'approved' === $new_status || 'approved' === $old_status ) {1568 foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {1569 wp_cache_delete( "lastcommentmodified:$timezone", 'timeinfo' );1570 }1571 }1572}1573/**1574 * Get current commenter's name, email, and URL.1575 *1576 * Expects cookies content to already be sanitized. User of this function might1577 * wish to recheck the returned array for validity.1578 *1579 * @see sanitize_comment_cookies() Use to sanitize cookies1580 *1581 * @since 2.0.41582 *1583 * @return array Comment author, email, url respectively.1584 */1585function wp_get_current_commenter() {1586 // Cookies should already be sanitized.1587 $comment_author = '';1588 if ( isset( $_COOKIE[ 'comment_author_' . COOKIEHASH ] ) ) {1589 $comment_author = $_COOKIE[ 'comment_author_' . COOKIEHASH ];1590 }1591 $comment_author_email = '';1592 if ( isset( $_COOKIE[ 'comment_author_email_' . COOKIEHASH ] ) ) {1593 $comment_author_email = $_COOKIE[ 'comment_author_email_' . COOKIEHASH ];1594 }1595 $comment_author_url = '';1596 if ( isset( $_COOKIE[ 'comment_author_url_' . COOKIEHASH ] ) ) {1597 $comment_author_url = $_COOKIE[ 'comment_author_url_' . COOKIEHASH ];1598 }1599 /**1600 * Filters the current commenter's name, email, and URL.1601 *1602 * @since 3.1.01603 *1604 * @param array $comment_author_data {1605 * An array of current commenter variables.1606 *1607 * @type string $comment_author The name of the author of the comment. Default empty.1608 * @type string $comment_author_email The email address of the `$comment_author`. Default empty.1609 * @type string $comment_author_url The URL address of the `$comment_author`. Default empty.1610 * }1611 */1612 return apply_filters( 'wp_get_current_commenter', compact( 'comment_author', 'comment_author_email', 'comment_author_url' ) );1613}1614/**1615 * Get unapproved comment author's email.1616 *1617 * Used to allow the commenter to see their pending comment.1618 *1619 * @since 5.1.01620 *1621 * @return string The unapproved comment author's email (when supplied).1622 */1623function wp_get_unapproved_comment_author_email() {1624 $commenter_email = '';1625 if ( ! empty( $_GET['unapproved'] ) && ! empty( $_GET['moderation-hash'] ) ) {1626 $comment_id = (int) $_GET['unapproved'];1627 $comment = get_comment( $comment_id );1628 if ( $comment && hash_equals( $_GET['moderation-hash'], wp_hash( $comment->comment_date_gmt ) ) ) {1629 $commenter_email = $comment->comment_author_email;1630 }1631 }1632 if ( ! $commenter_email ) {1633 $commenter = wp_get_current_commenter();1634 $commenter_email = $commenter['comment_author_email'];1635 }1636 return $commenter_email;1637}1638/**1639 * Inserts a comment into the database.1640 *1641 * @since 2.0.01642 * @since 4.4.0 Introduced `$comment_meta` argument.1643 *1644 * @global wpdb $wpdb WordPress database abstraction object.1645 *1646 * @param array $commentdata {1647 * Array of arguments for inserting a new comment.1648 *1649 * @type string $comment_agent The HTTP user agent of the `$comment_author` when1650 * the comment was submitted. Default empty.1651 * @type int|string $comment_approved Whether the comment has been approved. Default 1.1652 * @type string $comment_author The name of the author of the comment. Default empty.1653 * @type string $comment_author_email The email address of the `$comment_author`. Default empty.1654 * @type string $comment_author_IP The IP address of the `$comment_author`. Default empty.1655 * @type string $comment_author_url The URL address of the `$comment_author`. Default empty.1656 * @type string $comment_content The content of the comment. Default empty.1657 * @type string $comment_date The date the comment was submitted. To set the date1658 * manually, `$comment_date_gmt` must also be specified.1659 * Default is the current time.1660 * @type string $comment_date_gmt The date the comment was submitted in the GMT timezone.1661 * Default is `$comment_date` in the site's GMT timezone.1662 * @type int $comment_karma The karma of the comment. Default 0.1663 * @type int $comment_parent ID of this comment's parent, if any. Default 0.1664 * @type int $comment_post_ID ID of the post that relates to the comment, if any.1665 * Default 0.1666 * @type string $comment_type Comment type. Default empty.1667 * @type array $comment_meta Optional. Array of key/value pairs to be stored in commentmeta for the1668 * new comment.1669 * @type int $user_id ID of the user who submitted the comment. Default 0.1670 * }1671 * @return int|false The new comment's ID on success, false on failure.1672 */1673function wp_insert_comment( $commentdata ) {1674 global $wpdb;1675 $data = wp_unslash( $commentdata );1676 $comment_author = ! isset( $data['comment_author'] ) ? '' : $data['comment_author'];1677 $comment_author_email = ! isset( $data['comment_author_email'] ) ? '' : $data['comment_author_email'];1678 $comment_author_url = ! isset( $data['comment_author_url'] ) ? '' : $data['comment_author_url'];1679 $comment_author_IP = ! isset( $data['comment_author_IP'] ) ? '' : $data['comment_author_IP'];1680 $comment_date = ! isset( $data['comment_date'] ) ? current_time( 'mysql' ) : $data['comment_date'];1681 $comment_date_gmt = ! isset( $data['comment_date_gmt'] ) ? get_gmt_from_date( $comment_date ) : $data['comment_date_gmt'];1682 $comment_post_ID = ! isset( $data['comment_post_ID'] ) ? 0 : $data['comment_post_ID'];1683 $comment_content = ! isset( $data['comment_content'] ) ? '' : $data['comment_content'];1684 $comment_karma = ! isset( $data['comment_karma'] ) ? 0 : $data['comment_karma'];1685 $comment_approved = ! isset( $data['comment_approved'] ) ? 1 : $data['comment_approved'];1686 $comment_agent = ! isset( $data['comment_agent'] ) ? '' : $data['comment_agent'];1687 $comment_type = ! isset( $data['comment_type'] ) ? '' : $data['comment_type'];1688 $comment_parent = ! isset( $data['comment_parent'] ) ? 0 : $data['comment_parent'];1689 $user_id = ! isset( $data['user_id'] ) ? 0 : $data['user_id'];1690 $compacted = compact( 'comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_author_IP', 'comment_date', 'comment_date_gmt', 'comment_content', 'comment_karma', 'comment_approved', 'comment_agent', 'comment_type', 'comment_parent', 'user_id' );1691 if ( ! $wpdb->insert( $wpdb->comments, $compacted ) ) {1692 return false;1693 }1694 $id = (int) $wpdb->insert_id;1695 if ( $comment_approved == 1 ) {1696 wp_update_comment_count( $comment_post_ID );1697 foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {1698 wp_cache_delete( "lastcommentmodified:$timezone", 'timeinfo' );1699 }1700 }1701 clean_comment_cache( $id );1702 $comment = get_comment( $id );1703 // If metadata is provided, store it.1704 if ( isset( $commentdata['comment_meta'] ) && is_array( $commentdata['comment_meta'] ) ) {1705 foreach ( $commentdata['comment_meta'] as $meta_key => $meta_value ) {1706 add_comment_meta( $comment->comment_ID, $meta_key, $meta_value, true );1707 }1708 }1709 /**1710 * Fires immediately after a comment is inserted into the database.1711 *1712 * @since 2.8.01713 *1714 * @param int $id The comment ID.1715 * @param WP_Comment $comment Comment object.1716 */1717 do_action( 'wp_insert_comment', $id, $comment );1718 return $id;1719}1720/**1721 * Filters and sanitizes comment data.1722 *1723 * Sets the comment data 'filtered' field to true when finished. This can be1724 * checked as to whether the comment should be filtered and to keep from1725 * filtering the same comment more than once.1726 *1727 * @since 2.0.01728 *1729 * @param array $commentdata Contains information on the comment.1730 * @return array Parsed comment information.1731 */1732function wp_filter_comment( $commentdata ) {1733 if ( isset( $commentdata['user_ID'] ) ) {1734 /**1735 * Filters the comment author's user id before it is set.1736 *1737 * The first time this filter is evaluated, 'user_ID' is checked1738 * (for back-compat), followed by the standard 'user_id' value.1739 *1740 * @since 1.5.01741 *1742 * @param int $user_ID The comment author's user ID.1743 */1744 $commentdata['user_id'] = apply_filters( 'pre_user_id', $commentdata['user_ID'] );1745 } elseif ( isset( $commentdata['user_id'] ) ) {1746 /** This filter is documented in wp-includes/comment.php */1747 $commentdata['user_id'] = apply_filters( 'pre_user_id', $commentdata['user_id'] );1748 }1749 /**1750 * Filters the comment author's browser user agent before it is set.1751 *1752 * @since 1.5.01753 *1754 * @param string $comment_agent The comment author's browser user agent.1755 */1756 $commentdata['comment_agent'] = apply_filters( 'pre_comment_user_agent', ( isset( $commentdata['comment_agent'] ) ? $commentdata['comment_agent'] : '' ) );1757 /** This filter is documented in wp-includes/comment.php */1758 $commentdata['comment_author'] = apply_filters( 'pre_comment_author_name', $commentdata['comment_author'] );1759 /**1760 * Filters the comment content before it is set.1761 *1762 * @since 1.5.01763 *1764 * @param string $comment_content The comment content.1765 */1766 $commentdata['comment_content'] = apply_filters( 'pre_comment_content', $commentdata['comment_content'] );1767 /**1768 * Filters the comment author's IP address before it is set.1769 *1770 * @since 1.5.01771 *1772 * @param string $comment_author_ip The comment author's IP address.1773 */1774 $commentdata['comment_author_IP'] = apply_filters( 'pre_comment_user_ip', $commentdata['comment_author_IP'] );1775 /** This filter is documented in wp-includes/comment.php */1776 $commentdata['comment_author_url'] = apply_filters( 'pre_comment_author_url', $commentdata['comment_author_url'] );1777 /** This filter is documented in wp-includes/comment.php */1778 $commentdata['comment_author_email'] = apply_filters( 'pre_comment_author_email', $commentdata['comment_author_email'] );1779 $commentdata['filtered'] = true;1780 return $commentdata;1781}1782/**1783 * Whether a comment should be blocked because of comment flood.1784 *1785 * @since 2.1.01786 *1787 * @param bool $block Whether plugin has already blocked comment.1788 * @param int $time_lastcomment Timestamp for last comment.1789 * @param int $time_newcomment Timestamp for new comment.1790 * @return bool Whether comment should be blocked.1791 */1792function wp_throttle_comment_flood( $block, $time_lastcomment, $time_newcomment ) {1793 if ( $block ) { // a plugin has already blocked... we'll let that decision stand1794 return $block;1795 }1796 if ( ( $time_newcomment - $time_lastcomment ) < 15 ) {1797 return true;1798 }1799 return false;1800}1801/**1802 * Adds a new comment to the database.1803 *1804 * Filters new comment to ensure that the fields are sanitized and valid before1805 * inserting comment into database. Calls {@see 'comment_post'} action with comment ID1806 * and whether comment is approved by WordPress. Also has {@see 'preprocess_comment'}1807 * filter for processing the comment data before the function handles it.1808 *1809 * We use `REMOTE_ADDR` here directly. If you are behind a proxy, you should ensure1810 * that it is properly set, such as in wp-config.php, for your environment.1811 *1812 * See {@link https://core.trac.wordpress.org/ticket/9235}1813 *1814 * @since 1.5.01815 * @since 4.3.0 'comment_agent' and 'comment_author_IP' can be set via `$commentdata`.1816 * @since 4.7.0 The `$avoid_die` parameter was added, allowing the function to1817 * return a WP_Error object instead of dying.1818 *1819 * @see wp_insert_comment()1820 * @global wpdb $wpdb WordPress database abstraction object.1821 *1822 * @param array $commentdata {1823 * Comment data.1824 *1825 * @type string $comment_author The name of the comment author.1826 * @type string $comment_author_email The comment author email address.1827 * @type string $comment_author_url The comment author URL.1828 * @type string $comment_content The content of the comment.1829 * @type string $comment_date The date the comment was submitted. Default is the current time.1830 * @type string $comment_date_gmt The date the comment was submitted in the GMT timezone.1831 * Default is `$comment_date` in the GMT timezone.1832 * @type int $comment_parent The ID of this comment's parent, if any. Default 0.1833 * @type int $comment_post_ID The ID of the post that relates to the comment.1834 * @type int $user_id The ID of the user who submitted the comment. Default 0.1835 * @type int $user_ID Kept for backward-compatibility. Use `$user_id` instead.1836 * @type string $comment_agent Comment author user agent. Default is the value of 'HTTP_USER_AGENT'1837 * in the `$_SERVER` superglobal sent in the original request.1838 * @type string $comment_author_IP Comment author IP address in IPv4 format. Default is the value of1839 * 'REMOTE_ADDR' in the `$_SERVER` superglobal sent in the original request.1840 * }1841 * @param bool $avoid_die Should errors be returned as WP_Error objects instead of1842 * executing wp_die()? Default false.1843 * @return int|false|WP_Error The ID of the comment on success, false or WP_Error on failure.1844 */1845function wp_new_comment( $commentdata, $avoid_die = false ) {1846 global $wpdb;1847 if ( isset( $commentdata['user_ID'] ) ) {1848 $commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID'];1849 }1850 $prefiltered_user_id = ( isset( $commentdata['user_id'] ) ) ? (int) $commentdata['user_id'] : 0;1851 /**1852 * Filters a comment's data before it is sanitized and inserted into the database.1853 *1854 * @since 1.5.01855 *1856 * @param array $commentdata Comment data.1857 */1858 $commentdata = apply_filters( 'preprocess_comment', $commentdata );1859 $commentdata['comment_post_ID'] = (int) $commentdata['comment_post_ID'];1860 if ( isset( $commentdata['user_ID'] ) && $prefiltered_user_id !== (int) $commentdata['user_ID'] ) {1861 $commentdata['user_id'] = $commentdata['user_ID'] = (int) $commentdata['user_ID'];1862 } elseif ( isset( $commentdata['user_id'] ) ) {1863 $commentdata['user_id'] = (int) $commentdata['user_id'];1864 }1865 $commentdata['comment_parent'] = isset( $commentdata['comment_parent'] ) ? absint( $commentdata['comment_parent'] ) : 0;1866 $parent_status = ( 0 < $commentdata['comment_parent'] ) ? wp_get_comment_status( $commentdata['comment_parent'] ) : '';1867 $commentdata['comment_parent'] = ( 'approved' == $parent_status || 'unapproved' == $parent_status ) ? $commentdata['comment_parent'] : 0;1868 if ( ! isset( $commentdata['comment_author_IP'] ) ) {1869 $commentdata['comment_author_IP'] = $_SERVER['REMOTE_ADDR'];1870 }1871 $commentdata['comment_author_IP'] = preg_replace( '/[^0-9a-fA-F:., ]/', '', $commentdata['comment_author_IP'] );1872 if ( ! isset( $commentdata['comment_agent'] ) ) {1873 $commentdata['comment_agent'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';1874 }1875 $commentdata['comment_agent'] = substr( $commentdata['comment_agent'], 0, 254 );1876 if ( empty( $commentdata['comment_date'] ) ) {1877 $commentdata['comment_date'] = current_time( 'mysql' );1878 }1879 if ( empty( $commentdata['comment_date_gmt'] ) ) {1880 $commentdata['comment_date_gmt'] = current_time( 'mysql', 1 );1881 }1882 $commentdata = wp_filter_comment( $commentdata );1883 $commentdata['comment_approved'] = wp_allow_comment( $commentdata, $avoid_die );1884 if ( is_wp_error( $commentdata['comment_approved'] ) ) {1885 return $commentdata['comment_approved'];1886 }1887 $comment_ID = wp_insert_comment( $commentdata );1888 if ( ! $comment_ID ) {1889 $fields = array( 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content' );1890 foreach ( $fields as $field ) {1891 if ( isset( $commentdata[ $field ] ) ) {1892 $commentdata[ $field ] = $wpdb->strip_invalid_text_for_column( $wpdb->comments, $field, $commentdata[ $field ] );1893 }1894 }1895 $commentdata = wp_filter_comment( $commentdata );1896 $commentdata['comment_approved'] = wp_allow_comment( $commentdata, $avoid_die );1897 if ( is_wp_error( $commentdata['comment_approved'] ) ) {1898 return $commentdata['comment_approved'];1899 }1900 $comment_ID = wp_insert_comment( $commentdata );1901 if ( ! $comment_ID ) {1902 return false;1903 }1904 }1905 /**1906 * Fires immediately after a comment is inserted into the database.1907 *1908 * @since 1.2.01909 * @since 4.5.0 The `$commentdata` parameter was added.1910 *1911 * @param int $comment_ID The comment ID.1912 * @param int|string $comment_approved 1 if the comment is approved, 0 if not, 'spam' if spam.1913 * @param array $commentdata Comment data.1914 */1915 do_action( 'comment_post', $comment_ID, $commentdata['comment_approved'], $commentdata );1916 return $comment_ID;1917}1918/**1919 * Send a comment moderation notification to the comment moderator.1920 *1921 * @since 4.4.01922 *1923 * @param int $comment_ID ID of the comment.1924 * @return bool True on success, false on failure.1925 */1926function wp_new_comment_notify_moderator( $comment_ID ) {1927 $comment = get_comment( $comment_ID );1928 // Only send notifications for pending comments.1929 $maybe_notify = ( '0' == $comment->comment_approved );1930 /** This filter is documented in wp-includes/comment.php */1931 $maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_ID );1932 if ( ! $maybe_notify ) {1933 return false;1934 }1935 return wp_notify_moderator( $comment_ID );1936}1937/**1938 * Send a notification of a new comment to the post author.1939 *1940 * @since 4.4.01941 *1942 * Uses the {@see 'notify_post_author'} filter to determine whether the post author1943 * should be notified when a new comment is added, overriding site setting.1944 *1945 * @param int $comment_ID Comment ID.1946 * @return bool True on success, false on failure.1947 */1948function wp_new_comment_notify_postauthor( $comment_ID ) {1949 $comment = get_comment( $comment_ID );1950 $maybe_notify = get_option( 'comments_notify' );1951 /**1952 * Filters whether to send the post author new comment notification emails,1953 * overriding the site setting.1954 *1955 * @since 4.4.01956 *1957 * @param bool $maybe_notify Whether to notify the post author about the new comment.1958 * @param int $comment_ID The ID of the comment for the notification.1959 */1960 $maybe_notify = apply_filters( 'notify_post_author', $maybe_notify, $comment_ID );1961 /*1962 * wp_notify_postauthor() checks if notifying the author of their own comment.1963 * By default, it won't, but filters can override this.1964 */1965 if ( ! $maybe_notify ) {1966 return false;1967 }1968 // Only send notifications for approved comments.1969 if ( ! isset( $comment->comment_approved ) || '1' != $comment->comment_approved ) {1970 return false;1971 }1972 return wp_notify_postauthor( $comment_ID );1973}1974/**1975 * Sets the status of a comment.1976 *1977 * The {@see 'wp_set_comment_status'} action is called after the comment is handled.1978 * If the comment status is not in the list, then false is returned.1979 *1980 * @since 1.0.01981 *1982 * @global wpdb $wpdb WordPress database abstraction object.1983 *1984 * @param int|WP_Comment $comment_id Comment ID or WP_Comment object.1985 * @param string $comment_status New comment status, either 'hold', 'approve', 'spam', or 'trash'.1986 * @param bool $wp_error Whether to return a WP_Error object if there is a failure. Default is false.1987 * @return bool|WP_Error True on success, false or WP_Error on failure.1988 */1989function wp_set_comment_status( $comment_id, $comment_status, $wp_error = false ) {1990 global $wpdb;1991 switch ( $comment_status ) {1992 case 'hold':1993 case '0':1994 $status = '0';1995 break;1996 case 'approve':1997 case '1':1998 $status = '1';1999 add_action( 'wp_set_comment_status', 'wp_new_comment_notify_postauthor' );2000 break;2001 case 'spam':2002 $status = 'spam';2003 break;2004 case 'trash':2005 $status = 'trash';2006 break;2007 default:2008 return false;2009 }2010 $comment_old = clone get_comment( $comment_id );2011 if ( ! $wpdb->update( $wpdb->comments, array( 'comment_approved' => $status ), array( 'comment_ID' => $comment_old->comment_ID ) ) ) {2012 if ( $wp_error ) {2013 return new WP_Error( 'db_update_error', __( 'Could not update comment status' ), $wpdb->last_error );2014 } else {2015 return false;2016 }2017 }2018 clean_comment_cache( $comment_old->comment_ID );2019 $comment = get_comment( $comment_old->comment_ID );2020 /**2021 * Fires immediately before transitioning a comment's status from one to another2022 * in the database.2023 *2024 * @since 1.5.02025 *2026 * @param int $comment_id Comment ID.2027 * @param string|bool $comment_status Current comment status. Possible values include2028 * 'hold', 'approve', 'spam', 'trash', or false.2029 */2030 do_action( 'wp_set_comment_status', $comment->comment_ID, $comment_status );2031 wp_transition_comment_status( $comment_status, $comment_old->comment_approved, $comment );2032 wp_update_comment_count( $comment->comment_post_ID );2033 return true;2034}2035/**2036 * Updates an existing comment in the database.2037 *2038 * Filters the comment and makes sure certain fields are valid before updating.2039 *2040 * @since 2.0.02041 * @since 4.9.0 Add updating comment meta during comment update.2042 *2043 * @global wpdb $wpdb WordPress database abstraction object.2044 *2045 * @param array $commentarr Contains information on the comment.2046 * @return int Comment was updated if value is 1, or was not updated if value is 0.2047 */2048function wp_update_comment( $commentarr ) {2049 global $wpdb;2050 // First, get all of the original fields2051 $comment = get_comment( $commentarr['comment_ID'], ARRAY_A );2052 if ( empty( $comment ) ) {2053 return 0;2054 }2055 // Make sure that the comment post ID is valid (if specified).2056 if ( ! empty( $commentarr['comment_post_ID'] ) && ! get_post( $commentarr['comment_post_ID'] ) ) {2057 return 0;2058 }2059 // Escape data pulled from DB.2060 $comment = wp_slash( $comment );2061 $old_status = $comment['comment_approved'];2062 // Merge old and new fields with new fields overwriting old ones.2063 $commentarr = array_merge( $comment, $commentarr );2064 $commentarr = wp_filter_comment( $commentarr );2065 // Now extract the merged array.2066 $data = wp_unslash( $commentarr );2067 /**2068 * Filters the comment content before it is updated in the database.2069 *2070 * @since 1.5.02071 *2072 * @param string $comment_content The comment data.2073 */2074 $data['comment_content'] = apply_filters( 'comment_save_pre', $data['comment_content'] );2075 $data['comment_date_gmt'] = get_gmt_from_date( $data['comment_date'] );2076 if ( ! isset( $data['comment_approved'] ) ) {2077 $data['comment_approved'] = 1;2078 } elseif ( 'hold' == $data['comment_approved'] ) {2079 $data['comment_approved'] = 0;2080 } elseif ( 'approve' == $data['comment_approved'] ) {2081 $data['comment_approved'] = 1;2082 }2083 $comment_ID = $data['comment_ID'];2084 $comment_post_ID = $data['comment_post_ID'];2085 /**2086 * Filters the comment data immediately before it is updated in the database.2087 *2088 * Note: data being passed to the filter is already unslashed.2089 *2090 * @since 4.7.02091 *2092 * @param array $data The new, processed comment data.2093 * @param array $comment The old, unslashed comment data.2094 * @param array $commentarr The new, raw comment data.2095 */2096 $data = apply_filters( 'wp_update_comment_data', $data, $comment, $commentarr );2097 $keys = array( 'comment_post_ID', 'comment_content', 'comment_author', 'comment_author_email', 'comment_approved', 'comment_karma', 'comment_author_url', 'comment_date', 'comment_date_gmt', 'comment_type', 'comment_parent', 'user_id', 'comment_agent', 'comment_author_IP' );2098 $data = wp_array_slice_assoc( $data, $keys );2099 $rval = $wpdb->update( $wpdb->comments, $data, compact( 'comment_ID' ) );2100 // If metadata is provided, store it.2101 if ( isset( $commentarr['comment_meta'] ) && is_array( $commentarr['comment_meta'] ) ) {2102 foreach ( $commentarr['comment_meta'] as $meta_key => $meta_value ) {2103 update_comment_meta( $comment_ID, $meta_key, $meta_value );2104 }2105 }2106 clean_comment_cache( $comment_ID );2107 wp_update_comment_count( $comment_post_ID );2108 /**2109 * Fires immediately after a comment is updated in the database.2110 *2111 * The hook also fires immediately before comment status transition hooks are fired.2112 *2113 * @since 1.2.02114 * @since 4.6.0 Added the `$data` parameter.2115 *2116 * @param int $comment_ID The comment ID.2117 * @param array $data Comment data.2118 */2119 do_action( 'edit_comment', $comment_ID, $data );2120 $comment = get_comment( $comment_ID );2121 wp_transition_comment_status( $comment->comment_approved, $old_status, $comment );2122 return $rval;2123}2124/**2125 * Whether to defer comment counting.2126 *2127 * When setting $defer to true, all post comment counts will not be updated2128 * until $defer is set to false. When $defer is set to false, then all2129 * previously deferred updated post comment counts will then be automatically2130 * updated without having to call wp_update_comment_count() after.2131 *2132 * @since 2.5.02133 * @staticvar bool $_defer2134 *2135 * @param bool $defer2136 * @return bool2137 */2138function wp_defer_comment_counting( $defer = null ) {2139 static $_defer = false;2140 if ( is_bool( $defer ) ) {2141 $_defer = $defer;2142 // flush any deferred counts2143 if ( ! $defer ) {2144 wp_update_comment_count( null, true );2145 }2146 }2147 return $_defer;2148}2149/**2150 * Updates the comment count for post(s).2151 *2152 * When $do_deferred is false (is by default) and the comments have been set to2153 * be deferred, the post_id will be added to a queue, which will be updated at a2154 * later date and only updated once per post ID.2155 *2156 * If the comments have not be set up to be deferred, then the post will be2157 * updated. When $do_deferred is set to true, then all previous deferred post2158 * IDs will be updated along with the current $post_id.2159 *2160 * @since 2.1.02161 * @see wp_update_comment_count_now() For what could cause a false return value2162 *2163 * @staticvar array $_deferred2164 *2165 * @param int|null $post_id Post ID.2166 * @param bool $do_deferred Optional. Whether to process previously deferred2167 * post comment counts. Default false.2168 * @return bool|void True on success, false on failure or if post with ID does2169 * not exist.2170 */2171function wp_update_comment_count( $post_id, $do_deferred = false ) {2172 static $_deferred = array();2173 if ( empty( $post_id ) && ! $do_deferred ) {2174 return false;2175 }2176 if ( $do_deferred ) {2177 $_deferred = array_unique( $_deferred );2178 foreach ( $_deferred as $i => $_post_id ) {2179 wp_update_comment_count_now( $_post_id );2180 unset( $_deferred[ $i ] );2181 /** @todo Move this outside of the foreach and reset $_deferred to an array instead */2182 }2183 }2184 if ( wp_defer_comment_counting() ) {2185 $_deferred[] = $post_id;2186 return true;2187 } elseif ( $post_id ) {2188 return wp_update_comment_count_now( $post_id );2189 }2190}2191/**2192 * Updates the comment count for the post.2193 *2194 * @since 2.5.02195 *2196 * @global wpdb $wpdb WordPress database abstraction object.2197 *2198 * @param int $post_id Post ID2199 * @return bool True on success, false on '0' $post_id or if post with ID does not exist.2200 */2201function wp_update_comment_count_now( $post_id ) {2202 global $wpdb;2203 $post_id = (int) $post_id;2204 if ( ! $post_id ) {2205 return false;2206 }2207 wp_cache_delete( 'comments-0', 'counts' );2208 wp_cache_delete( "comments-{$post_id}", 'counts' );2209 if ( ! $post = get_post( $post_id ) ) {2210 return false;2211 }2212 $old = (int) $post->comment_count;2213 /**2214 * Filters a post's comment count before it is updated in the database.2215 *2216 * @since 4.5.02217 *2218 * @param int $new The new comment count. Default null.2219 * @param int $old The old comment count.2220 * @param int $post_id Post ID.2221 */2222 $new = apply_filters( 'pre_wp_update_comment_count_now', null, $old, $post_id );2223 if ( is_null( $new ) ) {2224 $new = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1'", $post_id ) );2225 } else {2226 $new = (int) $new;2227 }2228 $wpdb->update( $wpdb->posts, array( 'comment_count' => $new ), array( 'ID' => $post_id ) );2229 clean_post_cache( $post );2230 /**2231 * Fires immediately after a post's comment count is updated in the database.2232 *2233 * @since 2.3.02234 *2235 * @param int $post_id Post ID.2236 * @param int $new The new comment count.2237 * @param int $old The old comment count.2238 */2239 do_action( 'wp_update_comment_count', $post_id, $new, $old );2240 /** This action is documented in wp-includes/post.php */2241 do_action( "edit_post_{$post->post_type}", $post_id, $post );2242 /** This action is documented in wp-includes/post.php */2243 do_action( 'edit_post', $post_id, $post );2244 return true;2245}2246//2247// Ping and trackback functions.2248//2249/**2250 * Finds a pingback server URI based on the given URL.2251 *2252 * Checks the HTML for the rel="pingback" link and x-pingback headers. It does2253 * a check for the x-pingback headers first and returns that, if available. The2254 * check for the rel="pingback" has more overhead than just the header.2255 *2256 * @since 1.5.02257 *2258 * @param string $url URL to ping.2259 * @param int $deprecated Not Used.2260 * @return false|string False on failure, string containing URI on success.2261 */2262function discover_pingback_server_uri( $url, $deprecated = '' ) {2263 if ( ! empty( $deprecated ) ) {2264 _deprecated_argument( __FUNCTION__, '2.7.0' );2265 }2266 $pingback_str_dquote = 'rel="pingback"';2267 $pingback_str_squote = 'rel=\'pingback\'';2268 /** @todo Should use Filter Extension or custom preg_match instead. */2269 $parsed_url = parse_url( $url );2270 if ( ! isset( $parsed_url['host'] ) ) { // Not a URL. This should never happen.2271 return false;2272 }2273 //Do not search for a pingback server on our own uploads2274 $uploads_dir = wp_get_upload_dir();2275 if ( 0 === strpos( $url, $uploads_dir['baseurl'] ) ) {2276 return false;2277 }2278 $response = wp_safe_remote_head(2279 $url,2280 array(2281 'timeout' => 2,2282 'httpversion' => '1.0',2283 )2284 );2285 if ( is_wp_error( $response ) ) {2286 return false;2287 }2288 if ( wp_remote_retrieve_header( $response, 'x-pingback' ) ) {2289 return wp_remote_retrieve_header( $response, 'x-pingback' );2290 }2291 // Not an (x)html, sgml, or xml page, no use going further.2292 if ( preg_match( '#(image|audio|video|model)/#is', wp_remote_retrieve_header( $response, 'content-type' ) ) ) {2293 return false;2294 }2295 // Now do a GET since we're going to look in the html headers (and we're sure it's not a binary file)2296 $response = wp_safe_remote_get(2297 $url,2298 array(2299 'timeout' => 2,2300 'httpversion' => '1.0',2301 )2302 );2303 if ( is_wp_error( $response ) ) {2304 return false;2305 }2306 $contents = wp_remote_retrieve_body( $response );2307 $pingback_link_offset_dquote = strpos( $contents, $pingback_str_dquote );2308 $pingback_link_offset_squote = strpos( $contents, $pingback_str_squote );2309 if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) {2310 $quote = ( $pingback_link_offset_dquote ) ? '"' : '\'';2311 $pingback_link_offset = ( $quote == '"' ) ? $pingback_link_offset_dquote : $pingback_link_offset_squote;2312 $pingback_href_pos = @strpos( $contents, 'href=', $pingback_link_offset );2313 $pingback_href_start = $pingback_href_pos + 6;2314 $pingback_href_end = @strpos( $contents, $quote, $pingback_href_start );2315 $pingback_server_url_len = $pingback_href_end - $pingback_href_start;2316 $pingback_server_url = substr( $contents, $pingback_href_start, $pingback_server_url_len );2317 // We may find rel="pingback" but an incomplete pingback URL2318 if ( $pingback_server_url_len > 0 ) { // We got it!2319 return $pingback_server_url;2320 }2321 }2322 return false;2323}2324/**2325 * Perform all pingbacks, enclosures, trackbacks, and send to pingback services.2326 *2327 * @since 2.1.02328 *2329 * @global wpdb $wpdb WordPress database abstraction object.2330 */2331function do_all_pings() {2332 global $wpdb;2333 // Do pingbacks2334 while ( $ping = $wpdb->get_row( "SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_pingme' LIMIT 1" ) ) {2335 delete_metadata_by_mid( 'post', $ping->meta_id );2336 pingback( $ping->post_content, $ping->ID );2337 }2338 // Do Enclosures2339 while ( $enclosure = $wpdb->get_row( "SELECT ID, post_content, meta_id FROM {$wpdb->posts}, {$wpdb->postmeta} WHERE {$wpdb->posts}.ID = {$wpdb->postmeta}.post_id AND {$wpdb->postmeta}.meta_key = '_encloseme' LIMIT 1" ) ) {2340 delete_metadata_by_mid( 'post', $enclosure->meta_id );2341 do_enclose( $enclosure->post_content, $enclosure->ID );2342 }2343 // Do Trackbacks2344 $trackbacks = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE to_ping <> '' AND post_status = 'publish'" );2345 if ( is_array( $trackbacks ) ) {2346 foreach ( $trackbacks as $trackback ) {2347 do_trackbacks( $trackback );2348 }2349 }2350 //Do Update Services/Generic Pings2351 generic_ping();2352}2353/**2354 * Perform trackbacks.2355 *2356 * @since 1.5.02357 * @since 4.7.0 `$post_id` can be a WP_Post object.2358 *2359 * @global wpdb $wpdb WordPress database abstraction object.2360 *2361 * @param int|WP_Post $post_id Post object or ID to do trackbacks on.2362 */2363function do_trackbacks( $post_id ) {2364 global $wpdb;2365 $post = get_post( $post_id );2366 if ( ! $post ) {2367 return false;2368 }2369 $to_ping = get_to_ping( $post );2370 $pinged = get_pung( $post );2371 if ( empty( $to_ping ) ) {2372 $wpdb->update( $wpdb->posts, array( 'to_ping' => '' ), array( 'ID' => $post->ID ) );2373 return;2374 }2375 if ( empty( $post->post_excerpt ) ) {2376 /** This filter is documented in wp-includes/post-template.php */2377 $excerpt = apply_filters( 'the_content', $post->post_content, $post->ID );2378 } else {2379 /** This filter is documented in wp-includes/post-template.php */2380 $excerpt = apply_filters( 'the_excerpt', $post->post_excerpt );2381 }2382 $excerpt = str_replace( ']]>', ']]>', $excerpt );2383 $excerpt = wp_html_excerpt( $excerpt, 252, '…' );2384 /** This filter is documented in wp-includes/post-template.php */2385 $post_title = apply_filters( 'the_title', $post->post_title, $post->ID );2386 $post_title = strip_tags( $post_title );2387 if ( $to_ping ) {2388 foreach ( (array) $to_ping as $tb_ping ) {2389 $tb_ping = trim( $tb_ping );2390 if ( ! in_array( $tb_ping, $pinged ) ) {2391 trackback( $tb_ping, $post_title, $excerpt, $post->ID );2392 $pinged[] = $tb_ping;2393 } else {2394 $wpdb->query(2395 $wpdb->prepare(2396 "UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s,2397 '')) WHERE ID = %d",2398 $tb_ping,2399 $post->ID2400 )2401 );2402 }2403 }2404 }2405}2406/**2407 * Sends pings to all of the ping site services.2408 *2409 * @since 1.2.02410 *2411 * @param int $post_id Post ID.2412 * @return int Same as Post ID from parameter2413 */2414function generic_ping( $post_id = 0 ) {2415 $services = get_option( 'ping_sites' );2416 $services = explode( "\n", $services );2417 foreach ( (array) $services as $service ) {2418 $service = trim( $service );2419 if ( '' != $service ) {2420 weblog_ping( $service );2421 }2422 }2423 return $post_id;2424}2425/**2426 * Pings back the links found in a post.2427 *2428 * @since 0.712429 * @since 4.7.0 `$post_id` can be a WP_Post object.2430 *2431 * @param string $content Post content to check for links. If empty will retrieve from post.2432 * @param int|WP_Post $post_id Post Object or ID.2433 */2434function pingback( $content, $post_id ) {2435 include_once( ABSPATH . WPINC . '/class-IXR.php' );2436 include_once( ABSPATH . WPINC . '/class-wp-http-ixr-client.php' );2437 // original code by Mort (http://mort.mine.nu:8080)2438 $post_links = array();2439 $post = get_post( $post_id );2440 if ( ! $post ) {2441 return;2442 }2443 $pung = get_pung( $post );2444 if ( empty( $content ) ) {2445 $content = $post->post_content;2446 }2447 // Step 12448 // Parsing the post, external links (if any) are stored in the $post_links array2449 $post_links_temp = wp_extract_urls( $content );2450 // Step 2.2451 // Walking thru the links array2452 // first we get rid of links pointing to sites, not to specific files2453 // Example:2454 // http://dummy-weblog.org2455 // http://dummy-weblog.org/2456 // http://dummy-weblog.org/post.php2457 // We don't wanna ping first and second types, even if they have a valid <link/>2458 foreach ( (array) $post_links_temp as $link_test ) :2459 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 itself2460 && ! is_local_attachment( $link_test ) ) : // Also, let's never ping local attachments.2461 if ( $test = @parse_url( $link_test ) ) {2462 if ( isset( $test['query'] ) ) {2463 $post_links[] = $link_test;2464 } elseif ( isset( $test['path'] ) && ( $test['path'] != '/' ) && ( $test['path'] != '' ) ) {2465 $post_links[] = $link_test;2466 }2467 }2468 endif;2469 endforeach;2470 $post_links = array_unique( $post_links );2471 /**2472 * Fires just before pinging back links found in a post.2473 *2474 * @since 2.0.02475 *2476 * @param string[] $post_links Array of link URLs to be checked (passed by reference).2477 * @param string[] $pung Array of link URLs already pinged (passed by reference).2478 * @param int $post_ID The post ID.2479 */2480 do_action_ref_array( 'pre_ping', array( &$post_links, &$pung, $post->ID ) );2481 foreach ( (array) $post_links as $pagelinkedto ) {2482 $pingback_server_url = discover_pingback_server_uri( $pagelinkedto );2483 if ( $pingback_server_url ) {2484 @ set_time_limit( 60 );2485 // Now, the RPC call2486 $pagelinkedfrom = get_permalink( $post );2487 // using a timeout of 3 seconds should be enough to cover slow servers2488 $client = new WP_HTTP_IXR_Client( $pingback_server_url );2489 $client->timeout = 3;2490 /**2491 * Filters the user agent sent when pinging-back a URL.2492 *2493 * @since 2.9.02494 *2495 * @param string $concat_useragent The user agent concatenated with ' -- WordPress/'2496 * and the WordPress version.2497 * @param string $useragent The useragent.2498 * @param string $pingback_server_url The server URL being linked to.2499 * @param string $pagelinkedto URL of page linked to.2500 * @param string $pagelinkedfrom URL of page linked from.2501 */2502 $client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . get_bloginfo( 'version' ), $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom );2503 // when set to true, this outputs debug messages by itself2504 $client->debug = false;2505 if ( $client->query( 'pingback.ping', $pagelinkedfrom, $pagelinkedto ) || ( isset( $client->error->code ) && 48 == $client->error->code ) ) { // Already registered2506 add_ping( $post, $pagelinkedto );2507 }2508 }2509 }2510}2511/**2512 * Check whether blog is public before returning sites.2513 *2514 * @since 2.1.02515 *2516 * @param mixed $sites Will return if blog is public, will not return if not public.2517 * @return mixed Empty string if blog is not public, returns $sites, if site is public.2518 */2519function privacy_ping_filter( $sites ) {2520 if ( '0' != get_option( 'blog_public' ) ) {2521 return $sites;2522 } else {2523 return '';2524 }2525}2526/**2527 * Send a Trackback.2528 *2529 * Updates database when sending trackback to prevent duplicates.2530 *2531 * @since 0.712532 *2533 * @global wpdb $wpdb WordPress database abstraction object.2534 *2535 * @param string $trackback_url URL to send trackbacks.2536 * @param string $title Title of post.2537 * @param string $excerpt Excerpt of post.2538 * @param int $ID Post ID.2539 * @return int|false|void Database query from update.2540 */2541function trackback( $trackback_url, $title, $excerpt, $ID ) {2542 global $wpdb;2543 if ( empty( $trackback_url ) ) {2544 return;2545 }2546 $options = array();2547 $options['timeout'] = 10;2548 $options['body'] = array(2549 'title' => $title,2550 'url' => get_permalink( $ID ),2551 'blog_name' => get_option( 'blogname' ),2552 'excerpt' => $excerpt,2553 );2554 $response = wp_safe_remote_post( $trackback_url, $options );2555 if ( is_wp_error( $response ) ) {2556 return;2557 }2558 $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET pinged = CONCAT(pinged, '\n', %s) WHERE ID = %d", $trackback_url, $ID ) );2559 return $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->posts SET to_ping = TRIM(REPLACE(to_ping, %s, '')) WHERE ID = %d", $trackback_url, $ID ) );2560}2561/**2562 * Send a pingback.2563 *2564 * @since 1.2.02565 *2566 * @param string $server Host of blog to connect to.2567 * @param string $path Path to send the ping.2568 */2569function weblog_ping( $server = '', $path = '' ) {2570 include_once( ABSPATH . WPINC . '/class-IXR.php' );2571 include_once( ABSPATH . WPINC . '/class-wp-http-ixr-client.php' );2572 // using a timeout of 3 seconds should be enough to cover slow servers2573 $client = new WP_HTTP_IXR_Client( $server, ( ( ! strlen( trim( $path ) ) || ( '/' == $path ) ) ? false : $path ) );2574 $client->timeout = 3;2575 $client->useragent .= ' -- WordPress/' . get_bloginfo( 'version' );2576 // when set to true, this outputs debug messages by itself2577 $client->debug = false;2578 $home = trailingslashit( home_url() );2579 if ( ! $client->query( 'weblogUpdates.extendedPing', get_option( 'blogname' ), $home, get_bloginfo( 'rss2_url' ) ) ) { // then try a normal ping2580 $client->query( 'weblogUpdates.ping', get_option( 'blogname' ), $home );2581 }2582}2583/**2584 * Default filter attached to pingback_ping_source_uri to validate the pingback's Source URI2585 *2586 * @since 3.5.12587 * @see wp_http_validate_url()2588 *2589 * @param string $source_uri2590 * @return string2591 */2592function pingback_ping_source_uri( $source_uri ) {2593 return (string) wp_http_validate_url( $source_uri );2594}2595/**2596 * Default filter attached to xmlrpc_pingback_error.2597 *2598 * Returns a generic pingback error code unless the error code is 48,2599 * which reports that the pingback is already registered.2600 *2601 * @since 3.5.12602 * @link https://www.hixie.ch/specs/pingback/pingback#TOC32603 *2604 * @param IXR_Error $ixr_error2605 * @return IXR_Error2606 */2607function xmlrpc_pingback_error( $ixr_error ) {2608 if ( $ixr_error->code === 48 ) {2609 return $ixr_error;2610 }2611 return new IXR_Error( 0, '' );2612}2613//2614// Cache2615//2616/**2617 * Removes a comment from the object cache.2618 *2619 * @since 2.3.02620 *2621 * @param int|array $ids Comment ID or an array of comment IDs to remove from cache.2622 */2623function clean_comment_cache( $ids ) {2624 foreach ( (array) $ids as $id ) {2625 wp_cache_delete( $id, 'comment' );2626 /**2627 * Fires immediately after a comment has been removed from the object cache.2628 *2629 * @since 4.5.02630 *2631 * @param int $id Comment ID.2632 */2633 do_action( 'clean_comment_cache', $id );2634 }2635 wp_cache_set( 'last_changed', microtime(), 'comment' );2636}2637/**2638 * Updates the comment cache of given comments.2639 *2640 * Will add the comments in $comments to the cache. If comment ID already exists2641 * in the comment cache then it will not be updated. The comment is added to the2642 * cache using the comment group with the key using the ID of the comments.2643 *2644 * @since 2.3.02645 * @since 4.4.0 Introduced the `$update_meta_cache` parameter.2646 *2647 * @param WP_Comment[] $comments Array of comment objects2648 * @param bool $update_meta_cache Whether to update commentmeta cache. Default true.2649 */2650function update_comment_cache( $comments, $update_meta_cache = true ) {2651 foreach ( (array) $comments as $comment ) {2652 wp_cache_add( $comment->comment_ID, $comment, 'comment' );2653 }2654 if ( $update_meta_cache ) {2655 // Avoid `wp_list_pluck()` in case `$comments` is passed by reference.2656 $comment_ids = array();2657 foreach ( $comments as $comment ) {2658 $comment_ids[] = $comment->comment_ID;2659 }2660 update_meta_cache( 'comment', $comment_ids );2661 }2662}2663/**2664 * Adds any comments from the given IDs to the cache that do not already exist in cache.2665 *2666 * @since 4.4.02667 * @access private2668 *2669 * @see update_comment_cache()2670 * @global wpdb $wpdb WordPress database abstraction object.2671 *2672 * @param int[] $comment_ids Array of comment IDs.2673 * @param bool $update_meta_cache Optional. Whether to update the meta cache. Default true.2674 */2675function _prime_comment_caches( $comment_ids, $update_meta_cache = true ) {2676 global $wpdb;2677 $non_cached_ids = _get_non_cached_ids( $comment_ids, 'comment' );2678 if ( ! empty( $non_cached_ids ) ) {2679 $fresh_comments = $wpdb->get_results( sprintf( "SELECT $wpdb->comments.* FROM $wpdb->comments WHERE comment_ID IN (%s)", join( ',', array_map( 'intval', $non_cached_ids ) ) ) );2680 update_comment_cache( $fresh_comments, $update_meta_cache );2681 }2682}2683//2684// Internal2685//2686/**2687 * Close comments on old posts on the fly, without any extra DB queries. Hooked to the_posts.2688 *2689 * @access private2690 * @since 2.7.02691 *2692 * @param WP_Post $posts Post data object.2693 * @param WP_Query $query Query object.2694 * @return array2695 */2696function _close_comments_for_old_posts( $posts, $query ) {2697 if ( empty( $posts ) || ! $query->is_singular() || ! get_option( 'close_comments_for_old_posts' ) ) {2698 return $posts;2699 }2700 /**2701 * Filters the list of post types to automatically close comments for.2702 *2703 * @since 3.2.02704 *2705 * @param string[] $post_types An array of post type names.2706 */2707 $post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );2708 if ( ! in_array( $posts[0]->post_type, $post_types ) ) {2709 return $posts;2710 }2711 $days_old = (int) get_option( 'close_comments_days_old' );2712 if ( ! $days_old ) {2713 return $posts;2714 }2715 if ( time() - strtotime( $posts[0]->post_date_gmt ) > ( $days_old * DAY_IN_SECONDS ) ) {2716 $posts[0]->comment_status = 'closed';2717 $posts[0]->ping_status = 'closed';2718 }2719 return $posts;2720}2721/**2722 * Close comments on an old post. Hooked to comments_open and pings_open.2723 *2724 * @access private2725 * @since 2.7.02726 *2727 * @param bool $open Comments open or closed2728 * @param int $post_id Post ID2729 * @return bool $open2730 */2731function _close_comments_for_old_post( $open, $post_id ) {2732 if ( ! $open ) {2733 return $open;2734 }2735 if ( ! get_option( 'close_comments_for_old_posts' ) ) {2736 return $open;2737 }2738 $days_old = (int) get_option( 'close_comments_days_old' );2739 if ( ! $days_old ) {2740 return $open;2741 }2742 $post = get_post( $post_id );2743 /** This filter is documented in wp-includes/comment.php */2744 $post_types = apply_filters( 'close_comments_for_post_types', array( 'post' ) );2745 if ( ! in_array( $post->post_type, $post_types ) ) {2746 return $open;2747 }2748 // Undated drafts should not show up as comments closed.2749 if ( '0000-00-00 00:00:00' === $post->post_date_gmt ) {2750 return $open;2751 }2752 if ( time() - strtotime( $post->post_date_gmt ) > ( $days_old * DAY_IN_SECONDS ) ) {2753 return false;2754 }2755 return $open;2756}2757/**2758 * Handles the submission of a comment, usually posted to wp-comments-post.php via a comment form.2759 *2760 * This function expects unslashed data, as opposed to functions such as `wp_new_comment()` which2761 * expect slashed data.2762 *2763 * @since 4.4.02764 *2765 * @param array $comment_data {2766 * Comment data.2767 *2768 * @type string|int $comment_post_ID The ID of the post that relates to the comment.2769 * @type string $author The name of the comment author.2770 * @type string $email The comment author email address.2771 * @type string $url The comment author URL.2772 * @type string $comment The content of the comment.2773 * @type string|int $comment_parent The ID of this comment's parent, if any. Default 0.2774 * @type string $_wp_unfiltered_html_comment The nonce value for allowing unfiltered HTML.2775 * }2776 * @return WP_Comment|WP_Error A WP_Comment object on success, a WP_Error object on failure.2777 */2778function wp_handle_comment_submission( $comment_data ) {2779 $comment_post_ID = $comment_parent = $user_ID = 0;2780 $comment_author = $comment_author_email = $comment_author_url = $comment_content = null;2781 if ( isset( $comment_data['comment_post_ID'] ) ) {2782 $comment_post_ID = (int) $comment_data['comment_post_ID'];2783 }2784 if ( isset( $comment_data['author'] ) && is_string( $comment_data['author'] ) ) {2785 $comment_author = trim( strip_tags( $comment_data['author'] ) );2786 }2787 if ( isset( $comment_data['email'] ) && is_string( $comment_data['email'] ) ) {2788 $comment_author_email = trim( $comment_data['email'] );2789 }2790 if ( isset( $comment_data['url'] ) && is_string( $comment_data['url'] ) ) {2791 $comment_author_url = trim( $comment_data['url'] );2792 }2793 if ( isset( $comment_data['comment'] ) && is_string( $comment_data['comment'] ) ) {2794 $comment_content = trim( $comment_data['comment'] );2795 }2796 if ( isset( $comment_data['comment_parent'] ) ) {2797 $comment_parent = absint( $comment_data['comment_parent'] );2798 }2799 $post = get_post( $comment_post_ID );2800 if ( empty( $post->comment_status ) ) {2801 /**2802 * Fires when a comment is attempted on a post that does not exist.2803 *2804 * @since 1.5.02805 *2806 * @param int $comment_post_ID Post ID.2807 */2808 do_action( 'comment_id_not_found', $comment_post_ID );2809 return new WP_Error( 'comment_id_not_found' );2810 }2811 // get_post_status() will get the parent status for attachments.2812 $status = get_post_status( $post );2813 if ( ( 'private' == $status ) && ! current_user_can( 'read_post', $comment_post_ID ) ) {2814 return new WP_Error( 'comment_id_not_found' );2815 }2816 $status_obj = get_post_status_object( $status );2817 if ( ! comments_open( $comment_post_ID ) ) {2818 /**2819 * Fires when a comment is attempted on a post that has comments closed.2820 *2821 * @since 1.5.02822 *2823 * @param int $comment_post_ID Post ID.2824 */2825 do_action( 'comment_closed', $comment_post_ID );2826 return new WP_Error( 'comment_closed', __( 'Sorry, comments are closed for this item.' ), 403 );2827 } elseif ( 'trash' == $status ) {2828 /**2829 * Fires when a comment is attempted on a trashed post.2830 *2831 * @since 2.9.02832 *2833 * @param int $comment_post_ID Post ID.2834 */2835 do_action( 'comment_on_trash', $comment_post_ID );2836 return new WP_Error( 'comment_on_trash' );2837 } elseif ( ! $status_obj->public && ! $status_obj->private ) {2838 /**2839 * Fires when a comment is attempted on a post in draft mode.2840 *2841 * @since 1.5.12842 *2843 * @param int $comment_post_ID Post ID.2844 */2845 do_action( 'comment_on_draft', $comment_post_ID );2846 if ( current_user_can( 'read_post', $comment_post_ID ) ) {2847 return new WP_Error( 'comment_on_draft', __( 'Sorry, comments are not allowed for this item.' ), 403 );2848 } else {2849 return new WP_Error( 'comment_on_draft' );2850 }2851 } elseif ( post_password_required( $comment_post_ID ) ) {2852 /**2853 * Fires when a comment is attempted on a password-protected post.2854 *2855 * @since 2.9.02856 *2857 * @param int $comment_post_ID Post ID.2858 */2859 do_action( 'comment_on_password_protected', $comment_post_ID );2860 return new WP_Error( 'comment_on_password_protected' );2861 } else {2862 /**2863 * Fires before a comment is posted.2864 *2865 * @since 2.8.02866 *2867 * @param int $comment_post_ID Post ID.2868 */2869 do_action( 'pre_comment_on_post', $comment_post_ID );2870 }2871 // If the user is logged in2872 $user = wp_get_current_user();2873 if ( $user->exists() ) {2874 if ( empty( $user->display_name ) ) {2875 $user->display_name = $user->user_login;2876 }2877 $comment_author = $user->display_name;2878 $comment_author_email = $user->user_email;2879 $comment_author_url = $user->user_url;2880 $user_ID = $user->ID;2881 if ( current_user_can( 'unfiltered_html' ) ) {2882 if ( ! isset( $comment_data['_wp_unfiltered_html_comment'] )2883 || ! wp_verify_nonce( $comment_data['_wp_unfiltered_html_comment'], 'unfiltered-html-comment_' . $comment_post_ID )2884 ) {2885 kses_remove_filters(); // start with a clean slate2886 kses_init_filters(); // set up the filters2887 remove_filter( 'pre_comment_content', 'wp_filter_post_kses' );2888 add_filter( 'pre_comment_content', 'wp_filter_kses' );2889 }2890 }2891 } else {2892 if ( get_option( 'comment_registration' ) ) {2893 return new WP_Error( 'not_logged_in', __( 'Sorry, you must be logged in to comment.' ), 403 );2894 }2895 }2896 $comment_type = '';2897 if ( get_option( 'require_name_email' ) && ! $user->exists() ) {2898 if ( '' == $comment_author_email || '' == $comment_author ) {2899 return new WP_Error( 'require_name_email', __( '<strong>ERROR</strong>: please fill the required fields (name, email).' ), 200 );2900 } elseif ( ! is_email( $comment_author_email ) ) {2901 return new WP_Error( 'require_valid_email', __( '<strong>ERROR</strong>: please enter a valid email address.' ), 200 );2902 }2903 }2904 $commentdata = compact(2905 'comment_post_ID',2906 'comment_author',2907 'comment_author_email',2908 'comment_author_url',2909 'comment_content',2910 'comment_type',2911 'comment_parent',2912 'user_ID'2913 );2914 /**2915 * Filters whether an empty comment should be allowed.2916 *2917 * @since 5.1.02918 *2919 * @param bool $allow_empty_comment Whether to allow empty comments. Default false.2920 * @param array $commentdata Array of comment data to be sent to wp_insert_comment().2921 */2922 $allow_empty_comment = apply_filters( 'allow_empty_comment', false, $commentdata );2923 if ( '' === $comment_content && ! $allow_empty_comment ) {2924 return new WP_Error( 'require_valid_comment', __( '<strong>ERROR</strong>: please type a comment.' ), 200 );2925 }2926 $check_max_lengths = wp_check_comment_data_max_lengths( $commentdata );2927 if ( is_wp_error( $check_max_lengths ) ) {2928 return $check_max_lengths;2929 }2930 $comment_id = wp_new_comment( wp_slash( $commentdata ), true );2931 if ( is_wp_error( $comment_id ) ) {2932 return $comment_id;2933 }2934 if ( ! $comment_id ) {2935 return new WP_Error( 'comment_save_error', __( '<strong>ERROR</strong>: The comment could not be saved. Please try again later.' ), 500 );2936 }2937 return get_comment( $comment_id );2938}2939/**2940 * Registers the personal data exporter for comments.2941 *2942 * @since 4.9.62943 *2944 * @param array $exporters An array of personal data exporters.2945 * @return array $exporters An array of personal data exporters.2946 */2947function wp_register_comment_personal_data_exporter( $exporters ) {2948 $exporters['wordpress-comments'] = array(2949 'exporter_friendly_name' => __( 'WordPress Comments' ),2950 'callback' => 'wp_comments_personal_data_exporter',2951 );2952 return $exporters;2953}2954/**2955 * Finds and exports personal data associated with an email address from the comments table.2956 *2957 * @since 4.9.62958 *2959 * @param string $email_address The comment author email address.2960 * @param int $page Comment page.2961 * @return array $return An array of personal data.2962 */2963function wp_comments_personal_data_exporter( $email_address, $page = 1 ) {2964 // Limit us to 500 comments at a time to avoid timing out.2965 $number = 500;2966 $page = (int) $page;2967 $data_to_export = array();2968 $comments = get_comments(2969 array(2970 'author_email' => $email_address,2971 'number' => $number,2972 'paged' => $page,2973 'order_by' => 'comment_ID',2974 'order' => 'ASC',2975 'update_comment_meta_cache' => false,2976 )2977 );2978 $comment_prop_to_export = array(2979 'comment_author' => __( 'Comment Author' ),2980 'comment_author_email' => __( 'Comment Author Email' ),2981 'comment_author_url' => __( 'Comment Author URL' ),2982 'comment_author_IP' => __( 'Comment Author IP' ),2983 'comment_agent' => __( 'Comment Author User Agent' ),2984 'comment_date' => __( 'Comment Date' ),2985 'comment_content' => __( 'Comment Content' ),2986 'comment_link' => __( 'Comment URL' ),2987 );2988 foreach ( (array) $comments as $comment ) {2989 $comment_data_to_export = array();2990 foreach ( $comment_prop_to_export as $key => $name ) {2991 $value = '';2992 switch ( $key ) {2993 case 'comment_author':2994 case 'comment_author_email':2995 case 'comment_author_url':2996 case 'comment_author_IP':2997 case 'comment_agent':2998 case 'comment_date':2999 $value = $comment->{$key};3000 break;3001 case 'comment_content':3002 $value = get_comment_text( $comment->comment_ID );3003 break;3004 case 'comment_link':3005 $value = get_comment_link( $comment->comment_ID );3006 $value = sprintf(3007 '<a href="%s" target="_blank" rel="noreferrer noopener">%s</a>',3008 esc_url( $value ),3009 esc_html( $value )3010 );3011 break;3012 }3013 if ( ! empty( $value ) ) {3014 $comment_data_to_export[] = array(3015 'name' => $name,3016 'value' => $value,3017 );3018 }3019 }3020 $data_to_export[] = array(3021 'group_id' => 'comments',3022 'group_label' => __( 'Comments' ),3023 'item_id' => "comment-{$comment->comment_ID}",3024 'data' => $comment_data_to_export,3025 );3026 }3027 $done = count( $comments ) < $number;3028 return array(3029 'data' => $data_to_export,3030 'done' => $done,3031 );3032}3033/**3034 * Registers the personal data eraser for comments.3035 *3036 * @since 4.9.63037 *3038 * @param array $erasers An array of personal data erasers.3039 * @return array $erasers An array of personal data erasers.3040 */3041function wp_register_comment_personal_data_eraser( $erasers ) {3042 $erasers['wordpress-comments'] = array(3043 'eraser_friendly_name' => __( 'WordPress Comments' ),3044 'callback' => 'wp_comments_personal_data_eraser',3045 );3046 return $erasers;3047}3048/**3049 * Erases personal data associated with an email address from the comments table.3050 *3051 * @since 4.9.63052 *3053 * @param string $email_address The comment author email address.3054 * @param int $page Comment page.3055 * @return array3056 */3057function wp_comments_personal_data_eraser( $email_address, $page = 1 ) {3058 global $wpdb;3059 if ( empty( $email_address ) ) {3060 return array(3061 'items_removed' => false,3062 'items_retained' => false,3063 'messages' => array(),3064 'done' => true,3065 );3066 }3067 // Limit us to 500 comments at a time to avoid timing out.3068 $number = 500;3069 $page = (int) $page;3070 $items_removed = false;3071 $items_retained = false;3072 $comments = get_comments(3073 array(3074 'author_email' => $email_address,3075 'number' => $number,3076 'paged' => $page,3077 'order_by' => 'comment_ID',3078 'order' => 'ASC',3079 'include_unapproved' => true,3080 )3081 );3082 /* translators: Name of a comment's author after being anonymized. */3083 $anon_author = __( 'Anonymous' );3084 $messages = array();3085 foreach ( (array) $comments as $comment ) {3086 $anonymized_comment = array();3087 $anonymized_comment['comment_agent'] = '';3088 $anonymized_comment['comment_author'] = $anon_author;3089 $anonymized_comment['comment_author_email'] = '';3090 $anonymized_comment['comment_author_IP'] = wp_privacy_anonymize_data( 'ip', $comment->comment_author_IP );3091 $anonymized_comment['comment_author_url'] = '';3092 $anonymized_comment['user_id'] = 0;3093 $comment_id = (int) $comment->comment_ID;3094 /**3095 * Filters whether to anonymize the comment.3096 *3097 * @since 4.9.63098 *3099 * @param bool|string Whether to apply the comment anonymization (bool).3100 * Custom prevention message (string). Default true.3101 * @param WP_Comment $comment WP_Comment object.3102 * @param array $anonymized_comment Anonymized comment data.3103 */3104 $anon_message = apply_filters( 'wp_anonymize_comment', true, $comment, $anonymized_comment );3105 if ( true !== $anon_message ) {3106 if ( $anon_message && is_string( $anon_message ) ) {3107 $messages[] = esc_html( $anon_message );3108 } else {3109 /* translators: %d: Comment ID */3110 $messages[] = sprintf( __( 'Comment %d contains personal data but could not be anonymized.' ), $comment_id );3111 }3112 $items_retained = true;3113 continue;3114 }3115 $args = array(3116 'comment_ID' => $comment_id,3117 );3118 $updated = $wpdb->update( $wpdb->comments, $anonymized_comment, $args );3119 if ( $updated ) {3120 $items_removed = true;3121 clean_comment_cache( $comment_id );3122 } else {3123 $items_retained = true;3124 }...
Comment
Using AI Code Generation
1require_once('cucumber-common-library/Comment.php');2$comment = new Comment();3require_once('cucumber-common-library/User.php');4$user = new User();5require_once('cucumber-common-library/Post.php');6$post = new Post();7require_once('cucumber-common-library/Comment.php');8$comment = new Comment();9require_once('cucumber-common-library/User.php');10$user = new User();11require_once('cucumber-common-library/Post.php');12$post = new Post();13require_once('cucumber-common-library/Comment.php');14$comment = new Comment();15require_once('cucumber-common-library/User.php');16$user = new User();17require_once('cucumber-common-library/Post.php');18$post = new Post();19require_once('cucumber-common-library/Comment.php');20$comment = new Comment();21require_once('cucumber-common-library/User.php');22$user = new User();23require_once('cucumber-common-library/Post.php');24$post = new Post();25require_once('cucumber-common-library/Comment.php');26$comment = new Comment();27require_once('cucumber-common-library/User.php');28$user = new User();29require_once('cucumber-common-library/Post.php');30$post = new Post();31require_once('cucumber-common-library/Comment.php');32$comment = new Comment();33require_once('cucumber-common-library/User.php');34$user = new User();35require_once('cucumber-common-library/Post.php');36$post = new Post();
Comment
Using AI Code Generation
1require_once('CucumberCommonLibrary/Comment.php');2$comment = new Comment();3$comment->setComment('This is a comment');4echo $comment->getComment();5require_once('CucumberCommonLibrary/Comment.php');6$comment = new Comment();7$comment->setComment('This is a comment');8echo $comment->getComment();9require_once('CucumberCommonLibrary/Comment.php');10$comment = new Comment();11$comment->setComment('This is a comment');12echo $comment->getComment();13require_once('CucumberCommonLibrary/Comment.php');14$comment = new Comment();15$comment->setComment('This is a comment');16echo $comment->getComment();17require_once('CucumberCommonLibrary/Comment.php');18$comment = new Comment();19$comment->setComment('This is a comment');20echo $comment->getComment();21require_once('CucumberCommonLibrary/Comment.php');22$comment = new Comment();23$comment->setComment('This is a comment');24echo $comment->getComment();25require_once('CucumberCommonLibrary/Comment.php');26$comment = new Comment();27$comment->setComment('This is a comment');28echo $comment->getComment();29require_once('CucumberCommonLibrary/Comment.php');30$comment = new Comment();31$comment->setComment('This is a comment');32echo $comment->getComment();33require_once('CucumberCommonLibrary/Comment.php');34$comment = new Comment();35$comment->setComment('This is a comment');36echo $comment->getComment();37require_once('CucumberCommonLibrary/Comment.php');
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Trigger Selenium automation tests on a cloud-based Grid of 3000+ real browsers and operating systems.
Test now for FreeGet 100 minutes of automation test minutes FREE!!