Commit c41fb75e authored by Tomáš Pospíšil's avatar Tomáš Pospíšil
Browse files

Error counts

parent c08ab507
......@@ -20,6 +20,8 @@
"tracy/tracy": "^2.7",
"nette/utils": "^3.0",
"smarty/smarty": "^3.1",
"ext-pdo": "*"
"ext-pdo": "*",
"ext-dom": "*",
"voku/arrayy": "^7.4"
}
}
......@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4025776c3ad17438001b07401afee348",
"content-hash": "ed8c4ab4c912eb1aa46e5aa4c8da2547",
"packages": [
{
"name": "nette/utils",
......@@ -132,6 +132,157 @@
],
"time": "2019-09-30T09:25:56+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jaap van Otterdijk",
"email": "opensource@ijaap.nl"
}
],
"description": "Common reflection classes used by phpdocumentor to reflect the code structure",
"homepage": "http://www.phpdoc.org",
"keywords": [
"FQSEN",
"phpDocumentor",
"phpdoc",
"reflection",
"static analysis"
],
"time": "2018-08-07T13:53:10+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
"version": "5.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
"reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e",
"shasum": ""
},
"require": {
"ext-filter": "^7.1",
"php": "^7.2",
"phpdocumentor/reflection-common": "^2.0",
"phpdocumentor/type-resolver": "^1.0",
"webmozart/assert": "^1"
},
"require-dev": {
"doctrine/instantiator": "^1",
"mockery/mockery": "^1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
},
{
"name": "Jaap van Otterdijk",
"email": "account@ijaap.nl"
}
],
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
"time": "2020-02-22T12:28:44+00:00"
},
{
"name": "phpdocumentor/type-resolver",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
"reference": "7462d5f123dfc080dfdf26897032a6513644fc95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95",
"reference": "7462d5f123dfc080dfdf26897032a6513644fc95",
"shasum": ""
},
"require": {
"php": "^7.2",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "^7.2",
"mockery/mockery": "~1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"phpDocumentor\\Reflection\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mike van Riel",
"email": "me@mikevanriel.com"
}
],
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"time": "2020-02-18T18:59:58+00:00"
},
{
"name": "smarty/smarty",
"version": "v3.1.34",
......@@ -188,6 +339,151 @@
],
"time": "2019-02-28T06:42:20+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-ctype": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Ctype\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Gert de Pagter",
"email": "BackEndTea@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for ctype functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"ctype",
"polyfill",
"portable"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.15.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
"name": "tracy/tracy",
"version": "v2.7.3",
......@@ -260,6 +556,132 @@
"profiler"
],
"time": "2020-02-23T18:40:15+00:00"
},
{
"name": "voku/arrayy",
"version": "7.4.0",
"source": {
"type": "git",
"url": "https://github.com/voku/Arrayy.git",
"reference": "d88aef2e5dfd72e7a9582e269faa36a3f1c5a5b7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/voku/Arrayy/zipball/d88aef2e5dfd72e7a9582e269faa36a3f1c5a5b7",
"reference": "d88aef2e5dfd72e7a9582e269faa36a3f1c5a5b7",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": ">=7.0.0",
"phpdocumentor/reflection-docblock": "~4.3|~5.0",
"symfony/polyfill-mbstring": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~6.0 || ~7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Arrayy\\": "src/"
},
"files": [
"src/Create.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Lars Moelleken",
"email": "lars@moelleken.org",
"homepage": "http://www.moelleken.org/",
"role": "Maintainer"
}
],
"description": "Array manipulation library for PHP, called Arrayy!",
"keywords": [
"Arrayy",
"array",
"helpers",
"manipulation",
"methods",
"utility",
"utils"
],
"funding": [
{
"url": "https://www.paypal.me/moelleken",
"type": "custom"
},
{
"url": "https://github.com/voku",
"type": "github"
},
{
"url": "https://opencollective.com/arrayy",
"type": "open_collective"
},
{
"url": "https://www.patreon.com/voku",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/voku/arrayy",
"type": "tidelift"
}
],
"time": "2020-03-22T02:08:24+00:00"
},
{
"name": "webmozart/assert",
"version": "1.7.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598",
"shasum": ""
},
"require": {
"php": "^5.3.3 || ^7.0",
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"vimeo/psalm": "<3.6.0"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13"
},
"type": "library",
"autoload": {
"psr-4": {
"Webmozart\\Assert\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Bernhard Schussek",
"email": "bschussek@gmail.com"
}
],
"description": "Assertions to validate method input/output with nice error messages.",
"keywords": [
"assert",
"check",
"validate"
],
"time": "2020-02-14T12:15:55+00:00"
}
],
"packages-dev": [],
......@@ -270,7 +692,8 @@
"prefer-lowest": false,
"platform": {
"php": "^7.1",
"ext-pdo": "*"
"ext-pdo": "*",
"ext-dom": "*"
},
"platform-dev": [],
"plugin-api-version": "1.1.0"
......
......@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Praguebest\BarPanel;
use Praguebest\Tools\ErrorFilesParser;
use Smarty;
use SmartyException;
use Tracy\IBarPanel;
......@@ -15,18 +16,6 @@ final class ErrorCountBar implements IBarPanel
* @var Smarty
*/
private $smarty;
/**
* @var string
*/
private $errorDir;
/**
* @var array
*/
private $errors;
/**
* @var array
*/
private $infos;
/**
* ErrorCountBar constructor.
......@@ -36,25 +25,25 @@ final class ErrorCountBar implements IBarPanel
public function __construct(string $errorDir, Smarty $smarty)
{
$this->smarty = $smarty;
$this->errorDir = $errorDir;
foreach ([ILogger::CRITICAL, ILogger::EXCEPTION, ILogger::ERROR, ILogger::WARNING] as $errorCode) {
$this->errors[$errorCode] = $this->countFiles($errorCode);
}
$parser = new ErrorFilesParser();
foreach ([ILogger::DEBUG, ILogger::INFO] as $errorCode) {
$this->infos[$errorCode] = $this->countFiles($errorCode);
}
}
$errors = $parser->parse($errorDir);
private function countFiles(string $string): int
{
$files = glob($this->errorDir . DIRECTORY_SEPARATOR . $string . '*.html');
if ($files) {
return count($files);
}
$this->smarty->assign('errors', $errors);
$this->smarty->assign(
'criticals',
$errors->filterBy('type', [ILogger::CRITICAL, ILogger::EXCEPTION, ILogger::ERROR, ErrorFilesParser::UNKNOWN])->count()
);
return 0;
$this->smarty->assign(
'warnings',
$errors->filterBy('type', ILogger::WARNING)->count()
);
$this->smarty->assign(
'infos',
$errors->filterBy('type', [ILogger::DEBUG, ILogger::INFO])->count()
);
}
/**
......@@ -64,10 +53,6 @@ final class ErrorCountBar implements IBarPanel
*/
public function getPanel(): string
{
$this->smarty->assign('errorCount', array_sum($this->errors));
$this->smarty->assign('errors', $this->errors);
$this->smarty->assign('infos', $this->infos);
return $this->smarty->fetch(dirname(__DIR__) . '/templates/errorCount/errors.tpl');
}
......@@ -78,8 +63,7 @@ final class ErrorCountBar implements IBarPanel
*/
public function getTab(): string
{
$this->smarty->assign('errorCount', array_sum($this->errors));
return $this->smarty->fetch(dirname(__DIR__) . '/templates/errorCount/tab.tpl');
}
}
<?php
declare(strict_types=1);
namespace Praguebest\Tools;
use Arrayy\Arrayy;
use Nette\Utils\Strings;
use Tracy\Helpers;
final class ErrorFilesParser
{
public const UNKNOWN = 'unknown';
/**
* @var Arrayy
*/
private $errors;
public function __construct()
{
$this->errors = new Arrayy();
}
public function parse(string $errorDir): Arrayy
{
$pattern = realpath($errorDir . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . '*--*.html';
$files = glob($pattern);
foreach ($files as $file) {
$this->processFile($file);
}
$this->errors = $this->errors->sorter('time');
return $this->errors;
}
private function processFile(string $filename): void
{
$type = $this->getType($filename);
$fileContent = $this->getFileContent($filename);
$fileContent = Strings::replace($fileContent, '/[\t\n\r]/', '');
$fileContent = Strings::replace($fileContent, '/ /', ' ');
$fileContent = Strings::normalize($fileContent);
$message = Strings::match(
$fileContent,
'#<title>(?<message>.*)<\/title>.*?(<!-- in (?<location>.*):(?<row>\d*) -->).?.*#'
);
$this->errors->append(
[
'time' => filectime($filename) ?? 0,
'type' => $type,
'message' => Strings::truncate($message['message'] ?? '', 200),
'link' => Helpers::editorLink($message['location'] ?? '', (int)$message['row']),
]
);
}
/**
* @param string $filename
* @return string
*/
private function getType(string $filename): string
{
$type = (string)Strings::match(basename($filename), '#(.*?)-.*#')[1];
if (!isset($this->errors[$type])) {
$type = self::UNKNOWN;
}
return $type;
}
/**
* @param string $filename
* @return false|string
*/
private function getFileContent(string $filename): string
{
$handle = fopen($filename, 'rb');
if (false === $handle) {
return '';
}
fseek($handle, 297);
$message = $content = '';
$iterations = 0;
while (!feof($handle) && !Strings::contains($content, ' -->') && $iterations < 5) {
$content = fread(