%s<\/a>$',
$quoted_author
),
);
$patterns[] = array(
'body' => sprintf(
'%s https?:.+?$',
$quoted_author
),
);
$patterns[] = array(
'email' => '@gmail.com$',
'author' => '^[a-z0-9-\.]+\.[a-z]{2,6}$',
'host' => sprintf(
'^%s$',
$quoted_author
),
);
}
$patterns = apply_filters(
'antispam_bee_patterns',
$patterns
);
if ( ! $patterns ) {
return false;
}
foreach ( $patterns as $pattern ) {
$hits = array();
foreach ( $pattern as $field => $regexp ) {
if ( empty( $field ) || ! in_array( $field, $fields, true ) || empty( $regexp ) ) {
continue;
}
$comment[ $field ] = ( function_exists( 'iconv' ) ? iconv( 'utf-8', 'utf-8//TRANSLIT', $comment[ $field ] ) : $comment[ $field ] );
if ( empty( $comment[ $field ] ) ) {
continue;
}
if ( preg_match( '/' . $regexp . '/isu', $comment[ $field ] ) ) {
$hits[ $field ] = true;
}
}
if ( count( $hits ) === count( $pattern ) ) {
return true;
}
}
return false;
}
/**
* Review a comment on its existence in the local spam
*
* @since 2.0.0
* @since 2.5.4
*
* @param string $ip Comment IP.
* @param string $url Comment URL (optional).
* @param string $email Comment Email (optional).
* @return boolean True for suspicious comment.
*/
private static function _is_db_spam( $ip, $url = '', $email = '' ) {
global $wpdb;
$params = array();
$filter = array();
if ( ! empty( $url ) ) {
$filter[] = '`comment_author_url` = %s';
$params[] = wp_unslash( $url );
}
if ( ! empty( $ip ) ) {
$filter[] = '`comment_author_IP` = %s';
$params[] = wp_unslash( $ip );
}
if ( ! empty( $email ) ) {
$filter[] = '`comment_author_email` = %s';
$params[] = wp_unslash( $email );
}
if ( empty( $params ) ) {
return false;
}
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
// phpcs:disable WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
$filter_sql = implode( ' OR ', $filter );
$result = $wpdb->get_var(
$wpdb->prepare(
sprintf(
"SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = 'spam' AND (%s) LIMIT 1",
$filter_sql
),
$params
)
);
// phpcs:enable WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
return ! empty( $result );
}
/**
* Check for country spam by (anonymized) IP
*
* @since 2.6.9
* @since 2.10.0 Make country check API filterable and use iplocate.io instead of ip2country.info
*
* @param string $ip IP address.
* @return boolean True if the comment is spam based on country filter.
*/
private static function _is_country_spam( $ip ) {
$options = self::get_options();
$allowed = preg_split(
'/[\s,;]+/',
$options['country_allowed'],
-1,
PREG_SPLIT_NO_EMPTY
);
$denied = preg_split(
'/[\s,;]+/',
$options['country_denied'],
-1,
PREG_SPLIT_NO_EMPTY
);
if ( empty( $allowed ) && empty( $denied ) ) {
return false;
}
/**
* Filter to hook into the `_is_country_spam` functionality, to implement for example a custom IP check.
*
* @since 2.10.0
*
* @param null $is_country_spam The `is_country_spam` result.
* @param string $ip The IP address.
* @param array $allowed The list of allowed country codes.
* @param array $denied The list of denied country codes.
*
* @return null|boolean The `is_country_spam` result or null.
*/
$is_country_spam = apply_filters( 'antispam_bee_is_country_spam', null, $ip, $allowed, $denied );
if ( is_bool( $is_country_spam ) ) {
return $is_country_spam;
}
/**
* Filters the IPLocate API key. With this filter, you can add your own IPLocate API key.
*
* @since 2.10.0
*
* @param string The current IPLocate API key. Default is `null`.
*
* @return string The changed IPLocate API key or null.
*/
$apikey = apply_filters( 'antispam_bee_country_spam_apikey', '' );
$response = wp_safe_remote_get(
esc_url_raw(
sprintf(
'https://www.iplocate.io/api/lookup/%s?apikey=%s',
self::_anonymize_ip( $ip ),
$apikey
),
'https'
)
);
if ( is_wp_error( $response ) ) {
return false;
}
if ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
return false;
}
$body = (string) wp_remote_retrieve_body( $response );
$json = json_decode( $body, true );
// Check if response is valid json.
if ( ! is_array( $json ) ) {
return false;
}
if ( empty( $json['country_code'] ) ) {
return false;
}
$country = strtoupper( $json['country_code'] );
if ( empty( $country ) || strlen( $country ) !== 2 ) {
return false;
}
if ( ! empty( $denied ) ) {
return ( in_array( $country, $denied, true ) );
}
return ( ! in_array( $country, $allowed, true ) );
}
/**
* Check for BBCode spam
*
* @since 2.5.1
*
* @param string $body Content of a comment.
* @return boolean True for BBCode in content
*/
private static function _is_bbcode_spam( $body ) {
return (bool) preg_match( '/\[url[=\]].*\[\/url\]/is', $body );
}
/**
* Check for an already approved e-mail address
*
* @since 2.0
* @since 2.5.1
*
* @param string $email E-mail address.
* @return boolean True for a found entry.
*/
private static function _is_approved_email( $email ) {
global $wpdb;
$result = $wpdb->get_var(
$wpdb->prepare(
"SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = '1' AND `comment_author_email` = %s LIMIT 1",
wp_unslash( $email )
)
);
if ( $result ) {
return true;
}
return false;
}
/**
* Check for unwanted languages
*
* @since 2.0
* @since 2.6.6
* @since 2.8.2
*
* @param string $comment_content Content of the comment.
*
* @return boolean TRUE if it is spam.
*/
private static function _is_lang_spam( $comment_content ) {
$allowed_lang = (array) self::get_option( 'translate_lang' );
$comment_text = wp_strip_all_tags( $comment_content );
if ( empty( $allowed_lang ) || empty( $comment_text ) ) {
return false;
}
/**
* Filters the detected language. With this filter, other detection methods can skip in and detect the language.
*
* @since 2.8.2
*
* @param null $detected_lang The detected language.
* @param string $comment_text The text, to detect the language.
*
* @return null|string The detected language or null.
*/
$detected_lang = apply_filters( 'antispam_bee_detected_lang', null, $comment_text );
if ( null !== $detected_lang ) {
return ! in_array( $detected_lang, $allowed_lang, true );
}
$word_count = 0;
$text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $comment_text ), ' ' );
/*
* translators: If your word count is based on single characters (e.g. East Asian characters),
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
* Do not translate into your own language.
*/
if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) { // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
preg_match_all( '/./u', $text, $words_array );
if ( isset( $words_array[0] ) ) {
$word_count = count( $words_array[0] );
}
} else {
$words_array = preg_split( "/[\n\r\t ]+/", $text, -1, PREG_SPLIT_NO_EMPTY );
$word_count = count( $words_array );
}
if ( $word_count < 10 ) {
return false;
}
$response = wp_safe_remote_post(
'https://api.pluginkollektiv.org/language/v1/',
array( 'body' => wp_json_encode( array( 'body' => $comment_text ) ) )
);
if ( is_wp_error( $response )
|| wp_remote_retrieve_response_code( $response ) !== 200 ) {
return false;
}
$detected_lang = wp_remote_retrieve_body( $response );
if ( ! $detected_lang ) {
return false;
}
$detected_lang = json_decode( $detected_lang );
if ( ! $detected_lang || ! isset( $detected_lang->code ) ) {
return false;
}
return ! in_array( self::_map_lang_code( $detected_lang->code ), $allowed_lang, true );
}
/**
* Map franc language codes
*
* @since 2.9.0
*
* @param string $franc_code The franc code, received from the service.
*
* @return string Mapped ISO code
*/
private static function _map_lang_code( $franc_code ) {
$codes = array(
'zha' => 'za',
'zho' => 'zh',
'zul' => 'zu',
'yid' => 'yi',
'yor' => 'yo',
'xho' => 'xh',
'wln' => 'wa',
'wol' => 'wo',
'ven' => 've',
'vie' => 'vi',
'vol' => 'vo',
'uig' => 'ug',
'ukr' => 'uk',
'urd' => 'ur',
'uzb' => 'uz',
'tah' => 'ty',
'tam' => 'ta',
'tat' => 'tt',
'tel' => 'te',
'tgk' => 'tg',
'tgl' => 'tl',
'tha' => 'th',
'tir' => 'ti',
'ton' => 'to',
'tsn' => 'tn',
'tso' => 'ts',
'tuk' => 'tk',
'tur' => 'tr',
'twi' => 'tw',
'sag' => 'sg',
'san' => 'sa',
'sin' => 'si',
'slk' => 'sk',
'slv' => 'sl',
'sme' => 'se',
'smo' => 'sm',
'sna' => 'sn',
'snd' => 'sd',
'som' => 'so',
'sot' => 'st',
'spa' => 'es',
'sqi' => 'sq',
'srd' => 'sc',
'srp' => 'sr',
'ssw' => 'ss',
'sun' => 'su',
'swa' => 'sw',
'swe' => 'sv',
'roh' => 'rm',
'ron' => 'ro',
'run' => 'rn',
'rus' => 'ru',
'que' => 'qu',
'pan' => 'pa',
'pli' => 'pi',
'pol' => 'pl',
'por' => 'pt',
'pus' => 'ps',
'oci' => 'oc',
'oji' => 'oj',
'ori' => 'or',
'orm' => 'om',
'oss' => 'os',
'nau' => 'na',
'nav' => 'nv',
'nbl' => 'nr',
'nde' => 'nd',
'ndo' => 'ng',
'nep' => 'ne',
'nld' => 'nl',
'nno' => 'nn',
'nob' => 'nb',
'nor' => 'no',
'nya' => 'ny',
'mah' => 'mh',
'mal' => 'ml',
'mar' => 'mr',
'mkd' => 'mk',
'mlg' => 'mg',
'mlt' => 'mt',
'mon' => 'mn',
'mri' => 'mi',
'msa' => 'ms',
'mya' => 'my',
'lao' => 'lo',
'lat' => 'la',
'lav' => 'lv',
'lim' => 'li',
'lin' => 'ln',
'lit' => 'lt',
'ltz' => 'lb',
'lub' => 'lu',
'lug' => 'lg',
'kal' => 'kl',
'kan' => 'kn',
'kas' => 'ks',
'kat' => 'ka',
'kau' => 'kr',
'kaz' => 'kk',
'khm' => 'km',
'kik' => 'ki',
'kin' => 'rw',
'kir' => 'ky',
'kom' => 'kv',
'kon' => 'kg',
'kor' => 'ko',
'kua' => 'kj',
'kur' => 'ku',
'jav' => 'jv',
'jpn' => 'ja',
'ibo' => 'ig',
'ido' => 'io',
'iii' => 'ii',
'iku' => 'iu',
'ile' => 'ie',
'ina' => 'ia',
'ind' => 'id',
'ipk' => 'ik',
'isl' => 'is',
'ita' => 'it',
'hat' => 'ht',
'hau' => 'ha',
'hbs' => 'sh',
'heb' => 'he',
'her' => 'hz',
'hin' => 'hi',
'hmo' => 'ho',
'hrv' => 'hr',
'hun' => 'hu',
'hye' => 'hy',
'gla' => 'gd',
'gle' => 'ga',
'glg' => 'gl',
'glv' => 'gv',
'grn' => 'gn',
'guj' => 'gu',
'fao' => 'fo',
'fas' => 'fa',
'fij' => 'fj',
'fin' => 'fi',
'fra' => 'fr',
'fry' => 'fy',
'ful' => 'ff',
'ell' => 'el',
'eng' => 'en',
'epo' => 'eo',
'est' => 'et',
'eus' => 'eu',
'ewe' => 'ee',
'dan' => 'da',
'deu' => 'de',
'div' => 'dv',
'dzo' => 'dz',
'cat' => 'ca',
'ces' => 'cs',
'cha' => 'ch',
'che' => 'ce',
'chu' => 'cu',
'chv' => 'cv',
'cor' => 'kw',
'cos' => 'co',
'cre' => 'cr',
'cym' => 'cy',
'bak' => 'ba',
'bam' => 'bm',
'bel' => 'be',
'ben' => 'bn',
'bis' => 'bi',
'bod' => 'bo',
'bos' => 'bs',
'bre' => 'br',
'bul' => 'bg',
'aar' => 'aa',
'abk' => 'ab',
'afr' => 'af',
'aka' => 'ak',
'amh' => 'am',
'ara' => 'ar',
'arg' => 'an',
'asm' => 'as',
'ava' => 'av',
'ave' => 'ae',
'aym' => 'ay',
'aze' => 'az',
'nds' => 'de',
);
if ( array_key_exists( $franc_code, $codes ) ) {
return $codes[ $franc_code ];
}
return $franc_code;
}
/**
* Trim IP addresses
*
* @since 0.1
* @since 2.5.1
*
* @param string $ip Original IP.
* @param boolean $cut_end Shortening the end.
* @return string Shortened IP.
*/
private static function _cut_ip( $ip, $cut_end = true ) {
$separator = ( self::_is_ipv4( $ip ) ? '.' : ':' );
return str_replace(
( $cut_end ? strrchr( $ip, $separator ) : strstr( $ip, $separator ) ),
'',
$ip
);
}
/**
* Anonymize the IP addresses
*
* @since 2.5.1
*
* @param string $ip Original IP.
* @return string Anonymous IP.
*/
private static function _anonymize_ip( $ip ) {
if ( self::_is_ipv4( $ip ) ) {
return self::_cut_ip( $ip ) . '.0';
}
return self::_cut_ip( $ip, false ) . ':0:0:0:0:0:0:0';
}
/**
* Rotates the IP address
*
* @since 2.4.5
*
* @param string $ip IP address.
* @return string Turned IP address.
*/
private static function _reverse_ip( $ip ) {
return implode(
'.',
array_reverse(
explode(
'.',
$ip
)
)
);
}
/**
* Check for an IPv4 address
*
* @since 2.4
* @since 2.6.4
*
* @param string $ip IP to validate.
* @return integer TRUE if IPv4.
*/
private static function _is_ipv4( $ip ) {
if ( function_exists( 'filter_var' ) ) {
return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) !== false;
} else {
return preg_match( '/^\d{1,3}(\.\d{1,3}){3}$/', $ip );
}
}
/**
* Check for an IPv6 address
*
* @since 2.6.2
* @since 2.6.4
*
* @param string $ip IP to validate.
* @return boolean TRUE if IPv6.
*/
private static function _is_ipv6( $ip ) {
if ( function_exists( 'filter_var' ) ) {
return filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 ) !== false;
} else {
return ! self::_is_ipv4( $ip );
}
}
/**
* Testing on mobile devices
*
* @since 0.1
* @since 2.4
*
* @return boolean TRUE if "wptouch" is active
*/
private static function _is_mobile() {
return strpos( get_template_directory(), 'wptouch' );
}
/**
* Testing if we are on an AMP site.
*
* Starting with v2.0, amp_is_request() is the preferred method to check,
* but we fall back to the then deprecated is_amp_endpoint() as needed.
*
* @return bool
*/
private static function _is_amp() {
return ( function_exists( 'amp_is_request' ) && amp_is_request() ) || ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() );
}
/*
* ############################
* ##### SPAM-TREATMENT #####
* ############################
*/
/**
* Execution of the delete/marking process
*
* @since 0.1
* @since 2.6.0
*
* @param array $comment Untreated commentary data.
* @param string $reason Reason for suspicion.
* @param boolean $is_ping Ping (optional).
* @return array $comment Treated commentary data.
*/
private static function _handle_spam_request( $comment, $reason, $is_ping = false ) {
$options = self::get_options();
$spam_remove = ! $options['flag_spam'];
$spam_notice = ! $options['no_notice'];
// Filter settings.
$ignore_filter = $options['ignore_filter'];
$ignore_type = $options['ignore_type'];
$ignore_reason = in_array( $reason, (array) $options['ignore_reasons'], true );
// Remember spam.
self::_update_spam_log( $comment );
self::_update_spam_count();
self::_update_daily_stats();
// Delete spam.
if ( $spam_remove ) {
self::_go_in_peace();
}
if ( $ignore_filter && ( ( 1 === (int) $ignore_type && $is_ping ) || ( 2 === (int) $ignore_type && ! $is_ping ) ) ) {
self::_go_in_peace();
}
// Spam reason.
if ( $ignore_reason ) {
self::_go_in_peace();
}
self::$_reason = $reason;
// Mark spam.
add_filter(
'pre_comment_approved',
array(
__CLASS__,
'return_spam',
)
);
// Send e-mail.
add_action(
'comment_post',
array(
__CLASS__,
'send_mail_notification',
)
);
// Spam reason as comment meta.
if ( $spam_notice ) {
add_action(
'comment_post',
array(
__CLASS__,
'add_spam_reason_to_comment',
)
);
}
return $comment;
}
/**
* Logfile with detected spam
*
* @since 2.5.7
* @since 2.6.1
*
* @param array $comment Array with commentary data.
* @return mixed FALSE in case of error
*/
private static function _update_spam_log( $comment ) {
if ( ! defined( 'ANTISPAM_BEE_LOG_FILE' ) || ! ANTISPAM_BEE_LOG_FILE || ! is_writable( ANTISPAM_BEE_LOG_FILE ) || validate_file( ANTISPAM_BEE_LOG_FILE ) === 1 ) {
return false;
}
$entry = sprintf(
'%s comment for post=%d from host=%s marked as spam%s',
current_time( 'mysql' ),
$comment['comment_post_ID'],
$comment['comment_author_IP'],
PHP_EOL
);
file_put_contents(
ANTISPAM_BEE_LOG_FILE,
$entry,
FILE_APPEND | LOCK_EX
);
}
/**
* Sends the 403 header and terminates the connection
*
* @since 2.5.6
*/
private static function _go_in_peace() {
status_header( 403 );
die( 'Spam deleted.' );
}
/**
* Return real client IP
*
* @since 2.6.1
*
* @return mixed $ip Client IP
*/
public static function get_client_ip() {
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
// Sanitization of $ip takes place further down.
$ip = '';
if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) {
$ip = wp_unslash( $_SERVER['HTTP_CLIENT_IP'] );
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) {
$ip = wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] );
} elseif ( isset( $_SERVER['HTTP_X_FORWARDED'] ) ) {
$ip = wp_unslash( $_SERVER['HTTP_X_FORWARDED'] );
} elseif ( isset( $_SERVER['HTTP_FORWARDED_FOR'] ) ) {
$ip = wp_unslash( $_SERVER['HTTP_FORWARDED_FOR'] );
} elseif ( isset( $_SERVER['HTTP_FORWARDED'] ) ) {
$ip = wp_unslash( $_SERVER['HTTP_FORWARDED'] );
}
$ip = self::_sanitize_ip( $ip );
if ( $ip ) {
return $ip;
}
if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
$ip = wp_unslash( $_SERVER['REMOTE_ADDR'] );
return self::_sanitize_ip( $ip );
}
return '';
// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
}
/**
* Sanitize an IP string.
*
* @param string $raw_ip The raw IP.
*
* @return string The sanitized IP or an empty string.
*/
private static function _sanitize_ip( $raw_ip ) {
if ( strpos( $raw_ip, ',' ) !== false ) {
$ips = explode( ',', $raw_ip );
$raw_ip = trim( $ips[0] );
}
if ( function_exists( 'filter_var' ) ) {
return (string) filter_var(
$raw_ip,
FILTER_VALIDATE_IP
);
}
return (string) preg_replace(
'/[^0-9a-f:. ]/si',
'',
$raw_ip
);
}
/**
* Add spam reason as comment data
*
* @since 2.6.0
*
* @param integer $comment_id Comment ID.
*/
public static function add_spam_reason_to_comment( $comment_id ) {
add_comment_meta(
$comment_id,
'antispam_bee_reason',
self::$_reason
);
}
/**
* Delete spam reason as comment data
*
* @since 2.6.0
*
* @param integer $comment_id Comment ID.
*/
public static function delete_spam_reason_by_comment( $comment_id ) {
delete_comment_meta(
$comment_id,
'antispam_bee_reason'
);
}
/**
* Updates the Antispam Bee reason for manual transitions
*
* @since 2.9.2
* @param WP_Comment $comment Comment Object.
*/
public static function update_antispam_bee_reason( $comment ) {
update_comment_meta( $comment->comment_ID, 'antispam_bee_reason', 'manually' );
}
/**
* Get the current post ID.
*
* @since 2.7.1
*/
public static function populate_post_id() {
if ( null === self::$_current_post_id ) {
self::$_current_post_id = get_the_ID();
}
}
/**
* Send notification via e-mail
*
* @since 0.1
* @since 2.5.7
* @since 2.10.0 Change plugin website URL
*
* @hook string antispam_bee_notification_subject Custom subject for notification mails
*
* @param int $id ID of the comment.
* @return int $id ID of the comment.
*/
public static function send_mail_notification( $id ) {
$options = self::get_options();
if ( ! $options['email_notify'] ) {
return $id;
}
$comment = get_comment( $id, ARRAY_A );
if ( empty( $comment ) ) {
return $id;
}
$post = get_post( $comment['comment_post_ID'] );
if ( ! $post ) {
return $id;
}
self::load_plugin_lang();
$subject = sprintf(
'[%s] %s',
stripslashes_deep(
// phpcs:ignore PHPCompatibility.ParameterValues.NewHTMLEntitiesEncodingDefault.NotSet
html_entity_decode(
get_bloginfo( 'name' ),
ENT_QUOTES
)
),
esc_html__( 'Comment marked as spam', 'antispam-bee' )
);
// Content.
$content = strip_tags( stripslashes( $comment['comment_content'] ) );
if ( ! $content ) {
$content = sprintf(
'-- %s --',
esc_html__( 'Content removed by Antispam Bee', 'antispam-bee' )
);
}
// Prepare Comment Type.
$comment_name = __( 'Comment', 'antispam-bee' );
if ( 'trackback' === $comment['comment_type'] ) {
$comment_name = __( 'Trackback', 'antispam-bee' );
}
if ( 'pingback' === $comment['comment_type'] ) {
$comment_name = __( 'Pingback', 'antispam-bee' );
}
// Body.
$body = sprintf(
"%s \"%s\"\r\n\r\n",
esc_html__( 'New spam comment on your post', 'antispam-bee' ),
strip_tags( $post->post_title )
) . sprintf(
"%s: %s\r\n",
esc_html__( 'Author', 'antispam-bee' ),
( empty( $comment['comment_author'] ) ? '' : strip_tags( $comment['comment_author'] ) )
) . sprintf(
"URL: %s\r\n",
// empty check exists.
esc_url( $comment['comment_author_url'] )
) . sprintf(
"%s: %s\r\n",
esc_html__( 'Type', 'antispam-bee' ),
esc_html( $comment_name )
) . sprintf(
"Whois: http://whois.arin.net/rest/ip/%s\r\n",
$comment['comment_author_IP']
) . sprintf(
"%s: %s\r\n\r\n",
esc_html__( 'Spam Reason', 'antispam-bee' ),
esc_html( self::$defaults['reasons'][ self::$_reason ] )
) . sprintf(
"%s\r\n\r\n\r\n",
$content
) . (
EMPTY_TRASH_DAYS ? (
sprintf(
"%s: %s\r\n",
esc_html__( 'Trash it', 'antispam-bee' ),
admin_url( 'comment.php?action=trash&c=' . $id )
)
) : (
sprintf(
"%s: %s\r\n",
esc_html__( 'Delete it', 'antispam-bee' ),
admin_url( 'comment.php?action=delete&c=' . $id )
)
)
) . sprintf(
"%s: %s\r\n",
esc_html__( 'Approve it', 'antispam-bee' ),
admin_url( 'comment.php?action=approve&c=' . $id )
) . sprintf(
"%s: %s\r\n\r\n",
esc_html__( 'Spam list', 'antispam-bee' ),
admin_url( 'edit-comments.php?comment_status=spam' )
) . sprintf(
"%s\r\n%s\r\n",
esc_html__( 'Notify message by Antispam Bee', 'antispam-bee' ),
esc_html__( 'https://antispambee.pluginkollektiv.org/', 'antispam-bee' )
);
wp_mail(
/**
* Filters the recipients of the spam notification.
*
* @param array The recipients array.
*/
apply_filters(
'antispam_bee_notification_recipients',
array( get_bloginfo( 'admin_email' ) )
),
/**
* Filters the subject of the spam notification.
*
* @param string $subject subject line.
*/
apply_filters(
'antispam_bee_notification_subject',
$subject
),
$body
);
return $id;
}
/*
* ############################
* ####### STATISTICS #######
* ############################
*/
/**
* Return the number of spam comments
*
* @since 0.1
* @since 2.4
*/
private static function _get_spam_count() {
// Init.
$count = self::get_option( 'spam_count' );
// Fire.
return ( get_locale() === 'de_DE' ? number_format( $count, 0, '', '.' ) : number_format_i18n( $count ) );
}
/**
* Output the number of spam comments
*
* @since 0.1
* @since 2.4
*/
public static function the_spam_count() {
echo esc_html( self::_get_spam_count() );
}
/**
* Update the number of spam comments
*
* @since 0.1
* @since 2.6.1
*/
private static function _update_spam_count() {
// Skip if not enabled.
if ( ! self::get_option( 'dashboard_count' ) ) {
return;
}
self::_update_option(
'spam_count',
intval( self::get_option( 'spam_count' ) + 1 )
);
}
/**
* Update statistics
*
* @since 1.9
* @since 2.6.1
*/
private static function _update_daily_stats() {
// Skip if not enabled.
if ( ! self::get_option( 'dashboard_chart' ) ) {
return;
}
// Init.
$stats = (array) self::get_option( 'daily_stats' );
$today = (int) strtotime( 'today' );
// Count up.
if ( array_key_exists( $today, $stats ) ) {
$stats[ $today ] ++;
} else {
$stats[ $today ] = 1;
}
// Sort.
krsort( $stats, SORT_NUMERIC );
// Save.
self::_update_option(
'daily_stats',
array_slice( $stats, 0, 31, true )
);
}
/**
* Returns the secret of a post used in the textarea name attribute.
*
* @since 2.10.0 Modify secret generation because `always_allowed` option not longer exists
*
* @param int $post_id The Post ID.
*
* @return string
*/
public static function get_secret_name_for_post( $post_id ) {
$secret = substr( sha1( md5( 'comment-id' . self::$_salt ) ), 0, 10 );
$secret = self::ensure_secret_starts_with_letter( $secret );
/**
* Filters the secret for a post, which is used in the textarea name attribute.
*
* @param string $secret The secret.
* @param int $post_id The post ID.
* @param bool $always_allowed Whether the comment form is used outside of the single post view or not.
*/
return apply_filters(
'ab_get_secret_name_for_post',
$secret,
(int) $post_id,
(bool) self::get_option( 'always_allowed' )
);
}
/**
* Returns the secret of a post used in the textarea id attribute.
*
* @since 2.10.0 Modify secret generation because `always_allowed` option not longer exists
*
* @param int $post_id The post ID.
*
* @return string
*/
public static function get_secret_id_for_post( $post_id ) {
$secret = substr( sha1( md5( 'comment-id' . self::$_salt ) ), 0, 10 );
$secret = self::ensure_secret_starts_with_letter( $secret );
/**
* Filters the secret for a post, which is used in the textarea id attribute.
*
* @param string $secret The secret.
* @param int $post_id The post ID.
* @param bool $always_allowed Whether the comment form is used outside of the single post view or not.
*/
return apply_filters(
'ab_get_secret_id_for_post',
$secret,
(int) $post_id,
(bool) self::get_option( 'always_allowed' )
);
}
/**
* Ensures that the secret starts with a letter.
*
* @param string $secret The secret.
*
* @return string
*/
public static function ensure_secret_starts_with_letter( $secret ) {
$first_char = substr( $secret, 0, 1 );
if ( is_numeric( $first_char ) ) {
return chr( $first_char + 97 ) . substr( $secret, 1 );
} else {
return $secret;
}
}
/**
* Returns 'spam'
*
* @since 2.7.3
*
* @return string
*/
public static function return_spam() {
return 'spam';
}
/**
* A wrapper around wp_parse_url().
*
* @since 2.8.2
*
* @param string $url The URL to parse.
* @param string $component The component to get back.
*
* @return string
*/
private static function parse_url( $url, $component = 'host' ) {
$parts = wp_parse_url( $url );
return ( is_array( $parts ) && isset( $parts[ $component ] ) ) ? $parts[ $component ] : '';
}
/**
* Updates the database structure if necessary
*
* @since 2.10.0 Add update routine for country option names
*/
public static function update_database() {
if ( self::db_version_is_current() ) {
return;
}
$version_from_db = floatval( get_option( 'antispambee_db_version', 0 ) );
if ( $version_from_db < 1.01 ) {
global $wpdb;
/**
* In Version 2.9 the IP of the commenter was saved as a hash. We reverted this solution.
* Therefore, we need to delete this unused data.
*/
//phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
$sql = 'delete from `' . $wpdb->commentmeta . '` where `meta_key` IN ("antispam_bee_iphash")';
$wpdb->query( $sql );
//phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
}
// DB version was raised in ASB 2.10.0 to 1.02.
if ( $version_from_db < 1.02 ) {
// Update option names.
$options = self::get_options();
if ( isset( $options['country_black'] ) ) {
$options['country_denied'] = $options['country_black'];
unset( $options['country_black'] );
}
if ( isset( $options['country_white'] ) ) {
$options['country_allowed'] = $options['country_white'];
unset( $options['country_white'] );
}
update_option(
'antispam_bee',
$options
);
wp_cache_set(
'antispam_bee',
$options
);
}
update_option( 'antispambee_db_version', self::$db_version );
}
/**
* Whether the database structure is up to date.
*
* @since 2.10.0 Return a float instead of int
*
* @return bool
*/
private static function db_version_is_current() {
$current_version = floatval( get_option( 'antispambee_db_version', 0 ) );
return $current_version === self::$db_version;
}
/**
* Runs after upgrades are completed.
*
* @since 2.10.0
*
* @param \WP_Upgrader $wp_upgrader WP_Upgrader instance.
* @param array $hook_extra Array of bulk item update data.
*/
public static function upgrades_completed( $wp_upgrader, $hook_extra ) {
if ( ! $wp_upgrader instanceof Plugin_Upgrader || ! isset( $hook_extra['plugins'] ) ) {
return;
}
$updated_plugins = $hook_extra['plugins'];
$asb_updated = false;
foreach ( $updated_plugins as $updated_plugin ) {
if ( $updated_plugin !== self::$_base ) {
continue;
}
$asb_updated = true;
}
if ( false === $asb_updated ) {
return;
}
self::asb_updated();
}
/**
* Runs after an upgrade via an uploaded ZIP package was completed.
*
* @since 2.10.0
*
* @param string $package The package file.
* @param array $data The new plugin or theme data.
* @param string $package_type The package type.
*/
public static function uploaded_upgrade_completed( $package, $data, $package_type ) {
if ( 'plugin' !== $package_type ) {
return;
}
$text_domain = isset( $data['TextDomain'] ) ? $data['TextDomain'] : '';
if ( 'antispam-bee' !== $text_domain ) {
return;
}
self::asb_updated();
}
/**
* Runs after ASB was updated.
*
* @since 2.10.0
*
* @return void
*/
private static function asb_updated() {
self::update_database();
}
}
// Fire.
add_action(
'plugins_loaded',
array(
'Antispam_Bee',
'init',
)
);
// Activation.
register_activation_hook(
__FILE__,
array(
'Antispam_Bee',
'activate',
)
);
// Deactivation.
register_deactivation_hook(
__FILE__,
array(
'Antispam_Bee',
'deactivate',
)
);
// Uninstall.
register_uninstall_hook(
__FILE__,
array(
'Antispam_Bee',
'uninstall',
)
);
Why Silco Cables – Welcome to Silco Control Cables
Why Silco Cablesadmin2023-01-31T07:49:42+00:00
Why Silco Cables?
- Standardized and Tested Product
- Excellent Packaging Standards to make handling hassle free
- No Additional Charges for Box Packaging (10pcs. Standard Packing)
- High Returns on Low Investment
- Faster Delivery and up to 100% order Fulfillment
- Dedicated Team of Engineers for faster development of new products
- System Driven Company (ISO 9001:2015 certified)
- We listen to Our Customers (Toll Free Number +91 800-900-6604 )
- Efficient Sales and Marketing Team
- Sales and Marketing Support by regular market visits, order collections, promotional material, brand campaign events and exhibitions
- Resellers Schemes
- Mechanics Loyalty Program
- Authorized Business Partner: Fair Dealings
- Silco Cables gives you exclusive selling rights in your area
[ultimate_carousel slides_on_desk=”4″ slides_on_tabs=”2″ arrows=”off” dots_color=”#008fd5″ dots_icon=”ultsl-radio-checked”]
300+
Distributors Pan India
10
Exported to over 10 Countries
[/ultimate_carousel]