Completed
Push — dev ( 9392d7...313ec9 )
by James Ekow Abaka
01:32
created

Directory::copyTo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace ntentan\utils\filesystem;
4
5
use ntentan\utils\exceptions\FileAlreadyExistsException;
6
use ntentan\utils\exceptions\FileNotFoundException;
7
use ntentan\utils\exceptions\FileNotReadableException;
8
use ntentan\utils\exceptions\FileNotWriteableException;
9
use ntentan\utils\Filesystem;
10
use ntentan\utils\exceptions\FilesystemException;
11
12
/**
13
 * A directory on the filesystem.
14
 *
15
 * @package ntentan\utils\filesystem
16
 */
17
class Directory implements FileInterface
18
{
19
20
    /**
21
     * Full path to the directory.
22
     *
23
     * @var string
24
     */
25
    private $path;
26
27
    /**
28
     * Create a new instance with a path.
29
     *
30
     * @param string $path Optional path pointed to by new instance. Path does not have to exist.
31
     */
32 6
    public function __construct(string $path = null)
33
    {
34 6
        $this->path = $path;
35 6
    }
36
37
    /**
38
     * Used to perform copies and moves.
39
     *
40
     * @param string $operation
41
     * @param string $destination
42
     * @throws FileNotFoundException
43
     * @throws FilesystemException
44
     * @throws FileAlreadyExistsException
45
     * @throws FileNotReadableException
46
     * @throws FileNotWriteableException
47
     */
48 2
    private function directoryOperation(string $operation, string $destination):void
49
    {
50
        try {
51 2
            Filesystem::checkExists($destination);
52
            $destination = $destination . DIRECTORY_SEPARATOR . basename($this);
53 2
        } catch (FileNotFoundException $e) {
54 2
            Filesystem::directory($destination)->create(true);
55
        }
56
57 2
        foreach ($this->getFiles() as $file) {
58 2
            $file->$operation($destination . DIRECTORY_SEPARATOR . basename($file));
59
        }
60 2
    }
61
62
    /**
63
     * Recursively copies directory and its contents to destination.
64
     *
65
     * @param string $destination
66
     * @throws FileNotFoundException
67
     * @throws FilesystemException
68
     * @throws FileAlreadyExistsException
69
     * @throws FileNotReadableException
70
     * @throws FileNotWriteableException
71
     */
72 1
    public function copyTo(string $destination): void
73
    {
74 1
        $this->directoryOperation('copyTo', $destination);
75 1
    }
76
77
    /**
78
     * Recursively get the size of all contents in the directory.
79
     *
80
     * @return integer
81
     * @throws FileNotFoundException
82
     * @throws FilesystemException
83
     * @throws FileNotReadableException
84
     */
85 1
    public function getSize() : int
86
    {
87 1
        return $this->getFiles()->getSize();
88
    }
89
90
    /**
91
     * Recursively move a directory and its contents to another location.
92
     *
93
     * @param string $destination
94
     * @throws FileNotFoundException
95
     * @throws FilesystemException
96
     * @throws FileAlreadyExistsException
97
     * @throws FileNotReadableException
98
     * @throws FileNotWriteableException
99
     */
100 1
    public function moveTo(string $destination) : void
101
    {
102 1
        $this->directoryOperation('moveTo', $destination);
103 1
        $this->delete();
104 1
        $this->path = $destination;
105 1
    }
106
107
    /**
108
     * Create the directory pointed to by path.
109
     *
110
     * @param int $permissions
111
     * @throws FileAlreadyExistsException
112
     * @throws FileNotWriteableException
113
     */
114 2
    public function create($recursive=false, $permissions = 0755)
115
    {
116 2
        Filesystem::checkNotExists($this->path);
117 2
        if($recursive) {
118 2
            $parsedPath = parse_url($this->path);
119 2
            $segments = explode(DIRECTORY_SEPARATOR, $parsedPath['path']);
120 2
            $scheme = $parsedPath['scheme'] ?? '';
121 2
            $host = $parsedPath['host'] ?? '';
122 2
            array_unshift($segments, $scheme . ':' . DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR . $host);
123 2
            $accumulator = "";
124 2
            $parent = "";
125 2
            foreach($segments as $segment) {
126 2
                $accumulator .= $segment . DIRECTORY_SEPARATOR;
127 2
                if(is_dir($accumulator)) {
128 2
                    $parent = $accumulator;
129
                } else {
130 2
                    break;
131
                }
132
            }
133
        } else {
134
            $parent = dirname($this->path);
135
        }
136 2
        Filesystem::checkWritable($parent == "" ? "." : $parent);
137 2
        mkdir($this->path, $permissions, true);
138 2
    }
139
140
    /**
141
     * Recursively delete the directory and all its contents.
142
     *
143
     * @throws FileNotFoundException
144
     * @throws FilesystemException
145
     * @throws FileNotReadableException
146
     */
147 2
    public function delete() : void
148
    {
149 2
        $this->getFiles()->delete();
150 2
        rmdir($this->path);
151 2
    }
152
153
    /**
154
     * Get the path of the directory.
155
     *
156
     * @return string
157
     */
158 1
    public function getPath() : string
159
    {
160 1
        return $this->path;
161
    }
162
163
    /**
164
     * Get the files in the directory.
165
     *
166
     * @throws FilesystemException
167
     * @throws FileNotFoundException
168
     * @throws FileNotReadableException
169
     * @return array<FileInterface>
0 ignored issues
show
Documentation introduced by
Should the return type not be FileCollection?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
170
     */
171 5
    public function getFiles() : FileCollection
172
    {
173 5
        Filesystem::checkExists($this->path);
174 5
        Filesystem::checkReadable($this->path);
175 5
        $contents = [];
176
177 5
        $files = scandir($this->path);
178 5
        foreach ($files as $file) {
179 5
            if($file != '.' && $file != '..') {
180 5
                $contents[] = "$this->path/$file";
181
            }
182
        }
183 5
        return new FileCollection($contents);
184
    }
185
186 3
    public function __toString()
187
    {
188 3
        return $this->path;
189
    }
190
}
191