vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php line 113

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\Finder\Iterator;
  11. use Symfony\Component\Finder\Exception\AccessDeniedException;
  12. use Symfony\Component\Finder\SplFileInfo;
  13. /**
  14.  * Extends the \RecursiveDirectoryIterator to support relative paths.
  15.  *
  16.  * @author Victor Berchet <victor@suumit.com>
  17.  */
  18. class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
  19. {
  20.     /**
  21.      * @var bool
  22.      */
  23.     private $ignoreUnreadableDirs;
  24.     /**
  25.      * @var bool
  26.      */
  27.     private $rewindable;
  28.     // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
  29.     private $rootPath;
  30.     private $subPath;
  31.     private $directorySeparator '/';
  32.     /**
  33.      * @throws \RuntimeException
  34.      */
  35.     public function __construct(string $pathint $flagsbool $ignoreUnreadableDirs false)
  36.     {
  37.         if ($flags & (self::CURRENT_AS_PATHNAME self::CURRENT_AS_SELF)) {
  38.             throw new \RuntimeException('This iterator only support returning current as fileinfo.');
  39.         }
  40.         parent::__construct($path$flags);
  41.         $this->ignoreUnreadableDirs $ignoreUnreadableDirs;
  42.         $this->rootPath $path;
  43.         if ('/' !== \DIRECTORY_SEPARATOR && !($flags self::UNIX_PATHS)) {
  44.             $this->directorySeparator = \DIRECTORY_SEPARATOR;
  45.         }
  46.     }
  47.     /**
  48.      * Return an instance of SplFileInfo with support for relative paths.
  49.      *
  50.      * @return SplFileInfo File information
  51.      */
  52.     public function current()
  53.     {
  54.         // the logic here avoids redoing the same work in all iterations
  55.         if (null === $subPathname $this->subPath) {
  56.             $subPathname $this->subPath = (string) $this->getSubPath();
  57.         }
  58.         if ('' !== $subPathname) {
  59.             $subPathname .= $this->directorySeparator;
  60.         }
  61.         $subPathname .= $this->getFilename();
  62.         if ('/' !== $basePath $this->rootPath) {
  63.             $basePath .= $this->directorySeparator;
  64.         }
  65.         return new SplFileInfo($basePath.$subPathname$this->subPath$subPathname);
  66.     }
  67.     /**
  68.      * @return \RecursiveIterator
  69.      *
  70.      * @throws AccessDeniedException
  71.      */
  72.     public function getChildren()
  73.     {
  74.         try {
  75.             $children parent::getChildren();
  76.             if ($children instanceof self) {
  77.                 // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
  78.                 $children->ignoreUnreadableDirs $this->ignoreUnreadableDirs;
  79.                 // performance optimization to avoid redoing the same work in all children
  80.                 $children->rewindable = &$this->rewindable;
  81.                 $children->rootPath $this->rootPath;
  82.             }
  83.             return $children;
  84.         } catch (\UnexpectedValueException $e) {
  85.             if ($this->ignoreUnreadableDirs) {
  86.                 // If directory is unreadable and finder is set to ignore it, a fake empty content is returned.
  87.                 return new \RecursiveArrayIterator([]);
  88.             } else {
  89.                 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
  90.             }
  91.         }
  92.     }
  93.     /**
  94.      * Do nothing for non rewindable stream.
  95.      */
  96.     public function rewind()
  97.     {
  98.         if (false === $this->isRewindable()) {
  99.             return;
  100.         }
  101.         parent::rewind();
  102.     }
  103.     /**
  104.      * Checks if the stream is rewindable.
  105.      *
  106.      * @return bool true when the stream is rewindable, false otherwise
  107.      */
  108.     public function isRewindable()
  109.     {
  110.         if (null !== $this->rewindable) {
  111.             return $this->rewindable;
  112.         }
  113.         if (false !== $stream = @opendir($this->getPath())) {
  114.             $infos stream_get_meta_data($stream);
  115.             closedir($stream);
  116.             if ($infos['seekable']) {
  117.                 return $this->rewindable true;
  118.             }
  119.         }
  120.         return $this->rewindable false;
  121.     }
  122. }