VOOZH about

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

⇱ MahoCommerce/maho-phpstan-plugin | DeepWiki


Loading...
Menu

Overview

Purpose and Scope

This document provides a high-level introduction to the maho-phpstan-plugin, a PHPStan extension that enables static analysis of Maho and Magento codebases. It explains the problems the plugin solves, its architecture, and how it integrates with PHPStan.

For installation instructions, see Installation. For detailed architecture information, see Architecture. For information about specific components, see Type Inference System and Reflection Extensions.

Sources: README.md1-4 composer.json1-31 extension.neon1-71

What is maho-phpstan-plugin?

The maho-phpstan-plugin is a PHPStan extension designed to bridge the gap between PHPStan's static analysis capabilities and Maho/Magento's highly dynamic architecture. PHPStan is a powerful static analysis tool for PHP, but it cannot natively understand Magento's unique patterns such as factory methods, magic methods, and template scoping.

This plugin extends PHPStan by implementing multiple extension points that teach the analyzer how to interpret Magento-specific code patterns, allowing it to infer accurate types and validate code correctness in Maho/Magento projects.

The plugin is distributed as a Composer package with type: phpstan-extension, which PHPStan automatically discovers and loads via the configuration declared in composer.json.

Sources: composer.json2-4 composer.json24-30

Problems Solved

Factory Method Type Resolution

Magento uses string-based factory methods throughout its codebase where the return type depends on a runtime string parameter:


PHPStan cannot determine the return type of these methods without understanding Magento's alias resolution system. The plugin resolves these aliases to concrete class names.

Sources: extension.neon19-47

Magic Method Support

Magento's Varien_Object base class implements magic methods that allow property access via getFoo(), setBar(), hasBaz(), and unsetQux() without explicit method definitions. PHPStan would report these as undefined methods without the plugin's intervention.


Sources: extension.neon57-63

Template Scope Issues

Magento template files (.phtml) and data install scripts use $this to reference the block or setup class, often accessing protected methods. PHPStan strictly enforces visibility rules, which would prevent analysis of these files. The plugin transforms the scope to allow access while maintaining type safety.


Sources: extension.neon65-70

Architecture Overview

The plugin consists of three major subsystems that work together to analyze Maho/Magento code:


Diagram: Plugin Integration with PHPStan

Sources: extension.neon1-71 composer.json14-30

Type Inference System

The type inference system resolves Magento's factory method calls to concrete types. It consists of:

  • MageTypeExtension: Four instances handle different factory patterns (Mage::getModel(), Mage::getSingleton(), block methods, model methods, and layout methods)
  • MageCoreConfig: Central service that resolves Magento class aliases to fully-qualified class names
  • MageInvalidTypeRule: Validates that resolved class names refer to existing classes

See Type Inference System for details.

Sources: extension.neon14-55

Reflection Extensions

The reflection system handles Magento's dynamic method and scope patterns:

  • VarienObjectReflectionExtension: Implements phpstan.broker.methodsClassReflectionExtension to add magic method support for Varien_Object descendants
  • BindThisScopeResolverExtension: Implements phpstan.parser.richParserNodeVisitor and phpstan.phpDoc.typeNodeResolverExtension to handle template scope issues

See Reflection Extensions for details.

Sources: extension.neon57-70

Mock Framework

The mock framework provides stub implementations of Maho/Magento core classes that the plugin queries during type resolution. These mocks simulate the behavior of Mage::app()->getConfig() and related methods without requiring a full Magento installation.

See Mock Framework for details.

Sources: extension.neon9-11 composer.json19-23

Component Interaction Flow

The following diagram shows how components interact during a typical analysis:


Diagram: Component Interaction During Analysis

Sources: extension.neon19-63

PHPStan Integration Points

The plugin integrates with PHPStan through six different extension mechanisms, each serving a specific purpose:

Extension TagComponentPurpose
phpstan.broker.dynamicStaticMethodReturnTypeExtensionMageTypeExtension (Mage)Resolves Mage::getModel(), Mage::getSingleton(), etc.
phpstan.broker.dynamicMethodReturnTypeExtensionMageTypeExtension (blocks)Resolves block factory methods like createBlock()
phpstan.broker.dynamicMethodReturnTypeExtensionMageTypeExtension (models)Resolves model factory methods
phpstan.broker.dynamicMethodReturnTypeExtensionMageTypeExtension (layout)Resolves layout factory methods like createBlock()
phpstan.rules.ruleMageInvalidTypeRuleValidates resolved types exist
phpstan.broker.methodsClassReflectionExtensionVarienObjectReflectionExtensionAdds magic method support
phpstan.parser.richParserNodeVisitorBindThisScopeResolverExtensionTransforms template scope
phpstan.phpDoc.typeNodeResolverExtensionBindThisScopeResolverExtensionResolves custom type node

Sources: extension.neon25-70

Configuration

The plugin is configured through extension.neon, which defines three user-configurable parameters:

ParameterTypeDefaultPurpose
useLocalXmlboolfalseWhether to use local.xml configuration files
enforceMagicMethodDocBlockboolfalseWhether to require docblocks for magic methods
magentoRootPathstring|nullnull(Deprecated) Path to Magento root

The configuration also specifies scan directories that include the mock framework files needed for type resolution.

See Configuration for details on using these parameters.

Sources: extension.neon1-11

Key Code Entities

The following table maps conceptual components to their code entities:

ConceptClass/FileLocation
Central Configurationextension.neonextension.neon1-71
Package Definitioncomposer.jsoncomposer.json1-31
Type InferenceMaho\PHPStanPlugin\Type\MageTypeExtensionsrc/Type/MageTypeExtension.php
Alias ResolutionMaho\PHPStanPlugin\Config\MageCoreConfigsrc/Config/MageCoreConfig.php
Type ValidationMaho\PHPStanPlugin\Rules\MageInvalidTypeRulesrc/Rules/MageInvalidTypeRule.php
Magic MethodsMaho\PHPStanPlugin\Reflection\VarienObjectReflectionExtensionsrc/Reflection/VarienObjectReflectionExtension.php
Template ScopeMaho\PHPStanPlugin\PhpDoc\BindThisScopeResolverExtensionsrc/PhpDoc/BindThisScopeResolverExtension.php
Core MockMagemock/maho-phpstan-plugin/Mage.php

Sources: extension.neon14-70 composer.json14-23

How the Plugin is Discovered

PHPStan automatically discovers and loads the plugin through the following mechanism:


Diagram: Plugin Discovery and Loading Process

When a project includes mahocommerce/maho-phpstan-plugin as a dependency, PHPStan detects the phpstan-extension package type and automatically loads the configuration file specified in the extra.phpstan.includes array. This configuration registers all plugin services with PHPStan's dependency injection container.

Sources: composer.json4 composer.json24-30

Development and Quality

The plugin maintains high code quality through:

  • Self-analysis: The plugin analyzes its own code using PHPStan at level 10 (maximum strictness)
  • Strict rules: Includes phpstan/phpstan-strict-rules and phpstan/phpstan-deprecation-rules as development dependencies
  • CI/CD: GitHub Actions workflow tests the plugin across multiple PHP versions (8.3, 8.4, 8.5)

See Development and Contributing for details on contributing to the plugin.

Sources: composer.json6-12

Next Steps

To start using the plugin, proceed to Getting Started for installation and configuration instructions.

For a deeper understanding of the architecture, see Architecture.

To understand specific subsystems: