Shell::__construct()   A
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 8
nop 1
dl 0
loc 9
ccs 7
cts 7
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * DronePHP (http://www.dronephp.com)
4
 *
5
 * @link      http://github.com/Pleets/DronePHP
6
 * @copyright Copyright (c) 2016-2018 Pleets. (http://www.pleets.org)
7
 * @license   http://www.dronephp.com/license
8
 * @author    Darío Rivera <[email protected]>
9
 */
10
11
namespace Drone\FileSystem;
12
13
use Drone\Error\Errno;
14
15
/**
16
 * Shell class
17
 *
18
 * This class represents a system terminal
19
 */
20
class Shell implements ShellInterface
21
{
22
    use \Drone\Error\ErrorTrait;
23
24
    /**
25
     * Home directory (~)
26
     *
27
     * @var string
28
     */
29
    private $home;
30
31
    /**
32
     * Result of last command (optional)
33
     *
34
     * @var string
35
     */
36
    private $buffer = null;
37
38
    /**
39
     * Returns the home attribute
40
     *
41
     * @return string
42
     */
43 1
    public function getHome()
44
    {
45 1
        return $this->home;
46
    }
47
48
    /**
49
     * Returns the buffer attribute
50
     *
51
     * @return mixed
52
     */
53 5
    public function getBuffer()
54
    {
55 5
        return $this->buffer;
56
    }
57
58
    /**
59
     * Constructor
60
     *
61
     * @param string $home
62
     */
63 15
    public function __construct($home = null)
64
    {
65 15
        $this->home = (is_null($home) || empty($home))
66 2
            ? ($this->pwd() !== false)
67 2
                ? $this->pwd()
68 2
                : $home
69 13
            : $home;
70
71 15
        $this->cd($this->home);
72 15
    }
73
74
    /**
75
     * Iterative function for directories and files
76
     *
77
     * @param string   $directory
78
     * @param callable $fileCallback
79
     * @param callable $dirCallback
80
     * @param callable $callback
81
     *
82
     * @return array
83
     */
84 6
    public function getContents($directory, $fileCallback = null, $dirCallback = null, $callback = null)
85
    {
86 6
        $contents = $allContents = [];
87
88 6
        if (is_dir($directory)) {
89 6
            foreach ($this->ls($directory) as $item) {
90 6
                if ($item != '.' && $item != '..') {
91 6
                    $contents[] = $item;
92
                }
93
            }
94
95 6
            if (count($contents) > 0) {
96 6
                foreach ($contents as $i) {
97 6
                    if (is_file($directory.'/'.$i)) {
98 6
                        $allContents[] = $i;
99
100 6
                        $this->buffer = $directory.'/'.$i;
101 6
                        call_user_func($fileCallback, $this);
102 4
                    } elseif (is_dir($directory.'/'.$i)) {
103 4
                        $directory_name = basename($directory).'/'.$i;
104
105 4
                        if (strpos($directory_name, './') === 0) {
106 1
                            $from = './';
107 1
                            $from = '/'.preg_quote($from, '/').'/';
108 1
                            $directory_name = preg_replace($from, "", $directory_name, 1);
109
                        }
110
111 4
                        $allContents[$directory_name] =
112 4
                            $this->getContents($directory.'/'.$i, $fileCallback, $dirCallback);
113
114 4
                        $this->buffer = $directory.'/'.$i;
115 6
                        call_user_func($dirCallback, $this);
116
                    }
117
                }
118
            }
119
        } elseif (is_file($directory)) {
120
            throw new \InvalidArgumentException("'$directory' is actually a file");
121
        } else {
122
            throw new \InvalidArgumentException("The directory '$directory' does not exists");
123
        }
124
125 6
        if (!is_null($callback)) {
126 5
            call_user_func($callback, $this);
127
        }
128
129 6
        return $allContents;
130
    }
131
132
    /**
133
     * Returns the curent directory
134
     *
135
     * @return string|boolean
136
     */
137 4
    public function pwd()
138
    {
139 4
        if (getcwd()) {
140 4
            $this->buffer = getcwd();
141
        } else {
142
            return false;
143
        }
144
145 4
        return $this->buffer;
146
    }
147
148
    /**
149
     * Returns a list with directory contents
150
     *
151
     * @param string|null $path
152
     * @param boolean     $recursive
153
     *
154
     * @return array
155
     */
156 7
    public function ls($path = null, $recursive = false)
157
    {
158 7
        $filesToReturn = [];
159
160 7
        $path = (is_null($path) || empty($path)) ? '.' : $path;
161
162 7
        if (is_file($path)) {
163
            $filesToReturn = [$path];
164 7
        } elseif (is_dir($path)) {
165 7
            $pathIns = dir($path);
166
167 7
            if ($recursive) {
168 1
                $filesToReturn = $this->getContents($path);
169
            } else {
170 7
                while (($item = $pathIns->read()) !== false) {
171 7
                    if ($item != '.' && $item != '..') {
172 7
                        $filesToReturn[] = $item;
173
                    }
174
                }
175
176 7
                $pathIns->close();
177
            }
178
        } else {
179
            $contents = $this->ls();
180
181
            foreach ($contents as $item) {
182
                if (!empty($path)) {
183
                    if (!strlen(stristr($item, $path)) > 0) {
184
                        continue;
185
                    }
186
                }
187
                if (strstr($item, '~') === false && $item != '.' && $item != '..') {
188
                    $filesToReturn[] = $item;
189
                }
190
            }
191
        }
192
193 7
        return $filesToReturn;
194
    }
195
196
    /**
197
     * Changes the current directory
198
     *
199
     * @param string|null $path
200
     *
201
     * @return boolean
202
     */
203 15
    public function cd($path = null)
204
    {
205 15
        $path = (is_null($path) || empty($path)) ? $this->home : $path;
206
207 15
        if (is_dir($path)) {
208 15
            if (chdir($path)) {
209 15
                return true;
210
            }
211
        }
212
213
        return false;
214
    }
215
216
    /**
217
     * Changes the file's date
218
     *
219
     * @param string
220
     * @param mixed $file
221
     *
222
     * @return boolean
223
     */
224 2
    public function touch($file)
225
    {
226 2
        $contents = file_exists($file) ? file_get_contents($file) : "";
227
228 2
        $hd = @fopen($file, "w+");
229
230 2
        if (!$hd || @fwrite($hd, $contents) === false) {
0 ignored issues
show
introduced by
$hd is of type false|resource, thus it always evaluated to false.
Loading history...
231
            $this->error(Errno::FILE_PERMISSION_DENIED, $file);
0 ignored issues
show
Bug introduced by
The method error() does not exist on Drone\FileSystem\Shell. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

231
            $this->/** @scrutinizer ignore-call */ 
232
                   error(Errno::FILE_PERMISSION_DENIED, $file);
Loading history...
232
233
            return false;
234
        }
235
236 2
        @fclose($hd);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for fclose(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

236
        /** @scrutinizer ignore-unhandled */ @fclose($hd);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
237
238 2
        return true;
239
    }
240
241
    /**
242
     * Deletes one or more files or directories
243
     *
244
     * @param string  $file
245
     * @param boolean $recursive
246
     *
247
     * @return boolean
248
     */
249 5
    public function rm($file, $recursive = false)
250
    {
251 5
        if (is_null($file)) {
0 ignored issues
show
introduced by
The condition is_null($file) is always false.
Loading history...
252
            throw new \InvalidArgumentException("Missing first parameter");
253
        }
254
255 5
        if (file_exists($file) && !$recursive) {
256 1
            unlink($file);
257 4
        } elseif (is_dir($file) && $recursive) {
258 4
            $that = $this;
259
260 4
            $this->getContents(
261 4
                $file,
262
                # file's callback
263
                function () use ($that) {
264 4
                    unlink($that->getBuffer());
265 4
                },
266
                # folder's callback
267
                function () use ($that) {
268 2
                    rmdir($that->getBuffer());
269 4
                },
270
                # final callback
271
                function () use ($file) {
272 4
                    @rmdir($file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for rmdir(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

272
                    /** @scrutinizer ignore-unhandled */ @rmdir($file);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
273 4
                }
274
            );
275
        }
276
277 5
        return true;
278
    }
279
280
    /**
281
     * Copies one or more files or directories
282
     *
283
     * @param string       $file
284
     * @param string       $dest
285
     * @param boolean      $recursive
286
     *
287
     * @return boolean
288
     */
289 2
    public function cp($file, $dest, $recursive = false)
290
    {
291 2
        if (empty($file) || empty($dest)) {
292
            throw new \InvalidArgumentException("Missing parameters");
293
        }
294
295 2
        if (is_dir($file) && !$recursive) {
296 1
            throw new \RuntimeException("Ommiting directory <<$foo>>");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $foo seems to be never defined.
Loading history...
297
        }
298
299 2
        $dest_exists = file_exists($dest);
300
301 2
        if (is_dir($file) && (is_dir($dest) || !$dest_exists)) {
302
            $files = [
303 1
                "files"   => [],
304
                "folders" => [],
305
            ];
306
307 1
            $files["folders"][] = is_dir($dest) ? basename($file) : $dest;
308
309 1
            if (!$dest_exists) {
310 1
                mkdir($dest);
311
            }
312
313 1
            $that = $this;
314
315 1
            $this->getContents(
316 1
                $file,
317
                # file's callback
318
                function () use ($that, &$files) {
319 1
                    $files["files"][] = $that->getBuffer();
320 1
                },
321
                # folder's callback
322
                function () use ($that, &$files) {
323 1
                    $files["folders"][] = $that->getBuffer();
324 1
                },
325
                # final callback
326
                function () use (&$files, $file, $dest, $dest_exists) {
327 1
                    if ($dest_exists) {
328 1
                        foreach ($files["folders"] as $folder) {
329 1
                            if (!file_exists($dest.'/'.$folder)) {
330 1
                                mkdir("$dest/$folder", 0777, true);
331
                            }
332
                        }
333
334 1
                        if (count($files["files"])) {
335 1
                            foreach ($files["files"] as $item) {
336 1
                                if (!file_exists("$dest/$item")) {
337 1
                                    copy($item, $dest.'/'.$item);
338
                                }
339
                            }
340
                        }
341
                    } else {
342
                        # directory previoulsy created
343 1
                        array_shift($files["folders"]);
344
345 1
                        $from = "$file/";
346 1
                        $from = '/'.preg_quote($from, '/').'/';
347
348 1
                        if (count($files["folders"])) {
349 1
                            foreach ($files["folders"] as $folder) {
350 1
                                $_folder = preg_replace($from, "", $folder, 1);
351
352 1
                                if (!file_exists($dest.'/'.$_folder)) {
353 1
                                    mkdir("$dest/$_folder", 0777, true);
354
                                }
355
                            }
356
                        }
357
358 1
                        if (count($files["files"])) {
359 1
                            foreach ($files["files"] as $item) {
360 1
                                $_item = preg_replace($from, "", $item, 1);
361
362 1
                                if (!file_exists("$dest/$_item")) {
363 1
                                    copy($item, $dest.'/'.$_item);
364
                                }
365
                            }
366
                        }
367
                    }
368 1
                }
369
            );
370 1
        } elseif (is_dir($dest)) {
371 1
            copy($file, $dest.'/'.$file);
372
        } else {
373 1
            copy($file, $dest);
374
        }
375
376 2
        return true;
377
    }
378
379
    /**
380
     * Moves or renames files
381
     *
382
     * @param string $oldfile
383
     * @param string $newfile
384
     *
385
     * @return boolean
386
     */
387 2
    public function mv($oldfile, $newfile)
388
    {
389 2
        if (empty($oldfile) || empty($newfile)) {
390
            throw new \InvalidArgumentException("Missing parameters");
391
        }
392
393 2
        if (is_dir($newfile)) {
394 1
            $newfile .= '/'.basename($oldfile);
395
        }
396
397 2
        if ($oldfile == $newfile) {
398
            throw new \Exception("'$oldfile' and '$newfile' are the same file");
399
        }
400
401 2
        if (!rename($oldfile, $newfile)) {
402
            return false;
403
        }
404
405 2
        return true;
406
    }
407
408
    /**
409
     * Creates a directory
410
     *
411
     * @param string       $dir
412
     * @param string|null  $dest
413
     * @param boolean|null $recursive
414
     *
415
     * @return boolean
416
     */
417 1
    public function mkdir($dir, $dest = null, $recursive = null)
418
    {
419 1
        if (empty($dir)) {
420
            throw new \InvalidArgumentException("Missing first parameter");
421
        }
422
423 1
        if (empty($dest)) {
424 1
            $dest = '.';
425
        }
426
427 1
        $recursive = (is_null($recursive)) ? false : $recursive;
428
429 1
        if ($recursive) {
430
            mkdir("$dest/$dir", 0777, true);
431
        } else {
432 1
            if (!is_dir($dir)) {
433 1
                if (!mkdir("$dir", 0777)) {
434
                    return false;
435
                }
436
            }
437
        }
438
439 1
        return true;
440
    }
441
442
    /**
443
     * Deletes a directory
444
     *
445
     * @param string $dir
446
     *
447
     * @return boolean
448
     */
449 1
    public function rmdir($dir)
450
    {
451 1
        if (is_null($dir) || empty($dir)) {
452
            throw new \RuntimeException("Missing first parameter");
453
        }
454
455 1
        if (rmdir($dir)) {
456 1
            return true;
457
        } else {
458
            return false;
459
        }
460
    }
461
}
462