Skip to content

docs(php): document every function and remove the blanket doc-comment suppressions - #178

Merged
TheAggressive merged 1 commit into
feat/locksfrom
chore/doc-comments
Oct 11, 2026
Merged

TheAggressive merged 1 commit into
feat/locksfrom
chore/doc-comments

Conversation

@TheAggressive

Copy link
Copy Markdown
Owner

Stacked on #177, which is stacked on #176. The diff here shows only the documentation pass. GitHub retargets the PR as the PRs below it merge.

Why

116 files under includes/ started with // phpcs:disable Squiz.Commenting.FunctionComment,Generic.Commenting.DocComment.MissingShort (often with FunctionCommentThrowTag too). That hid 1,378 findings:

Finding Count
Functions with no doc comment 401
Missing @param tags 567
Missing summaries 149
@param tags out of step with their signatures (wrong name or type) 155
Missing @throws 39
Other 67

What changed

  • Every blanket doc-comment disable is removed. PHPCS is clean across includes/ with the doc sniffs active. The database-boundary disables are unchanged; they're deliberate and documented.
  • Every function has a summary describing what it does, written per function, not templated. Accessors are summarized from their class and property, such as "The job's attempts."
  • Complete, ordered @param lists with the signature's types. Existing PHPStan generic types such as array<string, mixed> are kept. Descriptions are reused where they already existed, and written in the project's own vocabulary otherwise. Context-sensitive names get context-specific descriptions: for example, an audit $result versus a Compile_Result, or a job $state versus a campaign $state.
  • Interface implementations use {@inheritDoc}, so each port (*_Source, provider gateways) documents its contract once. phpcs.xml.dist enables Squiz's skipIfInheritdoc for these.
  • @throws on every function that throws.
  • Typed callable(...) and \Closure(...) signatures move to @phpstan-param, because Squiz's type-hint check can't parse them.

One behaviour-preserving code change

Once its documentation was accurate, Database_Values::decode_json() turned out to leak an undeclared \JsonException. It now reports malformed JSON as the \InvalidArgumentException it already documented, with the JsonException attached as the previous exception. The three repository hydrators that caught both types now catch the one. A malformed stored row still reads as null; Campaign_Operation_Repository_Test covers this with a {broken context row.

Verification

  • pnpm qa:fast passes, including PHPCS over includes/, src/, campaignbridge.php, and uninstall.php.
  • PHPStan reports no errors.
  • Unit (1126), integration (458), and security (117) suites: all pass.

🤖 Generated with Claude Code

… suppressions

116 files under includes/ disabled Squiz.Commenting.FunctionComment,
Generic.Commenting.DocComment.MissingShort, and FunctionCommentThrowTag at
the top of the file, which hid 1,378 findings: 401 functions with no doc
comment, 567 missing @PARAM tags, and tags that no longer matched their
signatures. Every one of those disables is removed and the code is now
documented instead:

- Each function has a summary describing what it does, and a complete,
  ordered @PARAM list with the signature's types (keeping the existing
  PHPStan generic types) and a description.
- Interface implementations use {@inheritdoc}, so each port documents its
  contract once; phpcs.xml.dist enables Squiz's skipIfInheritdoc for them.
- Every exception a function throws has a @throws tag.
- Typed callable and Closure signatures move to @phpstan-param, which
  Squiz's type-hint check cannot parse.

Database_Values::decode_json() now reports malformed JSON as the
InvalidArgumentException it already documented, with the JsonException as
the previous exception, instead of leaking an undeclared exception type;
the three repository hydrators that caught both now catch the one.
Database-boundary disables are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TheAggressive
TheAggressive merged commit 4d7205a into feat/locks Oct 11, 2026
17 checks passed
@TheAggressive
TheAggressive deleted the chore/doc-comments branch October 11, 2026 10:50
TheAggressive added a commit that referenced this pull request Oct 11, 2026
… suppressions (#178)

116 files under includes/ disabled Squiz.Commenting.FunctionComment,
Generic.Commenting.DocComment.MissingShort, and FunctionCommentThrowTag at
the top of the file, which hid 1,378 findings: 401 functions with no doc
comment, 567 missing @PARAM tags, and tags that no longer matched their
signatures. Every one of those disables is removed and the code is now
documented instead:

- Each function has a summary describing what it does, and a complete,
  ordered @PARAM list with the signature's types (keeping the existing
  PHPStan generic types) and a description.
- Interface implementations use {@inheritdoc}, so each port documents its
  contract once; phpcs.xml.dist enables Squiz's skipIfInheritdoc for them.
- Every exception a function throws has a @throws tag.
- Typed callable and Closure signatures move to @phpstan-param, which
  Squiz's type-hint check cannot parse.

Database_Values::decode_json() now reports malformed JSON as the
InvalidArgumentException it already documented, with the JsonException as
the previous exception, instead of leaking an undeclared exception type;
the three repository hydrators that caught both now catch the one.
Database-boundary disables are unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
TheAggressive added a commit that referenced this pull request Oct 11, 2026
* feat(jobs): per-campaign and per-remote-operation locks

Two workers, or a worker and an operator, can no longer act on the same
campaign or the same provider list at once.

- Schema 8 adds {prefix}campaignbridge_locks. Acquiring inserts the name,
  so the primary key admits one holder; taking over an expired lock is a
  conditional update with one winner; only the holder can release.
- Lock_Manager holds the lock for a whole operation, provider calls
  included, and releases it in finally. A caller that finds it held does
  nothing and gets the new `locked` workflow error (REST 409) with
  retry_after, the seconds until the lock expires. A lock left by a process
  that stopped expires after five minutes and the takeover is audited.
- Draft handoff, test send, schedule, unschedule, send, and reconcile hold
  the campaign lock; a discovery refresh holds a lock per account and list
  and, when one is already running, returns the cached list with a
  retryable refusal instead of calling the provider again.
- The campaign timeline labels a takeover "Recovered an interrupted
  operation" with the operation that stopped.

Verified on MySQL and on the Studio SQLite site.

Closes #169

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(php): document every function and remove the blanket doc-comment suppressions (#178)

116 files under includes/ disabled Squiz.Commenting.FunctionComment,
Generic.Commenting.DocComment.MissingShort, and FunctionCommentThrowTag at
the top of the file, which hid 1,378 findings: 401 functions with no doc
comment, 567 missing @PARAM tags, and tags that no longer matched their
signatures. Every one of those disables is removed and the code is now
documented instead:

- Each function has a summary describing what it does, and a complete,
  ordered @PARAM list with the signature's types (keeping the existing
  PHPStan generic types) and a description.
- Interface implementations use {@inheritdoc}, so each port documents its
  contract once; phpcs.xml.dist enables Squiz's skipIfInheritdoc for them.
- Every exception a function throws has a @throws tag.
- Typed callable and Closure signatures move to @phpstan-param, which
  Squiz's type-hint check cannot parse.

Database_Values::decode_json() now reports malformed JSON as the
InvalidArgumentException it already documented, with the JsonException as
the previous exception, instead of leaking an undeclared exception type;
the three repository hydrators that caught both now catch the one.
Database-boundary disables are unchanged.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant