VOOZH about

URL: https://deepwiki.com/MahoCommerce/maho-phpstan-plugin/4.3-mageinvalidtyperule

⇱ MageInvalidTypeRule | MahoCommerce/maho-phpstan-plugin | DeepWiki


Loading...
Menu

MageInvalidTypeRule

Purpose and Scope

MageInvalidTypeRule is a PHPStan validation rule that ensures Magento factory method calls (like Mage::getModel(), Mage::helper(), etc.) resolve to valid, existing class names. This rule complements the type inference system by detecting cases where Magento alias resolution fails or produces invalid types.

For information about how types are inferred before validation, see MageTypeExtension. For details about the alias resolution mechanism used by this rule, see MageCoreConfig.

Sources: src/Rules/MageInvalidTypeRule.php1-97


Overview

MageInvalidTypeRule operates as the validation phase of the type resolution pipeline. While MageTypeExtension infers return types from Magento factory methods, MageInvalidTypeRule verifies that these inferred types refer to classes that actually exist in the codebase. This prevents PHPStan from accepting invalid types that would cause runtime errors.

The rule triggers on method and static calls, checking the first argument (the Magento alias) against the resolved class name to ensure the class exists.

Sources: src/Rules/MageInvalidTypeRule.php18-25


Rule Implementation

PHPStan Rule Interface

MageInvalidTypeRule implements Rule<Node\Expr\CallLike>, which means it processes all call-like expressions (method calls, static calls, function calls) during PHPStan analysis.


Node Type Processing

The rule declares its node type via getNodeType():

MethodReturn ValuePurpose
getNodeType()Node\Expr\CallLike::classDeclares which AST node types this rule processes
processNode()arrayAnalyzes a node and returns error messages if validation fails

Sources: src/Rules/MageInvalidTypeRule.php27-30

Constructor Dependencies

The rule requires two dependencies injected via constructor:

DependencyTypePurpose
$exprPrinterExprPrinterFormats code expressions for error messages
$mageCoreConfigMageCoreConfigProvides access to Magento alias-to-class conversion functions

Sources: src/Rules/MageInvalidTypeRule.php23-25


Validation Process

Call Analysis Workflow


Sources: src/Rules/MageInvalidTypeRule.php32-95

Step-by-Step Validation Logic

Step 1: Filter Non-Relevant Nodes src/Rules/MageInvalidTypeRule.php34-42

The rule first filters out nodes that aren't relevant:

CheckCode LocationPurpose
Is MethodCall or StaticCall?Lines 34-36Only factory methods use these call types
Has Identifier name?Lines 37-38Ensures method name is statically known
Has at least one argument?Lines 40-42Factory methods require at least the alias argument

Step 2: Resolve Called Type src/Rules/MageInvalidTypeRule.php44-52

The rule determines what class/object the method is called on:


Step 3: Get Method Reflection src/Rules/MageInvalidTypeRule.php54-58

Uses PHPStan's scope to get the method reflection. If the method doesn't exist, the rule exits early (returns empty array).

Step 4: Check if Factory Method src/Rules/MageInvalidTypeRule.php60-67

Queries MageCoreConfig to determine if this method is a registered Magento factory method. If not, the rule exits early.

Step 5: Validate Each Alias src/Rules/MageInvalidTypeRule.php69-82

For each constant string value in the first argument:

  1. Call the converter function to get the class name
  2. Check if the class exists using class_exists()
  3. If the class doesn't exist, or if the converter returns false, add it to $invalidTypes[]

Step 6: Report Errors src/Rules/MageInvalidTypeRule.php84-94

If any invalid types were found, construct and return a rule error.

Sources: src/Rules/MageInvalidTypeRule.php32-95


Error Reporting

Error Message Format

When validation fails, the rule constructs an error using RuleErrorBuilder:

Call to {method_call_expression} resulted in invalid type {type1}|{type2}|...

Example Error Messages:

CodeError Message
Mage::getModel('invalid/alias')Call to Mage::getModel('invalid/alias') resulted in invalid type bool(false).
Mage::helper('nonexistent/helper')Call to Mage::helper('nonexistent/helper') resulted in invalid type bool(false).
$layout->createBlock('fake/block')Call to $layout->createBlock('fake/block') resulted in invalid type bool(false).

Sources: src/Rules/MageInvalidTypeRule.php88-94

Error Identifier

All errors from this rule use the identifier mage.invalidType, which allows users to:

  • Filter specific error types in PHPStan reports
  • Suppress these errors using PHPStan's ignore mechanisms
  • Track error trends over time

Sources: src/Rules/MageInvalidTypeRule.php93

Invalid Type Representations

The rule handles two types of validation failures:

Failure TypeRepresentationCause
Converter returns falsebool(false)Magento config couldn't resolve the alias
Class doesn't existThe class name itselfClass name was resolved but class file doesn't exist

Sources: src/Rules/MageInvalidTypeRule.php77-81


Supported Factory Methods

MageInvalidTypeRule validates all factory methods supported by MageCoreConfig. The rule delegates to MageCoreConfig::getClassNameConverterFunction() to determine which methods to validate.

Validated Method Patterns


Sources: src/Config/MageCoreConfig.php34-74 src/Rules/MageInvalidTypeRule.php60-67

Method Categories

CategoryExample MethodsConverter Function
ModelsMage::getModel('catalog/product')getConfig()->getModelClassName($alias)
Resource ModelsMage::getResourceModel('catalog/product')getConfig()->getResourceModelClassName($alias)
HelpersMage::helper('catalog')getConfig()->getHelperClassName($alias)
Blocks$layout->createBlock('catalog/product_view')getConfig()->getBlockClassName($alias)
Resource HelpersMage::getResourceHelper('catalog')getConfig()->getResourceHelperClassName($alias)
Node Classes$config->getNodeClassInstance('path')getConfig()->getNodeClassName($path)

Sources: src/Config/MageCoreConfig.php36-73


Integration with Type Inference

Relationship to MageTypeExtension

MageInvalidTypeRule and MageTypeExtension work together as complementary components:


Sources: src/Rules/MageInvalidTypeRule.php60-67 src/Type/MageTypeExtension.php (referenced in diagrams)

Shared Configuration

Both components share the same MageCoreConfig instance, ensuring consistency:

ComponentUses MageCoreConfig For
MageTypeExtensionResolving aliases to infer return types
MageInvalidTypeRuleRe-resolving aliases to validate the inferred types

The shared instance means:

  • Same resolution logic applies to both inference and validation
  • Changes to supported methods in MageCoreConfig automatically affect both components
  • The useLocalXml parameter affects both equally

Sources: src/Config/MageCoreConfig.php8-29 src/Rules/MageInvalidTypeRule.php23

When Validation Catches Errors

MageInvalidTypeRule catches several error scenarios:

ScenarioHow MageTypeExtension BehavesHow MageInvalidTypeRule Detects
Invalid alias (e.g., 'nonexistent/model')Returns generic object typeConverter returns false, reported as error
Typo in alias (e.g., 'catlog/product')Returns ObjectType with wrong nameclass_exists() fails, reported as error
Missing moduleReturns ObjectType but class doesn't existclass_exists() fails, reported as error
Non-constant alias (e.g., $variable)Cannot infer specific type, returns objectCannot validate (no constant strings), skips

Sources: src/Rules/MageInvalidTypeRule.php69-82


Registration and Configuration

Service Registration

The rule is registered in extension.neon:


Configuration Points:

ElementValuePurpose
Service classMaho\PHPStanPlugin\Rules\MageInvalidTypeRuleThe rule implementation
mageCoreConfig argument@mageCoreConfigInjects the shared config service
PHPStan tagphpstan.rules.ruleRegisters as a rule with PHPStan

Sources: extension.neon (referenced in diagrams), src/Rules/MageInvalidTypeRule.php23

No User Configuration

Unlike some other plugin components, MageInvalidTypeRule has no user-configurable parameters. Its behavior is entirely determined by:

  1. The methods registered in MageCoreConfig::getClassNameConverterFunction()
  2. The useLocalXml parameter inherited via MageCoreConfig
  3. Which classes actually exist in the analyzed codebase

Sources: src/Rules/MageInvalidTypeRule.php23-25


Implementation Details

Constant String Extraction

The rule only validates constant string values in the first argument:


This means:

CodeValidation Result
Mage::getModel('catalog/product')✅ Validated (constant string)
Mage::getModel("catalog/product")✅ Validated (constant string)
Mage::getModel($variable)⚠️ Not validated (not constant)
Mage::getModel($obj->getAlias())⚠️ Not validated (not constant)
Mage::getModel('catalog/' . 'product')✅ Validated if PHPStan can resolve

Sources: src/Rules/MageInvalidTypeRule.php69

Expression Printing

The rule uses ExprPrinter to format the method call in error messages:


This produces readable expressions in error messages, such as:

  • Mage::getModel('catalog/product')
  • $this->helper('catalog')
  • $layout->createBlock('core/template')

Sources: src/Rules/MageInvalidTypeRule.php91

Error Building

Errors are constructed using PHPStan's RuleErrorBuilder:


This provides:

  • Formatted error message
  • Custom error identifier for filtering
  • Proper integration with PHPStan's error reporting system

Sources: src/Rules/MageInvalidTypeRule.php89-93


Summary

MageInvalidTypeRule serves as the validation layer for Magento factory method type inference:

Key Responsibilities:

  • Validates that resolved class names from factory methods actually exist
  • Reports clear errors when invalid aliases are used
  • Complements MageTypeExtension by catching cases where type inference produces invalid results

Design Characteristics:

  • Implements PHPStan's Rule interface
  • Processes CallLike AST nodes (method and static calls)
  • Shares MageCoreConfig with type inference system for consistency
  • Only validates constant string arguments (runtime values cannot be checked)
  • Reports errors with custom mage.invalidType identifier

Integration Points:

  • Registered via extension.neon with phpstan.rules.rule tag
  • Depends on MageCoreConfig for alias resolution
  • Works in tandem with MageTypeExtension for complete type safety

Sources: src/Rules/MageInvalidTypeRule.php1-97 src/Config/MageCoreConfig.php1-76