Skip to content

fix(quality): phpmd DevelopmentCodeFragment could never fire on namespaced code - #17

Merged
rubenvdlinde merged 1 commit into
developmentfrom
fix/phpmd-ignore-namespaces
Aug 3, 2026
Merged

fix(quality): phpmd DevelopmentCodeFragment could never fire on namespaced code#17
rubenvdlinde merged 1 commit into
developmentfrom
fix/phpmd-ignore-namespaces

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

The hole

Every Conduction repo enables rulesets/design.xml/DevelopmentCodeFragment — the
rule that is supposed to stop var_dump() / print_r() / var_export() shipping
in production code. It has never reported anything, in any repo.

The cause is a config gap, not a phpmd bug. PDepend resolves an unqualified
call inside a namespaced file to the current-namespace-qualified image, so:

namespace OCA\MyApp\Service;
...
var_dump($x);          // reaches the rule as OCA\MyApp\Service\var_dump

…which never matches the rule's unwanted-functions list. All of our production
PHP is namespaced, so with the default (ignore-namespaces=false) the rule is
dead everywhere. The fleet has had no composer check:strict protection
against shipped debug helpers
.

The rule's own ignore-namespaces property is the switch. This PR copies the
configuration already merged in openregister (ConductionNL/openregister#2286).

Proof it now fires

phpmd 2.15.0 / PHP 8.3.32, run against this repo's own phpmd.xml, using a
byte-identical pair of namespaced probe classes:

probe before after
namespaced class calling var_dump() exit 0, no finding exit 2, DevelopmentCodeFragment
same class, call removed exit 0 exit 0, no finding

Both directions are checked deliberately: a repair that only shows "something
failed" cannot distinguish a working rule from a noisy one.

Blast radius: 0 new findings

Measured, not assumed. The rule was run in isolation over this repo's scanned
path at the base branch before the flip: 0 findings.

The zero carries a per-run positive control — the namespaced probe was dropped
into the same extracted tree and did produce exit 2, so this is a true zero and
not a harness that silently analysed nothing. An independent git grep for
var_dump|print_r|dd|dump across lib/ agrees. Nothing is baselined or
suppressed by this PR.

Note on overlap with hydra gate 2

hydra-gate-forbidden-patterns independently greps lib/ for
var_dump / die / error_log / print_r / dd / dump, and is the broader control —
it also catches calls made outside a method body, which DevelopmentCodeFragment
(a MethodAware/FunctionAware rule) structurally cannot see. That gate is why the
measured count is 0: it has been holding this line alone. This rule is the
composer check:strict half of the same guard. Keep both.

⚠️ This repo has no CI phpmd gate

This repo does not call the shared quality workflow, so composer phpmd
is not executed in CI here. This change fixes composer check:strict when run
locally and stops the broken configuration propagating — it does not by itself
add a CI gate.
Wiring one up is separate follow-up work.

…paced code

Every Conduction repo enables rulesets/design.xml/DevelopmentCodeFragment, and
it has never reported anything in any of them. The cause is a config gap, not a
phpmd bug: PDepend resolves an unqualified call inside a namespaced file to the
current-namespace-qualified image, so `var_dump($x)` written inside
`namespace OCA\MyApp\Service;` reaches the rule as
`OCA\MyApp\Service\var_dump` and never matches the `unwanted-functions` list.
All of our production PHP is namespaced, so with the default the rule is dead.

The rule's own `ignore-namespaces` property is the switch. This mirrors the
configuration already merged in openregister (ConductionNL/openregister#2286).

Proof, phpmd 2.15.0 / PHP 8.3.32, against this repo's own phpmd.xml:
  namespaced probe class calling var_dump()  -> exit 2, DevelopmentCodeFragment
  same class with the call removed           -> exit 0, no finding
Before the change the identical namespaced probe exited 0.

Blast radius on this repo: measured 0 new findings over the scanned path on
the base branch, with a per-run positive control (dropping the namespaced probe
into the same extracted tree does produce exit 2, so the zero is a true zero).
Nothing is baselined or suppressed here.

Note: this repo does not run the shared quality workflow, so phpmd is not
executed in CI here. This change fixes `composer check:strict` when run locally
and stops the broken configuration propagating; it does not by itself add a CI
gate.
@rubenvdlinde
rubenvdlinde merged commit ed98c47 into development Aug 3, 2026
1 check passed
@rubenvdlinde
rubenvdlinde deleted the fix/phpmd-ignore-namespaces branch August 14, 2026 09:41
@rubenvdlinde
rubenvdlinde restored the fix/phpmd-ignore-namespaces branch August 19, 2026 16:28
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