Skip to content

Instantly share code, notes, and snippets.

@thekid
Last active February 18, 2023 21:56
Show Gist options
  • Save thekid/ad6f908f4badbc3460a74a43e9544a86 to your computer and use it in GitHub Desktop.
Save thekid/ad6f908f4badbc3460a74a43e9544a86 to your computer and use it in GitHub Desktop.
<?php namespace test;
use io\streams\LinesIn;
use io\{File, Files, Folder, Path};
use util\cmd\Console;
// Yields all files with a given extension inside a given folder
function filesIn(Folder $folder, string $extension): iterable {
$end= -1 * strlen($extension);
foreach ($folder->entries() as $entry) {
if ($entry->isFolder()) {
yield from filesIn($entry->asFolder(), $extension);
} else if (0 === substr_compare($entry, $extension, $end)) {
yield $entry->asFile();
}
}
}
// Parses an input line into an import
function importIn(string $line): array {
$p= strrpos($line, '\\');
$ns= substr($line, 0, $p);
if ('{' === $line[$p + 1]) {
return ['ns' => $ns, 'classes' => preg_split('/, ?/', substr($line, $p + 2, -2))];
} else {
return ['ns' => $ns, 'classes' => [substr($line, $p + 1, -1)]];
}
}
// Rewrites annotations
function rewriteAnnotations(string $input): string {
static $patterns= [
'/withMessage: /' => 'message: ',
'/Values\(\'(.+)\'\)/' => 'Values(from: \'$1\')',
'/Action\(eval: \'new RuntimeVersion\("([^"]+)"\)\'\)/' => 'Runtime(php: \'$1\')',
'/Action\(eval: \'new VerifyThat\((.+)\)\'\)/' => 'Condition(assert: \'$1\')',
];
return preg_replace(array_keys($patterns), array_values($patterns), $input);
}
// Replace requirement in composer.json
function rewriteYaml(File $input): int {
return Files::write($input, preg_replace(
'/sh xp-run xp\.unittest\.TestRunner/',
'sh xp-run xp.test.Runner',
Files::read($input)
));
}
// Rewrites the code in a given file and returns the performed operations
function rewriteSource(File $input): array {
$out= new File($input->getURI().'.rewrite');
$out->open(File::WRITE);
$operations= [];
foreach (new LinesIn($input->in()) as $i => $line) {
// Remove newlines at the end of the file
if ($i > 1) $out->write("\n");
// Adjust imports from unittest namespace -> test
if (0 === strncmp($line, 'use ', 4)) {
$import= importIn(rtrim(substr($line, 4)));
if ('unittest\\actions' === $import['ns']) {
$import['ns']= 'test\\verify';
foreach ($import['classes'] as &$class) {
$class= strtr($class, ['RuntimeVersion' => 'Runtime', 'VerifyThat' => 'Condition']);
}
$operations[]= 'replaced imports';
} else if ('unittest' === $import['ns']) {
$import['ns']= 'test';
$operations[]= 'replaced imports';
}
if (1 === sizeof($import['classes'])) {
$line= 'use '.$import['ns'].'\\'.$import['classes'][0].';';
} else {
sort($import['classes']);
$line= 'use '.$import['ns'].'\\{'.implode(', ', $import['classes']).'};';
}
}
// Rewrite annotations
if (preg_match('/(\s*)#\[(.+)\]\s?$/s', $line, $matches)) {
$line= $matches[1].'#['.rewriteAnnotations($matches[2]).']';
}
$out->write($line);
}
$out->close();
if (empty($operations)) {
$out->unlink();
} else {
$out->move($input);
}
return $operations;
}
$module= realpath($argv[1]);
$composer= new File($module, 'composer.json');
$paths= \xp\pathfiles($module);
if (!$composer->exists() || empty($paths)) {
Console::writeLine('No composer.json and no pathfiles found in ', $argv[1], ' - not a module?');
return 1;
}
// Rewrite code in all paths in-place
foreach ($paths as $path) {
$resolved= realpath($module.DIRECTORY_SEPARATOR.$path);
if (!is_dir($resolved) || 0 !== strncmp($module, $resolved, strlen($module))) continue;
Console::writeLine('> Rewrite sources in ', $path);
foreach (filesIn(new Folder($resolved), '.php') as $origin) {
Console::writeLine(' * ', $origin, ': ', rewriteSource($origin));
}
}
// Replace requirement in composer.json
Files::write($composer, preg_replace(
'/"xp-framework\/unittest"([ :]+)"[^"]+"/',
'"xp-framework/test"$1"^1.0"',
Files::read($composer)
));
// Rewrite .github
$github= new Folder($module, '.github');
if ($github->exists()) {
foreach (filesIn($github, '.yml') as $origin) {
Console::writeLine(' * ', $origin, ': ', rewriteYaml($origin));
}
}
Console::writeLine();
Console::writeLine('Done, now run `composer up` and then `xp test`');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment