final class ClassWriter in Drupal 9
Helper class to rewrite PHPUnit's TestCase class.
This class contains static methods only and is not meant to be instantiated.
@internal This should only be called by test running code. Drupal 9 will provide best effort to maintain this class for the Drupal 9 cycle. However if changes to PHP or PHPUnit make this impossible then support will be removed.
Hierarchy
- class \Drupal\TestTools\PhpUnitCompatibility\PhpUnit8\ClassWriter
Expanded class hierarchy of ClassWriter
2 files declare their use of ClassWriter
- bootstrap.php in core/
tests/ bootstrap.php - Autoloader for Drupal PHPUnit testing.
- TestDiscovery.php in core/
lib/ Drupal/ Core/ Test/ TestDiscovery.php
File
- core/
tests/ Drupal/ TestTools/ PhpUnitCompatibility/ PhpUnit8/ ClassWriter.php, line 17
Namespace
Drupal\TestTools\PhpUnitCompatibility\PhpUnit8View source
final class ClassWriter {
/**
* This class should not be instantiated.
*/
private function __construct() {
}
/**
* Mutates PHPUnit classes to make it compatible with Drupal.
*
* @param \Composer\Autoload\ClassLoader $autoloader
* The autoloader.
*
* @throws \ReflectionException
*/
public static function mutateTestBase($autoloader) {
static::alterAssert($autoloader);
static::alterTestCase($autoloader);
}
/**
* Alters the Assert class.
*
* @param \Composer\Autoload\ClassLoader $autoloader
* The autoloader.
*
* @throws \ReflectionException
*/
private static function alterAssert(ClassLoader $autoloader) : void {
// If the class exists already there is nothing we can do. Hopefully this
// is happening because this has been called already. The call from
// \Drupal\Core\Test\TestDiscovery::registerTestNamespaces() necessitates
// this protection.
if (class_exists('PHPUnit\\Framework\\Assert', FALSE)) {
return;
}
// Mutate Assert code to make it forward compatible with different PhpUnit
// versions, by adding Symfony's PHPUnit-bridge PolyfillAssertTrait.
$alteredFile = $autoloader
->findFile('PHPUnit\\Framework\\Assert');
$phpunit_dir = dirname($alteredFile, 3);
$alteredCode = file_get_contents($alteredFile);
$alteredCode = preg_replace('/abstract class Assert[^\\{]+\\{/', '$0 ' . \PHP_EOL . " use \\Symfony\\Bridge\\PhpUnit\\Legacy\\PolyfillAssertTrait;" . \PHP_EOL, $alteredCode, 1);
include static::flushAlteredCodeToFile('Assert.php', $alteredCode);
}
/**
* Alters the TestCase class.
*
* @param \Composer\Autoload\ClassLoader $autoloader
* The autoloader.
*
* @throws \ReflectionException
*/
private static function alterTestCase(ClassLoader $autoloader) : void {
// If the class exists already there is nothing we can do. Hopefully this
// is happening because this has been called already. The call from
// \Drupal\Core\Test\TestDiscovery::registerTestNamespaces() necessitates
// this protection.
if (class_exists('PHPUnit\\Framework\\TestCase', FALSE)) {
return;
}
// Mutate TestCase code to make it forward compatible with different PhpUnit
// versions, by adding Symfony's PHPUnit-bridge PolyfillTestCaseTrait.
$alteredFile = $autoloader
->findFile('PHPUnit\\Framework\\TestCase');
$phpunit_dir = dirname($alteredFile, 3);
$alteredCode = file_get_contents($alteredFile);
$alteredCode = preg_replace('/abstract class TestCase[^\\{]+\\{/', '$0 ' . \PHP_EOL . " use \\Symfony\\Bridge\\PhpUnit\\Legacy\\PolyfillTestCaseTrait;" . \PHP_EOL, $alteredCode, 1);
$alteredCode = str_replace("__DIR__ . '/../Util/", "'{$phpunit_dir}/src/Util/", $alteredCode);
// While Drupal still allows methods in test base classes that inherit from
// TestCase with no void return typehints specified, we also alter TestCase
// to remove the typehints.
// @see https://www.drupal.org/project/drupal/issues/3182103
$alteredCode = preg_replace('/^ ((?:protected|public)(?: static)? function \\w+\\(\\)): void/m', ' $1', $alteredCode);
include static::flushAlteredCodeToFile('TestCase.php', $alteredCode);
}
/**
* Flushes altered class code to file when necessary.
*
* @param string $file_name
* The file name.
* @param string $altered_code
* The altered code.
*
* @return string
* The full path of the file to be included.
*/
private static function flushAlteredCodeToFile(string $file_name, string $altered_code) : string {
$directory = __DIR__ . '/../../../../../../sites/simpletest';
$full_path = $directory . '/' . $file_name;
// Only write when necessary.
if (!file_exists($full_path) || md5_file($full_path) !== md5($altered_code)) {
// Create directory when necessary.
if (!file_exists($directory)) {
mkdir($directory, 0777, TRUE);
}
file_put_contents($full_path, $altered_code);
}
return $full_path;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
ClassWriter:: |
private static | function | Alters the Assert class. | |
ClassWriter:: |
private static | function | Alters the TestCase class. | |
ClassWriter:: |
private static | function | Flushes altered class code to file when necessary. | |
ClassWriter:: |
public static | function | Mutates PHPUnit classes to make it compatible with Drupal. | |
ClassWriter:: |
private | function | This class should not be instantiated. |