Initial commit
This commit is contained in:
21
vendor/spatie/laravel-ignition/LICENSE.md
vendored
Normal file
21
vendor/spatie/laravel-ignition/LICENSE.md
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Spatie <info@spatie.be>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
50
vendor/spatie/laravel-ignition/README.md
vendored
Normal file
50
vendor/spatie/laravel-ignition/README.md
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
# Ignition: a beautiful error page for Laravel apps
|
||||
|
||||
[](https://packagist.org/packages/spatie/laravel-ignition)
|
||||

|
||||
[](https://packagist.org/packages/spatie/laravel-ignition)
|
||||
|
||||
[Ignition](https://flareapp.io/docs/ignition-for-laravel/introduction) is a beautiful and customizable error page for Laravel applications. It also allows to publicly share your errors on [Flare](https://flareapp.io). If configured with a valid Flare API key, your errors in production applications will be tracked, and you'll get notified when they happen.
|
||||
|
||||
`spatie/laravel-ignition` works for Laravel 8 and 9 applications running on PHP 8.0 and above. Looking for Ignition for Laravel 5.x, 6.x or 7.x or old PHP versions? `facade/ignition` is still compatible.
|
||||
|
||||

|
||||
|
||||
## Are you a visual learner?
|
||||
|
||||
In [this video on YouTube](https://youtu.be/LEY0N0Bteew?t=739), you'll see a demo of all of the features.
|
||||
|
||||
Do know more about the design decisions we made, read [this blog post](https://freek.dev/2168-ignition-the-most-beautiful-error-page-for-laravel-and-php-got-a-major-redesign).
|
||||
|
||||
## Official Documentation
|
||||
|
||||
The official documentation for Ignition can be found on the [Flare website](https://flareapp.io/docs/ignition/introducing-ignition/overview).
|
||||
|
||||
## Support us
|
||||
|
||||
[<img src="https://github-ads.s3.eu-central-1.amazonaws.com/laravel-ignition.jpg?t=1" width="419px" />](https://spatie.be/github-ad-click/laravel-ignition)
|
||||
|
||||
We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).
|
||||
|
||||
We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).
|
||||
|
||||
### Changelog
|
||||
|
||||
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.
|
||||
|
||||
## Security Vulnerabilities
|
||||
|
||||
Please review [our security policy](../../security/policy) on how to report security vulnerabilities.
|
||||
|
||||
## Credits
|
||||
|
||||
- [Spatie](https://spatie.be)
|
||||
- [All Contributors](../../contributors)
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Please see [License File](LICENSE.md) for more information.
|
||||
91
vendor/spatie/laravel-ignition/composer.json
vendored
Normal file
91
vendor/spatie/laravel-ignition/composer.json
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"name": "spatie/laravel-ignition",
|
||||
"description": "A beautiful error page for Laravel applications.",
|
||||
"keywords": [
|
||||
"error",
|
||||
"page",
|
||||
"laravel",
|
||||
"flare"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Spatie",
|
||||
"email": "info@spatie.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"homepage": "https://flareapp.io/ignition",
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"ext-mbstring": "*",
|
||||
"illuminate/support": "^10.0|^11.0",
|
||||
"spatie/ignition": "^1.15",
|
||||
"symfony/console": "^6.2.3|^7.0",
|
||||
"symfony/var-dumper": "^6.2.3|^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"livewire/livewire": "^2.11|^3.3.5",
|
||||
"mockery/mockery": "^1.5.1",
|
||||
"openai-php/client": "^0.8.1",
|
||||
"orchestra/testbench": "8.22.3|^9.0",
|
||||
"pestphp/pest": "^2.34",
|
||||
"phpstan/extension-installer": "^1.3.1",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.3.16",
|
||||
"vlucas/phpdotenv": "^5.5"
|
||||
},
|
||||
"suggest": {
|
||||
"openai-php/client": "Require get solutions from OpenAI",
|
||||
"psr/simple-cache-implementation": "Needed to cache solutions from OpenAI"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"phpstan/extension-installer": true,
|
||||
"pestphp/pest-plugin": true,
|
||||
"php-http/discovery": false
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Spatie\\LaravelIgnition\\IgnitionServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Flare": "Spatie\\LaravelIgnition\\Facades\\Flare"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\LaravelIgnition\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/helpers.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Spatie\\LaravelIgnition\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"analyse": "vendor/bin/phpstan analyse",
|
||||
"baseline": "vendor/bin/phpstan --generate-baseline",
|
||||
"format": "vendor/bin/php-cs-fixer fix --allow-risky=yes",
|
||||
"test": "vendor/bin/pest",
|
||||
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
|
||||
},
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/laravel-ignition/issues",
|
||||
"forum": "https://twitter.com/flareappio",
|
||||
"source": "https://github.com/spatie/laravel-ignition",
|
||||
"docs": "https://flareapp.io/docs/ignition-for-laravel/introduction"
|
||||
}
|
||||
}
|
||||
89
vendor/spatie/laravel-ignition/config/flare.php
vendored
Normal file
89
vendor/spatie/laravel-ignition/config/flare.php
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
use Spatie\FlareClient\FlareMiddleware\AddGitInformation;
|
||||
use Spatie\FlareClient\FlareMiddleware\RemoveRequestIp;
|
||||
use Spatie\FlareClient\FlareMiddleware\CensorRequestBodyFields;
|
||||
use Spatie\FlareClient\FlareMiddleware\CensorRequestHeaders;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddDumps;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddEnvironmentInformation;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddExceptionHandledStatus;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddExceptionInformation;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddJobs;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddLogs;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddQueries;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddContext;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddNotifierName;
|
||||
|
||||
return [
|
||||
/*
|
||||
|
|
||||
|--------------------------------------------------------------------------
|
||||
| Flare API key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specify Flare's API key below to enable error reporting to the service.
|
||||
|
|
||||
| More info: https://flareapp.io/docs/general/projects
|
||||
|
|
||||
*/
|
||||
|
||||
'key' => env('FLARE_KEY'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| These middleware will modify the contents of the report sent to Flare.
|
||||
|
|
||||
*/
|
||||
|
||||
'flare_middleware' => [
|
||||
RemoveRequestIp::class,
|
||||
AddGitInformation::class,
|
||||
AddNotifierName::class,
|
||||
AddEnvironmentInformation::class,
|
||||
AddExceptionInformation::class,
|
||||
AddDumps::class,
|
||||
AddLogs::class => [
|
||||
'maximum_number_of_collected_logs' => 200,
|
||||
],
|
||||
AddQueries::class => [
|
||||
'maximum_number_of_collected_queries' => 200,
|
||||
'report_query_bindings' => true,
|
||||
],
|
||||
AddJobs::class => [
|
||||
'max_chained_job_reporting_depth' => 5,
|
||||
],
|
||||
AddContext::class,
|
||||
AddExceptionHandledStatus::class,
|
||||
CensorRequestBodyFields::class => [
|
||||
'censor_fields' => [
|
||||
'password',
|
||||
'password_confirmation',
|
||||
],
|
||||
],
|
||||
CensorRequestHeaders::class => [
|
||||
'headers' => [
|
||||
'API-KEY',
|
||||
'Authorization',
|
||||
'Cookie',
|
||||
'Set-Cookie',
|
||||
'X-CSRF-TOKEN',
|
||||
'X-XSRF-TOKEN',
|
||||
]
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Reporting log statements
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If this setting is `false` log statements won't be sent as events to Flare,
|
||||
| no matter which error level you specified in the Flare log channel.
|
||||
|
|
||||
*/
|
||||
|
||||
'send_logs_as_events' => true,
|
||||
];
|
||||
285
vendor/spatie/laravel-ignition/config/ignition.php
vendored
Normal file
285
vendor/spatie/laravel-ignition/config/ignition.php
vendored
Normal file
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
|
||||
use Spatie\Ignition\Solutions\SolutionProviders\BadMethodCallSolutionProvider;
|
||||
use Spatie\Ignition\Solutions\SolutionProviders\MergeConflictSolutionProvider;
|
||||
use Spatie\Ignition\Solutions\SolutionProviders\UndefinedPropertySolutionProvider;
|
||||
use Spatie\LaravelIgnition\Recorders\DumpRecorder\DumpRecorder;
|
||||
use Spatie\LaravelIgnition\Recorders\JobRecorder\JobRecorder;
|
||||
use Spatie\LaravelIgnition\Recorders\LogRecorder\LogRecorder;
|
||||
use Spatie\LaravelIgnition\Recorders\QueryRecorder\QueryRecorder;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\DefaultDbNameSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\GenericLaravelExceptionSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\IncorrectValetDbCredentialsSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\InvalidRouteActionSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\MissingAppKeySolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\MissingColumnSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\MissingImportSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\MissingLivewireComponentSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\MissingMixManifestSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\MissingViteManifestSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\RunningLaravelDuskInProductionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\TableNotFoundSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\UndefinedViewVariableSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\UnknownValidationSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\ViewNotFoundSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\OpenAiSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\SailNetworkSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\UnknownMariadbCollationSolutionProvider;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionProviders\UnknownMysql8CollationSolutionProvider;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Editor
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Choose your preferred editor to use when clicking any edit button.
|
||||
|
|
||||
| Supported: "phpstorm", "vscode", "vscode-insiders", "textmate", "emacs",
|
||||
| "sublime", "atom", "nova", "macvim", "idea", "netbeans",
|
||||
| "xdebug", "phpstorm-remote"
|
||||
|
|
||||
*/
|
||||
|
||||
'editor' => env('IGNITION_EDITOR', 'phpstorm'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Theme
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which theme Ignition should use.
|
||||
|
|
||||
| Supported: "light", "dark", "auto"
|
||||
|
|
||||
*/
|
||||
|
||||
'theme' => env('IGNITION_THEME', 'auto'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Sharing
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You can share local errors with colleagues or others around the world.
|
||||
| Sharing is completely free and doesn't require an account on Flare.
|
||||
|
|
||||
| If necessary, you can completely disable sharing below.
|
||||
|
|
||||
*/
|
||||
|
||||
'enable_share_button' => env('IGNITION_SHARING_ENABLED', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Ignition commands
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ignition comes with an additional make command that lets you create
|
||||
| new solution classes more easily. To keep your default Laravel
|
||||
| installation clean, this command is not registered by default.
|
||||
|
|
||||
| You can enable the command registration below.
|
||||
|
|
||||
*/
|
||||
|
||||
'register_commands' => env('REGISTER_IGNITION_COMMANDS', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Solution Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| List of solution providers that should be loaded. You may specify additional
|
||||
| providers as fully qualified class names.
|
||||
|
|
||||
*/
|
||||
|
||||
'solution_providers' => [
|
||||
// from spatie/ignition
|
||||
BadMethodCallSolutionProvider::class,
|
||||
MergeConflictSolutionProvider::class,
|
||||
UndefinedPropertySolutionProvider::class,
|
||||
|
||||
// from spatie/laravel-ignition
|
||||
IncorrectValetDbCredentialsSolutionProvider::class,
|
||||
MissingAppKeySolutionProvider::class,
|
||||
DefaultDbNameSolutionProvider::class,
|
||||
TableNotFoundSolutionProvider::class,
|
||||
MissingImportSolutionProvider::class,
|
||||
InvalidRouteActionSolutionProvider::class,
|
||||
ViewNotFoundSolutionProvider::class,
|
||||
RunningLaravelDuskInProductionProvider::class,
|
||||
MissingColumnSolutionProvider::class,
|
||||
UnknownValidationSolutionProvider::class,
|
||||
MissingMixManifestSolutionProvider::class,
|
||||
MissingViteManifestSolutionProvider::class,
|
||||
MissingLivewireComponentSolutionProvider::class,
|
||||
UndefinedViewVariableSolutionProvider::class,
|
||||
GenericLaravelExceptionSolutionProvider::class,
|
||||
OpenAiSolutionProvider::class,
|
||||
SailNetworkSolutionProvider::class,
|
||||
UnknownMysql8CollationSolutionProvider::class,
|
||||
UnknownMariadbCollationSolutionProvider::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Ignored Solution Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You may specify a list of solution providers (as fully qualified class
|
||||
| names) that shouldn't be loaded. Ignition will ignore these classes
|
||||
| and possible solutions provided by them will never be displayed.
|
||||
|
|
||||
*/
|
||||
|
||||
'ignored_solution_providers' => [
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Runnable Solutions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Some solutions that Ignition displays are runnable and can perform
|
||||
| various tasks. By default, runnable solutions are only enabled when your
|
||||
| app has debug mode enabled and the environment is `local` or
|
||||
| `development`.
|
||||
|
|
||||
| Using the `IGNITION_ENABLE_RUNNABLE_SOLUTIONS` environment variable, you
|
||||
| can override this behaviour and enable or disable runnable solutions
|
||||
| regardless of the application's environment.
|
||||
|
|
||||
| Default: env('IGNITION_ENABLE_RUNNABLE_SOLUTIONS')
|
||||
|
|
||||
*/
|
||||
|
||||
'enable_runnable_solutions' => env('IGNITION_ENABLE_RUNNABLE_SOLUTIONS'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Remote Path Mapping
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you are using a remote dev server, like Laravel Homestead, Docker, or
|
||||
| even a remote VPS, it will be necessary to specify your path mapping.
|
||||
|
|
||||
| Leaving one, or both of these, empty or null will not trigger the remote
|
||||
| URL changes and Ignition will treat your editor links as local files.
|
||||
|
|
||||
| "remote_sites_path" is an absolute base path for your sites or projects
|
||||
| in Homestead, Vagrant, Docker, or another remote development server.
|
||||
|
|
||||
| Example value: "/home/vagrant/Code"
|
||||
|
|
||||
| "local_sites_path" is an absolute base path for your sites or projects
|
||||
| on your local computer where your IDE or code editor is running on.
|
||||
|
|
||||
| Example values: "/Users/<name>/Code", "C:\Users\<name>\Documents\Code"
|
||||
|
|
||||
*/
|
||||
|
||||
'remote_sites_path' => env('IGNITION_REMOTE_SITES_PATH', base_path()),
|
||||
'local_sites_path' => env('IGNITION_LOCAL_SITES_PATH', ''),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Housekeeping Endpoint Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ignition registers a couple of routes when it is enabled. Below you may
|
||||
| specify a route prefix that will be used to host all internal links.
|
||||
|
|
||||
*/
|
||||
|
||||
'housekeeping_endpoint_prefix' => '_ignition',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Settings File
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ignition allows you to save your settings to a specific global file.
|
||||
|
|
||||
| If no path is specified, a file with settings will be saved to the user's
|
||||
| home directory. The directory depends on the OS and its settings but it's
|
||||
| typically `~/.ignition.json`. In this case, the settings will be applied
|
||||
| to all of your projects where Ignition is used and the path is not
|
||||
| specified.
|
||||
|
|
||||
| However, if you want to store your settings on a project basis, or you
|
||||
| want to keep them in another directory, you can specify a path where
|
||||
| the settings file will be saved. The path should be an existing directory
|
||||
| with correct write access.
|
||||
| For example, create a new `ignition` folder in the storage directory and
|
||||
| use `storage_path('ignition')` as the `settings_file_path`.
|
||||
|
|
||||
| Default value: '' (empty string)
|
||||
*/
|
||||
|
||||
'settings_file_path' => '',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Recorders
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ignition registers a couple of recorders when it is enabled. Below you may
|
||||
| specify a recorders will be used to record specific events.
|
||||
|
|
||||
*/
|
||||
|
||||
'recorders' => [
|
||||
DumpRecorder::class,
|
||||
JobRecorder::class,
|
||||
LogRecorder::class,
|
||||
QueryRecorder::class,
|
||||
],
|
||||
|
||||
/*
|
||||
* When a key is set, we'll send your exceptions to Open AI to generate a solution
|
||||
*/
|
||||
|
||||
'open_ai_key' => env('IGNITION_OPEN_AI_KEY'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Include arguments
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ignition show you stack traces of exceptions with the arguments that were
|
||||
| passed to each method. This feature can be disabled here.
|
||||
|
|
||||
*/
|
||||
|
||||
'with_stack_frame_arguments' => true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argument reducers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ignition show you stack traces of exceptions with the arguments that were
|
||||
| passed to each method. To make these variables more readable, you can
|
||||
| specify a list of classes here which summarize the variables.
|
||||
|
|
||||
*/
|
||||
|
||||
'argument_reducers' => [
|
||||
\Spatie\Backtrace\Arguments\Reducers\BaseTypeArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\ArrayArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\StdClassArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\EnumArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\ClosureArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\DateTimeArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\DateTimeZoneArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\SymphonyRequestArgumentReducer::class,
|
||||
\Spatie\LaravelIgnition\ArgumentReducers\ModelArgumentReducer::class,
|
||||
\Spatie\LaravelIgnition\ArgumentReducers\CollectionArgumentReducer::class,
|
||||
\Spatie\Backtrace\Arguments\Reducers\StringableArgumentReducer::class,
|
||||
],
|
||||
|
||||
];
|
||||
20
vendor/spatie/laravel-ignition/src/ArgumentReducers/CollectionArgumentReducer.php
vendored
Normal file
20
vendor/spatie/laravel-ignition/src/ArgumentReducers/CollectionArgumentReducer.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\ArgumentReducers;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Spatie\Backtrace\Arguments\ReducedArgument\ReducedArgumentContract;
|
||||
use Spatie\Backtrace\Arguments\ReducedArgument\UnReducedArgument;
|
||||
use Spatie\Backtrace\Arguments\Reducers\ArrayArgumentReducer;
|
||||
|
||||
class CollectionArgumentReducer extends ArrayArgumentReducer
|
||||
{
|
||||
public function execute(mixed $argument): ReducedArgumentContract
|
||||
{
|
||||
if (! $argument instanceof Collection) {
|
||||
return UnReducedArgument::create();
|
||||
}
|
||||
|
||||
return $this->reduceArgument($argument->toArray(), get_class($argument));
|
||||
}
|
||||
}
|
||||
24
vendor/spatie/laravel-ignition/src/ArgumentReducers/ModelArgumentReducer.php
vendored
Normal file
24
vendor/spatie/laravel-ignition/src/ArgumentReducers/ModelArgumentReducer.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\ArgumentReducers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\Backtrace\Arguments\ReducedArgument\ReducedArgument;
|
||||
use Spatie\Backtrace\Arguments\ReducedArgument\ReducedArgumentContract;
|
||||
use Spatie\Backtrace\Arguments\ReducedArgument\UnReducedArgument;
|
||||
use Spatie\Backtrace\Arguments\Reducers\ArgumentReducer;
|
||||
|
||||
class ModelArgumentReducer implements ArgumentReducer
|
||||
{
|
||||
public function execute(mixed $argument): ReducedArgumentContract
|
||||
{
|
||||
if (! $argument instanceof Model) {
|
||||
return UnReducedArgument::create();
|
||||
}
|
||||
|
||||
return new ReducedArgument(
|
||||
"{$argument->getKeyName()}:{$argument->getKey()}",
|
||||
get_class($argument)
|
||||
);
|
||||
}
|
||||
}
|
||||
35
vendor/spatie/laravel-ignition/src/Commands/SolutionMakeCommand.php
vendored
Normal file
35
vendor/spatie/laravel-ignition/src/Commands/SolutionMakeCommand.php
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Commands;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
class SolutionMakeCommand extends GeneratorCommand
|
||||
{
|
||||
protected $name = 'ignition:make-solution';
|
||||
|
||||
protected $description = 'Create a new custom Ignition solution class';
|
||||
|
||||
protected $type = 'Solution';
|
||||
|
||||
protected function getStub(): string
|
||||
{
|
||||
return $this->option('runnable')
|
||||
? __DIR__.'/stubs/runnable-solution.stub'
|
||||
: __DIR__.'/stubs/solution.stub';
|
||||
}
|
||||
|
||||
protected function getDefaultNamespace($rootNamespace)
|
||||
{
|
||||
return "{$rootNamespace}\\Solutions";
|
||||
}
|
||||
|
||||
/** @return array<int, mixed> */
|
||||
protected function getOptions(): array
|
||||
{
|
||||
return [
|
||||
['runnable', null, InputOption::VALUE_NONE, 'Create runnable solution'],
|
||||
];
|
||||
}
|
||||
}
|
||||
24
vendor/spatie/laravel-ignition/src/Commands/SolutionProviderMakeCommand.php
vendored
Normal file
24
vendor/spatie/laravel-ignition/src/Commands/SolutionProviderMakeCommand.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Commands;
|
||||
|
||||
use Illuminate\Console\GeneratorCommand;
|
||||
|
||||
class SolutionProviderMakeCommand extends GeneratorCommand
|
||||
{
|
||||
protected $name = 'ignition:make-solution-provider';
|
||||
|
||||
protected $description = 'Create a new custom Ignition solution provider class';
|
||||
|
||||
protected $type = 'Solution Provider';
|
||||
|
||||
protected function getStub(): string
|
||||
{
|
||||
return __DIR__.'/stubs/solution-provider.stub';
|
||||
}
|
||||
|
||||
protected function getDefaultNamespace($rootNamespace)
|
||||
{
|
||||
return "{$rootNamespace}\\SolutionProviders";
|
||||
}
|
||||
}
|
||||
131
vendor/spatie/laravel-ignition/src/Commands/TestCommand.php
vendored
Normal file
131
vendor/spatie/laravel-ignition/src/Commands/TestCommand.php
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Commands;
|
||||
|
||||
use Composer\InstalledVersions;
|
||||
use Exception;
|
||||
use Illuminate\Config\Repository;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Log\LogManager;
|
||||
use Spatie\FlareClient\Flare;
|
||||
use Spatie\FlareClient\Http\Exceptions\BadResponseCode;
|
||||
|
||||
class TestCommand extends Command
|
||||
{
|
||||
protected $signature = 'flare:test';
|
||||
|
||||
protected $description = 'Send a test notification to Flare';
|
||||
|
||||
protected Repository $config;
|
||||
|
||||
public function handle(Repository $config): void
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
$this->checkFlareKey();
|
||||
|
||||
if (app()->make('log') instanceof LogManager) {
|
||||
$this->checkFlareLogger();
|
||||
}
|
||||
|
||||
$this->sendTestException();
|
||||
}
|
||||
|
||||
protected function checkFlareKey(): self
|
||||
{
|
||||
$message = empty($this->config->get('flare.key'))
|
||||
? '❌ Flare key not specified. Make sure you specify a value in the `key` key of the `flare` config file.'
|
||||
: '✅ Flare key specified';
|
||||
|
||||
$this->info($message);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function checkFlareLogger(): self
|
||||
{
|
||||
$defaultLogChannel = $this->config->get('logging.default');
|
||||
|
||||
$activeStack = $this->config->get("logging.channels.{$defaultLogChannel}");
|
||||
|
||||
if (is_null($activeStack)) {
|
||||
$this->info("❌ The default logging channel `{$defaultLogChannel}` is not configured in the `logging` config file");
|
||||
}
|
||||
|
||||
if (! isset($activeStack['channels']) || ! in_array('flare', $activeStack['channels'])) {
|
||||
$this->info("❌ The logging channel `{$defaultLogChannel}` does not contain the 'flare' channel");
|
||||
}
|
||||
|
||||
if (is_null($this->config->get('logging.channels.flare'))) {
|
||||
$this->info('❌ There is no logging channel named `flare` in the `logging` config file');
|
||||
}
|
||||
|
||||
if ($this->config->get('logging.channels.flare.driver') !== 'flare') {
|
||||
$this->info('❌ The `flare` logging channel defined in the `logging` config file is not set to `flare`.');
|
||||
}
|
||||
|
||||
if ($this->config->get('ignition.with_stack_frame_arguments') && ini_get('zend.exception_ignore_args')) {
|
||||
$this->info('⚠️ The `zend.exception_ignore_args` php ini setting is enabled. This will prevent Flare from showing stack trace arguments.');
|
||||
}
|
||||
|
||||
$this->info('✅ The Flare logging driver was configured correctly.');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function sendTestException(): void
|
||||
{
|
||||
$testException = new Exception('This is an exception to test if the integration with Flare works.');
|
||||
|
||||
try {
|
||||
app(Flare::class)->sendTestReport($testException);
|
||||
$this->info('');
|
||||
} catch (Exception $exception) {
|
||||
$this->warn('❌ We were unable to send an exception to Flare. ');
|
||||
|
||||
if ($exception instanceof BadResponseCode) {
|
||||
$this->info('');
|
||||
$message = 'Unknown error';
|
||||
|
||||
$body = $exception->response->getBody();
|
||||
|
||||
if (is_array($body) && isset($body['message'])) {
|
||||
$message = $body['message'];
|
||||
}
|
||||
|
||||
$this->warn("{$exception->response->getHttpResponseCode()} - {$message}");
|
||||
} else {
|
||||
$this->warn($exception->getMessage());
|
||||
}
|
||||
|
||||
$this->warn('Make sure that your key is correct and that you have a valid subscription.');
|
||||
$this->info('');
|
||||
$this->info('For more info visit the docs on https://flareapp.io/docs/ignition-for-laravel/introduction');
|
||||
$this->info('You can see the status page of Flare at https://status.flareapp.io');
|
||||
$this->info('Flare support can be reached at support@flareapp.io');
|
||||
|
||||
$this->line('');
|
||||
$this->line('Extra info');
|
||||
$this->table([], [
|
||||
['Platform', PHP_OS],
|
||||
['PHP', phpversion()],
|
||||
['Laravel', app()->version()],
|
||||
['spatie/ignition', InstalledVersions::getVersion('spatie/ignition')],
|
||||
['spatie/laravel-ignition', InstalledVersions::getVersion('spatie/laravel-ignition')],
|
||||
['spatie/flare-client-php', InstalledVersions::getVersion('spatie/flare-client-php')],
|
||||
/** @phpstan-ignore-next-line */
|
||||
['Curl', curl_version()['version'] ?? 'Unknown'],
|
||||
/** @phpstan-ignore-next-line */
|
||||
['SSL', curl_version()['ssl_version'] ?? 'Unknown'],
|
||||
]);
|
||||
|
||||
if ($this->output->isVerbose()) {
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->info('We tried to send an exception to Flare. Please check if it arrived!');
|
||||
}
|
||||
}
|
||||
43
vendor/spatie/laravel-ignition/src/Commands/stubs/runnable-solution.stub
vendored
Normal file
43
vendor/spatie/laravel-ignition/src/Commands/stubs/runnable-solution.stub
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\RunnableSolution;
|
||||
|
||||
class DummyClass implements RunnableSolution
|
||||
{
|
||||
public function getSolutionTitle(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getDocumentationLinks(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getSolutionActionDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getRunButtonText(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getSolutionDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getRunParameters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function run(array $parameters = [])
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
19
vendor/spatie/laravel-ignition/src/Commands/stubs/solution-provider.stub
vendored
Normal file
19
vendor/spatie/laravel-ignition/src/Commands/stubs/solution-provider.stub
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\HasSolutionsForThrowable;
|
||||
use Throwable;
|
||||
|
||||
class DummyClass implements HasSolutionsForThrowable
|
||||
{
|
||||
public function canSolve(Throwable $throwable): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getSolutions(Throwable $throwable): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
23
vendor/spatie/laravel-ignition/src/Commands/stubs/solution.stub
vendored
Normal file
23
vendor/spatie/laravel-ignition/src/Commands/stubs/solution.stub
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace DummyNamespace;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\Solution;
|
||||
|
||||
class DummyClass implements Solution
|
||||
{
|
||||
public function getSolutionTitle(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getSolutionDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getDocumentationLinks(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
9
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelConsoleContextProvider.php
vendored
Normal file
9
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelConsoleContextProvider.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\ContextProviders;
|
||||
|
||||
use Spatie\FlareClient\Context\ConsoleContextProvider;
|
||||
|
||||
class LaravelConsoleContextProvider extends ConsoleContextProvider
|
||||
{
|
||||
}
|
||||
31
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelContextProviderDetector.php
vendored
Normal file
31
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelContextProviderDetector.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\ContextProviders;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Livewire\LivewireManager;
|
||||
use Spatie\FlareClient\Context\ContextProvider;
|
||||
use Spatie\FlareClient\Context\ContextProviderDetector;
|
||||
|
||||
class LaravelContextProviderDetector implements ContextProviderDetector
|
||||
{
|
||||
public function detectCurrentContext(): ContextProvider
|
||||
{
|
||||
if (app()->runningInConsole()) {
|
||||
return new LaravelConsoleContextProvider($_SERVER['argv'] ?? []);
|
||||
}
|
||||
|
||||
$request = app(Request::class);
|
||||
|
||||
if ($this->isRunningLiveWire($request)) {
|
||||
return new LaravelLivewireRequestContextProvider($request, app(LivewireManager::class));
|
||||
}
|
||||
|
||||
return new LaravelRequestContextProvider($request);
|
||||
}
|
||||
|
||||
protected function isRunningLiveWire(Request $request): bool
|
||||
{
|
||||
return $request->hasHeader('x-livewire') && $request->hasHeader('referer');
|
||||
}
|
||||
}
|
||||
129
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelLivewireRequestContextProvider.php
vendored
Normal file
129
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelLivewireRequestContextProvider.php
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\ContextProviders;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Livewire\LivewireManager;
|
||||
use Livewire\Mechanisms\ComponentRegistry;
|
||||
|
||||
class LaravelLivewireRequestContextProvider extends LaravelRequestContextProvider
|
||||
{
|
||||
public function __construct(
|
||||
Request $request,
|
||||
protected LivewireManager $livewireManager
|
||||
) {
|
||||
parent::__construct($request);
|
||||
}
|
||||
|
||||
/** @return array<string, string> */
|
||||
public function getRequest(): array
|
||||
{
|
||||
$properties = parent::getRequest();
|
||||
|
||||
$properties['method'] = $this->livewireManager->originalMethod();
|
||||
$properties['url'] = $this->livewireManager->originalUrl();
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/** @return array<int|string, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
$properties = parent::toArray();
|
||||
|
||||
$properties['livewire'] = $this->getLivewireInformation();
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
/** @return array<int, mixed> */
|
||||
protected function getLivewireInformation(): array
|
||||
{
|
||||
if ($this->request->has('components')) {
|
||||
$data = [];
|
||||
|
||||
foreach ($this->request->get('components') as $component) {
|
||||
$snapshot = json_decode($component['snapshot'], true);
|
||||
|
||||
$class = app(ComponentRegistry::class)->getClass($snapshot['memo']['name']);
|
||||
|
||||
$data[] = [
|
||||
'component_class' => $class ?? null,
|
||||
'data' => $snapshot['data'],
|
||||
'memo' => $snapshot['memo'],
|
||||
'updates' => $this->resolveUpdates($component['updates']),
|
||||
'calls' => $component['calls'],
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$componentId = $this->request->input('fingerprint.id');
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$componentAlias = $this->request->input('fingerprint.name');
|
||||
|
||||
if ($componentAlias === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
$componentClass = $this->livewireManager->getClass($componentAlias);
|
||||
} catch (Exception $e) {
|
||||
$componentClass = null;
|
||||
}
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$updates = $this->request->input('updates') ?? [];
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$updates = $this->request->input('updates') ?? [];
|
||||
|
||||
return [
|
||||
[
|
||||
'component_class' => $componentClass,
|
||||
'component_alias' => $componentAlias,
|
||||
'component_id' => $componentId,
|
||||
'data' => $this->resolveData(),
|
||||
'updates' => $this->resolveUpdates($updates),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
protected function resolveData(): array
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$data = $this->request->input('serverMemo.data') ?? [];
|
||||
|
||||
/** @phpstan-ignore-next-line */
|
||||
$dataMeta = $this->request->input('serverMemo.dataMeta') ?? [];
|
||||
|
||||
foreach ($dataMeta['modelCollections'] ?? [] as $key => $value) {
|
||||
$data[$key] = array_merge($data[$key] ?? [], $value);
|
||||
}
|
||||
|
||||
foreach ($dataMeta['models'] ?? [] as $key => $value) {
|
||||
$data[$key] = array_merge($data[$key] ?? [], $value);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
protected function resolveUpdates(array $updates): array
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$updates = $this->request->input('updates') ?? [];
|
||||
|
||||
return array_map(function (array $update) {
|
||||
$update['payload'] = Arr::except($update['payload'] ?? [], ['id']);
|
||||
|
||||
return $update;
|
||||
}, $updates);
|
||||
}
|
||||
}
|
||||
102
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelRequestContextProvider.php
vendored
Normal file
102
vendor/spatie/laravel-ignition/src/ContextProviders/LaravelRequestContextProvider.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\ContextProviders;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request as LaravelRequest;
|
||||
use Spatie\FlareClient\Context\RequestContextProvider;
|
||||
use Symfony\Component\HttpFoundation\Request as SymphonyRequest;
|
||||
use Throwable;
|
||||
|
||||
class LaravelRequestContextProvider extends RequestContextProvider
|
||||
{
|
||||
protected LaravelRequest|SymphonyRequest|null $request;
|
||||
|
||||
public function __construct(LaravelRequest $request)
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
/** @return null|array<string, mixed> */
|
||||
public function getUser(): array|null
|
||||
{
|
||||
try {
|
||||
/** @var object|null $user */
|
||||
/** @phpstan-ignore-next-line */
|
||||
$user = $this->request?->user();
|
||||
|
||||
if (! $user) {
|
||||
return null;
|
||||
}
|
||||
} catch (Throwable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
if (method_exists($user, 'toFlare')) {
|
||||
return $user->toFlare();
|
||||
}
|
||||
|
||||
if (method_exists($user, 'toArray')) {
|
||||
return $user->toArray();
|
||||
}
|
||||
} catch (Throwable $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return null|array<string, mixed> */
|
||||
public function getRoute(): array|null
|
||||
{
|
||||
/**
|
||||
* @phpstan-ignore-next-line
|
||||
* @var \Illuminate\Routing\Route|null $route
|
||||
*/
|
||||
$route = $this->request->route();
|
||||
|
||||
if (! $route) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'route' => $route->getName(),
|
||||
'routeParameters' => $this->getRouteParameters(),
|
||||
'controllerAction' => $route->getActionName(),
|
||||
'middleware' => array_values($route->gatherMiddleware() ?? []),
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<int, mixed> */
|
||||
protected function getRouteParameters(): array
|
||||
{
|
||||
try {
|
||||
/** @phpstan-ignore-next-line */
|
||||
return collect(optional($this->request->route())->parameters ?? [])
|
||||
->map(fn ($parameter) => $parameter instanceof Model ? $parameter->withoutRelations() : $parameter)
|
||||
->map(function ($parameter) {
|
||||
return method_exists($parameter, 'toFlare') ? $parameter->toFlare() : $parameter;
|
||||
})
|
||||
->toArray();
|
||||
} catch (Throwable) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/** @return array<int, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
$properties = parent::toArray();
|
||||
|
||||
if ($route = $this->getRoute()) {
|
||||
$properties['route'] = $route;
|
||||
}
|
||||
|
||||
if ($user = $this->getUser()) {
|
||||
$properties['user'] = $user;
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
}
|
||||
23
vendor/spatie/laravel-ignition/src/Exceptions/CannotExecuteSolutionForNonLocalIp.php
vendored
Normal file
23
vendor/spatie/laravel-ignition/src/Exceptions/CannotExecuteSolutionForNonLocalIp.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Exceptions;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\BaseSolution;
|
||||
use Spatie\ErrorSolutions\Contracts\ProvidesSolution;
|
||||
use Spatie\ErrorSolutions\Contracts\Solution;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class CannotExecuteSolutionForNonLocalIp extends HttpException implements ProvidesSolution
|
||||
{
|
||||
public static function make(): self
|
||||
{
|
||||
return new self(403, 'Solutions cannot be run from your current IP address.');
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return BaseSolution::create()
|
||||
->setSolutionTitle('Checking your environment settings')
|
||||
->setSolutionDescription("Solutions can only be executed by requests from a local IP address. Keep in mind that `APP_DEBUG` should set to false on any production environment.");
|
||||
}
|
||||
}
|
||||
31
vendor/spatie/laravel-ignition/src/Exceptions/InvalidConfig.php
vendored
Normal file
31
vendor/spatie/laravel-ignition/src/Exceptions/InvalidConfig.php
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Monolog\Level;
|
||||
use Spatie\ErrorSolutions\Contracts\BaseSolution;
|
||||
use Spatie\ErrorSolutions\Contracts\ProvidesSolution;
|
||||
use Spatie\ErrorSolutions\Contracts\Solution;
|
||||
|
||||
class InvalidConfig extends Exception implements ProvidesSolution
|
||||
{
|
||||
public static function invalidLogLevel(string $logLevel): self
|
||||
{
|
||||
return new self("Invalid log level `{$logLevel}` specified.");
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
$validLogLevels = array_map(
|
||||
fn (string $level) => strtolower($level),
|
||||
array_keys(Level::VALUES)
|
||||
);
|
||||
|
||||
$validLogLevelsString = implode(',', $validLogLevels);
|
||||
|
||||
return BaseSolution::create()
|
||||
->setSolutionTitle('You provided an invalid log level')
|
||||
->setSolutionDescription("Please change the log level in your `config/logging.php` file. Valid log levels are {$validLogLevelsString}.");
|
||||
}
|
||||
}
|
||||
55
vendor/spatie/laravel-ignition/src/Exceptions/ViewException.php
vendored
Normal file
55
vendor/spatie/laravel-ignition/src/Exceptions/ViewException.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Exceptions;
|
||||
|
||||
use ErrorException;
|
||||
use Spatie\FlareClient\Contracts\ProvidesFlareContext;
|
||||
use Spatie\LaravelIgnition\Recorders\DumpRecorder\HtmlDumper;
|
||||
|
||||
class ViewException extends ErrorException implements ProvidesFlareContext
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
protected array $viewData = [];
|
||||
|
||||
protected string $view = '';
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setViewData(array $data): void
|
||||
{
|
||||
$this->viewData = $data;
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function getViewData(): array
|
||||
{
|
||||
return $this->viewData;
|
||||
}
|
||||
|
||||
public function setView(string $path): void
|
||||
{
|
||||
$this->view = $path;
|
||||
}
|
||||
|
||||
protected function dumpViewData(mixed $variable): string
|
||||
{
|
||||
return (new HtmlDumper())->dumpVariable($variable);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function context(): array
|
||||
{
|
||||
$context = [
|
||||
'view' => [
|
||||
'view' => $this->view,
|
||||
],
|
||||
];
|
||||
|
||||
$context['view']['data'] = array_map([$this, 'dumpViewData'], $this->viewData);
|
||||
|
||||
return $context;
|
||||
}
|
||||
}
|
||||
21
vendor/spatie/laravel-ignition/src/Exceptions/ViewExceptionWithSolution.php
vendored
Normal file
21
vendor/spatie/laravel-ignition/src/Exceptions/ViewExceptionWithSolution.php
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Exceptions;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\ProvidesSolution;
|
||||
use Spatie\ErrorSolutions\Contracts\Solution;
|
||||
|
||||
class ViewExceptionWithSolution extends ViewException implements ProvidesSolution
|
||||
{
|
||||
protected Solution $solution;
|
||||
|
||||
public function setSolution(Solution $solution): void
|
||||
{
|
||||
$this->solution = $solution;
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
return $this->solution;
|
||||
}
|
||||
}
|
||||
26
vendor/spatie/laravel-ignition/src/Facades/Flare.php
vendored
Normal file
26
vendor/spatie/laravel-ignition/src/Facades/Flare.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
use Spatie\LaravelIgnition\Support\SentReports;
|
||||
|
||||
/**
|
||||
* @method static void glow(string $name, string $messageLevel = \Spatie\FlareClient\Enums\MessageLevels::INFO, array $metaData = [])
|
||||
* @method static void context($key, $value)
|
||||
* @method static void group(string $groupName, array $properties)
|
||||
*
|
||||
* @see \Spatie\FlareClient\Flare
|
||||
*/
|
||||
class Flare extends Facade
|
||||
{
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return \Spatie\FlareClient\Flare::class;
|
||||
}
|
||||
|
||||
public static function sentReports(): SentReports
|
||||
{
|
||||
return app(SentReports::class);
|
||||
}
|
||||
}
|
||||
27
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddContext.php
vendored
Normal file
27
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddContext.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Log\Context\Repository;
|
||||
use Illuminate\Support\Facades\Context;
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
|
||||
class AddContext implements FlareMiddleware
|
||||
{
|
||||
public function handle(Report $report, Closure $next)
|
||||
{
|
||||
if (! class_exists(Repository::class)) {
|
||||
return $next($report);
|
||||
}
|
||||
|
||||
$allContext = Context::all();
|
||||
|
||||
if (count($allContext)) {
|
||||
$report->group('laravel_context', $allContext);
|
||||
}
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
25
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddDumps.php
vendored
Normal file
25
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddDumps.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Closure;
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
use Spatie\LaravelIgnition\Recorders\DumpRecorder\DumpRecorder;
|
||||
|
||||
class AddDumps implements FlareMiddleware
|
||||
{
|
||||
protected DumpRecorder $dumpRecorder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->dumpRecorder = app(DumpRecorder::class);
|
||||
}
|
||||
|
||||
public function handle(Report $report, Closure $next)
|
||||
{
|
||||
$report->group('dumps', $this->dumpRecorder->getDumps());
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
26
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddEnvironmentInformation.php
vendored
Normal file
26
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddEnvironmentInformation.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Closure;
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
|
||||
class AddEnvironmentInformation implements FlareMiddleware
|
||||
{
|
||||
public function handle(Report $report, Closure $next)
|
||||
{
|
||||
$report->frameworkVersion(app()->version());
|
||||
|
||||
$report->group('env', [
|
||||
'laravel_version' => app()->version(),
|
||||
'laravel_locale' => app()->getLocale(),
|
||||
'laravel_config_cached' => app()->configurationIsCached(),
|
||||
'app_debug' => config('app.debug'),
|
||||
'app_env' => config('app.env'),
|
||||
'php_version' => phpversion(),
|
||||
]);
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
53
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddExceptionHandledStatus.php
vendored
Normal file
53
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddExceptionHandledStatus.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Closure;
|
||||
use Spatie\Backtrace\Backtrace;
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
use Throwable;
|
||||
|
||||
class AddExceptionHandledStatus implements FlareMiddleware
|
||||
{
|
||||
public function handle(Report $report, Closure $next)
|
||||
{
|
||||
$frames = Backtrace::create()->limit(40)->frames();
|
||||
$frameCount = count($frames);
|
||||
|
||||
try {
|
||||
foreach ($frames as $i => $frame) {
|
||||
// Check first frame, probably Illuminate\Foundation\Exceptions\Handler::report()
|
||||
// Next frame should be: Illuminate/Foundation/helpers.php::report()
|
||||
|
||||
if ($frame->method !== 'report') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($frame->class === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($i === $frameCount - 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($frames[$i + 1]->class !== null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($frames[$i + 1]->method !== 'report') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$report->handled();
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
58
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddExceptionInformation.php
vendored
Normal file
58
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddExceptionInformation.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Illuminate\Database\QueryException;
|
||||
use Spatie\FlareClient\Contracts\ProvidesFlareContext;
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
|
||||
class AddExceptionInformation implements FlareMiddleware
|
||||
{
|
||||
public function handle(Report $report, $next)
|
||||
{
|
||||
$throwable = $report->getThrowable();
|
||||
|
||||
$this->addUserDefinedContext($report);
|
||||
|
||||
if (! $throwable instanceof QueryException) {
|
||||
return $next($report);
|
||||
}
|
||||
|
||||
$report->group('exception', [
|
||||
'raw_sql' => $throwable->getSql(),
|
||||
]);
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
|
||||
private function addUserDefinedContext(Report $report): void
|
||||
{
|
||||
$throwable = $report->getThrowable();
|
||||
|
||||
if ($throwable === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($throwable instanceof ProvidesFlareContext) {
|
||||
// ProvidesFlareContext writes directly to context groups and is handled in the flare-client-php package.
|
||||
return;
|
||||
}
|
||||
|
||||
if (! method_exists($throwable, 'context')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = $throwable->context();
|
||||
|
||||
if (! is_array($context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$exceptionContextGroup = [];
|
||||
foreach ($context as $key => $value) {
|
||||
$exceptionContextGroup[$key] = $value;
|
||||
}
|
||||
$report->group('exception', $exceptionContextGroup);
|
||||
}
|
||||
}
|
||||
26
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddJobs.php
vendored
Normal file
26
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddJobs.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
use Spatie\LaravelIgnition\Recorders\JobRecorder\JobRecorder;
|
||||
|
||||
class AddJobs implements FlareMiddleware
|
||||
{
|
||||
protected JobRecorder $jobRecorder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->jobRecorder = app(JobRecorder::class);
|
||||
}
|
||||
|
||||
public function handle(Report $report, $next)
|
||||
{
|
||||
if ($job = $this->jobRecorder->getJob()) {
|
||||
$report->group('job', $job);
|
||||
}
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
24
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddLogs.php
vendored
Normal file
24
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddLogs.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
use Spatie\LaravelIgnition\Recorders\LogRecorder\LogRecorder;
|
||||
|
||||
class AddLogs implements FlareMiddleware
|
||||
{
|
||||
protected LogRecorder $logRecorder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->logRecorder = app(LogRecorder::class);
|
||||
}
|
||||
|
||||
public function handle(Report $report, $next)
|
||||
{
|
||||
$report->group('logs', $this->logRecorder->getLogMessages());
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddNotifierName.php
vendored
Normal file
18
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddNotifierName.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Spatie\FlareClient\FlareMiddleware\FlareMiddleware;
|
||||
use Spatie\FlareClient\Report;
|
||||
|
||||
class AddNotifierName implements FlareMiddleware
|
||||
{
|
||||
public const NOTIFIER_NAME = 'Laravel Client';
|
||||
|
||||
public function handle(Report $report, $next)
|
||||
{
|
||||
$report->notifierName(static::NOTIFIER_NAME);
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
23
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddQueries.php
vendored
Normal file
23
vendor/spatie/laravel-ignition/src/FlareMiddleware/AddQueries.php
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\FlareMiddleware;
|
||||
|
||||
use Spatie\FlareClient\Report;
|
||||
use Spatie\LaravelIgnition\Recorders\QueryRecorder\QueryRecorder;
|
||||
|
||||
class AddQueries
|
||||
{
|
||||
protected QueryRecorder $queryRecorder;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->queryRecorder = app(QueryRecorder::class);
|
||||
}
|
||||
|
||||
public function handle(Report $report, $next)
|
||||
{
|
||||
$report->group('queries', $this->queryRecorder->getQueries());
|
||||
|
||||
return $next($report);
|
||||
}
|
||||
}
|
||||
52
vendor/spatie/laravel-ignition/src/Http/Controllers/ExecuteSolutionController.php
vendored
Normal file
52
vendor/spatie/laravel-ignition/src/Http/Controllers/ExecuteSolutionController.php
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Spatie\ErrorSolutions\Contracts\SolutionProviderRepository;
|
||||
use Spatie\LaravelIgnition\Exceptions\CannotExecuteSolutionForNonLocalIp;
|
||||
use Spatie\LaravelIgnition\Http\Requests\ExecuteSolutionRequest;
|
||||
use Spatie\LaravelIgnition\Support\RunnableSolutionsGuard;
|
||||
|
||||
class ExecuteSolutionController
|
||||
{
|
||||
use ValidatesRequests;
|
||||
|
||||
public function __invoke(
|
||||
ExecuteSolutionRequest $request,
|
||||
SolutionProviderRepository $solutionProviderRepository
|
||||
) {
|
||||
$this
|
||||
->ensureRunnableSolutionsEnabled()
|
||||
->ensureLocalRequest();
|
||||
|
||||
$solution = $request->getRunnableSolution();
|
||||
|
||||
$solution->run($request->get('parameters', []));
|
||||
|
||||
return response()->noContent();
|
||||
}
|
||||
|
||||
public function ensureRunnableSolutionsEnabled(): self
|
||||
{
|
||||
// Should already be checked in middleware but we want to be 100% certain.
|
||||
abort_unless(RunnableSolutionsGuard::check(), 400);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function ensureLocalRequest(): self
|
||||
{
|
||||
$ipIsPublic = filter_var(
|
||||
request()->ip(),
|
||||
FILTER_VALIDATE_IP,
|
||||
FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
||||
);
|
||||
|
||||
if ($ipIsPublic) {
|
||||
throw CannotExecuteSolutionForNonLocalIp::make();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
25
vendor/spatie/laravel-ignition/src/Http/Controllers/HealthCheckController.php
vendored
Normal file
25
vendor/spatie/laravel-ignition/src/Http/Controllers/HealthCheckController.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class HealthCheckController
|
||||
{
|
||||
public function __invoke()
|
||||
{
|
||||
return [
|
||||
'can_execute_commands' => $this->canExecuteCommands(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function canExecuteCommands(): bool
|
||||
{
|
||||
Artisan::call('help', ['--version']);
|
||||
|
||||
$output = Artisan::output();
|
||||
|
||||
return Str::contains($output, app()->version());
|
||||
}
|
||||
}
|
||||
16
vendor/spatie/laravel-ignition/src/Http/Controllers/UpdateConfigController.php
vendored
Normal file
16
vendor/spatie/laravel-ignition/src/Http/Controllers/UpdateConfigController.php
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Http\Controllers;
|
||||
|
||||
use Spatie\Ignition\Config\IgnitionConfig;
|
||||
use Spatie\LaravelIgnition\Http\Requests\UpdateConfigRequest;
|
||||
|
||||
class UpdateConfigController
|
||||
{
|
||||
public function __invoke(UpdateConfigRequest $request)
|
||||
{
|
||||
$result = (new IgnitionConfig())->saveValues($request->validated());
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-ignition/src/Http/Middleware/RunnableSolutionsEnabled.php
vendored
Normal file
18
vendor/spatie/laravel-ignition/src/Http/Middleware/RunnableSolutionsEnabled.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Spatie\LaravelIgnition\Support\RunnableSolutionsGuard;
|
||||
|
||||
class RunnableSolutionsEnabled
|
||||
{
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
if (! RunnableSolutionsGuard::check()) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
40
vendor/spatie/laravel-ignition/src/Http/Requests/ExecuteSolutionRequest.php
vendored
Normal file
40
vendor/spatie/laravel-ignition/src/Http/Requests/ExecuteSolutionRequest.php
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Spatie\ErrorSolutions\Contracts\RunnableSolution;
|
||||
use Spatie\ErrorSolutions\Contracts\Solution;
|
||||
use Spatie\ErrorSolutions\Contracts\SolutionProviderRepository;
|
||||
|
||||
class ExecuteSolutionRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'solution' => 'required',
|
||||
'parameters' => 'array',
|
||||
];
|
||||
}
|
||||
|
||||
public function getSolution(): Solution
|
||||
{
|
||||
$solution = app(SolutionProviderRepository::class)
|
||||
->getSolutionForClass($this->get('solution'));
|
||||
|
||||
abort_if(is_null($solution), 404, 'Solution could not be found');
|
||||
|
||||
return $solution;
|
||||
}
|
||||
|
||||
public function getRunnableSolution(): RunnableSolution
|
||||
{
|
||||
$solution = $this->getSolution();
|
||||
|
||||
if (! $solution instanceof RunnableSolution) {
|
||||
abort(404, 'Runnable solution could not be found');
|
||||
}
|
||||
|
||||
return $solution;
|
||||
}
|
||||
}
|
||||
18
vendor/spatie/laravel-ignition/src/Http/Requests/UpdateConfigRequest.php
vendored
Normal file
18
vendor/spatie/laravel-ignition/src/Http/Requests/UpdateConfigRequest.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UpdateConfigRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'theme' => ['required', Rule::in(['light', 'dark', 'auto'])],
|
||||
'editor' => ['required'],
|
||||
'hide_solutions' => ['required', 'boolean'],
|
||||
];
|
||||
}
|
||||
}
|
||||
349
vendor/spatie/laravel-ignition/src/IgnitionServiceProvider.php
vendored
Normal file
349
vendor/spatie/laravel-ignition/src/IgnitionServiceProvider.php
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Debug\ExceptionHandler;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\View\ViewException;
|
||||
use Laravel\Octane\Events\RequestReceived;
|
||||
use Laravel\Octane\Events\RequestTerminated;
|
||||
use Laravel\Octane\Events\TaskReceived;
|
||||
use Laravel\Octane\Events\TickReceived;
|
||||
use Monolog\Level;
|
||||
use Monolog\Logger;
|
||||
use Spatie\ErrorSolutions\Contracts\SolutionProviderRepository as SolutionProviderRepositoryContract;
|
||||
use Spatie\ErrorSolutions\SolutionProviderRepository;
|
||||
use Spatie\FlareClient\Flare;
|
||||
use Spatie\FlareClient\FlareMiddleware\AddSolutions;
|
||||
use Spatie\Ignition\Config\FileConfigManager;
|
||||
use Spatie\Ignition\Config\IgnitionConfig;
|
||||
use Spatie\Ignition\Contracts\ConfigManager;
|
||||
use Spatie\Ignition\Ignition;
|
||||
use Spatie\LaravelIgnition\Commands\SolutionMakeCommand;
|
||||
use Spatie\LaravelIgnition\Commands\SolutionProviderMakeCommand;
|
||||
use Spatie\LaravelIgnition\Commands\TestCommand;
|
||||
use Spatie\LaravelIgnition\ContextProviders\LaravelContextProviderDetector;
|
||||
use Spatie\LaravelIgnition\Exceptions\InvalidConfig;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddJobs;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddLogs;
|
||||
use Spatie\LaravelIgnition\FlareMiddleware\AddQueries;
|
||||
use Spatie\LaravelIgnition\Recorders\DumpRecorder\DumpRecorder;
|
||||
use Spatie\LaravelIgnition\Recorders\JobRecorder\JobRecorder;
|
||||
use Spatie\LaravelIgnition\Recorders\LogRecorder\LogRecorder;
|
||||
use Spatie\LaravelIgnition\Recorders\QueryRecorder\QueryRecorder;
|
||||
use Spatie\LaravelIgnition\Renderers\IgnitionExceptionRenderer;
|
||||
use Spatie\LaravelIgnition\Support\FlareLogHandler;
|
||||
use Spatie\LaravelIgnition\Support\SentReports;
|
||||
use Spatie\LaravelIgnition\Views\ViewExceptionMapper;
|
||||
|
||||
class IgnitionServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function register(): void
|
||||
{
|
||||
$this->registerConfig();
|
||||
$this->registerFlare();
|
||||
$this->registerIgnition();
|
||||
$this->registerRenderer();
|
||||
$this->registerRecorders();
|
||||
$this->registerLogHandler();
|
||||
}
|
||||
|
||||
public function boot()
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->registerCommands();
|
||||
$this->publishConfigs();
|
||||
}
|
||||
|
||||
$this->registerRoutes();
|
||||
$this->configureTinker();
|
||||
$this->configureOctane();
|
||||
$this->registerViewExceptionMapper();
|
||||
$this->startRecorders();
|
||||
$this->configureQueue();
|
||||
}
|
||||
|
||||
protected function registerConfig(): void
|
||||
{
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/flare.php', 'flare');
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/ignition.php', 'ignition');
|
||||
}
|
||||
|
||||
protected function registerCommands(): void
|
||||
{
|
||||
if ($this->app['config']->get('flare.key')) {
|
||||
$this->commands([
|
||||
TestCommand::class,
|
||||
]);
|
||||
}
|
||||
|
||||
if ($this->app['config']->get('ignition.register_commands')) {
|
||||
$this->commands([
|
||||
SolutionMakeCommand::class,
|
||||
SolutionProviderMakeCommand::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function publishConfigs(): void
|
||||
{
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/ignition.php' => config_path('ignition.php'),
|
||||
], 'ignition-config');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/flare.php' => config_path('flare.php'),
|
||||
], 'flare-config');
|
||||
}
|
||||
|
||||
protected function registerRenderer(): void
|
||||
{
|
||||
$this->app->bind(
|
||||
'Illuminate\Contracts\Foundation\ExceptionRenderer',
|
||||
fn (Application $app) => $app->make(IgnitionExceptionRenderer::class)
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerFlare(): void
|
||||
{
|
||||
$this->app->singleton(Flare::class, function () {
|
||||
return Flare::make()
|
||||
->setApiToken(config('flare.key') ?? '')
|
||||
->setBaseUrl(config('flare.base_url', 'https://flareapp.io/api'))
|
||||
->applicationPath(base_path())
|
||||
->setStage(app()->environment())
|
||||
->setContextProviderDetector(new LaravelContextProviderDetector())
|
||||
->registerMiddleware($this->getFlareMiddleware())
|
||||
->registerMiddleware(new AddSolutions(new SolutionProviderRepository($this->getSolutionProviders())))
|
||||
->argumentReducers(config('ignition.argument_reducers', []))
|
||||
->withStackFrameArguments(config('ignition.with_stack_frame_arguments', true));
|
||||
});
|
||||
|
||||
$this->app->singleton(SentReports::class);
|
||||
}
|
||||
|
||||
protected function registerIgnition(): void
|
||||
{
|
||||
$this->app->singleton(
|
||||
ConfigManager::class,
|
||||
fn () => new FileConfigManager(config('ignition.settings_file_path', ''))
|
||||
);
|
||||
|
||||
$ignitionConfig = (new IgnitionConfig())
|
||||
->merge(config('ignition', []))
|
||||
->loadConfigFile();
|
||||
|
||||
$solutionProviders = $this->getSolutionProviders();
|
||||
$solutionProviderRepository = new SolutionProviderRepository($solutionProviders);
|
||||
|
||||
$this->app->singleton(IgnitionConfig::class, fn () => $ignitionConfig);
|
||||
|
||||
$this->app->singleton(SolutionProviderRepositoryContract::class, fn () => $solutionProviderRepository);
|
||||
|
||||
$this->app->singleton(
|
||||
Ignition::class,
|
||||
fn () => (new Ignition($this->app->make(Flare::class)))->applicationPath(base_path())
|
||||
);
|
||||
}
|
||||
|
||||
protected function registerRecorders(): void
|
||||
{
|
||||
$this->app->singleton(DumpRecorder::class);
|
||||
|
||||
$this->app->singleton(LogRecorder::class, function (Application $app): LogRecorder {
|
||||
return new LogRecorder(
|
||||
$app,
|
||||
config()->get('flare.flare_middleware.' . AddLogs::class . '.maximum_number_of_collected_logs')
|
||||
);
|
||||
});
|
||||
|
||||
$this->app->singleton(
|
||||
QueryRecorder::class,
|
||||
function (Application $app): QueryRecorder {
|
||||
return new QueryRecorder(
|
||||
$app,
|
||||
config('flare.flare_middleware.' . AddQueries::class . '.report_query_bindings', true),
|
||||
config('flare.flare_middleware.' . AddQueries::class . '.maximum_number_of_collected_queries', 200)
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
$this->app->singleton(JobRecorder::class, function (Application $app): JobRecorder {
|
||||
return new JobRecorder(
|
||||
$app,
|
||||
config('flare.flare_middleware.' . AddJobs::class . '.max_chained_job_reporting_depth', 5)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
public function configureTinker(): void
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
if (isset($_SERVER['argv']) && ['artisan', 'tinker'] === $_SERVER['argv']) {
|
||||
app(Flare::class)->sendReportsImmediately();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function configureOctane(): void
|
||||
{
|
||||
if (isset($_SERVER['LARAVEL_OCTANE'])) {
|
||||
$this->setupOctane();
|
||||
}
|
||||
}
|
||||
|
||||
protected function registerViewExceptionMapper(): void
|
||||
{
|
||||
$handler = $this->app->make(ExceptionHandler::class);
|
||||
|
||||
if (! method_exists($handler, 'map')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$handler->map(function (ViewException $viewException) {
|
||||
return $this->app->make(ViewExceptionMapper::class)->map($viewException);
|
||||
});
|
||||
}
|
||||
|
||||
protected function registerRoutes(): void
|
||||
{
|
||||
$this->loadRoutesFrom(realpath(__DIR__ . '/ignition-routes.php'));
|
||||
}
|
||||
|
||||
protected function registerLogHandler(): void
|
||||
{
|
||||
$this->app->singleton('flare.logger', function ($app) {
|
||||
$handler = new FlareLogHandler(
|
||||
$app->make(Flare::class),
|
||||
$app->make(SentReports::class),
|
||||
);
|
||||
|
||||
$logLevelString = config('logging.channels.flare.level', 'error');
|
||||
|
||||
$logLevel = $this->getLogLevel($logLevelString);
|
||||
|
||||
$handler->setMinimumReportLogLevel($logLevel);
|
||||
|
||||
return tap(
|
||||
new Logger('Flare'),
|
||||
fn (Logger $logger) => $logger->pushHandler($handler)
|
||||
);
|
||||
});
|
||||
|
||||
Log::extend('flare', fn ($app) => $app['flare.logger']);
|
||||
}
|
||||
|
||||
protected function startRecorders(): void
|
||||
{
|
||||
foreach ($this->app->config['ignition.recorders'] ?? [] as $recorder) {
|
||||
$this->app->make($recorder)->start();
|
||||
}
|
||||
}
|
||||
|
||||
protected function configureQueue(): void
|
||||
{
|
||||
if (! $this->app->bound('queue')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$queue = $this->app->get('queue');
|
||||
|
||||
// Reset before executing a queue job to make sure the job's log/query/dump recorders are empty.
|
||||
// When using a sync queue this also reports the queued reports from previous exceptions.
|
||||
$queue->before(function () {
|
||||
$this->resetFlareAndLaravelIgnition();
|
||||
app(Flare::class)->sendReportsImmediately();
|
||||
});
|
||||
|
||||
// Send queued reports (and reset) after executing a queue job.
|
||||
$queue->after(function () {
|
||||
$this->resetFlareAndLaravelIgnition();
|
||||
});
|
||||
|
||||
// Note: the $queue->looping() event can't be used because it's not triggered on Vapor
|
||||
}
|
||||
|
||||
protected function getLogLevel(string $logLevelString): int
|
||||
{
|
||||
try {
|
||||
$logLevel = Level::fromName($logLevelString);
|
||||
} catch (Exception $exception) {
|
||||
$logLevel = null;
|
||||
}
|
||||
|
||||
if (! $logLevel) {
|
||||
throw InvalidConfig::invalidLogLevel($logLevelString);
|
||||
}
|
||||
|
||||
return $logLevel->value;
|
||||
}
|
||||
|
||||
protected function getFlareMiddleware(): array
|
||||
{
|
||||
return collect(config('flare.flare_middleware'))
|
||||
->map(function ($value, $key) {
|
||||
if (is_string($key)) {
|
||||
$middlewareClass = $key;
|
||||
$parameters = $value ?? [];
|
||||
} else {
|
||||
$middlewareClass = $value;
|
||||
$parameters = [];
|
||||
}
|
||||
|
||||
return new $middlewareClass(...array_values($parameters));
|
||||
})
|
||||
->values()
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function getSolutionProviders(): array
|
||||
{
|
||||
return collect(config('ignition.solution_providers'))
|
||||
->reject(
|
||||
fn (string $class) => in_array($class, config('ignition.ignored_solution_providers'))
|
||||
)
|
||||
->toArray();
|
||||
}
|
||||
|
||||
protected function setupOctane(): void
|
||||
{
|
||||
$this->app['events']->listen(RequestReceived::class, function () {
|
||||
$this->resetFlareAndLaravelIgnition();
|
||||
});
|
||||
|
||||
$this->app['events']->listen(TaskReceived::class, function () {
|
||||
$this->resetFlareAndLaravelIgnition();
|
||||
});
|
||||
|
||||
$this->app['events']->listen(TickReceived::class, function () {
|
||||
$this->resetFlareAndLaravelIgnition();
|
||||
});
|
||||
|
||||
$this->app['events']->listen(RequestTerminated::class, function () {
|
||||
$this->resetFlareAndLaravelIgnition();
|
||||
});
|
||||
}
|
||||
|
||||
protected function resetFlareAndLaravelIgnition(): void
|
||||
{
|
||||
$this->app->get(SentReports::class)->clear();
|
||||
$this->app->get(Ignition::class)->reset();
|
||||
|
||||
if (config('flare.flare_middleware.' . AddLogs::class)) {
|
||||
$this->app->make(LogRecorder::class)->reset();
|
||||
}
|
||||
|
||||
if (config('flare.flare_middleware.' . AddQueries::class)) {
|
||||
$this->app->make(QueryRecorder::class)->reset();
|
||||
}
|
||||
|
||||
if (config('flare.flare_middleware.' . AddJobs::class)) {
|
||||
$this->app->make(JobRecorder::class)->reset();
|
||||
}
|
||||
|
||||
$this->app->make(DumpRecorder::class)->reset();
|
||||
}
|
||||
}
|
||||
33
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/Dump.php
vendored
Normal file
33
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/Dump.php
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\DumpRecorder;
|
||||
|
||||
class Dump
|
||||
{
|
||||
protected string $htmlDump;
|
||||
|
||||
protected ?string $file;
|
||||
|
||||
protected ?int $lineNumber;
|
||||
|
||||
protected float $microtime;
|
||||
|
||||
public function __construct(string $htmlDump, ?string $file, ?int $lineNumber, ?float $microtime = null)
|
||||
{
|
||||
$this->htmlDump = $htmlDump;
|
||||
$this->file = $file;
|
||||
$this->lineNumber = $lineNumber;
|
||||
$this->microtime = $microtime ?? microtime(true);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'html_dump' => $this->htmlDump,
|
||||
'file' => $this->file,
|
||||
'line_number' => $this->lineNumber,
|
||||
'microtime' => $this->microtime,
|
||||
];
|
||||
}
|
||||
}
|
||||
22
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/DumpHandler.php
vendored
Normal file
22
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/DumpHandler.php
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\DumpRecorder;
|
||||
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
|
||||
class DumpHandler
|
||||
{
|
||||
protected DumpRecorder $dumpRecorder;
|
||||
|
||||
public function __construct(DumpRecorder $dumpRecorder)
|
||||
{
|
||||
$this->dumpRecorder = $dumpRecorder;
|
||||
}
|
||||
|
||||
public function dump(mixed $value): void
|
||||
{
|
||||
$data = (new VarCloner)->cloneVar($value);
|
||||
|
||||
$this->dumpRecorder->record($data);
|
||||
}
|
||||
}
|
||||
135
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/DumpRecorder.php
vendored
Normal file
135
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/DumpRecorder.php
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\DumpRecorder;
|
||||
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Support\Arr;
|
||||
use ReflectionMethod;
|
||||
use ReflectionProperty;
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
|
||||
class DumpRecorder
|
||||
{
|
||||
/** @var array<array<int,mixed>> */
|
||||
protected array $dumps = [];
|
||||
|
||||
protected Application $app;
|
||||
|
||||
protected static bool $registeredHandler = false;
|
||||
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
public function start(): self
|
||||
{
|
||||
$multiDumpHandler = new MultiDumpHandler();
|
||||
|
||||
$this->app->singleton(MultiDumpHandler::class, fn () => $multiDumpHandler);
|
||||
|
||||
if (! self::$registeredHandler) {
|
||||
static::$registeredHandler = true;
|
||||
|
||||
$this->ensureOriginalHandlerExists();
|
||||
|
||||
$originalHandler = VarDumper::setHandler(fn ($dumpedVariable) => $multiDumpHandler->dump($dumpedVariable));
|
||||
|
||||
$multiDumpHandler?->addHandler($originalHandler);
|
||||
|
||||
$multiDumpHandler->addHandler(fn ($var) => (new DumpHandler($this))->dump($var));
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function record(Data $data): void
|
||||
{
|
||||
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 11);
|
||||
|
||||
$sourceFrame = $this->findSourceFrame($backtrace);
|
||||
|
||||
$file = (string) Arr::get($sourceFrame, 'file');
|
||||
$lineNumber = (int) Arr::get($sourceFrame, 'line');
|
||||
|
||||
$htmlDump = (new HtmlDumper())->dump($data);
|
||||
|
||||
$this->dumps[] = new Dump($htmlDump, $file, $lineNumber);
|
||||
}
|
||||
|
||||
public function getDumps(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->dumps = [];
|
||||
}
|
||||
|
||||
public function toArray(): array
|
||||
{
|
||||
$dumps = [];
|
||||
|
||||
foreach ($this->dumps as $dump) {
|
||||
$dumps[] = $dump->toArray();
|
||||
}
|
||||
|
||||
return $dumps;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only the `VarDumper` knows how to create the orignal HTML or CLI VarDumper.
|
||||
* Using reflection and the private VarDumper::register() method we can force it
|
||||
* to create and register a new VarDumper::$handler before we'll overwrite it.
|
||||
* Of course, we only need to do this if there isn't a registered VarDumper::$handler.
|
||||
*
|
||||
* @throws \ReflectionException
|
||||
*/
|
||||
protected function ensureOriginalHandlerExists(): void
|
||||
{
|
||||
$reflectionProperty = new ReflectionProperty(VarDumper::class, 'handler');
|
||||
$reflectionProperty->setAccessible(true);
|
||||
$handler = $reflectionProperty->getValue();
|
||||
|
||||
if (! $handler) {
|
||||
// No handler registered yet, so we'll force VarDumper to create one.
|
||||
$reflectionMethod = new ReflectionMethod(VarDumper::class, 'register');
|
||||
$reflectionMethod->setAccessible(true);
|
||||
$reflectionMethod->invoke(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the first meaningful stack frame that is not the `DumpRecorder` itself.
|
||||
*
|
||||
* @template T of array{class?: class-string, function?: string, line?: int, file?: string}
|
||||
*
|
||||
* @param array<T> $stacktrace
|
||||
*
|
||||
* @return null|T
|
||||
*/
|
||||
protected function findSourceFrame(array $stacktrace): ?array
|
||||
{
|
||||
$seenVarDumper = false;
|
||||
|
||||
foreach ($stacktrace as $frame) {
|
||||
// Keep looping until we're past the VarDumper::dump() call in Symfony's helper functions file.
|
||||
if (Arr::get($frame, 'class') === VarDumper::class && Arr::get($frame, 'function') === 'dump') {
|
||||
$seenVarDumper = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $seenVarDumper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Return the next frame in the stack after the VarDumper::dump() call:
|
||||
return $frame;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
34
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/HtmlDumper.php
vendored
Normal file
34
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/HtmlDumper.php
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\DumpRecorder;
|
||||
|
||||
use Symfony\Component\VarDumper\Cloner\Data;
|
||||
use Symfony\Component\VarDumper\Cloner\VarCloner;
|
||||
use Symfony\Component\VarDumper\Dumper\HtmlDumper as BaseHtmlDumper;
|
||||
|
||||
class HtmlDumper extends BaseHtmlDumper
|
||||
{
|
||||
public function __construct($output = null, ?string $charset = null, int $flags = 0)
|
||||
{
|
||||
parent::__construct($output, $charset, $flags);
|
||||
|
||||
$this->setDumpHeader('');
|
||||
}
|
||||
|
||||
public function dumpVariable($variable): string
|
||||
{
|
||||
$cloner = new VarCloner();
|
||||
|
||||
$clonedData = $cloner->cloneVar($variable)->withMaxDepth(3);
|
||||
|
||||
return $this->dump($clonedData);
|
||||
}
|
||||
|
||||
public function dump(Data $data, $output = null, array $extraDisplayOptions = []): string
|
||||
{
|
||||
return (string)parent::dump($data, true, [
|
||||
'maxDepth' => 3,
|
||||
'maxStringLength' => 160,
|
||||
]);
|
||||
}
|
||||
}
|
||||
27
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/MultiDumpHandler.php
vendored
Normal file
27
vendor/spatie/laravel-ignition/src/Recorders/DumpRecorder/MultiDumpHandler.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\DumpRecorder;
|
||||
|
||||
class MultiDumpHandler
|
||||
{
|
||||
/** @var array<int, callable|null> */
|
||||
protected array $handlers = [];
|
||||
|
||||
public function dump(mixed $value): void
|
||||
{
|
||||
foreach ($this->handlers as $handler) {
|
||||
if ($handler) {
|
||||
$handler($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function addHandler(?callable $callable = null): self
|
||||
{
|
||||
if ($callable) {
|
||||
$this->handlers[] = $callable;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
177
vendor/spatie/laravel-ignition/src/Recorders/JobRecorder/JobRecorder.php
vendored
Normal file
177
vendor/spatie/laravel-ignition/src/Recorders/JobRecorder/JobRecorder.php
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\JobRecorder;
|
||||
|
||||
use DateTime;
|
||||
use Error;
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\Queue\Job;
|
||||
use Illuminate\Queue\CallQueuedClosure;
|
||||
use Illuminate\Queue\Events\JobExceptionOccurred;
|
||||
use Illuminate\Queue\Jobs\RedisJob;
|
||||
use Illuminate\Support\Str;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use RuntimeException;
|
||||
|
||||
class JobRecorder
|
||||
{
|
||||
protected ?Job $job = null;
|
||||
|
||||
public function __construct(
|
||||
protected Application $app,
|
||||
protected int $maxChainedJobReportingDepth = 5,
|
||||
) {
|
||||
}
|
||||
|
||||
public function start(): self
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$this->app['events']->listen(JobExceptionOccurred::class, [$this, 'record']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function record(JobExceptionOccurred $event): void
|
||||
{
|
||||
$this->job = $event->job;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>|null
|
||||
*/
|
||||
public function getJob(): ?array
|
||||
{
|
||||
if ($this->job === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array_merge(
|
||||
$this->getJobProperties(),
|
||||
[
|
||||
'name' => $this->job->resolveName(),
|
||||
'connection' => $this->job->getConnectionName(),
|
||||
'queue' => $this->job->getQueue(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->job = null;
|
||||
}
|
||||
|
||||
protected function getJobProperties(): array
|
||||
{
|
||||
$payload = collect($this->resolveJobPayload());
|
||||
|
||||
$properties = [];
|
||||
|
||||
foreach ($payload as $key => $value) {
|
||||
if (! in_array($key, ['job', 'data', 'displayName'])) {
|
||||
$properties[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (is_string($payload['data'])) {
|
||||
$properties['data'] = json_decode($payload['data'], true, 512, JSON_THROW_ON_ERROR);
|
||||
}
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
|
||||
if ($pushedAt = DateTime::createFromFormat('U.u', $payload->get('pushedAt', ''))) {
|
||||
$properties['pushedAt'] = $pushedAt->format(DATE_ATOM);
|
||||
}
|
||||
|
||||
try {
|
||||
$properties['data'] = $this->resolveCommandProperties(
|
||||
$this->resolveObjectFromCommand($payload['data']['command']),
|
||||
$this->maxChainedJobReportingDepth
|
||||
);
|
||||
} catch (Exception $exception) {
|
||||
}
|
||||
|
||||
return $properties;
|
||||
}
|
||||
|
||||
protected function resolveJobPayload(): array
|
||||
{
|
||||
if (! $this->job instanceof RedisJob) {
|
||||
return $this->job->payload();
|
||||
}
|
||||
|
||||
try {
|
||||
return json_decode($this->job->getReservedJob(), true, 512, JSON_THROW_ON_ERROR);
|
||||
} catch (Exception $e) {
|
||||
return $this->job->payload();
|
||||
}
|
||||
}
|
||||
|
||||
protected function resolveCommandProperties(object $command, int $maxChainDepth): array
|
||||
{
|
||||
$propertiesToIgnore = ['job', 'closure'];
|
||||
|
||||
$properties = collect((new ReflectionClass($command))->getProperties())
|
||||
->reject(function (ReflectionProperty $property) use ($propertiesToIgnore) {
|
||||
return in_array($property->name, $propertiesToIgnore);
|
||||
})
|
||||
->mapWithKeys(function (ReflectionProperty $property) use ($command) {
|
||||
try {
|
||||
$property->setAccessible(true);
|
||||
|
||||
return [$property->name => $property->getValue($command)];
|
||||
} catch (Error $error) {
|
||||
return [$property->name => 'uninitialized'];
|
||||
}
|
||||
});
|
||||
|
||||
if ($properties->has('chained')) {
|
||||
$properties['chained'] = $this->resolveJobChain($properties->get('chained'), $maxChainDepth);
|
||||
}
|
||||
|
||||
return $properties->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $chainedCommands
|
||||
* @param int $maxDepth
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function resolveJobChain(array $chainedCommands, int $maxDepth): array
|
||||
{
|
||||
if ($maxDepth === 0) {
|
||||
return ['Ignition stopped recording jobs after this point since the max chain depth was reached'];
|
||||
}
|
||||
|
||||
return array_map(
|
||||
function (string $command) use ($maxDepth) {
|
||||
$commandObject = $this->resolveObjectFromCommand($command);
|
||||
|
||||
return [
|
||||
'name' => $commandObject instanceof CallQueuedClosure ? $commandObject->displayName() : get_class($commandObject),
|
||||
'data' => $this->resolveCommandProperties($commandObject, $maxDepth - 1),
|
||||
];
|
||||
},
|
||||
$chainedCommands
|
||||
);
|
||||
}
|
||||
|
||||
// Taken from Illuminate\Queue\CallQueuedHandler
|
||||
protected function resolveObjectFromCommand(string $command): object
|
||||
{
|
||||
if (Str::startsWith($command, 'O:')) {
|
||||
return unserialize($command);
|
||||
}
|
||||
|
||||
if ($this->app->bound(Encrypter::class)) {
|
||||
/** @phpstan-ignore-next-line */
|
||||
return unserialize($this->app[Encrypter::class]->decrypt($command));
|
||||
}
|
||||
|
||||
throw new RuntimeException('Unable to extract job payload.');
|
||||
}
|
||||
}
|
||||
55
vendor/spatie/laravel-ignition/src/Recorders/LogRecorder/LogMessage.php
vendored
Normal file
55
vendor/spatie/laravel-ignition/src/Recorders/LogRecorder/LogMessage.php
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\LogRecorder;
|
||||
|
||||
use Illuminate\Log\Events\MessageLogged;
|
||||
|
||||
class LogMessage
|
||||
{
|
||||
protected ?string $message;
|
||||
|
||||
protected string $level;
|
||||
|
||||
/** @var array<string, string> */
|
||||
protected array $context = [];
|
||||
|
||||
protected ?float $microtime;
|
||||
|
||||
/**
|
||||
* @param string|null $message
|
||||
* @param string $level
|
||||
* @param array<string, string> $context
|
||||
* @param float|null $microtime
|
||||
*/
|
||||
public function __construct(
|
||||
?string $message,
|
||||
string $level,
|
||||
array $context = [],
|
||||
?float $microtime = null
|
||||
) {
|
||||
$this->message = $message;
|
||||
$this->level = $level;
|
||||
$this->context = $context;
|
||||
$this->microtime = $microtime ?? microtime(true);
|
||||
}
|
||||
|
||||
public static function fromMessageLoggedEvent(MessageLogged $event): self
|
||||
{
|
||||
return new self(
|
||||
$event->message,
|
||||
$event->level,
|
||||
$event->context
|
||||
);
|
||||
}
|
||||
|
||||
/** @return array<string, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'message' => $this->message,
|
||||
'level' => $this->level,
|
||||
'context' => $this->context,
|
||||
'microtime' => $this->microtime,
|
||||
];
|
||||
}
|
||||
}
|
||||
93
vendor/spatie/laravel-ignition/src/Recorders/LogRecorder/LogRecorder.php
vendored
Normal file
93
vendor/spatie/laravel-ignition/src/Recorders/LogRecorder/LogRecorder.php
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\LogRecorder;
|
||||
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Log\Events\MessageLogged;
|
||||
use Throwable;
|
||||
|
||||
class LogRecorder
|
||||
{
|
||||
/** @var \Spatie\LaravelIgnition\Recorders\LogRecorder\LogMessage[] */
|
||||
protected array $logMessages = [];
|
||||
|
||||
protected Application $app;
|
||||
|
||||
protected ?int $maxLogs;
|
||||
|
||||
public function __construct(Application $app, ?int $maxLogs = null)
|
||||
{
|
||||
$this->app = $app;
|
||||
|
||||
$this->maxLogs = $maxLogs;
|
||||
}
|
||||
|
||||
public function start(): self
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$this->app['events']->listen(MessageLogged::class, [$this, 'record']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function record(MessageLogged $event): void
|
||||
{
|
||||
if ($this->shouldIgnore($event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logMessages[] = LogMessage::fromMessageLoggedEvent($event);
|
||||
|
||||
if (is_int($this->maxLogs)) {
|
||||
$this->logMessages = array_slice($this->logMessages, -$this->maxLogs);
|
||||
}
|
||||
}
|
||||
|
||||
/** @return array<array<int,string>> */
|
||||
public function getLogMessages(): array
|
||||
{
|
||||
return $this->toArray();
|
||||
}
|
||||
|
||||
/** @return array<int, mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
$logMessages = [];
|
||||
|
||||
foreach ($this->logMessages as $log) {
|
||||
$logMessages[] = $log->toArray();
|
||||
}
|
||||
|
||||
return $logMessages;
|
||||
}
|
||||
|
||||
protected function shouldIgnore(mixed $event): bool
|
||||
{
|
||||
if (! isset($event->context['exception'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $event->context['exception'] instanceof Throwable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->logMessages = [];
|
||||
}
|
||||
|
||||
public function getMaxLogs(): ?int
|
||||
{
|
||||
return $this->maxLogs;
|
||||
}
|
||||
|
||||
public function setMaxLogs(?int $maxLogs): self
|
||||
{
|
||||
$this->maxLogs = $maxLogs;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
65
vendor/spatie/laravel-ignition/src/Recorders/QueryRecorder/Query.php
vendored
Normal file
65
vendor/spatie/laravel-ignition/src/Recorders/QueryRecorder/Query.php
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\QueryRecorder;
|
||||
|
||||
use Illuminate\Database\Events\QueryExecuted;
|
||||
|
||||
class Query
|
||||
{
|
||||
protected string $sql;
|
||||
|
||||
protected float $time;
|
||||
|
||||
protected string $connectionName;
|
||||
|
||||
/** @var array<string, string>|null */
|
||||
protected ?array $bindings;
|
||||
|
||||
protected float $microtime;
|
||||
|
||||
public static function fromQueryExecutedEvent(QueryExecuted $queryExecuted, bool $reportBindings = false): self
|
||||
{
|
||||
return new self(
|
||||
$queryExecuted->sql,
|
||||
$queryExecuted->time,
|
||||
/** @phpstan-ignore-next-line */
|
||||
$queryExecuted->connectionName ?? '',
|
||||
$reportBindings ? $queryExecuted->bindings : null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param float $time
|
||||
* @param string $connectionName
|
||||
* @param array<string, string>|null $bindings
|
||||
* @param float|null $microtime
|
||||
*/
|
||||
protected function __construct(
|
||||
string $sql,
|
||||
float $time,
|
||||
string $connectionName,
|
||||
?array $bindings = null,
|
||||
?float $microtime = null
|
||||
) {
|
||||
$this->sql = $sql;
|
||||
$this->time = $time;
|
||||
$this->connectionName = $connectionName;
|
||||
$this->bindings = $bindings;
|
||||
$this->microtime = $microtime ?? microtime(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'sql' => $this->sql,
|
||||
'time' => $this->time,
|
||||
'connection_name' => $this->connectionName,
|
||||
'bindings' => $this->bindings,
|
||||
'microtime' => $this->microtime,
|
||||
];
|
||||
}
|
||||
}
|
||||
88
vendor/spatie/laravel-ignition/src/Recorders/QueryRecorder/QueryRecorder.php
vendored
Normal file
88
vendor/spatie/laravel-ignition/src/Recorders/QueryRecorder/QueryRecorder.php
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Recorders\QueryRecorder;
|
||||
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Database\Events\QueryExecuted;
|
||||
|
||||
class QueryRecorder
|
||||
{
|
||||
/** @var \Spatie\LaravelIgnition\Recorders\QueryRecorder\Query[] */
|
||||
protected array $queries = [];
|
||||
|
||||
protected Application $app;
|
||||
|
||||
protected bool $reportBindings = true;
|
||||
|
||||
protected ?int $maxQueries;
|
||||
|
||||
public function __construct(
|
||||
Application $app,
|
||||
bool $reportBindings = true,
|
||||
?int $maxQueries = 200
|
||||
) {
|
||||
$this->app = $app;
|
||||
$this->reportBindings = $reportBindings;
|
||||
$this->maxQueries = $maxQueries;
|
||||
}
|
||||
|
||||
public function start(): self
|
||||
{
|
||||
/** @phpstan-ignore-next-line */
|
||||
$this->app['events']->listen(QueryExecuted::class, [$this, 'record']);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function record(QueryExecuted $queryExecuted): void
|
||||
{
|
||||
$this->queries[] = Query::fromQueryExecutedEvent($queryExecuted, $this->reportBindings);
|
||||
|
||||
if (is_int($this->maxQueries)) {
|
||||
$this->queries = array_slice($this->queries, -$this->maxQueries);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
public function getQueries(): array
|
||||
{
|
||||
$queries = [];
|
||||
|
||||
foreach ($this->queries as $query) {
|
||||
$queries[] = $query->toArray();
|
||||
}
|
||||
|
||||
return $queries;
|
||||
}
|
||||
|
||||
public function reset(): void
|
||||
{
|
||||
$this->queries = [];
|
||||
}
|
||||
|
||||
public function getReportBindings(): bool
|
||||
{
|
||||
return $this->reportBindings;
|
||||
}
|
||||
|
||||
public function setReportBindings(bool $reportBindings): self
|
||||
{
|
||||
$this->reportBindings = $reportBindings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMaxQueries(): ?int
|
||||
{
|
||||
return $this->maxQueries;
|
||||
}
|
||||
|
||||
public function setMaxQueries(?int $maxQueries): self
|
||||
{
|
||||
$this->maxQueries = $maxQueries;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
41
vendor/spatie/laravel-ignition/src/Renderers/ErrorPageRenderer.php
vendored
Normal file
41
vendor/spatie/laravel-ignition/src/Renderers/ErrorPageRenderer.php
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Renderers;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\SolutionProviderRepository;
|
||||
use Spatie\FlareClient\Flare;
|
||||
use Spatie\Ignition\Config\IgnitionConfig;
|
||||
use Spatie\Ignition\Ignition;
|
||||
use Spatie\LaravelIgnition\ContextProviders\LaravelContextProviderDetector;
|
||||
use Spatie\LaravelIgnition\Solutions\SolutionTransformers\LaravelSolutionTransformer;
|
||||
use Spatie\LaravelIgnition\Support\LaravelDocumentationLinkFinder;
|
||||
use Throwable;
|
||||
|
||||
class ErrorPageRenderer
|
||||
{
|
||||
public function render(Throwable $throwable): void
|
||||
{
|
||||
$viteJsAutoRefresh = '';
|
||||
|
||||
if (class_exists('Illuminate\Foundation\Vite')) {
|
||||
$vite = app(\Illuminate\Foundation\Vite::class);
|
||||
|
||||
if (is_file($vite->hotFile())) {
|
||||
$viteJsAutoRefresh = $vite->__invoke([]);
|
||||
}
|
||||
}
|
||||
|
||||
app(Ignition::class)
|
||||
->resolveDocumentationLink(
|
||||
fn (Throwable $throwable) => (new LaravelDocumentationLinkFinder())->findLinkForThrowable($throwable)
|
||||
)
|
||||
->setFlare(app(Flare::class))
|
||||
->setConfig(app(IgnitionConfig::class))
|
||||
->setSolutionProviderRepository(app(SolutionProviderRepository::class))
|
||||
->setContextProviderDetector(new LaravelContextProviderDetector())
|
||||
->setSolutionTransformerClass(LaravelSolutionTransformer::class)
|
||||
->applicationPath(base_path())
|
||||
->addCustomHtmlToHead($viteJsAutoRefresh)
|
||||
->renderException($throwable);
|
||||
}
|
||||
}
|
||||
24
vendor/spatie/laravel-ignition/src/Renderers/IgnitionExceptionRenderer.php
vendored
Normal file
24
vendor/spatie/laravel-ignition/src/Renderers/IgnitionExceptionRenderer.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Renderers;
|
||||
|
||||
use Illuminate\Contracts\Foundation\ExceptionRenderer;
|
||||
|
||||
class IgnitionExceptionRenderer implements ExceptionRenderer
|
||||
{
|
||||
protected ErrorPageRenderer $errorPageHandler;
|
||||
|
||||
public function __construct(ErrorPageRenderer $errorPageHandler)
|
||||
{
|
||||
$this->errorPageHandler = $errorPageHandler;
|
||||
}
|
||||
|
||||
public function render($throwable)
|
||||
{
|
||||
ob_start();
|
||||
|
||||
$this->errorPageHandler->render($throwable);
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
61
vendor/spatie/laravel-ignition/src/Solutions/SolutionTransformers/LaravelSolutionTransformer.php
vendored
Normal file
61
vendor/spatie/laravel-ignition/src/Solutions/SolutionTransformers/LaravelSolutionTransformer.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Solutions\SolutionTransformers;
|
||||
|
||||
use Spatie\ErrorSolutions\Contracts\RunnableSolution;
|
||||
use Spatie\ErrorSolutions\Solutions\SolutionTransformer;
|
||||
use Spatie\LaravelIgnition\Http\Controllers\ExecuteSolutionController;
|
||||
use Throwable;
|
||||
|
||||
class LaravelSolutionTransformer extends SolutionTransformer
|
||||
{
|
||||
/** @return array<string|mixed> */
|
||||
public function toArray(): array
|
||||
{
|
||||
$baseProperties = parent::toArray();
|
||||
|
||||
if (! $this->isRunnable()) {
|
||||
return $baseProperties;
|
||||
}
|
||||
|
||||
/** @var RunnableSolution $solution Type shenanigans */
|
||||
$solution = $this->solution;
|
||||
|
||||
$runnableProperties = [
|
||||
'is_runnable' => true,
|
||||
'action_description' => $solution->getSolutionActionDescription(),
|
||||
'run_button_text' => $solution->getRunButtonText(),
|
||||
'execute_endpoint' => $this->executeEndpoint(),
|
||||
'run_parameters' => $solution->getRunParameters(),
|
||||
];
|
||||
|
||||
return array_merge($baseProperties, $runnableProperties);
|
||||
}
|
||||
|
||||
protected function isRunnable(): bool
|
||||
{
|
||||
if (! $this->solution instanceof RunnableSolution) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $this->executeEndpoint()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function executeEndpoint(): ?string
|
||||
{
|
||||
try {
|
||||
// The action class needs to be prefixed with a `\` to Laravel from trying
|
||||
// to add its own global namespace from RouteServiceProvider::$namespace.
|
||||
|
||||
return action('\\'.ExecuteSolutionController::class);
|
||||
} catch (Throwable $exception) {
|
||||
report($exception);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
107
vendor/spatie/laravel-ignition/src/Support/FlareLogHandler.php
vendored
Normal file
107
vendor/spatie/laravel-ignition/src/Support/FlareLogHandler.php
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Support;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Monolog\Handler\AbstractProcessingHandler;
|
||||
use Monolog\Level;
|
||||
use Monolog\Logger;
|
||||
use Monolog\LogRecord;
|
||||
use Spatie\FlareClient\Flare;
|
||||
use Spatie\FlareClient\Report;
|
||||
use Throwable;
|
||||
|
||||
class FlareLogHandler extends AbstractProcessingHandler
|
||||
{
|
||||
protected Flare $flare;
|
||||
|
||||
protected SentReports $sentReports;
|
||||
|
||||
protected int $minimumReportLogLevel;
|
||||
|
||||
public function __construct(Flare $flare, SentReports $sentReports, $level = Level::Debug, $bubble = true)
|
||||
{
|
||||
$this->flare = $flare;
|
||||
|
||||
$this->minimumReportLogLevel = Level::Error->value;
|
||||
|
||||
$this->sentReports = $sentReports;
|
||||
|
||||
parent::__construct($level, $bubble);
|
||||
}
|
||||
|
||||
public function setMinimumReportLogLevel(int $level): void
|
||||
{
|
||||
if (! in_array($level, Level::VALUES)) {
|
||||
throw new InvalidArgumentException('The given minimum log level is not supported.');
|
||||
}
|
||||
|
||||
$this->minimumReportLogLevel = $level;
|
||||
}
|
||||
|
||||
protected function write(LogRecord $record): void
|
||||
{
|
||||
if (! $this->shouldReport($record->toArray())) {
|
||||
return;
|
||||
}
|
||||
if ($this->hasException($record->toArray())) {
|
||||
$report = $this->flare->report($record['context']['exception']);
|
||||
|
||||
if ($report) {
|
||||
$this->sentReports->add($report);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (config('flare.send_logs_as_events')) {
|
||||
if ($this->hasValidLogLevel($record->toArray())) {
|
||||
$this->flare->reportMessage(
|
||||
$record['message'],
|
||||
'Log ' . Logger::toMonologLevel($record['level'])->getName(),
|
||||
function (Report $flareReport) use ($record) {
|
||||
foreach ($record['context'] as $key => $value) {
|
||||
$flareReport->context($key, $value);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function shouldReport(array $report): bool
|
||||
{
|
||||
if (! config('flare.key')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->hasException($report) || $this->hasValidLogLevel($report);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasException(array $report): bool
|
||||
{
|
||||
$context = $report['context'];
|
||||
|
||||
return isset($context['exception']) && $context['exception'] instanceof Throwable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $report
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasValidLogLevel(array $report): bool
|
||||
{
|
||||
return $report['level'] >= $this->minimumReportLogLevel;
|
||||
}
|
||||
}
|
||||
61
vendor/spatie/laravel-ignition/src/Support/LaravelDocumentationLinkFinder.php
vendored
Normal file
61
vendor/spatie/laravel-ignition/src/Support/LaravelDocumentationLinkFinder.php
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Support;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\LaravelIgnition\Exceptions\ViewException;
|
||||
use Throwable;
|
||||
|
||||
class LaravelDocumentationLinkFinder
|
||||
{
|
||||
public function findLinkForThrowable(Throwable $throwable): ?string
|
||||
{
|
||||
if ($throwable instanceof ViewException) {
|
||||
$throwable = $throwable->getPrevious();
|
||||
}
|
||||
|
||||
$majorVersion = LaravelVersion::major();
|
||||
|
||||
if (str_contains($throwable->getMessage(), Collection::class)) {
|
||||
return "https://laravel.com/docs/{$majorVersion}.x/collections#available-methods";
|
||||
}
|
||||
|
||||
$type = $this->getType($throwable);
|
||||
|
||||
if (! $type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return match ($type) {
|
||||
'Auth' => "https://laravel.com/docs/{$majorVersion}.x/authentication",
|
||||
'Broadcasting' => "https://laravel.com/docs/{$majorVersion}.x/broadcasting",
|
||||
'Container' => "https://laravel.com/docs/{$majorVersion}.x/container",
|
||||
'Database' => "https://laravel.com/docs/{$majorVersion}.x/eloquent",
|
||||
'Pagination' => "https://laravel.com/docs/{$majorVersion}.x/pagination",
|
||||
'Queue' => "https://laravel.com/docs/{$majorVersion}.x/queues",
|
||||
'Routing' => "https://laravel.com/docs/{$majorVersion}.x/routing",
|
||||
'Session' => "https://laravel.com/docs/{$majorVersion}.x/session",
|
||||
'Validation' => "https://laravel.com/docs/{$majorVersion}.x/validation",
|
||||
'View' => "https://laravel.com/docs/{$majorVersion}.x/views",
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
|
||||
protected function getType(?Throwable $throwable): ?string
|
||||
{
|
||||
if (! $throwable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (str_contains($throwable::class, 'Illuminate')) {
|
||||
return Str::between($throwable::class, 'Illuminate\\', '\\');
|
||||
}
|
||||
|
||||
if (str_contains($throwable->getMessage(), 'Illuminate')) {
|
||||
return explode('\\', Str::between($throwable->getMessage(), 'Illuminate\\', '\\'))[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
11
vendor/spatie/laravel-ignition/src/Support/LaravelVersion.php
vendored
Normal file
11
vendor/spatie/laravel-ignition/src/Support/LaravelVersion.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Support;
|
||||
|
||||
class LaravelVersion
|
||||
{
|
||||
public static function major(): string
|
||||
{
|
||||
return explode('.', app()->version())[0];
|
||||
}
|
||||
}
|
||||
37
vendor/spatie/laravel-ignition/src/Support/RunnableSolutionsGuard.php
vendored
Normal file
37
vendor/spatie/laravel-ignition/src/Support/RunnableSolutionsGuard.php
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Support;
|
||||
|
||||
class RunnableSolutionsGuard
|
||||
{
|
||||
/**
|
||||
* Check if runnable solutions are allowed based on the current
|
||||
* environment and config.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function check(): bool
|
||||
{
|
||||
if (! config('app.debug')) {
|
||||
// Never run solutions in when debug mode is not enabled.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config('ignition.enable_runnable_solutions') !== null) {
|
||||
// Allow enabling or disabling runnable solutions regardless of environment
|
||||
// if the IGNITION_ENABLE_RUNNABLE_SOLUTIONS env var is explicitly set.
|
||||
|
||||
return config('ignition.enable_runnable_solutions');
|
||||
}
|
||||
|
||||
if (! app()->environment('local') && ! app()->environment('development')) {
|
||||
// Never run solutions on non-local environments. This avoids exposing
|
||||
// applications that are somehow APP_ENV=production with APP_DEBUG=true.
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return config('app.debug');
|
||||
}
|
||||
}
|
||||
54
vendor/spatie/laravel-ignition/src/Support/SentReports.php
vendored
Normal file
54
vendor/spatie/laravel-ignition/src/Support/SentReports.php
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Support;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Spatie\FlareClient\Report;
|
||||
|
||||
class SentReports
|
||||
{
|
||||
/** @var array<int, Report> */
|
||||
protected array $reports = [];
|
||||
|
||||
public function add(Report $report): self
|
||||
{
|
||||
$this->reports[] = $report;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return array<int, Report> */
|
||||
public function all(): array
|
||||
{
|
||||
return $this->reports;
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function uuids(): array
|
||||
{
|
||||
return array_map(fn (Report $report) => $report->trackingUuid(), $this->reports);
|
||||
}
|
||||
|
||||
/** @return array<int, string> */
|
||||
public function urls(): array
|
||||
{
|
||||
return array_map(function (string $trackingUuid) {
|
||||
return "https://flareapp.io/tracked-occurrence/{$trackingUuid}";
|
||||
}, $this->uuids());
|
||||
}
|
||||
|
||||
public function latestUuid(): ?string
|
||||
{
|
||||
return Arr::last($this->reports)?->trackingUuid();
|
||||
}
|
||||
|
||||
public function latestUrl(): ?string
|
||||
{
|
||||
return Arr::last($this->urls());
|
||||
}
|
||||
|
||||
public function clear(): void
|
||||
{
|
||||
$this->reports = [];
|
||||
}
|
||||
}
|
||||
145
vendor/spatie/laravel-ignition/src/Views/BladeSourceMapCompiler.php
vendored
Normal file
145
vendor/spatie/laravel-ignition/src/Views/BladeSourceMapCompiler.php
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Views;
|
||||
|
||||
use Illuminate\View\Compilers\BladeCompiler;
|
||||
use Throwable;
|
||||
|
||||
class BladeSourceMapCompiler
|
||||
{
|
||||
protected BladeCompiler $bladeCompiler;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->bladeCompiler = app('blade.compiler');
|
||||
}
|
||||
|
||||
public function detectLineNumber(string $filename, int $compiledLineNumber): int
|
||||
{
|
||||
$map = $this->compileSourcemap((string)file_get_contents($filename));
|
||||
|
||||
return $this->findClosestLineNumberMapping($map, $compiledLineNumber);
|
||||
}
|
||||
|
||||
protected function compileSourcemap(string $value): string
|
||||
{
|
||||
try {
|
||||
$value = $this->addEchoLineNumbers($value);
|
||||
|
||||
$value = $this->addStatementLineNumbers($value);
|
||||
|
||||
$value = $this->addBladeComponentLineNumbers($value);
|
||||
|
||||
$value = $this->bladeCompiler->compileString($value);
|
||||
|
||||
return $this->trimEmptyLines($value);
|
||||
} catch (Throwable $e) {
|
||||
report($e);
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
protected function addEchoLineNumbers(string $value): string
|
||||
{
|
||||
$echoPairs = [['{{', '}}'], ['{{{', '}}}'], ['{!!', '!!}']];
|
||||
|
||||
foreach ($echoPairs as $pair) {
|
||||
// Matches {{ $value }}, {!! $value !!} and {{{ $value }}} depending on $pair
|
||||
$pattern = sprintf('/(@)?%s\s*(.+?)\s*%s(\r?\n)?/s', $pair[0], $pair[1]);
|
||||
|
||||
if (preg_match_all($pattern, $value, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
foreach (array_reverse($matches[0]) as $match) {
|
||||
$position = mb_strlen(substr($value, 0, $match[1]));
|
||||
|
||||
$value = $this->insertLineNumberAtPosition($position, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function addStatementLineNumbers(string $value): string
|
||||
{
|
||||
// Matches @bladeStatements() like @if, @component(...), @etc;
|
||||
$shouldInsertLineNumbers = preg_match_all(
|
||||
'/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x',
|
||||
$value,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
if ($shouldInsertLineNumbers) {
|
||||
foreach (array_reverse($matches[0]) as $match) {
|
||||
$position = mb_strlen(substr($value, 0, $match[1]));
|
||||
|
||||
$value = $this->insertLineNumberAtPosition($position, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function addBladeComponentLineNumbers(string $value): string
|
||||
{
|
||||
// Matches the start of `<x-blade-component`
|
||||
$shouldInsertLineNumbers = preg_match_all(
|
||||
'/<\s*x[-:]([\w\-:.]*)/mx',
|
||||
$value,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE
|
||||
);
|
||||
|
||||
if ($shouldInsertLineNumbers) {
|
||||
foreach (array_reverse($matches[0]) as $match) {
|
||||
$position = mb_strlen(substr($value, 0, $match[1]));
|
||||
|
||||
$value = $this->insertLineNumberAtPosition($position, $value);
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function insertLineNumberAtPosition(int $position, string $value): string
|
||||
{
|
||||
$before = mb_substr($value, 0, $position);
|
||||
$lineNumber = count(explode("\n", $before));
|
||||
|
||||
return mb_substr($value, 0, $position)."|---LINE:{$lineNumber}---|".mb_substr($value, $position);
|
||||
}
|
||||
|
||||
protected function trimEmptyLines(string $value): string
|
||||
{
|
||||
$value = preg_replace('/^\|---LINE:([0-9]+)---\|$/m', '', $value);
|
||||
|
||||
return ltrim((string)$value, PHP_EOL);
|
||||
}
|
||||
|
||||
protected function findClosestLineNumberMapping(string $map, int $compiledLineNumber): int
|
||||
{
|
||||
$map = explode("\n", $map);
|
||||
|
||||
// Max 20 lines between compiled and source line number.
|
||||
// Blade components can span multiple lines and the compiled line number is often
|
||||
// a couple lines below the source-mapped `<x-component>` code.
|
||||
$maxDistance = 20;
|
||||
|
||||
$pattern = '/\|---LINE:(?P<line>[0-9]+)---\|/m';
|
||||
$lineNumberToCheck = $compiledLineNumber - 1;
|
||||
|
||||
while (true) {
|
||||
if ($lineNumberToCheck < $compiledLineNumber - $maxDistance) {
|
||||
// Something wrong. Return the $compiledLineNumber (unless it's out of range)
|
||||
return min($compiledLineNumber, count($map));
|
||||
}
|
||||
|
||||
if (preg_match($pattern, $map[$lineNumberToCheck] ?? '', $matches)) {
|
||||
return (int)$matches['line'];
|
||||
}
|
||||
|
||||
$lineNumberToCheck--;
|
||||
}
|
||||
}
|
||||
}
|
||||
190
vendor/spatie/laravel-ignition/src/Views/ViewExceptionMapper.php
vendored
Normal file
190
vendor/spatie/laravel-ignition/src/Views/ViewExceptionMapper.php
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\LaravelIgnition\Views;
|
||||
|
||||
use Illuminate\Contracts\View\Engine;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\View\Engines\PhpEngine;
|
||||
use Illuminate\View\ViewException;
|
||||
use ReflectionClass;
|
||||
use ReflectionProperty;
|
||||
use Spatie\ErrorSolutions\Contracts\ProvidesSolution;
|
||||
use Spatie\LaravelIgnition\Exceptions\ViewException as IgnitionViewException;
|
||||
use Spatie\LaravelIgnition\Exceptions\ViewExceptionWithSolution;
|
||||
use Throwable;
|
||||
|
||||
class ViewExceptionMapper
|
||||
{
|
||||
protected Engine $compilerEngine;
|
||||
|
||||
protected BladeSourceMapCompiler $bladeSourceMapCompiler;
|
||||
|
||||
protected array $knownPaths;
|
||||
|
||||
public function __construct(BladeSourceMapCompiler $bladeSourceMapCompiler)
|
||||
{
|
||||
$resolver = app('view.engine.resolver');
|
||||
|
||||
$this->compilerEngine = $resolver->resolve('blade');
|
||||
|
||||
$this->bladeSourceMapCompiler = $bladeSourceMapCompiler;
|
||||
}
|
||||
|
||||
public function map(ViewException $viewException): IgnitionViewException
|
||||
{
|
||||
$baseException = $this->getRealException($viewException);
|
||||
|
||||
if ($baseException instanceof IgnitionViewException) {
|
||||
return $baseException;
|
||||
}
|
||||
|
||||
preg_match('/\(View: (?P<path>.*?)\)/', $viewException->getMessage(), $matches);
|
||||
|
||||
$compiledViewPath = $matches['path'];
|
||||
|
||||
$exception = $this->createException($baseException);
|
||||
|
||||
if ($baseException instanceof ProvidesSolution) {
|
||||
/** @var ViewExceptionWithSolution $exception */
|
||||
$exception->setSolution($baseException->getSolution());
|
||||
}
|
||||
|
||||
$this->modifyViewsInTrace($exception);
|
||||
|
||||
$exception->setView($compiledViewPath);
|
||||
$exception->setViewData($this->getViewData($exception));
|
||||
|
||||
return $exception;
|
||||
}
|
||||
|
||||
protected function createException(Throwable $baseException): IgnitionViewException
|
||||
{
|
||||
$viewExceptionClass = $baseException instanceof ProvidesSolution
|
||||
? ViewExceptionWithSolution::class
|
||||
: IgnitionViewException::class;
|
||||
|
||||
$viewFile = $this->findCompiledView($baseException->getFile());
|
||||
$file = $viewFile ?? $baseException->getFile();
|
||||
$line = $viewFile ? $this->getBladeLineNumber($file, $baseException->getLine()) : $baseException->getLine();
|
||||
|
||||
return new $viewExceptionClass(
|
||||
$baseException->getMessage(),
|
||||
0,
|
||||
1,
|
||||
$file,
|
||||
$line,
|
||||
$baseException
|
||||
);
|
||||
}
|
||||
|
||||
protected function modifyViewsInTrace(IgnitionViewException $exception): void
|
||||
{
|
||||
$viewIndex = null;
|
||||
|
||||
$trace = Collection::make($exception->getPrevious()->getTrace())
|
||||
->map(function ($trace, $index) use (&$viewIndex) {
|
||||
if ($originalPath = $this->findCompiledView(Arr::get($trace, 'file', ''))) {
|
||||
|
||||
$trace['file'] = $originalPath;
|
||||
$trace['line'] = $this->getBladeLineNumber($trace['file'], $trace['line']);
|
||||
|
||||
if ($viewIndex === null) {
|
||||
$viewIndex = $index;
|
||||
}
|
||||
}
|
||||
|
||||
return $trace;
|
||||
})
|
||||
->when(
|
||||
$viewIndex !== null && str_ends_with($exception->getFile(), '.blade.php'),
|
||||
fn (Collection $trace) => $trace->slice($viewIndex + 1) // Remove all traces before the view
|
||||
)
|
||||
->toArray();
|
||||
|
||||
$traceProperty = new ReflectionProperty('Exception', 'trace');
|
||||
$traceProperty->setAccessible(true);
|
||||
$traceProperty->setValue($exception, $trace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Look at the previous exceptions to find the original exception.
|
||||
* This is usually the first Exception that is not a ViewException.
|
||||
*/
|
||||
protected function getRealException(Throwable $exception): Throwable
|
||||
{
|
||||
$rootException = $exception->getPrevious() ?? $exception;
|
||||
|
||||
while ($rootException instanceof ViewException && $rootException->getPrevious()) {
|
||||
$rootException = $rootException->getPrevious();
|
||||
}
|
||||
|
||||
return $rootException;
|
||||
}
|
||||
|
||||
protected function findCompiledView(string $compiledPath): ?string
|
||||
{
|
||||
$this->knownPaths ??= $this->getKnownPaths();
|
||||
|
||||
return $this->knownPaths[$compiledPath] ?? null;
|
||||
}
|
||||
|
||||
protected function getKnownPaths(): array
|
||||
{
|
||||
$compilerEngineReflection = new ReflectionClass($this->compilerEngine);
|
||||
|
||||
if (! $compilerEngineReflection->hasProperty('lastCompiled') && $compilerEngineReflection->hasProperty('engine')) {
|
||||
$compilerEngine = $compilerEngineReflection->getProperty('engine');
|
||||
$compilerEngine->setAccessible(true);
|
||||
$compilerEngine = $compilerEngine->getValue($this->compilerEngine);
|
||||
$lastCompiled = new ReflectionProperty($compilerEngine, 'lastCompiled');
|
||||
$lastCompiled->setAccessible(true);
|
||||
$lastCompiled = $lastCompiled->getValue($compilerEngine);
|
||||
} else {
|
||||
$lastCompiled = $compilerEngineReflection->getProperty('lastCompiled');
|
||||
$lastCompiled->setAccessible(true);
|
||||
$lastCompiled = $lastCompiled->getValue($this->compilerEngine);
|
||||
}
|
||||
|
||||
$knownPaths = [];
|
||||
foreach ($lastCompiled as $lastCompiledPath) {
|
||||
$compiledPath = $this->compilerEngine->getCompiler()->getCompiledPath($lastCompiledPath);
|
||||
|
||||
$knownPaths[realpath($compiledPath ?? $lastCompiledPath)] = realpath($lastCompiledPath);
|
||||
}
|
||||
|
||||
return $knownPaths;
|
||||
}
|
||||
|
||||
protected function getBladeLineNumber(string $view, int $compiledLineNumber): int
|
||||
{
|
||||
return $this->bladeSourceMapCompiler->detectLineNumber($view, $compiledLineNumber);
|
||||
}
|
||||
|
||||
protected function getViewData(Throwable $exception): array
|
||||
{
|
||||
foreach ($exception->getTrace() as $frame) {
|
||||
if (Arr::get($frame, 'class') === PhpEngine::class) {
|
||||
$data = Arr::get($frame, 'args.1', []);
|
||||
|
||||
return $this->filterViewData($data);
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function filterViewData(array $data): array
|
||||
{
|
||||
// By default, Laravel views get two data keys:
|
||||
// __env and app. We try to filter them out.
|
||||
return array_filter($data, function ($value, $key) {
|
||||
if ($key === 'app') {
|
||||
return ! $value instanceof Application;
|
||||
}
|
||||
|
||||
return $key !== '__env';
|
||||
}, ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
}
|
||||
24
vendor/spatie/laravel-ignition/src/helpers.php
vendored
Normal file
24
vendor/spatie/laravel-ignition/src/helpers.php
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelIgnition\Renderers\ErrorPageRenderer;
|
||||
|
||||
if (! function_exists('ddd')) {
|
||||
function ddd()
|
||||
{
|
||||
$args = func_get_args();
|
||||
|
||||
if (count($args) === 0) {
|
||||
throw new Exception('You should pass at least 1 argument to `ddd`');
|
||||
}
|
||||
|
||||
call_user_func_array('dump', $args);
|
||||
|
||||
$renderer = app()->make(ErrorPageRenderer::class);
|
||||
|
||||
$exception = new Exception('Dump, Die, Debug');
|
||||
|
||||
$renderer->render($exception);
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
20
vendor/spatie/laravel-ignition/src/ignition-routes.php
vendored
Normal file
20
vendor/spatie/laravel-ignition/src/ignition-routes.php
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Spatie\LaravelIgnition\Http\Controllers\ExecuteSolutionController;
|
||||
use Spatie\LaravelIgnition\Http\Controllers\HealthCheckController;
|
||||
use Spatie\LaravelIgnition\Http\Controllers\UpdateConfigController;
|
||||
use Spatie\LaravelIgnition\Http\Middleware\RunnableSolutionsEnabled;
|
||||
|
||||
Route::group([
|
||||
'as' => 'ignition.',
|
||||
'prefix' => config('ignition.housekeeping_endpoint_prefix'),
|
||||
'middleware' => [RunnableSolutionsEnabled::class],
|
||||
], function () {
|
||||
Route::get('health-check', HealthCheckController::class)->name('healthCheck');
|
||||
|
||||
Route::post('execute-solution', ExecuteSolutionController::class)
|
||||
->name('executeSolution');
|
||||
|
||||
Route::post('update-config', UpdateConfigController::class)->name('updateConfig');
|
||||
});
|
||||
Reference in New Issue
Block a user