From 83249d88ca2b99db61ca475da917fb5e86a922d9 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 11:55:14 +0100 Subject: [PATCH 01/13] chore: remove unused PHP 5.4 dependencies We support >= 7, so the 5.4 stuff is obsolete. Remove it. --- .github/workflows/tests.yml | 5 +---- composer-php-5-4.json | 43 ------------------------------------- 2 files changed, 1 insertion(+), 47 deletions(-) delete mode 100644 composer-php-5-4.json diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e7b91e45..dd315348 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.3', '7.2', '5.4'] + php-versions: ['7.3', '7.2'] steps: - uses: actions/checkout@master - name: Setup PHP @@ -15,9 +15,6 @@ jobs: extensions: mbstring, intl ini-values: post_max_size=256M, short_open_tag=On tools: phpunit, composer - - name: Set COMPOSER environment variable for 5.4 - if: matrix.php-versions == '5.4' - run: echo "COMPOSER=composer-php-5-4.json" >> $GITHUB_ENV - name: Run tests run: | composer install diff --git a/composer-php-5-4.json b/composer-php-5-4.json deleted file mode 100644 index 89160d79..00000000 --- a/composer-php-5-4.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "pluginkollektiv/antispam-bee", - "description": "Antispam Bee blocks spam comments and trackbacks effectively and without captchas.", - "keywords": [ - "WordPress", - "antispam", - "honeypot" - ], - "homepage": "https://pluginkollektiv.github.io/antispam-bee/", - "authors": [ - { - "name": "pluginkollektiv", - "homepage": "https://github.com/pluginkollektiv", - "role": "Maintainer" - } - ], - "support": { - "issues": "https://github.com/pluginkollektiv/antispam-bee/issues", - "source": "https://github.com/pluginkollektiv/antispam-bee", - "docs": "https://github.com/pluginkollektiv/antispam-bee/blob/master/README.md" - }, - "type": "wordpress-plugin", - "license": "GPL-v2", - "require-dev": { - "phpunit/phpunit": "*", - "brain/monkey": "*" - }, - "config": { - "optimize-autoloader": true, - "platform": { - "php": "5.4" - } - }, - "autoload-dev": { - "classmap": [ - "antispam_bee.php", - "inc/" - ], - "psr-4": { - "AntispamBee\\Tests\\": "tests/" - } - } -} From 7fbe5d69fc6071decc944531e1370adb77f9e1f9 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 12:12:41 +0100 Subject: [PATCH 02/13] chore: remove unused Node dependencies --- .eslintrc | 20 ---------------- .github/workflows/tests.yml | 4 ---- .stylelintrc.json | 5 ---- package.json | 31 +----------------------- webpack.config.js | 48 ------------------------------------- 5 files changed, 1 insertion(+), 107 deletions(-) delete mode 100644 .eslintrc delete mode 100644 .stylelintrc.json delete mode 100644 webpack.config.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 6379d068..00000000 --- a/.eslintrc +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": [ - "plugin:@wordpress/eslint-plugin/recommended" - ], - "env": { - "browser": true - }, - "rules": { - "max-len": [ - "error", - { - "code": 160 - } - ], - "prettier/prettier": 0 - }, - "parserOptions": { - "requireConfigFile": false - } -} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dd315348..4e49f717 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -86,12 +86,8 @@ jobs: extensions: mbstring, intl ini-values: post_max_size=256M, short_open_tag=On tools: phpunit, composer - - uses: actions/setup-node@v2 - with: - node-version: '14' - name: Run code style checks for CSS, JavaScript and PHP run: | composer install - npm install composer lint-all composer cs diff --git a/.stylelintrc.json b/.stylelintrc.json deleted file mode 100644 index 829a7dcf..00000000 --- a/.stylelintrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": "@wordpress/stylelint-config", - "rules": { - } -} diff --git a/package.json b/package.json index d44971cd..5f32670d 100644 --- a/package.json +++ b/package.json @@ -3,34 +3,5 @@ "version": "3.0.0", "description": "Antispam Bee blocks spam comments and trackbacks effectively and without captchas.", "author": "pluginkollektiv", - "license": "GPL-2.0-or-later", - "main": "build/index.js", - "scripts": { - "build": "wp-scripts build", - "check-engines": "wp-scripts check-engines", - "check-licenses": "wp-scripts check-licenses", - "format:js": "wp-scripts format-js", - "format:js:src": "wp-scripts format-js ./src", - "lint:css": "wp-scripts lint-style", - "lint:css:src": "wp-scripts lint-style 'src/**/*.css'", - "lint:js": "wp-scripts lint-js", - "lint:js:src": "wp-scripts lint-js ./src", - "lint:md:docs": "wp-scripts lint-md-docs", - "lint:md:js": "wp-scripts lint-md-js", - "lint:pkg-json": "wp-scripts lint-pkg-json", - "packages-update": "wp-scripts packages-update", - "postpackages-update": "npm run build", - "start": "wp-scripts start", - "test:e2e": "wp-scripts test-e2e", - "test:unit": "wp-scripts test-unit-js" - }, - "devDependencies": { - "@wordpress/scripts": "^18.1.0", - "classnames": "^2.3.1", - "svg-spritemap-webpack-plugin": "^4.3.3", - "url-loader": "^4.1.1" - }, - "dependencies": { - "raphael": "^2.3.0" - } + "license": "GPL-2.0-or-later" } diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 53e74e8f..00000000 --- a/webpack.config.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * External dependencies - */ -const path = require( 'path' ); -const defaultConfig = require( '@wordpress/scripts/config/webpack.config' ); -const SVGSpritemapPlugin = require( 'svg-spritemap-webpack-plugin' ); - -/** - * Webpack config (Development mode) - * - * @see https://developer.wordpress.org/block-editor/packages/packages-scripts/#provide-your-own-webpack-config - */ -module.exports = { - ...defaultConfig, - entry: { - backend: path.resolve( process.cwd(), 'assets/src', 'backend.js' ), - }, - output: { - filename: '[name].js', - path: path.resolve( process.cwd(), 'assets/dist' ), - }, - module: { - rules: [ - ...defaultConfig.module.rules, - { - test: /\.svg$/, - use: [ '@svgr/webpack', 'url-loader' ], - }, - ], - }, - plugins: [ - ...defaultConfig.plugins, - - /** - * Generate an SVG sprite. - * - * @see https://github.com/cascornelissen/svg-spritemap-webpack-plugin - */ - new SVGSpritemapPlugin( 'assets/src/images/icons/**/*.svg', { - output: { - filename: 'images/icons/sprite.svg', - }, - sprite: { - prefix: 'antispam-bee-', - }, - } ), - ], -}; From 27de7b694b435a599b95b483f5c11f319dc98202 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 12:18:32 +0100 Subject: [PATCH 03/13] chore: fix code-style pipeline * remove "lint-all" which does not exist anymore * update WPCS to 3.0 * clean up GH action and update PHP version --- .github/workflows/tests.yml | 9 +++------ composer.json | 2 +- phpcs.xml | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4e49f717..b480c461 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -82,12 +82,9 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '7.2' - extensions: mbstring, intl - ini-values: post_max_size=256M, short_open_tag=On - tools: phpunit, composer + php-version: '8.2' + tools: composer - name: Run code style checks for CSS, JavaScript and PHP run: | - composer install - composer lint-all + composer install --ignore-platform-req=php composer cs diff --git a/composer.json b/composer.json index 5e671322..5867e99d 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "phpcompatibility/phpcompatibility-wp": "^2.1", "phpunit/phpunit": "^4", "wp-cli/wp-cli-bundle": "@stable", - "wp-coding-standards/wpcs": "^2.3" + "wp-coding-standards/wpcs": "^3.0" }, "autoload": { "psr-4": { diff --git a/phpcs.xml b/phpcs.xml index edec387e..c2fdc042 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -52,7 +52,7 @@ - + From e1a7c892880647907abf6016e963298de405de70 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 12:22:32 +0100 Subject: [PATCH 04/13] style: auto-fix some space, newline and indentation issues --- src/Admin/CommentsColumns.php | 16 +++--- src/Admin/DashboardWidgets.php | 24 ++++---- src/Admin/Fields/Field.php | 6 +- src/Admin/Section.php | 19 +++--- src/Admin/SettingsPage.php | 4 +- src/Admin/Tab.php | 4 +- src/GeneralOptions/Base.php | 2 - src/Handlers/Comment.php | 2 +- src/Handlers/PluginStateChangeHandler.php | 1 - src/Handlers/PluginUpdate.php | 70 +++++++++++------------ src/Handlers/PostProcessors.php | 6 +- src/Handlers/Reaction.php | 11 ++-- src/Handlers/Rules.php | 6 +- src/Helpers/ComponentsHelper.php | 2 +- src/Helpers/ContentTypeHelper.php | 4 +- src/Helpers/DebugMode.php | 34 +++++------ src/Helpers/Honeypot.php | 4 +- src/Helpers/InterfaceHelper.php | 2 +- src/Helpers/IpHelper.php | 1 - src/Helpers/LangHelper.php | 2 - src/Helpers/Sanitize.php | 4 +- src/Helpers/Settings.php | 26 ++++----- src/Helpers/SpamReasonTextHelper.php | 14 ++--- src/PostProcessors/Delete.php | 2 +- src/PostProcessors/DeleteForReasons.php | 2 +- src/PostProcessors/SendEmail.php | 3 +- src/PostProcessors/UpdateSpamCount.php | 1 - src/PostProcessors/UpdateSpamLog.php | 1 - src/Rules/ApprovedEmail.php | 2 +- src/Rules/Base.php | 4 +- src/Rules/CountrySpam.php | 4 +- src/Rules/DbSpam.php | 4 +- src/Rules/EmptyData.php | 10 ++-- src/Rules/Honeypot.php | 4 +- src/Rules/InvalidRequest.php | 2 +- src/Rules/LangSpam.php | 10 ++-- src/Rules/LinkbackFromMyself.php | 4 +- src/Rules/LinkbackPostTitleIsBlogName.php | 2 +- src/Rules/RegexpSpam.php | 4 +- src/Rules/TooFastSubmit.php | 10 ++-- 40 files changed, 165 insertions(+), 168 deletions(-) diff --git a/src/Admin/CommentsColumns.php b/src/Admin/CommentsColumns.php index 5a803662..146e34bf 100644 --- a/src/Admin/CommentsColumns.php +++ b/src/Admin/CommentsColumns.php @@ -71,7 +71,7 @@ public static function register_plugin_columns( $columns ) { /** * Display plugin column values on comments screen * - * @param string $column Currently selected column. + * @param string $column Currently selected column. * @param integer $comment_id Comment ID. * * @since 2.6.0 @@ -141,19 +141,19 @@ public static function filter_columns() { global $wpdb; ?> + for="filter-by-comment-spam-reason"> %s', - $unique_id, - time(), - $script - ); + '%s', + $unique_id, + time(), + $script + ); } ); } From e5c4ebe14251ab205b6dba1a0620f0fdccf007b6 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 13:00:51 +0100 Subject: [PATCH 05/13] fix: add missing default return value to EmptyData rule --- src/Rules/EmptyData.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Rules/EmptyData.php b/src/Rules/EmptyData.php index 306309df..a6791395 100644 --- a/src/Rules/EmptyData.php +++ b/src/Rules/EmptyData.php @@ -34,6 +34,8 @@ public static function verify( $item ) { return 999; } } + + return 0; } public static function get_name() { From cb9046e52f83acde42c860dcdb63b4972691fcc6 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 15:19:30 +0100 Subject: [PATCH 06/13] test: update test frameworks and restore unit tests in CI Behat dependencies have been updated, but it is not expected that the tests will work. Add some simple rule tests to start with. --- .github/workflows/tests.yml | 120 +++++++++++----------- composer.json | 20 ++-- phpunit.xml.dist | 47 +++++---- tests/TestCase.php | 45 -------- tests/TestListener.php | 12 ++- tests/Unit/AntispamBeeTest.php | 32 +++--- tests/Unit/Rules/AbstractRuleTestCase.php | 85 +++++++++++++++ tests/Unit/Rules/BBCodeTest.php | 35 +++++++ tests/Unit/Rules/EmptyDataTest.php | 50 +++++++++ tests/Unit/Rules/HoneypotTest.php | 38 +++++++ 10 files changed, 327 insertions(+), 157 deletions(-) delete mode 100644 tests/TestCase.php create mode 100644 tests/Unit/Rules/AbstractRuleTestCase.php create mode 100644 tests/Unit/Rules/BBCodeTest.php create mode 100644 tests/Unit/Rules/EmptyDataTest.php create mode 100644 tests/Unit/Rules/HoneypotTest.php diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b480c461..a230985c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,11 +1,11 @@ name: Tests, Behat, Coding Standards on: push jobs: - test: + test-unit: runs-on: ubuntu-latest strategy: matrix: - php-versions: ['7.3', '7.2'] + php-versions: ['8.3', '7.4'] steps: - uses: actions/checkout@master - name: Setup PHP @@ -14,67 +14,69 @@ jobs: php-version: ${{ matrix.php-versions }} extensions: mbstring, intl ini-values: post_max_size=256M, short_open_tag=On - tools: phpunit, composer - - name: Run tests + tools: composer + - name: Install run: | composer install - ./vendor/bin/phpunit -c ./phpunit.xml.dist - behat: - runs-on: ubuntu-latest - services: - mysql: - image: mysql:5.7 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: pluginkollektiv_antispambee_behat - ports: - - '8888:3306' - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - strategy: - matrix: - php: ['8'] - wordpress: ['nightly', 'latest'] - include: - - php: '7.4' - wordpress: '5.5' - - php: '7.4' - wordpress: '5.4' - - php: '7.3' - wordpress: '5.3' - - php: '7.3' - wordpress: '5.2' - - php: '7.3' - wordpress: '5.1' - - php: '7.2' - wordpress: '4.9' - - php: '7.2' - wordpress: '4.8' - - php: '7.2' - wordpress: '4.7' - - php: '7.2' - wordpress: '4.6' - steps: - - uses: actions/checkout@master - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: mbstring, intl, pdo_mysql, zip - ini-values: post_max_size=256M, short_open_tag=On - tools: phpunit, composer - - name: Start mysql service - run: sudo /etc/init.d/mysql start - - name: Install XVFB - run: sudo apt-get update && sudo apt-get install xvfb - name: Run tests run: | - composer install --ignore-platform-req=php - ./bin/behat.sh - env: - WORDPRESS_VERSION: ${{ matrix.wordpress }} - NAP_LENGTH: 10 - - name: Cleanup xvfb - uses: bcomnes/cleanup-xvfb@v1 + composer test:unit +# behat: +# runs-on: ubuntu-latest +# services: +# mysql: +# image: mysql:5.7 +# env: +# MYSQL_ALLOW_EMPTY_PASSWORD: yes +# MYSQL_DATABASE: pluginkollektiv_antispambee_behat +# ports: +# - '8888:3306' +# options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 +# strategy: +# matrix: +# php: ['8'] +# wordpress: ['nightly', 'latest'] +# include: +# - php: '7.4' +# wordpress: '5.5' +# - php: '7.4' +# wordpress: '5.4' +# - php: '7.3' +# wordpress: '5.3' +# - php: '7.3' +# wordpress: '5.2' +# - php: '7.3' +# wordpress: '5.1' +# - php: '7.2' +# wordpress: '4.9' +# - php: '7.2' +# wordpress: '4.8' +# - php: '7.2' +# wordpress: '4.7' +# - php: '7.2' +# wordpress: '4.6' +# steps: +# - uses: actions/checkout@master +# - name: Setup PHP +# uses: shivammathur/setup-php@v2 +# with: +# php-version: ${{ matrix.php }} +# extensions: mbstring, intl, pdo_mysql, zip +# ini-values: post_max_size=256M, short_open_tag=On +# tools: phpunit, composer +# - name: Start mysql service +# run: sudo /etc/init.d/mysql start +# - name: Install XVFB +# run: sudo apt-get update && sudo apt-get install xvfb +# - name: Run tests +# run: | +# composer install --ignore-platform-req=php +# ./bin/behat.sh +# env: +# WORDPRESS_VERSION: ${{ matrix.wordpress }} +# NAP_LENGTH: 10 +# - name: Cleanup xvfb +# uses: bcomnes/cleanup-xvfb@v1 quality: runs-on: ubuntu-latest steps: diff --git a/composer.json b/composer.json index 5867e99d..2211e200 100644 --- a/composer.json +++ b/composer.json @@ -25,18 +25,15 @@ "php": ">=7.0" }, "require-dev": { - "behat/mink": "1.7.1", - "behat/mink-goutte-driver": "^1.2", - "brain/monkey": "^1.5", - "composer/package-versions-deprecated": "^1.11", - "dmore/behat-chrome-extension": "^1.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.1", - "friends-of-behat/mink-extension": "^2.5", - "paulgibbs/behat-wordpress-extension": "^3.3", + "behat/mink": "^v1.11.0", + "behat/mink-browserkit-driver": "^v2.2.0", + "dmore/behat-chrome-extension": "^1.4.0", + "dealerdirect/phpcodesniffer-composer-installer": "^v1.0.0", + "friends-of-behat/mink-extension": "^v2.7.5", "phpcompatibility/phpcompatibility-wp": "^2.1", - "phpunit/phpunit": "^4", "wp-cli/wp-cli-bundle": "@stable", - "wp-coding-standards/wpcs": "^3.0" + "wp-coding-standards/wpcs": "^3.0.1", + "yoast/wp-test-utils": "^1.2.0" }, "autoload": { "psr-4": { @@ -61,7 +58,8 @@ ], "lint-php": [ "phpcs --standard=phpcs.xml -s" - ] + ], + "test:unit": [ "phpunit -c phpunit.xml.dist --testsuite unit" ] }, "config": { "allow-plugins": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 3047bcc1..a10ee074 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,25 +1,24 @@ - - - - - tests/Unit - - - tests/Integration - - - - - + + + + tests/Unit + tests/Unit/AntispamBeeTest.php + + + tests/Integration + + + + + diff --git a/tests/TestCase.php b/tests/TestCase.php deleted file mode 100644 index 732be189..00000000 --- a/tests/TestCase.php +++ /dev/null @@ -1,45 +0,0 @@ -getName() ) ) { case 'unit': $this->stub_functions(); diff --git a/tests/Unit/AntispamBeeTest.php b/tests/Unit/AntispamBeeTest.php index 9e979dc5..19239b15 100644 --- a/tests/Unit/AntispamBeeTest.php +++ b/tests/Unit/AntispamBeeTest.php @@ -3,12 +3,16 @@ namespace AntispamBee\Tests\Unit\Core; use Antispam_Bee as Testee; -use AntispamBee\Tests\TestCase; -use Brain\Monkey\Functions; +use Yoast\WPTestUtils\BrainMonkey\TestCase; + +use function Brain\Monkey\Functions\expect; +use function Brain\Monkey\Functions\when; /** * Test case for the factory class. * + * TODO: This is a legacy test from 2.x. Update or remove. + * * @since 2.7.0 */ class FactoryTest extends TestCase { @@ -18,20 +22,20 @@ class FactoryTest extends TestCase { * * @since 2.7.0 */ - protected function setUp() { - parent::setUp(); + protected function set_up() { + parent::set_up(); - Functions::when( 'get_bloginfo' )->justReturn( 'https://domain.com/' ); - Functions::when( 'wp_parse_url' )->alias('parse_url'); - Functions::when( 'is_admin' )->justReturn( false ); - Functions::expect( 'wp_unslash' ) + when( 'get_bloginfo' )->justReturn( 'https://domain.com/' ); + when( 'wp_parse_url' )->alias('parse_url'); + when( 'is_admin' )->justReturn( false ); + expect( 'wp_unslash' ) ->andReturnUsing( function( $data ) { return $data; } ); - Functions::when( 'get_option' )->justReturn( $this->get_options() ); + when( 'get_option' )->justReturn( $this->get_options() ); Testee::init(); } @@ -81,18 +85,16 @@ public function test_gets_ip_address() { * * @covers Testee::handle_incoming_request() * - * @param array $comment Comment overrides to use. - * @param string $reason Expected spam reason to catch. */ - public function test_spam_reasons( $comment, $reason ) { - $comment = array_merge( $this->get_base_comment(), $comment ); + public function test_spam_reasons($comment, $reason) { + $comment = array_merge($this->get_base_comment(), $comment); $_SERVER['HTTP_CLIENT_IP'] = '12.23.34.45'; $_SERVER['REQUEST_URI'] = 'https://domain.com/wp-comments-post.php'; $_POST['comment'] = $comment; // This is where we check for the spam reason that was detected. - Functions::expect( 'add_comment_meta' )->once() + expect( 'add_comment_meta' )->once() ->with( 1, 'antispam_bee_reason', @@ -133,7 +135,7 @@ public function spam_reasons_data_provider() { // @ToDo: static $_reason array( array( - 'comment_content' => "this is a pharmacy, why does it work now?.", + 'comment_content' => "this is a pharmacy, why does it work now?.", 'comment_author_email' => 'test@yandex.ru', ), 'regexp', diff --git a/tests/Unit/Rules/AbstractRuleTestCase.php b/tests/Unit/Rules/AbstractRuleTestCase.php new file mode 100644 index 00000000..84771457 --- /dev/null +++ b/tests/Unit/Rules/AbstractRuleTestCase.php @@ -0,0 +1,85 @@ +rule = $rule; + $this->slug = $slug; + } + + /** + * Test for expected slug. + * Might seem redundant, but we might just have forgotten about this... + * + * @return void + */ + public function test_slug() { + self::assertSame( $this->slug, $this->rule::get_slug(), 'unexpected slug' ); + } + + /** + * Test initialization. + * All rules should add themselves to the rules filter by default. + * Might be overwritten, if a rule does special initialization. + * + * @return void + */ + public function test_init() { + $this->rule::init(); + + self::assertNotFalse( + has_filter( 'antispam_bee_rules', array( $this->rule, 'add_rule' ) ), + 'add_rule filter was not added' + ); + } + + /** + * Generate a test comment. + * + * @param int $id Comment ID. + * @param string $author Author name. + * @param string $author_email Author email. + * @param string $author_url Author URL. + * @param string $author_ip Author IP address. + * @param string $content Content. + * + * @return array Comment array. + */ + protected static function make_comment( + int $id = 1, + string $author = 'Test Author', + string $author_email = 'test.author@example.com', + string $author_url = 'www.example.com', + string $author_ip = '192.0.2.1', + string $content = 'This is the base test comment.' + ): array { + return array( + 'reaction_type' => ContentTypeHelper::COMMENT_TYPE, + 'comment_ID' => $id, + 'comment_author' => $author, + 'comment_author_email' => $author_email, + 'comment_author_url' => $author_url, + 'comment_author_IP' => $author_ip, + 'comment_content' => $content, + ); + } +} diff --git a/tests/Unit/Rules/BBCodeTest.php b/tests/Unit/Rules/BBCodeTest.php new file mode 100644 index 00000000..6ee5783e --- /dev/null +++ b/tests/Unit/Rules/BBCodeTest.php @@ -0,0 +1,35 @@ + ContentTypeHelper::COMMENT_TYPE ); + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result for empty comment' ); + + $item['comment_content'] = 'This is a test.'; + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result for empty author IP' ); + + $item['comment_author_IP'] = '192.0.2.91'; + when( 'get_option' )->justReturn( false ); + self::assertSame( 0, EmptyData::verify( $item ), 'unexpected result with no name required' ); + + when( 'get_option' )->justReturn( true ); + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result without name and mail' ); + + $item['comment_author_email'] = 'comments@example.com'; + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result without author name' ); + + $item['comment_author'] = 'A. Tester'; + self::assertSame( 0, EmptyData::verify( $item ), 'unexpected result with name and mail' ); + } + + public function test_verify_linkback() { + $item = array( 'reaction_type' => ContentTypeHelper::LINKBACK_TYPE ); + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result for empty comment' ); + + $item['comment_content'] = 'This is a test.'; + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result for empty author IP' ); + + $item['comment_author_IP'] = '192.0.2.91'; + self::assertSame( 999, EmptyData::verify( $item ), 'unexpected result with empty URL' ); + + $item['comment_author_url'] = 'https://linkback.example.com/'; + self::assertSame( 0, EmptyData::verify( $item ), 'unexpected result with non-empty URL' ); + } +} diff --git a/tests/Unit/Rules/HoneypotTest.php b/tests/Unit/Rules/HoneypotTest.php new file mode 100644 index 00000000..a3d3180c --- /dev/null +++ b/tests/Unit/Rules/HoneypotTest.php @@ -0,0 +1,38 @@ + Date: Mon, 18 Mar 2024 18:10:05 +0100 Subject: [PATCH 07/13] fix: use correct variable to read linkback URL --- src/Rules/EmptyData.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rules/EmptyData.php b/src/Rules/EmptyData.php index a6791395..371b5fbb 100644 --- a/src/Rules/EmptyData.php +++ b/src/Rules/EmptyData.php @@ -29,7 +29,7 @@ public static function verify( $item ) { } if ( $item['reaction_type'] === ContentTypeHelper::LINKBACK_TYPE ) { - $url = $linkback['comment_author_url'] ?? ''; + $url = $item['comment_author_url'] ?? ''; if ( empty( $url ) ) { return 999; } From d7bcaca568838e7ed6102c0f7f4ba3d2247d67aa Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 17:49:22 +0100 Subject: [PATCH 08/13] fix: translation for label and description of DeleteOldSpam --- src/GeneralOptions/DeleteOldSpam.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GeneralOptions/DeleteOldSpam.php b/src/GeneralOptions/DeleteOldSpam.php index 0b3e3d96..6fa4a8d2 100644 --- a/src/GeneralOptions/DeleteOldSpam.php +++ b/src/GeneralOptions/DeleteOldSpam.php @@ -38,8 +38,8 @@ public static function get_options() { static::class ), 'option_name' => 'active', - 'label' => esc_html( 'Delete existing spam after %s days', 'antispam-bee' ), - 'description' => esc_html( 'Cleaning up the database from old entries', 'antispam-bee' ), + 'label' => esc_html__( 'Delete existing spam after %s days', 'antispam-bee' ), + 'description' => esc_html__( 'Cleaning up the database from old entries', 'antispam-bee' ), 'sanitize' => function ( $value ) { return Sanitize::checkbox( $value ); }, From a349b0383c70fb9c7e6154f3c399071a48f59633 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 18:43:33 +0100 Subject: [PATCH 09/13] fix: default tab assignment in sanitize_options --- src/Helpers/Sanitize.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Helpers/Sanitize.php b/src/Helpers/Sanitize.php index fa6109bd..018e45da 100644 --- a/src/Helpers/Sanitize.php +++ b/src/Helpers/Sanitize.php @@ -67,12 +67,12 @@ public static function checkbox( $value ) { public static function sanitize_options( $options ) { $current_options = Settings::get_options(); - if ( ! isset( $_GET['tab'] ) || empty( $_GET['tab'] ) ) { - return $_GET['tab'] = 'general'; + if ( empty( $_GET['tab'] ) ) { + $tab = 'general'; + } else { + $tab = sanitize_key( wp_unslash( $_GET['tab'] ) ); } - $tab = $_GET['tab']; - $options = ! empty( $options ) ? $options : [ $tab => [] ]; $sanitized_options = self::sanitize_controllables( $options, $tab ); From 3006c4383a44ccbde5b5523cb6d52312eee93419 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 18:53:54 +0100 Subject: [PATCH 10/13] fix: use of sprintf( esc_html_x () ) in SpamReasonTextHelper --- src/Helpers/SpamReasonTextHelper.php | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Helpers/SpamReasonTextHelper.php b/src/Helpers/SpamReasonTextHelper.php index 4e8655ee..e307da48 100644 --- a/src/Helpers/SpamReasonTextHelper.php +++ b/src/Helpers/SpamReasonTextHelper.php @@ -50,19 +50,17 @@ public static function get_texts_by_slugs( array $slugs ) { ]; if ( array_key_exists( $slug, $legacy_rules ) ) { - $texts[] = esc_html_x( + $texts[] = sprintf( /* translators: s=slug of unknown spam reason */ - sprintf( 'Legacy rule: %s', $legacy_rules[ $slug ] ), - 'spam-reason-legacy-text', - 'antispam-bee' + esc_html_x( 'Legacy rule: %s', 'spam-reason-legacy-text', 'antispam-bee' ), + $legacy_rules[ $slug ] ); continue; } - $texts[] = esc_html_x( - /* translators: s=slug of unknown spam reason */ - sprintf( 'Unknown rule: %s', $slug ), - 'spam-reason-unknown-text', - 'antispam-bee' + $texts[] = sprintf( + /* translators: s=slug of unknown spam reason */ + esc_html_x( 'Unknown rule: %s', 'spam-reason-unknown-text', 'antispam-bee' ), + $slug ); } From c85b6cd838f2143d6486855030324a8ce3cbc889 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 19:04:26 +0100 Subject: [PATCH 11/13] fix: return value for empty values in SaveReason and UpdateSpamLog --- src/PostProcessors/SaveReason.php | 3 ++- src/PostProcessors/UpdateSpamLog.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/PostProcessors/SaveReason.php b/src/PostProcessors/SaveReason.php index d4a5b920..b6c94125 100644 --- a/src/PostProcessors/SaveReason.php +++ b/src/PostProcessors/SaveReason.php @@ -14,7 +14,8 @@ public static function process( $item ) { } if ( ! isset( $item['asb_reasons'] ) ) { - return $item['asb_post_processors_failed'][] = self::get_slug(); + $item['asb_post_processors_failed'][] = self::get_slug(); + return $item; } add_action( diff --git a/src/PostProcessors/UpdateSpamLog.php b/src/PostProcessors/UpdateSpamLog.php index 1c124c2b..f8c2a27a 100644 --- a/src/PostProcessors/UpdateSpamLog.php +++ b/src/PostProcessors/UpdateSpamLog.php @@ -11,7 +11,8 @@ class UpdateSpamLog extends Base { public static function process( $item ) { if ( ! isset( $item['comment_post_ID'] ) || ! isset( $item['comment_author_IP'] ) ) { - return $item['asb_post_processors_failed'][] = self::get_slug(); + $item['asb_post_processors_failed'][] = self::get_slug(); + return $item; } if ( From 4c03a437644572c45a9a81b99bb534911a3ea59b Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sun, 17 Mar 2024 19:10:26 +0100 Subject: [PATCH 12/13] docs: extend PHPDocs and fix some minor code style issues --- src/Admin/CommentsColumns.php | 3 +- src/Admin/DashboardWidgets.php | 6 ++ src/Admin/Fields/Checkbox.php | 2 + src/Admin/Fields/CheckboxGroup.php | 11 ++- src/Admin/Fields/Field.php | 4 +- src/Admin/Fields/Inline.php | 15 +++++ src/Admin/Fields/Select.php | 7 ++ src/Admin/Fields/Text.php | 27 ++++++++ src/Admin/Fields/Textarea.php | 2 + src/Admin/Section.php | 30 ++++++--- src/Admin/SettingsPage.php | 19 ++++-- src/Admin/Tab.php | 15 ++++- src/Crons/DeleteSpamCron.php | 39 +++++++++-- src/GeneralOptions/Base.php | 81 +++++++++++++++++++---- src/GeneralOptions/DeleteOldSpam.php | 36 ++++++++++ src/GeneralOptions/IgnoreLinkbacks.php | 29 ++++++++ src/GeneralOptions/Statistics.php | 29 ++++++++ src/GeneralOptions/Uninstall.php | 29 ++++++++ src/Handlers/Comment.php | 20 ++++++ src/Handlers/GeneralOptions.php | 27 +++++++- src/Handlers/Linkback.php | 20 ++++++ src/Handlers/PluginStateChangeHandler.php | 7 +- src/Handlers/PluginUpdate.php | 32 ++++++++- src/Handlers/PostProcessors.php | 39 +++++++++-- src/Handlers/Reaction.php | 43 ++++++++++-- src/Handlers/Rules.php | 77 ++++++++++++++++++++- src/Helpers/ComponentsHelper.php | 32 ++++++--- src/Helpers/ContentTypeHelper.php | 14 ++++ src/Helpers/DashboardHelper.php | 2 + src/Helpers/DataHelper.php | 29 ++++++++ src/Helpers/DebugMode.php | 32 ++++++++- src/Helpers/InterfaceHelper.php | 18 +++-- src/Helpers/IpHelper.php | 11 ++- src/Helpers/LangHelper.php | 10 +++ src/Helpers/Sanitize.php | 43 ++++++++++-- src/Helpers/Settings.php | 60 ++++++++++++++--- src/Helpers/SpamReasonTextHelper.php | 28 +++++++- src/Interfaces/Controllable.php | 60 ++++++++++++++++- src/Interfaces/PostProcessor.php | 27 ++++++++ src/Interfaces/SpamReason.php | 13 ++++ src/Interfaces/Verifiable.php | 36 ++++++++++ src/PostProcessors/Base.php | 44 +++++++++++- src/PostProcessors/ControllableBase.php | 44 +++++++++++- src/PostProcessors/Delete.php | 39 ++++++++++- src/PostProcessors/DeleteForReasons.php | 50 +++++++++++++- src/PostProcessors/SaveReason.php | 35 +++++++++- src/PostProcessors/SendEmail.php | 58 +++++++++++++++- src/PostProcessors/UpdateSpamCount.php | 17 +++++ src/PostProcessors/UpdateSpamLog.php | 17 +++++ src/Rules/ApprovedEmail.php | 42 +++++++++++- src/Rules/BBCode.php | 39 +++++++++++ src/Rules/Base.php | 66 ++++++++++++++++-- src/Rules/ControllableBase.php | 51 ++++++++++++++ src/Rules/CountrySpam.php | 52 +++++++++++++++ src/Rules/DbSpam.php | 38 +++++++++++ src/Rules/EmptyData.php | 34 +++++++++- src/Rules/Honeypot.php | 54 ++++++++++++++- src/Rules/InvalidRequest.php | 30 +++++++++ src/Rules/LangSpam.php | 50 +++++++++++++- src/Rules/LinkbackFromMyself.php | 45 ++++++++++++- src/Rules/LinkbackPostTitleIsBlogName.php | 37 ++++++++++- src/Rules/RegexpSpam.php | 38 ++++++++++- src/Rules/TooFastSubmit.php | 44 ++++++++++++ src/Rules/ValidGravatar.php | 39 +++++++++++ src/load.php | 8 +-- 65 files changed, 1929 insertions(+), 106 deletions(-) diff --git a/src/Admin/CommentsColumns.php b/src/Admin/CommentsColumns.php index 146e34bf..20404a84 100644 --- a/src/Admin/CommentsColumns.php +++ b/src/Admin/CommentsColumns.php @@ -2,7 +2,7 @@ /** * Class registering columns for the "spam comments view". * - * @package AntispamBee\Helpers + * @package AntispamBee\Admin */ namespace AntispamBee\Admin; @@ -93,6 +93,7 @@ public static function print_plugin_column( $column, $comment_id ) { $reasons = explode( ',', $spam_reason ); $reason_texts = SpamReasonTextHelper::get_texts_by_slugs( $reasons ); + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- reason texts pre-sanitized. echo implode( ',
', $reason_texts ); } diff --git a/src/Admin/DashboardWidgets.php b/src/Admin/DashboardWidgets.php index d8333819..392d539b 100644 --- a/src/Admin/DashboardWidgets.php +++ b/src/Admin/DashboardWidgets.php @@ -74,6 +74,12 @@ private static function get_spam_count() { return self::format_number( $count ); } + /** + * Format a number. + * + * @param float $number Number to format. + * @return string + */ private static function format_number( $number ) { return ( get_locale() === 'de_DE' ? number_format( $number, 0, '', '.' ) : number_format_i18n( $number ) ); } diff --git a/src/Admin/Fields/Checkbox.php b/src/Admin/Fields/Checkbox.php index 9cc10768..f45034c6 100644 --- a/src/Admin/Fields/Checkbox.php +++ b/src/Admin/Fields/Checkbox.php @@ -17,6 +17,8 @@ class Checkbox extends Field implements RenderElement { * Get HTML. */ public function render() { + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + $label = ! empty( $this->get_label() ) ? sprintf( '', esc_attr( $this->get_name() ), diff --git a/src/Admin/Fields/CheckboxGroup.php b/src/Admin/Fields/CheckboxGroup.php index e7201e1f..f30a63d1 100644 --- a/src/Admin/Fields/CheckboxGroup.php +++ b/src/Admin/Fields/CheckboxGroup.php @@ -1,4 +1,9 @@ option['options'] ) ? $this->option['options'] : []; if ( ! is_array( $options ) ) { return; @@ -38,6 +45,8 @@ public function render() { /** * Get Value. * + * @param string $key Option key. + * * @return mixed Value stored in database. */ protected function get_custom_value( $key ) { diff --git a/src/Admin/Fields/Field.php b/src/Admin/Fields/Field.php index 84c1a50e..ea879bba 100644 --- a/src/Admin/Fields/Field.php +++ b/src/Admin/Fields/Field.php @@ -30,6 +30,8 @@ abstract class Field { /** * Type of controllable. + * + * @var string */ protected $controllable_option_name; @@ -123,7 +125,7 @@ protected function maybe_show_description() { /** * Get HTML for field. * - * @return string Elment HTML. + * @return string Element HTML. */ abstract public function render(); } diff --git a/src/Admin/Fields/Inline.php b/src/Admin/Fields/Inline.php index ec1dc476..507c35c9 100644 --- a/src/Admin/Fields/Inline.php +++ b/src/Admin/Fields/Inline.php @@ -1,12 +1,27 @@ option['input'] instanceof Field ) { echo ''; diff --git a/src/Admin/Fields/Select.php b/src/Admin/Fields/Select.php index ab399b95..d7df9a99 100644 --- a/src/Admin/Fields/Select.php +++ b/src/Admin/Fields/Select.php @@ -1,4 +1,9 @@ get_name(); $multiple = isset( $this->option['multiple'] ) && $this->option['multiple'] ? 'multiple' : ''; echo "', @@ -44,6 +61,11 @@ public function get_injectable_markup() { ); } + /** + * Get element class(es). + * + * @return string + */ protected function get_class() { $classes = [ 'small' => 'small-text', @@ -58,6 +80,11 @@ protected function get_class() { return 'regular-text'; } + /** + * Get type of input field. + * + * @return string + */ protected function get_type() { return isset( $this->option['input_type'] ) ? $this->option['input_type'] : 'text'; } diff --git a/src/Admin/Fields/Textarea.php b/src/Admin/Fields/Textarea.php index 8bde6f0a..59c09e69 100644 --- a/src/Admin/Fields/Textarea.php +++ b/src/Admin/Fields/Textarea.php @@ -17,6 +17,8 @@ class Textarea extends Field implements RenderElement { * Render HTML. */ public function render() { + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + printf( '

', esc_attr( $this->get_name() ), diff --git a/src/Admin/Section.php b/src/Admin/Section.php index b69a8329..4e075471 100644 --- a/src/Admin/Section.php +++ b/src/Admin/Section.php @@ -55,11 +55,6 @@ class Section { */ private $type; - /** - * - * @var Controllable[] - */ - private $controllables; /** * Initializing Tab. @@ -76,12 +71,24 @@ public function __construct( $slug, $title, $description = '', $type = null ) { $this->type = $type; } + /** + * Add controllable items to section. + * + * @param array|null $controllables List of controllable items to add. + * @return void + */ public function add_controllables( $controllables ) { if ( ! empty( $controllables ) ) { $this->generate_fields( $controllables ); } } + /** + * Generate settings fields for a list of controllable items. + * + * @param Controllable[] $controllables List of controllable items to add. + * @return void + */ private function generate_fields( $controllables ) { foreach ( $controllables as $controllable ) { $label = $controllable::get_label(); @@ -103,7 +110,7 @@ private function generate_fields( $controllables ) { if ( ! empty( $options ) ) { foreach ( $options as $option ) { $valid_for = isset( $option['valid_for'] ) ? $option['valid_for'] : null; - if ( $valid_for !== null && $this->type !== $valid_for ) { + if ( null !== $valid_for && $this->type !== $valid_for ) { continue; } $fields[] = $this->generate_field( $option, $controllable ); @@ -117,6 +124,13 @@ private function generate_fields( $controllables ) { } } + /** + * Generate field for a controllable item's option. + * + * @param array $option Option name. + * @param Controllable $controllable Controllable item. + * @return Checkbox|CheckboxGroup|Inline|Select|Text|Textarea|null + */ private function generate_field( $option, $controllable ) { switch ( $option['type'] ) { case 'input': @@ -215,14 +229,14 @@ function () use ( $row ) { /** * Renders the fields for a row. * - * @param array $row + * @param array $row Row of fields. */ protected function render_row_fields( $row ) { foreach ( $row['fields'] as $key => $field ) { $field->render(); // Add linebreak after field if not (last and not checkbox without label). - if ( $key !== count( $row['fields'] ) - 1 ) { + if ( ( count( $row['fields'] ) - 1 ) !== $key ) { if ( $field instanceof Checkbox && empty( $field->get_label() ) ) { continue; } diff --git a/src/Admin/SettingsPage.php b/src/Admin/SettingsPage.php index 2e547d26..459106b9 100644 --- a/src/Admin/SettingsPage.php +++ b/src/Admin/SettingsPage.php @@ -35,11 +35,15 @@ class SettingsPage { private $tabs = []; /** + * List of controllable rules. + * * @var Rules[] */ private $rules = []; /** + * List of controllable post processors + * * @var PostProcessors[] */ private $post_processors = []; @@ -59,7 +63,7 @@ public function init() { add_action( 'admin_init', [ $this, 'setup_settings' ] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended - $this->active_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : 'general'; + $this->active_tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'general'; } /** @@ -79,14 +83,16 @@ public function add_menu() { * Setup tabs content. */ public function setup_settings() { - // Todo: Add a way to build rows and fields with a fluent interface? (Nice-to-have) + // Todo: Add a way to build rows and fields with a fluent interface? (Nice-to-have). + /* * Todo: Instead of using an array to pass options to a function, one could introduce a class that contains * these options as class attributes. You instantiate an object of this class and pass it to the * Components::filter() method. For frequently used options, one could also use blueprints for options. * This would make refactoring easier, but would slightly increase the complexity. (nice-to-have). */ - // Todo: Fix the confusing naming. We have a lot of type e.g. (Nice-to-have) + + // Todo: Fix the confusing naming. We have a lot of type e.g. (Nice-to-have). $tabs['general'] = new Tab( 'general', @@ -114,7 +120,7 @@ public function setup_settings() { $this->populate_tabs(); - // Register option setting + // Register option setting. foreach ( $this->tabs as $tab ) { foreach ( $tab->get_sections() as $section ) { if ( $tab->get_slug() !== $this->active_tab ) { @@ -134,6 +140,11 @@ public function setup_settings() { ); } + /** + * Populate settings tabs. + * + * @return void + */ protected function populate_tabs() { $type = $this->active_tab; diff --git a/src/Admin/Tab.php b/src/Admin/Tab.php index c3aa7836..dcd914a2 100644 --- a/src/Admin/Tab.php +++ b/src/Admin/Tab.php @@ -1,4 +1,9 @@ sections; } + /** + * Add a section to the settings tab. + * + * @param Section $section Section to add. + * @return void + */ public function add_section( Section $section ) { $this->sections[] = $section; } diff --git a/src/Crons/DeleteSpamCron.php b/src/Crons/DeleteSpamCron.php index 8b851b53..95f4d3b9 100644 --- a/src/Crons/DeleteSpamCron.php +++ b/src/Crons/DeleteSpamCron.php @@ -1,14 +1,27 @@ 'active', + // translators: Number of days inserted at placeholder. 'label' => esc_html__( 'Delete existing spam after %s days', 'antispam-bee' ), 'description' => esc_html__( 'Cleaning up the database from old entries', 'antispam-bee' ), 'sanitize' => function ( $value ) { diff --git a/src/GeneralOptions/IgnoreLinkbacks.php b/src/GeneralOptions/IgnoreLinkbacks.php index 144f028f..e0370975 100644 --- a/src/GeneralOptions/IgnoreLinkbacks.php +++ b/src/GeneralOptions/IgnoreLinkbacks.php @@ -1,18 +1,47 @@ type = $type; } + /** + * Get controllable items for this option. + * + * @param string $type Option type. + * @return array List of controllable items. + */ public static function get_controllables( $type = 'general' ) { - if ( $type !== 'general' ) { + if ( 'general' !== $type ) { return []; } diff --git a/src/Handlers/Linkback.php b/src/Handlers/Linkback.php index 6d4adf41..07291ffc 100644 --- a/src/Handlers/Linkback.php +++ b/src/Handlers/Linkback.php @@ -1,4 +1,9 @@ 'asb-marked-manually', ]; + /** + * Was DB update triggered? + * + * @var bool + */ private static $db_update_triggered = false; + /** + * Is DB at current version? + * + * @var bool|null + */ private static $db_version_is_current = null; /** @@ -55,7 +70,7 @@ private static function maybe_update_database() { update_option( 'antispambee_db_version', self::get_plugin_version() ); - if ( $version_from_db === null ) { + if ( null === $version_from_db ) { return; } @@ -165,6 +180,16 @@ private static function maybe_update_database() { } } + /** + * Convert multiselect values. + * Takes an array of selected keys, applies optional mapping and generated a new array using + * these values as keys and "on" as value. + * + * @param array $values Selected values. + * @param array $mapping Key mapping (optional). + * + * @return array Converted array of selected options. + */ private static function convert_multiselect_values( $values, $mapping = [] ) { if ( ! is_array( $values ) || empty( $values ) ) { return $values; @@ -182,6 +207,11 @@ private static function convert_multiselect_values( $values, $mapping = [] ) { return $new_array; } + /** + * Get plugin version. + * + * @return string + */ private static function get_plugin_version() { $meta = get_file_data( MAIN_PLUGIN_FILE, [ 'Version' => 'Version' ] ); diff --git a/src/Handlers/PostProcessors.php b/src/Handlers/PostProcessors.php index 6daf003a..7a4845f5 100644 --- a/src/Handlers/PostProcessors.php +++ b/src/Handlers/PostProcessors.php @@ -1,4 +1,9 @@ get_spam_reasons() ); if ( ! isset( $item['asb_marked_as_delete'] ) ) { diff --git a/src/Handlers/Rules.php b/src/Handlers/Rules.php index 17e7fb1a..685a750b 100644 --- a/src/Handlers/Rules.php +++ b/src/Handlers/Rules.php @@ -1,4 +1,9 @@ type = $type; } + /** + * Apply rules. + * + * @param array $item Item to apply rules to. + * @return bool Item identified as spam. + */ public function apply( $item ) { $item['reaction_type'] = $this->type; $rules = self::get( $this->type, true ); @@ -64,6 +101,13 @@ public function apply( $item ) { return $score > 0.0; } + /** + * Get applicable rules. + * + * @param string $type Reaction type. + * @param bool $only_active Get only active rules. + * @return array List of applicable rules. + */ public static function get( $type = null, $only_active = false ) { return self::filter( [ @@ -74,6 +118,13 @@ public static function get( $type = null, $only_active = false ) { ); } + /** + * Get controllable items. + * + * @param string $type Reaction type. + * @param bool $only_active Get only active items. + * @return array List of suitable controllables. + */ public static function get_controllables( $type = null, $only_active = false ) { return self::filter( [ @@ -84,7 +135,13 @@ public static function get_controllables( $type = null, $only_active = false ) { ); } - // Todo: Try to find a better suited method name. + /** + * Todo: Try to find a better suited method name. + * + * @param string|null $type Reaction type. + * @param bool $only_active Get only active rules. + * @return array List of applicable rules. + */ public static function get_spam_rules( $type = null, $only_active = false ) { return self::filter( [ @@ -95,15 +152,31 @@ public static function get_spam_rules( $type = null, $only_active = false ) { ); } + /** + * Filter items. + * + * @param array $options Filter options. + * @return array List of filtered elements. + */ private static function filter( $options ) { // Todo: discuss if our rules should be filterable or not. return ComponentsHelper::filter( apply_filters( 'antispam_bee_rules', [] ), $options ); } + /** + * Get spam reasons. + * + * @return array + */ public function get_spam_reasons() { return $this->spam_reasons; } + /** + * Get no-spam reasons. + * + * @return array + */ public function get_no_spam_reasons() { return $this->no_spam_reasons; } diff --git a/src/Helpers/ComponentsHelper.php b/src/Helpers/ComponentsHelper.php index d9fa8426..60d2f696 100644 --- a/src/Helpers/ComponentsHelper.php +++ b/src/Helpers/ComponentsHelper.php @@ -1,4 +1,9 @@ 'comment', - * 'only_active' => true, - * 'is_controllable' => false, - * ); + * Filter a list of components. + * + * @param array $components Components to filter. + * @param array $options { + * Filter options. + * + * @type string $reaction_type Reaction type (e.g. "comment"). + * @type bool $only_active Only active components. + * @type bool $is_controllable Is controllable type. + * } + * @return array Filtered list. */ public static function filter( $components, $options ) { $reaction_type = isset( $options['reaction_type'] ) ? $options['reaction_type'] : null; @@ -39,16 +51,16 @@ public static function filter( $components, $options ) { } } - // Filter by supported types like Comment, Linkback + // Filter by supported types like Comment, Linkback. $supported_types = $component::get_supported_types(); if ( ! is_null( $reaction_type ) && ! in_array( $reaction_type, $supported_types ) ) { continue; } - // Filters if the component implements the Controllable interface + // Filters if the component implements the Controllable interface. $conforms_to_controllable = InterfaceHelper::class_implements_interface( $component, Controllable::class ); - // Filters out components that are not active + // Filters out components that are not active. if ( $only_active ) { if ( $conforms_to_controllable && ! $component::is_active( $reaction_type ) ) { continue; diff --git a/src/Helpers/ContentTypeHelper.php b/src/Helpers/ContentTypeHelper.php index e7729e86..99c7cdc6 100644 --- a/src/Helpers/ContentTypeHelper.php +++ b/src/Helpers/ContentTypeHelper.php @@ -1,13 +1,27 @@ __( 'General', 'antispam-bee' ), diff --git a/src/Helpers/DashboardHelper.php b/src/Helpers/DashboardHelper.php index 4e57395a..cd144ff2 100644 --- a/src/Helpers/DashboardHelper.php +++ b/src/Helpers/DashboardHelper.php @@ -9,6 +9,8 @@ /** * Class DashboardHelper + * + * A helper providing some conditional functions for the dashboard. */ class DashboardHelper { diff --git a/src/Helpers/DataHelper.php b/src/Helpers/DataHelper.php index 10c56b29..8ebc905f 100644 --- a/src/Helpers/DataHelper.php +++ b/src/Helpers/DataHelper.php @@ -1,9 +1,24 @@ $value ) { @@ -28,6 +50,13 @@ public static function get_values_where_key_contains( $substrs, $data ) { return $results; } + /** + * Parse URL wrapper. + * + * @param string $url URL to parse. + * @param string $component URL component (default: "host"). + * @return string URL component. + */ public static function parse_url( $url, $component = 'host' ) { $parts = wp_parse_url( $url ); diff --git a/src/Helpers/DebugMode.php b/src/Helpers/DebugMode.php index 72763daf..e4d2a42a 100644 --- a/src/Helpers/DebugMode.php +++ b/src/Helpers/DebugMode.php @@ -1,26 +1,52 @@ [ 'rule_asb_regexp_active' => 'on', @@ -28,6 +42,11 @@ class Settings { // @todo: check if code is PHP 7 compatible const OPTION_NAME = 'antispam_bee_options'; + /** + * Initialize. + * + * @return void + */ public static function init() { add_action( 'update_option_' . self::OPTION_NAME, @@ -37,11 +56,15 @@ public static function init() { ); } + /** + * Update cache. + * + * @param mixed $old_value The old option value. + * @param mixed $value The new option value. + * @return void + */ public static function update_cache( $old_value, $value ) { - wp_cache_set( - self::OPTION_NAME, - $value - ); + wp_cache_set( self::OPTION_NAME, $value ); } /** @@ -85,10 +108,10 @@ public static function get_option( $option_name, $type = 'general' ) { /** * Get value from array by path. * - * @param string $path Dot-separated path to the wanted value. - * @param array $array + * @param string $path Dot-separated path to the wanted value. + * @param array $array Options array. * - * @return null|mixed + * @return null|mixed Value at given path, if present. */ public static function get_array_value_by_path( $path, $array ) { if ( ! is_array( $array ) ) { @@ -158,7 +181,7 @@ public static function update_option( $field, $value ) { * Check and return an array key * * @param array $array Array with values. - * @param string $key Name of the key. + * @param string $key Name of the key. * * @return mixed Value of the requested key. * @since 2.10.0 Only return `null` if option does not exist. @@ -173,6 +196,13 @@ public static function get_key( $array, $key ) { return $array[ $key ]; } + /** + * Remove array item(s) by key. + * + * @param string $path Dot-separated path to the wanted value. + * @param array $array Array to filter. + * @return void + */ public static function remove_array_key_by_path( $path, &$array ) { if ( ! is_array( $array ) ) { return; @@ -197,6 +227,12 @@ public static function remove_array_key_by_path( $path, &$array ) { } } + /** + * Get path parts from dot-separated notation. + * + * @param mixed $path Dot-separated path to the wanted value. + * @return string[] Path parts. + */ private static function get_path_parts( $path ) { if ( ! is_string( $path ) ) { return []; @@ -210,6 +246,14 @@ private static function get_path_parts( $path ) { return $path_parts; } + /** + * Set an array item at given path. + * + * @param string $path Dot-separated path to the wanted value. + * @param mixed $sanitized Sanitized value. + * @param array $options Options array to process. + * @return void + */ public static function set_array_value_by_path( $path, $sanitized, &$options ) { if ( ! is_array( $options ) ) { return; diff --git a/src/Helpers/SpamReasonTextHelper.php b/src/Helpers/SpamReasonTextHelper.php index e307da48..2b4c32fd 100644 --- a/src/Helpers/SpamReasonTextHelper.php +++ b/src/Helpers/SpamReasonTextHelper.php @@ -1,17 +1,41 @@ ', @@ -144,6 +178,13 @@ public static function get_description() { ); } + /** + * Get options. + * + * {@inheritDoc} + * + * @return array + */ public static function get_options() { $iso_codes_link = 'https://www.iso.org/obp/ui/#search/code/'; return [ @@ -188,6 +229,12 @@ public static function get_options() { ]; } + /** + * Sanitize ISO code strings. + * + * @param string $value Comma-separated list of potential ISO country codes. + * @return string Comma-separated list if sanitized ISO country codes. + */ private static function sanitize_iso_codes_string( $value ) { $value = strtoupper( $value ); $values = explode( ',', $value ); @@ -196,6 +243,11 @@ private static function sanitize_iso_codes_string( $value ) { return implode( ',', $values ); } + /** + * Get human-readable spam reason. + * + * @return string + */ public static function get_reason_text() { return __( 'Country', 'antispam-bee' ); } diff --git a/src/Rules/DbSpam.php b/src/Rules/DbSpam.php index 44fe85a7..3f53f0c5 100644 --- a/src/Rules/DbSpam.php +++ b/src/Rules/DbSpam.php @@ -1,4 +1,9 @@ code ), $allowed_languages, true ); } + /** + * Get rule name. + * + * @return string + */ public static function get_name() { return __( 'Language', 'antispam-bee' ); } + /** + * Get rule label. + * + * @return string|null + */ public static function get_label() { return __( 'Allow reactions only in certain language', 'antispam-bee' ); } + /** + * Get rule description. + * + * @return string|null + */ public static function get_description() { $link1 = sprintf( '', @@ -117,6 +153,13 @@ public static function get_description() { ); } + /** + * Get options. + * + * {@inheritDoc} + * + * @return array + */ public static function get_options() { // @todo: we should enable the user to select all 82 languages we can detect. we use presets: the site language, the site language + english, if more than two langs are installed, use those; and: custom. We could check the preferred languages UI for the custom option. And also for the ISO codes. $languages = [ @@ -127,7 +170,7 @@ public static function get_options() { 'es' => __( 'Spanish', 'antispam-bee' ), ]; - // Todo: Deprecate old filters + // Todo: Deprecate old filters. /** * Filter the possible languages for the language spam test * @@ -151,6 +194,11 @@ public static function get_options() { ]; } + /** + * Get human-readable spam reason. + * + * @return string + */ public static function get_reason_text() { return __( 'Language', 'antispam-bee' ); } diff --git a/src/Rules/LinkbackFromMyself.php b/src/Rules/LinkbackFromMyself.php index 5b8f49f1..0f636a2c 100644 --- a/src/Rules/LinkbackFromMyself.php +++ b/src/Rules/LinkbackFromMyself.php @@ -1,4 +1,9 @@ ', diff --git a/src/load.php b/src/load.php index 3ae1e354..2807dcd4 100644 --- a/src/load.php +++ b/src/load.php @@ -51,12 +51,12 @@ function init() { CommentsColumns::class, DeleteSpamCron::class, Settings::class, - // Handlers + // Handlers. Comment::class, Linkback::class, - // Helpers + // Helpers. SpamReasonTextHelper::class, - // Post Processors + // Post Processors. DeleteOldSpam::class, Statistics::class, IgnoreLinkbacks::class, @@ -67,7 +67,7 @@ function init() { SendEmail::class, UpdateSpamCount::class, UpdateSpamLog::class, - // Rules + // Rules. ApprovedEmail::class, BBCode::class, CountrySpam::class, From 260756e64d26cc4faabf6cf1527e3730eca51fb6 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Mon, 18 Mar 2024 18:01:11 +0100 Subject: [PATCH 13/13] chore: display PHPCS warnings, but do not fail CI --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a230985c..8bf180e7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -89,4 +89,5 @@ jobs: - name: Run code style checks for CSS, JavaScript and PHP run: | composer install --ignore-platform-req=php + ./vendor/bin/phpcs --config-set ignore_warnings_on_exit 1 composer cs