You may have heard of Drupal Check. You may wonder what in the world it is or how it even came to be. I realized this went from an internal research and development task for a product, to open source contribution and then to an essential tool in the march toward Drupal 9. The timeline from January to DrupalCon in April has been pretty crazy, and I realized I have never done a proper blog post about Drupal Check.
In January I wrote a blog post about the PHPStan Drupal extension for writing better Drupal code with static code analysis. That quickly exploded and turned into a way to detect code deprecations on the journey to Drupal 9. Then that also took off. The problem was setting up PHPStan and making it more automated and repeatable.
The result of this dive into PHPStan and Drupal?
- The blogs and buzz formed the creation of the command line tool Drupal Check. I released Drupal Check as a way to have a no-fuss (spoiler alert: there was still dragons to be found) bundled configuration for running PHPStan against a Drupal site to check deprecations.
- At MidCamp the contributors scanned 1,692 modules. 1,692. Dwayne McDaniel from Pantheon has summarized it on their blog: https://pantheon.io/blog/your-module-ready-drupal-9-click-here-find-out.
- There was the development of a new Drupal 8 version of the Upgrade Status module. The new Drupal 8 version uses PHPStan for in-site deprecation detection and reporting as a non-command line solution.
- At DrupalCon Seattle, Dries even talked about Drupal Check in his State of Drupal presentation's How to Prepare for Drupal 9 section.
That is a lot that happened in just a few months.
How did this all get started?
Well, if you missed the news, Commerce Guys have rebranded as Centarro. At DrupalCon Seattle we unveiled Centarro Toolbox, a collection of SaaS products and support packages that help Drupal Commerce teams build with confidence. One of the products in our Centarro Toolbox is the Quality Monitor.
Quality Monitor performs proactive analysis on your codebase to detect problems in development before you deploy to production. It notifies you of necessary code updates and inappropriate API usage.
Drupal Check is, essentially, an open source version of Quality Monitor without our defined static analysis rules. I think this is awesome. We are an open source company. We are a team of seven. During the Driesnote, I realized four of us are in the Top 50 Contributors list. That's huge.
I love that our company's evolution is having an even more significant impact in open source than we expected.
Want to learn more about Centarro Toolbox? Check it out: https://www.centarro.io/products/centarro-toolbox
What does Drupal Check do?
Drupal Check is a customized runner for PHPStan. Instead of running PHPStan directly you run Drupal Check. It includes PHPStan, PHPStan's Deprecation Rules, and PHPStan Drupal and configurations for them.
Here's an example of running it against the Address module and Drupal 8.8.x with just deprecation detection:
Here we go, again, with the default PHPStan static analysis rules:
Why is this useful? Because documenting configuration is hard. It also needs to be taught and takes time at contribution events. The configuration files are available at https://github.com/mglaman/drupal-check/tree/master/phpstan
However, here's a quick overview of what is setup when running deprecation checks:
parameters: # Don't warn about rules not being executed. customRulesetUsed: true reportUnmatchedIgnoredErrors: false # Ignore things which cause problems. excludes_analyse: - */tests/Drupal/Tests/Listeners/Legacy/* - */tests/fixtures/*.php - */settings*.php # 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.#' services: # mglaman/phpstan-junit formatter (pre-checkstyle output) errorFormatter.junit: class: PHPStan\Command\ErrorFormatter\JUnitErrorFormatter includes: - ../vendor/phpstan/phpstan-deprecation-rules/rules.neon
What can't Drupal Check do?
Drupal Check, via PHPStan, can bootstrap Drupal's code and inspect it for errors or deprecations, but it cannot fix code errors. At the end of April, Dezső Biczó wrote an interesting blog: Drupal 9: Automated Deprecated Code Removal - A Proof of Concept. The library announced in the blog post integrates Rector with custom code fixing definitions. It'd be interesting to add this functionality in Drupal Check.
The current features of Drupal Check are dependent on those in PHPStan. PHPStan's deprecation rules do not output the deprecation messages; it only identifies something that is deprecated. Better display of deprecation messages is an open feature request which I have been actively working on. Descriptions for deprecations are now available but do not support multiple line descriptions. If you're interested in following along, development is actively happening in this phpstan/phpdoc-parser pull request: https://github.com/phpstan/phpdoc-parser/pull/26
What's new since Seattle?
Here are some things which are new since DrupalCon Seattle.
PHPStan Drupal improvements:
- Currently working on better integration https://github.com/mglaman/phpstan-drupal/issues/55
- Better handling of functions which throw an exception when a file is required and Drupal has no database available, and the compiled service container does not exist. https://github.com/mglaman/phpstan-drupal/issues/67
- Fixed warnings about DRUPAL_TEST_IN_CHILD_SITE not being defined
- Improved reporting on fetching properties from entities https://github.com/mglaman/phpstan-drupal/pull/27
- Support Drush function autoloading https://github.com/mglaman/phpstan-drupal/pull/65
Drupal Check improvements:
- Test coverage! Added multiple CircleCI jobs to perform integration tests
- Fix various installation problems (Phar, composer global require, cgr) which broke autoloading of Drupal (still to do: composer local install)
The next significant feature is to finalize the deprecation description features. Being able to explain why something was deprecated and how to fix it (part of the required deprecation messaging for Drupal core) is vital. Things also get deprecated that cannot be immediately corrected. For instance, things deprecated on Drupal 8.7.x cannot be fixed in contributed modules until Drupal 8.7 is no longer supported, technically.
I would also like to fix some PHPStan issues. There is an "Easy fixes" milestone on the PHPStan project: https://github.com/phpstan/phpstan/milestone/8