Verzeichnisstruktur phpBB-3.1.0


Veröffentlicht
27.10.2014

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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

Filesystem.php

Zuletzt modifiziert: 09.10.2024, 12:58 - Dateigröße: 17.84 KiB


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\Filesystem;
013   
014  use Symfony\Component\Filesystem\Exception\IOException;
015   
016  /**
017   * Provides basic utility to manipulate the file system.
018   *
019   * @author Fabien Potencier <fabien@symfony.com>
020   */
021  class Filesystem
022  {
023      /**
024       * Copies a file.
025       *
026       * This method only copies the file if the origin file is newer than the target file.
027       *
028       * By default, if the target already exists, it is not overridden.
029       *
030       * @param string  $originFile The original filename
031       * @param string  $targetFile The target filename
032       * @param bool    $override   Whether to override an existing file or not
033       *
034       * @throws IOException When copy fails
035       */
036      public function copy($originFile, $targetFile, $override = false)
037      {
038          if (stream_is_local($originFile) && !is_file($originFile)) {
039              throw new IOException(sprintf('Failed to copy %s because file not exists', $originFile));
040          }
041   
042          $this->mkdir(dirname($targetFile));
043   
044          if (!$override && is_file($targetFile) && null === parse_url($originFile, PHP_URL_HOST)) {
045              $doCopy = filemtime($originFile) > filemtime($targetFile);
046          } else {
047              $doCopy = true;
048          }
049   
050          if ($doCopy) {
051              // https://bugs.php.net/bug.php?id=64634
052              $source = fopen($originFile, 'r');
053              // Stream context created to allow files overwrite when using FTP stream wrapper - disabled by default
054              $target = fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))));
055              stream_copy_to_stream($source, $target);
056              fclose($source);
057              fclose($target);
058              unset($source, $target);
059   
060              if (!is_file($targetFile)) {
061                  throw new IOException(sprintf('Failed to copy %s to %s', $originFile, $targetFile));
062              }
063          }
064      }
065   
066      /**
067       * Creates a directory recursively.
068       *
069       * @param string|array|\Traversable $dirs The directory path
070       * @param int                       $mode The directory mode
071       *
072       * @throws IOException On any directory creation failure
073       */
074      public function mkdir($dirs, $mode = 0777)
075      {
076          foreach ($this->toIterator($dirs) as $dir) {
077              if (is_dir($dir)) {
078                  continue;
079              }
080   
081              if (true !== @mkdir($dir, $mode, true)) {
082                  $error = error_get_last();
083                  if (!is_dir($dir)) {
084                      // The directory was not created by a concurrent process. Let's throw an exception with a developer friendly error message if we have one
085                      if ($error) {
086                          throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']));
087                      }
088                      throw new IOException(sprintf('Failed to create "%s"', $dir));
089                  }
090              }
091          }
092      }
093   
094      /**
095       * Checks the existence of files or directories.
096       *
097       * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to check
098       *
099       * @return bool    true if the file exists, false otherwise
100       */
101      public function exists($files)
102      {
103          foreach ($this->toIterator($files) as $file) {
104              if (!file_exists($file)) {
105                  return false;
106              }
107          }
108   
109          return true;
110      }
111   
112      /**
113       * Sets access and modification time of file.
114       *
115       * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to create
116       * @param int                       $time  The touch time as a Unix timestamp
117       * @param int                       $atime The access time as a Unix timestamp
118       *
119       * @throws IOException When touch fails
120       */
121      public function touch($files, $time = null, $atime = null)
122      {
123          foreach ($this->toIterator($files) as $file) {
124              $touch = $time ? @touch($file, $time, $atime) : @touch($file);
125              if (true !== $touch) {
126                  throw new IOException(sprintf('Failed to touch %s', $file));
127              }
128          }
129      }
130   
131      /**
132       * Removes files or directories.
133       *
134       * @param string|array|\Traversable $files A filename, an array of files, or a \Traversable instance to remove
135       *
136       * @throws IOException When removal fails
137       */
138      public function remove($files)
139      {
140          $files = iterator_to_array($this->toIterator($files));
141          $files = array_reverse($files);
142          foreach ($files as $file) {
143              if (!file_exists($file) && !is_link($file)) {
144                  continue;
145              }
146   
147              if (is_dir($file) && !is_link($file)) {
148                  $this->remove(new \FilesystemIterator($file));
149   
150                  if (true !== @rmdir($file)) {
151                      throw new IOException(sprintf('Failed to remove directory %s', $file));
152                  }
153              } else {
154                  // https://bugs.php.net/bug.php?id=52176
155                  if (defined('PHP_WINDOWS_VERSION_MAJOR') && is_dir($file)) {
156                      if (true !== @rmdir($file)) {
157                          throw new IOException(sprintf('Failed to remove file %s', $file));
158                      }
159                  } else {
160                      if (true !== @unlink($file)) {
161                          throw new IOException(sprintf('Failed to remove file %s', $file));
162                      }
163                  }
164              }
165          }
166      }
167   
168      /**
169       * Change mode for an array of files or directories.
170       *
171       * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change mode
172       * @param int                       $mode      The new mode (octal)
173       * @param int                       $umask     The mode mask (octal)
174       * @param bool                      $recursive Whether change the mod recursively or not
175       *
176       * @throws IOException When the change fail
177       */
178      public function chmod($files, $mode, $umask = 0000, $recursive = false)
179      {
180          foreach ($this->toIterator($files) as $file) {
181              if ($recursive && is_dir($file) && !is_link($file)) {
182                  $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
183              }
184              if (true !== @chmod($file, $mode & ~$umask)) {
185                  throw new IOException(sprintf('Failed to chmod file %s', $file));
186              }
187          }
188      }
189   
190      /**
191       * Change the owner of an array of files or directories
192       *
193       * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change owner
194       * @param string                    $user      The new owner user name
195       * @param bool                      $recursive Whether change the owner recursively or not
196       *
197       * @throws IOException When the change fail
198       */
199      public function chown($files, $user, $recursive = false)
200      {
201          foreach ($this->toIterator($files) as $file) {
202              if ($recursive && is_dir($file) && !is_link($file)) {
203                  $this->chown(new \FilesystemIterator($file), $user, true);
204              }
205              if (is_link($file) && function_exists('lchown')) {
206                  if (true !== @lchown($file, $user)) {
207                      throw new IOException(sprintf('Failed to chown file %s', $file));
208                  }
209              } else {
210                  if (true !== @chown($file, $user)) {
211                      throw new IOException(sprintf('Failed to chown file %s', $file));
212                  }
213              }
214          }
215      }
216   
217      /**
218       * Change the group of an array of files or directories
219       *
220       * @param string|array|\Traversable $files     A filename, an array of files, or a \Traversable instance to change group
221       * @param string                    $group     The group name
222       * @param bool                      $recursive Whether change the group recursively or not
223       *
224       * @throws IOException When the change fail
225       */
226      public function chgrp($files, $group, $recursive = false)
227      {
228          foreach ($this->toIterator($files) as $file) {
229              if ($recursive && is_dir($file) && !is_link($file)) {
230                  $this->chgrp(new \FilesystemIterator($file), $group, true);
231              }
232              if (is_link($file) && function_exists('lchgrp')) {
233                  if (true !== @lchgrp($file, $group)) {
234                      throw new IOException(sprintf('Failed to chgrp file %s', $file));
235                  }
236              } else {
237                  if (true !== @chgrp($file, $group)) {
238                      throw new IOException(sprintf('Failed to chgrp file %s', $file));
239                  }
240              }
241          }
242      }
243   
244      /**
245       * Renames a file or a directory.
246       *
247       * @param string  $origin    The origin filename or directory
248       * @param string  $target    The new filename or directory
249       * @param bool    $overwrite Whether to overwrite the target if it already exists
250       *
251       * @throws IOException When target file or directory already exists
252       * @throws IOException When origin cannot be renamed
253       */
254      public function rename($origin, $target, $overwrite = false)
255      {
256          // we check that target does not exist
257          if (!$overwrite && is_readable($target)) {
258              throw new IOException(sprintf('Cannot rename because the target "%s" already exist.', $target));
259          }
260   
261          if (true !== @rename($origin, $target)) {
262              throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target));
263          }
264      }
265   
266      /**
267       * Creates a symbolic link or copy a directory.
268       *
269       * @param string  $originDir     The origin directory path
270       * @param string  $targetDir     The symbolic link name
271       * @param bool    $copyOnWindows Whether to copy files if on Windows
272       *
273       * @throws IOException When symlink fails
274       */
275      public function symlink($originDir, $targetDir, $copyOnWindows = false)
276      {
277          if (!function_exists('symlink') && $copyOnWindows) {
278              $this->mirror($originDir, $targetDir);
279   
280              return;
281          }
282   
283          $this->mkdir(dirname($targetDir));
284   
285          $ok = false;
286          if (is_link($targetDir)) {
287              if (readlink($targetDir) != $originDir) {
288                  $this->remove($targetDir);
289              } else {
290                  $ok = true;
291              }
292          }
293   
294          if (!$ok) {
295              if (true !== @symlink($originDir, $targetDir)) {
296                  $report = error_get_last();
297                  if (is_array($report)) {
298                      if (defined('PHP_WINDOWS_VERSION_MAJOR') && false !== strpos($report['message'], 'error code(1314)')) {
299                          throw new IOException('Unable to create symlink due to error code 1314: \'A required privilege is not held by the client\'. Do you have the required Administrator-rights?');
300                      }
301                  }
302                  throw new IOException(sprintf('Failed to create symbolic link from %s to %s', $originDir, $targetDir));
303              }
304          }
305      }
306   
307      /**
308       * Given an existing path, convert it to a path relative to a given starting path
309       *
310       * @param string $endPath   Absolute path of target
311       * @param string $startPath Absolute path where traversal begins
312       *
313       * @return string Path of target relative to starting path
314       */
315      public function makePathRelative($endPath, $startPath)
316      {
317          // Normalize separators on Windows
318          if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
319              $endPath = strtr($endPath, '\\', '/');
320              $startPath = strtr($startPath, '\\', '/');
321          }
322   
323          // Split the paths into arrays
324          $startPathArr = explode('/', trim($startPath, '/'));
325          $endPathArr = explode('/', trim($endPath, '/'));
326   
327          // Find for which directory the common path stops
328          $index = 0;
329          while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
330              $index++;
331          }
332   
333          // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels)
334          $depth = count($startPathArr) - $index;
335   
336          // Repeated "../" for each level need to reach the common path
337          $traverser = str_repeat('../', $depth);
338   
339          $endPathRemainder = implode('/', array_slice($endPathArr, $index));
340   
341          // Construct $endPath from traversing to the common path, then to the remaining $endPath
342          $relativePath = $traverser.(strlen($endPathRemainder) > 0 ? $endPathRemainder.'/' : '');
343   
344          return (strlen($relativePath) === 0) ? './' : $relativePath;
345      }
346   
347      /**
348       * Mirrors a directory to another.
349       *
350       * @param string       $originDir The origin directory
351       * @param string       $targetDir The target directory
352       * @param \Traversable $iterator  A Traversable instance
353       * @param array        $options   An array of boolean options
354       *                               Valid options are:
355       *                                 - $options['override'] Whether to override an existing file on copy or not (see copy())
356       *                                 - $options['copy_on_windows'] Whether to copy files instead of links on Windows (see symlink())
357       *                                 - $options['delete'] Whether to delete files that are not in the source directory (defaults to false)
358       *
359       * @throws IOException When file type is unknown
360       */
361      public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
362      {
363          $targetDir = rtrim($targetDir, '/\\');
364          $originDir = rtrim($originDir, '/\\');
365   
366          // Iterate in destination folder to remove obsolete entries
367          if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
368              $deleteIterator = $iterator;
369              if (null === $deleteIterator) {
370                  $flags = \FilesystemIterator::SKIP_DOTS;
371                  $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
372              }
373              foreach ($deleteIterator as $file) {
374                  $origin = str_replace($targetDir, $originDir, $file->getPathname());
375                  if (!$this->exists($origin)) {
376                      $this->remove($file);
377                  }
378              }
379          }
380   
381          $copyOnWindows = false;
382          if (isset($options['copy_on_windows']) && !function_exists('symlink')) {
383              $copyOnWindows = $options['copy_on_windows'];
384          }
385   
386          if (null === $iterator) {
387              $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
388              $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
389          }
390   
391          foreach ($iterator as $file) {
392              $target = str_replace($originDir, $targetDir, $file->getPathname());
393   
394              if ($copyOnWindows) {
395                  if (is_link($file) || is_file($file)) {
396                      $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
397                  } elseif (is_dir($file)) {
398                      $this->mkdir($target);
399                  } else {
400                      throw new IOException(sprintf('Unable to guess "%s" file type.', $file));
401                  }
402              } else {
403                  if (is_link($file)) {
404                      $this->symlink($file->getLinkTarget(), $target);
405                  } elseif (is_dir($file)) {
406                      $this->mkdir($target);
407                  } elseif (is_file($file)) {
408                      $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
409                  } else {
410                      throw new IOException(sprintf('Unable to guess "%s" file type.', $file));
411                  }
412              }
413          }
414      }
415   
416      /**
417       * Returns whether the file path is an absolute path.
418       *
419       * @param string $file A file path
420       *
421       * @return bool
422       */
423      public function isAbsolutePath($file)
424      {
425          if (strspn($file, '/\\', 0, 1)
426              || (strlen($file) > 3 && ctype_alpha($file[0])
427                  && substr($file, 1, 1) === ':'
428                  && (strspn($file, '/\\', 2, 1))
429              )
430              || null !== parse_url($file, PHP_URL_SCHEME)
431          ) {
432              return true;
433          }
434   
435          return false;
436      }
437   
438      /**
439       * @param mixed $files
440       *
441       * @return \Traversable
442       */
443      private function toIterator($files)
444      {
445          if (!$files instanceof \Traversable) {
446              $files = new \ArrayObject(is_array($files) ? $files : array($files));
447          }
448   
449          return $files;
450      }
451   
452      /**
453       * Atomically dumps content into a file.
454       *
455       * @param  string       $filename The file to be written to.
456       * @param  string       $content  The data to write into the file.
457       * @param  null|int     $mode     The file mode (octal). If null, file permissions are not modified
458       *                                Deprecated since version 2.3.12, to be removed in 3.0.
459       * @throws IOException            If the file cannot be written to.
460       */
461      public function dumpFile($filename, $content, $mode = 0666)
462      {
463          $dir = dirname($filename);
464   
465          if (!is_dir($dir)) {
466              $this->mkdir($dir);
467          } elseif (!is_writable($dir)) {
468              throw new IOException(sprintf('Unable to write in the %s directory.', $dir));
469          }
470   
471          $tmpFile = tempnam($dir, basename($filename));
472   
473          if (false === @file_put_contents($tmpFile, $content)) {
474              throw new IOException(sprintf('Failed to write file "%s".', $filename));
475          }
476   
477          $this->rename($tmpFile, $filename, true);
478          if (null !== $mode) {
479              $this->chmod($filename, $mode);
480          }
481      }
482  }
483