Extension for PHPStan to allow analysis of Drupal code.

Overview

phpstan-drupal

Tests CircleCI

Extension for PHPStan to allow analysis of Drupal code.

Sponsors

undpaul iO

Would you like to sponsor?

Usage

When you are using phpstan/extension-installer, phpstan.neon will be automatically included.

Manual installation

If you don't want to use phpstan/extension-installer, include extension.neon in your project's PHPStan config:

includes:
    - vendor/mglaman/phpstan-drupal/extension.neon

To include Drupal specific analysis rules, include this file:

includes:
    - vendor/mglaman/phpstan-drupal/rules.neon

Excluding tests from analysis

To exclude tests from analysis, add the following parameter

parameters:
	excludePaths:
		- *Test.php
		- *TestBase.php

Deprecation testing

Add the deprecation rules to your Drupal project's dependencies

composer require --dev phpstan/phpstan-deprecation-rules

Edit your phpstan.neon to look like the following:

includes:
	- vendor/mglaman/phpstan-drupal/extension.neon
	- vendor/phpstan/phpstan-deprecation-rules/rules.neon

To only handle deprecation testing, use a phpstan.neon like this:

parameters:
	customRulesetUsed: true
	reportUnmatchedIgnoredErrors: false
	# Ignore phpstan-drupal extension's rules.
	ignoreErrors:
		- '#\Drupal calls should be avoided in classes, use dependency injection instead#'
		- '#Plugin definitions cannot be altered.#'
		- '#Missing cache backend declaration for performance.#'
		- '#Plugin manager has cache backend specified but does not declare cache tags.#'
includes:
	- vendor/mglaman/phpstan-drupal/extension.neon
	- vendor/phpstan/phpstan-deprecation-rules/rules.neon

Adapting to your project

Specifying your Drupal project's root

By default, the PHPStan Drupal extension will try to determine your Drupal project's root directory based on the working directory that PHPStan is checking. If this is not working properly, you can explicitly define the Drupal project's root directory using the drupal.drupal_root parameter.

parameters:
	drupal:
		drupal_root: /path/to/drupal

You can also use container parameters. For instance you can always set it to the current working directory.

parameters:
	drupal:
		drupal_root: %currentWorkingDirectory%

Entity storage mappings.

The EntityTypeManagerGetStorageDynamicReturnTypeExtension service helps map dynamic return types. This inspects the passed entity type ID and tries to return a known storage class, besides the default EntityStorageInterface. The default mapping can be found in extension.neon. For example:

parameters:
	drupal:
		entityMapping:
			block:
				class: Drupal\block\Entity\Block
				storage: Drupal\Core\Config\Entity\ConfigEntityStorage
			node:
				class: Drupal\node\Entity\Node
				storage: Drupal\node\NodeStorage
			taxonomy_term:
				class: Drupal\taxonomy\Entity\Term
				storage: Drupal\taxonomy\TermStorage
			user:
				class: Drupal\user\Entity\User
				storage: Drupal\user\UserStorage

To add support for custom entities, you may add the same definition in your project's phpstan.neon. See the following example for adding a mapping for Search API:

parameters:
	drupal:
		entityMapping:
			search_api_index:
				class: Drupal\search_api\Entity\Index
				storage: Drupal\search_api\Entity\SearchApiConfigEntityStorage
			search_api_server:
				class: Drupal\search_api\Entity\Server
				storage: Drupal\search_api\Entity\SearchApiConfigEntityStorage			    

Similarly, the EntityStorageDynamicReturnTypeExtension service helps to determine the type of the entity which is loaded, created etc.. when using an entity storage. For instance when using

$node = \Drupal::entityTypeManager()->getStorage('node')->create(['type' => 'page', 'title' => 'foo']);

It helps with knowing the type of the $node variable is Drupal\node\Entity\Node.

The default mapping can be found in extension.neon:

parameters:
	drupal:
		entityMapping:
			block:
				class: Drupal\block\Entity\Block
				storage: Drupal\Core\Config\Entity\ConfigEntityStorage
			node:
				class: Drupal\node\Entity\Node
				storage: Drupal\node\NodeStorage
			taxonomy_term:
				class: Drupal\taxonomy\Entity\Term
				storage: Drupal\taxonomy\TermStorage
			user:
				class: Drupal\user\Entity\User
				storage: Drupal\user\UserStorage

To add support for custom entities, you may add the same definition in your project's phpstan.neon likewise.

Providing entity type mappings for a contrib module

Contributed modules can provide their own mapping that can be automatically registered with a user's code base when they use the phpstan/extension-installer. The extension installer scans installed package's composer.json for a value in extra.phpstan. This will automatically bundle the defined include that contains an entity mapping configuration.

For example, the Paragraphs module could have the following entity_mapping.neon file:

parameters:
	entityMapping:
		paragraph:
			class: Drupal\paragraphs\Entity\Paragraph
		paragraphs_type:
			class: Drupal\paragraphs\Entity\ParagraphsType

Then in the composer.json for Paragraphs, the entity_mapping.neon would be provided as a PHPStan include

