vendor/symfony/config/Resource/DirectoryResource.php line 32

  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. /**
  12.  * DirectoryResource represents a resources stored in a subdirectory tree.
  13.  *
  14.  * @author Fabien Potencier <fabien@symfony.com>
  15.  *
  16.  * @final
  17.  */
  18. class DirectoryResource implements SelfCheckingResourceInterface
  19. {
  20.     private string $resource;
  21.     private ?string $pattern;
  22.     /**
  23.      * @param string      $resource The file path to the resource
  24.      * @param string|null $pattern  A pattern to restrict monitored files
  25.      *
  26.      * @throws \InvalidArgumentException
  27.      */
  28.     public function __construct(string $resourcestring $pattern null)
  29.     {
  30.         $resolvedResource realpath($resource) ?: (file_exists($resource) ? $resource false);
  31.         $this->pattern $pattern;
  32.         if (false === $resolvedResource || !is_dir($resolvedResource)) {
  33.             throw new \InvalidArgumentException(sprintf('The directory "%s" does not exist.'$resource));
  34.         }
  35.         $this->resource $resolvedResource;
  36.     }
  37.     public function __toString(): string
  38.     {
  39.         return md5(serialize([$this->resource$this->pattern]));
  40.     }
  41.     public function getResource(): string
  42.     {
  43.         return $this->resource;
  44.     }
  45.     public function getPattern(): ?string
  46.     {
  47.         return $this->pattern;
  48.     }
  49.     public function isFresh(int $timestamp): bool
  50.     {
  51.         if (!is_dir($this->resource)) {
  52.             return false;
  53.         }
  54.         if ($timestamp filemtime($this->resource)) {
  55.             return false;
  56.         }
  57.         foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->resource), \RecursiveIteratorIterator::SELF_FIRST) as $file) {
  58.             // if regex filtering is enabled only check matching files
  59.             if ($this->pattern && $file->isFile() && !preg_match($this->pattern$file->getBasename())) {
  60.                 continue;
  61.             }
  62.             // always monitor directories for changes, except the .. entries
  63.             // (otherwise deleted files wouldn't get detected)
  64.             if ($file->isDir() && str_ends_with($file'/..')) {
  65.                 continue;
  66.             }
  67.             // for broken links
  68.             try {
  69.                 $fileMTime $file->getMTime();
  70.             } catch (\RuntimeException) {
  71.                 continue;
  72.             }
  73.             // early return if a file's mtime exceeds the passed timestamp
  74.             if ($timestamp $fileMTime) {
  75.                 return false;
  76.             }
  77.         }
  78.         return true;
  79.     }
  80. }