mirror of
https://github.com/pestphp/pest.git
synced 2026-03-10 09:47:23 +01:00
Fixes --version and --help
This commit is contained in:
@ -59,16 +59,18 @@ final class BootFiles
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given filename, if possible.
|
||||
* Loads, if possible, the given file.
|
||||
*/
|
||||
private function load(string $filename): void
|
||||
{
|
||||
if (! Str::endsWith($filename, '.php')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! file_exists($filename)) {
|
||||
return;
|
||||
}
|
||||
|
||||
include_once $filename;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ namespace Pest\Bootstrappers;
|
||||
|
||||
use Pest\Subscribers;
|
||||
use PHPUnit\Event;
|
||||
use PHPUnit\Event\Subscriber;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -15,7 +16,7 @@ final class BootSubscribers
|
||||
/**
|
||||
* The Kernel subscribers.
|
||||
*
|
||||
* @var array<int, class-string<\PHPUnit\Event\Subscriber>>
|
||||
* @var array<int, class-string<Subscriber>>
|
||||
*/
|
||||
private const SUBSCRIBERS = [
|
||||
Subscribers\EnsureConfigurationIsValid::class,
|
||||
|
||||
28
src/Bootstrappers/BootView.php
Normal file
28
src/Bootstrappers/BootView.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Bootstrappers;
|
||||
|
||||
use Pest\Support\View;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class BootView
|
||||
{
|
||||
public function __construct(
|
||||
private readonly OutputInterface $output
|
||||
) {
|
||||
// ..
|
||||
}
|
||||
|
||||
/**
|
||||
* Boots the view renderer.
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
View::renderUsing($this->output);
|
||||
}
|
||||
}
|
||||
16
src/Contracts/Plugins/Bootable.php
Normal file
16
src/Contracts/Plugins/Bootable.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Contracts\Plugins;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface Bootable
|
||||
{
|
||||
/**
|
||||
* Boots the plugin.
|
||||
*/
|
||||
public function boot(): void;
|
||||
}
|
||||
16
src/Contracts/Plugins/Shutdownable.php
Normal file
16
src/Contracts/Plugins/Shutdownable.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Contracts\Plugins;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface Shutdownable
|
||||
{
|
||||
/**
|
||||
* Shutdowns the plugin.
|
||||
*/
|
||||
public function shutdown(): void;
|
||||
}
|
||||
@ -4,6 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Pest;
|
||||
|
||||
use Pest\Plugins\Actions\CallsAddsOutput;
|
||||
use Pest\Plugins\Actions\CallsBoot;
|
||||
use Pest\Plugins\Actions\CallsShutdown;
|
||||
use Pest\Support\Container;
|
||||
use PHPUnit\TextUI\Application;
|
||||
use PHPUnit\TextUI\Exception;
|
||||
|
||||
@ -21,6 +25,7 @@ final class Kernel
|
||||
Bootstrappers\BootExceptionHandler::class,
|
||||
Bootstrappers\BootSubscribers::class,
|
||||
Bootstrappers\BootFiles::class,
|
||||
Bootstrappers\BootView::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@ -29,7 +34,13 @@ final class Kernel
|
||||
public function __construct(
|
||||
private readonly Application $application
|
||||
) {
|
||||
// ..
|
||||
register_shutdown_function(function (): void {
|
||||
if (error_get_last() !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -38,9 +49,11 @@ final class Kernel
|
||||
public static function boot(): self
|
||||
{
|
||||
foreach (self::BOOTSTRAPPERS as $bootstrapper) {
|
||||
(new $bootstrapper())->__invoke();
|
||||
Container::getInstance()->get($bootstrapper)->__invoke();
|
||||
}
|
||||
|
||||
(new CallsBoot())->__invoke();
|
||||
|
||||
return new self(new Application());
|
||||
}
|
||||
|
||||
@ -53,13 +66,13 @@ final class Kernel
|
||||
*/
|
||||
public function handle(array $argv): int
|
||||
{
|
||||
$argv = (new Plugins\Actions\HandleArguments())->__invoke($argv);
|
||||
$argv = (new Plugins\Actions\CallsHandleArguments())->__invoke($argv);
|
||||
|
||||
$this->application->run(
|
||||
$argv, false,
|
||||
);
|
||||
|
||||
return (new Plugins\Actions\AddsOutput())->__invoke(
|
||||
return (new CallsAddsOutput())->__invoke(
|
||||
Result::exitCode(),
|
||||
);
|
||||
}
|
||||
@ -69,6 +82,6 @@ final class Kernel
|
||||
*/
|
||||
public function shutdown(): void
|
||||
{
|
||||
// ..
|
||||
(new CallsShutdown())->__invoke();
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ use Pest\Plugin\Loader;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class AddsOutput
|
||||
final class CallsAddsOutput
|
||||
{
|
||||
/**
|
||||
* Executes the Plugin action.
|
||||
29
src/Plugins/Actions/CallsBoot.php
Normal file
29
src/Plugins/Actions/CallsBoot.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Plugins\Actions;
|
||||
|
||||
use Pest\Contracts\Plugins;
|
||||
use Pest\Plugin\Loader;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class CallsBoot
|
||||
{
|
||||
/**
|
||||
* Executes the Plugin action.
|
||||
*
|
||||
* Provides an opportunity for any plugins to boot..
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$plugins = Loader::getPlugins(Plugins\Bootable::class);
|
||||
|
||||
/** @var Plugins\Bootable $plugin */
|
||||
foreach ($plugins as $plugin) {
|
||||
$plugin->boot();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -10,7 +10,7 @@ use Pest\Plugin\Loader;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class HandleArguments
|
||||
final class CallsHandleArguments
|
||||
{
|
||||
/**
|
||||
* Executes the Plugin action.
|
||||
29
src/Plugins/Actions/CallsShutdown.php
Normal file
29
src/Plugins/Actions/CallsShutdown.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Plugins\Actions;
|
||||
|
||||
use Pest\Contracts\Plugins;
|
||||
use Pest\Plugin\Loader;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class CallsShutdown
|
||||
{
|
||||
/**
|
||||
* Executes the Plugin action.
|
||||
*
|
||||
* Provides an opportunity for any plugins to shutdown.
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$plugins = Loader::getPlugins(Plugins\Shutdownable::class);
|
||||
|
||||
/** @var Plugins\Shutdownable $plugin */
|
||||
foreach ($plugins as $plugin) {
|
||||
$plugin->shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
105
src/Plugins/Help.php
Normal file
105
src/Plugins/Help.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Plugins;
|
||||
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use Pest\Support\View;
|
||||
use function Pest\version;
|
||||
use PHPUnit\TextUI\Help as PHPUnitHelp;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class Help implements HandlesArguments
|
||||
{
|
||||
use Concerns\HandleArguments;
|
||||
|
||||
/**
|
||||
* Creates a new Plugin instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly OutputInterface $output
|
||||
) {
|
||||
// ..
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleArguments(array $arguments): array
|
||||
{
|
||||
if ($this->hasArgument('--help', $arguments)) {
|
||||
View::render('version', [
|
||||
'version' => version(),
|
||||
]);
|
||||
|
||||
View::render('usage');
|
||||
|
||||
foreach ($this->getContent() as $title => $options) {
|
||||
if ($title === 'Usage') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->output->writeln([
|
||||
'',
|
||||
sprintf(' <fg=blue;options=bold>%s:</>', mb_strtoupper($title)),
|
||||
]);
|
||||
|
||||
foreach ($options as $option) {
|
||||
if (! array_key_exists('arg', $option)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[
|
||||
'arg' => $argument,
|
||||
'desc' => $description,
|
||||
] = $option;
|
||||
|
||||
View::render('components.two-column-detail', [
|
||||
'left' => $argument,
|
||||
'right' => $description,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->output->write('', true);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<int, array{arg?: string, desc: string}>>
|
||||
*/
|
||||
private function getContent(): array
|
||||
{
|
||||
// Access the PHPUnit help class's private const HELP
|
||||
$helpReflection = new \ReflectionClass(PHPUnitHelp::class);
|
||||
|
||||
/** @var array<string, array<int, array{arg: string, desc: string}>> $content */
|
||||
$content = $helpReflection->getConstant('HELP_TEXT');
|
||||
|
||||
$content['Configuration'] = [[
|
||||
'arg' => '--init',
|
||||
'desc' => 'Initialise a standard Pest configuration',
|
||||
]] + $content['Configuration'];
|
||||
|
||||
$content['Code Coverage'] = [
|
||||
[
|
||||
'arg' => '--coverage ',
|
||||
'desc' => 'Generate code coverage report and output to standard output',
|
||||
],
|
||||
[
|
||||
'arg' => '--coverage --min',
|
||||
'desc' => 'Set the minimum required coverage percentage, and fail if not met',
|
||||
],
|
||||
] + $content['Code Coverage'];
|
||||
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
@ -5,8 +5,8 @@ declare(strict_types=1);
|
||||
namespace Pest\Plugins;
|
||||
|
||||
use Pest\Contracts\Plugins\HandlesArguments;
|
||||
use Pest\Support\View;
|
||||
use function Pest\version;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@ -15,24 +15,17 @@ final class Version implements HandlesArguments
|
||||
{
|
||||
use Concerns\HandleArguments;
|
||||
|
||||
/**
|
||||
* Creates a new Plugin instance.
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly OutputInterface $output
|
||||
) {
|
||||
// ..
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function handleArguments(array $arguments): array
|
||||
{
|
||||
if ($this->hasArgument('--version', $arguments)) {
|
||||
$this->output->writeln(
|
||||
sprintf('Pest %s', version()),
|
||||
);
|
||||
View::render('version', [
|
||||
'version' => version(),
|
||||
]);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
|
||||
@ -35,16 +35,21 @@ final class Container
|
||||
/**
|
||||
* Gets a dependency from the container.
|
||||
*
|
||||
* @param class-string $id
|
||||
* @return mixed
|
||||
* @template TObject of object
|
||||
*
|
||||
* @param class-string<TObject> $id
|
||||
* @return TObject
|
||||
*/
|
||||
public function get(string $id)
|
||||
public function get(string $id): mixed
|
||||
{
|
||||
if (! array_key_exists($id, $this->instances)) {
|
||||
$this->instances[$id] = $this->build($id);
|
||||
}
|
||||
|
||||
return $this->instances[$id];
|
||||
/** @var TObject $concrete */
|
||||
$concrete = $this->instances[$id];
|
||||
|
||||
return $concrete;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,9 +63,12 @@ final class Container
|
||||
/**
|
||||
* Tries to build the given instance.
|
||||
*
|
||||
* @param class-string $id
|
||||
* @template TObject of object
|
||||
*
|
||||
* @param class-string<TObject> $id
|
||||
* @return TObject
|
||||
*/
|
||||
private function build(string $id): object
|
||||
private function build(string $id): mixed
|
||||
{
|
||||
$reflectionClass = new ReflectionClass($id);
|
||||
|
||||
|
||||
71
src/Support/View.php
Normal file
71
src/Support/View.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Pest\Support;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use function Termwind\render;
|
||||
use function Termwind\renderUsing;
|
||||
use Termwind\Termwind;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class View
|
||||
{
|
||||
/**
|
||||
* The implementation of the output.
|
||||
*/
|
||||
private static OutputInterface $output;
|
||||
|
||||
/**
|
||||
* Renders views using the given Output instance.
|
||||
*/
|
||||
public static function renderUsing(OutputInterface $output): void
|
||||
{
|
||||
self::$output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the given view.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public static function render(string $path, array $data = []): void
|
||||
{
|
||||
$contents = self::compile($path, $data);
|
||||
|
||||
$existing = Termwind::getRenderer();
|
||||
|
||||
renderUsing(self::$output);
|
||||
|
||||
try {
|
||||
render($contents);
|
||||
} finally {
|
||||
renderUsing($existing);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the given view.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
private static function compile(string $path, array $data): string
|
||||
{
|
||||
extract($data);
|
||||
|
||||
ob_start();
|
||||
|
||||
$path = str_replace('.', '/', $path);
|
||||
|
||||
include sprintf('%s/../../resources/views/%s.php', __DIR__, $path);
|
||||
|
||||
$contents = ob_get_contents();
|
||||
|
||||
ob_clean();
|
||||
|
||||
return (string) $contents;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user