This commit is contained in:
2025-05-12 14:25:25 +02:00
parent ab2db755ef
commit 9e378ca2b7
2719 changed files with 46505 additions and 60181 deletions

View File

@@ -4,6 +4,8 @@ namespace Spatie\FlareClient\Context;
use RuntimeException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\InputBag;
use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Throwable;
@@ -12,7 +14,7 @@ class RequestContextProvider implements ContextProvider
{
protected ?Request $request;
public function __construct(Request $request = null)
public function __construct(?Request $request = null)
{
$this->request = $request ?? Request::createFromGlobals();
}
@@ -138,11 +140,26 @@ class RequestContextProvider implements ContextProvider
{
return [
'queryString' => $this->request->query->all(),
'body' => $this->request->request->all(),
'body' => $this->getInputBag()->all() + $this->request->query->all(),
'files' => $this->getFiles(),
];
}
protected function getInputBag(): InputBag|ParameterBag
{
$contentType = $this->request->headers->get('CONTENT_TYPE', 'text/html');
$isJson = str_contains($contentType, '/json') || str_contains($contentType, '+json');
if ($isJson) {
return new InputBag((array) json_decode($this->request->getContent(), true));
}
return in_array($this->request->getMethod(), ['GET', 'HEAD'])
? $this->request->query
: $this->request->request;
}
/** @return array<string, mixed> */
public function toArray(): array
{

View File

@@ -0,0 +1,10 @@
<?php
namespace Spatie\FlareClient\Enums;
class OverriddenGrouping
{
const ExceptionClass = 'exception_class';
const ExceptionMessage = 'exception_message';
const ExceptionMessageAndClass = 'exception_message_and_class';
}

61
vendor/spatie/flare-client-php/src/Flare.php vendored Normal file → Executable file
View File

@@ -13,6 +13,7 @@ use Spatie\FlareClient\Concerns\HasContext;
use Spatie\FlareClient\Context\BaseContextProviderDetector;
use Spatie\FlareClient\Context\ContextProviderDetector;
use Spatie\FlareClient\Enums\MessageLevels;
use Spatie\FlareClient\Enums\OverriddenGrouping;
use Spatie\FlareClient\FlareMiddleware\AddEnvironmentInformation;
use Spatie\FlareClient\FlareMiddleware\AddGlows;
use Spatie\FlareClient\FlareMiddleware\CensorRequestBodyFields;
@@ -21,6 +22,7 @@ use Spatie\FlareClient\FlareMiddleware\RemoveRequestIp;
use Spatie\FlareClient\Glows\Glow;
use Spatie\FlareClient\Glows\GlowRecorder;
use Spatie\FlareClient\Http\Client;
use Spatie\FlareClient\Support\PhpStackFrameArgumentsFixer;
use Throwable;
class Flare
@@ -40,7 +42,7 @@ class Flare
protected ContextProviderDetector $contextDetector;
protected $previousExceptionHandler = null;
protected mixed $previousExceptionHandler = null;
/** @var null|callable */
protected $previousErrorHandler = null;
@@ -67,9 +69,12 @@ class Flare
protected bool $withStackFrameArguments = true;
/** @var array<class-string, string> */
protected array $overriddenGroupings = [];
public static function make(
string $apiKey = null,
ContextProviderDetector $contextDetector = null
?string $apiKey = null,
?ContextProviderDetector $contextDetector = null
): self {
$client = new Client($apiKey);
@@ -145,10 +150,28 @@ class Flare
return $this;
}
public function withStackFrameArguments(bool $withStackFrameArguments = true): self
{
public function withStackFrameArguments(
bool $withStackFrameArguments = true,
bool $forcePHPIniSetting = false,
): self {
$this->withStackFrameArguments = $withStackFrameArguments;
if ($forcePHPIniSetting) {
(new PhpStackFrameArgumentsFixer())->enable();
}
return $this;
}
/**
* @param class-string $exceptionClass
*/
public function overrideGrouping(
string $exceptionClass,
string $type = OverriddenGrouping::ExceptionMessageAndClass,
): self {
$this->overriddenGroupings[$exceptionClass] = $type;
return $this;
}
@@ -168,7 +191,7 @@ class Flare
*/
public function __construct(
Client $client,
ContextProviderDetector $contextDetector = null,
?ContextProviderDetector $contextDetector = null,
array $middleware = [],
) {
$this->client = $client;
@@ -211,15 +234,16 @@ class Flare
public function registerExceptionHandler(): self
{
/** @phpstan-ignore-next-line */
$this->previousExceptionHandler = set_exception_handler([$this, 'handleException']);
return $this;
}
public function registerErrorHandler(): self
public function registerErrorHandler(?int $errorLevels = null): self
{
$this->previousErrorHandler = set_error_handler([$this, 'handleError']);
$this->previousErrorHandler = $errorLevels
? set_error_handler([$this, 'handleError'], $errorLevels)
: set_error_handler([$this, 'handleError']);
return $this;
}
@@ -294,8 +318,8 @@ class Flare
if ($this->previousErrorHandler) {
return call_user_func(
$this->previousErrorHandler,
$message,
$code,
$message,
$file,
$line
);
@@ -309,7 +333,7 @@ class Flare
return $this;
}
public function report(Throwable $throwable, callable $callback = null, Report $report = null): ?Report
public function report(Throwable $throwable, ?callable $callback = null, ?Report $report = null, ?bool $handled = null): ?Report
{
if (! $this->shouldSendReport($throwable)) {
return null;
@@ -317,6 +341,10 @@ class Flare
$report ??= $this->createReport($throwable);
if ($handled) {
$report->handled();
}
if (! is_null($callback)) {
call_user_func($callback, $report);
}
@@ -328,6 +356,11 @@ class Flare
return $report;
}
public function reportHandled(Throwable $throwable): ?Report
{
return $this->report($throwable, null, null, true);
}
protected function shouldSendReport(Throwable $throwable): bool
{
if (isset($this->reportErrorLevels) && $throwable instanceof Error) {
@@ -345,7 +378,7 @@ class Flare
return true;
}
public function reportMessage(string $message, string $logLevel, callable $callback = null): void
public function reportMessage(string $message, string $logLevel, ?callable $callback = null): void
{
$report = $this->createReportFromMessage($message, $logLevel);
@@ -420,7 +453,8 @@ class Flare
$this->applicationPath,
$this->version(),
$this->argumentReducers,
$this->withStackFrameArguments
$this->withStackFrameArguments,
$this->overriddenGroupings,
);
return $this->applyMiddlewareToReport($report);
@@ -449,6 +483,7 @@ class Flare
: $singleMiddleware;
}, $this->middleware);
$report = (new Pipeline())
->send($report)
->through($middleware)

View File

@@ -3,14 +3,15 @@
namespace Spatie\FlareClient\FlareMiddleware;
use Closure;
use Spatie\ErrorSolutions\Contracts\SolutionProviderRepository;
use Spatie\FlareClient\Report;
use Spatie\Ignition\Contracts\SolutionProviderRepository;
use Spatie\Ignition\Contracts\SolutionProviderRepository as IgnitionSolutionProviderRepository;
class AddSolutions implements FlareMiddleware
{
protected SolutionProviderRepository $solutionProviderRepository;
protected SolutionProviderRepository|IgnitionSolutionProviderRepository $solutionProviderRepository;
public function __construct(SolutionProviderRepository $solutionProviderRepository)
public function __construct(SolutionProviderRepository|IgnitionSolutionProviderRepository $solutionProviderRepository)
{
$this->solutionProviderRepository = $solutionProviderRepository;
}

View File

@@ -7,14 +7,16 @@ use Spatie\Backtrace\Arguments\ArgumentReducers;
use Spatie\Backtrace\Arguments\Reducers\ArgumentReducer;
use Spatie\Backtrace\Backtrace;
use Spatie\Backtrace\Frame as SpatieFrame;
use Spatie\ErrorSolutions\Contracts\Solution;
use Spatie\FlareClient\Concerns\HasContext;
use Spatie\FlareClient\Concerns\UsesTime;
use Spatie\FlareClient\Context\ContextProvider;
use Spatie\FlareClient\Contracts\ProvidesFlareContext;
use Spatie\FlareClient\Glows\Glow;
use Spatie\FlareClient\Solutions\ReportSolution;
use Spatie\Ignition\Contracts\Solution;
use Spatie\LaravelIgnition\Exceptions\ViewException;
use Spatie\Ignition\Contracts\Solution as IgnitionSolution;
use Spatie\LaravelFlare\Exceptions\ViewException;
use Spatie\LaravelIgnition\Exceptions\ViewException as IgnitionViewException;
use Throwable;
class Report
@@ -65,7 +67,14 @@ class Report
public static ?string $fakeTrackingUuid = null;
/** @param array<class-string<ArgumentReducer>|ArgumentReducer>|ArgumentReducers|null $argumentReducers */
protected ?bool $handled = null;
protected ?string $overriddenGrouping = null;
/**
* @param array<class-string<ArgumentReducer>|ArgumentReducer>|ArgumentReducers|null $argumentReducers
* @param array<class-string, string> $overriddenGroupings
*/
public static function createForThrowable(
Throwable $throwable,
ContextProvider $context,
@@ -73,27 +82,36 @@ class Report
?string $version = null,
null|array|ArgumentReducers $argumentReducers = null,
bool $withStackTraceArguments = true,
array $overriddenGroupings = [],
): self {
$stacktrace = Backtrace::createForThrowable($throwable)
->withArguments($withStackTraceArguments)
->reduceArguments($argumentReducers)
->applicationPath($applicationPath ?? '');
return (new self())
$exceptionClass = self::getClassForThrowable($throwable);
$report = (new self())
->setApplicationPath($applicationPath)
->throwable($throwable)
->useContext($context)
->exceptionClass(self::getClassForThrowable($throwable))
->exceptionClass($exceptionClass)
->message($throwable->getMessage())
->stackTrace($stacktrace)
->exceptionContext($throwable)
->setApplicationVersion($version);
if (array_key_exists($exceptionClass, $overriddenGroupings)) {
$report->overriddenGrouping($overriddenGroupings[$exceptionClass]);
}
return $report;
}
protected static function getClassForThrowable(Throwable $throwable): string
{
/** @phpstan-ignore-next-line */
if ($throwable::class === ViewException::class) {
if ($throwable::class === IgnitionViewException::class || $throwable::class === ViewException::class) {
/** @phpstan-ignore-next-line */
if ($previous = $throwable->getPrevious()) {
return get_class($previous);
@@ -257,7 +275,7 @@ class Report
return $this;
}
public function addSolution(Solution $solution): self
public function addSolution(Solution|IgnitionSolution $solution): self
{
$this->solutions[] = ReportSolution::fromSolution($solution)->toArray();
@@ -300,6 +318,20 @@ class Report
return array_merge_recursive_distinct($context, $this->userProvidedContext);
}
public function handled(?bool $handled = true): self
{
$this->handled = $handled;
return $this;
}
public function overriddenGrouping(?string $overriddenGrouping): self
{
$this->overriddenGrouping = $overriddenGrouping;
return $this;
}
protected function exceptionContext(Throwable $throwable): self
{
if ($throwable instanceof ProvidesFlareContext) {
@@ -376,6 +408,8 @@ class Report
'application_path' => $this->applicationPath,
'application_version' => $this->applicationVersion,
'tracking_uuid' => $this->trackingUuid,
'handled' => $this->handled,
'overridden_grouping' => $this->overriddenGrouping,
];
}

View File

@@ -2,19 +2,21 @@
namespace Spatie\FlareClient\Solutions;
use Spatie\Ignition\Contracts\RunnableSolution;
use Spatie\Ignition\Contracts\Solution as SolutionContract;
use Spatie\ErrorSolutions\Contracts\RunnableSolution;
use Spatie\ErrorSolutions\Contracts\Solution;
use Spatie\Ignition\Contracts\RunnableSolution as IgnitionRunnableSolution;
use Spatie\Ignition\Contracts\Solution as IgnitionSolution;
class ReportSolution
{
protected SolutionContract $solution;
protected Solution|IgnitionSolution $solution;
public function __construct(SolutionContract $solution)
public function __construct(Solution|IgnitionSolution $solution)
{
$this->solution = $solution;
}
public static function fromSolution(SolutionContract $solution): self
public static function fromSolution(Solution|IgnitionSolution $solution): self
{
return new self($solution);
}
@@ -24,7 +26,7 @@ class ReportSolution
*/
public function toArray(): array
{
$isRunnable = ($this->solution instanceof RunnableSolution);
$isRunnable = ($this->solution instanceof RunnableSolution || $this->solution instanceof IgnitionRunnableSolution);
return [
'class' => get_class($this->solution),

View File

@@ -0,0 +1,24 @@
<?php
namespace Spatie\FlareClient\Support;
class PhpStackFrameArgumentsFixer
{
public function enable(): void
{
if (! $this->isCurrentlyIgnoringStackFrameArguments()) {
return;
}
ini_set('zend.exception_ignore_args', '0');
}
protected function isCurrentlyIgnoringStackFrameArguments(): bool
{
return match (ini_get('zend.exception_ignore_args')) {
'1' => true,
'0' => false,
default => false,
};
}
}