Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / vendor / consolidation / robo / src / Task / Filesystem / FilesystemStack.php
1 <?php
2 namespace Robo\Task\Filesystem;
3
4 use Robo\Task\StackBasedTask;
5 use Symfony\Component\Filesystem\Filesystem as sfFilesystem;
6 use Symfony\Component\Filesystem\Exception\IOException;
7 use Robo\Contract\BuilderAwareInterface;
8 use Robo\Common\BuilderAwareTrait;
9
10 /**
11  * Wrapper for [Symfony Filesystem](http://symfony.com/doc/current/components/filesystem.html) Component.
12  * Comands are executed in stack and can be stopped on first fail with `stopOnFail` option.
13  *
14  * ``` php
15  * <?php
16  * $this->taskFilesystemStack()
17  *      ->mkdir('logs')
18  *      ->touch('logs/.gitignore')
19  *      ->chgrp('www', 'www-data')
20  *      ->symlink('/var/log/nginx/error.log', 'logs/error.log')
21  *      ->run();
22  *
23  * // one line
24  * $this->_touch('.gitignore');
25  * $this->_mkdir('logs');
26  *
27  * ?>
28  * ```
29  *
30  * @method $this mkdir(string|array|\Traversable $dir, int $mode = 0777)
31  * @method $this touch(string|array|\Traversable $file, int $time = null, int $atime = null)
32  * @method $this copy(string $from, string $to, bool $force = false)
33  * @method $this chmod(string|array|\Traversable $file, int $permissions, int $umask = 0000, bool $recursive = false)
34  * @method $this chgrp(string|array|\Traversable $file, string $group, bool $recursive = false)
35  * @method $this chown(string|array|\Traversable $file, string $user, bool $recursive = false)
36  * @method $this remove(string|array|\Traversable $file)
37  * @method $this rename(string $from, string $to, bool $force = false)
38  * @method $this symlink(string $from, string $to, bool $copyOnWindows = false)
39  * @method $this mirror(string $from, string $to, \Traversable $iterator = null, array $options = [])
40  */
41 class FilesystemStack extends StackBasedTask implements BuilderAwareInterface
42 {
43     use BuilderAwareTrait;
44
45     /**
46      * @var \Symfony\Component\Filesystem\Filesystem
47      */
48     protected $fs;
49
50     public function __construct()
51     {
52         $this->fs = new sfFilesystem();
53     }
54
55     /**
56      * @return \Symfony\Component\Filesystem\Filesystem
57      */
58     protected function getDelegate()
59     {
60         return $this->fs;
61     }
62
63     /**
64      * @param string $from
65      * @param string $to
66      * @param bool $force
67      */
68     protected function _copy($from, $to, $force = false)
69     {
70         $this->fs->copy($from, $to, $force);
71     }
72
73     /**
74      * @param string|string[]|\Traversable $file
75      * @param int $permissions
76      * @param int $umask
77      * @param bool $recursive
78      */
79     protected function _chmod($file, $permissions, $umask = 0000, $recursive = false)
80     {
81         $this->fs->chmod($file, $permissions, $umask, $recursive);
82     }
83
84     /**
85      * @param string|string[]|\Traversable $file
86      * @param string $group
87      * @param bool $recursive
88      */
89     protected function _chgrp($file, $group, $recursive = null)
90     {
91         $this->fs->chgrp($file, $group, $recursive);
92     }
93
94     /**
95      * @param string|string[]|\Traversable $file
96      * @param string $user
97      * @param bool $recursive
98      */
99     protected function _chown($file, $user, $recursive = null)
100     {
101         $this->fs->chown($file, $user, $recursive);
102     }
103
104     /**
105      * @param string $origin
106      * @param string $target
107      * @param bool $overwrite
108      *
109      * @return null|true|\Robo\Result
110      */
111     protected function _rename($origin, $target, $overwrite = false)
112     {
113         // we check that target does not exist
114         if ((!$overwrite && is_readable($target)) || (file_exists($target) && !is_writable($target))) {
115             throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
116         }
117
118         // Due to a bug (limitation) in PHP, cross-volume renames do not work.
119         // See: https://bugs.php.net/bug.php?id=54097
120         if (true !== @rename($origin, $target)) {
121             return $this->crossVolumeRename($origin, $target);
122         }
123         return true;
124     }
125
126     /**
127      * @param string $origin
128      * @param string $target
129      *
130      * @return null|\Robo\Result
131      */
132     protected function crossVolumeRename($origin, $target)
133     {
134         // First step is to try to get rid of the target. If there
135         // is a single, deletable file, then we will just unlink it.
136         if (is_file($target)) {
137             unlink($target);
138         }
139         // If the target still exists, we will try to delete it.
140         // TODO: Note that if this fails partway through, then we cannot
141         // adequately rollback.  Perhaps we need to preflight the operation
142         // and determine if everything inside of $target is writable.
143         if (file_exists($target)) {
144             $this->fs->remove($target);
145         }
146
147         /** @var \Robo\Result $result */
148         $result = $this->collectionBuilder()->taskCopyDir([$origin => $target])->run();
149         if (!$result->wasSuccessful()) {
150             return $result;
151         }
152         $this->fs->remove($origin);
153     }
154 }