Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <fabien@symfony.com>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
 
12
namespace Symfony\Component\Finder\Iterator;
13
 
14
use Symfony\Component\Finder\Exception\AccessDeniedException;
15
use Symfony\Component\Finder\SplFileInfo;
16
 
17
/**
18
 * Extends the \RecursiveDirectoryIterator to support relative paths.
19
 *
20
 * @author Victor Berchet <victor@suumit.com>
688 lars 21
 *
148 lars 22
 * @extends \RecursiveDirectoryIterator<string, SplFileInfo>
23
 */
24
class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
25
{
26
    private bool $ignoreUnreadableDirs;
27
    private ?bool $rewindable = null;
28
 
29
    // these 3 properties take part of the performance optimization to avoid redoing the same work in all iterations
30
    private string $rootPath;
31
    private string $subPath;
32
    private string $directorySeparator = '/';
33
 
34
    /**
35
     * @throws \RuntimeException
36
     */
37
    public function __construct(string $path, int $flags, bool $ignoreUnreadableDirs = false)
38
    {
39
        if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
40
            throw new \RuntimeException('This iterator only support returning current as fileinfo.');
41
        }
42
 
43
        parent::__construct($path, $flags);
44
        $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
45
        $this->rootPath = $path;
46
        if ('/' !== \DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
47
            $this->directorySeparator = \DIRECTORY_SEPARATOR;
48
        }
49
    }
50
 
51
    /**
52
     * Return an instance of SplFileInfo with support for relative paths.
53
     */
54
    public function current(): SplFileInfo
55
    {
56
        // the logic here avoids redoing the same work in all iterations
57
 
58
        if (!isset($this->subPath)) {
59
            $this->subPath = $this->getSubPath();
60
        }
61
        $subPathname = $this->subPath;
62
        if ('' !== $subPathname) {
63
            $subPathname .= $this->directorySeparator;
64
        }
65
        $subPathname .= $this->getFilename();
66
 
67
        if ('/' !== $basePath = $this->rootPath) {
68
            $basePath .= $this->directorySeparator;
69
        }
70
 
71
        return new SplFileInfo($basePath.$subPathname, $this->subPath, $subPathname);
72
    }
73
 
74
    public function hasChildren(bool $allowLinks = false): bool
75
    {
76
        $hasChildren = parent::hasChildren($allowLinks);
77
 
78
        if (!$hasChildren || !$this->ignoreUnreadableDirs) {
79
            return $hasChildren;
80
        }
81
 
82
        try {
83
            parent::getChildren();
84
 
85
            return true;
86
        } catch (\UnexpectedValueException) {
87
            // If directory is unreadable and finder is set to ignore it, skip children
88
            return false;
89
        }
90
    }
91
 
92
    /**
93
     * @throws AccessDeniedException
94
     */
95
    public function getChildren(): \RecursiveDirectoryIterator
96
    {
97
        try {
98
            $children = parent::getChildren();
99
 
100
            if ($children instanceof self) {
101
                // parent method will call the constructor with default arguments, so unreadable dirs won't be ignored anymore
102
                $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
103
 
104
                // performance optimization to avoid redoing the same work in all children
105
                $children->rewindable = &$this->rewindable;
106
                $children->rootPath = $this->rootPath;
107
            }
108
 
109
            return $children;
110
        } catch (\UnexpectedValueException $e) {
111
            throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
112
        }
113
    }
114
 
115
    /**
116
     * Do nothing for non rewindable stream.
117
     */
118
    public function rewind(): void
119
    {
120
        if (false === $this->isRewindable()) {
121
            return;
122
        }
123
 
124
        parent::rewind();
125
    }
126
 
127
    /**
128
     * Checks if the stream is rewindable.
129
     */
130
    public function isRewindable(): bool
131
    {
132
        if (null !== $this->rewindable) {
133
            return $this->rewindable;
134
        }
135
 
136
        if (false !== $stream = @opendir($this->getPath())) {
137
            $infos = stream_get_meta_data($stream);
138
            closedir($stream);
139
 
140
            if ($infos['seekable']) {
141
                return $this->rewindable = true;
142
            }
143
        }
144
 
145
        return $this->rewindable = false;
146
    }
147
}