class PluginManagerInspectionRule
@implements \PHPStan\Rules\Rule<\PhpParser\Node\Stmt\Class_>
Hierarchy
- class \mglaman\PHPStanDrupal\Rules\Classes\PluginManagerInspectionRule implements \PHPStan\Rules\Rule
Expanded class hierarchy of PluginManagerInspectionRule
File
-
vendor/
mglaman/ phpstan-drupal/ src/ Rules/ Classes/ PluginManagerInspectionRule.php, line 15
Namespace
mglaman\PHPStanDrupal\Rules\ClassesView source
class PluginManagerInspectionRule implements Rule {
/** @var ReflectionProvider */
private $reflectionProvider;
public function __construct(ReflectionProvider $reflectionProvider) {
$this->reflectionProvider = $reflectionProvider;
}
public function getNodeType() : string {
return Node\Stmt\Class_::class;
}
public function processNode(Node $node, Scope $scope) : array {
if ($node->namespacedName === null) {
// anonymous class
return [];
}
if ($node->extends === null) {
return [];
}
$className = (string) $node->namespacedName;
$pluginManagerType = new ObjectType($className);
$pluginManagerInterfaceType = new ObjectType('\\Drupal\\Component\\Plugin\\PluginManagerInterface');
if (!$pluginManagerInterfaceType->isSuperTypeOf($pluginManagerType)
->yes()) {
return [];
}
$errors = [];
if ($this->isYamlDiscovery($node)) {
$errors = $this->inspectYamlPluginManager($node);
}
else {
// @todo inspect annotated plugin managers.
}
$hasAlterInfoSet = false;
foreach ($node->stmts as $stmt) {
if ($stmt instanceof Node\Stmt\ClassMethod && $stmt->name
->toString() === '__construct') {
foreach ($stmt->stmts ?? [] as $statement) {
if ($statement instanceof Node\Stmt\Expression) {
$statement = $statement->expr;
}
if ($statement instanceof Node\Expr\MethodCall && $statement->name instanceof Node\Identifier && $statement->name->name === 'alterInfo') {
$hasAlterInfoSet = true;
}
}
}
}
if (!$hasAlterInfoSet) {
$errors[] = 'Plugin definitions cannot be altered.';
}
return $errors;
}
private function isYamlDiscovery(Node\Stmt\Class_ $class) : bool {
foreach ($class->stmts as $stmt) {
// YAML discovery plugin managers must override getDiscovery.
if ($stmt instanceof Node\Stmt\ClassMethod && $stmt->name
->toString() === 'getDiscovery') {
foreach ($stmt->stmts ?? [] as $methodStmt) {
if ($methodStmt instanceof Node\Stmt\If_) {
foreach ($methodStmt->stmts as $ifStmt) {
if ($ifStmt instanceof Node\Stmt\Expression) {
$ifStmtExpr = $ifStmt->expr;
if ($ifStmtExpr instanceof Node\Expr\Assign) {
$ifStmtExprVar = $ifStmtExpr->var;
if ($ifStmtExprVar instanceof Node\Expr\PropertyFetch && $ifStmtExprVar->var instanceof Node\Expr\Variable && $ifStmtExprVar->name instanceof Node\Identifier && $ifStmtExprVar->name->name === 'discovery') {
$ifStmtExprExpr = $ifStmtExpr->expr;
if ($ifStmtExprExpr instanceof Node\Expr\New_ && $ifStmtExprExpr->class instanceof Node\Name && $ifStmtExprExpr->class
->toString() === 'Drupal\\Core\\Plugin\\Discovery\\YamlDiscovery') {
return true;
}
}
}
}
}
}
}
}
}
return false;
}
private function inspectYamlPluginManager(Node\Stmt\Class_ $class) : array {
$errors = [];
$fqn = (string) $class->namespacedName;
$reflection = $this->reflectionProvider
->getClass($fqn);
$constructor = $reflection->getConstructor();
if ($constructor->getDeclaringClass()
->getName() !== $fqn) {
$errors[] = sprintf('%s must override __construct if using YAML plugins.', $fqn);
}
else {
foreach ($class->stmts as $stmt) {
if ($stmt instanceof Node\Stmt\ClassMethod && $stmt->name
->toString() === '__construct') {
foreach ($stmt->stmts ?? [] as $constructorStmt) {
if ($constructorStmt instanceof Node\Stmt\Expression) {
$constructorStmt = $constructorStmt->expr;
}
if ($constructorStmt instanceof Node\Expr\StaticCall && $constructorStmt->class instanceof Node\Name && (string) $constructorStmt->class === 'parent' && $constructorStmt->name instanceof Node\Identifier && $constructorStmt->name->name === '__construct') {
$errors[] = sprintf('YAML plugin managers should not invoke its parent constructor.');
}
}
}
}
}
return $errors;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary |
---|---|---|---|
PluginManagerInspectionRule::$reflectionProvider | private | property | @var ReflectionProvider |
PluginManagerInspectionRule::getNodeType | public | function | |
PluginManagerInspectionRule::inspectYamlPluginManager | private | function | |
PluginManagerInspectionRule::isYamlDiscovery | private | function | |
PluginManagerInspectionRule::processNode | public | function | |
PluginManagerInspectionRule::__construct | public | function |