CopyDir   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 5
dl 0
loc 156
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A overwrite() 0 5 1
A excluded() 0 9 5
A simplifyForCompare() 0 4 1
A run() 0 11 3
A dirPermissions() 0 5 1
A exclude() 0 5 1
B copyDir() 0 24 6
1
<?php
2
3
namespace Robo\Task\Filesystem;
4
5
use Robo\Common\ResourceExistenceChecker;
6
use Robo\Result;
7
use Robo\Exception\TaskException;
8
9
/**
10
 * Copies one dir into another
11
 *
12
 * ``` php
13
 * <?php
14
 * $this->taskCopyDir(['dist/config' => 'config'])->run();
15
 * // as shortcut
16
 * $this->_copyDir('dist/config', 'config');
17
 * ?>
18
 * ```
19
 */
20
class CopyDir extends BaseDir
21
{
22
    use ResourceExistenceChecker;
23
24
    /**
25
     * Explicitly declare our consturctor, so that
26
     * our copyDir() method does not look like a php4 constructor.
27
     *
28
     * @param string|string[] $dirs
29
     */
30
    public function __construct($dirs)
31
    {
32
        parent::__construct($dirs);
33
    }
34
35
    /**
36
     * @var int
37
     */
38
    protected $chmod = 0755;
39
40
    /**
41
     * Files to exclude on copying.
42
     *
43
     * @var string[]
44
     */
45
    protected $exclude = [];
46
47
    /**
48
     * Overwrite destination files newer than source files.
49
     */
50
    protected $overwrite = true;
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function run()
56
    {
57
        if (!$this->checkResources($this->dirs, 'dir')) {
58
            return Result::error($this, 'Source directories are missing!');
59
        }
60
        foreach ($this->dirs as $src => $dst) {
61
            $this->copyDir($src, $dst);
62
            $this->printTaskInfo('Copied from {source} to {destination}', ['source' => $src, 'destination' => $dst]);
63
        }
64
        return Result::success($this);
65
    }
66
67
    /**
68
     * Sets the default folder permissions for the destination if it doesn't exist
69
     *
70
     * @link http://en.wikipedia.org/wiki/Chmod
71
     * @link http://php.net/manual/en/function.mkdir.php
72
     * @link http://php.net/manual/en/function.chmod.php
73
     *
74
     * @param int $value
75
     *
76
     * @return $this
77
     */
78
    public function dirPermissions($value)
79
    {
80
        $this->chmod = (int)$value;
81
        return $this;
82
    }
83
84
    /**
85
     * List files to exclude.
86
     *
87
     * @param string[] $exclude
88
     *
89
     * @return $this
90
     */
91
    public function exclude($exclude = [])
92
    {
93
        $this->exclude = $this->simplifyForCompare($exclude);
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->simplifyForCompare($exclude) of type string is incompatible with the declared type array<integer,string> of property $exclude.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
94
        return $this;
95
    }
96
97
    /**
98
     * Destination files newer than source files are overwritten.
99
     *
100
     * @param bool $overwrite
101
     *
102
     * @return $this
103
     */
104
    public function overwrite($overwrite)
105
    {
106
        $this->overwrite = $overwrite;
107
        return $this;
108
    }
109
110
    /**
111
     * Copies a directory to another location.
112
     *
113
     * @param string $src Source directory
114
     * @param string $dst Destination directory
115
     * @param string $parent Parent directory
116
     *
117
     * @throws \Robo\Exception\TaskException
118
     */
119
    protected function copyDir($src, $dst, $parent = '')
120
    {
121
        $dir = @opendir($src);
122
        if (false === $dir) {
123
            throw new TaskException($this, "Cannot open source directory '" . $src . "'");
124
        }
125
        if (!is_dir($dst)) {
126
            mkdir($dst, $this->chmod, true);
127
        }
128
        while (false !== ($file = readdir($dir))) {
129
            // Support basename and full path exclusion.
130
            if ($this->excluded($file, $src, $parent)) {
131
                continue;
132
            }
133
            $srcFile = $src . '/' . $file;
134
            $destFile = $dst . '/' . $file;
135
            if (is_dir($srcFile)) {
136
                $this->copyDir($srcFile, $destFile, $parent . $file . DIRECTORY_SEPARATOR);
137
            } else {
138
                $this->fs->copy($srcFile, $destFile, $this->overwrite);
139
            }
140
        }
141
        closedir($dir);
142
    }
143
144
    /**
145
     * Check to see if the current item is excluded.
146
     *
147
     * @param string $file
148
     * @param string $src
149
     * @param string $parent
150
     *
151
     * @return bool
152
     */
153
    protected function excluded($file, $src, $parent)
154
    {
155
        return
156
            ($file == '.') ||
157
            ($file == '..') ||
158
            in_array($file, $this->exclude) ||
159
            in_array($this->simplifyForCompare($parent . $file), $this->exclude) ||
160
            in_array($this->simplifyForCompare($src . DIRECTORY_SEPARATOR . $file), $this->exclude);
161
    }
162
163
    /**
164
     * Avoid problems comparing paths on Windows that may have a
165
     * combination of DIRECTORY_SEPARATOR and /.
166
     *
167
     * @param string$item
168
     *
169
     * @return string
170
     */
171
    protected function simplifyForCompare($item)
172
    {
173
        return str_replace(DIRECTORY_SEPARATOR, '/', $item);
174
    }
175
}
176