Skip to main content

drupal-check 1.4.0: enforcing PHPStan level 2

Published on

I have just tagged drupal-check 1.4.0. This is kind of a big deal. And it's either a great thing or is going to destroy my inbox with support requests. But, in my opinion, it is completely necessary.

drupal-check will now run PHPStan at level 2 analysis when performing deprecation checks. To summarize from PHPStan's rule level documentation:

  • basic checks, unknown classes, unknown functions, unknown methods called on $this, wrong number of arguments passed to those methods and functions, always undefined variables
  • possibly undefined variables, unknown magic methods and properties on classes with __call and __get
  • unknown methods checked on all expressions (not just $this), validating PHPDocs

Basically, it ensures code is calling actual methods and properties. This is important as it ensures code is correctly analyzed for finding deprecations. It is something that I have discussed in my Tighten up your Drupal code using PHPStan talks and explained in my blog post. I'll reiterate it here.

Why do we need to run PHPStan at level 2?

Level 2 begins to report undefined methods called on classes. The slides go through the example of a typo for a call to an expected isPublished method in a hook_node_insert hook. PHPStan does not report the typo until we go to level 2. When the typo is fixed, assuming that is the problem, PHPStan may say that it still does not exist. This is because the hook has the default type of EntityInterface when it should be NodeInterface, which has isPublished.

This example is based on real support that I have provided multiple times. One of those was handled in GitHub issues versus Slack/Twitter. You can see it here: https://github.com/mglaman/phpstan-drupal/issues/210.

I DON'T WANT THIS AT ALL, ROLLBACK!

😬 😬 😬 😬 😬 😬 😬

Sorry, not going to happen. You can choose to pin your drupal-check dependency onto the 1.3.x minor release so that you don't receive 1.4.x by using the ~1.3.0 constraint. Considering that drupal-check just generates PHPStan configuration, you're fine.

What you should do is install PHPStan directly with the legacy configuration, which is now documented on the README. But I'll copy it here, as well.

Remove drupal-check, install PHPStan and required extensions

composer remove mglaman/drupal-check
composer require  --dev phpstan/phpstan \
  phpstan/extension-installer \
  mglaman/phpstan-drupal \
  phpstan/phpstan-deprecation-rules

Create a phpstan.neon file with the legacy configuration

parameters:
	customRulesetUsed: true
	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.#'

	# FROM mglaman/drupal-check/phpstan/base_config.neon
	reportUnmatchedIgnoredErrors: false
	excludePaths:
		- */tests/Drupal/Tests/Listeners/Legacy/*
		- */tests/fixtures/*.php
		- */settings*.php
		- */bower_components/*
		- */node_modules/*

You can copy this from the Upgrade Status module directly https://git.drupalcode.org/project/upgrade_status/-/blob/8.x-3.x/deprecation_testing_template.neon