From 6d64a3747b6543c6009c0f1de46f973549ee1570 Mon Sep 17 00:00:00 2001
From: Bernhard Kau
Date: Sat, 19 Mar 2022 19:44:51 +0100
Subject: [PATCH 001/184] first draft of new 3.0 branch with the basic
bootstrapping project and build processes
---
.editorconfig | 22 +
.eslintrc | 20 +
.eslintrc.json | 21 -
.gitignore | 4 +
.stylelintrc.json | 6 -
antispam_bee.php | 3080 +----------
composer.json | 22 +-
composer.lock | 8171 ------------------------------
css/dashboard.css | 19 -
css/styles.css | 265 -
inc/columns.class.php | 160 -
inc/gui.class.php | 573 ---
js/dashboard.js | 112 -
js/raphael.helper.js | 140 -
js/raphael.min.js | 3 -
js/scripts.js | 20 -
lib/Helpers/AssetsLoader.php | 91 +
lib/load.php | 29 +
package.json | 39 +-
phpcs.xml | 128 +-
src/backend.js | 1 +
src/backend.scss | 1 +
src/images/icons/filter.svg | 1 +
src/images/icons/share-nodes.svg | 1 +
src/images/icons/sliders.svg | 1 +
webpack.config.js | 44 +
26 files changed, 410 insertions(+), 12564 deletions(-)
create mode 100644 .editorconfig
create mode 100644 .eslintrc
delete mode 100644 .eslintrc.json
mode change 100755 => 100644 antispam_bee.php
delete mode 100644 composer.lock
delete mode 100644 css/dashboard.css
delete mode 100644 css/styles.css
delete mode 100644 inc/columns.class.php
delete mode 100644 inc/gui.class.php
delete mode 100644 js/dashboard.js
delete mode 100644 js/raphael.helper.js
delete mode 100644 js/raphael.min.js
delete mode 100644 js/scripts.js
create mode 100644 lib/Helpers/AssetsLoader.php
create mode 100644 lib/load.php
create mode 100644 src/backend.js
create mode 100644 src/backend.scss
create mode 100644 src/images/icons/filter.svg
create mode 100644 src/images/icons/share-nodes.svg
create mode 100644 src/images/icons/sliders.svg
create mode 100644 webpack.config.js
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..79207a40
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,22 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+# WordPress Coding Standards
+# https://make.wordpress.org/core/handbook/coding-standards/
+
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = tab
+indent_size = 4
+
+[{.jshintrc,*.json,*.yml}]
+indent_style = space
+indent_size = 2
+
+[{*.txt,wp-config-sample.php}]
+end_of_line = crlf
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 00000000..6379d068
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,20 @@
+{
+ "extends": [
+ "plugin:@wordpress/eslint-plugin/recommended"
+ ],
+ "env": {
+ "browser": true
+ },
+ "rules": {
+ "max-len": [
+ "error",
+ {
+ "code": 160
+ }
+ ],
+ "prettier/prettier": 0
+ },
+ "parserOptions": {
+ "requireConfigFile": false
+ }
+}
diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index 782125e7..00000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,21 +0,0 @@
-{
- "extends": "plugin:@wordpress/eslint-plugin/es5",
- "env": {
- "browser": true,
- "jquery": true
- },
- "globals": {
- "Raphael": "readonly",
- "getAnchors": "readonly"
- },
- "rules": {
- "camelcase": 0,
- "eqeqeq": 0,
- "no-mixed-operators": 0,
- "no-redeclare": 0,
- "no-shadow": 0,
- "no-unused-expressions": 0,
- "no-unused-vars": 0,
- "vars-on-top": 0
- }
-}
diff --git a/.gitignore b/.gitignore
index 0436199f..35f41dba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,12 +1,16 @@
+*.css.map
css/*.min.css
js/*.min.js
.idea/
+build/
node_modules/
tmp/
vendor/
chromedriver
+composer.lock
driver.tar.gz
driver.zip
geckodrier
nohup.out
package-lock.json
+yarn.lock
diff --git a/.stylelintrc.json b/.stylelintrc.json
index 68e038b0..829a7dcf 100644
--- a/.stylelintrc.json
+++ b/.stylelintrc.json
@@ -1,11 +1,5 @@
{
"extends": "@wordpress/stylelint-config",
"rules": {
- "declaration-property-unit-allowed-list": null,
- "font-weight-notation": null,
- "font-family-no-missing-generic-family-keyword": null,
- "no-descending-specificity": null,
- "selector-class-pattern": null,
- "selector-id-pattern": null
}
}
diff --git a/antispam_bee.php b/antispam_bee.php
old mode 100755
new mode 100644
index 008c0060..6af04132
--- a/antispam_bee.php
+++ b/antispam_bee.php
@@ -1,3041 +1,87 @@
0,
- ),
- '',
- 'no'
- );
-
- if ( self::get_option( 'cronjob_enable' ) ) {
- self::init_scheduled_hook();
- }
- }
-
-
- /**
- * Action to deactivate the plugin
- *
- * @since 0.1
- * @since 2.4
- */
- public static function deactivate() {
- self::clear_scheduled_hook();
- }
-
-
- /**
- * Action deleting the plugin
- *
- * @since 2.4
- */
- public static function uninstall() {
- if ( ! self::get_option( 'delete_data_on_uninstall' ) ) {
- return;
- }
- global $wpdb;
-
- delete_option( 'antispam_bee' );
- $wpdb->query( 'OPTIMIZE TABLE `' . $wpdb->options . '`' );
-
- //phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
- $sql = 'delete from `' . $wpdb->commentmeta . '` where `meta_key` IN ("antispam_bee_iphash", "antispam_bee_reason")';
- $wpdb->query( $sql );
- //phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
- }
-
-
-
- /*
- * ############################
- * ######## INTERNAL ########
- * ############################
- */
-
- /**
- * Initialization of the internal variables
- *
- * @since 2.4
- * @since 2.7.0
- * @since 2.10.0 Change renamed country option names in options array
- */
- private static function _init_internal_vars() {
- self::$_base = plugin_basename( __FILE__ );
-
- $salt = defined( 'NONCE_SALT' ) ? NONCE_SALT : ABSPATH;
- self::$_salt = substr( sha1( $salt ), 0, 10 );
-
- self::$defaults = array(
- 'options' => array(
- 'regexp_check' => 1,
- 'spam_ip' => 1,
- 'already_commented' => 1,
- 'gravatar_check' => 0,
- 'time_check' => 0,
- 'ignore_pings' => 0,
-
- 'dashboard_chart' => 0,
- 'dashboard_count' => 0,
-
- 'country_code' => 0,
- 'country_denied' => '',
- 'country_allowed' => '',
-
- 'translate_api' => 0,
- 'translate_lang' => array(),
-
- 'bbcode_check' => 1,
-
- 'flag_spam' => 1,
- 'email_notify' => 0,
- 'no_notice' => 0,
- 'cronjob_enable' => 0,
- 'cronjob_interval' => 0,
-
- 'ignore_filter' => 0,
- 'ignore_type' => 0,
-
- 'reasons_enable' => 0,
- 'ignore_reasons' => array(),
-
- 'delete_data_on_uninstall' => 1,
- ),
- 'reasons' => array(
- 'css' => esc_attr__( 'Honeypot', 'antispam-bee' ),
- 'time' => esc_attr__( 'Comment time', 'antispam-bee' ),
- 'empty' => esc_attr__( 'Empty Data', 'antispam-bee' ),
- 'localdb' => esc_attr__( 'Local DB Spam', 'antispam-bee' ),
- 'server' => esc_attr__( 'Fake IP', 'antispam-bee' ),
- 'country' => esc_attr__( 'Country Check', 'antispam-bee' ),
- 'bbcode' => esc_attr__( 'BBCode', 'antispam-bee' ),
- 'lang' => esc_attr__( 'Comment Language', 'antispam-bee' ),
- 'regexp' => esc_attr__( 'Regular Expression', 'antispam-bee' ),
- 'title_is_name' => esc_attr__( 'Identical Post title and blog title', 'antispam-bee' ),
- 'manually' => esc_attr__( 'Manually', 'antispam-bee' ),
- ),
- );
- }
-
- /**
- * Check and return an array key
- *
- * @since 2.4.2
- * @since 2.10.0 Only return `null` if option does not exist.
- *
- * @param array $array Array with values.
- * @param string $key Name of the key.
- * @return mixed Value of the requested key.
- */
- public static function get_key( $array, $key ) {
- if ( empty( $array ) || empty( $key ) || ! isset( $array[ $key ] ) ) {
- return null;
- }
-
- return $array[ $key ];
- }
-
- /**
- * Check if comment is a ping (pingback, trackback or something similar)
- *
- * @since 2.10.0
- *
- * @param array $comment Treated commentary data.
- * @return boolean `true` if ping and `false` if classic comment
- */
- public static function is_ping( $comment ) {
- $types = array( 'pingback', 'trackback', 'pings' );
- $is_ping = false;
-
- if ( in_array( self::get_key( $comment, 'comment_type' ), $types, true ) ) {
- $is_ping = true;
- }
-
- return apply_filters( 'antispam_bee_is_ping', $is_ping, $comment );
- }
-
- /**
- * Localization of the admin pages
- *
- * @since 0.1
- * @since 2.4
- *
- * @param string $page Mark the page.
- * @return boolean True on success.
- */
- private static function _current_page( $page ) {
- // phpcs:disable WordPress.CSRF.NonceVerification.NoNonceVerification
- switch ( $page ) {
- case 'dashboard':
- return ( empty( $GLOBALS['pagenow'] ) || ( ! empty( $GLOBALS['pagenow'] ) && 'index.php' === $GLOBALS['pagenow'] ) );
-
- case 'options':
- return ( ! empty( $_GET['page'] ) && 'antispam_bee' === $_GET['page'] );
-
- case 'plugins':
- return ( ! empty( $GLOBALS['pagenow'] ) && 'plugins.php' === $GLOBALS['pagenow'] );
-
- case 'admin-post':
- return ( ! empty( $GLOBALS['pagenow'] ) && 'admin-post.php' === $GLOBALS['pagenow'] );
-
- case 'edit-comments':
- return ( ! empty( $GLOBALS['pagenow'] ) && 'edit-comments.php' === $GLOBALS['pagenow'] );
-
- default:
- return false;
- }
- // phpcs:enable WordPress.CSRF.NonceVerification.NoNonceVerification
- }
-
-
- /**
- * Integration of the localization file
- *
- * @since 0.1
- * @since 2.4
- */
- public static function load_plugin_lang() {
- load_plugin_textdomain(
- 'antispam-bee'
- );
- }
-
-
- /**
- * Add the link to the settings
- *
- * @since 1.1
- *
- * @param array $data The action link array.
- * @return array $data The action link array.
- */
- public static function init_action_links( $data ) {
- if ( ! current_user_can( 'manage_options' ) ) {
- return $data;
- }
-
- return array_merge(
- $data,
- array(
- sprintf(
- '%s',
- add_query_arg(
- array(
- 'page' => 'antispam_bee',
- ),
- admin_url( 'options-general.php' )
- ),
- esc_attr__( 'Settings', 'antispam-bee' )
- ),
- )
- );
- }
-
- /**
- * Meta links of the plugin
- *
- * @since 0.1
- * @since 2.6.2
- *
- * @param array $input Existing links.
- * @param string $file Current page.
- * @return array $data Modified links.
- */
- public static function init_row_meta( $input, $file ) {
- if ( $file !== self::$_base ) {
- return $input;
- }
-
- return array_merge(
- $input,
- array(
- '' . esc_html__( 'Donate', 'antispam-bee' ) . '',
- '' . esc_html__( 'Support', 'antispam-bee' ) . '',
- )
- );
- }
-
- /*
- * ############################
- * ####### RESOURCES ########
- * ############################
- */
-
- /**
- * Registration of resources (CSS & JS)
- *
- * @since 1.6
- * @since 2.4.5
- */
- public static function init_plugin_sources() {
- $plugin = get_plugin_data( __FILE__ );
-
- wp_register_script(
- 'ab_script',
- plugins_url( 'js/scripts.min.js', __FILE__ ),
- array( 'jquery' ),
- $plugin['Version']
- );
-
- wp_register_style(
- 'ab_style',
- plugins_url( 'css/styles.min.css', __FILE__ ),
- array( 'dashicons' ),
- $plugin['Version']
- );
- }
-
-
- /**
- * Initialization of the option page
- *
- * @since 0.1
- * @since 2.4.3
- */
- public static function add_sidebar_menu() {
- $page = add_options_page(
- 'Antispam Bee',
- 'Antispam Bee',
- 'manage_options',
- 'antispam_bee',
- array(
- 'Antispam_Bee_GUI',
- 'options_page',
- )
- );
-
- add_action(
- 'admin_print_scripts-' . $page,
- array(
- __CLASS__,
- 'add_options_script',
- )
- );
-
- add_action(
- 'admin_print_styles-' . $page,
- array(
- __CLASS__,
- 'add_options_style',
- )
- );
-
- add_action(
- 'load-' . $page,
- array(
- __CLASS__,
- 'init_options_page',
- )
- );
- }
-
-
- /**
- * Initialization of JavaScript
- *
- * @since 1.6
- * @since 2.4
- */
- public static function add_options_script() {
- wp_enqueue_script( 'ab_script' );
- }
-
-
- /**
- * Initialization of Stylesheets
- *
- * @since 1.6
- * @since 2.4
- */
- public static function add_options_style() {
- wp_enqueue_style( 'ab_style' );
- }
-
-
- /**
- * Integration of the GUI
- *
- * @since 2.4
- */
- public static function init_options_page() {
- require_once dirname( __FILE__ ) . '/inc/gui.class.php';
- }
-
-
-
- /*
- * ############################
- * ####### DASHBOARD ########
- * ############################
- */
-
- /**
- * Display the spam counter on the dashboard
- *
- * @since 0.1
- * @since 2.6.5
- *
- * @param array $items Initial array with dashboard items.
- * @return array $items Merged array with dashboard items.
- */
- public static function add_dashboard_count( $items = array() ) {
- if ( ! current_user_can( 'manage_options' ) || ! self::get_option( 'dashboard_count' ) ) {
- return $items;
- }
-
- echo '';
-
- $items[] = '' . esc_html(
- sprintf(
- // translators: The number of spam comments Antispam Bee blocked so far.
- __( '%s Blocked', 'antispam-bee' ),
- self::_get_spam_count()
- )
- ) . '';
-
- return $items;
- }
-
- /**
- * Initialize the dashboard chart
- *
- * @since 1.9
- * @since 2.5.6
- */
- public static function add_dashboard_chart() {
- if ( ! current_user_can( 'publish_posts' ) || ! self::get_option( 'dashboard_chart' ) ) {
- return;
- }
-
- wp_add_dashboard_widget(
- 'ab_widget',
- 'Antispam Bee',
- array(
- __CLASS__,
- 'show_spam_chart',
- )
- );
-
- add_action(
- 'admin_head',
- array(
- __CLASS__,
- 'add_dashboard_style',
- )
- );
- }
-
- /**
- * Print dashboard styles
- *
- * @since 1.9.0
- * @since 2.5.8
- */
- public static function add_dashboard_style() {
- $plugin = get_plugin_data( __FILE__ );
-
- wp_register_style(
- 'ab_chart',
- plugins_url( 'css/dashboard.min.css', __FILE__ ),
- array(),
- $plugin['Version']
- );
-
- wp_print_styles( 'ab_chart' );
- }
-
-
- /**
- * Print dashboard scripts
- *
- * @since 1.9.0
- * @since 2.5.8
- */
- public static function add_dashboard_script() {
- if ( ! self::get_option( 'daily_stats' ) ) {
- return;
- }
-
- $plugin = get_plugin_data( __FILE__ );
-
- wp_enqueue_script(
- 'raphael',
- plugins_url( 'js/raphael.min.js', __FILE__ ),
- array(),
- '2.1.0',
- true
- );
-
- wp_enqueue_script(
- 'ab-raphael',
- plugins_url( 'js/raphael.helper.min.js', __FILE__ ),
- array( 'raphael' ),
- $plugin['Version'],
- true
- );
-
- wp_enqueue_script(
- 'ab_chart_js',
- plugins_url( 'js/dashboard.min.js', __FILE__ ),
- array( 'jquery', 'ab-raphael' ),
- $plugin['Version'],
- true
- );
- }
-
- /**
- * Print dashboard html
- *
- * @since 1.9.0
- * @since 2.5.8
- */
- public static function show_spam_chart() {
- $items = (array) self::get_option( 'daily_stats' );
-
- if ( empty( $items ) ) {
- echo sprintf(
- '',
- esc_html__( 'No data available.', 'antispam-bee' )
- );
-
- return;
- }
-
- self::add_dashboard_script();
-
- ksort( $items, SORT_NUMERIC );
-
- $html = "\n";
-
- $html .= "\n";
- foreach ( $items as $date => $count ) {
- $html .= '' . date_i18n( 'j. F Y', $date ) . " | \n";
- }
- $html .= "
\n";
-
- $html .= "\n";
- foreach ( $items as $date => $count ) {
- $html .= '' . (int) $count . " | \n";
- }
- $html .= "
\n";
-
- $html .= "
\n";
-
- echo wp_kses_post( '' . $html . '
' );
- }
-
- /*
- * ############################
- * ######## OPTIONS #########
- * ############################
- */
-
- /**
- * Get all plugin options
- *
- * @since 2.4
- * @since 2.6.1
- *
- * @return array $options Array with option fields.
- */
- public static function get_options() {
- $options = wp_cache_get( 'antispam_bee' );
- if ( ! $options ) {
- wp_cache_set(
- 'antispam_bee',
- $options = get_option( 'antispam_bee' )
- );
- }
-
- if ( null === self::$defaults ) {
- self::_init_internal_vars();
- }
-
- return wp_parse_args(
- $options,
- self::$defaults['options']
- );
- }
-
- /**
- * Get single option field
- *
- * @since 0.1
- * @since 2.4.2
- *
- * @param string $field Field name.
- * @return mixed Field value.
- */
- public static function get_option( $field ) {
- $options = self::get_options();
-
- return self::get_key( $options, $field );
- }
-
-
- /**
- * Update single option field
- *
- * @since 0.1
- * @since 2.4
- *
- * @param string $field Field name.
- * @param mixed $value The Field value.
- */
- private static function _update_option( $field, $value ) {
- self::update_options(
- array(
- $field => $value,
- )
- );
- }
-
-
- /**
- * Update multiple option fields
- *
- * @since 0.1
- * @since 2.6.1
- *
- * @param array $data Array with plugin option fields.
- */
- public static function update_options( $data ) {
- $options = get_option( 'antispam_bee' );
-
- if ( is_array( $options ) ) {
- $options = array_merge(
- $options,
- $data
- );
- } else {
- $options = $data;
- }
-
- update_option(
- 'antispam_bee',
- $options
- );
-
- wp_cache_set(
- 'antispam_bee',
- $options
- );
- }
-
-
-
- /*
- * ############################
- * ######## CRONJOBS ########
- * ############################
- */
-
- /**
- * Execution of the daily cronjobs
- *
- * @since 0.1
- * @since 2.4
- */
- public static function start_daily_cronjob() {
- if ( ! self::get_option( 'cronjob_enable' ) ) {
- return;
- }
-
- self::_update_option(
- 'cronjob_timestamp',
- time()
- );
-
- self::_delete_old_spam();
- }
-
-
- /**
- * Delete old spam comments
- *
- * @since 0.1
- * @since 2.4
- */
- private static function _delete_old_spam() {
- $days = (int) self::get_option( 'cronjob_interval' );
-
- if ( empty( $days ) ) {
- return false;
- }
-
- global $wpdb;
-
- $wpdb->query(
- $wpdb->prepare(
- "DELETE c, cm FROM `$wpdb->comments` AS c LEFT JOIN `$wpdb->commentmeta` AS cm ON (c.comment_ID = cm.comment_id) WHERE c.comment_approved = 'spam' AND SUBDATE(NOW(), %d) > c.comment_date_gmt",
- $days
- )
- );
+function antispam_bee_pre_init() {
+ // Load the translation, as they might be needed in pre_init.
+ add_action( 'plugins_loaded', 'antispam_bee_load_textdomain' );
- $wpdb->query( "OPTIMIZE TABLE `$wpdb->comments`" );
- }
-
-
- /**
- * Initialization of the cronjobs
- *
- * @since 0.1
- * @since 2.4
- */
- public static function init_scheduled_hook() {
- if ( ! wp_next_scheduled( 'antispam_bee_daily_cronjob' ) ) {
- wp_schedule_event(
- time(),
- 'daily',
- 'antispam_bee_daily_cronjob'
- );
- }
- }
-
-
- /**
- * Deletion of the cronjobs
- *
- * @since 0.1
- * @since 2.4
- */
- public static function clear_scheduled_hook() {
- if ( wp_next_scheduled( 'antispam_bee_daily_cronjob' ) ) {
- wp_clear_scheduled_hook( 'antispam_bee_daily_cronjob' );
- }
- }
-
-
-
- /*
- * ############################
- * ###### SPAM CHECK ########
- * ############################
- */
-
- /**
- * Check POST values
- *
- * @since 0.1
- * @since 2.6.3
- */
- public static function precheck_incoming_request() {
- // phpcs:disable WordPress.Security.NonceVerification.Missing
- if ( is_feed() || is_trackback() || empty( $_POST ) || self::_is_mobile() ) {
- return;
- }
-
- $request_uri = self::get_key( $_SERVER, 'REQUEST_URI' );
- $request_path = self::parse_url( $request_uri, 'path' );
-
- if ( strpos( $request_path, 'wp-comments-post.php' ) === false ) {
- return;
- }
-
- $post_id = (int) self::get_key( $_POST, 'comment_post_ID' );
- $hidden_field = self::get_key( $_POST, 'comment' );
- $plugin_field = self::get_key( $_POST, self::get_secret_name_for_post( $post_id ) );
-
- if ( ! empty( $hidden_field ) ) {
- $_POST['ab_spam__hidden_field'] = 1;
- } else {
- $_POST['comment'] = $plugin_field;
- unset( $_POST[ self::get_secret_name_for_post( $post_id ) ] );
- }
- // phpcs:enable WordPress.Security.NonceVerification.Missing
- }
-
-
- /**
- * Check incoming requests for spam
- *
- * @since 0.1
- * @since 2.6.3
- * @since 2.10.0 Refactoring of code if pings are allowed and if is ping
- *
- * @param array $comment Untreated comment.
- * @return array $comment Treated comment.
- */
- public static function handle_incoming_request( $comment ) {
- $comment['comment_author_IP'] = self::get_client_ip();
-
- $request_uri = self::get_key( $_SERVER, 'REQUEST_URI' );
- $request_path = self::parse_url( $request_uri, 'path' );
-
- if ( empty( $request_path ) ) {
- return self::_handle_spam_request(
- $comment,
- 'empty'
- );
- }
-
- $pings_allowed = ! self::get_option( 'ignore_pings' );
-
- // phpcs:disable WordPress.Security.NonceVerification.Missing
- // Everybody can post.
- if ( strpos( $request_path, 'wp-comments-post.php' ) !== false && ! empty( $_POST ) ) {
- // phpcs:enable WordPress.Security.NonceVerification.Missing
- $status = self::_verify_comment_request( $comment );
-
- if ( ! empty( $status['reason'] ) ) {
- return self::_handle_spam_request(
- $comment,
- $status['reason']
- );
- }
- } elseif ( self::is_ping( $comment ) && $pings_allowed ) {
- $status = self::_verify_trackback_request( $comment );
-
- if ( ! empty( $status['reason'] ) ) {
- return self::_handle_spam_request(
- $comment,
- $status['reason'],
- true
- );
- }
- }
-
- return $comment;
- }
-
- /**
- * Prepares the replacement of the comment field with output buffering.
- *
- * @since 2.10.0
- */
- public static function prepare_comment_field_output_buffering() {
- if ( is_feed() || is_trackback() || is_robots() || self::_is_mobile() ) {
- return;
- }
-
- ob_start(
- array(
- 'Antispam_Bee',
- 'prepare_comment_field',
- )
- );
- }
-
-
- /**
- * Prepares the replacement of the comment field
- *
- * @since 0.1
- * @since 2.4
- * @since 2.10.0 Changes needed because of new way to add the honeypot field via filter instead of output buffering
- *
- * @param string $data Markup of the comment field or whole page (depending on ob option).
- */
- public static function prepare_comment_field( $data ) {
- if ( empty( $data ) ) {
- return $data;
- }
+ // Check, if the min. required PHP version is available and if not, show an admin notice.
+ if ( version_compare( PHP_VERSION, '7.2', '<' ) ) {
+ add_action( 'admin_notices', 'antispam_bee_min_php_version_error' );
- if ( ! preg_match( '# (?# match the whole textarea tag )
-
';
}
+/**
+ * Show a admin notice error message, if the PHP version is too low
+ */
+function antispam_bee_domdocument_class_error() {
+ echo '';
+ esc_html_e( 'Antispam Bee requires the DOMDocument PHP class. Please install the PHP DOM/XML extension.', 'antispam-bee' );
+ echo '
';
+}
+
/**
* Show a admin notice error message, if the PHP version is too low
*/
From e3e24d42126ad22c8ad2702bbb4bc0f774d4cc40 Mon Sep 17 00:00:00 2001
From: Bernhard Kau
Date: Sat, 2 Apr 2022 14:20:38 +0200
Subject: [PATCH 041/184] replace the anonymous callback function adding the
rule to make it easier to remove it later
---
lib/Rules/InitRule.php | 30 +++++++++++++++++++++---------
1 file changed, 21 insertions(+), 9 deletions(-)
diff --git a/lib/Rules/InitRule.php b/lib/Rules/InitRule.php
index ab37448d..01a76a14 100644
--- a/lib/Rules/InitRule.php
+++ b/lib/Rules/InitRule.php
@@ -3,16 +3,28 @@
namespace AntispamBee\Rules;
trait InitRule {
+
+ /**
+ * Initialize the rule.
+ *
+ * @return void
+ */
public static function init() {
- add_filter(
- 'asb_rules',
- function ( $rules ) {
- $rules[] = [
- 'verifiable' => self::class,
- ];
+ add_filter( 'asb_rules', [ __CLASS__, 'add_rule' ] );
+ }
+
+ /**
+ * Add the current rule class to the 'asb_rules' filter.
+ *
+ * @param array $rules The currently registered rules.
+ *
+ * @return array
+ */
+ public static function add_rule( $rules ) {
+ $rules[] = [
+ 'verifiable' => self::class,
+ ];
- return $rules;
- }
- );
+ return $rules;
}
}
From ea6c7975d981dec4f7d617541dc66befb5aeb84b Mon Sep 17 00:00:00 2001
From: Bernhard Kau
Date: Sat, 2 Apr 2022 18:31:57 +0200
Subject: [PATCH 042/184] PHPCS security fixes
---
lib/Admin/Fields/Checkbox.php | 6 +++++-
lib/Admin/Fields/Field.php | 5 ++++-
lib/Admin/Fields/Text.php | 6 +++++-
lib/Admin/Fields/Textarea.php | 6 +++++-
lib/Admin/Section.php | 7 +++++--
lib/Admin/SettingsPage.php | 7 ++++---
lib/Handlers/Comment.php | 2 +-
lib/Rules/Honeypot.php | 6 ++++--
lib/Rules/LangSpam.php | 1 +
lib/Rules/ShortestTime.php | 2 ++
10 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/lib/Admin/Fields/Checkbox.php b/lib/Admin/Fields/Checkbox.php
index 058822f0..03a088b7 100644
--- a/lib/Admin/Fields/Checkbox.php
+++ b/lib/Admin/Fields/Checkbox.php
@@ -12,7 +12,11 @@ class Checkbox extends Field implements RenderElement {
* Get HTML.
*/
public function render() {
- echo 'get_value(), false ) . ' />';
+ printf(
+ '',
+ esc_attr( $this->get_name() ),
+ checked( 1, $this->get_value(), false )
+ );
$this->maybe_show_description();
}
}
diff --git a/lib/Admin/Fields/Field.php b/lib/Admin/Fields/Field.php
index 7953aa13..f09bf89f 100644
--- a/lib/Admin/Fields/Field.php
+++ b/lib/Admin/Fields/Field.php
@@ -74,7 +74,10 @@ protected function get_value() {
*/
protected function maybe_show_description() {
if ( ! empty( $this->get_description() ) ) {
- echo '' . $this->get_description() . '';
+ printf(
+ '%s',
+ wp_kses_post( $this->get_description() )
+ );
}
}
diff --git a/lib/Admin/Fields/Text.php b/lib/Admin/Fields/Text.php
index a5ffa6a8..c438271a 100644
--- a/lib/Admin/Fields/Text.php
+++ b/lib/Admin/Fields/Text.php
@@ -14,7 +14,11 @@ class Text extends Field implements RenderElement {
* @return string Elment HTML.
*/
public function render() {
- echo '';
+ printf(
+ '',
+ esc_attr( $this->get_name() ),
+ esc_attr( $this->get_value() )
+ );
$this->maybe_show_description();
}
}
diff --git a/lib/Admin/Fields/Textarea.php b/lib/Admin/Fields/Textarea.php
index 646f77e6..04ec01cd 100644
--- a/lib/Admin/Fields/Textarea.php
+++ b/lib/Admin/Fields/Textarea.php
@@ -14,7 +14,11 @@ class Textarea extends Field implements RenderElement {
* @return string Elment HTML.
*/
public function render() {
- echo '';
+ printf(
+ '',
+ esc_attr( $this->get_name() ),
+ esc_html( $this->get_value() )
+ );
$this->maybe_show_description();
}
}
diff --git a/lib/Admin/Section.php b/lib/Admin/Section.php
index 52447e11..efa92ffc 100644
--- a/lib/Admin/Section.php
+++ b/lib/Admin/Section.php
@@ -37,7 +37,7 @@ class Section {
/**
* Initializung Tab.
*
- * @param string $label Title for tab
+ * @param string $label Title for tab
* @param Section[] $sections Sections object array.
*/
public function __construct( $name, $title, $description = '', $fields ) {
@@ -85,7 +85,10 @@ public function get_fields() {
public function get_callback() {
if ( ! empty( $this->description ) ) {
- echo '' . $this->get_description() . '
';
+ printf(
+ '%s
',
+ wp_kses_post( $this->get_description() )
+ );
}
}
}
diff --git a/lib/Admin/SettingsPage.php b/lib/Admin/SettingsPage.php
index 4703bd89..5b998ba7 100644
--- a/lib/Admin/SettingsPage.php
+++ b/lib/Admin/SettingsPage.php
@@ -29,7 +29,8 @@ public function init() {
add_action( 'admin_menu', [ $this, 'add_menu' ] );
add_action( 'admin_init', [ $this, 'setup_settings' ] );
- $this->active_section = isset( $_GET['section'] ) ? $_GET['section'] : 'general';
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+ $this->active_section = isset( $_GET['section'] ) ? sanitize_text_field( wp_unslash( $_GET['section'] ) ) : 'general';
}
/**
@@ -97,9 +98,9 @@ public function options_page() {
diff --git a/lib/Handlers/Comment.php b/lib/Handlers/Comment.php
index 33720088..0a4eec22 100644
--- a/lib/Handlers/Comment.php
+++ b/lib/Handlers/Comment.php
@@ -32,7 +32,7 @@ function () {
public static function process( $comment ) {
$comment['comment_author_IP'] = IpHelper::get_client_ip();
- $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : null;
+ $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : null;
$request_path = DataHelper::parse_url( $request_uri, 'path' );
if ( empty( $request_path ) ) {
diff --git a/lib/Rules/Honeypot.php b/lib/Rules/Honeypot.php
index 9f101c7c..e4a61473 100644
--- a/lib/Rules/Honeypot.php
+++ b/lib/Rules/Honeypot.php
@@ -15,7 +15,8 @@ class Honeypot implements Verifiable, Controllable {
use InitRule;
public static function verify( $data ) {
- if ( isset( $_POST['ab_spam__hidden_field'] ) && $_POST['ab_spam__hidden_field'] == 1 ) {
+ // phpcs:ignore WordPress.Security.NonceVerification.Missing
+ if ( isset( $_POST['ab_spam__hidden_field'] ) && 1 === $_POST['ab_spam__hidden_field'] ) {
return 1;
}
@@ -47,6 +48,7 @@ public static function precheck() {
if ( ! empty( $_POST[ $fields['hidden_field'] ] ) ) {
$_POST['ab_spam__hidden_field'] = 1;
} else {
+ // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
$_POST[ $fields['hidden_field'] ] = $_POST[ $fields['plugin_field'] ];
unset( $_POST[ HoneypotField::get_secret_name_for_post() ] );
}
@@ -58,7 +60,7 @@ public static function get_name() {
}
public static function get_label() {
- return __( '', 'antispam-bee' );
+ return '';
}
public static function get_description() {
diff --git a/lib/Rules/LangSpam.php b/lib/Rules/LangSpam.php
index d4c3104b..7a80c32e 100644
--- a/lib/Rules/LangSpam.php
+++ b/lib/Rules/LangSpam.php
@@ -48,6 +48,7 @@ public static function verify( $data ) {
* Do not translate into your own language.
*/
if ( strpos(
+ // phpcs:ignore WordPress.WP.I18n.MissingArgDomain
_x( 'words', 'Word count type. Do not translate!' ),
'characters'
) === 0 && preg_match(
diff --git a/lib/Rules/ShortestTime.php b/lib/Rules/ShortestTime.php
index 27d7dd06..10c1d40c 100644
--- a/lib/Rules/ShortestTime.php
+++ b/lib/Rules/ShortestTime.php
@@ -23,6 +23,8 @@ public static function verify( $data ) {
return 0;
}
+ // @todo: maybe rename this filter to start with `abs` and add a deprecation message.
+ // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
if ( time() - $init_time < apply_filters( 'ab_action_time_limit', 5 ) ) {
return 1;
}
From a6e477c757cec8cdf634b4b5406562f3201b31aa Mon Sep 17 00:00:00 2001
From: Bernhard Kau
Date: Sat, 2 Apr 2022 18:51:24 +0200
Subject: [PATCH 043/184] use sprintf for honeypot script markup
- remove type attribute as in a44bca14a2ba1f660ccf2b3c9a9a8cc0bc7f0fe4
---
lib/Fields/Honeypot.php | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lib/Fields/Honeypot.php b/lib/Fields/Honeypot.php
index 045fff2d..c0476797 100644
--- a/lib/Fields/Honeypot.php
+++ b/lib/Fields/Honeypot.php
@@ -78,7 +78,12 @@ function ( $matches ) use ( $honeypot_id, $honeypot_name, $attributes_string ) {
if ( ! empty( $matches['id1'] ) || ! empty( $matches['id2'] ) ) {
$output .= 'id="' . self::get_secret_id_for_post() . '" ';
if ( ! self::_is_amp() ) {
- $id_script = '';
+ $id_script = sprintf(
+ '',
+ $honeypot_id,
+ esc_js( substr( md5( time() ), 0, 31 ) ),
+ esc_js( self::get_secret_id_for_post() )
+ );
}
}
From c64aa832cd7763abbb300e6e582918492f99c90a Mon Sep 17 00:00:00 2001
From: Bernhard Kau
Date: Sat, 2 Apr 2022 19:20:08 +0200
Subject: [PATCH 044/184] PHPCS fixing issues in lib/Admin
---
lib/Admin/Fields/Checkbox.php | 5 +++++
lib/Admin/Fields/Field.php | 13 ++++++++----
lib/Admin/Fields/Text.php | 7 +++++--
lib/Admin/Fields/Textarea.php | 7 +++++--
lib/Admin/RenderElement.php | 5 +++++
lib/Admin/Section.php | 18 ++++++++++++++---
lib/Admin/SettingsPage.php | 37 +++++++++++++++++++++++++++++------
lib/Helpers/AssetsLoader.php | 2 +-
8 files changed, 76 insertions(+), 18 deletions(-)
diff --git a/lib/Admin/Fields/Checkbox.php b/lib/Admin/Fields/Checkbox.php
index 03a088b7..07fafec0 100644
--- a/lib/Admin/Fields/Checkbox.php
+++ b/lib/Admin/Fields/Checkbox.php
@@ -1,4 +1,9 @@
name = $name;
$this->title = $title;
$this->fields = $fields;
@@ -83,6 +92,9 @@ public function get_fields() {
return $this->fields;
}
+ /**
+ * Print the UI element.
+ */
public function get_callback() {
if ( ! empty( $this->description ) ) {
printf(
diff --git a/lib/Admin/SettingsPage.php b/lib/Admin/SettingsPage.php
index 5b998ba7..24776a7c 100644
--- a/lib/Admin/SettingsPage.php
+++ b/lib/Admin/SettingsPage.php
@@ -1,4 +1,9 @@
comment_form_field_comment' ) ),
+ new Checkbox(
+ 'ab_dashboard_chart',
+ esc_html__( 'Generate statistics as a dashboard widget', 'antispam-bee' ),
+ esc_html__( 'Daily updates of spam detection rate', 'antispam-bee' )
+ ),
+ new Checkbox(
+ 'ab_dashboard_count',
+ esc_html__( 'Spam counter on the dashboard', 'antispam-bee' ),
+ esc_html__( 'Amount of identified spam comments', 'antispam-bee' )
+ ),
+ new Checkbox(
+ 'ab_ignore_pings',
+ esc_html__( 'Do not check trackbacks / pingbacks', 'antispam-bee' ),
+ esc_html__( 'No spam check for link notifications', 'antispam-bee' )
+ ),
+ new Checkbox(
+ 'ab_use_output_buffer',
+ esc_html__( 'Check complete site markup for comment forms', 'antispam-bee' ),
+ sprintf(
+ /* translators: %s: filter name */
+ esc_html__( 'Uses output buffering instead of the %s filter.', 'antispam-bee' ),
+ 'comment_form_field_comment
'
+ )
+ ),
]
);
$this->sections = apply_filters( 'antispam_bee_sections', $sections );
- // Register option setting
+ // Register option setting.
foreach ( $this->sections as $section ) {
if ( $section->get_name() !== $this->active_section ) {
continue;
diff --git a/lib/Helpers/AssetsLoader.php b/lib/Helpers/AssetsLoader.php
index f67cdbd7..e4801979 100644
--- a/lib/Helpers/AssetsLoader.php
+++ b/lib/Helpers/AssetsLoader.php
@@ -8,7 +8,7 @@
namespace AntispamBee\Helpers;
/**
- * Class AssetsLoader
+ * AssetsLoader helper.
*/
class AssetsLoader {
/**
From 0d3912405131d496fc6d46a0ffeabb2555acb20b Mon Sep 17 00:00:00 2001
From: Bernhard Kau
Date: Sat, 2 Apr 2022 19:35:39 +0200
Subject: [PATCH 045/184] PHPCS fixing issues in lib/Fields
---
lib/Fields/Honeypot.php | 60 ++++++++++++++++++++++++++++-------------
1 file changed, 41 insertions(+), 19 deletions(-)
diff --git a/lib/Fields/Honeypot.php b/lib/Fields/Honeypot.php
index c0476797..335b670a 100644
--- a/lib/Fields/Honeypot.php
+++ b/lib/Fields/Honeypot.php
@@ -1,22 +1,41 @@
query( '//*[@id="' . $options['field_id'] . '"]' )->item( 0 );
if ( ! $input ) {
- return;
+ return '';
}
- $input_type = $input->nodeName;
- $honeypot_id = $input->attributes->getNamedItem( 'id' )->textContent;
- $honeypot_name = $input->attributes->getNamedItem( 'name' )->textContent;
+ // phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
+ $input_type = $input->nodeName;
+ $honeypot_id = $input->attributes->getNamedItem( 'id' )->textContent;
+ $honeypot_name = $input->attributes->getNamedItem( 'name' )->textContent;
+ // phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$attributes_string = sprintf(
'id="%s" name="%s" aria-hidden="true" aria-label="hp-comment" autocomplete="new-password" tabindex="-1" style="padding:0 !important;clip:rect(1px, 1px, 1px, 1px) !important;position:absolute !important;white-space:nowrap !important;height:1px !important;width:1px !important;overflow:hidden !important;"',
$honeypot_id,
@@ -77,7 +98,7 @@ function ( $matches ) use ( $honeypot_id, $honeypot_name, $attributes_string ) {
$id_script = '';
if ( ! empty( $matches['id1'] ) || ! empty( $matches['id2'] ) ) {
$output .= 'id="' . self::get_secret_id_for_post() . '" ';
- if ( ! self::_is_amp() ) {
+ if ( ! self::is_amp() ) {
$id_script = sprintf(
'',
$honeypot_id,
@@ -118,10 +139,8 @@ function ( $matches ) use ( $honeypot_id, $honeypot_name, $attributes_string ) {
/**
* Returns the secret of a post used in the textarea id attribute.
*
- * @param int $post_id The post ID.
- *
* @return string
- * @since 2.10.0 Modify secret generation because `always_allowed` option not longer exists
+ * @since 2.10.0 Modify secret generation because `always_allowed` option no longer exists
*/
public static function get_secret_id_for_post() {
$secret = substr( sha1( md5( 'comment-id' . self::get_salt() ) ), 0, 10 );
@@ -132,10 +151,8 @@ public static function get_secret_id_for_post() {
/**
* Returns the secret of a post used in the textarea name attribute.
*
- * @param int $post_id The Post ID.
- *
* @return string
- * @since 2.10.0 Modify secret generation because `always_allowed` option not longer exists
+ * @since 2.10.0 Modify secret generation because `always_allowed` option no longer exists
*/
public static function get_secret_name_for_post() {
$secret = substr( sha1( md5( 'comment-id' . self::get_salt() ) ), 0, 10 );
@@ -167,10 +184,15 @@ public static function ensure_secret_starts_with_letter( $secret ) {
*
* @return bool
*/
- private static function _is_amp() {
+ private static function is_amp() {
return ( function_exists( 'amp_is_request' ) && amp_is_request() ) || ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() );
}
+ /**
+ * Get the current salt.
+ *
+ * @return string
+ */
private static function get_salt() {
$salt = defined( 'NONCE_SALT' ) ? NONCE_SALT : ABSPATH;
From af4f4ef63e2e06578f505af2fe4050bad537f3c8 Mon Sep 17 00:00:00 2001
From: Angelo Cali
Date: Thu, 7 Apr 2022 08:54:55 +0200
Subject: [PATCH 046/184] extract the honeypot inject to the init method of the
rule
---
lib/Rules/Honeypot.php | 16 ++++++++++++++++
lib/load.php | 7 -------
2 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/lib/Rules/Honeypot.php b/lib/Rules/Honeypot.php
index e4a61473..aca65df5 100644
--- a/lib/Rules/Honeypot.php
+++ b/lib/Rules/Honeypot.php
@@ -14,6 +14,22 @@ class Honeypot implements Verifiable, Controllable {
use IsActive;
use InitRule;
+ /**
+ * Initialize the rule.
+ *
+ * @return void
+ */
+ public static function init() {
+ add_filter( 'asb_rules', [ __CLASS__, 'add_rule' ] );
+
+ add_filter(
+ 'comment_form_field_comment',
+ function ( $field_markup ) {
+ return HoneypotField::inject( $field_markup, [ 'field_id' => 'comment' ] );
+ }
+ );
+ }
+
public static function verify( $data ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( isset( $_POST['ab_spam__hidden_field'] ) && 1 === $_POST['ab_spam__hidden_field'] ) {
diff --git a/lib/load.php b/lib/load.php
index dffcd746..180550c4 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -74,13 +74,6 @@ function init() {
call_user_func( [ $module, 'init' ] );
}
}
-
- add_filter(
- 'comment_form_field_comment',
- function ( $field_markup ) {
- return HoneypotField::inject( $field_markup, [ 'field_id' => 'comment' ] );
- }
- );
}
add_action( 'plugins_loaded', 'AntispamBee\init' );
From 8532369ae5ddf1f11b492a5db595d84ca64becb3 Mon Sep 17 00:00:00 2001
From: Angelo Cali
Date: Thu, 7 Apr 2022 16:20:47 +0200
Subject: [PATCH 047/184] Work on settings
---
lib/Admin/Fields/Checkbox.php | 7 ++-
lib/Admin/Fields/Field.php | 34 +++++------
lib/Admin/Fields/Select.php | 7 ---
lib/Admin/Fields/Text.php | 11 ++--
lib/Admin/Fields/Textarea.php | 3 +-
lib/Admin/Section.php | 71 +++++++++++++++-------
lib/Admin/SettingsPage.php | 84 +++++++++++++++++++-------
lib/Handlers/PostProcessors.php | 5 ++
lib/Handlers/Rules.php | 28 +++++----
lib/Helpers/CommentsColumns.php | 4 +-
lib/Helpers/InterfaceHelper.php | 7 ++-
lib/Helpers/ItemTypeHelper.php | 1 +
lib/Helpers/Settings.php | 102 ++++++++++----------------------
lib/Rules/BBCode.php | 33 +----------
lib/Rules/CountrySpam.php | 8 +--
lib/Rules/Honeypot.php | 4 +-
lib/Rules/LangSpam.php | 4 +-
lib/Rules/RegexpSpam.php | 4 +-
lib/Rules/ValidGravatar.php | 6 +-
lib/load.php | 41 +++++++++++++
20 files changed, 253 insertions(+), 211 deletions(-)
diff --git a/lib/Admin/Fields/Checkbox.php b/lib/Admin/Fields/Checkbox.php
index 07fafec0..e9de1de8 100644
--- a/lib/Admin/Fields/Checkbox.php
+++ b/lib/Admin/Fields/Checkbox.php
@@ -18,9 +18,12 @@ class Checkbox extends Field implements RenderElement {
*/
public function render() {
printf(
- '',
+ '',
esc_attr( $this->get_name() ),
- checked( 1, $this->get_value(), false )
+ checked( 'on', $this->get_value(), false ),
+ esc_html( $this->get_label() )
);
$this->maybe_show_description();
}
diff --git a/lib/Admin/Fields/Field.php b/lib/Admin/Fields/Field.php
index f69eeb54..bf6dbc44 100644
--- a/lib/Admin/Fields/Field.php
+++ b/lib/Admin/Fields/Field.php
@@ -7,35 +7,35 @@
namespace AntispamBee\Admin\Fields;
+use AntispamBee\Helpers\Settings;
+
/**
* Abstract class for field.
*/
abstract class Field {
/**
- * Field Name.
+ * Item type.
*
* @var string
*/
- private $name;
+ protected $type;
/**
- * Field Description.
+ * Field options.
*
- * @var string
+ * @var array
*/
- private $description;
+ protected $option;
/**
* Initializing field
*
- * @param string $name Name of the field.
- * @param string $label Label of the field.
- * @param string $description Description of the field.
+ * @param string $type Item type.
+ * @param array $option Field options.
*/
- public function __construct( $name, $label, $description = '' ) {
- $this->name = $name;
- $this->label = $label;
- $this->description = $description;
+ public function __construct( $type, $option ) {
+ $this->type = $type;
+ $this->option = $option;
}
/**
@@ -44,7 +44,7 @@ public function __construct( $name, $label, $description = '' ) {
* @return string Name of the field.
*/
public function get_name() {
- return $this->name;
+ return str_replace( '-', '_', 'antispam_bee[' . $this->type . '][' . $this->option['option_name'] . ']' );
}
/**
@@ -53,7 +53,7 @@ public function get_name() {
* @return string Label of the field.
*/
public function get_label() {
- return $this->label;
+ return isset( $this->option['label'] ) ? $this->option['label'] : '';
}
/**
@@ -62,7 +62,7 @@ public function get_label() {
* @return string Description of the field.
*/
public function get_description() {
- return $this->description;
+ return isset( $this->option['description'] ) ? $this->option['description'] : '';
}
/**
@@ -71,7 +71,7 @@ public function get_description() {
* @return mixed Value stored in database.
*/
protected function get_value() {
- return get_option( $this->name );
+ return Settings::get_option( $this->option['option_name'], $this->type );
}
/**
@@ -80,7 +80,7 @@ protected function get_value() {
protected function maybe_show_description() {
if ( ! empty( $this->get_description() ) ) {
printf(
- '%s',
+ '%s
',
wp_kses_post( $this->get_description() )
);
}
diff --git a/lib/Admin/Fields/Select.php b/lib/Admin/Fields/Select.php
index 16f5b88a..c240eda2 100644
--- a/lib/Admin/Fields/Select.php
+++ b/lib/Admin/Fields/Select.php
@@ -13,13 +13,6 @@ class Select extends Field implements RenderElement {
protected $multiple;
- public function __construct( $name, $label, $description = '', $options = [], $multiple = false ) {
- parent::__construct( $name, $label, $description );
-
- $this->options = $options;
- $this->multiple = $multiple;
- }
-
/**
* Get HTML.
*
diff --git a/lib/Admin/Fields/Text.php b/lib/Admin/Fields/Text.php
index 4c863f71..5544022a 100644
--- a/lib/Admin/Fields/Text.php
+++ b/lib/Admin/Fields/Text.php
@@ -16,10 +16,8 @@ class Text extends Field implements RenderElement {
protected $placeholder;
- public function __construct( $name, $label, $description = '', $placeholder = '' ) {
- parent::__construct( $name, $label, $description );
-
- $this->placeholder = $placeholder;
+ public function get_placeholder() {
+ return $this->placeholder;
}
/**
@@ -27,10 +25,11 @@ public function __construct( $name, $label, $description = '', $placeholder = ''
*/
public function render() {
printf(
- '',
+ '',
esc_attr( $this->get_name() ),
+ esc_html( $this->get_label() ),
esc_attr( $this->get_value() ),
- esc_attr( $this->placeholder )
+ esc_attr( $this->get_placeholder() )
);
$this->maybe_show_description();
}
diff --git a/lib/Admin/Fields/Textarea.php b/lib/Admin/Fields/Textarea.php
index 6a50e396..8d994b8d 100644
--- a/lib/Admin/Fields/Textarea.php
+++ b/lib/Admin/Fields/Textarea.php
@@ -18,8 +18,9 @@ class Textarea extends Field implements RenderElement {
*/
public function render() {
printf(
- '',
+ '',
esc_attr( $this->get_name() ),
+ esc_html( $this->get_label() ),
esc_html( $this->get_value() )
);
$this->maybe_show_description();
diff --git a/lib/Admin/Section.php b/lib/Admin/Section.php
index a3874db9..e5081109 100644
--- a/lib/Admin/Section.php
+++ b/lib/Admin/Section.php
@@ -7,6 +7,7 @@
namespace AntispamBee\Admin;
+use AntispamBee\Admin\Fields\Checkbox;
use AntispamBee\Admin\Fields\Select;
use AntispamBee\Admin\Fields\Text;
use AntispamBee\Admin\Fields\Textarea;
@@ -41,10 +42,15 @@ class Section {
/**
* Fields.
*
- * @var Field[]
+ * @var array
*/
- private $fields = [];
+ private $rows = [];
+ /**
+ * Item type.
+ *
+ * @var string
+ */
private $type;
/**
@@ -62,8 +68,12 @@ public function __construct( $name, $title, $description = '', $type = null ) {
$this->type = $type;
}
- public function add_fields( $fields ) {
- $this->fields = array_merge( $this->fields, $fields );
+
+
+ public function add_rows( $rows ) {
+ foreach ( $rows as $row ) {
+ $this->rows[] = $row;
+ }
}
public function add_controllables( $controllables ) {
@@ -71,33 +81,46 @@ public function add_controllables( $controllables ) {
}
private function generate_fields( $controllables ) {
- $fields = [];
+ // Todo: DRY - Don’t run for other types than displayed
foreach ( $controllables as $controllable ) {
- // Todo: Generate checkbox to activate/deactivate rule
+ $slug = InterfaceHelper::call( $controllable, 'controllable', 'get_slug' );
+ $label = InterfaceHelper::call( $controllable, 'controllable', 'get_label' );
+ $description = InterfaceHelper::call( $controllable, 'controllable', 'get_description' );
+ $fields = [];
+ $fields[] = $this->generate_field( [
+ 'type' => 'checkbox',
+ 'option_name' => $slug . '_active',
+ 'label' => $label,
+ 'description' => $description
+ ] );
$options = InterfaceHelper::call( $controllable, 'controllable', 'get_options' );
- if ( empty( $options ) ) {
- continue;
+ if ( ! empty( $options ) ) {
+ foreach ( $options as $option ) {
+ $fields[] = $this->generate_field( $option );
+ }
}
- foreach ( $options as $option ) {
- $fields[] = $this->generate_field( $option );
- }
+ $this->rows[] = [
+ 'label' => InterfaceHelper::call( $controllable, 'controllable', 'get_name' ),
+ 'fields' => $fields
+ ];
}
-
- $this->fields = array_merge( $this->fields, $fields );
}
private function generate_field( $option ) {
+ $description = isset( $option['description'] ) ? $option['description'] : '';
+ // Todo: Find a more descriptive name for option_name
+ $name = 'antispam_bee[' . $this->type . '][' . $option['option_name'] . ']';
switch ( $option['type'] ) {
case 'input':
- return new Text( $this->type . '_' . $option['option_name'], $option['label'], '' );
+ return new Text( $this->type, $option );
case 'select':
- return new Select( $this->type . '_' . $option['option_name'], $option['label'],
- 'Hold CTRL to select multiple entries', $option['options'], false );
+ return new Select( $this->type, $option );
case 'textarea':
- return new Textarea( $this->type . '_' . $option['option_name'], $option['label'],
- $option['label'] );
+ return new Textarea( $this->type, $option );
+ case 'checkbox':
+ return new Checkbox( $this->type, $option );
}
}
@@ -133,8 +156,8 @@ public function get_description() {
*
* @return Field[]
*/
- public function get_fields() {
- return $this->fields;
+ public function get_rows() {
+ return $this->rows;
}
/**
@@ -148,4 +171,12 @@ public function get_callback() {
);
}
}
+
+ /**
+ * Section
+ * Field Lists/Rows array
+ * Left-side Label string
+ * Fields array
+ * Field
+ */
}
diff --git a/lib/Admin/SettingsPage.php b/lib/Admin/SettingsPage.php
index 736a10ab..53a1eda5 100644
--- a/lib/Admin/SettingsPage.php
+++ b/lib/Admin/SettingsPage.php
@@ -15,6 +15,7 @@
use AntispamBee\Handlers\Trackback;
use AntispamBee\Helpers\InterfaceHelper;
use AntispamBee\Helpers\ItemTypeHelper;
+use AntispamBee\Helpers\Settings;
use AntispamBee\Interfaces\Controllable;
use AntispamBee\Interfaces\Verifiable;
@@ -30,18 +31,18 @@ class SettingsPage {
private $active_tab = [];
/**
- * Active section
+ * Tabs
*
- * @var string
+ * @var Tab[]
*/
- private $active_section = [];
+ private $tabs = [];
/**
- * Tabs
+ * The slug used for the Settings page
*
- * @var Tab[]
+ * @var string
*/
- private $tabs = [];
+ const SETTINGS_PAGE_SLUG = 'antispam_bee';
/**
* Add Hooks.
@@ -62,7 +63,7 @@ public function add_menu() {
__( 'Antispam Bee', 'antispam-bee' ),
__( 'Antispam Bee', 'antispam-bee' ),
'manage_options',
- 'antispam_bee',
+ self::SETTINGS_PAGE_SLUG,
[ $this, 'options_page' ]
);
}
@@ -71,16 +72,45 @@ public function add_menu() {
* Setup tabs content.
*/
public function setup_settings() {
+ // Todo: Extract parts of the method in new methods.
$general_section = new Section(
'general',
__( 'General', 'antispam-bee' ),
__( 'Setup global plugin spam settings.', 'antispam-bee' ) );
- $general_section->add_fields( [
- new Checkbox( 'ab_dashboard_chart', esc_html( 'Generate statistics as a dashboard widget', 'antispam-bee' ), esc_html( 'Daily updates of spam detection rate', 'antispam-bee' ) ),
- new Checkbox( 'ab_dashboard_count', esc_html( 'Spam counter on the dashboard', 'antispam-bee' ), esc_html( 'Amount of identified spam comments', 'antispam-bee' ) ),
- new Checkbox( 'ab_ignore_pings', esc_html( 'Do not check trackbacks / pingbacks', 'antispam-bee' ), esc_html( 'No spam check for link notifications', 'antispam-bee' ) ),
- new Checkbox( 'ab_use_output_buffer', esc_html( 'Check complete site markup for comment forms', 'antispam-bee' ), sprintf( /* translators: s=filter name */ esc_html( 'Uses output buffering instead of the %s filter.', 'antispam-bee' ), 'comment_form_field_comment
' ) ),
+
+ $general_section->add_rows( [
+ [
+ 'label' => __( 'Statistics', 'antispam-bee' ),
+ 'fields' => [
+ new Checkbox( 'general', [
+ 'option_name' => 'ab_dashboard_chart',
+ 'label' => esc_html( 'Generate statistics as a dashboard widget', 'antispam-bee' ),
+ 'description' => esc_html( 'Daily updates of spam detection rate', 'antispam-bee' ),
+ ] ),
+ new Checkbox( 'general', [
+ 'option_name' => 'ab_dashboard_count',
+ 'label' => esc_html( 'Spam counter on the dashboard', 'antispam-bee' ),
+ 'description' => esc_html( 'Amount of identified spam comments', 'antispam-bee' )
+ ] ),
+ ]
+ ],
+ [
+ 'label' => __( 'Pings', 'antispam-bee' ),
+ 'fields' => [
+ new Checkbox( 'general', [
+ 'option_name' => 'ab_ignore_pings',
+ 'label' => esc_html( 'Do not check trackbacks / pingbacks', 'antispam-bee' ),
+ 'description' => esc_html( 'No spam check for link notifications', 'antispam-bee' ),
+ ] ),
+ ]
+ ]
] );
+
+ // Todo: Add a way to build rows and fields with a fluent interface?
+ // Todo: Fix the weird naming
+ // Todo: Discuss if we want to remove that setting in V3 and maybe have a filter for that.
+ // If we keep it, we have to add it to the comments tab.
+ // new Checkbox( 'ab_use_output_buffer', esc_html( 'Check complete site markup for comment forms', 'antispam-bee' ), sprintf( /* translators: s=filter name */ esc_html( 'Uses output buffering instead of the %s filter.', 'antispam-bee' ), 'comment_form_field_comment
' ) ),
$general_tab = new Tab(
'general',
__( 'General','antispam-bee' ),
@@ -112,7 +142,7 @@ public function setup_settings() {
'type' => $type,
] ) );
$tabs[$type] = new Tab(
- $type . '_tab',
+ $type,
ItemTypeHelper::get_type_name( $type ),
[
'rules' => $section
@@ -128,18 +158,28 @@ public function setup_settings() {
continue;
}
- add_settings_section( $section->get_name(), $section->get_title(), [ $section, 'get_callback' ], 'antispam_bee' );
+ add_settings_section( $section->get_name(), $section->get_title(), [ $section, 'get_callback' ], self::SETTINGS_PAGE_SLUG );
- foreach ( $section->get_fields() as $field ) {
+ foreach ( $section->get_rows() as $row ) {
add_settings_field(
- $field->get_name(),
- $field->get_label(),
- [ $field, 'render' ],
- 'antispam_bee',
+ sanitize_title( $row['label'] ),
+ $row['label'],
+ function() use ( $row ) {
+ $last_field = false;
+ foreach ( $row['fields'] as $key => $field ) {
+ $field->render( $last_field );
+ if ( $key !== count( $row['fields'] ) - 1 ) {
+ echo '
';
+ }
+ }
+ },
+ self::SETTINGS_PAGE_SLUG,
$section->get_name()
);
- register_setting( 'antispam_bee', $field->get_name() );
+ register_setting( self::SETTINGS_PAGE_SLUG, Settings::ANTISPAM_BEE_OPTION_NAME, [
+ 'sanitize_callback' => [ Settings::class, 'sanitize' ],
+ ] );
}
}
}
@@ -166,8 +206,8 @@ public function options_page() {
diff --git a/lib/Handlers/PostProcessors.php b/lib/Handlers/PostProcessors.php
index 9e8fea21..6ec35a00 100644
--- a/lib/Handlers/PostProcessors.php
+++ b/lib/Handlers/PostProcessors.php
@@ -29,6 +29,9 @@ public static function apply( $type, $item, $reasons = [] ) {
}
public static function get( $type = null, $only_active = false ) {
+ // Todo: Fix: The name mustn't break the options page, we should sort out everything that can break the plugin.
+ // Todo: Check if other things can break it too
+
$all_post_processors = apply_filters( 'asb_post_processors', [] );
$post_processors = [];
foreach ( $all_post_processors as $key => $post_processor ) {
@@ -74,4 +77,6 @@ private static function is_valid_post_processor( $post_processor ) {
return InterfaceHelper::array_has_callables( $post_processor, $post_processor_callables );
}
+
+ // Todo: Add a filter method like in Rules
}
diff --git a/lib/Handlers/Rules.php b/lib/Handlers/Rules.php
index 5e500b4c..32f94ad1 100644
--- a/lib/Handlers/Rules.php
+++ b/lib/Handlers/Rules.php
@@ -23,15 +23,13 @@ public function apply( $item ) {
$score = 0.0;
foreach ( $rules as $rule ) {
- $verify_function = isset( $rule['verifiable'] ) ? [ $rule['verifiable'], 'verify' ] : $rule['verify'];
- $get_weight_function = isset( $rule['verifiable'] ) ? [ $rule['verifiable'], 'get_weight' ] : $rule['get_weight'];
- $get_slug_function = isset( $rule['verifiable'] ) ? [ $rule['verifiable'], 'get_slug' ] : $rule['get_slug'];
+ $rule_score = InterfaceHelper::call( $rule, 'verifiable', 'verify', $item )
+ * InterfaceHelper::call( $rule, 'verifiable', 'get_weight' );
- $rule_score = call_user_func( $verify_function, $item ) * call_user_func( $get_weight_function );
if ( $rule_score > 0.0 ) {
- $this->spam_reasons[] = call_user_func( $get_slug_function );
+ $this->spam_reasons[] = InterfaceHelper::call( $rule, 'verifiable', 'get_slug' );
} else {
- $this->no_spam_reasons[] = call_user_func( $get_slug_function );
+ $this->no_spam_reasons[] = InterfaceHelper::call( $rule, 'verifiable', 'get_slug' );
}
$score += $rule_score;
@@ -82,9 +80,13 @@ public function get_no_spam_reasons() {
* );
*/
public static function filter( $rules, $options ) {
+ // Todo: Fix: The name mustn't break the options page, we should sort out everything that can break the plugin.
+ // Todo: Check if other things can break it too
+
$type = isset( $options['type'] ) ? $options['type'] : null;
$only_active = isset( $options['only_active'] ) ? $options['only_active'] : false;
- $is_controllable = isset( $options['is_controllable'] ) ? $options['is_controllable'] : false;
+ // Todo: Change the key from is_controllable to only_controllables
+ $only_controllables = isset( $options['is_controllable'] ) ? $options['is_controllable'] : false;
$filtered_rules = [];
foreach ( $rules as $rule ) {
@@ -94,15 +96,15 @@ public static function filter( $rules, $options ) {
continue;
}
- if ( $is_controllable ) {
- if ( ! isset( $rule['controllable'] )
- || ! InterfaceHelper::conforms_to_interface( $rule['controllable'], Controllable::class ) ) {
- continue;
- }
+
+ $conforms_to_controllable = isset( $rule['controllable'] ) ?
+ InterfaceHelper::conforms_to_interface( $rule['controllable'], Controllable::class ) : false;
+ if ( $only_controllables && ! $conforms_to_controllable ) {
+ continue;
}
if ( $only_active ) {
- if ( ! InterfaceHelper::call( $rule, 'verifiable', 'is_active', $type ) ) {
+ if ( $conforms_to_controllable && ! InterfaceHelper::call( $rule, 'verifiable', 'is_active', $type ) ) {
continue;
}
}
diff --git a/lib/Helpers/CommentsColumns.php b/lib/Helpers/CommentsColumns.php
index fad027bd..6dbd22ce 100644
--- a/lib/Helpers/CommentsColumns.php
+++ b/lib/Helpers/CommentsColumns.php
@@ -64,11 +64,11 @@ public static function print_plugin_column( $column, $comment_id ) {
$spam_reason = get_comment_meta( $comment_id, $column, true );
$spam_reasons = Settings::get_options( 'reasons' );
- if ( empty( $spam_reason ) || empty( $spam_reasons[ $spam_reason ] ) ) {
+ if ( empty( $spam_reason ) ) {
return;
}
- echo esc_html( $spam_reasons[ $spam_reason ] );
+ echo esc_html( $spam_reason );
}
/**
diff --git a/lib/Helpers/InterfaceHelper.php b/lib/Helpers/InterfaceHelper.php
index ed7fb9c6..28ff6aa4 100644
--- a/lib/Helpers/InterfaceHelper.php
+++ b/lib/Helpers/InterfaceHelper.php
@@ -5,9 +5,10 @@
class InterfaceHelper {
// Todo: adapt method because the methods have to be stored under the verifiable key
- public static function call( $array, $interface, $method, ...$args ) {
- if ( isset( $array[ $method ] ) && is_callable( $array[ $method ] ) ) {
- return call_user_func( $array[ $method ], $args );
+ public static function call( $array, $interface, $method, $args = [] ) {
+ $callable = isset( $array[ $interface ][ $method ] ) ? $array[ $interface ][ $method ] : null;
+ if ( is_callable( $callable ) ) {
+ return call_user_func( $callable, $args );
}
if ( isset( $array[ $interface ] ) && is_callable( array( $array[ $interface ], $method ) ) ) {
diff --git a/lib/Helpers/ItemTypeHelper.php b/lib/Helpers/ItemTypeHelper.php
index d7517305..6bb4d648 100644
--- a/lib/Helpers/ItemTypeHelper.php
+++ b/lib/Helpers/ItemTypeHelper.php
@@ -15,6 +15,7 @@ public static function get_type_name( $item_type ) {
self::PINGBACK_TYPE => __( 'Pingback', 'antispam-bee' ),
];
+ // Todo: Write a doc how to add custom types.
$type_names = array_merge( apply_filters( 'asb_item_types', [] ), $type_names );
return isset( $type_names[ $item_type ] ) ? $type_names[ $item_type ] : $item_type;
}
diff --git a/lib/Helpers/Settings.php b/lib/Helpers/Settings.php
index b71eb059..0539bb84 100644
--- a/lib/Helpers/Settings.php
+++ b/lib/Helpers/Settings.php
@@ -2,68 +2,12 @@
namespace AntispamBee\Helpers;
-use AntispamBee\Interfaces\Controllable;
-
class Settings {
protected static $defaults;
- public static function init() {
- self::init_options();
- }
+ const ANTISPAM_BEE_OPTION_NAME = 'antispam_bee';
- protected static function init_options() {
- $defaults = [
- 'options' => [
- 'regexp_check' => 1,
- 'spam_ip' => 1,
- 'already_commented' => 1,
- 'gravatar_check' => 0,
- 'time_check' => 0,
- 'ignore_pings' => 0,
-
- 'dashboard_chart' => 0,
- 'dashboard_count' => 0,
-
- 'country_code' => 0,
- 'country_denied' => '',
- 'country_allowed' => '',
-
- 'translate_api' => 0,
- 'translate_lang' => [],
-
- 'bbcode_check' => 1,
-
- 'flag_spam' => 1,
- 'email_notify' => 0,
- 'no_notice' => 0,
- 'cronjob_enable' => 0,
- 'cronjob_interval' => 0,
-
- 'ignore_filter' => 0,
- 'ignore_type' => 0,
-
- 'reasons_enable' => 0,
- 'ignore_reasons' => [],
-
- 'delete_data_on_uninstall' => 1,
- ],
- 'reasons' => [
- 'css' => esc_attr__( 'Honeypot', 'antispam-bee' ),
- 'time' => esc_attr__( 'Comment time', 'antispam-bee' ),
- 'empty' => esc_attr__( 'Empty Data', 'antispam-bee' ),
- 'localdb' => esc_attr__( 'Local DB Spam', 'antispam-bee' ),
- 'server' => esc_attr__( 'Fake IP', 'antispam-bee' ),
- 'country' => esc_attr__( 'Country Check', 'antispam-bee' ),
- 'bbcode' => esc_attr__( 'BBCode', 'antispam-bee' ),
- 'lang' => esc_attr__( 'Comment Language', 'antispam-bee' ),
- 'regexp' => esc_attr__( 'Regular Expression', 'antispam-bee' ),
- 'title_is_name' => esc_attr__( 'Identical Post title and blog title', 'antispam-bee' ),
- 'manually' => esc_attr__( 'Manually', 'antispam-bee' ),
- ],
- ];
-
- self::$defaults = apply_filters( 'asb_default_options', $defaults );
- }
+ public static function init() {}
/**
* Get all plugin options
@@ -79,29 +23,23 @@ public static function get_options() {
);
}
- if ( null === self::$defaults ) {
- self::init_options();
- }
-
- return wp_parse_args(
- $options,
- self::$defaults['options']
- );
+ return $options;
}
/**
* Get single option field
*
- * @param string $field Field name.
+ * @param string $option_name Option name.
+ * @param string $type The type.
*
- * @return mixed Field value.
- * @since 0.1
- * @since 2.4.2
+ * @return mixed Field value.
*/
- public static function get_option( $field ) {
+ public static function get_option( $option_name, $type = 'general' ) {
$options = self::get_options();
- return self::get_key( $options, $field );
+ $type = str_replace( '-', '_', $type );
+ $option_name = str_replace( '-', '_', $option_name );
+ return isset( $options[ $type ][ $option_name ] ) ? $options[ $type ][ $option_name ] : null;
}
/**
@@ -164,4 +102,24 @@ public static function get_key( $array, $key ) {
return $array[ $key ];
}
+
+ public static function sanitize( $options ) {
+ $current_options = self::get_options();
+
+ // Todo: Call the sanitize functions for the rules/post processors/settings
+
+ if ( ! isset( $_GET['tab'] ) || empty ( $_GET['tab'] ) ) {
+ return $current_options;
+ }
+
+ $tab = $_GET['tab'];
+ $options = ! empty( $options ) ? $options : [ $tab => [] ];
+ $current_options[ $tab ] = $options[ $tab ];
+
+ echo '';
+ var_dump( $options, $current_options );
+ echo '
';
+
+ return $current_options;
+ }
}
diff --git a/lib/Rules/BBCode.php b/lib/Rules/BBCode.php
index b3dc9232..fda0aa13 100644
--- a/lib/Rules/BBCode.php
+++ b/lib/Rules/BBCode.php
@@ -30,7 +30,7 @@ public static function get_label() {
}
public static function get_description() {
- __( 'Review the comment contents for BBCode links', 'antispam-bee' );
+ return __( 'Review the comment contents for BBCode links', 'antispam-bee' );
}
public static function get_weight() {
@@ -46,36 +46,7 @@ public static function is_final() {
}
public static function get_options() {
- return [
- [
- 'type' => 'input',
- 'input_type' => 'email|password|number...',
- 'label' => __( 'BBCodes to allow', 'antispam-bee' ),
- 'option_name' => 'asb_deny_langcodes',
- 'options' => [ 'Option A', 'Option B' ],
- 'multiple' => true,
- 'placeholder' => 'My placeholder text',
- 'default' => 'Default value'
- ],
- [
- 'type' => 'select',
- 'label' => __( 'BBCodes to allow', 'antispam-bee' ),
- 'option_name' => 'asb_deny_langcodes',
- 'options' => [
- [
- 'value' => 1,
- 'label' => 'Option A'
- ],
- [
- 'value' => 2,
- 'label' => 'Option B'
- ],
- ],
- 'multiple' => false,
- 'placeholder' => 'My placeholder text',
- 'default' => 'Default value'
- ]
- ];
+ return null;
}
public static function get_supported_types() {
diff --git a/lib/Rules/CountrySpam.php b/lib/Rules/CountrySpam.php
index dd8d87d4..6cfd3aaf 100644
--- a/lib/Rules/CountrySpam.php
+++ b/lib/Rules/CountrySpam.php
@@ -3,6 +3,7 @@
namespace AntispamBee\Rules;
use AntispamBee\Helpers\ItemTypeHelper;
+use AntispamBee\Helpers\Settings;
use AntispamBee\Interfaces\Controllable;
use AntispamBee\Interfaces\Verifiable;
@@ -17,7 +18,7 @@ public static function verify( $data ) {
}
$ip = $data['comment_author_IP'];
- $options = self::get_options();
+ $options = Settings::get_options();
$allowed = preg_split(
'/[\s,;]+/',
@@ -178,13 +179,8 @@ public static function get_supported_types() {
return [ ItemTypeHelper::COMMENT_TYPE, ItemTypeHelper::TRACKBACK_TYPE ];
}
- public static function is_active( $type ) {
- return true;
- }
-
private static function sanitize_input( $value ) {
return false;
}
-
}
diff --git a/lib/Rules/Honeypot.php b/lib/Rules/Honeypot.php
index aca65df5..1bed6ab6 100644
--- a/lib/Rules/Honeypot.php
+++ b/lib/Rules/Honeypot.php
@@ -72,11 +72,11 @@ public static function precheck() {
}
public static function get_name() {
- return __( 'Approved Email', 'antispam-bee' );
+ return __( 'Honeypot', 'antispam-bee' );
}
public static function get_label() {
- return '';
+ return __( 'Inject hidden field', 'antispam-bee' );
}
public static function get_description() {
diff --git a/lib/Rules/LangSpam.php b/lib/Rules/LangSpam.php
index 7a80c32e..d4296332 100644
--- a/lib/Rules/LangSpam.php
+++ b/lib/Rules/LangSpam.php
@@ -108,7 +108,7 @@ public static function is_final() {
}
public static function get_label() {
- __( 'Allow comments only in certain language', 'antispam-bee' );
+ return __( 'Allow comments only in certain language', 'antispam-bee' );
}
public static function get_description() {
@@ -120,7 +120,7 @@ public static function get_description() {
)
);
- printf(
+ return sprintf(
/* translators: 1: opening tag with link to documentation. 2: closing tag. */
esc_html__( 'Detect and approve only the specified language. Please note the %1$sprivacy notice%2$s for this option.', 'antispam-bee' ),
wp_kses_post( $link1 ),
diff --git a/lib/Rules/RegexpSpam.php b/lib/Rules/RegexpSpam.php
index 06e081c1..ec1ed49e 100644
--- a/lib/Rules/RegexpSpam.php
+++ b/lib/Rules/RegexpSpam.php
@@ -179,11 +179,11 @@ public static function get_supported_types() {
}
public static function get_label() {
- __( 'Use regular expressions', 'antispam-bee' );
+ return __( 'Use regular expressions', 'antispam-bee' );
}
public static function get_description() {
- __( 'Predefined and custom patterns by plugin hook', 'antispam-bee' );
+ return __( 'Predefined and custom patterns by plugin hook', 'antispam-bee' );
}
public static function get_options() {
diff --git a/lib/Rules/ValidGravatar.php b/lib/Rules/ValidGravatar.php
index 9cdca833..dd7ca957 100644
--- a/lib/Rules/ValidGravatar.php
+++ b/lib/Rules/ValidGravatar.php
@@ -35,7 +35,7 @@ public static function verify( $data ) {
}
public static function get_name() {
- return '';
+ return __( 'Valid Gravatar', 'antispam-bee' );
}
public static function get_weight() {
@@ -51,7 +51,7 @@ public static function is_final() {
}
public static function get_label() {
- __( 'Trust commenters with a Gravatar', 'antispam-bee' );
+ return __( 'Trust commenters with a Gravatar', 'antispam-bee' );
}
public static function get_description() {
@@ -62,7 +62,7 @@ public static function get_description() {
'https'
)
);
- printf(
+ return sprintf(
/* translators: 1: opening tag with link to documentation. 2: closing tag */
esc_html__( 'Check if commenter has a Gravatar image. Please note the %1$sprivacy notice%2$s for this option.', 'antispam-bee' ),
wp_kses_post( $link1 ),
diff --git a/lib/load.php b/lib/load.php
index 180550c4..a2565f86 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -14,8 +14,12 @@
use AntispamBee\Handlers\Trackback;
use AntispamBee\Helpers\AssetsLoader;
use AntispamBee\Helpers\CommentsColumns;
+use AntispamBee\Helpers\DataHelper;
use AntispamBee\Helpers\Installer;
+use AntispamBee\Helpers\InterfaceHelper;
+use AntispamBee\Helpers\ItemTypeHelper;
use AntispamBee\Helpers\Settings;
+use AntispamBee\Interfaces\Controllable;
use AntispamBee\PostProcessors\Delete;
use AntispamBee\PostProcessors\DeleteForReasons;
use AntispamBee\PostProcessors\SaveReason;
@@ -74,6 +78,43 @@ function init() {
call_user_func( [ $module, 'init' ] );
}
}
+
+ // Todo: Allow to give values instead of callables. Test for return types.
+ // Todo: Write a doc how to implement a custom rule and postprocessor.
+ add_filter( 'asb_rules', function( $rules ) {
+ $rule = [];
+ $rule['verifiable']['verify'] = function() {
+ return 1;
+ };
+ $rule['verifiable']['get_name'] = function() {
+ return "Imaginary Rule";
+ };
+ $rule['verifiable']['get_weight'] = function() {
+ return 1000.0;
+ };
+ $rule['verifiable']['get_slug'] = function() {
+ return 'imaginary_rule';
+ };
+ $rule['verifiable']['get_supported_types'] = function() {
+ return [ 'comment', 'webmention' ];
+ };
+ $rule['verifiable']['is_final'] = function() {
+ return true;
+ };
+
+ $rule['controllable']['get_label'] = function() {
+ return 'Imaginary Rule';
+ };
+ $rule['controllable']['get_description'] = function() {
+ return 'Description for our Imaginary Rule';
+ };
+ $rule['controllable']['get_description'] = function() {
+ return 'Description for our Imaginary Rule';
+ };
+
+ $rules[] = $rule;
+ return $rules;
+ } );
}
add_action( 'plugins_loaded', 'AntispamBee\init' );
From 68573cd466166222de857eb663db4273e8e58183 Mon Sep 17 00:00:00 2001
From: Angelo Cali
Date: Thu, 14 Apr 2022 11:18:33 +0200
Subject: [PATCH 048/184] Further work on settings and interfaces
---
lib/Admin/SettingsPage.php | 3 ++-
lib/Handlers/Rules.php | 1 -
lib/Helpers/InterfaceHelper.php | 30 ++++++++++++++++++++++++++----
lib/Helpers/Settings.php | 4 ----
lib/Rules/CountrySpam.php | 3 +++
lib/load.php | 30 ++++++++++++++++++++++++++++++
6 files changed, 61 insertions(+), 10 deletions(-)
diff --git a/lib/Admin/SettingsPage.php b/lib/Admin/SettingsPage.php
index 53a1eda5..4e218e88 100644
--- a/lib/Admin/SettingsPage.php
+++ b/lib/Admin/SettingsPage.php
@@ -107,7 +107,8 @@ public function setup_settings() {
] );
// Todo: Add a way to build rows and fields with a fluent interface?
- // Todo: Fix the weird naming
+ // Todo: Fix the confusing naming. We have a lot of type e.g.
+
// Todo: Discuss if we want to remove that setting in V3 and maybe have a filter for that.
// If we keep it, we have to add it to the comments tab.
// new Checkbox( 'ab_use_output_buffer', esc_html( 'Check complete site markup for comment forms', 'antispam-bee' ), sprintf( /* translators: s=filter name */ esc_html( 'Uses output buffering instead of the %s filter.', 'antispam-bee' ), 'comment_form_field_comment
' ) ),
diff --git a/lib/Handlers/Rules.php b/lib/Handlers/Rules.php
index 32f94ad1..a6fb7779 100644
--- a/lib/Handlers/Rules.php
+++ b/lib/Handlers/Rules.php
@@ -96,7 +96,6 @@ public static function filter( $rules, $options ) {
continue;
}
-
$conforms_to_controllable = isset( $rule['controllable'] ) ?
InterfaceHelper::conforms_to_interface( $rule['controllable'], Controllable::class ) : false;
if ( $only_controllables && ! $conforms_to_controllable ) {
diff --git a/lib/Helpers/InterfaceHelper.php b/lib/Helpers/InterfaceHelper.php
index 28ff6aa4..6697f907 100644
--- a/lib/Helpers/InterfaceHelper.php
+++ b/lib/Helpers/InterfaceHelper.php
@@ -4,16 +4,38 @@
class InterfaceHelper {
- // Todo: adapt method because the methods have to be stored under the verifiable key
+ // Todo: adapt class methods because the callable methods now have to be stored under the interface key
+ /**
+ * Tries to call a method with different approaches. Firstly it tries to call it via object/fqn and method name.
+ * Next it tries to call the array element directly. At least it returns the value of the node.
+ *
+ * @param array $array
+ * @param string $interface
+ * @param string $method
+ * @param array $args
+ *
+ * @return mixed|null
+ */
public static function call( $array, $interface, $method, $args = [] ) {
- $callable = isset( $array[ $interface ][ $method ] ) ? $array[ $interface ][ $method ] : null;
+ // Just return if there is no interface key in the array
+ if ( ! isset ( $array[ $interface ] ) ) {
+ return null;
+ }
+
+ // Call the method if it is an object or fully qualified name and the method is callable
+ $callable = [ $array[ $interface ], $method ];
if ( is_callable( $callable ) ) {
return call_user_func( $callable, $args );
}
- if ( isset( $array[ $interface ] ) && is_callable( array( $array[ $interface ], $method ) ) ) {
- return call_user_func( [ $array[ $interface ], $method ], $args );
+ // Call the method if the callable is stored in the array
+ $callable = isset( $array[ $interface ][ $method ] ) ? $array[ $interface ][ $method ] : null;
+ if ( is_callable( $callable ) ) {
+ return call_user_func( $callable, $args );
}
+
+ // Return the value at least, if nothing other works
+ return $callable;
}
public static function class_implements_interface( $class_name, $interface ) {
diff --git a/lib/Helpers/Settings.php b/lib/Helpers/Settings.php
index 0539bb84..67932082 100644
--- a/lib/Helpers/Settings.php
+++ b/lib/Helpers/Settings.php
@@ -116,10 +116,6 @@ public static function sanitize( $options ) {
$options = ! empty( $options ) ? $options : [ $tab => [] ];
$current_options[ $tab ] = $options[ $tab ];
- echo '';
- var_dump( $options, $current_options );
- echo '
';
-
return $current_options;
}
}
diff --git a/lib/Rules/CountrySpam.php b/lib/Rules/CountrySpam.php
index 6cfd3aaf..40ff0fd2 100644
--- a/lib/Rules/CountrySpam.php
+++ b/lib/Rules/CountrySpam.php
@@ -19,6 +19,9 @@ public static function verify( $data ) {
$ip = $data['comment_author_IP'];
$options = Settings::get_options();
+ if ( ! ( isset( $options['country_allowed'] ) && isset( $options['country_denied'] ) ) ) {
+ return 0;
+ }
$allowed = preg_split(
'/[\s,;]+/',
diff --git a/lib/load.php b/lib/load.php
index a2565f86..929658d3 100644
--- a/lib/load.php
+++ b/lib/load.php
@@ -81,6 +81,10 @@ function init() {
// Todo: Allow to give values instead of callables. Test for return types.
// Todo: Write a doc how to implement a custom rule and postprocessor.
+ // Todo: Remove the following code as it is only for testing the extendibility at the moment
+ /*
+ * Example with callables
+ *
add_filter( 'asb_rules', function( $rules ) {
$rule = [];
$rule['verifiable']['verify'] = function() {
@@ -115,6 +119,32 @@ function init() {
$rules[] = $rule;
return $rules;
} );
+ */
+
+ /*
+ * Example without callables
+ *
+ add_filter( 'asb_rules', function( $rules ) {
+ $rule = [];
+ $rule['verifiable']['verify'] = function() {
+ return 1;
+ };
+ $rule['verifiable']['get_name'] = 'Imaginary Rule';
+ $rule['verifiable']['get_weight'] = 1000.0;
+ $rule['verifiable']['get_slug'] = 'imaginary_rule';
+ $rule['verifiable']['get_supported_types'] = [ 'comment', 'webmention' ];
+ $rule['verifiable']['is_final'] = true;
+
+ $rule['controllable']['get_label'] = 'Imaginary Rule';
+ $rule['controllable']['get_description'] = 'Description for our Imaginary Rule';
+ $rule['controllable']['is_active'] = function( $type ) {
+ return true;
+ };
+
+ $rules[] = $rule;
+ return $rules;
+ } );
+ */
}
add_action( 'plugins_loaded', 'AntispamBee\init' );
From 285f4d557ed8e52a479ac96988b3eac0607b096a Mon Sep 17 00:00:00 2001
From: Angelo Cali
Date: Thu, 14 Apr 2022 18:17:25 +0200
Subject: [PATCH 049/184] Add PostProcessors, general settings, inline fields
---
lib/Admin/Fields/Checkbox.php | 12 ++-
lib/Admin/Fields/CheckboxGroup.php | 34 ++++++-
lib/Admin/Fields/Field.php | 1 +
lib/Admin/Fields/Inline.php | 25 +++++
lib/Admin/Fields/Text.php | 35 ++++++-
lib/Admin/Section.php | 24 ++---
lib/Admin/SettingsPage.php | 74 +++++++++++----
lib/Handlers/PostProcessors.php | 62 ++++---------
lib/Handlers/Rules.php | 72 +++------------
lib/Helpers/Components.php | 64 +++++++++++++
lib/Helpers/InterfaceHelper.php | 112 +++++------------------
lib/Interfaces/Controllable.php | 2 +
lib/Interfaces/Verifiable.php | 2 -
lib/PostProcessors/Delete.php | 10 +-
lib/PostProcessors/DeleteForReasons.php | 39 +++++++-
lib/PostProcessors/InitPostProcessor.php | 14 +--
lib/PostProcessors/SaveReason.php | 8 +-
lib/PostProcessors/SendEmail.php | 4 +
lib/PostProcessors/UpdateDailyStats.php | 2 +-
lib/PostProcessors/UpdateSpamCount.php | 2 +-
lib/PostProcessors/UpdateSpamLog.php | 2 +-
lib/Rules/InitRule.php | 8 +-
lib/load.php | 72 ---------------
23 files changed, 348 insertions(+), 332 deletions(-)
create mode 100644 lib/Admin/Fields/Inline.php
create mode 100644 lib/Helpers/Components.php
diff --git a/lib/Admin/Fields/Checkbox.php b/lib/Admin/Fields/Checkbox.php
index e9de1de8..1a416c5a 100644
--- a/lib/Admin/Fields/Checkbox.php
+++ b/lib/Admin/Fields/Checkbox.php
@@ -17,13 +17,17 @@ class Checkbox extends Field implements RenderElement {
* Get HTML.
*/
public function render() {
+ $label = ! empty( $this->get_label() ) ? sprintf(
+ '',
+ esc_attr( $this->get_name() ),
+ esc_html( $this->get_label() )
+ ) : '';
+
printf(
- '',
+ '%3$s',
esc_attr( $this->get_name() ),
checked( 'on', $this->get_value(), false ),
- esc_html( $this->get_label() )
+ $label
);
$this->maybe_show_description();
}
diff --git a/lib/Admin/Fields/CheckboxGroup.php b/lib/Admin/Fields/CheckboxGroup.php
index 2254205a..49937ddd 100644
--- a/lib/Admin/Fields/CheckboxGroup.php
+++ b/lib/Admin/Fields/CheckboxGroup.php
@@ -3,16 +3,46 @@
namespace AntispamBee\Admin\Fields;
use AntispamBee\Admin\RenderElement;
+use AntispamBee\Helpers\Settings;
/**
* Checkbox field.
*/
class CheckboxGroup extends Field implements RenderElement {
/**
- * Get HTML.
+ * Render HTML.
*/
public function render() {
- echo 'get_value(), false ) . ' />';
+ $options = isset( $this->option['options'] ) ? $this->option['options'] : [];
+ if ( ! is_array( $options ) ) {
+ return;
+ }
+
+ printf(
+ '%s
',
+ $this->get_label()
+ );
+ foreach ( $options as $key => $value ) {
+ printf(
+ '
',
+ esc_attr( $this->get_name() . '[' . $key . ']' ),
+ checked( 'on', $this->get_custom_value( $key ), false ),
+ esc_html( $value )
+ );
+ }
$this->maybe_show_description();
}
+
+ /**
+ * Get Value.
+ *
+ * @return mixed Value stored in database.
+ */
+ protected function get_custom_value( $key ) {
+ $options = Settings::get_option( $this->option['option_name'], $this->type );
+
+ return isset ( $options[ $key ] ) ? $options[ $key ] : null;
+ }
}
diff --git a/lib/Admin/Fields/Field.php b/lib/Admin/Fields/Field.php
index bf6dbc44..238b51ac 100644
--- a/lib/Admin/Fields/Field.php
+++ b/lib/Admin/Fields/Field.php
@@ -44,6 +44,7 @@ public function __construct( $type, $option ) {
* @return string Name of the field.
*/
public function get_name() {
+ // Todo: Find a more descriptive name for option_name
return str_replace( '-', '_', 'antispam_bee[' . $this->type . '][' . $this->option['option_name'] . ']' );
}
diff --git a/lib/Admin/Fields/Inline.php b/lib/Admin/Fields/Inline.php
new file mode 100644
index 00000000..85b18169
--- /dev/null
+++ b/lib/Admin/Fields/Inline.php
@@ -0,0 +1,25 @@
+option['input'];
+ $inject_markup = $inject_field_object->get_injectable_markup();
+ $label_with_inline_field = sprintf(
+ $this->get_label(),
+ '' . $inject_markup . sprintf(
+ '