{
  "name": "drupal/paragraphs",
  "description": "Enables the creation of Paragraphs entities.",
  "type": "drupal-module",
  "license": "GPL-2.0-or-later",
  "require": {
    "drupal/entity_reference_revisions": "~1.3"
  },
  "extra": {
    "phpstan": {
      "includes": [
        "entity_mapping.neon"
      ]
    }
  }
}
Comments
  •  Reflection error: Drupal\Tests\PhpunitCompatibilityTrait not found

    Reflection error: Drupal\Tests\PhpunitCompatibilityTrait not found

    How is drupal-check installed?

    drupal-check is installed as a dependency to my project

    Environment:

    • OS: macOS
    • PHP Version: 7.3
    • Drupal core: 9.0.x

    Describe the bug Reflection error occurs when using multiple arguments to test different files. $ vendor/bin/drupal-check --deprecations --no-progress --drupal-root=../drupal --exclude-dir=vendor cookiebot_consent.module src/Event/LibrariesEvent.php

    This issue was partially fixed in https://github.com/phpstan/phpstan/issues/3522 but still occurs when using different files as arguments.

    cookiebot_consent.module

      $event = new LibrariesEvent($extension);
    

    src/Event/LibrariesEvent.php

    use Symfony\Contracts\EventDispatcher\Event;
    
    class LibrariesEvent extends Event {
    

    Symfony\Contracts\EventDispatcher\Event

    namespace Symfony\Contracts\EventDispatcher;
    
    use Psr\EventDispatcher\StoppableEventInterface;
    
    if (interface_exists(StoppableEventInterface::class)) {
        class Event implements StoppableEventInterface
        {
        }
    } else {
        class Event
        {
        }
    }
    

    Console output

     ------ -------------------------------------------------------------------- 
      Line   cookiebot_consent.module                                            
     ------ -------------------------------------------------------------------- 
             Reflection error: Psr\EventDispatcher\StoppableEventInterface not   
             found.                                                              
             💡 Learn more at https://phpstan.org/user-guide/discovering-symbols  
     ------ -------------------------------------------------------------------- 
    
     ------ -------------------------------------------------------------------- 
      Line   src/Event/LibrariesEvent.php                                        
     ------ -------------------------------------------------------------------- 
             Reflection error: Psr\EventDispatcher\StoppableEventInterface not   
             found.                                                              
             💡 Learn more at https://phpstan.org/user-guide/discovering-symbols  
      52     Reflection error: Psr\EventDispatcher\StoppableEventInterface not   
             found.                                                              
             💡 Learn more at https://phpstan.org/user-guide/discovering-symbols  
     ------ -------------------------------------------------------------------- 
    
    opened by MPParsley 31
  • Extension service provider classes are not autoloaded.

    Extension service provider classes are not autoloaded.

    The pattern is camel case of the extension with ServiceProvider appended.

     ------ ------------------------------------------------------------------------- 
      Line   src/EntityReferenceRevisionsServiceProvider.php                          
     ------ ------------------------------------------------------------------------- 
             Class                                                                    
             Drupal\entity_reference_revisions\EntityReferenceRevisionsServiceProvid  
             er was not found while trying to analyse it - autoloading is probably    
             not configured properly.                                                 
     ------ ------------------------------------------------------------------------- 
    
    bug Autoloading 
    opened by mglaman 13
  • Entities: Allow FieldItemList access through magic __get/__set methods

    Entities: Allow FieldItemList access through magic __get/__set methods

    PHPStan said "Access to an undefined property". A custom entity may define fields in ::baseFieldDefinitions(). Other ways to define a field are though hook implementations like hook_entity_base_field_info(), or through config entites created from the Drupal admin UI. Thus, it seems very hard to track all cases in PHPStan.

    While ContentEntityBase::__get() will return a FieldItemListInterface, ContentEntityBase::__set may be used to set fields directly, thus I decided to tell PHPStan that the type is mixed. For example, the following code can be valid:

    $entity = SomeCustomEntity();
    $entity->some_int_field = 34;
    $entity->save();
    
    opened by fonata 13
  • BrowserTestBaseDefaultThemeRule false positives needs to account for profile

    BrowserTestBaseDefaultThemeRule false positives needs to account for profile

    The rule BrowserTestBaseDefaultThemeRule results in false positives. BrowserTestBase::$defaultTheme is not always required. See \Drupal\Core\Test\FunctionalTestSetupTrait::installDefaultThemeFromClassProperty(). If the test is using a profile that uses config installation then the theme is set from that.

    I'm not sure that PHPStan can ever correctly identify this.

    opened by alexpott 12
  • TestCase not found with BrowserTestBaseDefaultThemeRule

    TestCase not found with BrowserTestBaseDefaultThemeRule

    The BrowserTestBaseDefaultThemeRule class throws the false positive error:

    Class PHPUnit\Framework\TestCase not found.
    

    when scanning a normal subclass e.g. Forms, even though it doesn't necessarily depend on PHPUnit itself.

    Related to #167

    opened by codebymikey 11
  • Error: No Drupal service map was registered. when running Rector

    Error: No Drupal service map was registered. when running Rector

    Originally reported in https://www.drupal.org/project/rector/issues/3243281

    Drupal version 9.2.6 Drupal Rector version 0.11.3 PHPStan Drupal version 0.12.15

    I saw that my CI scanning contrib module fails for Rector because of the following error:

    [ERROR] Could not process "app/modules/custom/views_merge_rows/views_merge_rows.module" file, due to: "No Drupal service map was registered.". On line: 19

    Same error on all files scanned by Rector.

    But the error message is from vendor/mglaman/phpstan-drupal/src/Drupal/ServiceMap.php

    Thanks for any help.

    opened by FlorentTorregrosa 11
  • Replace only in string arguments

    Replace only in string arguments

    This fix blocking drupal/upgrade_status on PHP 8

    The https://github.com/mglaman/phpstan-drupal/pull/161 missed to fix when arguments are int, bool, null

    Related to #150

    opened by andypost 11
  • Ignore return type hints for Drupal hooks

    Ignore return type hints for Drupal hooks

      # Ignore certain standards for legacy procedural functions in module, theme, profile and includes.
      # Specifically centered around hook/alters and lack of proper types.
      reportUnmatchedIgnoredErrors: false
      ignoreErrors:
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has no return typehint specified\./'
          path: *.module
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) return type has no value type specified/'
          path: *.module
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has parameter .* no value type specified/'
          path: *.module
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has no return typehint specified\./'
          path: *.theme
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) return type has no value type specified/'
          path: *.theme
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has parameter .* no value type specified/'
          path: *.theme
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has no return typehint specified\./'
          path: *.profile
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) return type has no value type specified/'
          path: *.profile
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has parameter .* no value type specified/'
          path: *.profile
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has no return typehint specified\./'
          path: *.inc
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) return type has no value type specified/'
          path: *.inc
        -
          message: '/^Function [a-zA-Z0-9\\_]+\(\) has parameter .* no value type specified/'
          path: *.inc
    
    opened by markhalliwell 11
  • Improve the extension

    Improve the extension

    Hi, I'd like to discourage you from using the CompilerExtension concept. The fact that PHPStan uses Nette\DI is not a public API and can break. Also, it means that this PHPStan extension is not usable with phpstan-shim (PHAR) where Nette is prefixed.

    Also, I will remove the global variables in the next version, I didn't realize that someone would access and read them intentionally - they're not part of PHPStan's official API :)

    opened by ondrejmirtes 11
  • Can your extension be used standalone on a module ?

    Can your extension be used standalone on a module ?

    Hi,

    I'm trying to use your extension for a specific module. Which means that I placed the phpstan.neon file at the root of my module, and not at the root of a complete drupal installation. My module is a separate project, registered in a private composer index (satis) and has a specific continuous integration tunnel configured in gitlab. I need to be able to analyse the code standalone.

    This is my configuration file :

    parameters:
    	level: 7
    includes:
    	- vendor/phpstan/phpstan-phpunit/extension.neon
    	- vendor/mglaman//phpstan-drupal/extension.neon
    

    And this is the output of the phpstan analyse src command

    ote: Using configuration file /app/phpstan.neon.
    PHP Fatal error:  Uncaught TypeError: is_dir() expects parameter 1 to be a valid path, boolean given in /app/vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php:320
    Stack trace:
    #0 /app/vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php(320): is_dir(false)
    #1 /app/vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php(139): PHPStan\Drupal\ExtensionDiscovery->scanDirectory('')
    #2 /app/vendor/mglaman/phpstan-drupal/src/DependencyInjection/DrupalExtension.php(83): PHPStan\Drupal\ExtensionDiscovery->scan('profile')
    #3 /composer/vendor/nette/di/src/DI/Compiler.php(215): PHPStan\DependencyInjection\DrupalExtension->loadConfiguration()
    #4 /composer/vendor/nette/di/src/DI/Compiler.php(175): Nette\DI\Compiler->processExtensions()
    #5 /composer/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(306): Nette\DI\Compiler->compile()
    #6 [internal function]: Nette\Configurator->generateContainer(Object(Nette\DI\Compiler))
    #7 /composer/vendor/nette/di/src/DI/ContainerLoader.php(125): call_user_func_array(Arr in /app/vendor/mglaman/phpstan-drupal/src/Drupal/ExtensionDiscovery.php on line 320
    

    When I remove your extension from the includes section, everything works as it should !

    Thanks in advance !

    postponed 
    opened by CaptainQuirk 11
  • Detect when a class extends a class that has been flagged as @internal

    Detect when a class extends a class that has been flagged as @internal

    See #183

    In this PR, a shared namespace for Drupal starts with Drupal\project_name.

    It means:

    • a class inside Drupal\Core can extends an internal class from Drupal\Core
    • a class inside Drupal\my_module can extends an internal class from Drupal\my_module
    • a class inside Drupal\my_module cannot extends an internal class from Drupal\Core or \Drupal\another_module
    • a class inside Drupal\Component cannot extends an internal class from Drupal\Core or \Drupal\another_module
    • a class inside Drupal\Core cannot extends an internal class from Drupal\Component or \Drupal\another_module
    • etc..

    For the part detecting calls to internal methods, I think it can be handled in another PR 🤔

    opened by brambaud 9
  • Track deprecated global drush constants

    Track deprecated global drush constants

    This is a follow-up issue of https://github.com/mglaman/phpstan-drupal/issues/486. As discussed there, we should replicate the AccessDeprecatedConstant rule to track known deprecated global drush constants.

    See https://github.com/mglaman/phpstan-drupal/blob/main/src/Rules/Deprecations/AccessDeprecatedConstant.php for the model class.

    opened by joshsedl 0
  • Fix possible return types on AccessResult with a stub

    Fix possible return types on AccessResult with a stub

    Small POC

    /**
     * @return \Drupal\Core\Access\AccessResultAllowed|\Drupal\Core\Access\AccessResultForbidden
     */
    function foo(bool $true) {
      if ($true === TRUE) {
        // Incorrect typehint on https://github.com/drupal/core/blob/10.0.0-beta2/lib/Drupal/Core/Access/AccessResult.php#L75-L78
       // This is clearly AccessResultAllowed() when the condition is true.
        $access = \Drupal\Core\Access\AccessResult::allowedIf($true);
      }
      else {
        $access = \Drupal\Core\Access\AccessResult::forbidden();
      }
      return $access;
    }
    

    Unexpected result

    
     ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------- 
      Line   access_result_poc.php                                                                                                                                      
     ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------- 
      19     Function foo() should return Drupal\Core\Access\AccessResultAllowed|Drupal\Core\Access\AccessResultForbidden but returns Drupal\Core\Access\AccessResult.  
     ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------- 
    
    
    opened by mxr576 0
  • Uncaught error: Cannot unset string offsets - DrupalExtension.php:152

    Uncaught error: Cannot unset string offsets - DrupalExtension.php:152

    This is a duplicate of the issue here, but I dont have access to re-open it:

    https://github.com/mglaman/phpstan-drupal/issues/79

    PHP Fatal error:  Uncaught Error: Cannot unset string offsets in phar:///tmp/drupal-check/vendor/mglaman/phpstan-drupal/src/DependencyInjection/DrupalExtension.php:152
    Stack trace:
    #0 phar:///tmp/drupal-check/vendor/nette/di/src/DI/Compiler.php(232): PHPStan\DependencyInjection\DrupalExtension->loadConfiguration()
    #1 phar:///tmp/drupal-check/vendor/nette/di/src/DI/Compiler.php([20](https://github.com/reload/storypal/actions/runs/3151245237/jobs/5147905382#step:5:21)7): Nette\DI\Compiler->processExtensions()
    #2 phar:///tmp/drupal-check/vendor/nette/di/src/DI/ContainerLoader.php(119): Nette\DI\Compiler->compile()
    #3 phar:///tmp/drupal-check/vendor/nette/di/src/DI/ContainerLoader.php(79): Nette\DI\ContainerLoader->generate()
    #4 phar:///tmp/drupal-check/vendor/nette/di/src/DI/ContainerLoader.php(44): Nette\DI\ContainerLoader->loadFile()
    #5 phar:///tmp/drupal-check/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(242): Nette\DI\ContainerLoader->load()
    #6 phar:///tmp/drupal-check/vendor/nette/bootstrap/src/Bootstrap/Configurator.php(2[21](https://github.com/reload/storypal/actions/runs/3151245237/jobs/5147905382#step:5:22)): Nette\Configurator->loadContainer()
    #7 phar:///tmp/drupal-check/vendor/phpst in phar:///tmp/drupal-check/vendor/mglaman/phpstan-drupal/src/DependencyInjection/DrupalExtension.php on line 152
    reviewdog: EOF
    
    

    As @opdavies points out, it's an issue that this patch introduced: https://www.drupal.org/node/3021898

    But, now that patch has been merged to Drupal core.

    opened by rasben 0
Releases(1.1.26)
  • 1.1.26(Dec 22, 2022)

    What's Changed

    • Replace deprecated PHPStan\Type\Constant\ConstantArrayType::findTypeAndMethodName() call by @mxr576 in https://github.com/mglaman/phpstan-drupal/pull/485
    • bump phpstan minimum to 1.8 by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/489
    • Allow EntityReferenceFieldItemListInterface::referencedEntities to work with generic by @dpi in https://github.com/mglaman/phpstan-drupal/pull/478
    • fix: Fix unpredictable false positive/negative of missing entity access check in function scope due to cache key conflict by @driskell in https://github.com/mglaman/phpstan-drupal/pull/476
    • Update EntityQueryWithoutAccessRule rule message to use full Drupal message by @goba in https://github.com/mglaman/phpstan-drupal/pull/469
    • REQUEST_TIME pushed to 11.0.0 removal by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/491

    New Contributors

    • @mxr576 made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/485
    • @driskell made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/476

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.25...1.1.26

    Source code(tar.gz)
    Source code(zip)
  • 1.1.25(Jul 18, 2022)

    Quick patch release following up on the RequestStack forward compatibility shim work in https://github.com/mglaman/phpstan-drupal/pull/446. This reduces the noise by only reporting an error when using the method deprecated in Symfony 5 and removed in Symfony 6.

    What's Changed

    • More specific rules for RequestStack shim by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/459

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.24...1.1.25

    Source code(tar.gz)
    Source code(zip)
  • 1.1.24(Jul 14, 2022)

    What's Changed

    • Add generic callable check for RenderCallbackRule by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/453
    • Entity query access check rule improvements by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/454
    • Specify T for FieldableEntityInterface stub by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/456

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.23...1.1.24

    Source code(tar.gz)
    Source code(zip)
  • 1.1.23(Jul 14, 2022)

    Includes a hotfix for 1.1.22 to fix SymfonyCmfRoutingInClassMethodSignatureRule

    What's Changed

    • Generic FieldItemListInterface and related stubs by @jacktonkin in https://github.com/mglaman/phpstan-drupal/pull/433
    • Update phpstan-dev workflow by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/450
    • SymfonyCmfRoutingInClassMethodSignatureRule stop using isSuperOf by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/451

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.22...1.1.23

    Source code(tar.gz)
    Source code(zip)
  • 1.1.22(Jul 13, 2022)

    What's Changed

    • add support for class string service ids by @laytan in https://github.com/mglaman/phpstan-drupal/pull/434
    • Test #lazy_builder and static::class concat for callback by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/426
    • fix composer allow-plugins in CI by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/444
    • Allow static::class . '::methodName' concatenation in lazy builders. by @longwave in https://github.com/mglaman/phpstan-drupal/pull/436
    • Add SymfonyCmfRouteObjectInterfaceConstantsRule by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/445
    • Forward compatibility shim added for Symfony 5 RequestStack rule by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/446

    New Contributors

    • @laytan made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/434
    • @longwave made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/436

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.21...1.1.22

    Source code(tar.gz)
    Source code(zip)
  • 1.1.21(Jul 7, 2022)

    What's Changed

    • Allow PHPStan 1.6 by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/435
    • Fix preg_match() usage when looking for extension type by @andypost in https://github.com/mglaman/phpstan-drupal/pull/442

    New Contributors

    • @andypost made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/442

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.20...1.1.21

    Source code(tar.gz)
    Source code(zip)
  • 1.1.20(Jun 7, 2022)

    What's Changed

    • Add missing stub dependency stubs by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/430

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.19...1.1.20

    Source code(tar.gz)
    Source code(zip)
  • 1.1.19(Jun 4, 2022)

    What's Changed

    • Replace AccessibleReturnTypeExtension with stub for AccessibleInterface by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/419
    • Add EntityInterface stub by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/425

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.18...1.1.19

    Source code(tar.gz)
    Source code(zip)
  • 1.1.18(May 28, 2022)

    What's Changed

    • Add stubs for ContentEntityInterface and FieldableEntityInterface by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/413
    • Remove drupal-phpunit-hack.php by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/415
    • Allow \Drupal calls in StreamWrapperInterface by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/416
    • Update README.md by @webflo in https://github.com/mglaman/phpstan-drupal/pull/405
    • do not use DIRECTORY_SEPARATOR in error messages by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/417

    New Contributors

    • @webflo made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/405

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.17...1.1.18

    Source code(tar.gz)
    Source code(zip)
  • 1.1.17(May 24, 2022)

    Fixes with #409 allow using PHPStan without the rich node parser.

    What's Changed

    • Enable richParserNodeVisitor for tests by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/400
    • Explicit allowed class checks for #lazy_builder by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/409
    • Fix PHPStan 1.7.0 incompatibilities by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/410

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.16...1.1.17

    Source code(tar.gz)
    Source code(zip)
  • 1.1.16(Apr 13, 2022)

    What's Changed

    • Entity query count and accessCheck order should not matter by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/382
    • Move rules to rules.neon by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/389
    • Start using slevomat/coding-standard rules by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/390

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.15...1.1.16

    Source code(tar.gz)
    Source code(zip)
  • 1.1.15(Apr 6, 2022)

    What's Changed

    • Report missing explicit access check on entity queries by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/378
    • resolveFromStorage does not respect default phpDoc for generic storage interface by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/379

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.14...1.1.15

    Source code(tar.gz)
    Source code(zip)
  • 1.1.14(Mar 23, 2022)

    What's Changed

    • Move getQuery method return type to own extension by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/372
    • Entity storage with type hint prevent inferring entity query execute return type by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/355
    • Update PHPUnit config and workflow by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/373
    • Register stub files automatically by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/374
    • Move Rules to rules out of services by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/375

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.13...1.1.14

    Source code(tar.gz)
    Source code(zip)
  • 1.1.13(Mar 11, 2022)

    What's Changed

    • Add field type stubs for file module by @xendk in https://github.com/mglaman/phpstan-drupal/pull/354
    • The entity property can return NULL by @larowlan in https://github.com/mglaman/phpstan-drupal/pull/356

    New Contributors

    • @xendk made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/354
    • @larowlan made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/356

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.12...1.1.13

    Source code(tar.gz)
    Source code(zip)
  • 1.1.12(Feb 23, 2022)

    What's Changed

    • Mark \Drupal::VERSION as a dynamic constant by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/349
    • FIXUP: Perform \Drupal::VERSION check for deprecated constants by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/350
    • Rule for ConditionManager::createInstance() when 'context' is passed as array key by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/351

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.11...1.1.12

    Source code(tar.gz)
    Source code(zip)
  • 1.1.11(Feb 18, 2022)

    Entity field analysis improvements

    Field types provided by Drupal core have been stubbed to provide @property annotations. If you have a field value and it has been type hinted, PHPStan will not complain about accessing a non-existent property.

    Example:

    // EntityReferenceItem.
    $entity_reference_field = $node->get('field_entity_reference')->first();
    assert($entity_reference_field instanceof EntityReferenceItem);
    assertType(EntityReferenceItem::class, $entity_reference_field);
    assertType('int|string', $entity_reference_field->target_id);
    assertType('Drupal\Core\Entity\EntityInterface', $entity_reference_field->entity);
    

    Updated deprecated global constants

    Drupal 9.3.x and 9.4.x deprecated more global constants. The rule to check for these has been updated.

    What's Changed

    • Optimize BrowserTestBaseDefaultThemeRule by @neclimdul in https://github.com/mglaman/phpstan-drupal/pull/323
    • BrowserTestBaseDefaultThemeRule namespace check by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/319
    • Resolve conflicts on root with drupal/core-dev:10.0.x by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/324
    • Update constants by @mallezie in https://github.com/mglaman/phpstan-drupal/pull/332
    • Update README.md by @mallezie in https://github.com/mglaman/phpstan-drupal/pull/333
    • Provide a stub for twig_escape_filter by @neclimdul in https://github.com/mglaman/phpstan-drupal/pull/327
    • drupal/core:10.0.x requires PHP 8.1 by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/345
    • Fix HEAD fails on branch alias for build integration jobs by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/346
    • Add stubs for core field types by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/344

    New Contributors

    • @neclimdul made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/323
    • @mallezie made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/332

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.10...1.1.11

    Source code(tar.gz)
    Source code(zip)
  • 1.1.10(Jan 26, 2022)

    What's Changed

    • Proper return type for config entity queries by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/309
    • Exclude InstallerExistingConfigTestBase from $defaultTheme rule by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/312
    • Allow non-callable in #lazy_builder if array_intersect_key by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/313

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.9...1.1.10

    Source code(tar.gz)
    Source code(zip)
  • 1.1.9(Jan 17, 2022)

    This relaxes the constraints so that phpstan-drupal can be installed on the Drupal 10.0.x branch.

    What's Changed

    • Relax constraints by @alexpott in https://github.com/mglaman/phpstan-drupal/pull/306

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.8...1.1.9

    Source code(tar.gz)
    Source code(zip)
  • 1.1.8(Jan 12, 2022)

    RenderCallbackRule Improvements

    The RenderCallbackRule added in 1.1.5 had various flaws. This release should fix them:

    • Improper analysis of #access_callback – not an array, single callable.
    • Improper analysis of #lazy_builder – an array, but of call_user_func_array values ([callable, args])
    • service_name:method style callbacks were not parsed, now they are

    What's Changed

    • Calling getStorage with a constant does not resolve entity mapped storage class by @dpi in https://github.com/mglaman/phpstan-drupal/pull/300
    • Handle controller notation for callbacks by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/302
    • Fix #lazy_builder callback analysis and static::class concatenation warning by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/304

    New Contributors

    • @dpi made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/300

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.7...1.1.8

    Source code(tar.gz)
    Source code(zip)
  • 1.1.7(Jan 10, 2022)

    What's Changed

    • Remove nette/finder for symfony/finder (reusing Drupal dependencies) by @alexpott in https://github.com/mglaman/phpstan-drupal/pull/297

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.6...1.1.7

    Source code(tar.gz)
    Source code(zip)
  • 1.1.6(Jan 6, 2022)

    Hotfix.

    What's Changed

    • Fix/render callback by @alexpott in https://github.com/mglaman/phpstan-drupal/pull/292

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.5...1.1.6

    Source code(tar.gz)
    Source code(zip)
  • 1.1.5(Jan 5, 2022)

    What's Changed

    • Require PHP ^7.4 by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/290
    • #pre_render callback rule by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/217

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.4...1.1.5

    Source code(tar.gz)
    Source code(zip)
  • 1.1.4(Dec 29, 2021)

    What's Changed

    • Add phpstan prophecy suggestion by @ptt-homme in https://github.com/mglaman/phpstan-drupal/pull/282
    • Add phpstan/phpstan-phpunit to the suggested packages list by @ptt-homme in https://github.com/mglaman/phpstan-drupal/pull/283
    • Add documentation for contrib entity mapping by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/285
    • Add tips to the extends internal class rule errors by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/286
    • Add return type extensions for AccessResult methods by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/287

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.3...1.1.4

    Source code(tar.gz)
    Source code(zip)
  • 1.1.3(Dec 22, 2021)

    What's Changed

    • Expand list of entity type storages by @ptt-homme in https://github.com/mglaman/phpstan-drupal/pull/277
    • Allow ::referencedEntities on field items by @eiriksm in https://github.com/mglaman/phpstan-drupal/pull/265

    New Contributors

    • @ptt-homme made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/277

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.2...1.1.3

    Source code(tar.gz)
    Source code(zip)
  • 1.1.2(Dec 15, 2021)

    Highlights

    With #264 we have added the ability to look up discovered extensions, which should greatly improve the rules which load files called by module_load_include and ModuleHandlerInterface::loadInclude. Previously these two rules had to re-scan for extensions whenever the function or method was analyzed.

    What's Changed

    • Fail to map a service with a parent which overrides its parent too by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/260
    • Detect when a class extends a class that has been flagged as @internal by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/248
    • issue #142: resolve incorrect $reflection definition by @eugene-brit in https://github.com/mglaman/phpstan-drupal/pull/178
    • Add 10.0.x to tests by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/269
    • Make the discovered Drupal extensions accessible via a service by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/264
    • Respect @property annotations on Entity classes by @jacktonkin in https://github.com/mglaman/phpstan-drupal/pull/268

    New Contributors

    • @eugene-brit made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/178
    • @jacktonkin made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/268

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.1...1.1.2

    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Nov 29, 2021)

    Major fix for sites without drupal/core-dev

    This release includes fixes for Class PHPUnit\Framework\TestCase not found. errors!

    testcase-not-found

    Note you must have this in your phpstan.neon if drupal/core-dev is missing:

    	excludePaths:
    		-  */tests/src/*/*.php
    

    What's Changed

    • Support dynamic return type of Drupal\Core\Url::toString by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/255
    • Support parent definition service by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/256
    • Avoid false positives when PHPUnit doesn't exist. by @codebymikey in https://github.com/mglaman/phpstan-drupal/pull/216
    • Fix incompatibility without drupal/core-dev by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/246

    New Contributors

    • @codebymikey made their first contribution in https://github.com/mglaman/phpstan-drupal/pull/216

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.1.0...1.1.1

    Source code(tar.gz)
    Source code(zip)
  • 1.1.0(Nov 24, 2021)

    Backwards compatibility warning

    1.1.0 has introduced a breaking change in the configuration schema. See below for more information.

    What's Changed

    • Test drupal container related type inference by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/227
    • BrowserTestBaseDefaultThemeRule false positives with UpdatePathTests by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/235
    • Update branch alias in composer.json by @jibran in https://github.com/mglaman/phpstan-drupal/pull/236
    • Test EntityInterface return type by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/237
    • Allow magic methods for variables of type FieldItemListInterface by @eiriksm in https://github.com/mglaman/phpstan-drupal/pull/244
    • Support entity query execute dynamic return type whether it is a count query or not by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/241
    • Support entity class return type extension from entity storage methods by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/239
    • EntityDataRepository for entity type data by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/250
    • Use entity storage class inferred from entity type by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/251

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.0.3...1.1.0

    Configuration changes

    The drupal.entityTypeStorageMapping allowed specifying what storage classes were used for different entity types. With #239, support was added to specify what entity class an entity type uses. With #250 the way entity type information is configured has been changed.

    Previously:

    parameters:
    	drupal:
    		entityTypeStorageMapping:
    			node: Drupal\node\NodeStorage
    			taxonomy_term: Drupal\taxonomy\TermStorage
    			user: Drupal\user\UserStorage
    

    Now there is an entityMapping property so that we can handle future enhancements with entity type static analysis.

    parameters:
    	drupal:
    		entityMapping:
    			node:
    				class: Drupal\node\Entity\Node
    				storage: Drupal\node\NodeStorage
    			taxonomy_term:
    				class: Drupal\taxonomy\Entity\Term
    				storage: Drupal\taxonomy\TermStorage
    			user:
    				class: Drupal\user\Entity\User
    				storage: Drupal\user\UserStorage
    			block:
    				class: Drupal\block\Entity\Block
    
    Source code(tar.gz)
    Source code(zip)
  • 1.0.3(Nov 12, 2021)

    What's Changed

    • Use isSuperTypeOf to detect if module handler by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/233

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.0.2...1.0.3

    Source code(tar.gz)
    Source code(zip)
  • 1.0.2(Nov 12, 2021)

    What's Changed

    • Ignore defaultTheme on abstract test classes by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/230
    • Only error on defaultTheme for testing profiles by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/231

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.0.1...1.0.2

    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(Nov 10, 2021)

    What's Changed

    • Fix remaining test and analysis errors by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/219
    • Resolve return of ClassResolver::getInstanceFromDefinition by @brambaud in https://github.com/mglaman/phpstan-drupal/pull/220
    • Handle shortcut service aliasing by @mglaman in https://github.com/mglaman/phpstan-drupal/pull/224

    Full Changelog: https://github.com/mglaman/phpstan-drupal/compare/1.0.0...1.0.1

    Source code(tar.gz)
    Source code(zip)
Owner
Matt Glaman
Principal Software Engineer at @acquia
Matt Glaman
An extension for PHPStan for adding analysis for PHP Language Extensions.

PHPStan PHP Language Extensions (currently in BETA) This is an extension for PHPStan for adding analysis for PHP Language Extensions. Language feature

Dave Liddament 9 Nov 30, 2022
Allows installing Drupal extensions event if not compatible with installed drupal/core package

mglaman/composer-drupal-lenient Lenient with it, Drupal 10 with it. Why? The Drupal community introduced a lenient Composer facade that modified the d

Matt Glaman 14 Dec 18, 2022
⚗️ Adds code analysis to Laravel improving developer productivity and code quality.

⚗️ About Larastan Larastan was created by Can Vural and Nuno Maduro, got artwork designed by @Caneco, is maintained by Can Vural, Nuno Maduro, and Vik

Nuno Maduro 4.4k Jan 4, 2023
The SensioLabs DeprecationDetector runs a static code analysis against your project's source code to find usages of deprecated methods, classes and interfaces

SensioLabs DeprecationDetector CAUTION: This package is abandoned and will no longer receive any updates. The SensioLabs DeprecationDetector runs a st

QOSSMIC GmbH 389 Nov 24, 2022
PHPStan extension to support #[Readonly] constructor properties

icanhazstring/phpstan-readonly-property Support #[Readonly] promoted constructor properties for PHPStan. This library is used to have a full transitio

Andreas Frömer 4 Apr 5, 2022
Magento specific extension for phpstan

bitexpert/phpstan-magento This package provides some additional features for PHPStan to make it work for Magento 2 projects. Installation The preferre

bitExpert AG 92 Dec 7, 2022
The main scope of this extension is to help phpstan to detect the type of object after the Assert\Assertion validation.

PHPStan beberlei/assert extension PHPStan beberlei/assert Description The main scope of this extension is to help phpstan to detect the type of object

PHPStan 33 Jan 2, 2023
PHPStan extension for webmozart/assert

PHPStan webmozart/assert extension PHPStan webmozart/assert Description The main scope of this extension is to help phpstan to detect the type of obje

PHPStan 139 Dec 22, 2022
PHPStan extension for sealed classes and interfaces.

Sealed classes with PHPStan This extension adds support for sealed classes and interfaces to PHPStan. Installation To use this extension, require it v

Jiří Pudil 14 Nov 28, 2022
A pure PHP implementation of the open Language Server Protocol. Provides static code analysis for PHP for any IDE.

A pure PHP implementation of the open Language Server Protocol. Provides static code analysis for PHP for any IDE.

Felix Becker 1.1k Jan 4, 2023
Analyzes PHPStan baseline files and creates aggregated error trend-reports

Analyzes phpstan baseline files Analyzes PHPStan baseline files and creates aggregated error trend-reports.

Markus Staab 22 Dec 23, 2022
Sandbox project for the PHPStan workshop

Sandbox project for a PHPStan workshop Installation Requirements Docker Engine Docker Compose Git Bash Getting started Clone this repository (git clon

Matthias Noback 4 Oct 17, 2022
A PHPStan package that supports working with Extbase

PHPStan for Extbase This package provides a couple of stubs and services to make your life easier when working with PHPStan and Extbase. Examples clas

Alexander Schnitzler 7 Dec 10, 2021
Custom PHPStan rules

phpstan-rules Provides additional rules for phpstan/phpstan. Installation Run $ composer require --dev alister/phpstan-rules Usage All of the rules pr

Alister Bulman 1 Nov 4, 2021
Doctrine extensions for PHPStan

Doctrine extensions for PHPStan PHPStan Doctrine This extension provides following features: DQL validation for parse errors, unknown entity classes a

PHPStan 478 Jan 3, 2023
Various PHPStan rules we found useful in ShipMonk.

ShipMonk PHPStan rules Various rules we found useful in ShipMonk. You may found some of them opinionated, so we recommend picking only those fitting y

ShipMonk R&D 31 Dec 22, 2022
Repository containing all the PHPStan rules from the book "Recipes for Decoupling"

PHPStan rules from the book "Recipes for Decoupling" by Matthias Noback In the book "Recipes for Decoupling" we discuss how to decouple from web and C

Matthias Noback 19 Sep 21, 2022
WordPress extensions for PHPStan ⛏️

WordPress extensions for PHPStan Static analysis for the WordPress ecosystem. PHPStan WordPress Installation Add this package to your project. compose

Viktor Szépe 183 Dec 30, 2022
Magento 2 Extension to cleanup admin menu and Store > Configuration area by arranging third party extension items.

Clean Admin Menu - Magento 2 Extension It will merge all 3rd party extension's menu items in backend's primary menu to a common menu item named "Exten

RedChamps 109 Jan 3, 2023