VOOZH about

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

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


Loading...
Menu

Architecture

Purpose and Scope

This document provides an overview of the maho-phpstan-plugin's architecture, including its major subsystems, configuration structure, and integration points with PHPStan. It explains how the plugin is organized into distinct functional areas and how these areas work together to enable static analysis of Maho/Magento codebases.

For detailed information about specific subsystems, see:

Architectural Overview

The maho-phpstan-plugin is structured as a collection of PHPStan extensions that address specific patterns in Maho/Magento codebases. The plugin's architecture divides into three primary subsystems, each handling a distinct category of analysis challenges.

High-Level System Structure


Sources: extension.neon1-71 composer.json1-31

Three Primary Subsystems

The plugin organizes its functionality into three independent subsystems that each address specific Maho/Magento analysis challenges:

SubsystemPurposePrimary ClassesPHPStan Extension Type
Type ResolutionResolves factory method return types (e.g., Mage::getModel())MageTypeExtension, MageCoreConfig, MageInvalidTypeRuleDynamic return type extensions, custom rules
ReflectionHandles magic methods on Varien_Object descendantsVarienObjectReflectionExtension, MagicMethodReflectionMethods class reflection extension
Scope ResolutionEnables protected method access in templates and scriptsBindThisScopeResolverExtension, PublicMethodReflection, PublicPropertyReflectionParser node visitor, type node resolver

Sources: extension.neon19-71

Configuration-Driven Architecture

The plugin uses a declarative configuration model where extension.neon1-71 serves as the single source of truth for all component registration, parameter injection, and PHPStan integration.

Configuration Structure


Sources: extension.neon1-71

Service Dependency Injection

The configuration file defines a dependency injection pattern where mageCoreConfig is a central service that other components depend on:


Sources: extension.neon14-55

Layered Component Architecture

The plugin's components are organized in layers, with each layer building on the functionality of layers below it.

Component Layers


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

Layer Responsibilities

Configuration Layer (Layer 0)

  • Defines all configurable parameters
  • Declares services and their dependencies
  • Registers components with PHPStan through tags
  • Files: extension.neon1-71

Mock Framework Layer (Layer 1)

Service Layer (Layer 2)

  • Implements core business logic for type resolution and reflection
  • Provides reusable services consumed by extension layer
  • Key classes: MageCoreConfig, MagicMethodReflection, PublicMethodReflection, PublicPropertyReflection

Extension Layer (Layer 3)

  • Implements PHPStan extension interfaces
  • Directly invoked by PHPStan during analysis
  • Key classes: MageTypeExtension, MageInvalidTypeRule, VarienObjectReflectionExtension, BindThisScopeResolverExtension

Analysis Layer (Layer 4)

  • PHPStan core analyzer that discovers and invokes extensions
  • Not part of plugin codebase

Plugin Discovery and Bootstrap

The plugin uses PHPStan's standard extension discovery mechanism, which relies on Composer package metadata.

Discovery Flow


Sources: composer.json4 composer.json24-29 extension.neon1-71

The key configuration elements that enable discovery:

ElementLocationPurpose
type: phpstan-extensioncomposer.json4Identifies package as PHPStan extension
extra.phpstan.includescomposer.json24-29Points to configuration file
extension.neonRoot directoryDefines all services and registrations

Service Registration Pattern

The plugin registers services with PHPStan using a tag-based system. Each service class implements specific PHPStan interfaces and is registered with corresponding tags.

Service-to-Tag Mapping


Sources: extension.neon20-71

The configuration file declares four separate MageTypeExtension instances, each with different className arguments:

InstanceclassName ArgumentTagLines
Instance 1MagedynamicStaticMethodReturnTypeExtensionextension.neon20-26
Instance 2Mage_Core_Block_AbstractdynamicMethodReturnTypeExtensionextension.neon27-33
Instance 3Mage_Core_Model_AbstractdynamicMethodReturnTypeExtensionextension.neon34-40
Instance 4Mage_Core_Model_LayoutdynamicMethodReturnTypeExtensionextension.neon41-47

This multi-instance pattern allows a single class to handle different method signatures across different base classes, with the className parameter controlling which class's methods are intercepted.

Parameter System

The plugin exposes three configurable parameters that users can override in their project's PHPStan configuration.

Parameter Definition and Flow


Sources: extension.neon1-8 extension.neon14-17 extension.neon58-61

Parameter Usage

ParameterTypeDefaultConsumerPurpose
magentoRootPathstring|nullnullNoneDeprecated, no longer used
useLocalXmlboolfalseMageCoreConfigWhether to load local.xml configuration
enforceMagicMethodDocBlockboolfalseVarienObjectReflectionExtensionWhether to require docblocks for magic methods

Parameters are injected into service constructors using the %parameterName% syntax in extension.neon17 and extension.neon61

Mock Framework Integration

The plugin includes mock implementations of core Maho/Magento classes to enable type resolution without requiring a full framework installation.

Mock Class Organization


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

The mock framework serves two critical functions:

  1. Type Resolution Support: Classes like Mage and Mage_Core_Model_Config provide methods that MageCoreConfig calls to resolve Magento class aliases (e.g., "catalog/product" → "Mage_Catalog_Model_Product")

  2. Reflection Analysis: Classes like Varien_Object and Maho\DataObject define the base methods (getData(), setData()) that VarienObjectReflectionExtension maps magic method calls to

The plugin declares these mock directories in two places:

  • extension.neon9-11 adds them to PHPStan's scanDirectories for analysis-time class availability
  • composer.json19-23 includes them in Composer's autoload-dev classmap for development-time usage

Architecture Summary

The maho-phpstan-plugin implements a modular, configuration-driven architecture with clear separation of concerns:

  • Configuration Layer: Declarative service definitions in extension.neon
  • Service Layer: Reusable business logic components
  • Extension Layer: PHPStan integration points
  • Mock Layer: Framework simulation for type resolution

This architecture enables the plugin to extend PHPStan's analysis capabilities while maintaining clean abstractions between different functional areas. The dependency injection pattern ensures components are loosely coupled and can be configured independently through parameters.

Sources: extension.neon1-71 composer.json1-31