Completed
Push — master ( bfd2db...9db4ff )
by Greg
03:27
created

CopyDir::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
namespace Robo\Task\Filesystem;
3
4
use Robo\Common\ResourceExistenceChecker;
5
use Robo\Result;
6
use Robo\Exception\TaskException;
7
8
/**
9
 * Copies one dir into another
10
 *
11
 * ``` php
12
 * <?php
13
 * $this->taskCopyDir(['dist/config' => 'config'])->run();
14
 * // as shortcut
15
 * $this->_copyDir('dist/config', 'config');
16
 * ?>
17
 * ```
18
 */
19
class CopyDir extends BaseDir
20
{
21
    use ResourceExistenceChecker;
22
23
    /**
24
     * Explicitly declare our consturctor, so that
25
     * our copyDir() method does not look like a php4 constructor.
26
     */
27
    public function __construct($dirs)
28
    {
29
        parent::__construct($dirs);
30
    }
31
32
    /**
33
     * @var int
34
     */
35
    protected $chmod = 0755;
36
37
    /**
38
     * Files to exclude on copying.
39
     *
40
     * @var string[]
41
     */
42
    protected $exclude = [];
43
44
    /**
45
     * Overwrite destination files newer than source files.
46
     */
47
    protected $overwrite = true;
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function run()
53
    {
54
        if (!$this->checkResources($this->dirs, 'dir')) {
55
            return Result::error($this, 'Source directories are missing!');
56
        }
57
        foreach ($this->dirs as $src => $dst) {
58
            $this->copyDir($src, $dst);
59
            $this->printTaskInfo('Copied from {source} to {destination}', ['source' => $src, 'destination' => $dst]);
60
        }
61
        return Result::success($this);
62
    }
63
64
    /**
65
     * Sets the default folder permissions for the destination if it doesn't exist
66
     *
67
     * @link http://en.wikipedia.org/wiki/Chmod
68
     * @link http://php.net/manual/en/function.mkdir.php
69
     * @link http://php.net/manual/en/function.chmod.php
70
     *
71
     * @param int $value
72
     *
73
     * @return $this
74
     */
75
    public function dirPermissions($value)
76
    {
77
        $this->chmod = (int)$value;
78
        return $this;
79
    }
80
81
    /**
82
     * List files to exclude.
83
     *
84
     * @param string[] $exclude
85
     *
86
     * @return $this
87
     */
88
    public function exclude($exclude = [])
89
    {
90
        $this->exclude = $this->simplifyForCompare($exclude);
91
        return $this;
92
    }
93
94
    /**
95
     * Destination files newer than source files are overwritten.
96
     *
97
     * @param bool $overwrite
98
     *
99
     * @return $this
100
     */
101
    public function overwrite($overwrite)
102
    {
103
        $this->overwrite = $overwrite;
104
        return $this;
105
    }
106
107
    /**
108
     * Copies a directory to another location.
109
     *
110
     * @param string $src Source directory
111
     * @param string $dst Destination directory
112
     * @param string $parent Parent directory
113
     *
114
     * @throws \Robo\Exception\TaskException
115
     */
116
    protected function copyDir($src, $dst, $parent = '')
117
    {
118
        $dir = @opendir($src);
119
        if (false === $dir) {
120
            throw new TaskException($this, "Cannot open source directory '" . $src . "'");
121
        }
122
        if (!is_dir($dst)) {
123
            mkdir($dst, $this->chmod, true);
124
        }
125
        while (false !== ($file = readdir($dir))) {
126
            // Support basename and full path exclusion.
127
            if ($this->excluded($file, $src, $parent)) {
128
                continue;
129
            }
130
            $srcFile = $src . '/' . $file;
131
            $destFile = $dst . '/' . $file;
132
            if (is_dir($srcFile)) {
133
                $this->copyDir($srcFile, $destFile, $parent . $file . DIRECTORY_SEPARATOR);
134
            } else {
135
                $this->fs->copy($srcFile, $destFile, $this->overwrite);
136
            }
137
        }
138
        closedir($dir);
139
    }
140
141
    /**
142
     * Check to see if the current item is excluded.
143
     */
144
    protected function excluded($file, $src, $parent)
145
    {
146
        return
147
            ($file == '.') ||
148
            ($file == '..') ||
149
            in_array($file, $this->exclude) ||
150
            in_array($this->simplifyForCompare($parent . $file), $this->exclude) ||
151
            in_array($this->simplifyForCompare($src . DIRECTORY_SEPARATOR . $file), $this->exclude);
152
    }
153
154
    /**
155
     * Avoid problems comparing paths on Windows that may have a
156
     * combination of DIRECTORY_SEPARATOR and /.
157
     */
158
    protected function simplifyForCompare($item)
159
    {
160
        return str_replace(DIRECTORY_SEPARATOR, '/', $item);
161
    }
162
}
163