Problem/Motivation

My composer is in /app, the website is in /app/docroot, but the phpstan stuff is apparently trying to find Drupal core stuff in /app/core/includes instead of /app/docroot/core/includes. I cannot for the life of me figure out where that's coming from.

PHPStan command failed:
/app/vendor/bin/phpstan analyse --error-format=json -c /tmp/upgrade_status/deprecation_testing.neon /app/docroot/modules/custom/nodesymlinks_tng 2> /tmp/upgrade_status/phpstan_error_output

Command output:
Empty.

Command error:
UnexpectedValueException thrown in /app/vendor/nette/finder/src/Utils/Finder.php on line 209 while loading bootstrap file /app/vendor/mglaman/phpstan-drupal/drupal-autoloader.php: RecursiveDirectoryIterator::__construct(/app/core/includes): failed to open dir: No such file or directory

How can I find out where that's coming from? If it makes any difference, I'm running this locally in Lando using the Acquia recipe, but another site set up the same way worked fine.

This is what's in that .neon file, which looks right to me:

/app$ more /tmp/upgrade_status/deprecation_testing.neon
# FROM mglaman/drupal-check/phpstan/deprecation_testing.neon
parameters:
	tmpDir: '/tmp/upgrade_status/phpstan'
	drupal:
		drupal_root: '/app/docroot'
	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/*

includes:
	- '/app/vendor/mglaman/phpstan-drupal/extension.neon'
	- '/app/vendor/phpstan/phpstan-deprecation-rules/rules.neon'
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

seanr created an issue. See original summary.

seanr’s picture

Issue summary: View changes
gábor hojtsy’s picture

It looks like the autoloader in phpstan-drupal is identifying the wrong directory. Will ping @mglaman to check this out. Are there multiple composer.json files in the project? That could confuse finding where the root is.

mglaman’s picture

PHPStan Drupal is using webflo/drupal-finder under the hood to find the Drupal root location.

What I find is more odd is that this isn't being respected

	drupal:
		drupal_root: '/app/docroot'

I'll make some time to look into this over the next few days. As stated in #3, multiple composer.json could be confusing it. But it shouldn't "care" since drupal_root is defined.

seanr’s picture

FYI, we only have one composer.json in the project root, appart from those included in modules. There isn't one in docroot.

mglaman’s picture

Interesting. The DrupalFinder should take /app/docroot and find the Drupal root (given directory) and vendor directory fine. The vendor directory seems to be discovered just fine as well.

        $drupalParams = $container->getParameter('drupal');
        $drupalRoot = $drupalParams['drupal_root'];
        $finder = new DrupalFinder();
        $finder->locateRoot($drupalRoot);

        $drupalRoot = $finder->getDrupalRoot();
        $drupalVendorRoot = $finder->getVendorDir();
        if (! (bool) $drupalRoot || ! (bool) $drupalVendorRoot) {
            throw new \RuntimeException("Unable to detect Drupal at $drupalRoot");
        }

PHPStan Drupal should kill early if there were big errors. https://github.com/mglaman/phpstan-drupal/blob/main/src/Drupal/DrupalAut...

Then there is this: https://github.com/mglaman/phpstan-drupal/blob/548fa7cb31239997863bf695f...

    protected function loadLegacyIncludes(): void
    {
        /** @var \SplFileInfo $file */
        foreach (Finder::findFiles('*.inc')->in($this->drupalRoot . '/core/includes') as $file) {
            require_once $file->getPathname();
        }
    }

Is the project a Composer template? Did someone symlink web to docroot instead of modifying the scaffolding directories?

seanr’s picture

StatusFileSize
new4 KB

Someone want to tell me why I can't just upload a .json file without changing the extension? Ugh.

I've attached my composer.json. We do not have a symlink involved (though we've got some other sites where that was done before I got there for whatever reason - what issues can we expect from that?).

mglaman’s picture

what issues can we expect from that?).

I don't think any, but just asking.

Question: what happens when you run drupal-check versus upgrade status?

So

php vendor/bin/drupal-check docroot/modules/custom 

Drupal Check is a custom PHPStan runner just like Upgrade Status. Just a CLI and not module. If drupal-check is OK then something weird is happening in Upgrade Status

seanr’s picture

Yeah, I snagged that while debugging this, was meaning to try that (for the first one of these for another site, I got both side-by-side to compare results and confirmed they matched).

seanr’s picture

Same crud:

 ~/P/c/[redacted] ±  lando ssh -s appserver                                                     10:41:33 AM
www-data@982d640bc34e:/app$ drupal-check -d docroot/modules/custom/
UnexpectedValueException thrown in /app/vendor/nette/finder/src/Utils/Finder.php on line 209 while loading bootstrap file /app/vendor/mglaman/phpstan-drupal/drupal-autoloader.php: RecursiveDirectoryIterator::__construct(/app/core/includes): failed to open dir: No such file or directory
gábor hojtsy’s picture

Title: phpstan-drupal sent wrong path for core » phpstan-drupal identifies Drupal root as a different path from what Drupal root is provided for it

Making title more specific.

seanr’s picture

Wondering if there's anything in particular I should try to help debug this? Happy to try anything since it's all local development anyway, just don't know quite where to start.

