This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Robo\Task\Filesystem; |
||
4 | |||
5 | use Robo\Result; |
||
6 | use Robo\Exception\TaskException; |
||
7 | use Symfony\Component\Finder\Finder; |
||
8 | |||
9 | /** |
||
10 | * Searches for files in a nested directory structure and copies them to |
||
11 | * a target directory with or without the parent directories. The task was |
||
12 | * inspired by [gulp-flatten](https://www.npmjs.com/package/gulp-flatten). |
||
13 | * |
||
14 | * Example directory structure: |
||
15 | * |
||
16 | * ``` |
||
17 | * └── assets |
||
18 | * ├── asset-library1 |
||
19 | * │ ├── README.md |
||
20 | * │ └── asset-library1.min.js |
||
21 | * └── asset-library2 |
||
22 | * ├── README.md |
||
23 | * └── asset-library2.min.js |
||
24 | * ``` |
||
25 | * |
||
26 | * The following code will search the `*.min.js` files and copy them |
||
27 | * inside a new `dist` folder: |
||
28 | * |
||
29 | * ``` php |
||
30 | * <?php |
||
31 | * $this->taskFlattenDir(['assets/*.min.js' => 'dist'])->run(); |
||
32 | * // or use shortcut |
||
33 | * $this->_flattenDir('assets/*.min.js', 'dist'); |
||
34 | * ?> |
||
35 | * ``` |
||
36 | * |
||
37 | * You can also define the target directory with an additional method, instead of |
||
38 | * key/value pairs. More similar to the gulp-flatten syntax: |
||
39 | * |
||
40 | * ``` php |
||
41 | * <?php |
||
42 | * $this->taskFlattenDir(['assets/*.min.js']) |
||
43 | * ->to('dist') |
||
44 | * ->run(); |
||
45 | * ?> |
||
46 | * ``` |
||
47 | * |
||
48 | * You can also append parts of the parent directories to the target path. If you give |
||
49 | * the value `1` to the `includeParents()` method, then the top parent will be appended |
||
50 | * to the target directory resulting in a path such as `dist/assets/asset-library1.min.js`. |
||
51 | * |
||
52 | * If you give a negative number, such as `-1` (the same as specifying `array(0, 1)` then |
||
53 | * the bottom parent will be appended, resulting in a path such as |
||
54 | * `dist/asset-library1/asset-library1.min.js`. |
||
55 | * |
||
56 | * The top parent directory will always be starting from the relative path to the current |
||
57 | * directory. You can override that with the `parentDir()` method. If in the above example |
||
58 | * you would specify `assets`, then the top parent directory would be `asset-library1`. |
||
59 | * |
||
60 | * ``` php |
||
61 | * <?php |
||
62 | * $this->taskFlattenDir(['assets/*.min.js' => 'dist']) |
||
63 | * ->parentDir('assets') |
||
64 | * ->includeParents(1) |
||
65 | * ->run(); |
||
66 | * ?> |
||
67 | * ``` |
||
68 | */ |
||
69 | class FlattenDir extends BaseDir |
||
70 | { |
||
71 | /** |
||
72 | * @var int |
||
73 | */ |
||
74 | protected $chmod = 0755; |
||
75 | |||
76 | /** |
||
77 | * @var int[] |
||
78 | */ |
||
79 | protected $parents = array(0, 0); |
||
80 | |||
81 | /** |
||
82 | * @var string |
||
83 | */ |
||
84 | protected $parentDir = ''; |
||
85 | |||
86 | /** |
||
87 | * @var string |
||
88 | */ |
||
89 | protected $to; |
||
90 | |||
91 | /** |
||
92 | * {@inheritdoc} |
||
93 | */ |
||
94 | public function __construct($dirs) |
||
95 | { |
||
96 | parent::__construct($dirs); |
||
97 | $this->parentDir = getcwd(); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * {@inheritdoc} |
||
102 | */ |
||
103 | public function run() |
||
104 | { |
||
105 | // find the files |
||
106 | $files = $this->findFiles($this->dirs); |
||
107 | |||
108 | // copy the files |
||
109 | $this->copyFiles($files); |
||
0 ignored issues
–
show
|
|||
110 | |||
111 | $fileNoun = count($files) == 1 ? ' file' : ' files'; |
||
112 | $this->printTaskSuccess("Copied {count} $fileNoun to {destination}", ['count' => count($files), 'destination' => $this->to]); |
||
113 | |||
114 | return Result::success($this); |
||
115 | } |
||
116 | |||
117 | /** |
||
118 | * Sets the default folder permissions for the destination if it does not exist. |
||
119 | * |
||
120 | * @link http://en.wikipedia.org/wiki/Chmod |
||
121 | * @link http://php.net/manual/en/function.mkdir.php |
||
122 | * @link http://php.net/manual/en/function.chmod.php |
||
123 | * |
||
124 | * @param int $permission |
||
125 | * |
||
126 | * @return $this |
||
127 | */ |
||
128 | public function dirPermissions($permission) |
||
129 | { |
||
130 | $this->chmod = (int) $permission; |
||
131 | |||
132 | return $this; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Sets the value from which direction and how much parent dirs should be included. |
||
137 | * Accepts a positive or negative integer or an array with two integer values. |
||
138 | * |
||
139 | * @param int|int[] $parents |
||
140 | * |
||
141 | * @return $this |
||
142 | * |
||
143 | * @throws TaskException |
||
144 | */ |
||
145 | public function includeParents($parents) |
||
146 | { |
||
147 | if (is_int($parents)) { |
||
148 | // if an integer is given check whether it is for top or bottom parent |
||
149 | if ($parents >= 0) { |
||
150 | $this->parents[0] = $parents; |
||
151 | return $this; |
||
152 | } |
||
153 | $this->parents[1] = 0 - $parents; |
||
154 | return $this; |
||
155 | } |
||
156 | |||
157 | if (is_array($parents)) { |
||
158 | // check if the array has two values no more, no less |
||
159 | if (count($parents) == 2) { |
||
160 | $this->parents = $parents; |
||
161 | return $this; |
||
162 | } |
||
163 | } |
||
164 | |||
165 | throw new TaskException($this, 'includeParents expects an integer or an array with two values'); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * Sets the parent directory from which the relative parent directories will be calculated. |
||
170 | * |
||
171 | * @param string $dir |
||
172 | * |
||
173 | * @return $this |
||
174 | */ |
||
175 | public function parentDir($dir) |
||
176 | { |
||
177 | if (!$this->fs->isAbsolutePath($dir)) { |
||
178 | // attach the relative path to current working directory |
||
179 | $dir = getcwd() . '/' . $dir; |
||
180 | } |
||
181 | $this->parentDir = $dir; |
||
182 | |||
183 | return $this; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Sets the target directory where the files will be copied to. |
||
188 | * |
||
189 | * @param string $target |
||
190 | * |
||
191 | * @return $this |
||
192 | */ |
||
193 | public function to($target) |
||
194 | { |
||
195 | $this->to = rtrim($target, '/'); |
||
196 | |||
197 | return $this; |
||
198 | } |
||
199 | |||
200 | /** |
||
201 | * @param array $dirs |
||
202 | * |
||
203 | * @return array|\Robo\Result |
||
204 | * |
||
205 | * @throws \Robo\Exception\TaskException |
||
206 | */ |
||
207 | View Code Duplication | protected function findFiles($dirs) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
208 | { |
||
209 | $files = array(); |
||
210 | |||
211 | // find the files |
||
212 | foreach ($dirs as $k => $v) { |
||
213 | // reset finder |
||
214 | $finder = new Finder(); |
||
215 | |||
216 | $dir = $k; |
||
217 | $to = $v; |
||
218 | // check if target was given with the to() method instead of key/value pairs |
||
219 | if (is_int($k)) { |
||
220 | $dir = $v; |
||
221 | if (isset($this->to)) { |
||
222 | $to = $this->to; |
||
223 | } else { |
||
224 | throw new TaskException($this, 'target directory is not defined'); |
||
225 | } |
||
226 | } |
||
227 | |||
228 | try { |
||
229 | $finder->files()->in($dir); |
||
230 | } catch (\InvalidArgumentException $e) { |
||
231 | // if finder cannot handle it, try with in()->name() |
||
232 | if (strpos($dir, '/') === false) { |
||
233 | $dir = './' . $dir; |
||
234 | } |
||
235 | $parts = explode('/', $dir); |
||
236 | $new_dir = implode('/', array_slice($parts, 0, -1)); |
||
237 | try { |
||
238 | $finder->files()->in($new_dir)->name(array_pop($parts)); |
||
239 | } catch (\InvalidArgumentException $e) { |
||
240 | return Result::fromException($this, $e); |
||
241 | } |
||
242 | } |
||
243 | |||
244 | foreach ($finder as $file) { |
||
245 | // store the absolute path as key and target as value in the files array |
||
246 | $files[$file->getRealpath()] = $this->getTarget($file->getRealPath(), $to); |
||
247 | } |
||
248 | $fileNoun = count($files) == 1 ? ' file' : ' files'; |
||
249 | $this->printTaskInfo("Found {count} $fileNoun in {dir}", ['count' => count($files), 'dir' => $dir]); |
||
250 | } |
||
251 | |||
252 | return $files; |
||
253 | } |
||
254 | |||
255 | /** |
||
256 | * @param string $file |
||
257 | * @param string $to |
||
258 | * |
||
259 | * @return string |
||
260 | */ |
||
261 | protected function getTarget($file, $to) |
||
262 | { |
||
263 | $target = $to . '/' . basename($file); |
||
264 | if ($this->parents !== array(0, 0)) { |
||
265 | // if the parent is set, create additional directories inside target |
||
266 | // get relative path to parentDir |
||
267 | $rel_path = $this->fs->makePathRelative(dirname($file), $this->parentDir); |
||
268 | // get top parents and bottom parents |
||
269 | $parts = explode('/', rtrim($rel_path, '/')); |
||
270 | $prefix_dir = ''; |
||
271 | $prefix_dir .= ($this->parents[0] > 0 ? implode('/', array_slice($parts, 0, $this->parents[0])) . '/' : ''); |
||
272 | $prefix_dir .= ($this->parents[1] > 0 ? implode('/', array_slice($parts, (0 - $this->parents[1]), $this->parents[1])) : ''); |
||
273 | $prefix_dir = rtrim($prefix_dir, '/'); |
||
274 | $target = $to . '/' . $prefix_dir . '/' . basename($file); |
||
275 | } |
||
276 | |||
277 | return $target; |
||
278 | } |
||
279 | |||
280 | /** |
||
281 | * @param array $files |
||
282 | */ |
||
283 | protected function copyFiles($files) |
||
284 | { |
||
285 | // copy the files |
||
286 | foreach ($files as $from => $to) { |
||
287 | // check if target dir exists |
||
288 | if (!is_dir(dirname($to))) { |
||
289 | $this->fs->mkdir(dirname($to), $this->chmod); |
||
290 | } |
||
291 | $this->fs->copy($from, $to); |
||
292 | } |
||
293 | } |
||
294 | } |
||
295 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.