From ecbe3f60a09a3d3803c7a939557dca0c0875d832 Mon Sep 17 00:00:00 2001 From: Jonathan Vollebregt Date: Sun, 3 Nov 2024 09:57:38 +0100 Subject: [PATCH] Rename Kint::$app_root_dirs to Utils::$path_aliases Call Utils::shortenPath now instead of Kint::shortenPath --- build/kint.phar | Bin 547596 -> 547742 bytes init.php | 5 +- src/Kint.php | 61 ------- src/Renderer/PlainRenderer.php | 3 +- .../Rich/CallableDefinitionPlugin.php | 4 +- src/Renderer/RichRenderer.php | 3 +- src/Renderer/TextRenderer.php | 3 +- src/Utils.php | 78 +++++++++ src/Value/ClosureValue.php | 4 +- src/Value/StreamValue.php | 4 +- tests/EndToEndTest.php | 2 +- tests/KintTest.php | 55 ------ tests/KintTestCase.php | 3 + tests/UtilsTest.php | 162 ++++++++++++++++++ 14 files changed, 256 insertions(+), 131 deletions(-) diff --git a/build/kint.phar b/build/kint.phar index 7a199f9a2f98ded599532b38c2513ee2868f84ed..bdf838c1c91e32639b838a7689b9378afc4868a8 100644 GIT binary patch delta 1306 zcmZuxeM}o=80T&8`VAa|7TN$ix@-CB2e@q6x(x<)fkYWis!OH|UB?bMy|w4vspB7U z!DN^yA*u41Z7M_}ku17c$4!m>pu}Y}5{ZeUBHQZ@OzNCd#xIm}A^j(HiA!LP-clGA25kAS$yg2;WFh@U} zr1^d(nIM~j7IJNEz%V-Jm*)J4i%RBEbhb*mej1&2pKM!1@}ra57WJPMAk%_*q~I9V zT8gU-(9PmEfa}9b;m;L(FHCv$7-ZZgt90%SY{mnYG0Xu!PUr}Dp-I;cuM)TmlGibV zbR~oRhBOXoDTfuFhc9;ECDQvl@X4)fW|?{{Dy?Mkna%eP^GIh`@T+#Pkkv;@~~>&k26JRcw4ok%A9^f68x_6s7|8)z5v#8Z1a4aK|dq}vsfV_~&A|ouzcA$#K4h%5I6{<`D zRom4aA4##v#2_t*v14(ue+bAtazIwZZG@*U*hG2iWe+V7I;P|lbBB=$*IeuNpc)`; z1{0xv2kL|M0nHa~9hO;MUqJ1!x`2W;yVggB8j2r{@pPPxsrBLFya+vi;WfCHXSjf3 zlLBTad%z8r7j<@s^vE5{UBD}0)vc@epCZe@ikL<~2Xs}C5%J;;WjOD1)N(wnRfS^6 zHnNp$C+h=&K(L++k+LB8iPo2^qDwT#HHF7PRj(A>r3SW;UN3n_?mtT>8mOn4g!m-I zz%-2!Vh*!ywue2LvL z@S1De;QYa|&o}$iJ!kHYw|~QC|NdbACF{pABD~YRj?8;E_lcJ8$G>{C^m1MGjQhD`90YvDdEhSc8fL9^`bZX8GRy;dC+aK z2LABJ^qGuQ_!l#qYmo*zzYLXTB!@fudeI`z#N$@Pz^TtYBU#BYhCTe+0~TxGf#34W zj$=9Ibq{)~N;2}a#tUj#PRmmbme9bfv5TiOEhXPDUm=-c*T8RuxrJ=VwbRZ_=2@(P zWr{GKX{mH)->EFO7dP{wR$uR7WjUcpl9uS^mCStb>y7xAmqPkd2$S2YSw&%oKo_fW z0O`4;CMi6p0x1QCq<#gUVgjFJHC__o!gcbfYl9{#XawzWewi$RN0!M?;ZPo4n!nx! zJbIlhhbIqUq~5k48*};A2UQ^aUPplly{7vS;!^Ko>Rf-ol zw2BUMrHKJn=;u`b+82sxoZ^Rz#Z<^11U^+$1Wxq9e~PKCSOgZvX@_IO9l&QcQy#c| z0WZi$IlR~dJjNa%cpTqMbA7TlsF%0XS;wl-F~r;pW==^zM)!)rsS=xA_$k0A&Gk06OXoT?>ES>OeD>KN{X zu{k==?u+)VT29z7V)M_ixS69dns^A4cPaG+e%FZJXuQ?z||=3hi^pDWIs7`$81J|K5}2~+@tZEa}`m~vrX>a$*U!o zMvr$4AD+Z_&v@e>e%}JhLcPcAZ#MoOe*XPaul%wpsMXz!N1nU5cQPjmMq@SJ-J|sr N1p4Fc-0|d&{{eYZ^GN^z diff --git a/init.php b/init.php index d71b35e0f..6d7c48423 100644 --- a/init.php +++ b/init.php @@ -51,13 +51,14 @@ AbstractRenderer::$file_link_format = \ini_get('xdebug.file_link_format'); } if (isset($_SERVER['DOCUMENT_ROOT']) && false === \strpos($_SERVER['DOCUMENT_ROOT'], "\0")) { - Kint::$app_root_dirs = [ + Utils::$path_aliases = [ $_SERVER['DOCUMENT_ROOT'] => '', ]; // Suppressed for unreadable document roots (related to open_basedir) if (false !== @\realpath($_SERVER['DOCUMENT_ROOT'])) { - Kint::$app_root_dirs[\realpath($_SERVER['DOCUMENT_ROOT'])] = ''; + /** @psalm-suppress PropertyTypeCoercion */ + Utils::$path_aliases[\realpath($_SERVER['DOCUMENT_ROOT'])] = ''; } } diff --git a/src/Kint.php b/src/Kint.php index 0281d4021..e872c8f25 100644 --- a/src/Kint.php +++ b/src/Kint.php @@ -85,23 +85,6 @@ class Kint implements FacadeInterface */ public static bool $cli_detection = true; - /** - * @var array base directories of your application that will be displayed instead of the full path. - * - * Keys are paths, values are replacement strings - * - * Example for laravel: - * - * Kint::$app_root_dirs = [ - * base_path() => '', - * app_path() => '', - * base_path().'/vendor' => '', - * ]; - * - * Defaults to [$_SERVER['DOCUMENT_ROOT'] => ''] - */ - public static array $app_root_dirs = []; - /** * @var bool Return output instead of echoing */ @@ -308,7 +291,6 @@ public static function getStatics(): array { return [ 'aliases' => static::$aliases, - 'app_root_dirs' => static::$app_root_dirs, 'cli_detection' => static::$cli_detection, 'depth_limit' => static::$depth_limit, 'display_called_from' => static::$display_called_from, @@ -611,49 +593,6 @@ public static function dump(...$args) return 0; } - /** - * generic path display callback, can be configured in app_root_dirs; purpose is - * to show relevant path info and hide as much of the path as possible. - */ - public static function shortenPath(string $file): string - { - $file = \array_values(\array_filter(\explode('/', \str_replace('\\', '/', $file)), 'strlen')); - - $longest_match = 0; - $match = '/'; - - foreach (static::$app_root_dirs as $path => $alias) { - /** @psalm-var string $path */ - if (empty($path)) { - continue; - } - - $path = \array_values(\array_filter(\explode('/', \str_replace('\\', '/', $path)), 'strlen')); - - if (\array_slice($file, 0, \count($path)) === $path && \count($path) > $longest_match) { - $longest_match = \count($path); - $match = $alias; - } - } - - if ($longest_match) { - $file = [$match, ...\array_slice($file, $longest_match)]; - - return \implode('/', $file); - } - - // fallback to find common path with Kint dir - $kint = \array_values(\array_filter(\explode('/', \str_replace('\\', '/', KINT_DIR)), 'strlen')); - - foreach ($file as $i => $part) { - if (!isset($kint[$i]) || $kint[$i] !== $part) { - return ($i ? '.../' : '/').\implode('/', \array_slice($file, $i)); - } - } - - return '/'.\implode('/', $file); - } - /** * Returns specific function call info from a stack trace frame, or null if no match could be found. * diff --git a/src/Renderer/PlainRenderer.php b/src/Renderer/PlainRenderer.php index 56ae2ba3b..ac949e5b6 100644 --- a/src/Renderer/PlainRenderer.php +++ b/src/Renderer/PlainRenderer.php @@ -27,7 +27,6 @@ namespace Kint\Renderer; -use Kint\Kint; use Kint\Utils; use Kint\Value\AbstractValue; @@ -175,7 +174,7 @@ public function postRender(): string public function ideLink(string $file, int $line): string { - $path = $this->escape(Kint::shortenPath($file)).':'.$line; + $path = $this->escape(Utils::shortenPath($file)).':'.$line; $ideLink = self::getFileLink($file, $line); if (null === $ideLink) { diff --git a/src/Renderer/Rich/CallableDefinitionPlugin.php b/src/Renderer/Rich/CallableDefinitionPlugin.php index c73d7ad14..fdae7eed0 100644 --- a/src/Renderer/Rich/CallableDefinitionPlugin.php +++ b/src/Renderer/Rich/CallableDefinitionPlugin.php @@ -27,7 +27,7 @@ namespace Kint\Renderer\Rich; -use Kint\Kint; +use Kint\Utils; use Kint\Value\Representation\CallableDefinitionRepresentation; use Kint\Value\Representation\RepresentationInterface; @@ -44,7 +44,7 @@ public function renderTab(RepresentationInterface $r): ?string $docstring[] = 'Inherited from '.$this->renderer->escape($class); } - $docstring[] = 'Defined in '.$this->renderer->escape(Kint::shortenPath($r->getFileName())).':'.$r->getLine(); + $docstring[] = 'Defined in '.$this->renderer->escape(Utils::shortenPath($r->getFileName())).':'.$r->getLine(); $docstring = ''.\implode("\n", $docstring).''; diff --git a/src/Renderer/RichRenderer.php b/src/Renderer/RichRenderer.php index fdccb553e..f84a90cc4 100644 --- a/src/Renderer/RichRenderer.php +++ b/src/Renderer/RichRenderer.php @@ -27,7 +27,6 @@ namespace Kint\Renderer; -use Kint\Kint; use Kint\Renderer\Rich\TabPluginInterface; use Kint\Renderer\Rich\ValuePluginInterface; use Kint\Utils; @@ -477,7 +476,7 @@ public function escape(string $string, $encoding = false): string public function ideLink(string $file, int $line): string { - $path = $this->escape(Kint::shortenPath($file)).':'.$line; + $path = $this->escape(Utils::shortenPath($file)).':'.$line; $ideLink = self::getFileLink($file, $line); if (null === $ideLink) { diff --git a/src/Renderer/TextRenderer.php b/src/Renderer/TextRenderer.php index 1528b06a5..64c850a1f 100644 --- a/src/Renderer/TextRenderer.php +++ b/src/Renderer/TextRenderer.php @@ -27,7 +27,6 @@ namespace Kint\Renderer; -use Kint\Kint; use Kint\Parser; use Kint\Parser\PluginInterface as ParserPluginInterface; use Kint\Renderer\Text\PluginInterface; @@ -329,7 +328,7 @@ public function filterParserPlugins(array $plugins): array public function ideLink(string $file, int $line): string { - return $this->escape(Kint::shortenPath($file)).':'.$line; + return $this->escape(Utils::shortenPath($file)).':'.$line; } /** diff --git a/src/Utils.php b/src/Utils.php index 3fcc64c82..3f3832f35 100644 --- a/src/Utils.php +++ b/src/Utils.php @@ -105,6 +105,25 @@ final class Utils */ public static array $legacy_encodings = []; + /** + * @var array Path aliases that will be displayed instead of the full path. + * + * Keys are paths, values are replacement strings + * + * Example for laravel: + * + * Utils::$path_aliases = [ + * base_path() => '', + * app_path() => '', + * base_path().'/vendor' => '', + * ]; + * + * Defaults to [$_SERVER['DOCUMENT_ROOT'] => ''] + * + * @psalm-var array + */ + public static array $path_aliases = []; + /** * @codeCoverageIgnore * @@ -419,6 +438,65 @@ public static function substr(string $string, int $start, ?int $length = null, $ return \substr($string, $start, $length ?? PHP_INT_MAX); } + public static function shortenPath(string $file): string + { + $split = \explode('/', \str_replace('\\', '/', $file)); + + $longest_match = 0; + $match = ''; + + foreach (self::$path_aliases as $path => $alias) { + $path = \explode('/', \str_replace('\\', '/', $path)); + + if (\count($path) < 2) { + continue; + } + + if (\array_slice($split, 0, \count($path)) === $path && \count($path) > $longest_match) { + $longest_match = \count($path); + $match = $alias; + } + } + + if ($longest_match) { + $suffix = \implode('/', \array_slice($split, $longest_match)); + + if (\preg_match('%^/*$%', $suffix)) { + return $match; + } + + return $match.'/'.$suffix; + } + + // fallback to find common path with Kint dir + $kint = \explode('/', \str_replace('\\', '/', KINT_DIR)); + $had_real_path_part = false; + + foreach ($split as $i => $part) { + if (!isset($kint[$i]) || $kint[$i] !== $part) { + if (!$had_real_path_part) { + break; + } + + $suffix = \implode('/', \array_slice($split, $i)); + + if (\preg_match('%^/*$%', $suffix)) { + break; + } + + $prefix = $i > 1 ? '.../' : '/'; + + return $prefix.$suffix; + } + + if ($i > 0 && \strlen($kint[$i])) { + $had_real_path_part = true; + } + } + + return $file; + } + public static function composerGetExtras(string $key = 'kint'): array { if (0 === \strpos(KINT_DIR, 'phar://')) { diff --git a/src/Value/ClosureValue.php b/src/Value/ClosureValue.php index 152a81ad3..7bad29abb 100644 --- a/src/Value/ClosureValue.php +++ b/src/Value/ClosureValue.php @@ -28,7 +28,7 @@ namespace Kint\Value; use Closure; -use Kint\Kint; +use Kint\Utils; use Kint\Value\Context\BaseContext; use Kint\Value\Context\ContextInterface; use ReflectionFunction; @@ -112,7 +112,7 @@ public function getDisplayName(): string public function getDisplayValue(): ?string { if (null !== $this->filename && null !== $this->startline) { - return Kint::shortenPath($this->filename).':'.$this->startline; + return Utils::shortenPath($this->filename).':'.$this->startline; } return parent::getDisplayValue(); diff --git a/src/Value/StreamValue.php b/src/Value/StreamValue.php index 3da3f6f5b..d01b52425 100644 --- a/src/Value/StreamValue.php +++ b/src/Value/StreamValue.php @@ -27,7 +27,7 @@ namespace Kint\Value; -use Kint\Kint; +use Kint\Utils; use Kint\Value\Context\ContextInterface; use Kint\Value\Representation\ContainerRepresentation; @@ -66,7 +66,7 @@ public function getDisplayValue(): ?string } if ('/' === $this->uri[0] && \stream_is_local($this->uri)) { - return Kint::shortenPath($this->uri); + return Utils::shortenPath($this->uri); } return $this->uri; diff --git a/tests/EndToEndTest.php b/tests/EndToEndTest.php index 14309e631..2a8ecf9d6 100644 --- a/tests/EndToEndTest.php +++ b/tests/EndToEndTest.php @@ -646,7 +646,7 @@ function (&$var, $v) use (&$p1_triggered) { [ '$value', 'stream resource', - Kint::shortenPath(__FILE__), + Utils::shortenPath(__FILE__), ], $d2 ); diff --git a/tests/KintTest.php b/tests/KintTest.php index c0f83c0ab..1c56436c2 100644 --- a/tests/KintTest.php +++ b/tests/KintTest.php @@ -1066,59 +1066,4 @@ public function testGetCallInfo($aliases, $trace, $args, $expect) { $this->assertSame($expect, Kint::getCallInfo($aliases, $trace, $args)); } - - public function pathProvider() - { - return [ - 'standard file' => [ - 'path' => __FILE__, - 'expect' => '/KintTest.php', - ], - 'standard dir' => [ - 'path' => __DIR__, - 'expect' => '', - ], - 'parent dir' => [ - 'path' => KINT_DIR, - 'expect' => '', - ], - 'sub file' => [ - 'path' => KINT_DIR.'/src//test', - 'expect' => '/src/test', - ], - 'common path' => [ - 'path' => \dirname(KINT_DIR).'/test/', - 'expect' => '.../test', - ], - 'root path' => [ - 'path' => '/', - 'expect' => '/', - ], - 'no common path' => [ - 'path' => '/asdfasdf/test/', - 'expect' => '/asdfasdf/test', - ], - ]; - } - - /** - * @dataProvider pathProvider - * - * @covers \Kint\Kint::shortenPath - * - * @param string $path - * @param string $expect - */ - public function testShortenPath($path, $expect) - { - Kint::$app_root_dirs = [ - KINT_DIR => '', - KINT_DIR.'/test' => '', - '' => '', - __DIR__ => '', - KINT_DIR.'/tes' => '', - ]; - - $this->assertSame($expect, Kint::shortenPath($path)); - } } diff --git a/tests/KintTestCase.php b/tests/KintTestCase.php index 825135960..493da4414 100644 --- a/tests/KintTestCase.php +++ b/tests/KintTestCase.php @@ -54,6 +54,7 @@ class KintTestCase extends TestCase protected $rich_statics; protected $char_encodings; protected $legacy_encodings; + protected $path_aliases; protected $file_link_format; protected $text_decorations; protected $text_plugin_whitelist; @@ -86,6 +87,7 @@ protected function setUp(): void ]; $this->char_encodings = Utils::$char_encodings; $this->legacy_encodings = Utils::$legacy_encodings; + $this->path_aliases = Utils::$path_aliases; $this->file_link_format = AbstractRenderer::$file_link_format; $this->text_decorations = TextRenderer::$decorations; $this->text_plugin_whitelist = TextRenderer::$parser_plugin_whitelist; @@ -122,6 +124,7 @@ protected function tearDown(): void Utils::$char_encodings = $this->char_encodings; Utils::$legacy_encodings = $this->legacy_encodings; + Utils::$path_aliases = $this->path_aliases; AbstractRenderer::$file_link_format = $this->file_link_format; TextRenderer::$decorations = $this->text_decorations; TextRenderer::$parser_plugin_whitelist = $this->text_plugin_whitelist; diff --git a/tests/UtilsTest.php b/tests/UtilsTest.php index ee053144e..ada3202f2 100644 --- a/tests/UtilsTest.php +++ b/tests/UtilsTest.php @@ -794,4 +794,166 @@ public function testSubstr(string $string, $encoding, array $encodings, array $l ); } } + + public function pathProvider() + { + $root_parent = '/'.\explode('/', __DIR__)[1]; + + $tests = [ + 'standard file' => [ + 'path' => __FILE__, + 'expect' => '/UtilsTest.php', + ], + 'standard dir' => [ + 'path' => __DIR__, + 'expect' => '', + ], + 'parent dir' => [ + 'path' => KINT_DIR, + 'expect' => '', + ], + 'sub file' => [ + 'path' => KINT_DIR.'/src/test', + 'expect' => '/src/test', + ], + 'no mangle bad paths' => [ + 'path' => KINT_DIR.'/src//test', + 'expect' => '/src//test', + ], + 'parent path' => [ + 'path' => $root_parent, + 'expect' => $root_parent, + ], + 'common path' => [ + 'path' => $root_parent.'/test/test', + 'expect' => '.../test/test', + ], + 'root path' => [ + 'path' => '/', + 'expect' => '/', + ], + 'no common path' => [ + 'path' => '/asdfasdf/test', + 'expect' => '/asdfasdf/test', + ], + 'partial folder path' => [ + 'path' => __DIR__.'/partialfolder', + 'expect' => '/partialfolder', + ], + 'phar path' => [ + 'path' => 'phar:///var/test.phar/file', + 'expect' => 'phar:///var/test.phar/file', + ], + 'common phar path' => [ + 'path' => 'phar://'.$root_parent.'/test.phar/file', + 'expect' => 'phar://'.$root_parent.'/test.phar/file', + ], + 'windows path' => [ + 'path' => 'C:\\windows\\system32\\etc', + 'expect' => '/etc', + ], + 'trailing / on folder' => [ + 'path' => KINT_DIR.'/folder/', + 'expect' => '/folder/', + ], + 'trailing / on alias' => [ + 'path' => __DIR__.'/', + 'expect' => '', + ], + 'trailing / on parent path' => [ + 'path' => $root_parent.'/', + 'expect' => $root_parent.'/', + ], + 'trailing / on common path' => [ + 'path' => $root_parent.'/test/test/', + 'expect' => '.../test/test/', + ], + 'trailing / on no common path' => [ + 'path' => '/asdfasdf/test/', + 'expect' => '/asdfasdf/test/', + ], + 'trailing / on partial folder path' => [ + 'path' => __DIR__.'/partialfolder/', + 'expect' => '/partialfolder/', + ], + 'trailing / on phar path' => [ + 'path' => 'phar:///var/test.phar/file/', + 'expect' => 'phar:///var/test.phar/file/', + ], + 'trailing / on common phar path' => [ + 'path' => 'phar://'.$root_parent.'/test.phar/file/', + 'expect' => 'phar://'.$root_parent.'/test.phar/file/', + ], + 'trailing / on windows path' => [ + 'path' => 'C:\\windows\\system32\\etc\\', + 'expect' => '/etc/', + ], + 'trailing // on folder' => [ + 'path' => KINT_DIR.'/folder//', + 'expect' => '/folder//', + ], + 'trailing // on alias' => [ + 'path' => __DIR__.'//', + 'expect' => '', + ], + 'trailing // on parent path' => [ + 'path' => $root_parent.'//', + 'expect' => $root_parent.'//', + ], + 'trailing // on common path' => [ + 'path' => $root_parent.'/test/test//', + 'expect' => '.../test/test//', + ], + 'trailing // on no common path' => [ + 'path' => '/asdfasdf/test//', + 'expect' => '/asdfasdf/test//', + ], + 'trailing // on partial folder path' => [ + 'path' => __DIR__.'/partialfolder//', + 'expect' => '/partialfolder//', + ], + 'trailing // on phar path' => [ + 'path' => 'phar:///var/test.phar/file//', + 'expect' => 'phar:///var/test.phar/file//', + ], + 'trailing // on common phar path' => [ + 'path' => 'phar://'.$root_parent.'/test.phar/file//', + 'expect' => 'phar://'.$root_parent.'/test.phar/file//', + ], + 'trailing // on windows path' => [ + 'path' => 'C:\\windows\\system32\\etc\\\\', + 'expect' => '/etc//', + ], + ]; + + if (\getenv('KINT_PHAR_TEST')) { + $tests['common path']['path'] = 'phar://'.$tests['common path']['path']; + $tests['trailing / on common path']['path'] = 'phar://'.$tests['trailing / on common path']['path']; + $tests['trailing // on common path']['path'] = 'phar://'.$tests['trailing // on common path']['path']; + $tests['common phar path']['expect'] = '.../test.phar/file'; + $tests['trailing / on common phar path']['expect'] = '.../test.phar/file/'; + $tests['trailing // on common phar path']['expect'] = '.../test.phar/file//'; + } + + return $tests; + } + + /** + * @dataProvider pathProvider + * + * @covers \Kint\Utils::shortenPath + */ + public function testShortenPath(string $path, string $expect) + { + Utils::$path_aliases = [ + KINT_DIR => '', + __DIR__.'/partialfo' => '', + '' => '', + __DIR__ => '', + KINT_DIR.'/tes' => '', + 'C:\\windows\\system32' => '', + ]; + + $this->assertSame($expect, Utils::shortenPath($path)); + } }