wp/wp-includes/comment.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
    38  */
    38  */
    39 function check_comment( $author, $email, $url, $comment, $user_ip, $user_agent, $comment_type ) {
    39 function check_comment( $author, $email, $url, $comment, $user_ip, $user_agent, $comment_type ) {
    40 	global $wpdb;
    40 	global $wpdb;
    41 
    41 
    42 	// If manual moderation is enabled, skip all checks and return false.
    42 	// If manual moderation is enabled, skip all checks and return false.
    43 	if ( 1 == get_option( 'comment_moderation' ) ) {
    43 	if ( '1' === get_option( 'comment_moderation' ) ) {
    44 		return false;
    44 		return false;
    45 	}
    45 	}
    46 
    46 
    47 	/** This filter is documented in wp-includes/comment-template.php */
    47 	/** This filter is documented in wp-includes/comment-template.php */
    48 	$comment = apply_filters( 'comment_text', $comment, null, array() );
    48 	$comment = apply_filters( 'comment_text', $comment, null, array() );
   124 	 *
   124 	 *
   125 	 * If it is enabled, check whether the comment author has a previously-approved comment,
   125 	 * If it is enabled, check whether the comment author has a previously-approved comment,
   126 	 * as well as whether there are any moderation keywords (if set) present in the author
   126 	 * as well as whether there are any moderation keywords (if set) present in the author
   127 	 * email address. If both checks pass, return true. Otherwise, return false.
   127 	 * email address. If both checks pass, return true. Otherwise, return false.
   128 	 */
   128 	 */
   129 	if ( 1 == get_option( 'comment_previously_approved' ) ) {
   129 	if ( '1' === get_option( 'comment_previously_approved' ) ) {
   130 		if ( 'trackback' !== $comment_type && 'pingback' !== $comment_type && '' !== $author && '' !== $email ) {
   130 		if ( 'trackback' !== $comment_type && 'pingback' !== $comment_type && '' !== $author && '' !== $email ) {
   131 			$comment_user = get_user_by( 'email', wp_unslash( $email ) );
   131 			$comment_user = get_user_by( 'email', wp_unslash( $email ) );
   132 			if ( ! empty( $comment_user->ID ) ) {
   132 			if ( ! empty( $comment_user->ID ) ) {
   133 				$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 ) );
   133 				$ok_to_comment = $wpdb->get_var(
       
   134 					$wpdb->prepare(
       
   135 						"SELECT comment_approved
       
   136 						FROM $wpdb->comments
       
   137 						WHERE user_id = %d
       
   138 						AND comment_approved = '1'
       
   139 						LIMIT 1",
       
   140 						$comment_user->ID
       
   141 					)
       
   142 				);
   134 			} else {
   143 			} else {
   135 				// expected_slashed ($author, $email)
   144 				// expected_slashed ($author, $email)
   136 				$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 ) );
   145 				$ok_to_comment = $wpdb->get_var(
       
   146 					$wpdb->prepare(
       
   147 						"SELECT comment_approved
       
   148 						FROM $wpdb->comments
       
   149 						WHERE comment_author = %s
       
   150 						AND comment_author_email = %s
       
   151 						AND comment_approved = '1'
       
   152 						LIMIT 1",
       
   153 						$author,
       
   154 						$email
       
   155 					)
       
   156 				);
   137 			}
   157 			}
   138 			if ( ( 1 == $ok_to_comment ) &&
   158 
   139 				( empty( $mod_keys ) || ! str_contains( $email, $mod_keys ) ) ) {
   159 			if ( '1' === $ok_to_comment && ( empty( $mod_keys ) || ! str_contains( $email, $mod_keys ) ) ) {
   140 					return true;
   160 				return true;
   141 			} else {
   161 			} else {
   142 				return false;
   162 				return false;
   143 			}
   163 			}
   144 		} else {
   164 		} else {
   145 			return false;
   165 			return false;
   430  *
   450  *
   431  * @link https://developer.wordpress.org/reference/functions/add_comment_meta/
   451  * @link https://developer.wordpress.org/reference/functions/add_comment_meta/
   432  *
   452  *
   433  * @param int    $comment_id Comment ID.
   453  * @param int    $comment_id Comment ID.
   434  * @param string $meta_key   Metadata name.
   454  * @param string $meta_key   Metadata name.
   435  * @param mixed  $meta_value Metadata value. Must be serializable if non-scalar.
   455  * @param mixed  $meta_value Metadata value. Arrays and objects are stored as serialized data and
       
   456  *                           will be returned as the same type when retrieved. Other data types will
       
   457  *                           be stored as strings in the database:
       
   458  *                           - false is stored and retrieved as an empty string ('')
       
   459  *                           - true is stored and retrieved as '1'
       
   460  *                           - numbers (both integer and float) are stored and retrieved as strings
       
   461  *                           Must be serializable if non-scalar.
   436  * @param bool   $unique     Optional. Whether the same key should not be added.
   462  * @param bool   $unique     Optional. Whether the same key should not be added.
   437  *                           Default false.
   463  *                           Default false.
   438  * @return int|false Meta ID on success, false on failure.
   464  * @return int|false Meta ID on success, false on failure.
   439  */
   465  */
   440 function add_comment_meta( $comment_id, $meta_key, $meta_value, $unique = false ) {
   466 function add_comment_meta( $comment_id, $meta_key, $meta_value, $unique = false ) {
   477  *                           This parameter has no effect if `$key` is not specified.
   503  *                           This parameter has no effect if `$key` is not specified.
   478  *                           Default false.
   504  *                           Default false.
   479  * @return mixed An array of values if `$single` is false.
   505  * @return mixed An array of values if `$single` is false.
   480  *               The value of meta data field if `$single` is true.
   506  *               The value of meta data field if `$single` is true.
   481  *               False for an invalid `$comment_id` (non-numeric, zero, or negative value).
   507  *               False for an invalid `$comment_id` (non-numeric, zero, or negative value).
   482  *               An empty string if a valid but non-existing comment ID is passed.
   508  *               An empty array if a valid but non-existing comment ID is passed and `$single` is false.
       
   509  *               An empty string if a valid but non-existing comment ID is passed and `$single` is true.
       
   510  *               Note: Non-serialized values are returned as strings:
       
   511  *               - false values are returned as empty strings ('')
       
   512  *               - true values are returned as '1'
       
   513  *               - numbers are returned as strings
       
   514  *               Arrays and objects retain their original type.
   483  */
   515  */
   484 function get_comment_meta( $comment_id, $key = '', $single = false ) {
   516 function get_comment_meta( $comment_id, $key = '', $single = false ) {
   485 	return get_metadata( 'comment', $comment_id, $key, $single );
   517 	return get_metadata( 'comment', $comment_id, $key, $single );
   486 }
   518 }
   487 
   519 
   770 		$comment_flood_message = apply_filters( 'comment_flood_message', __( 'You are posting comments too quickly. Slow down.' ) );
   802 		$comment_flood_message = apply_filters( 'comment_flood_message', __( 'You are posting comments too quickly. Slow down.' ) );
   771 
   803 
   772 		return new WP_Error( 'comment_flood', $comment_flood_message, 429 );
   804 		return new WP_Error( 'comment_flood', $comment_flood_message, 429 );
   773 	}
   805 	}
   774 
   806 
   775 	if ( ! empty( $commentdata['user_id'] ) ) {
   807 	return wp_check_comment_data( $commentdata );
   776 		$user        = get_userdata( $commentdata['user_id'] );
       
   777 		$post_author = $wpdb->get_var(
       
   778 			$wpdb->prepare(
       
   779 				"SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1",
       
   780 				$commentdata['comment_post_ID']
       
   781 			)
       
   782 		);
       
   783 	}
       
   784 
       
   785 	if ( isset( $user ) && ( $commentdata['user_id'] == $post_author || $user->has_cap( 'moderate_comments' ) ) ) {
       
   786 		// The author and the admins get respect.
       
   787 		$approved = 1;
       
   788 	} else {
       
   789 		// Everyone else's comments will be checked.
       
   790 		if ( check_comment(
       
   791 			$commentdata['comment_author'],
       
   792 			$commentdata['comment_author_email'],
       
   793 			$commentdata['comment_author_url'],
       
   794 			$commentdata['comment_content'],
       
   795 			$commentdata['comment_author_IP'],
       
   796 			$commentdata['comment_agent'],
       
   797 			$commentdata['comment_type']
       
   798 		) ) {
       
   799 			$approved = 1;
       
   800 		} else {
       
   801 			$approved = 0;
       
   802 		}
       
   803 
       
   804 		if ( wp_check_comment_disallowed_list(
       
   805 			$commentdata['comment_author'],
       
   806 			$commentdata['comment_author_email'],
       
   807 			$commentdata['comment_author_url'],
       
   808 			$commentdata['comment_content'],
       
   809 			$commentdata['comment_author_IP'],
       
   810 			$commentdata['comment_agent']
       
   811 		) ) {
       
   812 			$approved = EMPTY_TRASH_DAYS ? 'trash' : 'spam';
       
   813 		}
       
   814 	}
       
   815 
       
   816 	/**
       
   817 	 * Filters a comment's approval status before it is set.
       
   818 	 *
       
   819 	 * @since 2.1.0
       
   820 	 * @since 4.9.0 Returning a WP_Error value from the filter will short-circuit comment insertion
       
   821 	 *              and allow skipping further processing.
       
   822 	 *
       
   823 	 * @param int|string|WP_Error $approved    The approval status. Accepts 1, 0, 'spam', 'trash',
       
   824 	 *                                         or WP_Error.
       
   825 	 * @param array               $commentdata Comment data.
       
   826 	 */
       
   827 	return apply_filters( 'pre_comment_approved', $approved, $commentdata );
       
   828 }
   808 }
   829 
   809 
   830 /**
   810 /**
   831  * Hooks WP's native database-based comment-flood check.
   811  * Hooks WP's native database-based comment-flood check.
   832  *
   812  *
  1104 				$args['max_depth'] = -1;
  1084 				$args['max_depth'] = -1;
  1105 			}
  1085 			}
  1106 		}
  1086 		}
  1107 
  1087 
  1108 		// Find this comment's top-level parent if threading is enabled.
  1088 		// Find this comment's top-level parent if threading is enabled.
  1109 		if ( $args['max_depth'] > 1 && 0 != $comment->comment_parent ) {
  1089 		if ( $args['max_depth'] > 1 && '0' !== $comment->comment_parent ) {
  1110 			return get_page_of_comment( $comment->comment_parent, $args );
  1090 			return get_page_of_comment( $comment->comment_parent, $args );
  1111 		}
  1091 		}
  1112 
  1092 
  1113 		$comment_args = array(
  1093 		$comment_args = array(
  1114 			'type'       => $args['type'],
  1094 			'type'       => $args['type'],
  1164 
  1144 
  1165 		$comment_query       = new WP_Comment_Query();
  1145 		$comment_query       = new WP_Comment_Query();
  1166 		$older_comment_count = $comment_query->query( $comment_args );
  1146 		$older_comment_count = $comment_query->query( $comment_args );
  1167 
  1147 
  1168 		// No older comments? Then it's page #1.
  1148 		// No older comments? Then it's page #1.
  1169 		if ( 0 == $older_comment_count ) {
  1149 		if ( 0 === $older_comment_count ) {
  1170 			$page = 1;
  1150 			$page = 1;
  1171 
  1151 
  1172 			// Divide comments older than this one by comments per page to get this comment's page number.
  1152 			// Divide comments older than this one by comments per page to get this comment's page number.
  1173 		} else {
  1153 		} else {
  1174 			$page = (int) ceil( ( $older_comment_count + 1 ) / $args['per_page'] );
  1154 			$page = (int) ceil( ( $older_comment_count + 1 ) / $args['per_page'] );
  1290 
  1270 
  1291 	return true;
  1271 	return true;
  1292 }
  1272 }
  1293 
  1273 
  1294 /**
  1274 /**
       
  1275  * Checks whether comment data passes internal checks or has disallowed content.
       
  1276  *
       
  1277  * @since 6.7.0
       
  1278  *
       
  1279  * @global wpdb $wpdb WordPress database abstraction object.
       
  1280  *
       
  1281  * @param array $comment_data Array of arguments for inserting a comment.
       
  1282  * @return int|string|WP_Error The approval status on success (0|1|'spam'|'trash'),
       
  1283  *                             WP_Error otherwise.
       
  1284  */
       
  1285 function wp_check_comment_data( $comment_data ) {
       
  1286 	global $wpdb;
       
  1287 
       
  1288 	if ( ! empty( $comment_data['user_id'] ) ) {
       
  1289 		$user        = get_userdata( $comment_data['user_id'] );
       
  1290 		$post_author = (int) $wpdb->get_var(
       
  1291 			$wpdb->prepare(
       
  1292 				"SELECT post_author FROM $wpdb->posts WHERE ID = %d LIMIT 1",
       
  1293 				$comment_data['comment_post_ID']
       
  1294 			)
       
  1295 		);
       
  1296 	}
       
  1297 
       
  1298 	if ( isset( $user ) && ( $comment_data['user_id'] === $post_author || $user->has_cap( 'moderate_comments' ) ) ) {
       
  1299 		// The author and the admins get respect.
       
  1300 		$approved = 1;
       
  1301 	} else {
       
  1302 		// Everyone else's comments will be checked.
       
  1303 		if ( check_comment(
       
  1304 			$comment_data['comment_author'],
       
  1305 			$comment_data['comment_author_email'],
       
  1306 			$comment_data['comment_author_url'],
       
  1307 			$comment_data['comment_content'],
       
  1308 			$comment_data['comment_author_IP'],
       
  1309 			$comment_data['comment_agent'],
       
  1310 			$comment_data['comment_type']
       
  1311 		) ) {
       
  1312 			$approved = 1;
       
  1313 		} else {
       
  1314 			$approved = 0;
       
  1315 		}
       
  1316 
       
  1317 		if ( wp_check_comment_disallowed_list(
       
  1318 			$comment_data['comment_author'],
       
  1319 			$comment_data['comment_author_email'],
       
  1320 			$comment_data['comment_author_url'],
       
  1321 			$comment_data['comment_content'],
       
  1322 			$comment_data['comment_author_IP'],
       
  1323 			$comment_data['comment_agent']
       
  1324 		) ) {
       
  1325 			$approved = EMPTY_TRASH_DAYS ? 'trash' : 'spam';
       
  1326 		}
       
  1327 	}
       
  1328 
       
  1329 	/**
       
  1330 	 * Filters a comment's approval status before it is set.
       
  1331 	 *
       
  1332 	 * @since 2.1.0
       
  1333 	 * @since 4.9.0 Returning a WP_Error value from the filter will short-circuit comment insertion
       
  1334 	 *              and allow skipping further processing.
       
  1335 	 *
       
  1336 	 * @param int|string|WP_Error $approved    The approval status. Accepts 1, 0, 'spam', 'trash',
       
  1337 	 *                                         or WP_Error.
       
  1338 	 * @param array               $commentdata Comment data.
       
  1339 	 */
       
  1340 	return apply_filters( 'pre_comment_approved', $approved, $comment_data );
       
  1341 }
       
  1342 
       
  1343 /**
  1295  * Checks if a comment contains disallowed characters or words.
  1344  * Checks if a comment contains disallowed characters or words.
  1296  *
  1345  *
  1297  * @since 5.5.0
  1346  * @since 5.5.0
  1298  *
  1347  *
  1299  * @param string $author The author of the comment
  1348  * @param string $author     The author of the comment.
  1300  * @param string $email The email of the comment
  1349  * @param string $email      The email of the comment.
  1301  * @param string $url The url used in the comment
  1350  * @param string $url        The url used in the comment.
  1302  * @param string $comment The comment content
  1351  * @param string $comment    The comment content.
  1303  * @param string $user_ip The comment author's IP address
  1352  * @param string $user_ip    The comment author's IP address.
  1304  * @param string $user_agent The author's browser user agent
  1353  * @param string $user_agent The author's browser user agent.
  1305  * @return bool True if comment contains disallowed content, false if comment does not
  1354  * @return bool True if the comment contains disallowed content, false otherwise.
  1306  */
  1355  */
  1307 function wp_check_comment_disallowed_list( $author, $email, $url, $comment, $user_ip, $user_agent ) {
  1356 function wp_check_comment_disallowed_list( $author, $email, $url, $comment, $user_ip, $user_agent ) {
  1308 	/**
  1357 	/**
  1309 	 * Fires before the comment is tested for disallowed characters or words.
  1358 	 * Fires before the comment is tested for disallowed characters or words.
  1310 	 *
  1359 	 *
  1497 	 * @param WP_Comment $comment    The deleted comment.
  1546 	 * @param WP_Comment $comment    The deleted comment.
  1498 	 */
  1547 	 */
  1499 	do_action( 'deleted_comment', $comment->comment_ID, $comment );
  1548 	do_action( 'deleted_comment', $comment->comment_ID, $comment );
  1500 
  1549 
  1501 	$post_id = $comment->comment_post_ID;
  1550 	$post_id = $comment->comment_post_ID;
  1502 	if ( $post_id && 1 == $comment->comment_approved ) {
  1551 	if ( $post_id && '1' === $comment->comment_approved ) {
  1503 		wp_update_comment_count( $post_id );
  1552 		wp_update_comment_count( $post_id );
  1504 	}
  1553 	}
  1505 
  1554 
  1506 	clean_comment_cache( $comment->comment_ID );
  1555 	clean_comment_cache( $comment->comment_ID );
  1507 
  1556 
  1731 		return false;
  1780 		return false;
  1732 	}
  1781 	}
  1733 
  1782 
  1734 	$approved = $comment->comment_approved;
  1783 	$approved = $comment->comment_approved;
  1735 
  1784 
  1736 	if ( null == $approved ) {
  1785 	if ( null === $approved ) {
  1737 		return false;
  1786 		return false;
  1738 	} elseif ( '1' == $approved ) {
  1787 	} elseif ( '1' === $approved ) {
  1739 		return 'approved';
  1788 		return 'approved';
  1740 	} elseif ( '0' == $approved ) {
  1789 	} elseif ( '0' === $approved ) {
  1741 		return 'unapproved';
  1790 		return 'unapproved';
  1742 	} elseif ( 'spam' === $approved ) {
  1791 	} elseif ( 'spam' === $approved ) {
  1743 		return 'spam';
  1792 		return 'spam';
  1744 	} elseif ( 'trash' === $approved ) {
  1793 	} elseif ( 'trash' === $approved ) {
  1745 		return 'trash';
  1794 		return 'trash';
  1784 	if ( isset( $comment_statuses[ $old_status ] ) ) {
  1833 	if ( isset( $comment_statuses[ $old_status ] ) ) {
  1785 		$old_status = $comment_statuses[ $old_status ];
  1834 		$old_status = $comment_statuses[ $old_status ];
  1786 	}
  1835 	}
  1787 
  1836 
  1788 	// Call the hooks.
  1837 	// Call the hooks.
  1789 	if ( $new_status != $old_status ) {
  1838 	if ( $new_status !== $old_status ) {
  1790 		/**
  1839 		/**
  1791 		 * Fires when the comment status is in transition.
  1840 		 * Fires when the comment status is in transition.
  1792 		 *
  1841 		 *
  1793 		 * @since 2.7.0
  1842 		 * @since 2.7.0
  1794 		 *
  1843 		 *
  1795 		 * @param int|string $new_status The new comment status.
  1844 		 * @param string     $new_status The new comment status.
  1796 		 * @param int|string $old_status The old comment status.
  1845 		 * @param string     $old_status The old comment status.
  1797 		 * @param WP_Comment $comment    Comment object.
  1846 		 * @param WP_Comment $comment    Comment object.
  1798 		 */
  1847 		 */
  1799 		do_action( 'transition_comment_status', $new_status, $old_status, $comment );
  1848 		do_action( 'transition_comment_status', $new_status, $old_status, $comment );
       
  1849 
  1800 		/**
  1850 		/**
  1801 		 * Fires when the comment status is in transition from one specific status to another.
  1851 		 * Fires when the comment status is in transition from one specific status to another.
  1802 		 *
  1852 		 *
  1803 		 * The dynamic portions of the hook name, `$old_status`, and `$new_status`,
  1853 		 * The dynamic portions of the hook name, `$old_status`, and `$new_status`,
  1804 		 * refer to the old and new comment statuses, respectively.
  1854 		 * refer to the old and new comment statuses, respectively.
  2039 		return false;
  2089 		return false;
  2040 	}
  2090 	}
  2041 
  2091 
  2042 	$id = (int) $wpdb->insert_id;
  2092 	$id = (int) $wpdb->insert_id;
  2043 
  2093 
  2044 	if ( 1 == $comment_approved ) {
  2094 	if ( 1 === (int) $comment_approved ) {
  2045 		wp_update_comment_count( $comment_post_id );
  2095 		wp_update_comment_count( $comment_post_id );
  2046 
  2096 
  2047 		$data = array();
  2097 		$data = array();
  2048 		foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
  2098 		foreach ( array( 'server', 'gmt', 'blog' ) as $timezone ) {
  2049 			$data[] = "lastcommentmodified:$timezone";
  2099 			$data[] = "lastcommentmodified:$timezone";
  2274 
  2324 
  2275 	if ( empty( $commentdata['comment_type'] ) ) {
  2325 	if ( empty( $commentdata['comment_type'] ) ) {
  2276 		$commentdata['comment_type'] = 'comment';
  2326 		$commentdata['comment_type'] = 'comment';
  2277 	}
  2327 	}
  2278 
  2328 
       
  2329 	$commentdata['comment_approved'] = wp_allow_comment( $commentdata, $wp_error );
       
  2330 
       
  2331 	if ( is_wp_error( $commentdata['comment_approved'] ) ) {
       
  2332 		return $commentdata['comment_approved'];
       
  2333 	}
       
  2334 
  2279 	$commentdata = wp_filter_comment( $commentdata );
  2335 	$commentdata = wp_filter_comment( $commentdata );
  2280 
  2336 
  2281 	$commentdata['comment_approved'] = wp_allow_comment( $commentdata, $wp_error );
  2337 	if ( ! in_array( $commentdata['comment_approved'], array( 'trash', 'spam' ), true ) ) {
       
  2338 		// Validate the comment again after filters are applied to comment data.
       
  2339 		$commentdata['comment_approved'] = wp_check_comment_data( $commentdata );
       
  2340 	}
  2282 
  2341 
  2283 	if ( is_wp_error( $commentdata['comment_approved'] ) ) {
  2342 	if ( is_wp_error( $commentdata['comment_approved'] ) ) {
  2284 		return $commentdata['comment_approved'];
  2343 		return $commentdata['comment_approved'];
  2285 	}
  2344 	}
  2286 
  2345 
  2333  */
  2392  */
  2334 function wp_new_comment_notify_moderator( $comment_id ) {
  2393 function wp_new_comment_notify_moderator( $comment_id ) {
  2335 	$comment = get_comment( $comment_id );
  2394 	$comment = get_comment( $comment_id );
  2336 
  2395 
  2337 	// Only send notifications for pending comments.
  2396 	// Only send notifications for pending comments.
  2338 	$maybe_notify = ( '0' == $comment->comment_approved );
  2397 	$maybe_notify = ( '0' === $comment->comment_approved );
  2339 
  2398 
  2340 	/** This filter is documented in wp-includes/pluggable.php */
  2399 	/** This filter is documented in wp-includes/pluggable.php */
  2341 	$maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
  2400 	$maybe_notify = apply_filters( 'notify_moderator', $maybe_notify, $comment_id );
  2342 
  2401 
  2343 	if ( ! $maybe_notify ) {
  2402 	if ( ! $maybe_notify ) {
  2381 	if ( ! $maybe_notify ) {
  2440 	if ( ! $maybe_notify ) {
  2382 		return false;
  2441 		return false;
  2383 	}
  2442 	}
  2384 
  2443 
  2385 	// Only send notifications for approved comments.
  2444 	// Only send notifications for approved comments.
  2386 	if ( ! isset( $comment->comment_approved ) || '1' != $comment->comment_approved ) {
  2445 	if ( ! isset( $comment->comment_approved ) || '1' !== $comment->comment_approved ) {
  2387 		return false;
  2446 		return false;
  2388 	}
  2447 	}
  2389 
  2448 
  2390 	return wp_notify_postauthor( $comment_id );
  2449 	return wp_notify_postauthor( $comment_id );
  2391 }
  2450 }
  2850 
  2909 
  2851 	$contents = wp_remote_retrieve_body( $response );
  2910 	$contents = wp_remote_retrieve_body( $response );
  2852 
  2911 
  2853 	$pingback_link_offset_dquote = strpos( $contents, $pingback_str_dquote );
  2912 	$pingback_link_offset_dquote = strpos( $contents, $pingback_str_dquote );
  2854 	$pingback_link_offset_squote = strpos( $contents, $pingback_str_squote );
  2913 	$pingback_link_offset_squote = strpos( $contents, $pingback_str_squote );
       
  2914 
  2855 	if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) {
  2915 	if ( $pingback_link_offset_dquote || $pingback_link_offset_squote ) {
  2856 		$quote                   = ( $pingback_link_offset_dquote ) ? '"' : '\'';
  2916 		$quote                   = ( $pingback_link_offset_dquote ) ? '"' : '\'';
  2857 		$pingback_link_offset    = ( '"' === $quote ) ? $pingback_link_offset_dquote : $pingback_link_offset_squote;
  2917 		$pingback_link_offset    = ( '"' === $quote ) ? $pingback_link_offset_dquote : $pingback_link_offset_squote;
  2858 		$pingback_href_pos       = strpos( $contents, 'href=', $pingback_link_offset );
  2918 		$pingback_href_pos       = strpos( $contents, 'href=', $pingback_link_offset );
  2859 		$pingback_href_start     = $pingback_href_pos + 6;
  2919 		$pingback_href_start     = $pingback_href_pos + 6;
  3039 /**
  3099 /**
  3040  * Pings back the links found in a post.
  3100  * Pings back the links found in a post.
  3041  *
  3101  *
  3042  * @since 0.71
  3102  * @since 0.71
  3043  * @since 4.7.0 `$post` can be a WP_Post object.
  3103  * @since 4.7.0 `$post` can be a WP_Post object.
       
  3104  * @since 6.8.0 Returns an array of pingback statuses indexed by link.
  3044  *
  3105  *
  3045  * @param string      $content Post content to check for links. If empty will retrieve from post.
  3106  * @param string      $content Post content to check for links. If empty will retrieve from post.
  3046  * @param int|WP_Post $post    Post ID or object.
  3107  * @param int|WP_Post $post    Post ID or object.
       
  3108  * @return array<string, bool> An array of pingback statuses indexed by link.
  3047  */
  3109  */
  3048 function pingback( $content, $post ) {
  3110 function pingback( $content, $post ) {
  3049 	require_once ABSPATH . WPINC . '/class-IXR.php';
  3111 	require_once ABSPATH . WPINC . '/class-IXR.php';
  3050 	require_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';
  3112 	require_once ABSPATH . WPINC . '/class-wp-http-ixr-client.php';
  3051 
  3113 
  3053 	$post_links = array();
  3115 	$post_links = array();
  3054 
  3116 
  3055 	$post = get_post( $post );
  3117 	$post = get_post( $post );
  3056 
  3118 
  3057 	if ( ! $post ) {
  3119 	if ( ! $post ) {
  3058 		return;
  3120 		return array();
  3059 	}
  3121 	}
  3060 
  3122 
  3061 	$pung = get_pung( $post );
  3123 	$pung = get_pung( $post );
  3062 
  3124 
  3063 	if ( empty( $content ) ) {
  3125 	if ( empty( $content ) ) {
  3068 	 * Step 1.
  3130 	 * Step 1.
  3069 	 * Parsing the post, external links (if any) are stored in the $post_links array.
  3131 	 * Parsing the post, external links (if any) are stored in the $post_links array.
  3070 	 */
  3132 	 */
  3071 	$post_links_temp = wp_extract_urls( $content );
  3133 	$post_links_temp = wp_extract_urls( $content );
  3072 
  3134 
       
  3135 	$ping_status = array();
  3073 	/*
  3136 	/*
  3074 	 * Step 2.
  3137 	 * Step 2.
  3075 	 * Walking through the links array.
  3138 	 * Walking through the links array.
  3076 	 * First we get rid of links pointing to sites, not to specific files.
  3139 	 * First we get rid of links pointing to sites, not to specific files.
  3077 	 * Example:
  3140 	 * Example:
  3080 	 * http://dummy-weblog.org/post.php
  3143 	 * http://dummy-weblog.org/post.php
  3081 	 * We don't wanna ping first and second types, even if they have a valid <link/>.
  3144 	 * We don't wanna ping first and second types, even if they have a valid <link/>.
  3082 	 */
  3145 	 */
  3083 	foreach ( (array) $post_links_temp as $link_test ) {
  3146 	foreach ( (array) $post_links_temp as $link_test ) {
  3084 		// If we haven't pung it already and it isn't a link to itself.
  3147 		// If we haven't pung it already and it isn't a link to itself.
  3085 		if ( ! in_array( $link_test, $pung, true ) && ( url_to_postid( $link_test ) != $post->ID )
  3148 		if ( ! in_array( $link_test, $pung, true ) && ( url_to_postid( $link_test ) !== $post->ID )
  3086 			// Also, let's never ping local attachments.
  3149 			// Also, let's never ping local attachments.
  3087 			&& ! is_local_attachment( $link_test )
  3150 			&& ! is_local_attachment( $link_test )
  3088 		) {
  3151 		) {
  3089 			$test = parse_url( $link_test );
  3152 			$test = parse_url( $link_test );
  3090 			if ( $test ) {
  3153 			if ( $test ) {
  3112 
  3175 
  3113 	foreach ( (array) $post_links as $pagelinkedto ) {
  3176 	foreach ( (array) $post_links as $pagelinkedto ) {
  3114 		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
  3177 		$pingback_server_url = discover_pingback_server_uri( $pagelinkedto );
  3115 
  3178 
  3116 		if ( $pingback_server_url ) {
  3179 		if ( $pingback_server_url ) {
       
  3180 			// Allow an additional 60 seconds for each pingback to complete.
  3117 			if ( function_exists( 'set_time_limit' ) ) {
  3181 			if ( function_exists( 'set_time_limit' ) ) {
  3118 				set_time_limit( 60 );
  3182 				set_time_limit( 60 );
  3119 			}
  3183 			}
  3120 
  3184 
  3121 			// Now, the RPC call.
  3185 			// Now, the RPC call.
  3138 			 */
  3202 			 */
  3139 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . get_bloginfo( 'version' ), $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom );
  3203 			$client->useragent = apply_filters( 'pingback_useragent', $client->useragent . ' -- WordPress/' . get_bloginfo( 'version' ), $client->useragent, $pingback_server_url, $pagelinkedto, $pagelinkedfrom );
  3140 			// When set to true, this outputs debug messages by itself.
  3204 			// When set to true, this outputs debug messages by itself.
  3141 			$client->debug = false;
  3205 			$client->debug = false;
  3142 
  3206 
  3143 			if ( $client->query( 'pingback.ping', $pagelinkedfrom, $pagelinkedto ) || ( isset( $client->error->code ) && 48 == $client->error->code ) ) { // Already registered.
  3207 			$status = $client->query( 'pingback.ping', $pagelinkedfrom, $pagelinkedto );
       
  3208 
       
  3209 			if ( $status // Ping registered.
       
  3210 				|| ( isset( $client->error->code ) && 48 === $client->error->code ) // Already registered.
       
  3211 			) {
  3144 				add_ping( $post, $pagelinkedto );
  3212 				add_ping( $post, $pagelinkedto );
  3145 			}
  3213 			}
  3146 		}
  3214 			$ping_status[ $pagelinkedto ] = $status;
  3147 	}
  3215 		}
       
  3216 	}
       
  3217 
       
  3218 	return $ping_status;
  3148 }
  3219 }
  3149 
  3220 
  3150 /**
  3221 /**
  3151  * Checks whether blog is public before returning sites.
  3222  * Checks whether blog is public before returning sites.
  3152  *
  3223  *
  3154  *
  3225  *
  3155  * @param mixed $sites Will return if blog is public, will not return if not public.
  3226  * @param mixed $sites Will return if blog is public, will not return if not public.
  3156  * @return mixed Empty string if blog is not public, returns $sites, if site is public.
  3227  * @return mixed Empty string if blog is not public, returns $sites, if site is public.
  3157  */
  3228  */
  3158 function privacy_ping_filter( $sites ) {
  3229 function privacy_ping_filter( $sites ) {
  3159 	if ( '0' != get_option( 'blog_public' ) ) {
  3230 	if ( '0' !== get_option( 'blog_public' ) ) {
  3160 		return $sites;
  3231 		return $sites;
  3161 	} else {
  3232 	} else {
  3162 		return '';
  3233 		return '';
  3163 	}
  3234 	}
  3164 }
  3235 }
  3628 	}
  3699 	}
  3629 
  3700 
  3630 	$comment_type = 'comment';
  3701 	$comment_type = 'comment';
  3631 
  3702 
  3632 	if ( get_option( 'require_name_email' ) && ! $user->exists() ) {
  3703 	if ( get_option( 'require_name_email' ) && ! $user->exists() ) {
  3633 		if ( '' == $comment_author_email || '' == $comment_author ) {
  3704 		if ( '' === $comment_author_email || '' === $comment_author ) {
  3634 			return new WP_Error( 'require_name_email', __( '<strong>Error:</strong> Please fill the required fields.' ), 200 );
  3705 			return new WP_Error( 'require_name_email', __( '<strong>Error:</strong> Please fill the required fields.' ), 200 );
  3635 		} elseif ( ! is_email( $comment_author_email ) ) {
  3706 		} elseif ( ! is_email( $comment_author_email ) ) {
  3636 			return new WP_Error( 'require_valid_email', __( '<strong>Error:</strong> Please enter a valid email address.' ), 200 );
  3707 			return new WP_Error( 'require_valid_email', __( '<strong>Error:</strong> Please enter a valid email address.' ), 200 );
  3637 		}
  3708 		}
  3638 	}
  3709 	}
  3762 					break;
  3833 					break;
  3763 
  3834 
  3764 				case 'comment_link':
  3835 				case 'comment_link':
  3765 					$value = get_comment_link( $comment->comment_ID );
  3836 					$value = get_comment_link( $comment->comment_ID );
  3766 					$value = sprintf(
  3837 					$value = sprintf(
  3767 						'<a href="%s" target="_blank" rel="noopener">%s</a>',
  3838 						'<a href="%s" target="_blank">%s</a>',
  3768 						esc_url( $value ),
  3839 						esc_url( $value ),
  3769 						esc_html( $value )
  3840 						esc_html( $value )
  3770 					);
  3841 					);
  3771 					break;
  3842 					break;
  3772 			}
  3843 			}