vendor/symfony/config/Resource/GlobResource.php line 24

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\Config\Resource;
  11. use Symfony\Component\Finder\Finder;
  12. use Symfony\Component\Finder\Glob;
  13. /**
  14.  * GlobResource represents a set of resources stored on the filesystem.
  15.  *
  16.  * Only existence/removal is tracked (not mtimes.)
  17.  *
  18.  * @author Nicolas Grekas <p@tchwork.com>
  19.  */
  20. class GlobResource implements \IteratorAggregateSelfCheckingResourceInterface\Serializable
  21. {
  22.     private $prefix;
  23.     private $pattern;
  24.     private $recursive;
  25.     private $hash;
  26.     /**
  27.      * @param string $prefix    A directory prefix
  28.      * @param string $pattern   A glob pattern
  29.      * @param bool   $recursive Whether directories should be scanned recursively or not
  30.      *
  31.      * @throws \InvalidArgumentException
  32.      */
  33.     public function __construct($prefix$pattern$recursive)
  34.     {
  35.         $this->prefix realpath($prefix) ?: (file_exists($prefix) ? $prefix false);
  36.         $this->pattern $pattern;
  37.         $this->recursive $recursive;
  38.         if (false === $this->prefix) {
  39.             throw new \InvalidArgumentException(sprintf('The path "%s" does not exist.'$prefix));
  40.         }
  41.     }
  42.     public function getPrefix()
  43.     {
  44.         return $this->prefix;
  45.     }
  46.     /**
  47.      * {@inheritdoc}
  48.      */
  49.     public function __toString()
  50.     {
  51.         return 'glob.'.$this->prefix.$this->pattern.(int) $this->recursive;
  52.     }
  53.     /**
  54.      * {@inheritdoc}
  55.      */
  56.     public function isFresh($timestamp)
  57.     {
  58.         $hash $this->computeHash();
  59.         if (null === $this->hash) {
  60.             $this->hash $hash;
  61.         }
  62.         return $this->hash === $hash;
  63.     }
  64.     /**
  65.      * @internal
  66.      */
  67.     public function serialize()
  68.     {
  69.         if (null === $this->hash) {
  70.             $this->hash $this->computeHash();
  71.         }
  72.         return serialize([$this->prefix$this->pattern$this->recursive$this->hash]);
  73.     }
  74.     /**
  75.      * @internal
  76.      */
  77.     public function unserialize($serialized)
  78.     {
  79.         list($this->prefix$this->pattern$this->recursive$this->hash) = unserialize($serialized);
  80.     }
  81.     public function getIterator()
  82.     {
  83.         if (!file_exists($this->prefix) || (!$this->recursive && '' === $this->pattern)) {
  84.             return;
  85.         }
  86.         if (!== strpos($this->prefix'phar://') && false === strpos($this->pattern'/**/') && (\defined('GLOB_BRACE') || false === strpos($this->pattern'{'))) {
  87.             $paths glob($this->prefix.$this->patternGLOB_NOSORT | (\defined('GLOB_BRACE') ? GLOB_BRACE 0));
  88.             sort($paths);
  89.             foreach ($paths as $path) {
  90.                 if ($this->recursive && is_dir($path)) {
  91.                     $files iterator_to_array(new \RecursiveIteratorIterator(
  92.                         new \RecursiveCallbackFilterIterator(
  93.                             new \RecursiveDirectoryIterator($path\FilesystemIterator::SKIP_DOTS \FilesystemIterator::FOLLOW_SYMLINKS),
  94.                             function (\SplFileInfo $file) { return '.' !== $file->getBasename()[0]; }
  95.                         ),
  96.                         \RecursiveIteratorIterator::LEAVES_ONLY
  97.                     ));
  98.                     uasort($files, function (\SplFileInfo $a\SplFileInfo $b) {
  99.                         return (string) $a > (string) $b : -1;
  100.                     });
  101.                     foreach ($files as $path => $info) {
  102.                         if ($info->isFile()) {
  103.                             yield $path => $info;
  104.                         }
  105.                     }
  106.                 } elseif (is_file($path)) {
  107.                     yield $path => new \SplFileInfo($path);
  108.                 }
  109.             }
  110.             return;
  111.         }
  112.         if (!class_exists(Finder::class)) {
  113.             throw new \LogicException(sprintf('Extended glob pattern "%s" cannot be used as the Finder component is not installed.'$this->pattern));
  114.         }
  115.         $finder = new Finder();
  116.         $regex Glob::toRegex($this->pattern);
  117.         if ($this->recursive) {
  118.             $regex substr_replace($regex'(/|$)', -21);
  119.         }
  120.         $prefixLen \strlen($this->prefix);
  121.         foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) {
  122.             if (preg_match($regexsubstr('\\' === \DIRECTORY_SEPARATOR str_replace('\\''/'$path) : $path$prefixLen)) && $info->isFile()) {
  123.                 yield $path => $info;
  124.             }
  125.         }
  126.     }
  127.     private function computeHash()
  128.     {
  129.         $hash hash_init('md5');
  130.         foreach ($this->getIterator() as $path => $info) {
  131.             hash_update($hash$path."\n");
  132.         }
  133.         return hash_final($hash);
  134.     }
  135. }