MDL-87717 core: Update for composer in parent directory
Co-authored-by: Andrew Nicols <[email protected]>
This commit is contained in:
co-authored by
Andrew Nicols
parent
746815af49
commit
1cf6bd8b87
@@ -204,6 +204,16 @@ class component {
|
||||
spl_autoload_register([self::class, 'classloader']);
|
||||
}
|
||||
|
||||
// Attempt to load the Composer autoloader from the Moodle root.
|
||||
// In composer scaffolded installations this is a shim which delegates to the parent project.
|
||||
global $CFG;
|
||||
if (!empty($CFG->root)) {
|
||||
$composerautoload = "{$CFG->root}/vendor/autoload.php";
|
||||
if (is_file($composerautoload)) {
|
||||
require_once($composerautoload);
|
||||
}
|
||||
}
|
||||
|
||||
// Load any composer-driven autoload files.
|
||||
// This is intended to mimic the behaviour of the standard Composer Autoloader.
|
||||
foreach (static::$composerautoloadfiles as $file) {
|
||||
|
||||
@@ -24,6 +24,26 @@ namespace core;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class environment {
|
||||
|
||||
/**
|
||||
* Get the Composer root install path for the active Composer runtime.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected static function get_composer_root_install_path(): ?string {
|
||||
if (!class_exists(\Composer\InstalledVersions::class)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$rootpackage = \Composer\InstalledVersions::getRootPackage();
|
||||
if (!is_array($rootpackage) || empty($rootpackage['install_path'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$realpath = realpath($rootpackage['install_path']);
|
||||
return $realpath ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that Composer dependencies are installed and the necessary files are present.
|
||||
*
|
||||
@@ -32,24 +52,7 @@ class environment {
|
||||
*/
|
||||
public static function check_composer_dependencies_installed(\environment_results $result): ?\environment_results {
|
||||
// Check if the composer vendor directory exists.
|
||||
$vendorpath = static::get_vendor_path();
|
||||
if (!is_dir($vendorpath)) {
|
||||
$result->setInfo('Composer vendor directory not found');
|
||||
$result->setFeedbackStr('composernotfound');
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Check if the composer autoload file exists.
|
||||
$autoloadpath = "{$vendorpath}/autoload.php";
|
||||
if (!is_file($autoloadpath)) {
|
||||
$result->setInfo('Composer autoload file not found');
|
||||
$result->setFeedbackStr('composernotfound');
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Check if the installed.php file exists in the composer directory.
|
||||
$installedpath = "{$vendorpath}/composer/installed.php";
|
||||
if (!is_file($installedpath)) {
|
||||
if (!class_exists(\Composer\InstalledVersions::class)) {
|
||||
$result->setInfo('Composer installed data not found');
|
||||
$result->setFeedbackStr('composernotfound');
|
||||
return $result;
|
||||
@@ -72,21 +75,34 @@ class environment {
|
||||
return null; // Skip this check in developer mode.
|
||||
}
|
||||
|
||||
$vendorpath = static::get_vendor_path();
|
||||
if (!is_dir($vendorpath)) {
|
||||
return null; // No vendor directory, so no developer dependencies to check.
|
||||
if (!class_exists(\Composer\InstalledVersions::class)) {
|
||||
return null; // Composer not installed, so no developer dependencies to check.
|
||||
}
|
||||
|
||||
// Check if the installed.php file exists in the composer directory.
|
||||
$installedpath = "{$vendorpath}/composer/installed.php";
|
||||
if (!is_file($installedpath)) {
|
||||
return null; // No installed file, so no developer dependencies to check.
|
||||
$installed = \Composer\InstalledVersions::getAllRawData();
|
||||
if (!is_array($installed)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if developer dependencies have been installed too.
|
||||
$installed = include($installedpath);
|
||||
if (is_array($installed) && array_key_exists('root', $installed)) {
|
||||
if ($installed['root']['dev']) {
|
||||
// Only consider the installed data set which matches the active Composer root.
|
||||
// This reduces the risk of reporting false positives if multiple Composer autoloaders
|
||||
// have been included in the same process.
|
||||
$rootinstallpath = static::get_composer_root_install_path();
|
||||
if ($rootinstallpath === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($installed as $data) {
|
||||
if (!is_array($data) || !array_key_exists('root', $data) || !is_array($data['root'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$installpath = $data['root']['install_path'] ?? null;
|
||||
if (empty($installpath) || realpath($installpath) !== $rootinstallpath) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($data['root']['dev'])) {
|
||||
$result->setInfo('Composer Developer dependencies are installed');
|
||||
$result->setFeedbackStr('composerdeveloperdependenciesinstalled');
|
||||
return $result;
|
||||
@@ -106,12 +122,27 @@ class environment {
|
||||
public static function check_composer_dependencies_optimised(
|
||||
\environment_results $result
|
||||
): ?\environment_results {
|
||||
$vendorpath = static::get_vendor_path();
|
||||
if (!is_dir($vendorpath)) {
|
||||
return null; // No vendor directory, so no developer dependencies to check.
|
||||
if (!class_exists(\Composer\InstalledVersions::class)) {
|
||||
return null; // Composer not installed, so no developer dependencies to check.
|
||||
}
|
||||
|
||||
$autoloader = require("{$vendorpath}/autoload.php");
|
||||
$rootpackage = \Composer\InstalledVersions::getRootPackage();
|
||||
if (!is_array($rootpackage) || empty($rootpackage['install_path'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$rootpath = $rootpackage['install_path'];
|
||||
$rootvendor = realpath("{$rootpath}/vendor");
|
||||
if (!$rootvendor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$loaders = \Composer\Autoload\ClassLoader::getRegisteredLoaders();
|
||||
if (!array_key_exists($rootvendor, $loaders)) {
|
||||
return null; // No autoloader for our vendor dir, so nothing to check.
|
||||
}
|
||||
|
||||
$autoloader = $loaders[$rootvendor];
|
||||
|
||||
if (static::is_developer_mode_enabled()) {
|
||||
if ($autoloader->isClassMapAuthoritative()) {
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace core\tests;
|
||||
*/
|
||||
class environment extends \core\environment {
|
||||
/** @var string|null The path to the vendor dir if modified */
|
||||
protected static ?string $vendorpath;
|
||||
protected static ?string $vendorpath = null;
|
||||
|
||||
/** @var bool|null Whether developer mode is enabled, or defer to $CFG */
|
||||
protected static ?bool $devmode = null;
|
||||
|
||||
@@ -28,50 +28,6 @@ use core\tests\environment as environment_tester;
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(environment::class)]
|
||||
final class environment_test extends \advanced_testcase {
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('composer_error_states_provider')]
|
||||
public function test_composer_not_installed_cases(
|
||||
array $fs = [],
|
||||
string $expectedfeedback = 'composernotfound'
|
||||
): void {
|
||||
\org\bovigo\vfs\vfsStream::setup('root', null, $fs);
|
||||
environment_tester::set_vendor_path(\org\bovigo\vfs\vfsStream::url('root/vendor'));
|
||||
|
||||
$result = new \environment_results('custom_check');
|
||||
$result = environment_tester::check_composer_dependencies_installed($result);
|
||||
$this->assertEquals($expectedfeedback, $result->getFeedbackStr());
|
||||
|
||||
// Check that the developer dependencies tests do not error in these conditions.
|
||||
$result = new \environment_results('custom_check');
|
||||
$result = environment_tester::check_composer_developer_dependencies_not_installed($result);
|
||||
$this->assertNull($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_composer_not_installed_cases.
|
||||
*
|
||||
* @return \Generator
|
||||
*/
|
||||
public static function composer_error_states_provider(): \Generator {
|
||||
yield 'composer vendor directory not found' => [
|
||||
'fs' => [],
|
||||
'expectedfeedback' => 'composernotfound',
|
||||
];
|
||||
yield 'composer autoload file not found' => [
|
||||
'fs' => [
|
||||
'vendor' => [],
|
||||
],
|
||||
'expectedfeedback' => 'composernotfound',
|
||||
];
|
||||
yield 'composer installed data not found' => [
|
||||
'fs' => [
|
||||
'vendor' => [
|
||||
'autoload.php' => '',
|
||||
],
|
||||
],
|
||||
'expectedfeedback' => 'composernotfound',
|
||||
];
|
||||
}
|
||||
|
||||
public function test_composer_installed(): void {
|
||||
\org\bovigo\vfs\vfsStream::setup('root', null, [
|
||||
'vendor' => [
|
||||
|
||||
Reference in New Issue
Block a user