mglaman’s picture

@seanr I wish I knew :/. Does lando let you do Xdebug over the CLI? I would try dropping a breakpoint on $finder->locateRoot($drupalRoot); and see why it gets confused.

dvmanjunath’s picture

@mglaman @gábor-hojtsy i'm also facing same issue. But in my case i'm using docksal instead of lando but error is same. Same error when i tried to do drupal-check and rector as well.

UnexpectedValueException thrown in /var/www/vendor/nette/finder/src/Utils/Finder.php on line 209 while loading bootstrap file /var/www/vendor/mglaman/phpstan-drupal/drupal-autoloader.php: RecursiveDirectoryIterator::__construct(/var/www/core/includes): failed to open dir: No such file or directory

It's looking for code at /var/www/core/includes instead /var/www/docroot/core/includes

gábor hojtsy’s picture

I believe @mglaman tracked this down:

https://twitter.com/nmdmatt/status/1432735316952166401

Make sure your Drupal project has a customized "name" in its composer.json. Especially if you had the "drupal/drupal" project and migrated it to a composer build.

Otherwise, webflo/drupal-finder will break and phpstan-drupal/upgrade_status will not work.

There does not seem to be a webflo/drupal-finder issue yet though at https://github.com/webflo/drupal-finder/issues

mglaman’s picture

I don't think this requires a fix in webflo/drupal-finder. Upgrade Status may need to warn users that they haven't modified their composer "name" property. Or that it says drupal/drupal but is a composer build.

Basically, upgrade_status can detect the error itself by running the finder and seeing if it errors as a preflight check.

dvmanjunath’s picture

@mglaman @gábor-hojtsy Thanks a lot. after changing "name": "drupal/drupal" to "name": "drupal/project_specific_name" has worked.

mglaman’s picture

Title: phpstan-drupal identifies Drupal root as a different path from what Drupal root is provided for it » Warn if site's composer.json is named "drupal/drupal" but is a Composer build
Category: Support request » Task

Retitling and moving to Task. This can be an environment check to prevent phpstan-drupal failures.

mglaman’s picture

mglaman’s picture

Linking to #3239749-3: Install issues w/ symfony/css-selector. I wonder if we need more preflight Composer checks as well.

...fix this by removing the nested/synced composer.json in the web subdirectory for my specific site.

gábor hojtsy’s picture

Status: Active » Needs review
StatusFileSize
new1006 bytes

Are we looking for something like this? I tried wording it in a way that people could also understand it as "wrong composer file found" in case they have multiple, and would not necessarily blindly fix the wrong one found. To be honest not sure how to know if we found a "wrong" composer file though? Do we have fingerprinting ways (look for presence of specific keys)?

On the other hand, looking at #3239749: Install issues w/ symfony/css-selector it looks like a pre-Drupal problem with composer, so we cannot add helpful guidance into the module for that.

Status: Needs review » Needs work

The last submitted patch, 21: 3229725.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

gábor hojtsy’s picture

Ok LOL this fails on CI with

The /var/www/html/composer.json file was identified as the composer file for this site. However the "name" property specified is "drupal/drupal". Change this to a custom value. Scanning is not possible until this is resolved.

So if CI has this template and it still works, not sure why it fails for others? Are there other conditions besides the name value that would lead to the failure?

mglaman’s picture

So if CI has this template and it still works, not sure why it fails for others? Are there other conditions besides the name value that would lead to the failure?

CI doesn't have Drupal has a Composer build, but full development trunk clone.

We need to check if the name is drupal/drupal AND it's a Composer build.

My thought was a preflight check which runs webflo/drupal-finder and sees if it fails.

mglaman’s picture

Status: Needs work » Needs review

Added code to check if the core directory cannot be found. If it cannot we try to load the composer.json and check the name property. Added extra warnings along the way to try and bring clarity to this obscure bug.

mglaman’s picture

StatusFileSize
new99.25 KB

I added commit https://git.drupalcode.org/project/upgrade_status/-/merge_requests/13/di... after reading #3230781: Scan and Export buttons are not-clickable. We can split off into a new one, but my dev stream was coming to a close. I opted to push up rather than let it sit for a week.

This makes it a bit more prominent as to why scans cannot be run.

gábor hojtsy’s picture

Status: Needs review » Needs work

I think displaying the dedicated error at the bottom is a very good idea. I think it would still be a good idea to ALSO add the error to the (top/global) messages list. Otherwise some people may end up processing (in their head) the output, picking which ones to scan, etc. just to end up at the bottom where the form tells them it was in vain. So I think displaying the error up top would still be useful. I think displaying it at the bottom is useful for people with banner blindness though :)

I think this would be a matter of not removing that one line where it is added to messages :D

mglaman’s picture

Version: 8.x-3.9 » 8.x-3.x-dev

Perfect! I'll put that back on Wednesday

gábor hojtsy’s picture

Status: Needs work » Needs review
gábor hojtsy’s picture

Status: Needs review » Fixed

Committed this one, thanks a lot!

  • 302eb30 committed on 8.x-3.x
    Issue #3229725 by mglaman, Gábor Hojtsy, seanr, dvmanjunath: Warn if...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.