diff --git a/.github/workflows/static-analysis.yml b/.github/workflows/static-analysis.yml index 1b855cdb7..396244b28 100644 --- a/.github/workflows/static-analysis.yml +++ b/.github/workflows/static-analysis.yml @@ -10,7 +10,7 @@ jobs: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.1 coverage: none - run: composer install --no-progress --prefer-dist diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 71bbf0ccf..9251d57c6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - php: ['8.0', '8.1', '8.2', '8.3', '8.4'] + php: ['8.1', '8.2', '8.3', '8.4'] sapi: ['php', 'php-cgi'] fail-fast: false @@ -41,7 +41,7 @@ jobs: - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: - php-version: 8.0 + php-version: 8.1 extensions: ds coverage: none diff --git a/composer.json b/composer.json index 2ff2d3824..ae170c629 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ } ], "require": { - "php": "8.0 - 8.4", + "php": "8.1 - 8.4", "ext-session": "*", "ext-json": "*" }, @@ -43,7 +43,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.10-dev" + "dev-master": "3.0-dev" } } } diff --git a/readme.md b/readme.md index bacf2aee9..23477b665 100644 --- a/readme.md +++ b/readme.md @@ -48,7 +48,7 @@ composer require tracy/tracy Alternatively, you can download the whole package or [tracy.phar](https://github.com/nette/tracy/releases) file. -Tracy is compatible with PHP 8.0 to 8.4. +Tracy is compatible with PHP 8.1 to 8.4.   @@ -456,5 +456,6 @@ This is a list of unofficial integrations to other frameworks and CMS: - [Slim Framework](https://github.com/runcmf/runtracy) - Symfony framework: [kutny/tracy-bundle](https://github.com/kutny/tracy-bundle), [VasekPurchart/Tracy-Blue-Screen-Bundle](https://github.com/VasekPurchart/Tracy-Blue-Screen-Bundle) - [Wordpress](https://github.com/ktstudio/WP-Tracy) +- [Joomla! CMS](https://n3t.bitbucket.io/extension/n3t-debug/) ... feel free to be famous, create an integration for your favourite platform! diff --git a/src/Bridges/Nette/Bridge.php b/src/Bridges/Nette/Bridge.php index b79624531..d984a6c69 100644 --- a/src/Bridges/Nette/Bridge.php +++ b/src/Bridges/Nette/Bridge.php @@ -9,7 +9,6 @@ namespace Tracy\Bridges\Nette; -use Latte; use Nette; use Tracy; use Tracy\BlueScreen; @@ -17,87 +16,18 @@ /** - * Bridge for NEON & Latte. + * Bridge for NEON. */ class Bridge { public static function initialize(): void { $blueScreen = Tracy\Debugger::getBlueScreen(); - if (!class_exists(Latte\Bridges\Tracy\BlueScreenPanel::class)) { - $blueScreen->addPanel([self::class, 'renderLatteError']); - $blueScreen->addAction([self::class, 'renderLatteUnknownMacro']); - $blueScreen->addFileGenerator(fn(string $file) => substr($file, -6) === '.latte' - ? "{block content}\n\$END\$" - : null); - Tracy\Debugger::addSourceMapper([self::class, 'mapLatteSourceCode']); - } - $blueScreen->addAction([self::class, 'renderMemberAccessException']); $blueScreen->addPanel([self::class, 'renderNeonError']); } - public static function renderLatteError(?\Throwable $e): ?array - { - if ($e instanceof Latte\CompileException && $e->sourceName) { - return [ - 'tab' => 'Template', - 'panel' => (preg_match('#\n|\?#', $e->sourceName) - ? '' - : '

' - . (@is_file($e->sourceName) // @ - may trigger error - ? 'File: ' . Helpers::editorLink($e->sourceName, $e->sourceLine) - : '' . htmlspecialchars($e->sourceName . ($e->sourceLine ? ':' . $e->sourceLine : '')) . '') - . '

