Add a rector to replace hardcoded rightnames - #12
Conversation
| * @var array<string, ?string> | ||
| */ | ||
| private const MAPPING = [ | ||
| 'contact_enterprise' => null, // too ambiguous |
There was a problem hiding this comment.
null represents the fact that these strings should be left untouched.
That is currently the outcome, but nothing in the code enforces it: none of these strings
resolves to a CommonGLPI class through ucfirst(), so the first
replacement try, line 118
fails on its own. MAPPING is only consulted once the decision to replace has already been
made, so the null marker can never prevent anything. The
hardcoded-string-matching-mapping.php.inc fixture passes for that same accidental reason, so
it does not actually cover the null entries.
You can verify it by adding this stub:
<?php
declare(strict_types=1);
class Dropdown extends CommonGLPI
{
public static string $rightname = 'dropdown';
}Then regenerate the autoloader — stubs/ is loaded through autoload-dev.classmap, so the
class stays invisible and the test wrongly passes without this step:
composer dump-autoload && vendor/bin/phpunit
The fixture now fails: 'dropdown' is replaced by \Dropdown::$rightname despite the null
marker. Dropdown is not a CommonGLPI in GLPI today, so this is only a demonstration — but
the same holds for every null entry, none of which is actually protected.
The code should explicitly prevent this, by returning null when a hardcoded string matches a
mapping entry with a null value.
There was a problem hiding this comment.
stubs/Rack.php declares class Rack without extending CommonGLPI, so the hardcoded-string-not-matching-property-value fixture doesn't test what its comment claims.
The condition is a short-circuiting &&:
if (\is_a($expected_class, 'CommonGLPI', true) && $expected_class::$rightname === $hardcoded_value) {
// ^ 'Rack' is not a CommonGLPI -> false
// ^ never evaluated The fixture stops at the first guard, taking the exact same path as the bar fixture ("unknown class"), so the rightname comparison — the guard the fixture is named after — is never exercised.
Proof by mutation: dropping && $expected_class::$rightname === $hardcoded_value from the rule keeps the whole suite green (16/16). A test that stays green when you delete t
| } | ||
|
|
||
| if ($this->isNames($node->name, ['checkRight', 'checkRightsOr', 'haveRight', 'haveRightsAnd', 'haveRightsOr']) === false) { | ||
| // Process only gven methods |
There was a problem hiding this comment.
Typo: gven → given.
| // Process only gven methods | |
| // Process only given methods |
This rector will replace most occurences of hardcoded rightnames detected by the PHPStan rule introduced in glpi-project/phpstan-glpi#25 .
The following cases are not handled:
dropdown(the concrete class should be targeted instead);contact_enterprisethat matchesContact::$rightnameandSupplier::$rightname;ucfirst($rightname)), e.g.QueuedNotification::$rightname.With this, only 50 occurences remains in GLPI itself.