$values Sanitized values. * @param string $ip Visitor IP. */ public static function is_spam( Form $form, array $values, string $ip ): bool { $parts = self::parts( $form, $values ); $agent = self::user_agent(); if ( Settings::get( 'use_disallowed_list' ) && wp_check_comment_disallowed_list( $parts['author'], $parts['email'], $parts['url'], $parts['content'], $ip, $agent ) ) { return true; } if ( ! empty( $form->settings['akismet'] ) && self::akismet_available() ) { return self::akismet_says_spam( $form, $parts, $ip, $agent ); } return false; } /** * Maps form values to comment-like parts. * * @param Form $form Form. * @param array $values Values. * @return array{author:string,email:string,url:string,content:string} */ private static function parts( Form $form, array $values ): array { $parts = array( 'author' => '', 'email' => '', 'url' => '', 'content' => '', ); $text = array(); foreach ( $form->input_fields() as $name => $field ) { $value = $values[ $name ] ?? ''; $value = is_array( $value ) ? implode( ', ', $value ) : (string) $value; if ( '' === $value ) { continue; } if ( 'email' === $field->type && '' === $parts['email'] ) { $parts['email'] = $value; } elseif ( 'url' === $field->type && '' === $parts['url'] ) { $parts['url'] = $value; } elseif ( '' === $parts['author'] && ( 'name' === $field->type || ( 'text' === $field->type && str_contains( strtolower( $name ), 'name' ) ) ) ) { $parts['author'] = $value; } elseif ( in_array( $field->type, array( 'text', 'textarea' ), true ) ) { $text[] = $value; } } $parts['content'] = implode( "\n\n", $text ); return $parts; } /** * Asks Akismet. Network problems count as "not spam" (fail open), as * Akismet is an extra layer on top of the other checks. * * @param Form $form Form. * @param array{author:string,email:string,url:string,content:string} $parts Parts. * @param string $ip IP. * @param string $agent User agent. */ private static function akismet_says_spam( Form $form, array $parts, string $ip, string $agent ): bool { $query = array( 'blog' => home_url(), 'blog_lang' => get_locale(), 'blog_charset' => get_option( 'blog_charset' ), 'user_ip' => $ip, 'user_agent' => $agent, 'referrer' => isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : '', 'comment_type' => 'contact-form', 'comment_author' => $parts['author'], 'comment_author_email' => $parts['email'], 'comment_author_url' => $parts['url'], 'comment_content' => $parts['content'], ); /** * Filters the data sent to Akismet. * * @param array $query Akismet comment-check parameters. * @param Form $form Form. */ $query = (array) apply_filters( 'tflexforms_akismet_query', $query, $form ); $response = \Akismet::http_post( http_build_query( $query ), 'comment-check' ); return is_array( $response ) && isset( $response[1] ) && 'true' === trim( (string) $response[1] ); } /** * Visitor user agent, trimmed. */ public static function user_agent(): string { $agent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : ''; return substr( $agent, 0, 300 ); } }