craftcms / plugin-installer

Composer installer for Craft CMS plugins.
MIT License
28 stars 3 forks source link

Plugin installer throws Unable to determine the base path during composer update #10

Open matfish2 opened 3 years ago

matfish2 commented 3 years ago

Description

When installing plugins, sometimes composer update/install will abort with the following error:

  [craft\composer\InvalidPluginException]                                         
  Couldn't install some/plugin: Unable to determine the base path  

Or

 [craft\composer\InvalidPluginException]                                         
  Couldn't install some/plugin: Unable to determine the Plugin class

Steps to reproduce

Unfortunately that seems to happen only on some environments, and even then inconsistently, so it might be difficult to reproduce. I'm running composer update from a laravel homestead VM. Linux homestead 5.4.0-81-generic #91-Ubuntu SMP Thu Jul 15 19:09:17 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

I have traced the error to plugin-installer/Installer.php:124-131 both $class and $basePath are null, because they are not included in the $extra = $package->getExtra(); response.

I have run:

rm -rf vendor
rm composer.lock
composer clearcache
composer install

But to no avail.

I have noticed this bug was reported on some individual plugins, but it seems like it's a craft issue, since I'm getting this for multiple plugins.

Additional info

brandonkelly commented 3 years ago

both $class and $basePath are null, because they are not included in the $extra = $package->getExtra(); response.

If extra.class is not defined within the plugin’s composer.json file, then the installer will look for a Plugin.php file within each of the plugin’s autoload paths:

https://github.com/craftcms/plugin-installer/blob/23ec472acd4410b70b07d5a02b2b82db9ee3f66b/src/Installer.php#L324-L327

If it can’t find one, you will get the “Unable to determine the Plugin class” error.

The base path is then set to the directory that contains the Plugin class:

https://github.com/craftcms/plugin-installer/blob/23ec472acd4410b70b07d5a02b2b82db9ee3f66b/src/Installer.php#L329-L341

I’m not really sure what to make of this not working inconsistently. Is there any chance we can get SSH access to an environment where this occurs? If so, please send the connection info to support@craftcms.com.

matfish2 commented 3 years ago

I've narrowed it down to lines 335-338 $testClassPath is set to /home/vagrant/code/mcl-craft/vendor/nystudio107/craft-seomatic/src/Seomatic.php Which is correct. However, the file_exists check returns false.

Commenting out the if statement on line 336, fixes the issue for me.

One more option that worked was adding sleep(1) before line 336. It appears to be a syncing of shared folders issue then, though I'm running composer from the VM, not the Windows host, so I fail to see how it is related.

In conclusion a suggested fix would be something like:

$attempts = 0;

do {
  if ($attempts>0) {
      sleep(1);
  }

  if (file_exists($testClassPath)) {
      $basePath = $this->_path($vendorDir, $cwd, dirname($testClassPath));
  }

  $attempts++;
} while (!$basePath && $attempts <= 2);