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