├── composer.json ├── config └── larvabug.php ├── readme.md ├── resources └── views │ ├── analytics.blade.php │ └── feedback.blade.php ├── routes └── api.php └── src ├── Client └── HttpClient.php ├── Commands └── LarvaBugTestCommand.php ├── Facade └── LarvaBug.php ├── Handler ├── LarvaBugExceptionHandler.php └── PrepareExceptionData.php ├── Http └── Controllers │ └── LarvaBugMainController.php └── Provider ├── BootServices.php └── ServiceProvider.php /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "larvabug/larvabug-laravel", 3 | "description": "Larvabug monitoring", 4 | "require": { 5 | "php": ">=7.1", 6 | "illuminate/support": "5.0 - 5.8", 7 | "ext-curl": "*" 8 | }, 9 | "license": "MIT", 10 | "authors": [ 11 | { 12 | "name": "Larvabug", 13 | "email": "larvabugmonitor@gmail.com" 14 | } 15 | ], 16 | "autoload": { 17 | "psr-4": { 18 | "LarvaBug\\": "src/" 19 | } 20 | }, 21 | "extra": { 22 | "laravel": { 23 | "providers": [ 24 | "LarvaBug\\Provider\\ServiceProvider" 25 | ], 26 | "aliases": { 27 | "LarvaBug": "LarvaBug\\Facade" 28 | } 29 | } 30 | }, 31 | "minimum-stability": "dev" 32 | } 33 | -------------------------------------------------------------------------------- /config/larvabug.php: -------------------------------------------------------------------------------- 1 | env('LB_PROJECT_ID',''), 10 | 11 | /* 12 | * Project secret from larvabug.com 13 | * 14 | */ 15 | 'project_secret' => env('LB_SECRET',''), 16 | 17 | /* 18 | * Array of environments to enable error reporting 19 | * If environment configured in the array will match with the laravel app environment 20 | * then error will be reported to larvabug.com 21 | * 22 | */ 23 | 'environment' => ['production','local'], 24 | 25 | /* 26 | * Mention any error that should skip from reporting to laravbug 27 | * Must be mentioned as a string 28 | * 29 | */ 30 | 'skip_errors' => [ 31 | 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException', 32 | ], 33 | 34 | /* 35 | * Add request parameters to be black listed 36 | * any parameter defined here will not be reported to larvabug.com and 37 | * all request, session and cookies will be filtered 38 | * 39 | */ 40 | 'blacklist' => [ 41 | 'password' 42 | ] 43 | 44 | ]; -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | # LarvaBug 6 | Laravel 5.2+ package for logging errors to [larvabug.com](https://www.larvabug.com) 7 | 8 | [![Software License](https://poser.pugx.org/larvabug/larvabug-laravel/license.svg)](LICENSE.md) 9 | [![Latest Version on Packagist](https://poser.pugx.org/larvabug/larvabug-laravel/v/stable.svg)](https://packagist.org/packages/larvabug/larvabug-laravel) 10 | [![Total Downloads](https://poser.pugx.org/larvabug/larvabug-laravel/d/total.svg)](https://packagist.org/packages/larvabug/larvabug-laravel) 11 | 12 | 13 | ## Installation 14 | You can install the package through Composer. 15 | ```bash 16 | composer require larvabug/larvabug-laravel 17 | ``` 18 | 19 | Add the LarvaBug service provider and facade in config/app.php: 20 | ```php 21 | 22 | 'providers' => [ 23 | LarvaBug\Provider\ServiceProvider::class, 24 | ], 25 | 26 | 'aliases' => [ 27 | 'LarvaBug' => \LarvaBug\Facade\LarvaBug::class 28 | ], 29 | 30 | ``` 31 | Then publish the config file of the larvabug using artisan command. 32 | ```bash 33 | php artisan vendor:publish --provider="LarvaBug\Provider\ServiceProvider" 34 | ``` 35 | File (`config/larvabug.php`) contains all the configuration related to bug reporting. 36 | 37 | Note: by default production and local environments will report errors. To modify this edit your larvabug configuration environment array. 38 | 39 | ## Environment variables 40 | Need to define two environment variable and their values. 41 | 42 | ``` 43 | LB_PROJECT_ID= 44 | LB_SECRET= 45 | ``` 46 | Get these variable values under setting page of the project at [larvabug.com](https://www.larvabug.com) 47 | 48 | # Reporting unhandled exceptions 49 | 50 | Add larvabug reporting to `app/Exceptions/Handler.php` file of laravel. 51 | 52 | ```php 53 | public function report(Exception $exception) 54 | { 55 | LarvaBug::report($exception); 56 | parent::report($exception); 57 | } 58 | ``` 59 | 60 | # Reporting handled exceptions 61 | 62 | In case of handled exceptions, exceptions can be reported to larvabug by using `LarvaBug` facade: 63 | 64 | ```php 65 | try { 66 | //Code here 67 | }catch (\Exception $exception){ 68 | LarvaBug::report($exception); 69 | } 70 | ``` 71 | 72 | #Logging specific data 73 | 74 | To log specific data to LarvaBug use `log()` method of LarvaBug facade: 75 | 76 | ```php 77 | $metaData = ['custom_data' => ['x','y','z']]; //Array 78 | LarvaBug::log('Log message here',$metaData); 79 | ``` 80 | 81 | # User feedback 82 | 83 | LarvaBug provides the ability to collect feedback from user when an error occurs, 84 | LarvaBug shows feedback collection page and then feedback is added with the exception report, 85 | to enable this functionality simply need to add `collectFeedback()` method in `render()` method of `app/Exceptions/Handler.php` 86 | 87 | ```php 88 | public function render($request, Exception $exception) 89 | { 90 | if (LarvaBug::shouldCollectFeedback($exception) && !$request->wantsJson()) { 91 | return LarvaBug::collectFeedback(); 92 | } 93 | return parent::render($request, $exception); 94 | } 95 | ``` 96 | 97 | ## License 98 | The larvabug package is open source software licensed under the [license MIT](http://opensource.org/licenses/MIT) 99 | -------------------------------------------------------------------------------- /resources/views/analytics.blade.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/views/feedback.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 500 Server Error 4 | 5 | 309 | 310 |
311 |

500 :(

312 |

Seems Like we have an internal issue, Please tell us more to batter understand the issue

313 |
314 |
315 |
316 |
319 | 320 | 324 | 328 | 334 | 337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
    351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
363 |
364 |
365 |
366 |
367 |
    368 |
369 |
370 |
371 |
372 |
373 |
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 |
383 |
384 |
    385 |
386 |
387 |
388 |
389 |
390 |
391 |
392 |
393 |
394 |
395 |
396 |
397 |
398 |
399 |
400 |
401 |
    402 |
403 |
404 |
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 |
415 |
416 |
417 |
418 |
    419 |
420 |
421 |
422 |
423 |
424 |
425 |
426 |
427 |
428 |
429 |
430 |
431 |
432 |
433 |
434 |
435 |
    436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 |
444 | 445 | 446 | Powered By: LarvaBug 447 | 448 | 516 | 517 | 518 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | projectId = $projectId; 35 | $this->projectSecret = $projectSecret; 36 | } 37 | 38 | /** 39 | * Report error to larvabug website 40 | * 41 | * @param $exception 42 | */ 43 | public function report($exceptionData) 44 | { 45 | try { 46 | $data_string = json_encode($exceptionData); 47 | 48 | $result = $this->postRequest($data_string,self::POST_EXCEPTION); 49 | 50 | if ($result && 51 | isset($result['status']) && 52 | isset($result['exceptionId']) && 53 | $result['status'] == 200 54 | ){ 55 | app('larvabug')->setLastExceptionId($result['exceptionId']); 56 | } 57 | 58 | return true; 59 | }catch (\Exception $exception) { 60 | return false; 61 | } 62 | } 63 | 64 | /** 65 | * Validate env project id and secret 66 | * 67 | * @param array $credentials 68 | * @return bool 69 | * @author Syed Faisal 70 | */ 71 | public function validateCredentials(array $credentials) 72 | { 73 | $result = $this->postRequest(json_encode($credentials),self::VALIDATE_CREDENTIALS); 74 | 75 | if ($result && isset($result['status']) && $result['status'] == 200){ 76 | return true; 77 | } 78 | 79 | return false; 80 | 81 | } 82 | 83 | /** 84 | * Curl Request 85 | * 86 | * @param $requestData 87 | * @param $url 88 | * @return bool|mixed 89 | */ 90 | private function postRequest($requestData, $url) 91 | { 92 | $header = [ 93 | 'Content-Type:application/json', 94 | 'Authorization-APP:' . $this->projectId, 95 | 'Authorization-KEY:' . $this->projectSecret 96 | ]; 97 | 98 | $ch = curl_init($url); 99 | 100 | curl_setopt($ch, CURLOPT_POSTFIELDS, $requestData); 101 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 102 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 103 | 104 | $result = curl_exec($ch); 105 | 106 | curl_close($ch); 107 | 108 | if ($result) { 109 | return json_decode($result, true); 110 | } 111 | 112 | return false; 113 | } 114 | 115 | /** 116 | * Submit last exception feedback 117 | * 118 | * @param $data 119 | * @return bool 120 | */ 121 | public function submitFeedback($data) 122 | { 123 | $result = $this->postRequest(json_encode($data),self::POST_FEEDBACK); 124 | 125 | if ($result && isset($result['status']) && $result['status'] == 200){ 126 | return true; 127 | } 128 | 129 | return false; 130 | 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /src/Commands/LarvaBugTestCommand.php: -------------------------------------------------------------------------------- 1 | info('Testing LarvaBug Configurations'); 42 | 43 | if (env('LB_PROJECT_ID') && !is_null(env('LB_PROJECT_ID'))){ 44 | $this->info('1. ✓ [Larvabug] Found project id'); 45 | }else{ 46 | $this->info('1. ✗ [Larvabug] Could not find your project id, please set this in your .env'); 47 | } 48 | 49 | if (env('LB_SECRET') && !is_null(env('LB_SECRET'))){ 50 | $this->info('2. ✓ [Larvabug] Found secret key'); 51 | }else{ 52 | $this->info('2. ✗ [Larvabug] Could not find LarvaBug secret, please set this in your .env'); 53 | } 54 | 55 | $requestData = [ 56 | 'projectId' => env('LB_PROJECT_ID'), 57 | 'projectSecret' => env('LB_SECRET') 58 | ]; 59 | 60 | if (app('larvabug') && app('larvabug')->validateCredentials($requestData)){ 61 | $this->info('3. ✓ [Larvabug] Validation Success'); 62 | }else{ 63 | $this->info('3. ✗ [Larvabug] Project id and secret do not match our records'); 64 | } 65 | 66 | try{ 67 | throw new \Exception('Larvabug Test Exception'); 68 | }catch (\Exception $exception){ 69 | LarvaBug::report($exception); 70 | } 71 | 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /src/Facade/LarvaBug.php: -------------------------------------------------------------------------------- 1 | client = $client; 39 | $this->exceptionData = $exceptionData; 40 | } 41 | 42 | /** 43 | * Report exception to larvabug 44 | * 45 | * @param \Throwable $exception 46 | * @return bool 47 | */ 48 | public function report(\Throwable $exception) 49 | { 50 | try { 51 | if (!$this->checkAppEnvironment()) { 52 | return false; 53 | } 54 | 55 | if ($this->skipError(get_class($exception))) { 56 | return false; 57 | } 58 | 59 | $data = $this->exceptionData->prepareException($exception); 60 | 61 | $this->client->report($data); 62 | 63 | return true; 64 | }catch (\Exception $exception){ 65 | Log::info('Lavabug Exception :'.$exception->getMessage()); 66 | return false; 67 | } 68 | } 69 | 70 | /** 71 | * Log details to larvabug 72 | * 73 | * @param $message 74 | * @param array $meta 75 | * @return bool 76 | */ 77 | public function log($message, array $meta = []) 78 | { 79 | try { 80 | $data = $this->exceptionData->prepareLogData($message, $meta); 81 | 82 | $this->client->report($data); 83 | 84 | return true; 85 | }catch (\Exception $exception){ 86 | Log::info('Lavabug Exception :'.$exception->getMessage()); 87 | return false; 88 | } 89 | } 90 | 91 | /** 92 | * Check if larvabug environment configurations match with app environment 93 | * 94 | * @return bool 95 | */ 96 | private function checkAppEnvironment() 97 | { 98 | if (!config('larvabug.environment')){ 99 | return false; 100 | } 101 | 102 | if (is_array(config('larvabug.environment'))){ 103 | if (count(config('larvabug.environment')) == 0){ 104 | return false; 105 | } 106 | 107 | if (in_array(App::environment(),config('larvabug.environment'))){ 108 | return true; 109 | } 110 | } 111 | 112 | return false; 113 | } 114 | 115 | /** 116 | * Error dont report, configured in config file 117 | * 118 | * @param $class 119 | * @return bool 120 | */ 121 | private function skipError($class) 122 | { 123 | if (in_array($class,config('larvabug.skip_errors'))){ 124 | return true; 125 | } 126 | 127 | return false; 128 | } 129 | 130 | public function shouldCollectFeedback(\Exception $exception) 131 | { 132 | return !$this->skipError(get_class($exception)); 133 | } 134 | 135 | /** 136 | * Validate env credentials from larvabug 137 | * 138 | * @param array $credentials 139 | * @return bool 140 | */ 141 | public function validateCredentials(array $credentials) 142 | { 143 | return $this->client->validateCredentials($credentials); 144 | } 145 | 146 | /** 147 | * Collect error feedback from user 148 | * 149 | * @return \Illuminate\Foundation\Application|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector 150 | */ 151 | public function collectFeedback() 152 | { 153 | if ($this->lastExceptionId) { 154 | return redirect($this->feedbackUrl().'?exceptionId='.$this->lastExceptionId); 155 | } 156 | 157 | return redirect('/'); 158 | } 159 | 160 | /** 161 | * Get feedback url 162 | * 163 | * @return mixed 164 | * @author Syed Faisal 165 | */ 166 | public function feedbackUrl() 167 | { 168 | return URL::to('larvabug-api/collect/feedback'); 169 | } 170 | 171 | /** 172 | * Submit user collected feedback 173 | * 174 | * @param $data 175 | * @return bool 176 | */ 177 | public function submitFeedback($data) 178 | { 179 | $this->client->submitFeedback($data); 180 | 181 | return true; 182 | } 183 | 184 | public function setLastExceptionId(string $exceptionId) 185 | { 186 | return $this->lastExceptionId = $exceptionId; 187 | } 188 | 189 | public function getLastExceptionId() 190 | { 191 | return $this->lastExceptionId; 192 | } 193 | 194 | } -------------------------------------------------------------------------------- /src/Handler/PrepareExceptionData.php: -------------------------------------------------------------------------------- 1 | blacklist = config('larvabug.blackList') ?? []; 22 | } 23 | 24 | /** 25 | * return prepared exception data 26 | * 27 | * @author Syed Faisal 28 | * @param \Throwable $exception 29 | */ 30 | public function prepareException(\Throwable $exception) 31 | { 32 | $data = $this->getRequestInfo($exception); 33 | 34 | $data['exception'] = $exception->getMessage(); 35 | $data['class'] = get_class($exception); 36 | $data['file'] = $exception->getFile(); 37 | $data['line'] = $exception->getLine(); 38 | $data['error'] = $exception->getTraceAsString(); 39 | $data['trace_with_details'] = $this->prepareTraceData($exception->getTrace()); 40 | 41 | $count = config('larvabug.lines_count'); 42 | 43 | if (!$count || $count > 12) { 44 | $count = 10; 45 | } 46 | 47 | $lines = file($data['file']); 48 | $data['executor'] = []; 49 | 50 | for ($i = -1 * abs($count); $i <= abs($count); $i++) { 51 | $data['executor'][] = $this->getLineInfo($lines, $data['line'], $i); 52 | } 53 | 54 | $data['executor'] = array_filter($data['executor']); 55 | 56 | // to make symfony exception more readable 57 | if ($data['class'] == 'Symfony\Component\Debug\Exception\FatalErrorException') { 58 | preg_match("~^(.+)' in ~", $data['exception'], $matches); 59 | if (isset($matches[1])) { 60 | $data['exception'] = $matches[1]; 61 | } 62 | } 63 | 64 | return $data; 65 | } 66 | 67 | public function prepareLogData(string $message,array $meta = []) 68 | { 69 | $data = $this->getRequestInfo(); 70 | $data['exception'] = $message; 71 | $data['class'] = 'Log Information'; 72 | $data['type'] = 'log'; 73 | $data['meta_data'] = $meta; 74 | 75 | return $data; 76 | 77 | } 78 | 79 | /** 80 | * Prepare All exception data 81 | * 82 | * @param \Throwable $exception 83 | * @return array 84 | */ 85 | private function getRequestInfo() 86 | { 87 | $data = []; 88 | 89 | $data['php_version'] = PHP_VERSION; 90 | $data['server_ip'] = $_SERVER['SERVER_ADDR'] ?? null; 91 | $data['environment'] = App::environment(); 92 | $data['server_name'] = @gethostname(); 93 | $data['browser'] = $this->getUserBrowser(); 94 | $data['userOs'] = $this->getUserOS(); 95 | $data['host'] = Request::server('SERVER_NAME'); 96 | $data['method'] = Request::method(); 97 | $data['fullUrl'] = Request::fullUrl(); 98 | $data['url'] = Request::path(); 99 | $data['userIp'] = Request::ip(); 100 | $data['date_time'] = date("Y-m-d H:i:s"); 101 | $data['session_id'] = Session::getId(); 102 | $data['storage'] = [ 103 | 'SERVER' => [ 104 | 'USER' => Request::server('USER'), 105 | 'HTTP_USER_AGENT' => Request::server('HTTP_USER_AGENT'), 106 | 'SERVER_PROTOCOL' => Request::server('SERVER_PROTOCOL'), 107 | 'SERVER_SOFTWARE' => Request::server('SERVER_SOFTWARE'), 108 | 'PHP_VERSION' => PHP_VERSION 109 | ], 110 | 'GET' => $this->filterBlackList(Request::query()), 111 | 'POST' => $this->filterBlackList($_POST), 112 | 'FILE' => Request::file(), 113 | 'OLD' => $this->filterBlackList(Request::hasSession() ? Request::old() : []), 114 | 'COOKIE' => $this->filterBlackList(Request::cookie()), 115 | 'SESSION' => $this->filterBlackList(Request::hasSession() ? Session::all() : []), 116 | 'HEADERS' => $this->filterBlackList(Request::header()), 117 | ]; 118 | $data['auth_user'] = $this->getAuthUser(); 119 | $data['storage'] = array_filter($data['storage']); 120 | 121 | return $data; 122 | } 123 | 124 | /** 125 | * Filter black listed keys 126 | * 127 | * @param $variables 128 | * @return array 129 | */ 130 | private function filterBlackList($variables) 131 | { 132 | if (is_array($variables)) { 133 | array_walk($variables, function ($val, $key) use (&$variables) { 134 | if (is_array($val)) { 135 | $variables[$key] = $this->filterBlackList($val); 136 | } 137 | if (in_array(strtolower($key), $this->blacklist)) { 138 | unset($variables[$key]); 139 | } 140 | }); 141 | return $variables; 142 | } 143 | return []; 144 | } 145 | 146 | /** 147 | * Prepare Trace data with line details 148 | * 149 | * @param $trace 150 | * @return array 151 | */ 152 | private function prepareTraceData($trace): array 153 | { 154 | $count = 5; 155 | $response = []; 156 | 157 | foreach ($trace as $file) 158 | { 159 | if (isset($file['file']) && isset($file['line'])){ 160 | $lines = file($file['file']); 161 | $data = []; 162 | 163 | for ($i = -1 * abs($count); $i <= abs($count); $i++) { 164 | $data[] = $this->getLineInfo($lines, $file['line'], $i); 165 | } 166 | $data = array_filter($data); 167 | 168 | $response[] = [ 169 | 'trace' => $file, 170 | 'content' => $data 171 | ]; 172 | } 173 | } 174 | 175 | return $response; 176 | } 177 | 178 | /** 179 | * get auth user if exists 180 | * 181 | * @return |null 182 | */ 183 | private function getAuthUser() 184 | { 185 | if (function_exists('auth') && auth()->check()) { 186 | return auth()->user()->toArray(); 187 | } 188 | 189 | if (class_exists(\Cartalyst\Sentinel\Sentinel::class) && $user = Sentinel::check()) { 190 | return $user->toArray(); 191 | } 192 | 193 | return null; 194 | } 195 | 196 | 197 | /** 198 | * Gets information from the line 199 | * 200 | * @param $lines 201 | * @param $line 202 | * @param $i 203 | * 204 | * @return array|void 205 | */ 206 | private function getLineInfo($lines, $line, $i) 207 | { 208 | $currentLine = $line + $i; 209 | 210 | $index = $currentLine - 1; 211 | 212 | if (!array_key_exists($index, $lines)) { 213 | return; 214 | } 215 | return [ 216 | 'line_number' => $currentLine, 217 | 'line' => $lines[$index] 218 | ]; 219 | } 220 | 221 | /** 222 | * Get Request User Browser 223 | * 224 | * @return string 225 | */ 226 | private function getUserBrowser() 227 | { 228 | 229 | $fullUserBrowser = (!empty($_SERVER['HTTP_USER_AGENT'])? 230 | $_SERVER['HTTP_USER_AGENT']:getenv('HTTP_USER_AGENT')); 231 | $userBrowser = explode(')', $fullUserBrowser); 232 | $userBrowser = $userBrowser[count($userBrowser)-1]; 233 | 234 | if((!$userBrowser || $userBrowser === '' || $userBrowser === ' ' || strpos($userBrowser, 'like Gecko') === 1) && strpos($fullUserBrowser, 'Windows') !== false){ 235 | return 'Internet Explorer'; 236 | }else if((strpos($userBrowser, 'Edge/') !== false || strpos($userBrowser, 'Edg/') !== false) && strpos($fullUserBrowser, 'Windows') !== false){ 237 | return 'Microsoft Edge'; 238 | }else if(strpos($userBrowser, 'Chrome/') === 1 || strpos($userBrowser, 'CriOS/') === 1){ 239 | return 'Chrome'; 240 | }else if(strpos($userBrowser, 'Firefox/') !== false || strpos($userBrowser, 'FxiOS/') !== false){ 241 | return 'Mozilla Firefox'; 242 | }else if(strpos($userBrowser, 'Safari/') !== false && strpos($fullUserBrowser, 'Mac') !== false){ 243 | return 'Safari'; 244 | }else if(strpos($userBrowser, 'OPR/') !== false && strpos($fullUserBrowser, 'Opera Mini') !== false){ 245 | return 'Opera Mini'; 246 | }else if(strpos($userBrowser, 'OPR/') !== false){ 247 | return 'Opera'; 248 | } 249 | 250 | return null; 251 | } 252 | 253 | /** 254 | * Get request user Operating System 255 | * 256 | * @return string 257 | */ 258 | private function getUserOS(): string 259 | { 260 | 261 | $user_agent = \request()->header('User-Agent'); 262 | 263 | $os_platform = "Unknown OS Platform"; 264 | 265 | $os_array = array( 266 | '/windows nt 10/i' => 'Windows 10', 267 | '/windows nt 6.3/i' => 'Windows 8.1', 268 | '/windows nt 6.2/i' => 'Windows 8', 269 | '/windows nt 6.1/i' => 'Windows 7', 270 | '/windows nt 6.0/i' => 'Windows Vista', 271 | '/windows nt 5.2/i' => 'Windows Server 2003/XP x64', 272 | '/windows nt 5.1/i' => 'Windows XP', 273 | '/windows xp/i' => 'Windows XP', 274 | '/windows nt 5.0/i' => 'Windows 2000', 275 | '/windows me/i' => 'Windows ME', 276 | '/win98/i' => 'Windows 98', 277 | '/win95/i' => 'Windows 95', 278 | '/win16/i' => 'Windows 3.11', 279 | '/macintosh|mac os x/i' => 'Mac OS X', 280 | '/mac_powerpc/i' => 'Mac OS 9', 281 | '/linux/i' => 'Linux', 282 | '/ubuntu/i' => 'Ubuntu', 283 | '/iphone/i' => 'iPhone', 284 | '/ipod/i' => 'iPod', 285 | '/ipad/i' => 'iPad', 286 | '/android/i' => 'Android', 287 | '/blackberry/i' => 'BlackBerry', 288 | '/webos/i' => 'Mobile' 289 | ); 290 | 291 | foreach ($os_array as $regex => $value) 292 | if (preg_match($regex, $user_agent)) 293 | $os_platform = $value; 294 | 295 | return $os_platform; 296 | } 297 | 298 | 299 | 300 | } -------------------------------------------------------------------------------- /src/Http/Controllers/LarvaBugMainController.php: -------------------------------------------------------------------------------- 1 | submitFeedback($data); 23 | 24 | return Redirect::to('/'); 25 | } 26 | 27 | /** 28 | * Collect feedback view 29 | * 30 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\Foundation\Application|\Illuminate\View\View 31 | */ 32 | public function postFeedback() 33 | { 34 | return view('larvabug::feedback'); 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /src/Provider/BootServices.php: -------------------------------------------------------------------------------- 1 | publishConfig(); 27 | $this->registerView(); 28 | $this->registerCommands(); 29 | $this->mapLaraBugApiRoutes(); 30 | } 31 | 32 | /** 33 | * Register view directory with larvabug namespace 34 | */ 35 | private function registerView() 36 | { 37 | $this->app['view']->addNamespace('larvabug',__DIR__.'/../../resources/views'); 38 | } 39 | 40 | /** 41 | * Map api routes directory to enable all api routes for larvabug 42 | */ 43 | private function mapLaraBugApiRoutes() 44 | { 45 | Route::namespace('\LarvaBug\Http\Controllers') 46 | ->prefix('larvabug-api') 47 | ->group(__DIR__ . '/../../routes/api.php'); 48 | } 49 | 50 | /** 51 | * Publish package config files that contains package configurations 52 | */ 53 | private function publishConfig() 54 | { 55 | if (function_exists('config_path')) { 56 | $this->publishes([ 57 | __DIR__ . '/../../config/larvabug.php' => config_path('larvabug.php'), 58 | ]); 59 | } 60 | } 61 | 62 | /** 63 | * Register array of commands 64 | */ 65 | private function registerCommands() 66 | { 67 | $this->commands($this->commands); 68 | } 69 | } -------------------------------------------------------------------------------- /src/Provider/ServiceProvider.php: -------------------------------------------------------------------------------- 1 | bootServices(); 22 | } 23 | 24 | /** 25 | * Register method of service provider 26 | */ 27 | public function register() 28 | { 29 | $this->app->singleton('larvabug',function ($app){ 30 | $this->mergeConfigFrom(__DIR__ . '/../../config/larvabug.php', 'larvabug'); 31 | return new LarvaBugExceptionHandler( 32 | new HttpClient( 33 | config('larvabug.project_id'), 34 | config('larvabug.project_secret') 35 | ), 36 | new PrepareExceptionData() 37 | ); 38 | }); 39 | } 40 | 41 | 42 | } --------------------------------------------------------------------------------