Skip to content

Antispam Bee 3#506

Draft
florianbrinkmann wants to merge 243 commits into
masterfrom
v3
Draft

Antispam Bee 3#506
florianbrinkmann wants to merge 243 commits into
masterfrom
v3

Conversation

@florianbrinkmann

Copy link
Copy Markdown
Member

No description provided.

Bernhard Kau and others added 30 commits March 19, 2022 20:55
…tion call, as the translations are loaded from translate.wordpress.org
2ndkauboy and others added 10 commits June 29, 2026 00:15
* feat: add PHPStan static analysis and fix all reported issues

* chore: gitignore test-results and e2e report directories

* chore: add @Package tag to bootstrap file and PHPStan CI job

* chore: use actions/checkout@v7 and PHP 8.5 in PHPStan CI job

* chore: align all CI jobs to latest versions

* fix: bump PHPStan memory limit to 1G for CI runner

* fix: add return type declarations to Field methods

* test: disable WP auto-updates and cron during E2E tests
…#722)

* feat: render all tabs in a single form with client-side switching

Replaces full-page-reload tab navigation with a JS-driven tabbed
interface. All tab panels are now rendered inside one <form>, so
unsaved changes on one tab are preserved when switching to another.
Saving from any tab submits settings for all tabs at once.

- SettingsPage: populate and register sections for all tabs; render
  all panels inside one form with <button> tab controls and ARIA roles
- Section: register each section under a per-tab page slug so
  do_settings_sections() can target individual tab panels
- Sanitize: derive all valid tab slugs from registered controllables
  and sanitize every tab on each save (removes GET-tab dependency)
- assets/js/admin-tabs.js: new file for tab show/hide, ARIA state,
  URL sync via history.replaceState, and keyboard navigation

* fix: resolve PHPCS embedded PHP tag indentation issues in SettingsPage

* fix: align array properties indentation in RegexpSpam rule
* chore: add AI agent contribution guidelines

Add AGENTS.md as the single source of truth for AI agent contribution
rules (code quality checks, git workflow, conventional commits, PR
format). Tool-specific stub files point to it so each tool's native
config file is covered without duplicating content.

| File | AI agent |
|------|----------|
| `AGENTS.md` | OpenAI Codex (native), any agent that reads it |
| `CLAUDE.md` | Claude Code (references AGENTS.md) |
| `.github/copilot-instructions.md` | GitHub Copilot |
| `.cursor/rules/agents.mdc` | Cursor |
| `.windsurfrules` | Windsurf |
| `CONVENTIONS.md` | Aider |

* chore: add CLAUDE.md with Claude Code specific guidelines

Add CLAUDE.md for Claude Code, referencing AGENTS.md and adding
Claude-specific rules (no Co-Authored-By trailer, v3 PR workflow).

* chore: exclude AI agent guideline files from dist

* chore: document .distignore conventions in AGENTS.md

* chore: ignore local AI agent config and instruction files

* chore: normalise directory entries across .gitignore, .distignore, .gitattributes

- .gitignore: remove duplicate /node_modules/ and /vendor/ entries (covered by
  the /**/  variants already present); sort directories alphabetically
- .distignore: remove /**/node_modules and /**/vendor (WP-CLI does not support
  glob syntax, making them no-ops); /node_modules and /vendor remain
- .gitattributes: add / prefix to all directory entries to match the root-anchored
  convention already used in the # Files section

* chore: document .gitignore, .distignore, .gitattributes conventions in AGENTS.md

* chore: update .distignore

Co-authored-by: Christopher Ross <122108986+thisismyurl@users.noreply.github.com>

* chore: update .gitignore

Co-authored-by: Christopher Ross <122108986+thisismyurl@users.noreply.github.com>

* chore: update AGENTS.md

Co-authored-by: Christopher Ross <122108986+thisismyurl@users.noreply.github.com>

* chore: add PHP version target and WordPress security conventions to AGENTS.md

* chore: streamline .distignore and .gitattributes

- Remove unused directories and files like `/node_modules`, `/vendor`, and local config artifacts.
- Refine export-ignore rules for consistency.

---------

Co-authored-by: Christopher Ross <122108986+thisismyurl@users.noreply.github.com>
* docs: fix spelling and grammar in comments, docblocks and interfaces

* fix: require PHP 7.2 in version guard to match documented requirement

The bootstrap guard checked for PHP 5.6, but composer.json, readme.txt
and the admin notice itself all state 7.2 as the minimum. Sites on PHP
7.0/7.1 passed the guard and then hit code requiring 7.2.

* chore: remove TODO comments now tracked as GitHub issues

Removes the feature/refactor TODOs that were moved to issues #737-#743,
deletes a stale PHP 7 compatibility TODO, and replaces the two 'out of
beta' markers in the uninstall routine with a reference to issue #744
(keeping the commented-out cleanup code in place).

* chore: remove remaining feature and doc TODO comments

Moves the remaining actionable TODOs to GitHub issues #745-#747 (h2
section ids, custom item type docs, LinkbackFromMyself remote-server
verification) and removes them from the code. The two naming-related
TODOs are intentionally kept pending the separate naming discussion.

* chore: deduplicate WPCS dev dependency in composer.json
The commented-out post-3.0 cleanup lines (`// delete_option( ... );` and
`// $wpdb->query( ... )`) ended each inline-comment block, and end in `;`/`)`,
tripping Squiz.Commenting.InlineComment.InvalidEndChar (a phpcs error that
was failing the `quality` CI check on v3).

Reorder each block so the explanatory sentence (ending in a full stop) is
the last comment, keeping the commented-out code intact for the post-beta
cleanup tracked in #744.
Scope the `push` trigger in `tests.yml` to the `master` and `v3`
branches so pushes to a feature branch with an open PR no longer fire
both `push` and `pull_request`, running every job twice.
* refactor: disambiguate component_type vs reaction_type naming

Two distinct concepts shared the name "type", flagged by TODOs in
SettingsPage and Handlers/Rules:

- Component kind (rule/post_processor/general): Controllable::get_type()
  and the $type property are renamed to get_component_type() and
  $component_type.
- Reaction/content type (comment/linkback/general): standardised on
  $reaction_type everywhere (handler properties, is_active(), the Rules
  getters, Settings::get_option(), Section, Field, etc.).

Rules::get_spam_rules() is renamed to get_spam_reason_rules() (it returns
rules implementing the SpamReason interface); its parameter is $reaction_type.

Stored option keys and DB values are unchanged - this is a code-level
rename only. Renaming the public Controllable::get_type() interface method
is a breaking change for third-party components, done now while v3 is
still pre-beta.

* refactor: rename get_type_name to get_reaction_type_name

Complete the reaction_type disambiguation from 39f8979, which renamed the
`$item_type` parameter but left the surrounding "item type" vocabulary in
`ContentTypeHelper`:

- `get_type_name()` -> `get_reaction_type_name()` (and call sites in
  `SettingsPage` and `SendEmail`)
- filter hook `antispam_bee_item_types` -> `antispam_bee_reaction_types`,
  consistent with the sibling `antispam_bee_reaction_is_one_of`
- docblock wording "item type" -> "reaction type"

Renaming the public filter is a breaking change for third-party code, done
now while v3 is pre-beta. It is undocumented and unused internally.
Agents were treating vendor/ (dev-only, gitignored, composer-installed
code-quality tools) as project code, producing false findings. Add a
"What is project code" section pointing agents at src/, tests/, and the
root PHP files and telling them to ignore vendor/ and node_modules/.
* feat: add support links next to Save button on General tab

Replaces the bare submit_button() call on the General tab with a custom
footer row that places Donate, FAQ, Manual and Support text links to the
right of the Save Changes button, separated by a vertical rule.

* feat: add support links next to Save button on General tab

- Add support links (Donate, FAQ, Manual, Support) to the right of the
  Save Changes button on the General tab, separated by a vertical rule
- Move all admin styles to src/Admin/assets/admin.css, enqueued via
  wp_enqueue_style() on the settings page only
- Add PLUGIN_VERSION constant for stylesheet cache busting
- Use get_submit_button() instead of a raw input element

* feat: redesign action row layout and improve responsiveness

- Replace `.ab-form-footer` with `.ab-action-row` for a more flexible and responsive layout
- Add `.ab-help-links` to display plugin resources (Donate, FAQ, Manual, Support) with enhanced styling and accessibility
- Implement media queries for improved layout on small, medium, and large screens
- Refactor settings page to adopt the new responsive layout structure

* refactor: combine `admin_enqueue_scripts` callbacks

* refactor: move CSS file and fix button cursor style

* fix: add new constant to the `phpstan-bootstrap.php`
2ndkauboy added a commit that referenced this pull request Jul 2, 2026
The new code is using a `foreach` to get the two fields, but requires them to be in the correct order.

This change uses a code similar to v2 which would get the parameters, independent of the order.

Fixes: #506 (review)
2ndkauboy and others added 11 commits July 2, 2026 23:19
Add the `antispam_bee_post_processor_supported_types` filter to
`PostProcessors\Base::get_supported_types()`, mirroring the existing
`antispam_bee_rule_supported_types` filter on `Rules\Base`. This lets
third parties adjust the reaction types a post processor supports,
bringing the post processor extension API in line with rules.

Closes #741
* Get hidden and plugin field correctly

The new code is using a `foreach` to get the two fields, but requires them to be in the correct order.

This change uses a code similar to v2 which would get the parameters, independent of the order.

Fixes: #506 (review)

* Prevent a "Only variables should be passed by reference" notice

* chore: remove "asb" prefix from PHPCS globals rule

We do not use this prefix and a new rule now fails because it is too
short. Remove it from the configuration.

# Conflicts:
#	composer.json
#	phpcs.xml

* Fixing tests

---------

Co-authored-by: Stefan Kalscheuer <stefan@stklcode.de>
Every existing honeypot e2e test fills the hidden trap to force a spam
verdict; none covered the ham path. Add a test that submits a genuine
comment with the trap left empty and asserts it is held for moderation
and absent from the spam list.

This behaviour is identical on `v3` and the `feature/honeypot-extended-validation`
branch, so it also serves as a stable regression guard for PR #656.
)

* Add `ab_spam__invalid_request` logic back to `precheck()` function

* test: cover honeypot precheck when hidden field is absent

The reworked `precheck()` treats a missing `comment` honeypot field
(`is_null($hidden_field)`) as spam, but that branch had no test. Add a
scenario where the secret field is present and the honeypot field is
entirely absent, asserting `ab_spam__hidden_field` is set.
* ci: add spell-checking workflow

* chore: add spellchecker config and update related ignore files

* chore: fix typos in comments, documentation, and configuration files

* chore: update comments for spellchecker directives in LangHelper
@jmslbam

jmslbam commented Jul 5, 2026

Copy link
Copy Markdown

Didn't now where to put the feedbac and maybe seperate issue, it's up to you, but here is my feedback https://toot.re/@2ndkauboy@dewp.space/116864017021004502
Danke!

@2ndkauboy

Copy link
Copy Markdown
Member

@jmslbam please feel free to open dedicated issues. Or just one with a collection of your findings.

This PR will likely not be merged finally, as I think conserving the current version in the old master branch and using v3 as the new development branch makes more sense.

* chore: remove unused imports, constants, and class properties

* chore(tests): update URLs and emails in e2e tests to use example.com

* chore(tests): update BBCode test URLs to use HTTPS

* chore: remove unused behat.sh script

* chore: remove unused behat.sh script

* chore: fix typos and improve grammar in README.md

* chore: remove docker-compose and update README with new local testing guide

* chore: add required PHP extensions and associated admin notices

* chore: simplify conditional checks across helper classes and rules

* chore(tests): add missing exception annotations and update docblocks

* chore(tests): replace deprecated PHPUnit TestListener with bootstrap

The `TestListener` interface and `TestListenerDefaultImplementation`
trait were deprecated in PHPUnit 9 and removed in PHPUnit 10. Move the
stub setup off the deprecated API:

- Autoload stub classes via Composer `autoload-dev.classmap`
- Load WP function stubs from a new `tests/bootstrap.php`
- Point `phpunit.xml.dist` at the new bootstrap and drop `<listeners>`
- Delete `tests/TestListener.php`

* chore: rename `$comment` to `$reaction` in `Comment` and `Linkback` handlers

* chore: update regex modifier in `IpHelper` for case-insensitivity

* chore(tests): replace `AntispamBeeTest` with `RegexpSpamTest` and update `phpunit.xml.dist`

* chore: update docblock typehint for `$controllables` parameter in `generate_fields` method

* chore: update Whois URL to use HTTPS in `SendEmail` post-processor

* chore(tests): remove unused `cli` parameter from e2e test definitions

* chore: simplify `parse_url` usage in `RegexpSpam` rule

* chore: simplify null coalescing in `CountrySpam` rule

