vendor/symfony/var-dumper/Caster/LinkStub.php line 94

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\VarDumper\Caster;
  11. /**
  12.  * Represents a file or a URL.
  13.  *
  14.  * @author Nicolas Grekas <p@tchwork.com>
  15.  */
  16. class LinkStub extends ConstStub
  17. {
  18.     public $inVendor = false;
  19.     private static array $vendorRoots;
  20.     private static array $composerRoots = [];
  21.     public function __construct(string $label, int $line = 0, string $href = null)
  22.     {
  23.         $this->value = $label;
  24.         if (null === $href) {
  25.             $href = $label;
  26.         }
  27.         if (!\is_string($href)) {
  28.             return;
  29.         }
  30.         if (str_starts_with($href, 'file://')) {
  31.             if ($href === $label) {
  32.                 $label = substr($label, 7);
  33.             }
  34.             $href = substr($href, 7);
  35.         } elseif (str_contains($href, '://')) {
  36.             $this->attr['href'] = $href;
  37.             return;
  38.         }
  39.         if (!is_file($href)) {
  40.             return;
  41.         }
  42.         if ($line) {
  43.             $this->attr['line'] = $line;
  44.         }
  45.         if ($label !== $this->attr['file'] = realpath($href) ?: $href) {
  46.             return;
  47.         }
  48.         if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) {
  49.             $this->attr['ellipsis'] = \strlen($href) - \strlen($composerRoot) + 1;
  50.             $this->attr['ellipsis-type'] = 'path';
  51.             $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + \strlen(implode('', \array_slice(explode(\DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0);
  52.         } elseif (3 < \count($ellipsis = explode(\DIRECTORY_SEPARATOR, $href))) {
  53.             $this->attr['ellipsis'] = 2 + \strlen(implode('', \array_slice($ellipsis, -2)));
  54.             $this->attr['ellipsis-type'] = 'path';
  55.             $this->attr['ellipsis-tail'] = 1;
  56.         }
  57.     }
  58.     private function getComposerRoot(string $file, bool &$inVendor)
  59.     {
  60.         if (!isset(self::$vendorRoots)) {
  61.             self::$vendorRoots = [];
  62.             foreach (get_declared_classes() as $class) {
  63.                 if ('C' === $class[0] && str_starts_with($class, 'ComposerAutoloaderInit')) {
  64.                     $r = new \ReflectionClass($class);
  65.                     $v = \dirname($r->getFileName(), 2);
  66.                     if (is_file($v.'/composer/installed.json')) {
  67.                         self::$vendorRoots[] = $v.\DIRECTORY_SEPARATOR;
  68.                     }
  69.                 }
  70.             }
  71.         }
  72.         $inVendor = false;
  73.         if (isset(self::$composerRoots[$dir = \dirname($file)])) {
  74.             return self::$composerRoots[$dir];
  75.         }
  76.         foreach (self::$vendorRoots as $root) {
  77.             if ($inVendor = str_starts_with($file, $root)) {
  78.                 return $root;
  79.             }
  80.         }
  81.         $parent = $dir;
  82.         while (!@is_file($parent.'/composer.json')) {
  83.             if (!@file_exists($parent)) {
  84.                 // open_basedir restriction in effect
  85.                 break;
  86.             }
  87.             if ($parent === \dirname($parent)) {
  88.                 return self::$composerRoots[$dir] = false;
  89.             }
  90.             $parent = \dirname($parent);
  91.         }
  92.         return self::$composerRoots[$dir] = $parent.\DIRECTORY_SEPARATOR;
  93.     }
  94. }