Skip to content

Add a rector to replace hardcoded rightnames - #12

Open
cedric-anne wants to merge 3 commits into
mainfrom
feature/hardcoded-rightnames
Open

Add a rector to replace hardcoded rightnames#12
cedric-anne wants to merge 3 commits into
mainfrom
feature/hardcoded-rightnames

Conversation

@cedric-anne

@cedric-anne cedric-anne commented Jul 29, 2026

Copy link
Copy Markdown
Member

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:

  • rightnames that may correspond to an abstract class rightname, e.g. dropdown (the concrete class should be targeted instead);
  • rightnames that may match multiple classes, e.g. contact_enterprise that matches Contact::$rightname and Supplier::$rightname;
  • rightnames related to class that have a specific case (not matching ucfirst($rightname)), e.g. QueuedNotification::$rightname.

With this, only 50 occurences remains in GLPI itself.

@cedric-anne cedric-anne self-assigned this Jul 29, 2026
@cedric-anne
cedric-anne requested a review from SebSept July 29, 2026 13:08
* @var array<string, ?string>
*/
private const MAPPING = [
'contact_enterprise' => null, // too ambiguous

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: gvengiven.

Suggested change
// Process only gven methods
// Process only given methods

@cedric-anne
cedric-anne requested a review from SebSept July 30, 2026 12:14

@SebSept SebSept left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reported problems are solved.
lgtm.

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.

2 participants