* chore: inline `apply_filters` call in `ContentTypeHelper` for clarity

* chore: use imported constants and update type hints across multiple classes

* chore: remove unnecessary string cast

* chore: add `ReflectionException` to method docblocks for better exception handling visibility

* chore: update type hints in docblocks to use `class-string<Controllable>` for improved accuracy

* chore: define `ANTISPAM_BEE_LOG_FILE` constant in bootstrap file

* chore: update README for grammar, clarity, and consistency

* chore: update CHANGELOG for grammar, style, and consistency corrections

* chore: fix grammar and improve phrasing across comments and docblocks for clarity

* chore: fix grammar and consistency issues in CHANGELOG and documentation files

* chore: fix grammar and phrasing in comments and docblocks for consistency

* chore: remove unused imports and update docblocks with `ReflectionException` for clarity and accuracy

* chore: improve formatting, grammar, and consistency in comments, docblocks, and code alignment throughout the codebase

* chore: normalize PHPDoc grammar, articles, and mood across source

Fix residual typos (of/filter/Gravatar), add missing articles and trailing
periods, convert method summaries to imperative mood, replace bare "Class X"
summaries with descriptive phrases, and tidy @param/@return descriptions.

* chore(tests): fix typos and normalize assertion message casing

Correct "no"->"not" and "fiend"->"field", reword a backwards assertion
message, and capitalize PHPUnit assertion messages consistently.

* chore: normalize user-facing prose and terminology

Standardize "linkback", and "third-party" usage, fix grammar
and awkward FAQ wording, align duplicated bullet phrasings, and make Markdown
heading closers consistent. German sections left untouched.

* chore: use @phpstan-param for class-string generics instead of phpcs:ignore

Document the native `string` type in `@param` (satisfying PHPCS) and the
`class-string<Controllable>` generic in a `@phpstan-param` tag (honored by
PHPStan), removing the `Squiz.Commenting.FunctionComment.IncorrectTypeHint`
suppressions. Also adds missing articles to the docblocks in these files.

* chore: add missing articles in PHPDoc summaries and descriptions

Add the/a/an to imperative summaries and @param/@return descriptions, and
correct copy-paste docblock mislabels in the Tab and Section getters.

* chore: fix grammar, add missing articles, and improve phrasing in comments and PHPDoc

* chore: rename `$link1` to `$link` for consistency across rule descriptions

* chore: improve code alignment, formatting, and PHPDoc consistency

Ensure uniform alignment of array keys, parameters, and string concatenations. Replace misplaced comments, normalize PHPDoc formatting, remove redundant definitions, and fix minor grammatical inconsistencies in existing documentation.

* chore(tests): add parameters to stub functions for improved consistency and accuracy

* chore: adjust `WICHTIG` regex in `typos.toml` to match multiline patterns

* chore: apply review suggestions from PR #765

* chore: remove `@since` tags for classes and functions, keep them for hooks

* docs: add descriptions to `@return` tags for consistency

* chore: remove `@change` tags from class and function docblocks

* chore(tests): replace `array()` with short array syntax in unit tests

* chore: replace `array()` with short array syntax across plugin codebase

* chore: remove unnecessary parentheses in ternary operator for code clarity
* chore: update type hints and default handling for arrays and docblocks across multiple classes

* fix: resolve all PHPStan level 8 issues

Add precise iterable value types across the codebase and fix the
underlying type/logic problems surfaced at level 8.

- Type array docblocks: `array<string, mixed>` for reaction/item data,
  `string[]` for reason/type lists, `array<int, array<string, mixed>>`
  for option configs, `array<class-string<Controllable>>` for component
  lists.
- Thread `class-string<Controllable>` through `ComponentsHelper::filter`
  and the `get_controllables()` methods; fix `SettingsPage::$rules` and
  `$post_processors`, which hold class-strings, not instances.
- Treat `ANTISPAM_BEE_DEBUG_MODE_ENABLED` and `ANTISPAM_BEE_LOG_FILE` as
  `dynamicConstantNames` so their user-defined values are not narrowed.
- Fix latent bugs: DOM null-safety and argument types in `Honeypot`,
  unchecked `preg_match` in `IpHelper::anonymize_ip`, null spam-reason
  mapping key in `PluginUpdate::convert_multiselect_values`, null
  `$reaction_type` guard in `ComponentsHelper`, `comment_ID` cast in
  `Reaction`, `esc_url` protocols and `preg_split` handling in
  `LangSpam`/`CountrySpam`, offset/`iconv` safety in `RegexpSpam`, and
  the dead `Text::get_placeholder()` override.
- Use `@phpstan-param` annotations instead of `// phpcs:ignore`.

PHPStan level 8 and PHPCS both pass.

* refactor: remove unused `the_spam_count` method from `DashboardWidgets`

ref: 5906dcf
* refactor: build normalized rule payload in the reaction

Move responsibility for shaping rule input from the individual rules to the
`Reaction`. Each reaction now maps its own content onto a normalized payload
with generic keys (`reaction_type`, `ip`, `url`, `host`, `body`, `email`,
`author`, `useragent`, `post_id`) via a new `build_payload()` method, including
helper-based enrichment such as host parsing. Rules read only these generic
keys and no longer branch on the reaction type or know about WordPress
`comment_*` fields.

`Rules::apply()` becomes reaction-agnostic: it declares the canonical payload
attributes via the new `antispam_bee_payload_attributes` filter (documentation
only) and anonymizes sensitive keys for the debug log through the new
`antispam_bee_log_anonymized_attributes` filter, which also receives the
payload so callbacks can react on `reaction_type`.

Each rule documents the payload attributes it handles. Removes the now-unused
`DataHelper::get_values_by_keys()` and `get_values_where_key_contains()`.

* fix: carry linkback author into the normalized payload

`Linkback::build_payload()` set `author` to an empty string, so
`LinkbackPostTitleIsBlogName` — which compares the linkback's
`<strong>title</strong>` against `author` — never matched, and every
title-is-blog-name linkback slipped through. Map `author` from
`comment_author` (the linkback's blog name), mirroring `Comment::build_payload()`.

* test: cover linkback author payload mapping

Guards the `Linkback::build_payload()` fix: assert `author` is mapped from
`comment_author` (scalarised), so `LinkbackPostTitleIsBlogName` keeps matching.
* docs: add `@since` tags and full PHPDoc to `apply_filters()` hooks

Document every `apply_filters()` call with a complete PHPDoc block
(`@param`, `@return`) and a `@since` tag.

For filters that already exist on `master`, the version was traced to
the introducing commit and appended as a commit hash:

- `antispam_bee_notification_subject`, `antispam_bee_patterns`,
  `pre_comment_user_ip` – 2.6.7 (`d7b500c`)
- `antispam_bee_notification_recipients` – 2.8.0 (`f4718d6`)
- `antispam_bee_disallow_ajax_calls` – 2.9.4 (`dc60450`)
- `allow_empty_comment` – 2.11.0 (`1aaf8b1`)

All filters not present on `master` are tagged `@since 3.0.0`.

Also convert the non-standard `@hook` annotation on
`IpHelper::get_client_ip()` into a proper filter docblock placed
directly above the `pre_comment_user_ip` call.

* docs: align hook docblocks with WordPress documentation standards

Per the WordPress inline documentation standards for hooks
(https://developer.wordpress.org/coding-standards/inline-documentation-standards/php/):

- Remove `@return` from all hook docblocks. Filter hooks always return
  their first parameter, so `@return` is not used for hook documentation.
- Move `@since` above the `@param` block (order: summary, description,
  `@since`, `@param`).

Applies to every documented `apply_filters()` call, including the
pre-existing docblocks in `CountrySpam` and `LangSpam`.

* docs: remove commit hashes from `@since` tags in hook docblocks

Simplify documentation by removing commit hashes from `@since` tags in hook docblocks. Maintains version information for clarity.

* docs: document hook DocBlock standard in `AGENTS.md`

Add an 'Inline documentation' section describing how hooks must be
documented, following the WordPress PHP inline documentation standards
(placement, tag order, no `@return`, three-digit `@since`), with a link
to the standard.
The scalar-field bug this originally fixed is already resolved on v3 by the
normalized rule payload (#767); verify() now reads `url`/`post_id`. Keep the
regression coverage, rewritten against the normalized payload.
The rule builds a `rawurl` subject and ships a `rawurl` pattern (the Binance
referral URL), but `rawurl` was missing from the `$fields` allow-list, so those
patterns were silently skipped. Add it and cover the behaviour in the existing
RegexpSpam unit test (Binance referral + non-referral, porn/20bet author terms).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v3 This issue is for the new version (v3) of the plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants