Viewing file: CliPrinter.php (8.8 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
namespace Laravel\Pail\Printers;
use Illuminate\Support\Collection; use Illuminate\Support\Str; use Laravel\Pail\Contracts\Printer; use Laravel\Pail\ValueObjects\MessageLogged; use Laravel\Pail\ValueObjects\Origin\Http; use Laravel\Pail\ValueObjects\Origin\Queue; use Symfony\Component\Console\Output\OutputInterface;
use function Termwind\render; use function Termwind\renderUsing; use function Termwind\terminal;
class CliPrinter implements Printer { /** * {@inheritDoc} */ public function print(MessageLogged $messageLogged): void { $classOrType = $this->truncateClassOrType($messageLogged->classOrType()); $color = $messageLogged->color(); $message = $this->truncateMessage($messageLogged->message()); $date = $this->output->isVerbose() ? $messageLogged->date() : $messageLogged->time();
$fileHtml = $this->fileHtml($messageLogged->file(), $classOrType); $messageHtml = $this->messageHtml($message); $optionsHtml = $this->optionsHtml($messageLogged); $traceHtml = $this->traceHtml($messageLogged);
$messageClasses = $this->output->isVerbose() ? '' : 'truncate';
$endingTopRight = $this->output->isVerbose() ? '' : '┐'; $endingMiddle = $this->output->isVerbose() ? '' : '│'; $endingBottomRight = $this->output->isVerbose() ? '' : '┘';
renderUsing($this->output); render(<<<HTML <div class="max-w-150"> <div class="flex"> <div> <span class="mr-1 text-gray">┌</span> <span class="text-gray">$date</span> <span class="px-1 text-$color font-bold">$classOrType</span> </div> <span class="flex-1 content-repeat-[─] text-gray"></span> <span class="text-gray"> $fileHtml <span class="text-gray">$endingTopRight</span> </span> </div> <div class="flex $messageClasses"> <span> <span class="mr-1 text-gray">│</span> $messageHtml </span> <span class="flex-1"></span> <span class="flex-1 text-gray text-right">$endingMiddle</span> </div> $traceHtml <div class="flex text-gray"> <span>└</span> <span class="mr-1 flex-1 content-repeat-[─]"></span> $optionsHtml <span class="ml-1">$endingBottomRight</span> </div> </div> HTML); }
/** * Creates a new instance printer instance. */ public function __construct(protected OutputInterface $output, protected string $basePath) { // }
/** * Gets the file html. */ protected function fileHtml(?string $file, string $classOrType): ?string { if (is_null($file)) { return null; }
if ($_ENV['PAIL_TESTS'] ?? false) { $file = $this->basePath.'/app/MyClass.php:12'; }
$file = str_replace($this->basePath.'/', '', $file);
if (! $this->output->isVerbose()) { $file = Str::of($file) ->explode('/') ->when( fn (Collection $file) => $file->count() > 4, fn (Collection $file) => $file->take(2)->merge( ['…', (string) $file->last()], ), )->implode('/');
$fileSize = max(0, min(terminal()->width() - strlen($classOrType) - 16, 145));
if (strlen($file) > $fileSize) { $file = mb_substr($file, 0, $fileSize).'…'; } }
if ($file === '…') { return null; }
$file = str_replace('……', '…', $file);
return <<<HTML <span class="text-gray mx-1"> $file </span> HTML; }
/** * Gets the message html. */ protected function messageHtml(string $message): string { if (empty($message)) { return '<span class="text-gray">No message.</span>'; }
$message = htmlspecialchars($message);
if (strstr($message, PHP_EOL)) { return "<pre>$message</pre>"; }
return "<span>$message</span>"; }
/** * Truncates the class or type, if needed. */ protected function truncateClassOrType(string $classOrType): string { if ($this->output->isVerbose()) { return $classOrType; }
return Str::of($classOrType) ->explode('\\') ->when( fn (Collection $classOrType) => $classOrType->count() > 4, fn (Collection $classOrType) => $classOrType->take(2)->merge( ['…', (string) $classOrType->last()] ), )->implode('\\'); }
/** * Truncates the message, if needed. */ protected function truncateMessage(string $message): string { if (! $this->output->isVerbose()) { $messageSize = max(0, min(terminal()->width() - 5, 145));
if (strlen($message) > $messageSize) { $message = mb_substr($message, 0, $messageSize).'…'; } }
return $message; }
/** * Gets the options html. */ public function optionsHtml(MessageLogged $messageLogged): string { $origin = $messageLogged->origin();
if ($origin instanceof Http) { if (str_starts_with($path = $origin->path, '/') === false) { $path = '/'.$origin->path; }
$options = [ strtoupper($origin->method) => $path, 'Auth ID' => $origin->authId ? ($origin->authId.($origin->authEmail ? " ({$origin->authEmail})" : '')) : 'guest', ]; } elseif ($origin instanceof Queue) { $options = [ $origin->command ? "artisan {$origin->command}" : null, $origin->queue, $origin->job, ]; } else { $options = [ $origin->command ? "artisan {$origin->command}" : 'artisan', ]; }
return collect($options)->merge( $messageLogged->context() // @phpstan-ignore argument.type )->reject(fn (mixed $value, string|int $key) => is_int($key) && is_null($value)) ->map(fn (mixed $value) => is_string($value) ? $value : var_export($value, true)) ->map(fn (string $value) => htmlspecialchars($value)) ->map(fn (string $value, string|int $key) => is_string($key) ? "$key: $value" : $value) ->map(fn (string $value) => "<span class=\"font-bold\">$value</span>") ->implode(' • '); }
/** * Gets the trace html. */ public function traceHtml(MessageLogged $messageLogged): string { if (! $this->output->isVeryVerbose()) { return ''; }
$trace = $messageLogged->trace();
if ($_ENV['PAIL_TESTS'] ?? false) { $trace = [ [ 'line' => 12, 'file' => $this->basePath.'/app/MyClass.php', ], [ 'line' => 34, 'file' => $this->basePath.'/app/MyClass.php', ], ]; }
if (is_null($trace)) { return ''; }
return collect($trace) ->map(function (array $frame, int $index) { $number = $index + 1;
[ 'line' => $line, 'file' => $file, ] = $frame;
$file = str_replace($this->basePath.'/', '', $file);
$remainingTraces = '';
if (! $this->output->isVerbose()) { $file = (string) Str::of($file) ->explode('/') ->when( fn (Collection $file) => $file->count() > 4, fn (Collection $file) => $file->take(2)->merge( ['…', (string) $file->last()], ), )->implode('/'); }
return <<<HTML <div class="flex text-gray"> <span> <span class="mr-1 text-gray">│</span> <span>$number. $file:$line $remainingTraces</span> </span> </div> HTML; })->implode(''); } }
|