function TemplateProjectTestBase::createTestProject

Creates a test project from a given template and installs Drupal.

Parameters

string $template: The template to use. Can be 'RecommendedProject' or 'LegacyProject'.

File

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

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 createTestProject(string $template) : void {
    // Create a copy of core (including its Composer plugins, templates, and
    // metapackages) which we can modify.
    $this->copyCodebase();
    $workspace_dir = $this->getWorkspaceDirectory();
    $project_dir = $workspace_dir . '/project';
    mkdir($project_dir);
    $data = file_get_contents("{$workspace_dir}/composer/Template/{$template}/composer.json");
    $data = json_decode($data, TRUE, flags: JSON_THROW_ON_ERROR);
    // Allow pre-release versions of dependencies.
    $data['minimum-stability'] = 'dev';
    // Remove all repositories and replace them with a single local one that
    // provides all dependencies.
    $data['repositories'] = [
        'vendor' => [
            'type' => 'composer',
            'url' => 'file://' . $workspace_dir . '/vendor.json',
        ],
        // Disable Packagist entirely so that we don't test the Internet.
'packagist.org' => FALSE,
    ];
    // Allow any version of the Drupal core packages in the template project.
    self::unboundCoreConstraints($data['require']);
    self::unboundCoreConstraints($data['require-dev']);
    // Do not run development Composer plugin, since it tries to run an
    // executable that might not exist while dependencies are being installed.
    // It adds no value to this test.
    $data['config']['allow-plugins']['dealerdirect/phpcodesniffer-composer-installer'] = FALSE;
    // Always force Composer to mirror path repositories. This is necessary
    // because dependencies are installed from a Composer-type repository, which
    // will normally try to symlink packages which are installed from local
    // directories. This breaks Package Manager, because it does not support
    // symlinks pointing outside the main code base.
    $script = '@putenv COMPOSER_MIRROR_PATH_REPOS=1';
    $data['scripts']['pre-install-cmd'] = $script;
    $data['scripts']['pre-update-cmd'] = $script;
    file_put_contents($project_dir . '/composer.json', json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
    // Because we set the COMPOSER_MIRROR_PATH_REPOS=1 environment variable when
    // creating the project, none of the dependencies should be symlinked.
    $this->assertStringNotContainsString('Symlinking', $this->runComposer('composer install', 'project'));
    // If using the drupal/recommended-project template, we don't expect there
    // to be an .htaccess file at the project root. One would normally be
    // generated by Composer when Package Manager or other code creates a
    // ComposerInspector object in the active directory, except that Package
    // Manager takes specific steps to prevent that. So, here we're just
    // confirming that, in fact, Composer's .htaccess protection was disabled.
    // We don't do this for the drupal/legacy-project template because its
    // project root, which is also the document root, SHOULD contain a .htaccess
    // generated by Drupal core.
    // We do this check because this test uses PHP's built-in web server, which
    // ignores .htaccess files and everything in them, so a Composer-generated
    // .htaccess file won't cause this test to fail.
    if ($template === 'RecommendedProject') {
        $this->assertFileDoesNotExist("{$workspace_dir}/project/.htaccess");
    }
    // Now that we know the project was created successfully, we can set the
    // web root with confidence.
    $this->webRoot = 'project/' . $data['extra']['drupal-scaffold']['locations']['web-root'];
    // Install Drupal.
    $this->installQuickStart('standard');
    $this->formLogin($this->adminUsername, $this->adminPassword);
    // When checking for updates, we need to be able to make sub-requests, but
    // the built-in PHP server is single-threaded. Therefore, open a second
    // server instance on another port, which will serve the metadata about
    // available updates.
    $port = $this->findAvailablePort();
    $this->metadataServer = $this->instantiateServer($port);
    $code = <<<END
\$config['update.settings']['fetch']['url'] = 'http://localhost:{<span class="php-variable">$port</span>}/test-release-history';
END;
    // Ensure Package Manager logs Composer Stager's process output to a file
    // named for the current test.
    $log = $this->getDrupalRoot() . '/sites/simpletest/browser_output';
    @mkdir($log, recursive: TRUE);
    $this->assertDirectoryIsWritable($log);
    $log .= '/' . str_replace('\\', '_', static::class) . '-' . $this->name();
    if ($this->usesDataProvider()) {
        $log .= '-' . preg_replace('/[^a-z0-9]+/i', '_', $this->dataName());
    }
    $code .= <<<END
\$config['package_manager.settings']['log'] = '{<span class="php-variable">$log</span>}-package_manager.log';
END;
    $this->writeSettings($code);
    // Install helpful modules.
    $this->installModules([
        'package_manager_test_api',
        'package_manager_test_event_logger',
        'package_manager_test_release_history',
    ]);
    // Confirm the server time out settings.
    // @see \Drupal\Tests\package_manager\Build\TemplateProjectTestBase::instantiateServer()
    $this->visit('/package-manager-test-api/check-setup');
    $this->getMink()
        ->assertSession()
        ->pageTextContains("max_execution_time=" . static::MAX_EXECUTION_TIME . ":set_time_limit-exists=no");
}

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