VOOZH about

URL: https://deepwiki.com/MahoCommerce/maho-phpstan-plugin/4.1-magetypeextension

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


Loading...
Menu

MageTypeExtension

Purpose and Scope

MageTypeExtension is the core type inference component that enables PHPStan to understand Magento/Maho factory method return types. When analyzing code that calls methods like Mage::getModel('catalog/product'), $block->getChild('name'), or $model->getResource(), this extension resolves the Magento-style string aliases to concrete PHP class types.

This page documents the technical implementation and configuration of MageTypeExtension. For information about the underlying configuration system that resolves class aliases, see MageCoreConfig. For validation of resolved types, see MageInvalidTypeRule.

Sources: src/Type/MageTypeExtension.php1-91 extension.neon19-47

PHPStan Integration

MageTypeExtension implements two PHPStan extension interfaces:

  • DynamicStaticMethodReturnTypeExtension - for static method calls like Mage::getModel()
  • DynamicMethodReturnTypeExtension - for instance method calls like $block->getChild()

Both interfaces require the extension to determine whether it supports a given method and, if so, provide the inferred return type. The extension delegates both static and instance method handling to the same internal logic.


Diagram: PHPStan Extension Interface Implementation

Sources: src/Type/MageTypeExtension.php20 src/Type/MageTypeExtension.php81-89

Service Registration

The plugin registers four separate instances of MageTypeExtension, each configured for a different class and PHPStan tag. This multi-instance pattern allows the same extension logic to handle factory methods across different parts of the Magento framework.

InstanceTarget ClassPHPStan TagMethods Handled
#1Magephpstan.broker.dynamicStaticMethodReturnTypeExtensiongetModel(), getHelper(), getSingleton(), getResourceModel(), getResourceSingleton()
#2Mage_Core_Block_Abstractphpstan.broker.dynamicMethodReturnTypeExtensiongetChild(), getChildBlock(), getParentBlock(), getHelper()
#3Mage_Core_Model_Abstractphpstan.broker.dynamicMethodReturnTypeExtensiongetResource(), getResourceCollection(), getHelper()
#4Mage_Core_Model_Layoutphpstan.broker.dynamicMethodReturnTypeExtensiongetBlock(), createBlock(), getHelper()

Diagram: Service Registration and Dependency Injection

Sources: extension.neon14-47

Class Structure

The MageTypeExtension class is declared as final and maintains two private properties injected via constructor:






















PropertyTypePurpose
$classNameclass-stringThe target class this instance handles (e.g., Mage, Mage_Core_Block_Abstract)
$mageCoreConfigMageCoreConfigConfiguration service that provides class name converter functions

Sources: src/Type/MageTypeExtension.php20-27

Method Support Detection

The extension determines whether it can handle a particular method by querying MageCoreConfig for a converter function and checking if it's callable.


Diagram: Method Support Detection Flow

The isMethodSupported() and isStaticMethodSupported() methods both delegate to the same logic:

src/Type/MageTypeExtension.php37-45

public function isMethodSupported(MethodReflection $methodReflection): bool
{
 $fn = $this->mageCoreConfig->getClassNameConverterFunction(
 $methodReflection->getDeclaringClass()->getName(),
 $methodReflection->getName()
 );

 return is_callable($fn);
}

src/Type/MageTypeExtension.php81-84

public function isStaticMethodSupported(MethodReflection $methodReflection): bool
{
 return $this->isMethodSupported($methodReflection);
}

Sources: src/Type/MageTypeExtension.php37-45 src/Type/MageTypeExtension.php81-84

Type Resolution Algorithm

When PHPStan encounters a supported method call, MageTypeExtension performs the following steps:

  1. Validate Arguments: Return ConstantBooleanType(false) if no arguments provided
  2. Retrieve Converter Function: Get the class name converter from MageCoreConfig
  3. Extract Alias Values: Analyze the first argument to get all possible string values
  4. Convert Each Alias: Call the converter function for each alias string
  5. Validate Class Existence: Check if the resolved class name exists
  6. Build Return Types: Create ObjectType for valid classes, ConstantBooleanType(false) for invalid
  7. Combine Types: Union all return types together

Diagram: Complete Type Resolution Sequence

Sources: src/Type/MageTypeExtension.php47-79 src/Type/MageTypeExtension.php86-89

Return Type Behavior

The extension produces different return types based on the resolution outcome:

Successful Resolution

When a class alias resolves to an existing class:

$model = Mage::getModel('catalog/product');
// Inferred type: Mage_Catalog_Model_Product

Result: ObjectType('Mage_Catalog_Model_Product')

src/Type/MageTypeExtension.php66-68

Failed Resolution

When a class alias cannot be resolved or the class doesn't exist:

$model = Mage::getModel('invalid/alias');
// Inferred type: false

Result: ConstantBooleanType(false)

src/Type/MageTypeExtension.php70

No Arguments

When the method is called without arguments:

$model = Mage::getModel();
// Inferred type: false

Result: ConstantBooleanType(false)

src/Type/MageTypeExtension.php49-51

Multiple Possible Values

When the argument could be multiple string values:

$alias = $someCondition ? 'catalog/product' : 'catalog/category';
$model = Mage::getModel($alias);
// Inferred type: Mage_Catalog_Model_Product|Mage_Catalog_Model_Category

Result: Union type combining all resolved types

src/Type/MageTypeExtension.php78

Fallback to Original

If no constant strings can be extracted from the argument, the extension falls back to the method's declared return type:

src/Type/MageTypeExtension.php74-76

if (count($returnTypes) === 0) {
 $returnTypes[] = $methodReflection->getVariants()[0]->getReturnType();
}

Sources: src/Type/MageTypeExtension.php47-79

Integration with Validation

While MageTypeExtension resolves types optimistically (checking class_exists() inline), the MageInvalidTypeRule performs comprehensive validation of these resolutions during analysis. This separation allows the type extension to provide immediate feedback while the rule enforces strict validation policies.


Diagram: Type Extension and Validation Rule Interaction

Sources: extension.neon19-55

Error Handling

The extension throws ShouldNotHappenException if getClassNameConverterFunction() returns a non-callable value despite isMethodSupported() previously returning true. This indicates an internal inconsistency in the extension's state.

src/Type/MageTypeExtension.php58-60

if (!is_callable($fn)) {
 throw new ShouldNotHappenException();
}

This should theoretically never occur because PHPStan only calls getTypeFromMethodCall() / getTypeFromStaticMethodCall() after isMethodSupported() / isStaticMethodSupported() returns true.

Sources: src/Type/MageTypeExtension.php58-60