diff --git a/.travis.yml b/.travis.yml index 0af52da..f3d42ab 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,18 @@ language: php php: - - 7.2 + - 7.2 + - 7.3 + - 7.4 + - 8.0snapshot env: - matrix: -# - COMPOSER_FLAGS="--prefer-lowest" - - COMPOSER_FLAGS="" + matrix: + - COMPOSER_FLAGS="" before_script: -- travis_retry composer self-update -- travis_retry composer update ${COMPOSER_FLAGS} --no-interaction + - travis_retry composer self-update + - travis_retry composer update ${COMPOSER_FLAGS} --no-interaction --prefer-dist # script: # - vendor/bin/phpunit --coverage-clover build/logs/clover.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index cc394ca..1e00603 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to `LERN` will be documented in this file. +### Unreleased +- Updated for Laravel 7 and 8 +- Add support for PHP 7.3, 7.4, 8.0 +- Removed support for Laravel 5.5, 5.6, 5.7, 5.8 +- Removed support for PHP 7.0, 7.1 +- Removed deprecated RavenHandler handler, use sentry/sentry 3.x and their Sentry\Monolog\Handler instead +- Removed deprecated HipChat handler, migrate to Slack and use SlackWebhookHandler or SlackHandler instead + ### 5.0.0 - Updated for Laravel 6 diff --git a/README.md b/README.md index 4a3feec..f95da39 100755 --- a/README.md +++ b/README.md @@ -14,12 +14,11 @@ Currently supported notification channels via [Monolog](https://github.com/Selda - Email - [Pushover](https://pushover.net/) - [Slack](https://slack.com/) -- [Hipchat](https://www.hipchat.com/) - [Fleephook](https://fleep.io/) - [Flowdock](https://www.flowdock.com/) - [Plivo](https://www.plivo.com/) an SMS messaging service. - [Twilio](https://www.twilio.com/) an SMS messaging service. -- [Sentry](https://getsentry.com) via [Raven](https://github.com/getsentry/raven-php) +- [Sentry](https://getsentry.com) via [Sentry SDK for PHP](https://github.com/getsentry/sentry-php) - [Mailgun](https://mailgun.com) ## Version Compatibility @@ -32,7 +31,9 @@ Currently supported notification channels via [Monolog](https://github.com/Selda 5.4.x | 3.x 5.5.x | 4.x 5.6.x | 4.x - 6.x | 5.x + 6.x | 5.x and 6.x + 7.x | 6.x + 8.x | 6.x ## Migrating from `3.x` to `4.x` Make sure that the config file now includes the new `lern.notify.class` and `lern.record.class` settings. Check the [config file](https://github.com/tylercd100/lern/blob/master/config/lern.php) to see how they are used. @@ -40,7 +41,7 @@ Make sure that the config file now includes the new `lern.notify.class` and `ler ## Migrating from `2.x` to `3.x` Version 3.x introduces the ability to collect more information from the error such as the user_id, url, method, and input data. In order to use 3.x you will need to copy over the new [config file](https://github.com/tylercd100/lern/blob/master/config/lern.php), the migration file and then migrate it. ```php -# This will only copy over the migration file. For the config file you can either include the --force flag (Which will overwrite it) or copy it manually from github +# This will only copy over the migration file. For the config file you can either include the --force flag (Which will overwrite it) or copy it manually from github php artisan vendor:publish --provider="Tylercd100\LERN\LERNServiceProvider" php artisan migrate ``` @@ -59,7 +60,7 @@ Then you will need to run these commands in the terminal in order to copy the co php artisan vendor:publish --provider="Tylercd100\LERN\LERNServiceProvider" ``` -Before you run the migration you may want to take a look at `config/lern.php` and change the `table` property to a table name that you would like to use. After that run the migration +Before you run the migration you may want to take a look at `config/lern.php` and change the `table` property to a table name that you would like to use. After that run the migration ```bash php artisan migrate ``` @@ -67,10 +68,10 @@ php artisan migrate ## Usage To use LERN modify the report method in the `app/Exceptions/Handler.php` file ```php -public function report(Exception $e) +public function report(Throwable $e) { if ($this->shouldReport($e)) { - + //Check to see if LERN is installed otherwise you will not get an exception. if (app()->bound("lern")) { app()->make("lern")->handle($e); //Record and Notify the Exception @@ -82,17 +83,19 @@ public function report(Exception $e) */ } } - + return parent::report($e); } ``` -Dont forget to add this to the top of the file +Dont forget to add this to the top of the file ```php //If you updated your aliases array in "config/app.php" use LERN; +use Throwable; //or if you didnt... use Tylercd100\LERN\Facades\LERN; +use Throwable; ``` ### Recording @@ -143,7 +146,7 @@ LERN uses the Monolog library to send notifications. If you need more than the s #### Changing the log level programmatically Some notification services support different log levels. If changing the config value `lern.notify.log_level` is not enough then try it this way: ```php -// Change the log level. +// Change the log level. // Default is: critical // Options are: debug, info, notice, warning, error, critical, alert, emergency LERN::setLogLevel("emergency"); @@ -176,8 +179,8 @@ Make sure that you set the view config value to null or the `LERN::setMessage()` #### Custom Monolog Handlers To use a custom Monolog Handler call the `pushHandler` method ```php -use Monolog\Handler\HipChatHandler; -$handler = new HipChatHandler($token,$room); +use Monolog\Handler\SlackHandler; +$handler = new SlackHandler($token, $channel); LERN::pushHandler($handler); LERN::notify($exception); ``` diff --git a/composer.json b/composer.json index ecd462a..ff726e5 100755 --- a/composer.json +++ b/composer.json @@ -29,17 +29,19 @@ "Tylercd100\\LERN\\Tests\\": "tests/" } }, - "minimum-stability": "stable", + "minimum-stability": "dev", + "prefer-stable": true, "require": { - "php": "^7.2", - "illuminate/support": "^6.0", - "monolog/monolog": "^1.22", - "tylercd100/laravel-notify": "^3.0" + "php": "^7.2|^8.0", + "illuminate/support": "^6.0|^7.0|^8.0", + "monolog/monolog": "^2.0", + "tylercd100/laravel-notify": "^4.0" }, "require-dev": { - "orchestra/testbench": "^4.0", - "phpunit/phpunit": "^8.0", - "doctrine/dbal": "~2.3" + "mockery/mockery": "~1.3.3|^1.4.2", + "orchestra/testbench": "^4.0|^5.0|^6.0", + "phpunit/phpunit": "^8.4|^9.3.3", + "doctrine/dbal": "^2.6|^3.0" }, "suggest": { }, @@ -52,8 +54,5 @@ "LERN": "Tylercd100\\LERN\\Facades\\LERN" } } - }, - "repositories": [ - - ] + } } diff --git a/config/lern.php b/config/lern.php index 1c2800e..a61513b 100755 --- a/config/lern.php +++ b/config/lern.php @@ -2,13 +2,13 @@ return [ - /** - * To avoid infinite loops that generate thousands of records/notifications in an instant + /** + * To avoid infinite loops that generate thousands of records/notifications in an instant * Please make sure you use a Cache driver that is persistant such as redis, memcache, file, etc - * + * * Value is in seconds. */ - 'ratelimit' => 1, + 'ratelimit' => 1, 'record'=>[ /** @@ -30,7 +30,7 @@ * Database table to use */ 'table'=>'vendor_tylercd100_lern_exceptions', - + /** * Information to store */ @@ -71,12 +71,12 @@ * The log level to use when notifying */ 'log_level' => 'critical', //Options are: debug, info, notice, warning, error, critical, alert, emergency. - + /** * When using the default message body this will also include the stack trace */ 'includeExceptionStackTrace' => true, - + /** * mail, pushover, slack, etc... */ @@ -120,20 +120,17 @@ ], /** - * HipChat settings + * Flowdock settings */ - 'hipchat'=>[ - 'token' => env('HIPCHAT_APP_TOKEN'), - 'room' => 'room', - 'name' => 'name', - 'notify'=> true, + 'flowdock'=>[ + 'token' => env('FLOWDOCK_APP_TOKEN'), ], /** - * Flowdock settings + * Sentry settings */ - 'flowdock'=>[ - 'token' => env('FLOWDOCK_APP_TOKEN'), + 'sentry'=>[ + 'dsn' => env('SENTRY_DSN'), ], /** @@ -161,14 +158,7 @@ 'secret' => env('TWILIO_AUTH_SECRET'), 'to' => env('TWILIO_TO'), 'from' => env('TWILIO_FROM'), - ], - - /** - * Raven settings - */ - 'raven'=>[ - 'dsn' => env('RAVEN_DSN'), ] ], - + ]; diff --git a/src/Components/Component.php b/src/Components/Component.php index a248639..5dd7b45 100755 --- a/src/Components/Component.php +++ b/src/Components/Component.php @@ -2,7 +2,7 @@ namespace Tylercd100\LERN\Components; -use Exception; +use Throwable; use Illuminate\Support\Facades\Cache; use Carbon\Carbon; @@ -23,10 +23,10 @@ abstract class Component { /** * Determine if the exception is in the "do not handle" list. * - * @param \Exception $e + * @param \Throwable $e * @return bool */ - protected function shouldntHandle(Exception $e) { + protected function shouldntHandle(Throwable $e) { $dontHandle = array_merge($this->dontHandle, $this->absolutelyDontHandle); foreach ($dontHandle as $type) { @@ -46,10 +46,10 @@ protected function shouldntHandle(Exception $e) { /** * Returns the cache key for the exception with the current component * - * @param \Exception $e + * @param \Throwable $e * @return string */ - protected function getCacheKey(Exception $e) + protected function getCacheKey(Throwable $e) { return "LERN::".static::class."::".get_class($e); } diff --git a/src/Components/Notifier.php b/src/Components/Notifier.php index 9e5873b..4095379 100755 --- a/src/Components/Notifier.php +++ b/src/Components/Notifier.php @@ -3,7 +3,7 @@ namespace Tylercd100\LERN\Components; use Auth; -use Exception; +use Throwable; use Illuminate\Support\Facades\Request; use Illuminate\Support\Facades\Cache; use Monolog\Handler\HandlerInterface; @@ -69,10 +69,10 @@ public function setMessage($cb) /** * Returns the result of the message closure - * @param Exception $e The Exception instance that you want to build the message around + * @param Throwable $e The Throwable instance that you want to build the message around * @return string The message string */ - public function getMessage(Exception $e) + public function getMessage(Throwable $e) { $msg = $this->getMessageViaView($e); @@ -88,11 +88,11 @@ public function getMessage(Exception $e) } /** - * Gets a basic Exception message - * @param Exception $e The Exception instance that you want to build the message around + * Gets a basic Throwable message + * @param Throwable $e The Throwable instance that you want to build the message around * @return String Returns the message string */ - public function getMessageViaDefault(Exception $e) + public function getMessageViaDefault(Throwable $e) { $msg = get_class($e)." was thrown! \n".$e->getMessage(); if ($this->config['includeExceptionStackTrace'] === true) { @@ -102,11 +102,11 @@ public function getMessageViaDefault(Exception $e) } /** - * Gets the Exception message using a callback if it is set - * @param Exception $e The Exception instance that you want to build the message around + * Gets the Throwable message using a callback if it is set + * @param Throwable $e The Throwable instance that you want to build the message around * @return String|false Returns the message string or false */ - public function getMessageViaCallback(Exception $e) + public function getMessageViaCallback(Throwable $e) { if (is_callable($this->messageCb)) { return $this->messageCb->__invoke($e); @@ -115,11 +115,11 @@ public function getMessageViaCallback(Exception $e) } /** - * Gets the Exception message using a Laravel view file - * @param Exception $e The Exception instance that you want to build the message around + * Gets the Throwable message using a Laravel view file + * @param Throwable $e The Throwable instance that you want to build the message around * @return String|false Returns the message string or false */ - public function getMessageViaView(Exception $e) + public function getMessageViaView(Throwable $e) { $path = @$this->config["view"]; if (!empty($path) && View::exists($path)) { @@ -147,10 +147,10 @@ public function setSubject($cb) /** * Returns the result of the subject closure - * @param Exception $e The Exception instance that you want to build the subject around + * @param Throwable $e The Throwable instance that you want to build the subject around * @return string The subject string */ - public function getSubject(Exception $e) + public function getSubject(Throwable $e) { if (is_callable($this->subjectCb)) { return $this->subjectCb->__invoke($e); @@ -172,10 +172,10 @@ public function setContext($cb) /** * Returns the result of the context closure - * @param Exception $e The Exception instance that you want to build the context around + * @param Throwable $e The Throwable instance that you want to build the context around * @return array The context array */ - public function getContext(Exception $e, $context = []) + public function getContext(Throwable $e, $context = []) { //This needs a better solution. How do I set specific context needs for different drivers? if (in_array('pushover', $this->config['drivers'])) { @@ -223,12 +223,12 @@ public function pushHandler(HandlerInterface $handler) /** * Triggers the Monolog Logger instance to log an error to all handlers - * @param Exception $e The exception to use + * @param Throwable $e The exception to use * @param array $context Additional information that you would like to pass to Monolog * @return bool * @throws NotifierFailedException */ - public function send(Exception $e, array $context = []) + public function send(Throwable $e, array $context = []) { if ($this->shouldntHandle($e)) { return false; @@ -250,7 +250,7 @@ public function send(Exception $e, array $context = []) Cache::forever($this->getCacheKey($e), Carbon::now()); return true; - } catch (Exception $e) { + } catch (Throwable $e) { $code = (is_int($e->getCode()) ? $e->getCode() : 0); throw new NotifierFailedException($e->getMessage(), $code, $e); } diff --git a/src/Components/Recorder.php b/src/Components/Recorder.php index c9b1eb5..cbcc883 100755 --- a/src/Components/Recorder.php +++ b/src/Components/Recorder.php @@ -2,7 +2,7 @@ namespace Tylercd100\LERN\Components; -use Exception; +use Throwable; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Request; use Illuminate\Support\Facades\Cache; @@ -35,11 +35,11 @@ public function __construct() { /** * Records an Exception to the database - * @param Exception $e The exception you want to record + * @param Throwable $e The exception you want to record * @return false|ExceptionModel * @throws RecorderFailedException */ - public function record(Exception $e) + public function record(Throwable $e) { if ($this->shouldntHandle($e)) { return false; @@ -94,11 +94,11 @@ private function canCollect($type) { /** * @param string $key - * @param Exception $e + * @param Throwable $e * @return array|int|null|string - * @throws Exception + * @throws Throwable */ - protected function collect($key, Exception $e = null) { + protected function collect($key, Throwable $e = null) { switch ($key) { case 'user_id': return $this->getUserId(); @@ -116,7 +116,8 @@ protected function collect($key, Exception $e = null) { } return $this->getStatusCode($e); default: - throw new Exception("{$key} is not supported! Therefore it cannot be collected!"); + ddd();// what to do here ?????????? +// throw new Exception("{$key} is not supported! Therefore it cannot be collected!"); } } @@ -182,11 +183,11 @@ protected function getIp() { } /** - * Gets the status code of the Exception - * @param Exception $e The Exception to check + * Gets the status code of the Throwable + * @param Throwable $e The Throwable to check * @return string|integer The status code value */ - protected function getStatusCode(Exception $e) { + protected function getStatusCode(Throwable $e) { if ($e instanceof HttpExceptionInterface) { return $e->getStatusCode(); } else { @@ -197,7 +198,7 @@ protected function getStatusCode(Exception $e) { /** * This function will remove all keys from an array recursively as defined in the config file * @param array $data The array to remove keys from - * @return void + * @return array $data */ protected function excludeKeys(array $data) { $keys = isset($this->config['excludeKeys']) ? $this->config['excludeKeys'] : []; diff --git a/src/LERN.php b/src/LERN.php index 143abcf..fa4ec24 100755 --- a/src/LERN.php +++ b/src/LERN.php @@ -2,7 +2,7 @@ namespace Tylercd100\LERN; -use Exception; +use Throwable; use Monolog\Handler\HandlerInterface; use Tylercd100\LERN\Components\Notifier; use Tylercd100\LERN\Components\Recorder; @@ -15,7 +15,7 @@ class LERN { /** - * @var Exception + * @var Throwable */ private $exception; @@ -41,10 +41,10 @@ public function __construct(Notifier $notifier = null, Recorder $recorder = null /** * Will execute record and notify methods - * @param Exception $e The exception to use + * @param Throwable $e The exception to use * @return ExceptionModel the recorded Eloquent Model */ - public function handle(Exception $e) + public function handle(Throwable $e) { $this->exception = $e; $this->notify($e); @@ -53,10 +53,10 @@ public function handle(Exception $e) /** * Stores the exception in the database - * @param Exception $e The exception to use + * @param Throwable $e The exception to use * @return \Tylercd100\LERN\Models\ExceptionModel|false The recorded Exception as an Eloquent Model */ - public function record(Exception $e) + public function record(Throwable $e) { $this->exception = $e; return $this->recorder->record($e); @@ -64,10 +64,10 @@ public function record(Exception $e) /** * Will send the exception to all monolog handlers - * @param Exception $e The exception to use + * @param Throwable $e The exception to use * @return void */ - public function notify(Exception $e) + public function notify(Throwable $e) { $this->exception = $e; $this->notifier->send($e); @@ -145,7 +145,7 @@ public function setLogLevel($level) /** * Set a string or a closure to be called that will generate the message body for the notification - * @param function|string $cb This closure function will be passed an Exception and must return a string + * @param function|string $cb This closure function will be passed an Throwable and must return a string * @return $this */ public function setMessage($cb) @@ -156,7 +156,7 @@ public function setMessage($cb) /** * Set a string or a closure to be called that will generate the subject line for the notification - * @param function|string $cb This closure function will be passed an Exception and must return a string + * @param function|string $cb This closure function will be passed an Throwable and must return a string * @return $this */ public function setSubject($cb) diff --git a/tests/LERNTest.php b/tests/LERNTest.php index ea0bd3b..9fe0300 100755 --- a/tests/LERNTest.php +++ b/tests/LERNTest.php @@ -9,6 +9,7 @@ use Tylercd100\LERN\Exceptions\RecorderFailedException; use Tylercd100\Notify\Factories\MonologHandlerFactory; use Exception; +use Throwable; class LERNTest extends TestCase { @@ -64,10 +65,10 @@ public function testItCallsNotifierSendMethod() public function testItCallsNotifierPushHandlerMethod() { $mock = $this->getMockBuilder('Tylercd100\LERN\Components\Notifier')->setMethods(array('pushHandler'))->getMock(); - + $mock->expects($this->once()) ->method('pushHandler'); - + $lern = new LERN($mock); $handler = (new MonologHandlerFactory)->create('mail', config('lern.notify.mail'), 'Test Subject'); $lern->pushHandler($handler); @@ -139,7 +140,7 @@ public function testCantConnectToDatabaseError() // Mysql should not work as we have not configured it properly for testing. // this should reproduce an error similar to having the database offline. - \Config::set("database.default", "mysql"); + \Config::set("database.default", "mysql"); $this->expectException(\Illuminate\Database\QueryException::class); $lern->handle(new Exception); } diff --git a/tests/NotifierTest.php b/tests/NotifierTest.php index 1a63478..fc6fcf1 100755 --- a/tests/NotifierTest.php +++ b/tests/NotifierTest.php @@ -3,13 +3,13 @@ namespace Tylercd100\LERN\Tests; use Exception; +use Throwable; use Tylercd100\LERN\Components\Notifier; use Tylercd100\LERN\Exceptions\NotifierFailedException; use Tylercd100\LERN\Exceptions\RecorderFailedException; use Tylercd100\Notify\Factories\MonologHandlerFactory; use Illuminate\Support\Facades\Cache; - class NotifierTest extends TestCase { public function setUp(): void @@ -97,7 +97,7 @@ public function testNotifierReturnsTheCorrectMessageWhenUsingNoCallbackAndNoView config(['lern.notify.view' => null]); $this->notifier = new Notifier; $result = $this->notifier->getMessage(new Exception); - $this->assertContains('Exception was thrown!', $result); + $this->assertStringContainsString('Exception was thrown!', $result); } public function testNotifierReturnsTheCorrectMessageWhenUsingTheDefaultView() diff --git a/tests/RecorderTest.php b/tests/RecorderTest.php index 32fbe31..a894256 100755 --- a/tests/RecorderTest.php +++ b/tests/RecorderTest.php @@ -7,6 +7,7 @@ use Tylercd100\LERN\Exceptions\RecorderFailedException; use Tylercd100\LERN\Exceptions\NotifierFailedException; use Exception; +use Throwable; class RecorderTest extends TestCase { diff --git a/tests/TestCase.php b/tests/TestCase.php index 234a6aa..0aa496a 100755 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -5,6 +5,7 @@ use Orchestra\Testbench\TestCase as Orchestra; use Tylercd100\LERN\Factories\MonologHandlerFactory; use Exception; +use Throwable; use Illuminate\Support\Facades\Cache; class TestCase extends Orchestra @@ -22,7 +23,6 @@ public function setUp(): void 'pushover', 'plivo', 'twilio', - 'hipchat', 'flowdock', 'fleephook', 'mailgun' @@ -170,13 +170,6 @@ protected function getEnvironmentSetUp($app) 'from' => '+16666666666', ]); - $app['config']->set('lern.notify.hipchat', [ - 'token' => 'test-token', - 'room' => 'test-room', - 'name' => 'test-name', - 'notify' => false, - ]); - $app['config']->set('lern.notify.flowdock', [ 'token' => 'token', ]); @@ -190,7 +183,7 @@ protected function getEnvironmentSetUp($app) throw new Exception("Could not find laravel inside of testbench. Is testbench installed?"); } } - + // Test view copy(__DIR__ . "/views/test.blade.php", "{$root}/test.blade.php");