Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
AbstractFindAdapter.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\Finder\Adapter;
013
014 @trigger_error('The '.__NAMESPACE__.'\AbstractFindAdapter class is deprecated since version 2.8 and will be removed in 3.0. Use directly the Finder class instead.', E_USER_DEPRECATED);
015
016 use Symfony\Component\Finder\Exception\AccessDeniedException;
017 use Symfony\Component\Finder\Iterator;
018 use Symfony\Component\Finder\Shell\Shell;
019 use Symfony\Component\Finder\Expression\Expression;
020 use Symfony\Component\Finder\Shell\Command;
021 use Symfony\Component\Finder\Comparator\NumberComparator;
022 use Symfony\Component\Finder\Comparator\DateComparator;
023
024 /**
025 * Shell engine implementation using GNU find command.
026 *
027 * @author Jean-François Simon <contact@jfsimon.fr>
028 *
029 * @deprecated since 2.8, to be removed in 3.0. Use Finder instead.
030 */
031 abstract class AbstractFindAdapter extends AbstractAdapter
032 {
033 /**
034 * @var Shell
035 */
036 protected $shell;
037
038 /**
039 * Constructor.
040 */
041 public function __construct()
042 {
043 $this->shell = new Shell();
044 }
045
046 /**
047 * {@inheritdoc}
048 */
049 public function searchInDirectory($dir)
050 {
051 // having "/../" in path make find fail
052 $dir = realpath($dir);
053
054 // searching directories containing or not containing strings leads to no result
055 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
056 return new Iterator\FilePathsIterator(array(), $dir);
057 }
058
059 $command = Command::create();
060 $find = $this->buildFindCommand($command, $dir);
061
062 if ($this->followLinks) {
063 $find->add('-follow');
064 }
065
066 $find->add('-mindepth')->add($this->minDepth + 1);
067
068 if (PHP_INT_MAX !== $this->maxDepth) {
069 $find->add('-maxdepth')->add($this->maxDepth + 1);
070 }
071
072 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
073 $find->add('-type d');
074 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
075 $find->add('-type f');
076 }
077
078 $this->buildNamesFiltering($find, $this->names);
079 $this->buildNamesFiltering($find, $this->notNames, true);
080 $this->buildPathsFiltering($find, $dir, $this->paths);
081 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
082 $this->buildSizesFiltering($find, $this->sizes);
083 $this->buildDatesFiltering($find, $this->dates);
084
085 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
086 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
087
088 if ($useGrep && ($this->contains || $this->notContains)) {
089 $grep = $command->ins('grep');
090 $this->buildContentFiltering($grep, $this->contains);
091 $this->buildContentFiltering($grep, $this->notContains, true);
092 }
093
094 if ($useSort) {
095 $this->buildSorting($command, $this->sort);
096 }
097
098 $command->setErrorHandler(
099 $this->ignoreUnreadableDirs
100 // If directory is unreadable and finder is set to ignore it, `stderr` is ignored.
101 ? function ($stderr) { }
102 : function ($stderr) { throw new AccessDeniedException($stderr); }
103 );
104
105 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
106 $iterator = new Iterator\FilePathsIterator($paths, $dir);
107
108 if ($this->exclude) {
109 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
110 }
111
112 if (!$useGrep && ($this->contains || $this->notContains)) {
113 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
114 }
115
116 if ($this->filters) {
117 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
118 }
119
120 if (!$useSort && $this->sort) {
121 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
122 $iterator = $iteratorAggregate->getIterator();
123 }
124
125 return $iterator;
126 }
127
128 /**
129 * {@inheritdoc}
130 */
131 protected function canBeUsed()
132 {
133 return $this->shell->testCommand('find');
134 }
135
136 /**
137 * @param Command $command
138 * @param string $dir
139 *
140 * @return Command
141 */
142 protected function buildFindCommand(Command $command, $dir)
143 {
144 return $command
145 ->ins('find')
146 ->add('find ')
147 ->arg($dir)
148 ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions
149 }
150
151 /**
152 * @param Command $command
153 * @param string[] $names
154 * @param bool $not
155 */
156 private function buildNamesFiltering(Command $command, array $names, $not = false)
157 {
158 if (0 === count($names)) {
159 return;
160 }
161
162 $command->add($not ? '-not' : null)->cmd('(');
163
164 foreach ($names as $i => $name) {
165 $expr = Expression::create($name);
166
167 // Find does not support expandable globs ("*.{a,b}" syntax).
168 if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
169 $expr = Expression::create($expr->getGlob()->toRegex(false));
170 }
171
172 // Fixes 'not search' and 'full path matching' regex problems.
173 // - Jokers '.' are replaced by [^/].
174 // - We add '[^/]*' before and after regex (if no ^|$ flags are present).
175 if ($expr->isRegex()) {
176 $regex = $expr->getRegex();
177 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
178 ->setStartFlag(false)
179 ->setStartJoker(true)
180 ->replaceJokers('[^/]');
181 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
182 $regex->setEndJoker(false)->append('[^/]*');
183 }
184 }
185
186 $command
187 ->add($i > 0 ? '-or' : null)
188 ->add($expr->isRegex()
189 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
190 : ($expr->isCaseSensitive() ? '-name' : '-iname')
191 )
192 ->arg($expr->renderPattern());
193 }
194
195 $command->cmd(')');
196 }
197
198 /**
199 * @param Command $command
200 * @param string $dir
201 * @param string[] $paths
202 * @param bool $not
203 */
204 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
205 {
206 if (0 === count($paths)) {
207 return;
208 }
209
210 $command->add($not ? '-not' : null)->cmd('(');
211
212 foreach ($paths as $i => $path) {
213 $expr = Expression::create($path);
214
215 // Find does not support expandable globs ("*.{a,b}" syntax).
216 if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
217 $expr = Expression::create($expr->getGlob()->toRegex(false));
218 }
219
220 // Fixes 'not search' regex problems.
221 if ($expr->isRegex()) {
222 $regex = $expr->getRegex();
223 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
224 } else {
225 $expr->prepend('*')->append('*');
226 }
227
228 $command
229 ->add($i > 0 ? '-or' : null)
230 ->add($expr->isRegex()
231 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
232 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
233 )
234 ->arg($expr->renderPattern());
235 }
236
237 $command->cmd(')');
238 }
239
240 /**
241 * @param Command $command
242 * @param NumberComparator[] $sizes
243 */
244 private function buildSizesFiltering(Command $command, array $sizes)
245 {
246 foreach ($sizes as $i => $size) {
247 $command->add($i > 0 ? '-and' : null);
248
249 switch ($size->getOperator()) {
250 case '<=':
251 $command->add('-size -'.($size->getTarget() + 1).'c');
252 break;
253 case '>=':
254 $command->add('-size +'.($size->getTarget() - 1).'c');
255 break;
256 case '>':
257 $command->add('-size +'.$size->getTarget().'c');
258 break;
259 case '!=':
260 $command->add('-size -'.$size->getTarget().'c');
261 $command->add('-size +'.$size->getTarget().'c');
262 break;
263 case '<':
264 default:
265 $command->add('-size -'.$size->getTarget().'c');
266 }
267 }
268 }
269
270 /**
271 * @param Command $command
272 * @param DateComparator[] $dates
273 */
274 private function buildDatesFiltering(Command $command, array $dates)
275 {
276 foreach ($dates as $i => $date) {
277 $command->add($i > 0 ? '-and' : null);
278
279 $mins = (int) round((time() - $date->getTarget()) / 60);
280
281 if (0 > $mins) {
282 // mtime is in the future
283 $command->add(' -mmin -0');
284 // we will have no result so we don't need to continue
285 return;
286 }
287
288 switch ($date->getOperator()) {
289 case '<=':
290 $command->add('-mmin +'.($mins - 1));
291 break;
292 case '>=':
293 $command->add('-mmin -'.($mins + 1));
294 break;
295 case '>':
296 $command->add('-mmin -'.$mins);
297 break;
298 case '!=':
299 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
300 break;
301 case '<':
302 default:
303 $command->add('-mmin +'.$mins);
304 }
305 }
306 }
307
308 /**
309 * @param Command $command
310 * @param string $sort
311 *
312 * @throws \InvalidArgumentException
313 */
314 private function buildSorting(Command $command, $sort)
315 {
316 $this->buildFormatSorting($command, $sort);
317 }
318
319 /**
320 * @param Command $command
321 * @param string $sort
322 */
323 abstract protected function buildFormatSorting(Command $command, $sort);
324
325 /**
326 * @param Command $command
327 * @param array $contains
328 * @param bool $not
329 */
330 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
331 }
332