TYPO3  7.6
Filesystem.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Composer\Plugin\Util;
3 
4 /*
5  * This file is part of the TYPO3 project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
20 class Filesystem extends \Composer\Util\Filesystem {
21 
26  public function allFilesExist(array $files) {
27  foreach ($files as $file) {
28  if (!file_exists($file)) {
29  return FALSE;
30  }
31  }
32  return TRUE;
33  }
34 
39  public function someFilesExist(array $files) {
40  foreach ($files as $file) {
41  if (file_exists($file) || is_link($file)) {
42  return TRUE;
43  }
44  }
45  return FALSE;
46  }
47 
53  public function establishSymlinks(array $links, $copyOnFailure = TRUE, $makeRelative = TRUE) {
54  foreach ($links as $source => $target) {
55  $this->symlink($source, $target, $copyOnFailure, $makeRelative);
56  }
57  }
58 
62  public function removeSymlinks(array $links) {
63  foreach ($links as $target) {
64  $this->remove($target);
65  }
66  }
67 
74  public function symlink($source, $target, $copyOnFailure = TRUE, $makeRelative = TRUE) {
75  if (!file_exists($source)) {
76  throw new \InvalidArgumentException('The symlink source "' . $source . '" is not available.');
77  }
78  if (file_exists($target)) {
79  throw new \InvalidArgumentException('The symlink target "' . $target . '" already exists.');
80  }
81  // As Windows needs a relative path with backslashes, we ensure the proper directory separator is used
82  $symlinkSource = strtr($makeRelative ? $this->findShortestPath($target, $source) : $source, '/', DIRECTORY_SEPARATOR);
83  $symlinkTarget = strtr($target, '/', DIRECTORY_SEPARATOR);
84  $symlinkSuccessfull = @symlink($symlinkSource, $symlinkTarget);
85  if (!$symlinkSuccessfull && !stristr(PHP_OS, 'darwin') && !stristr(PHP_OS, 'cygwin') && stristr(PHP_OS, 'win')) {
86  // Try fallback to mklink for Windows, because symlink can't handle relative paths starting with "..\"
87  $output = NULL;
88  $parameter = is_dir($source) ? ' /D' : '';
89  $processExecutor = new \Composer\Util\ProcessExecutor();
90  $symlinkSuccessfull = $processExecutor->execute('mklink' . $parameter . ' ' . escapeshellarg($symlinkTarget) . ' ' . escapeshellarg($symlinkSource), $output) === 0;
91  }
92  if (!$symlinkSuccessfull && !$copyOnFailure) {
93  throw new \RuntimeException('Symlinking target "' . $symlinkTarget . '" to source "' . $symlinkSource . '" ("' . $source . '") failed.', 1430494084);
94  } elseif (!$symlinkSuccessfull && $copyOnFailure) {
95  try {
96  $this->copy($symlinkSource, $symlinkTarget);
97  } catch (\Exception $exception) {
98  throw new \RuntimeException('Neiter symlinking nor copying target "' . $symlinkTarget . '" to source "' . $symlinkSource . '" ("' . $source . '") worked.', 1430494090);
99  }
100  }
101  }
102 
109  public function copy($source, $target) {
110  if (!file_exists($source)) {
111  throw new \RuntimeException('The source "' . $source . '" does not exist and cannot be copied.');
112  }
113  if (is_file($source)) {
114  $this->ensureDirectoryExists(dirname($target));
115  $this->copyFile($source, $target);
116  return;
117  } elseif (is_dir($source)) {
118  $this->copyDirectory($source, $target);
119  return;
120  }
121  throw new \RuntimeException('The source "' . $source . '" is neither a file nor a directory.');
122  }
123 
128  protected function copyFile($source, $target) {
129  $copySuccessful = @copy($source, $target);
130  if (!$copySuccessful) {
131  throw new \RuntimeException('The source "' . $source . '" could not be copied to target "' . $target . '".');
132  }
133  }
134 
139  protected function copyDirectory($source, $target) {
140  $iterator = new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS);
141  $recursiveIterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
142  $this->ensureDirectoryExists($target);
143 
144  foreach ($recursiveIterator as $file) {
145  $targetPath = $target . DIRECTORY_SEPARATOR . $recursiveIterator->getSubPathName();
146  if ($file->isDir()) {
147  $this->ensureDirectoryExists($targetPath);
148  } else {
149  $this->copyFile($file->getPathname(), $targetPath);
150  }
151  }
152  }
153 
154 }