') - . BlueScreen::highlightFile($e->sourceCode, $e->sourceLine, php: false), - ]; - } - - return null; - } - - - public static function renderLatteUnknownMacro(?\Throwable $e): ?array - { - if ( - $e instanceof Latte\CompileException - && $e->sourceName - && @is_file($e->sourceName) // @ - may trigger error - && (preg_match('#Unknown macro (\{\w+)\}, did you mean (\{\w+)\}\?#A', $e->getMessage(), $m) - || preg_match('#Unknown attribute (n:\w+), did you mean (n:\w+)\?#A', $e->getMessage(), $m)) - ) { - return [ - 'link' => Helpers::editorUri($e->sourceName, $e->sourceLine, 'fix', $m[1], $m[2]), - 'label' => 'fix it', - ]; - } - - return null; - } - - - /** @return array{file: string, line: int, label: string, active: bool} */ - public static function mapLatteSourceCode(string $file, int $line): ?array - { - if (!strpos($file, '.latte--')) { - return null; - } - - $lines = file($file); - if ( - !preg_match('#^/(?:\*\*|/) source: (\S+\.latte)#m', implode('', array_slice($lines, 0, 10)), $m) - || !@is_file($m[1]) // @ - may trigger error - ) { - return null; - } - - $file = $m[1]; - $line = $line && preg_match('#/\* line (\d+) \*/#', $lines[$line - 1], $m) ? (int) $m[1] : 0; - return ['file' => $file, 'line' => $line, 'label' => 'Latte', 'active' => true]; - } - - public static function renderMemberAccessException(?\Throwable $e): ?array { if (!$e instanceof Nette\MemberAccessException && !$e instanceof \LogicException) { diff --git a/src/Bridges/Nette/TracyExtension.php b/src/Bridges/Nette/TracyExtension.php index 3f0c6ac2b..809ef50e4 100644 --- a/src/Bridges/Nette/TracyExtension.php +++ b/src/Bridges/Nette/TracyExtension.php @@ -130,7 +130,7 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class): void if ($this->debugMode) { foreach ($this->config->bar as $item) { if (is_string($item) && substr($item, 0, 1) === '@') { - $item = new Statement(['@' . $builder::THIS_CONTAINER, 'getService'], [substr($item, 1)]); + $item = new Statement(['@' . $builder::ThisContainer, 'getService'], [substr($item, 1)]); } elseif (is_string($item)) { $item = new Statement($item); } diff --git a/src/Tracy/Bar/panels/errors.panel.phtml b/src/Tracy/Bar/panels/warnings.panel.phtml similarity index 100% rename from src/Tracy/Bar/panels/errors.panel.phtml rename to src/Tracy/Bar/panels/warnings.panel.phtml diff --git a/src/Tracy/Bar/panels/errors.tab.phtml b/src/Tracy/Bar/panels/warnings.tab.phtml similarity index 92% rename from src/Tracy/Bar/panels/errors.tab.phtml rename to src/Tracy/Bar/panels/warnings.tab.phtml index 70b0a53ed..baef3e1cf 100644 --- a/src/Tracy/Bar/panels/errors.tab.phtml +++ b/src/Tracy/Bar/panels/warnings.tab.phtml @@ -10,7 +10,7 @@ if (empty($data)) { } ?> - + 1 ? ' warnings' : ' warning' ?> diff --git a/src/Tracy/Debugger/Debugger.php b/src/Tracy/Debugger/Debugger.php index 0b608cbe3..0bdc91819 100644 --- a/src/Tracy/Debugger/Debugger.php +++ b/src/Tracy/Debugger/Debugger.php @@ -17,7 +17,7 @@ */ class Debugger { - public const Version = '2.10.10'; + public const Version = '3.0-dev'; /** server modes for Debugger::enable() */ public const @@ -27,19 +27,19 @@ class Debugger public const CookieSecret = 'tracy-debug'; - /** @deprecated use Debugger::Version */ + #[\Deprecated('use Debugger::Version')] public const VERSION = self::Version; - /** @deprecated use Debugger::Development */ + #[\Deprecated('use Debugger::Development')] public const DEVELOPMENT = self::Development; - /** @deprecated use Debugger::Production */ + #[\Deprecated('use Debugger::Production')] public const PRODUCTION = self::Production; - /** @deprecated use Debugger::Detect */ + #[\Deprecated('use Debugger::Detect')] public const DETECT = self::Detect; - /** @deprecated use Debugger::CookieSecret */ + #[\Deprecated('use Debugger::CookieSecret')] public const COOKIE_SECRET = self::CookieSecret; /** in production mode is suppressed any debugging output */ @@ -93,7 +93,7 @@ class Debugger /** theme for dump() */ public static string $dumpTheme = 'light'; - /** @deprecated */ + #[\Deprecated] public static $maxLen; /********************* logging ****************d*g**/ @@ -408,7 +408,7 @@ public static function getBar(): Bar self::$bar = new Bar; self::$bar->addPanel($info = new DefaultBarPanel('info'), 'Tracy:info'); $info->cpuUsage = self::$cpuUsage; - self::$bar->addPanel(new DefaultBarPanel('errors'), 'Tracy:errors'); // filled by errorHandler() + self::$bar->addPanel(new DefaultBarPanel('warnings'), 'Tracy:warnings'); // filled by errorHandler() } return self::$bar; diff --git a/src/Tracy/Debugger/DevelopmentStrategy.php b/src/Tracy/Debugger/DevelopmentStrategy.php index e53cb791d..ef53aef07 100644 --- a/src/Tracy/Debugger/DevelopmentStrategy.php +++ b/src/Tracy/Debugger/DevelopmentStrategy.php @@ -90,7 +90,7 @@ public function handleError( } $message = Helpers::errorTypeToString($severity) . ': ' . Helpers::improveError($message); - $count = &$this->bar->getPanel('Tracy:errors')->data["$file|$line|$message"]; + $count = &$this->bar->getPanel('Tracy:warnings')->data["$file|$line|$message"]; if (!$count++ && !Helpers::isHtmlMode() && !Helpers::isAjax()) { echo "\n$message in $file on line $line\n"; diff --git a/src/Tracy/Debugger/ProductionStrategy.php b/src/Tracy/Debugger/ProductionStrategy.php index fb8f6d398..a9718d193 100644 --- a/src/Tracy/Debugger/ProductionStrategy.php +++ b/src/Tracy/Debugger/ProductionStrategy.php @@ -63,7 +63,7 @@ public function handleError( $err = 'PHP ' . Helpers::errorTypeToString($severity) . ': ' . Helpers::improveError($message) . " in $file:$line"; } - Debugger::tryLog($err, Debugger::ERROR); + Debugger::tryLog($err, Debugger::WARNING); } diff --git a/src/Tracy/Logger/Logger.php b/src/Tracy/Logger/Logger.php index 0f9fd0c63..1fb4099c2 100644 --- a/src/Tracy/Logger/Logger.php +++ b/src/Tracy/Logger/Logger.php @@ -15,23 +15,22 @@ */ class Logger implements ILogger { - /** @var string|null name of the directory where errors should be logged */ - public $directory; + /** name of the directory where errors should be logged */ + public ?string $directory = null; - /** @var string|array|null email or emails to which send error notifications */ - public $email; + /** email or emails to which send error notifications */ + public string|array|null $email = null; - /** @var string|null sender of email notifications */ - public $fromEmail; + /** sender of email notifications */ + public ?string $fromEmail = null; - /** @var mixed interval for sending email is 2 days */ - public $emailSnooze = '2 days'; + /** interval for sending email is 2 days */ + public mixed $emailSnooze = '2 days'; /** @var callable handler for sending emails */ public $mailer; - /** @var BlueScreen|null */ - private $blueScreen; + private ?BlueScreen $blueScreen = null; public function __construct(?string $directory, string|array|null $email = null, ?BlueScreen $blueScreen = null) @@ -78,10 +77,7 @@ public function log(mixed $message, string $level = self::INFO) } - /** - * @param mixed $message - */ - public static function formatMessage($message): string + public static function formatMessage(mixed $message): string { if ($message instanceof \Throwable) { foreach (Helpers::getExceptionChain($message) as $exception) { @@ -101,10 +97,7 @@ public static function formatMessage($message): string } - /** - * @param mixed $message - */ - public static function formatLogLine($message, ?string $exceptionFile = null): string + public static function formatLogLine(mixed $message, ?string $exceptionFile = null): string { return implode(' ', [ date('[Y-m-d H-i-s]'), @@ -127,7 +120,7 @@ public function getExceptionFile(\Throwable $exception, string $level = self::EX ]; } - $hash = substr(md5(serialize($data)), 0, 10); + $hash = substr(hash('xxh128', serialize($data)), 0, 10); $dir = strtr($this->directory . '/', '\/', DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR); foreach (new \DirectoryIterator($this->directory) as $file) { if (strpos($file->getBasename(), $hash)) { @@ -152,10 +145,7 @@ protected function logException(\Throwable $exception, ?string $file = null): st } - /** - * @param mixed $message - */ - protected function sendEmail($message): void + protected function sendEmail(mixed $message): void { $snooze = is_numeric($this->emailSnooze) ? $this->emailSnooze @@ -174,10 +164,9 @@ protected function sendEmail($message): void /** * Default mailer. - * @param mixed $message * @internal */ - public function defaultMailer($message, string $email): void + public function defaultMailer(mixed $message, string $email): void { $host = preg_replace('#[^\w.-]+#', '', $_SERVER['SERVER_NAME'] ?? php_uname('n')); mail( diff --git a/tools/open-in-editor/windows/open-editor.js b/tools/open-in-editor/windows/open-editor.js index ac1093e70..2bb8c79ac 100644 --- a/tools/open-in-editor/windows/open-editor.js +++ b/tools/open-in-editor/windows/open-editor.js @@ -59,9 +59,24 @@ var replace = match[5]; var shell = new ActiveXObject('WScript.Shell'); var fileSystem = new ActiveXObject('Scripting.FileSystemObject'); -for (var id in settings.mappings) { - if (file.indexOf(id) === 0) { - file = settings.mappings[id] + file.substr(id.length); +function makeWildcardRegExp(s) { + s = s.replace(/([\\.^$+?{}()\[\]|])/g, '\\$1'); + s = s.replace(/\*/g, '[^/]*'); + return new RegExp('^' + s); +} + +var compiled = []; +for (var key in settings.mappings) { + compiled.push([ makeWildcardRegExp(key), settings.mappings[key] ]); +} + +for (var i = 0; i < compiled.length; ++i) { + var rx = compiled[i][0]; + var dst = compiled[i][1]; + + var m = rx.exec(file); + if (m) { + file = dst + file.slice(m[0].length); break; } }