Enforce self:: for own-hierarchy class constants with a PHPStan rule
### Overview Inherited (or own) class constants are sometimes referenced by an explicit ancestor class name — e.g. `CanvasKernelTestBase::CANVAS_KERNEL_TEST_MINIMAL_MODULES` from a subclass — instead of `self::`. This is redundant, and it drifts when a class is renamed. There is no automated guard, so occurrences slip in and are only caught by manual review (spotted while reviewing #3573022). ### Proposed resolution Add a custom PHPStan rule (`Canvas\PHPStan\Rules\SelfConstantReferenceRule`) that flags `Ancestor::CONST` where the referenced class is the analyzed class or one of its parent classes, and suggests `self::`. It deliberately does **not** flag, to stay behavior-preserving and idiomatic: - trait bodies — `self::` resolves against each using class, so the explicit reference is the correct choice there; - interface constants (`SomeInterface::CONST`) — naming the interface documents the contract; - enum cases (`SomeEnum::Case`) — referencing a case by the enum name is the idiomatic style; - `SomeClass::class` — `Ancestor::class` is not equal to `self::class`; - shadowed constants — where an override makes `self::CONST` resolve to a different value than `Ancestor::CONST`. Register it under `rules:` in `phpstan.neon` and fix the existing occurrences so CI stays green. ### Remaining tasks - Add the rule and register it in `phpstan.neon`. - Fix the 4 existing violations (all the `CanvasKernelTestBase::CANVAS_KERNEL_TEST_MINIMAL_MODULES` pattern, in `canvas_ai` and translation test classes). ### User interface changes None. ### API changes None.
issue