function TemplateProjectTestBase::createVendorRepository

Creates a Composer repository for all dependencies of the test project.

We always reference third-party dependencies (i.e., any package that isn't part of Drupal core) from the main project which is running this test.

Packages that are part of Drupal core -- such as `drupal/core`, `drupal/core-composer-scaffold`, and so on -- are expected to have been copied into the workspace directory, so that we can modify them as needed.

The file will be written to WORKSPACE_DIR/vendor.json.

Parameters

string[] $versions: (optional) The versions of specific packages, keyed by package name. Versions of packages not in this array will be determined first by looking for a `version` key in the package's composer.json, then by calling \Composer\InstalledVersions::getPrettyVersion(). If none of that works, `dev-main` will be used as the package's version.

2 calls to TemplateProjectTestBase::createVendorRepository()
TemplateProjectTestBase::copyCodebase in core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php
Copy the current working codebase into a workspace.
TemplateProjectTestBase::setUpstreamCoreVersion in core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php
Sets the version of Drupal core to which the test site will be updated.

File

core/modules/package_manager/tests/src/Build/TemplateProjectTestBase.php, line 407

Class

TemplateProjectTestBase
Base class for tests which create a test site from a core project template.

Namespace

Drupal\Tests\package_manager\Build

Code

protected function createVendorRepository(array $versions = []) : void {
  $packages = [];
  $class_loaders = ClassLoader::getRegisteredLoaders();
  $workspace_dir = $this->getWorkspaceDirectory();
  $finder = Finder::create()->in([
    $this->getWorkspaceDrupalRoot() . '/core',
    "{$workspace_dir}/composer/Metapackage",
    "{$workspace_dir}/composer/Plugin",
    key($class_loaders),
  ])
    ->depth('< 3')
    ->files()
    ->name('composer.json');
  /** @var \Symfony\Component\Finder\SplFileInfo $file */
  foreach ($finder as $file) {
    $package_info = json_decode($file->getContents(), TRUE, flags: JSON_THROW_ON_ERROR);
    $name = $package_info['name'];
    $requirements = $package_info['require'] ?? [];
    // These polyfills are dependencies of some packages, but for reasons we
    // don't understand, they are not installed in code bases built on PHP
    // versions that are newer than the ones being polyfilled, which means we
    // won't be able to build our test project because these polyfills aren't
    // available in the local code base. Since we're guaranteed to be on PHP
    // 8.3 or later, no package should need to polyfill older versions.
    unset($requirements['symfony/polyfill-php72'], $requirements['symfony/polyfill-php73'], $requirements['symfony/polyfill-php74'], $requirements['symfony/polyfill-php80'], $requirements['symfony/polyfill-php81'], $requirements['symfony/polyfill-php82'], $requirements['symfony/polyfill-php83'], $requirements['symfony/polyfill-php84']);
    // If this package requires any Drupal core packages, ensure it allows
    // any version.
    self::unboundCoreConstraints($requirements);
    // In certain situations, like specific CI environments, auto_updates
    // might be required into the code base by Composer. This may cause it to
    // be added to the drupal/core-recommended metapackage, which can prevent
    // the test site from being built correctly, among other deleterious
    // effects. To prevent such shenanigans, always remove drupal/auto_updates
    // from drupal/core-recommended.
    if ($name === 'drupal/core-recommended') {
      unset($requirements['drupal/auto_updates']);
    }
    try {
      $version = $versions[$name] ?? $package_info['version'] ?? InstalledVersions::getPrettyVersion($name);
    } catch (\OutOfBoundsException) {
      $version = 'dev-main';
    }
    // Create a pared-down package definition that has just enough information
    // for Composer to install the package from the local copy: the name,
    // version, package type, source path ("dist" in Composer terminology),
    // and the autoload information, so that the classes provided by the
    // package will actually be loadable in the test site we're building.
    $path = $file->getPath();
    $packages[$name][$version] = [
      'name' => $name,
      'version' => $version,
      'type' => $package_info['type'] ?? 'library',
      // Disabling symlinks in the transport options doesn't seem to have an
      // effect, so we use the COMPOSER_MIRROR_PATH_REPOS environment
      // variable to force mirroring in ::createTestProject().
'dist' => [
        'type' => 'path',
        'url' => $path,
      ],
      'require' => $requirements,
      'autoload' => $package_info['autoload'] ?? [],
      'provide' => $package_info['provide'] ?? [],
      // Composer plugins are loaded and activated as early as possible, and
      // they must have a `class` key defined in their `extra` section, along
      // with a dependency on `composer-plugin-api` (plus any other real
      // runtime dependencies). This is also necessary for packages that ship
      // scaffold files, like Drupal core.
'extra' => $package_info['extra'] ?? [],
    ];
  }
  $data = json_encode([
    'packages' => $packages,
  ], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
  file_put_contents($workspace_dir . '/vendor.json', $data);
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.