Compare commits
No commits in common. "master" and "0.0.4" have entirely different histories.
15 changed files with 7438 additions and 296 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,2 @@
|
||||||
workspace.code-workspace
|
workspace.code-workspace
|
||||||
vendor
|
vendor
|
||||||
.vscode
|
|
||||||
|
|
|
||||||
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
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
27
changelog.md
27
changelog.md
|
|
@ -2,33 +2,6 @@
|
||||||
|
|
||||||
All notable changes to `ExceptionHandler` will be documented in this file.
|
All notable changes to `ExceptionHandler` will be documented in this file.
|
||||||
|
|
||||||
# version 2.0.0
|
|
||||||
- Changed enhance getAnonymizedMessage (for DB queries)
|
|
||||||
- Changed Support only for laravel 10
|
|
||||||
- Added env element EXCEPTION_MAIL_LIST
|
|
||||||
|
|
||||||
# version 0.1.1
|
|
||||||
- Changed better parsing for email recipients
|
|
||||||
- Changed if no recipients are available, a warning will be emitted, also native Laravel report method will be called instead.
|
|
||||||
- Changed if mail report fails, native reporting method will be called.
|
|
||||||
|
|
||||||
# version 0.1.0
|
|
||||||
- Add a a method to manually send exception by email (plus the same to call statically).
|
|
||||||
|
|
||||||
# version 0.0.9
|
|
||||||
- Multiline exception message in mail.
|
|
||||||
|
|
||||||
# version 0.0.8
|
|
||||||
- Make sure sending mail error is always correctly handled (write in logs)
|
|
||||||
|
|
||||||
# version 0.0.7
|
|
||||||
- Added support for laravel 9
|
|
||||||
|
|
||||||
# version 0.0.6
|
|
||||||
- Added class name to email message
|
|
||||||
|
|
||||||
# version 0.0.5
|
|
||||||
- Fixed Handle cases where exception came from a function instead of a class
|
|
||||||
# version 0.0.4
|
# version 0.0.4
|
||||||
- Fixed Try to fix undefined index file error
|
- Fixed Try to fix undefined index file error
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,13 @@
|
||||||
"Policies"
|
"Policies"
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"illuminate/support": "~10",
|
"illuminate/support": "~7|~8",
|
||||||
"laravel/framework": "~10"
|
"laravel/framework": "~7|~8"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"slevomat/coding-standard": "^8.10"
|
"phpunit/phpunit": "~9.0",
|
||||||
|
"squizlabs/php_codesniffer": "^3.5",
|
||||||
|
"orchestra/testbench": "^6.13"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
@ -39,10 +41,5 @@
|
||||||
"Kwaadpepper\\ExceptionHandler\\ExceptionHandlerServiceProvider"
|
"Kwaadpepper\\ExceptionHandler\\ExceptionHandlerServiceProvider"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"allow-plugins": {
|
|
||||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7242
composer.lock
generated
Normal file
7242
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -11,5 +11,5 @@ return [
|
||||||
* Put a developper secured mailbox in here
|
* Put a developper secured mailbox in here
|
||||||
* so you can receive email if things go mad
|
* so you can receive email if things go mad
|
||||||
*/
|
*/
|
||||||
'contactsList' => collect(explode(',', env('EXCEPTION_MAIL_LIST')))->all(),
|
'contactsList' => []
|
||||||
];
|
];
|
||||||
|
|
|
||||||
175
phpcs.xml
175
phpcs.xml
|
|
@ -1,86 +1,74 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ruleset name="LDC Laravel"
|
<ruleset name="RealWorld" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
<arg name="colors"/>
|
||||||
<description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/</description>
|
<arg name="extensions" value="php"/>
|
||||||
<arg name="colors" />
|
|
||||||
<arg name="extensions" value="php" />
|
|
||||||
<file>src/</file>
|
<file>src/</file>
|
||||||
<rule ref="PSR1" />
|
<file>tests/</file>
|
||||||
<rule ref="PSR12" />
|
<description>Created with the PHP Coding Standard Generator. http://edorian.github.com/php-coding-standard-generator/
|
||||||
|
</description>
|
||||||
<rule ref="Generic.Classes.DuplicateClassName"/>
|
<rule ref="Generic.CodeAnalysis.EmptyStatement" />
|
||||||
<rule ref="Generic.CodeAnalysis.EmptyStatement"/>
|
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop" />
|
||||||
<rule ref="Generic.CodeAnalysis.ForLoopShouldBeWhileLoop"/>
|
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall" />
|
||||||
<rule ref="Generic.CodeAnalysis.ForLoopWithTestFunctionCall"/>
|
<rule ref="Generic.CodeAnalysis.JumbledIncrementer" />
|
||||||
<rule ref="Generic.CodeAnalysis.JumbledIncrementer"/>
|
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement" />
|
||||||
<rule ref="Generic.CodeAnalysis.UnconditionalIfStatement"/>
|
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier" />
|
||||||
<rule ref="Generic.CodeAnalysis.UnnecessaryFinalModifier"/>
|
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter" />
|
||||||
<rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
|
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod" />
|
||||||
<rule ref="Generic.CodeAnalysis.UselessOverridingMethod"/>
|
<rule ref="Generic.Commenting.Todo" />
|
||||||
<rule ref="Generic.Commenting.DocComment.SpacingBeforeTags"/>
|
<rule ref="Generic.Commenting.Fixme" />
|
||||||
<rule ref="Generic.Commenting.Todo"/>
|
<rule ref="Generic.ControlStructures.InlineControlStructure" />
|
||||||
<rule ref="Generic.Commenting.Fixme"/>
|
<rule ref="Generic.Files.ByteOrderMark" />
|
||||||
<rule ref="Generic.ControlStructures.InlineControlStructure"/>
|
<rule ref="Generic.Files.LineEndings" />
|
||||||
<rule ref="Generic.Files.ByteOrderMark"/>
|
<rule ref="Generic.Files.LineLength">
|
||||||
<rule ref="Generic.Files.LineEndings"/>
|
|
||||||
<rule ref="Generic.Files.LineLength"/>
|
|
||||||
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
|
|
||||||
<rule ref="Generic.Formatting.MultipleStatementAlignment"/>
|
|
||||||
<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.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="PSR2.Classes.ClassDeclaration"/>
|
|
||||||
<rule ref="PSR2.Classes.PropertyDeclaration"/>
|
|
||||||
<rule ref="PSR2.ControlStructures.ElseIfDeclaration"/>
|
|
||||||
<rule ref="PSR2.ControlStructures.SwitchDeclaration"/>
|
|
||||||
<rule ref="PSR2.Files.EndFileNewline"/>
|
|
||||||
<rule ref="PSR2.Methods.MethodDeclaration"/>
|
|
||||||
<rule ref="PSR2.Namespaces.NamespaceDeclaration"/>
|
|
||||||
<rule ref="PSR2.Namespaces.UseDeclaration"/>
|
|
||||||
<rule ref="Squiz.PHP.CommentedOutCode"/>
|
|
||||||
<rule ref="Squiz.PHP.DisallowMultipleAssignments">
|
|
||||||
<exclude name="Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.PHP.DisallowSizeFunctionsInLoops"/>
|
|
||||||
|
|
||||||
<rule ref="Squiz.PHP.DiscouragedFunctions">
|
|
||||||
<properties>
|
<properties>
|
||||||
<property name="error" value="true"/>
|
<property name="lineLimit" value="120"/>
|
||||||
|
<property name="absoluteLineLimit" value="0"/>
|
||||||
</properties>
|
</properties>
|
||||||
</rule>
|
</rule>
|
||||||
<rule ref="Squiz.PHP.Eval"/>
|
<rule ref="Generic.Formatting.DisallowMultipleStatements" />
|
||||||
<rule ref="Squiz.PHP.GlobalKeyword"/>
|
<rule ref="Generic.Formatting.NoSpaceAfterCast" />
|
||||||
<rule ref="Squiz.PHP.Heredoc"/>
|
<rule ref="Generic.Functions.CallTimePassByReference" />
|
||||||
<rule ref="Squiz.PHP.InnerFunctions"/>
|
<rule ref="Generic.Functions.FunctionCallArgumentSpacing" />
|
||||||
<rule ref="Squiz.PHP.LowercasePHPFunctions"/>
|
<rule ref="Generic.Metrics.CyclomaticComplexity" />
|
||||||
<rule ref="Squiz.PHP.NonExecutableCode"/>
|
<rule ref="Generic.Metrics.NestingLevel" />
|
||||||
<rule ref="Squiz.Scope.MemberVarScope"/>
|
<rule ref="Generic.NamingConventions.ConstructorName" />
|
||||||
<rule ref="Squiz.Scope.MethodScope"/>
|
<rule ref="Generic.NamingConventions.UpperCaseConstantName" />
|
||||||
<rule ref="Squiz.Scope.StaticThisUsage"/>
|
<rule ref="Generic.NamingConventions.CamelCapsFunctionName" />
|
||||||
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
|
<rule ref="Generic.PHP.DeprecatedFunctions" />
|
||||||
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
|
<rule ref="Generic.PHP.DisallowShortOpenTag" />
|
||||||
<rule ref="Squiz.WhiteSpace.MemberVarSpacing">
|
<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>
|
<properties>
|
||||||
<property name="spacingBeforeFirst " value="false"/>
|
<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>
|
</properties>
|
||||||
</rule>
|
</rule>
|
||||||
<rule ref="Squiz.WhiteSpace.OperatorSpacing">
|
<rule ref="Squiz.WhiteSpace.OperatorSpacing">
|
||||||
|
|
@ -88,39 +76,12 @@
|
||||||
<property name="ignoreNewlines" value="true"/>
|
<property name="ignoreNewlines" value="true"/>
|
||||||
</properties>
|
</properties>
|
||||||
</rule>
|
</rule>
|
||||||
<rule ref="Squiz.WhiteSpace.ObjectOperatorSpacing">
|
<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing" />
|
||||||
<properties>
|
<rule ref="Squiz.WhiteSpace.SemicolonSpacing" />
|
||||||
<property name="ignoreNewlines" value="true"/>
|
|
||||||
</properties>
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.WhiteSpace.ScopeKeywordSpacing"/>
|
|
||||||
<rule ref="Squiz.WhiteSpace.SemicolonSpacing"/>
|
|
||||||
<rule ref="Squiz.Commenting.BlockComment">
|
|
||||||
<exclude name="Squiz.Commenting.BlockComment.WrongStart" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.ClassComment">
|
|
||||||
<exclude name="Squiz.Commenting.ClassComment.Missing" />
|
|
||||||
<exclude name="Squiz.Commenting.ClassComment.TagNotAllowed" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.DocCommentAlignment"/>
|
|
||||||
<rule ref="Squiz.Commenting.EmptyCatchComment"/>
|
|
||||||
<rule ref="Squiz.Commenting.FunctionComment">
|
|
||||||
<exclude name="Squiz.Commenting.FunctionComment.MissingParamComment" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.FunctionCommentThrowTag"/>
|
|
||||||
<rule ref="Squiz.Commenting.InlineComment">
|
|
||||||
<exclude name="Squiz.Commenting.InlineComment.DocBlock" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.LongConditionClosingComment">
|
|
||||||
<exclude name="Squiz.Commenting.LongConditionClosingComment.SpacingBefore" />
|
|
||||||
</rule>
|
|
||||||
<rule ref="Squiz.Commenting.PostStatementComment"/>
|
|
||||||
<rule ref="Squiz.Commenting.VariableComment"/>
|
|
||||||
<rule ref="SlevomatCodingStandard.Namespaces.UnusedUses.UnusedUse" />
|
|
||||||
|
|
||||||
<!-- For Laravel migrations -->
|
<!-- For Laravel migrations -->
|
||||||
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
|
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
|
||||||
<exclude-pattern>*/database/migrations/*</exclude-pattern>
|
<exclude-pattern>*/database/migrations/*</exclude-pattern>
|
||||||
</rule>
|
</rule>
|
||||||
|
|
||||||
</ruleset>
|
</ruleset>
|
||||||
|
|
|
||||||
17
readme.md
17
readme.md
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
[![Latest Version on Packagist][ico-version]][link-packagist]
|
[![Latest Version on Packagist][ico-version]][link-packagist]
|
||||||
[![Total Downloads][ico-downloads]][link-downloads]
|
[![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
|
Handles exceptions and send email when it does happen
|
||||||
It does send you a mail with anonymized debug data
|
It does send you a mail with anonymized debug data
|
||||||
|
|
@ -16,26 +18,23 @@ $ composer require kwaadpepper/exception-handler
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
- `php artisan handler:install`
|
1 - php artisan handler:install
|
||||||
- Change configuration in `config/exception-handler.php` if needed.
|
2 - Change configuration in config/exception-handler.php
|
||||||
- Put at least your team email in the above file in `contactsList` array or using `.env` put a list in `EXCEPTION_MAIL_LIST`. You can add emails separated with `,` like `admin1@email.com,admin2@email.com`
|
3 - put at least your team email in the above file in `contactsList` array
|
||||||
|
|
||||||
You can uninstall it by using `php artisan handler:remove` or just revert changes in Exception/Handler.php
|
You can uninstall it by using php artisan handler:remove or juste revert changes in Exception/Handler.php
|
||||||
## Change log
|
## Change log
|
||||||
|
|
||||||
Please see the [changelog](changelog.md) for more information on what has changed recently.
|
Please see the [changelog](changelog.md) for more information on what has changed recently.
|
||||||
|
|
||||||
# Todo
|
|
||||||
|
|
||||||
- Add other transmission possibilities (other than mail)
|
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
If you discover any security related issues, please email `github@jeremydev.ovh` instead of using the issue tracker.
|
If you discover any security related issues, please email github@jeremydev.ovh instead of using the issue tracker.
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [Jérémy Munsch][link-author]
|
- [Jérémy Munsch][link-author]
|
||||||
|
- [All Contributors][link-contributors]
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
]) }}
|
]) }}
|
||||||
{{ __('check_trace') }}
|
{{ __('check_trace') }}
|
||||||
|
|
||||||
{{ $ename }}
|
|
||||||
{{ $emessage }}
|
{{ $emessage }}
|
||||||
{{ __('uri') }} : {{ $uri }}
|
{{ __('uri') }} : {{ $uri }}
|
||||||
{{ __('date') }} : {{ date('Y-m-d H:i:s') }}
|
{{ __('date') }} : {{ date('Y-m-d H:i:s') }}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,7 @@
|
||||||
<h1>{{ __('error_occured_in_app', ['appName' => $appName]) }}</h1>
|
<h1>{{ __('error_occured_in_app', ['appName' => $appName]) }}</h1>
|
||||||
<p>{{ __('check_trace') }}</p>
|
<p>{{ __('check_trace') }}</p>
|
||||||
|
|
||||||
<h2>{{ $ename }}</h2>
|
<h2>{{ $emessage }}</h2>
|
||||||
<h3>{!! nl2br(strip_tags(e($emessage))) !!}</h3>
|
|
||||||
<p>{{ __('uri') }} : {{ $uri }}</p>
|
<p>{{ __('uri') }} : {{ $uri }}</p>
|
||||||
<p>{{ __('date') }} : {{ date('Y-m-d H:i:s') }}</p>
|
<p>{{ __('date') }} : {{ date('Y-m-d H:i:s') }}</p>
|
||||||
<p>{{ __('code') }} : {{ $code }}</p>
|
<p>{{ __('code') }} : {{ $code }}</p>
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
class InstallHandler extends Command
|
class InstallHandler extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
|
|
@ -34,8 +35,8 @@ class InstallHandler extends Command
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
$handlerFile = File::get($handlerPath);
|
$handlerFile = File::get($handlerPath);
|
||||||
$find = 'use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;';
|
$find = 'use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;';
|
||||||
$replace = 'use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;';
|
$replace = 'use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;';
|
||||||
if (\strpos($handlerFile, $replace) !== false) {
|
if (\strpos($handlerFile, $replace) !== false) {
|
||||||
$this->error('Exception handler seems to already be installed');
|
$this->error('Exception handler seems to already be installed');
|
||||||
exit;
|
exit;
|
||||||
|
|
@ -48,8 +49,8 @@ class InstallHandler extends Command
|
||||||
File::put($handlerPath, $handlerFile);
|
File::put($handlerPath, $handlerFile);
|
||||||
$this->info("Replaced $handlerPath");
|
$this->info("Replaced $handlerPath");
|
||||||
|
|
||||||
$source = __DIR__ . '/../../../config/exception-handler.php';
|
$source = __DIR__ . '/../../../config/exception-handler.php';
|
||||||
$dest = \config_path('exception-handler.php');
|
$dest = \config_path('exception-handler.php');
|
||||||
$destExist = File::exists($dest);
|
$destExist = File::exists($dest);
|
||||||
if (
|
if (
|
||||||
!$destExist or
|
!$destExist or
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use Illuminate\Support\Facades\File;
|
||||||
|
|
||||||
class RemoveHandler extends Command
|
class RemoveHandler extends Command
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name and signature of the console command.
|
* The name and signature of the console command.
|
||||||
*
|
*
|
||||||
|
|
@ -34,8 +35,8 @@ class RemoveHandler extends Command
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
$handlerFile = File::get($handlerPath);
|
$handlerFile = File::get($handlerPath);
|
||||||
$find = 'use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;';
|
$find = 'use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler;';
|
||||||
$replace = 'use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;';
|
$replace = 'use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;';
|
||||||
if (\strpos($handlerFile, $replace) !== false) {
|
if (\strpos($handlerFile, $replace) !== false) {
|
||||||
$this->error('Exception handler seems to already be removed');
|
$this->error('Exception handler seems to already be removed');
|
||||||
exit;
|
exit;
|
||||||
|
|
@ -47,7 +48,7 @@ class RemoveHandler extends Command
|
||||||
$handlerFile = \str_replace($find, $replace, $handlerFile);
|
$handlerFile = \str_replace($find, $replace, $handlerFile);
|
||||||
File::put($handlerPath, $handlerFile);
|
File::put($handlerPath, $handlerFile);
|
||||||
|
|
||||||
$source = \config_path('exception-handler.php');
|
$source = \config_path('exception-handler.php');
|
||||||
$sourceExist = File::exists($source);
|
$sourceExist = File::exists($source);
|
||||||
if (
|
if (
|
||||||
$sourceExist and
|
$sourceExist and
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
class ExceptionHandlerServiceProvider extends ServiceProvider
|
class ExceptionHandlerServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
||||||
protected $commands = [
|
protected $commands = [
|
||||||
'Kwaadpepper\ExceptionHandler\Console\Commands\InstallHandler',
|
'Kwaadpepper\ExceptionHandler\Console\Commands\InstallHandler',
|
||||||
'Kwaadpepper\ExceptionHandler\Console\Commands\RemoveHandler'
|
'Kwaadpepper\ExceptionHandler\Console\Commands\RemoveHandler'
|
||||||
|
|
@ -29,7 +30,7 @@ class ExceptionHandlerServiceProvider extends ServiceProvider
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->mergeConfigFrom(
|
$this->mergeConfigFrom(
|
||||||
__DIR__ . '/../config/exception-handler.php',
|
sprintf('%s/../config/exception-handler.php', __DIR__),
|
||||||
'exception-handler'
|
'exception-handler'
|
||||||
);
|
);
|
||||||
$this->commands($this->commands);
|
$this->commands($this->commands);
|
||||||
|
|
|
||||||
|
|
@ -2,115 +2,92 @@
|
||||||
|
|
||||||
namespace Kwaadpepper\ExceptionHandler\Exceptions;
|
namespace Kwaadpepper\ExceptionHandler\Exceptions;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Exception;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Foundation\Exceptions\Handler;
|
use Illuminate\Foundation\Exceptions\Handler;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
class ExceptionHandler extends Handler
|
class ExceptionHandler extends Handler
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new exception handler instance.
|
* Create a new exception handler instance.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Contracts\Container\Container $container
|
* @param \Illuminate\Contracts\Container\Container $container
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function __construct(Container $container)
|
public function __construct(Container $container)
|
||||||
{
|
{
|
||||||
parent::__construct($container);
|
parent::__construct($container);
|
||||||
$this->reportable($this->reportExceptionByEmail());
|
if (\strpos(app()->version(), '8') === 0) {
|
||||||
|
$this->reportable($this->reportExceptionByEmail());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report or log an exception.
|
* Report or log an exception.
|
||||||
*
|
*
|
||||||
* @param \Throwable $e
|
* @param \Throwable $exception
|
||||||
* @return void
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws \Exception
|
||||||
*/
|
*/
|
||||||
public function report(\Throwable $e)
|
public function report(Throwable $e)
|
||||||
{
|
{
|
||||||
if (get_class($e) == RedirectTo::class) {
|
if (get_class($e) == RedirectTo::class) {
|
||||||
abort(redirect($e->url));
|
abort(redirect($e->url));
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
\strpos(app()->version(), '8') !== 0 and
|
||||||
|
!$this->reportExceptionByEmail()($e)
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
parent::report($e);
|
parent::report($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually send exception by email
|
|
||||||
*
|
|
||||||
* @param \Throwable $e
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public static function sendExceptionByEmailStatic(\Throwable $e)
|
|
||||||
{
|
|
||||||
app(self::class)->sendExceptionByEmail($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manually send exception by email
|
|
||||||
*
|
|
||||||
* @param \Throwable $e
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function sendExceptionByEmail(\Throwable $e)
|
|
||||||
{
|
|
||||||
$this->reportExceptionByEmail()($e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report sending mail closure
|
* Report sending mail closure
|
||||||
*
|
*
|
||||||
* @return \Closure
|
* @return Closure
|
||||||
*/
|
*/
|
||||||
private function reportExceptionByEmail(): \Closure
|
private function reportExceptionByEmail(): Closure
|
||||||
{
|
{
|
||||||
return function (\Throwable $e) {
|
return function (Throwable $e) {
|
||||||
if ($this->shouldntReport($e)) {
|
$dest = config('exception-handler.contactsList', config('mail.from.address'));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// * Ignore NoContactException.
|
|
||||||
if ($e instanceof NoContactException) {
|
|
||||||
Log::critical($e->getMessage());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$dest = \collect(config('exception-handler.contactsList', config('mail.from.address')))->filter();
|
|
||||||
try {
|
try {
|
||||||
if (!config('exception-handler.enableMaiLog')) {
|
if ($dest and config('exception-handler.enableMaiLog')) {
|
||||||
return false;
|
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');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!$dest->count()) {
|
} catch (Exception $e) {
|
||||||
throw new NoContactException(
|
Log::critical('Handler could not send Exception email', ['exception' => $e]);
|
||||||
'No contact in `EXCEPTION_MAIL_LIST` nor `exception-handler.contactsList` config',
|
}
|
||||||
0,
|
|
||||||
$e
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Mail::send([
|
|
||||||
'html' => 'exception-handler::emails.exception',
|
|
||||||
'text' => 'exception-handler::emails.exception-plain'
|
|
||||||
], [
|
|
||||||
'appName' => config('app.name'),
|
|
||||||
'code' => $e->getCode(),
|
|
||||||
'line' => $e->getLine(),
|
|
||||||
'ename' => \get_class($e),
|
|
||||||
'emessage' => self::getAnonymizedMessage($e->getMessage()),
|
|
||||||
'file' => str_replace(\realpath(\sprintf('%s/../', \app_path())), '', $e->getFile()),
|
|
||||||
'stackTrace' => self::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->all(),
|
|
||||||
sprintf('%s Exception Handler', config('app.name'))
|
|
||||||
)->subject('Need help !, an error occured in your application, please check Logs ASAP');
|
|
||||||
});
|
|
||||||
} catch (\Error $reportE) {
|
|
||||||
parent::report($e);
|
|
||||||
Log::critical('Handler could not send Exception email', ['exception' => $reportE]);
|
|
||||||
}//end try
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,81 +97,59 @@ class ExceptionHandler extends Handler
|
||||||
* @param string $message
|
* @param string $message
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function getAnonymizedMessage(string $message): string
|
private function getAnonymizedMessage(string $message): string
|
||||||
{
|
{
|
||||||
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
|
$message = \preg_replace('/^(.*)( \(SQL:.*\))$/', '$1', $message) ?? $message;
|
||||||
if ($sqlPos = \strpos($message, 'to use near')) {
|
|
||||||
$message = \mb_strcut($message, 0, $sqlPos);
|
|
||||||
}
|
|
||||||
return $message;
|
return $message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Anonymize stack trace
|
* Anonymize stack trace
|
||||||
*
|
*
|
||||||
* @param \Throwable $e
|
* @param \Exception $e
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function getAnonymizedStackTrace(\Throwable $e): string
|
private function getAnonymizedStackTrace(Throwable $e): string
|
||||||
{
|
{
|
||||||
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
|
$projectPath = \realpath(\sprintf('%s/../', \app_path()));
|
||||||
$traceStack = $e->getTrace();
|
$traceStack = $e->getTrace();
|
||||||
$traceStr = '';
|
$traceStr = '';
|
||||||
$maxStackStage = 0;
|
$maxStackStage = 0;
|
||||||
foreach ($traceStack as $stackStage => $stack) {
|
foreach ($traceStack as $stackStage => $stack) {
|
||||||
$maxStackStage = $stackStage;
|
$maxStackStage = $stackStage;
|
||||||
$traceStr .= \sprintf(
|
$traceStr .= \sprintf(
|
||||||
'#%s %s(%d): ',
|
'#%s %s(%d): ',
|
||||||
$stackStage,
|
$stackStage,
|
||||||
str_replace($projectPath, '', $stack['file'] ?? ''),
|
str_replace($projectPath, '', $stack['file'] ?? ''),
|
||||||
$stack['line'] ?? ''
|
$stack['line'] ?? ''
|
||||||
);
|
);
|
||||||
if (isset($stack['class'])) {
|
$traceStr .= "{$stack['class']}->{$stack['function']}(";
|
||||||
$traceStr .= "{$stack['class']}->{$stack['function']}(";
|
$traceArgs = '';
|
||||||
if (isset($stack['args'])) {
|
if (isset($stack['args'])) {
|
||||||
$traceStr .= self::handleArgs($stack);
|
$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 .= ")\n";
|
$traceStr .= $traceArgs;
|
||||||
} elseif (isset($stack['function'])) {
|
|
||||||
$traceStr .= "{$stack['function']}(";
|
|
||||||
if (isset($stack['args'])) {
|
|
||||||
$traceStr .= self::handleArgs($stack);
|
|
||||||
}
|
|
||||||
$traceStr .= ")\n";
|
|
||||||
}
|
}
|
||||||
} //end foreach
|
$traceStr .= ")\n";
|
||||||
|
}
|
||||||
$maxStackStage++;
|
$maxStackStage++;
|
||||||
$traceStr .= "#$maxStackStage {main}";
|
$traceStr .= "#$maxStackStage {main}";
|
||||||
return $traceStr;
|
return $traceStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle Args
|
|
||||||
*
|
|
||||||
* @param array $stack
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
private static function handleArgs(array $stack): string
|
|
||||||
{
|
|
||||||
$traceArgs = '';
|
|
||||||
$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) ? ',' : '');
|
|
||||||
}
|
|
||||||
return $traceArgs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace Kwaadpepper\ExceptionHandler\Exceptions;
|
|
||||||
|
|
||||||
class NoContactException extends \RuntimeException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue