first working version
This commit is contained in:
commit
a7d3dc8a57
20 changed files with 7874 additions and 0 deletions
18
.editorconfig
Normal file
18
.editorconfig
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.json]
|
||||
indent_size = 4
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
workspace.code-workspace
|
||||
vendor
|
||||
2
.styleci.yml
Normal file
2
.styleci.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
php:
|
||||
preset: laravel
|
||||
22
.vscode/launch.json
vendored
Normal file
22
.vscode/launch.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
// Utilisez IntelliSense pour en savoir plus sur les attributs possibles.
|
||||
// Pointez pour afficher la description des attributs existants.
|
||||
// Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Listen for XDebug",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"port": 9000
|
||||
},
|
||||
{
|
||||
"name": "Launch currently open script",
|
||||
"type": "php",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"cwd": "${fileDirname}",
|
||||
"port": 9000
|
||||
}
|
||||
]
|
||||
}
|
||||
6
changelog.md
Normal file
6
changelog.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to `ExceptionHandler` will be documented in this file.
|
||||
|
||||
## Version 0.0.1
|
||||
|
||||
45
composer.json
Normal file
45
composer.json
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
{
|
||||
"name": "kwaadpepper/exception-handler",
|
||||
"description": "Send emails when exceptions occurs",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jérémy Munsch",
|
||||
"email": "github@jeremydev.ovh",
|
||||
"homepage": "https://jeremydev.ovh"
|
||||
}
|
||||
],
|
||||
"homepage": "https://github.com/kwaadpepper/exception-handler",
|
||||
"keywords": [
|
||||
"Laravel",
|
||||
"Exception",
|
||||
"Email",
|
||||
"Policies"
|
||||
],
|
||||
"require": {
|
||||
"illuminate/support": "~7|~8",
|
||||
"laravel/framework": "~7|~8"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~9.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"orchestra/testbench": "^6.13"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Kwaadpepper\\ExceptionHandler\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Kwaadpepper\\ExceptionHandler\\Tests\\": "tests"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Kwaadpepper\\ExceptionHandler\\ExceptionHandlerServiceProvider"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
7242
composer.lock
generated
Normal file
7242
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
15
config/exception-handler.php
Normal file
15
config/exception-handler.php
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
/**
|
||||
* Send mail when app debug is turn off
|
||||
* so you can be warned if an unhandled exception occurs
|
||||
*/
|
||||
'enableMaiLog' => !config('app.debug'),
|
||||
|
||||
/**
|
||||
* Put a developper secured mailbox in here
|
||||
* so you can receive email if things go mad
|
||||
*/
|
||||
'contactsList' => []
|
||||
];
|
||||
21
license.md
Normal file
21
license.md
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License (!! includes CC BY-NC 3.0 parts please read Readme.md)
|
||||
|
||||
Copyright (c) 2021 Jérémy Munsch
|
||||
|
||||
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.
|
||||
87
phpcs.xml
Normal file
87
phpcs.xml
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ruleset name="RealWorld" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||
<arg name="colors"/>
|
||||
<arg name="extensions" value="php"/>
|
||||
<file>src/</file>
|
||||
<file>tests/</file>
|
||||
<description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/
|
||||
</description>
|
||||
<rule ref="Generic.CodeAnalysis.EmptyStatement" />
|
||||
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop" />
|
||||
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall" />
|
||||
<rule ref="Generic.CodeAnalysis.JumbledIncrementer" />
|
||||
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement" />
|
||||
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier" />
|
||||
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter" />
|
||||
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod" />
|
||||
<rule ref="Generic.Commenting.Todo" />
|
||||
<rule ref="Generic.Commenting.Fixme" />
|
||||
<rule ref="Generic.ControlStructures.InlineControlStructure" />
|
||||
<rule ref="Generic.Files.ByteOrderMark" />
|
||||
<rule ref="Generic.Files.LineEndings" />
|
||||
<rule ref="Generic.Files.LineLength">
|
||||
<properties>
|
||||
<property name="lineLimit" value="120"/>
|
||||
<property name="absoluteLineLimit" value="0"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Generic.Formatting.DisallowMultipleStatements" />
|
||||
<rule ref="Generic.Formatting.NoSpaceAfterCast" />
|
||||
<rule ref="Generic.Functions.CallTimePassByReference" />
|
||||
<rule ref="Generic.Functions.FunctionCallArgumentSpacing" />
|
||||
<rule ref="Generic.Metrics.CyclomaticComplexity" />
|
||||
<rule ref="Generic.Metrics.NestingLevel" />
|
||||
<rule ref="Generic.NamingConventions.ConstructorName" />
|
||||
<rule ref="Generic.NamingConventions.UpperCaseConstantName" />
|
||||
<rule ref="Generic.NamingConventions.CamelCapsFunctionName" />
|
||||
<rule ref="Generic.PHP.DeprecatedFunctions" />
|
||||
<rule ref="Generic.PHP.DisallowShortOpenTag" />
|
||||
<rule ref="Generic.PHP.ForbiddenFunctions" />
|
||||
<rule ref="Generic.PHP.LowerCaseConstant" />
|
||||
<rule ref="Generic.PHP.NoSilencedErrors" />
|
||||
<rule ref="Generic.Strings.UnnecessaryStringConcat" />
|
||||
<rule ref="Generic.WhiteSpace.DisallowTabIndent" />
|
||||
<rule ref="Generic.WhiteSpace.ScopeIndent" />
|
||||
<rule ref="MySource.PHP.EvalObjectFactory" />
|
||||
<rule ref="MySource.PHP.GetRequestData" />
|
||||
<rule ref="MySource.PHP.AjaxNullComparison" />
|
||||
<rule ref="PEAR.Classes.ClassDeclaration" />
|
||||
<rule ref="PEAR.Commenting.InlineComment" />
|
||||
<rule ref="PSR1.Classes.ClassDeclaration" />
|
||||
<rule ref="PSR1.Files.SideEffects" />
|
||||
<rule ref="Squiz.PHP.CommentedOutCode" />
|
||||
<rule ref="Squiz.PHP.DisallowSizeFunctionsInLoops" />
|
||||
<rule ref="Squiz.PHP.DiscouragedFunctions">
|
||||
<properties>
|
||||
<property name="error" value="true" />
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Squiz.PHP.Eval" />
|
||||
<rule ref="Squiz.PHP.GlobalKeyword" />
|
||||
<rule ref="Squiz.PHP.Heredoc" />
|
||||
<rule ref="Squiz.PHP.InnerFunctions" />
|
||||
<rule ref="Squiz.PHP.LowercasePHPFunctions" />
|
||||
<rule ref="Squiz.PHP.NonExecutableCode" />
|
||||
<rule ref="Squiz.Scope.MemberVarScope" />
|
||||
<rule ref="Squiz.Scope.MethodScope" />
|
||||
<rule ref="Squiz.Scope.StaticThisUsage" />
|
||||
<rule ref="Squiz.WhiteSpace.MemberVarSpacing" />
|
||||
<rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing">
|
||||
<properties>
|
||||
<property name="ignoreNewlines" value="true"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Squiz.WhiteSpace.OperatorSpacing">
|
||||
<properties>
|
||||
<property name="ignoreNewlines" value="true"/>
|
||||
</properties>
|
||||
</rule>
|
||||
<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing" />
|
||||
<rule ref="Squiz.WhiteSpace.SemicolonSpacing" />
|
||||
|
||||
|
||||
<!-- For Laravel migrations -->
|
||||
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
|
||||
<exclude-pattern>*/database/migrations/*</exclude-pattern>
|
||||
</rule>
|
||||
</ruleset>
|
||||
13
phpunit.xml
Normal file
13
phpunit.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" backupStaticAttributes="false" colors="true" verbose="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
|
||||
<coverage>
|
||||
<include>
|
||||
<directory>src/</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
<testsuites>
|
||||
<testsuite name="Package">
|
||||
<directory suffix=".php">./tests/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
||||
52
readme.md
Normal file
52
readme.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Exception Handler
|
||||
|
||||
[![Latest Version on Packagist][ico-version]][link-packagist]
|
||||
[![Total Downloads][ico-downloads]][link-downloads]
|
||||
[![Build Status][ico-travis]][link-travis]
|
||||
[![StyleCI][ico-styleci]][link-styleci]
|
||||
|
||||
Handles exceptions and send email when it does happen
|
||||
|
||||
## Installation
|
||||
|
||||
Via Composer
|
||||
|
||||
``` bash
|
||||
$ composer require kwaadpepper/exception-handler
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1 - Publish config if you want to customize things
|
||||
|
||||
php artisan vendor:publish --provider="Kwaadpepper\ExceptionHandler\ExceptionHandlerServiceProvider"
|
||||
|
||||
## Change log
|
||||
|
||||
Please see the [changelog](changelog.md) for more information on what has changed recently.
|
||||
|
||||
## Testing
|
||||
|
||||
``` bash
|
||||
$ composer test
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
If you discover any security related issues, please email github@jeremydev.ovh instead of using the issue tracker.
|
||||
|
||||
## Credits
|
||||
|
||||
- [Jérémy Munsch][link-author]
|
||||
- [All Contributors][link-contributors]
|
||||
|
||||
## License
|
||||
|
||||
MIT. Please see the [license file](license.md) for more information.
|
||||
|
||||
[ico-version]: https://img.shields.io/packagist/v/kwaadpepper/exception-handler?style=flat-square
|
||||
[ico-downloads]: https://img.shields.io/packagist/dt/kwaadpepper/exception-handler?style=flat-square
|
||||
|
||||
[link-packagist]: https://packagist.org/packages/kwaadpepper/exception-handler
|
||||
[link-downloads]: https://packagist.org/packages/kwaadpepper/exception-handler
|
||||
[link-author]: https://github.com/kwaadpepper
|
||||
10
resources/lang/en.json
Normal file
10
resources/lang/en.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"error_occured_in_app_check_trace": "An error occured on :appName",
|
||||
"check_trace": "Please check logs in order to fix this.",
|
||||
"uri": "uri",
|
||||
"date": "date",
|
||||
"code": "code",
|
||||
"file": "file",
|
||||
"line": "line",
|
||||
"anonymized_stack_trace": "anonymized stack trace"
|
||||
}
|
||||
10
resources/lang/fr.json
Normal file
10
resources/lang/fr.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"error_occured_in_app": "Une erreur est survenue sur :appName",
|
||||
"check_trace": "Veuillez vérifier les logs pour réparer ceci.",
|
||||
"uri": "uri",
|
||||
"date": "date",
|
||||
"code": "code",
|
||||
"file": "fichier",
|
||||
"line": "ligne",
|
||||
"anonymized_stack_trace": "pile d'appels anonymisée"
|
||||
}
|
||||
16
resources/views/emails/exception-plain.blade.php
Normal file
16
resources/views/emails/exception-plain.blade.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{{ $appName }} Exception Handler
|
||||
|
||||
{{ __('error_occured_in_app_check_trace', [
|
||||
'appName' => $appName,
|
||||
]) }}
|
||||
{{ __('check_trace') }}
|
||||
|
||||
{{ $emessage }}
|
||||
{{ __('uri') }} : {{ $uri }}
|
||||
{{ __('date') }} : {{ date('Y-m-d H:i:s') }}
|
||||
{{ __('code') }} : {{ $code }}
|
||||
{{ __('file') }} : {{ $file }}
|
||||
{{ __('line') }} : {{ $line }}
|
||||
|
||||
{{ __('anonymized_stack_trace') }} :
|
||||
{!! nl2br($stackTrace) !!}
|
||||
24
resources/views/emails/exception.blade.php
Normal file
24
resources/views/emails/exception.blade.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html
|
||||
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
<title>{{ $appName }} Exception Handler</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>{{ __('error_occured_in_app', ['appName' => $appName]) }}</h1>
|
||||
<p>{{ __('check_trace') }}</p>
|
||||
|
||||
<h2>{{ $emessage }}</h2>
|
||||
<p>{{ __('uri') }} : {{ $uri }}</p>
|
||||
<p>{{ __('date') }} : {{ date('Y-m-d H:i:s') }}</p>
|
||||
<p>{{ __('code') }} : {{ $code }}</p>
|
||||
<p>{{ __('file') }} : {{ $file }}</p>
|
||||
<p>{{ __('line') }} : {{ $line }}</p><br>
|
||||
<p>{{ __('anonymized_stack_trace') }} :</p>
|
||||
<p>{!! nl2br($stackTrace) !!}</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
66
src/Console/Commands/InstallHandler.php
Normal file
66
src/Console/Commands/InstallHandler.php
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Kwaadpepper\ExceptionHandler\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class InstallHandler extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'handler:install';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Install the exception handler';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$handlerPath = \app_path('Exceptions/Handler.php');
|
||||
if (!File::exists($handlerPath)) {
|
||||
$this->error("The [$handlerPath] file could not be found.");
|
||||
exit;
|
||||
}
|
||||
$handlerFile = File::get($handlerPath);
|
||||
$find = 'use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;';
|
||||
$replace = 'use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;';
|
||||
if (\strpos($handlerFile, $replace) !== false) {
|
||||
$this->error('Exception handler seems to already be installed');
|
||||
exit;
|
||||
}
|
||||
if (\strpos($handlerFile, $find) === false) {
|
||||
$this->error('Exception handler could not be installed, cannot find str to replace');
|
||||
exit;
|
||||
}
|
||||
$handlerFile = \str_replace($find, $replace, $handlerFile);
|
||||
File::put($handlerPath, $handlerFile);
|
||||
$this->info("Replaced $handlerPath");
|
||||
|
||||
$source = __DIR__ . '/../../../config/exception-handler.php';
|
||||
$dest = \config_path('exception-handler.php');
|
||||
$destExist = File::exists($dest);
|
||||
if (
|
||||
!$destExist or
|
||||
($destExist and
|
||||
$this->ask('Config file exception-handler.php already exists, overwrite ? [y/n]') === 'y')
|
||||
) {
|
||||
File::copy($source, $dest);
|
||||
$this->info("Installed config file $dest");
|
||||
}
|
||||
|
||||
$this->info('Exception handler was successfully installed');
|
||||
}
|
||||
}
|
||||
62
src/Console/Commands/RemoveHandler.php
Normal file
62
src/Console/Commands/RemoveHandler.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace Kwaadpepper\ExceptionHandler\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\File;
|
||||
|
||||
class RemoveHandler extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'handler:remove';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Remove the exception handler';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$handlerPath = \app_path('Exceptions/Handler.php');
|
||||
if (!File::exists($handlerPath)) {
|
||||
$this->error("The [$handlerPath] file could not be found.");
|
||||
exit;
|
||||
}
|
||||
$handlerFile = File::get($handlerPath);
|
||||
$find = 'use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;';
|
||||
$replace = 'use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;';
|
||||
if (\strpos($handlerFile, $replace) !== false) {
|
||||
$this->error('Exception handler seems to already be removed');
|
||||
exit;
|
||||
}
|
||||
if (\strpos($handlerFile, $find) === false) {
|
||||
$this->error('Exception handler could not be removed, cannot find str to replace');
|
||||
exit;
|
||||
}
|
||||
$handlerFile = \str_replace($find, $replace, $handlerFile);
|
||||
File::put($handlerPath, $handlerFile);
|
||||
|
||||
$source = \config_path('exception-handler.php');
|
||||
$sourceExist = File::exists($source);
|
||||
if (
|
||||
$sourceExist and
|
||||
$this->ask('Remove config/exception-handler.php ? [y/n]') === 'y'
|
||||
) {
|
||||
File::delete($source);
|
||||
}
|
||||
|
||||
$this->info('Exception handler was successfully removed');
|
||||
}
|
||||
}
|
||||
38
src/ExceptionHandlerServiceProvider.php
Normal file
38
src/ExceptionHandlerServiceProvider.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Kwaadpepper\ExceptionHandler;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class ExceptionHandlerServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
protected $commands = [
|
||||
'Kwaadpepper\ExceptionHandler\Console\Commands\InstallHandler',
|
||||
'Kwaadpepper\ExceptionHandler\Console\Commands\RemoveHandler'
|
||||
];
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->loadJsonTranslationsFrom(__DIR__ . '/../resources/lang/');
|
||||
$this->loadViewsFrom(__DIR__ . '/../resources/views', 'exception-handler');
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config' => config_path(),
|
||||
], 'config');
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->mergeConfigFrom(
|
||||
sprintf('%s/../config/exception-handler.php', __DIR__),
|
||||
'exception-handler'
|
||||
);
|
||||
$this->commands($this->commands);
|
||||
}
|
||||
}
|
||||
123
src/Exceptions/ExceptionHandler.php
Normal file
123
src/Exceptions/ExceptionHandler.php
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
namespace Kwaadpepper\ExceptionHandler\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Container\Container;
|
||||
use Illuminate\Foundation\Exceptions\Handler;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Throwable;
|
||||
|
||||
class ExceptionHandler extends Handler
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a new exception handler instance.
|
||||
*
|
||||
* @param \Illuminate\Contracts\Container\Container $container
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
parent::__construct($container);
|
||||
$this->reportable(function (Throwable $e) {
|
||||
$dest = config('exception-handler.contactsList', config('mail.from.address'));
|
||||
try {
|
||||
if ($dest and config('exception-handler.enableMaiLog')) {
|
||||
if ($this->shouldntReport($e)) {
|
||||
return false;
|
||||
}
|
||||
Mail::send([
|
||||
'html' => 'exception-handler::emails.exception',
|
||||
'text' => 'exception-handler::emails.exception-plain'
|
||||
], [
|
||||
'appName' => config('app.name'),
|
||||
'code' => $e->getCode(),
|
||||
'line' => $e->getLine(),
|
||||
'emessage' => $this->getAnonymizedMessage($e->getMessage()),
|
||||
'file' => str_replace(\realpath(\sprintf('%s/../', \app_path())), '', $e->getFile()),
|
||||
'stackTrace' => $this->getAnonymizedStackTrace($e),
|
||||
'uri' => app()->runningInConsole() ?
|
||||
'CONSOLE' : (
|
||||
(request() and request()->fullUrl()) ?
|
||||
request()->fullUrl() : 'none')
|
||||
], function ($m) use ($dest) {
|
||||
/** @var \Illuminate\Mail\Message $m */
|
||||
$m->to(
|
||||
$dest,
|
||||
sprintf('%s Exception Handler', config('app.name'))
|
||||
)->subject('Need help !, an error occured in your application, please check Logs ASAP');
|
||||
});
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
dd($e);
|
||||
Log::critical('Handler could not send Exception email', ['exception' => $e]);
|
||||
} finally {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymize at least Sql queries
|
||||
*
|
||||
* @param string $message
|
||||
* @return string
|
||||
*/
|
||||
private function getAnonymizedMessage(string $message): string
|
||||
{
|
||||
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Anonymize stack trace
|
||||
*
|
||||
* @param \Exception $e
|
||||
* @return string
|
||||
*/
|
||||
private function getAnonymizedStackTrace(\Exception $e): string
|
||||
{
|
||||
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
|
||||
$traceStack = $e->getTrace();
|
||||
$traceStr = '';
|
||||
$maxStackStage = 0;
|
||||
foreach ($traceStack as $stackStage => $stack) {
|
||||
$maxStackStage = $stackStage;
|
||||
$traceStr .= \sprintf(
|
||||
'#%s %s(%d): ',
|
||||
$stackStage,
|
||||
str_replace($projectPath, '', $stack['file']),
|
||||
$stack['line']
|
||||
);
|
||||
$traceStr .= "{$stack['class']}->{$stack['function']}(";
|
||||
$traceArgs = '';
|
||||
if (isset($stack['args'])) {
|
||||
$argsCount = count($stack['args']);
|
||||
for ($i = 0; $i < $argsCount; $i++) {
|
||||
$type = \gettype($stack['args'][$i]);
|
||||
switch ($type) {
|
||||
case 'object':
|
||||
$traceArgs .= sprintf('Object(%s)', \get_class($stack['args'][$i]));
|
||||
break;
|
||||
case 'array':
|
||||
$traceArgs .= sprintf('Array(%d)', \count($stack['args'][$i]));
|
||||
break;
|
||||
case 'string':
|
||||
$traceArgs .= sprintf('String(%d)', \strlen($stack['args'][$i]));
|
||||
break;
|
||||
default:
|
||||
$traceArgs .= \gettype($stack['args'][$i]);
|
||||
}
|
||||
$traceArgs .= ($i !== ($argsCount - 1) ? ',' : '');
|
||||
}
|
||||
$traceStr .= $traceArgs;
|
||||
}
|
||||
$traceStr .= ")\n";
|
||||
}
|
||||
$maxStackStage++;
|
||||
$traceStr .= "#$maxStackStage {main}";
|
||||
return $traceStr;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue