ClassWriter.php
Same filename in other branches
Namespace
Drupal\TestTools\PhpUnitCompatibility\PhpUnit8File
-
core/
tests/ Drupal/ TestTools/ PhpUnitCompatibility/ PhpUnit8/ ClassWriter.php
View source
<?php
namespace Drupal\TestTools\PhpUnitCompatibility\PhpUnit8;
use Composer\Autoload\ClassLoader;
/**
* 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.
*/
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 (!is_dir($directory) && !@mkdir($directory, 0777, TRUE) && !is_dir($directory)) {
throw new \RuntimeException('Unable to create directory: ' . $directory);
}
file_put_contents($full_path, $altered_code);
}
return $full_path;
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
ClassWriter | Helper class to rewrite PHPUnit's TestCase class. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.