Passed
Push — main ( 8e6204...a1c3a3 )
by James Ekow Abaka
10:05
created

Directory::create()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 26
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 7.0099

Importance

Changes 8
Bugs 0 Features 1
Metric Value
cc 7
eloc 16
c 8
b 0
f 1
nc 8
nop 2
dl 0
loc 26
ccs 16
cts 17
cp 0.9412
crap 7.0099
rs 8.8333
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
 * Represents a directory from the filesystem.
14
 *
15
 * @package ntentan\utils\filesystem
16
 * 
17
 */
18
class Directory implements FileInterface
19
{
20
    const OVERWRITE_MERGE = 4;
21
    const OVERWRITE_SKIP = 8;
22
23
    /**
24
     * Full path to the directory.
25
     *
26
     * @var string
27
     */
28
    private $path;
29
30
    /**
31
     * Create a new instance with a path.
32
     *
33
     * @param string $path Optional path pointed to by new instance. Path does not have to exist.
34
     */
35 6
    public function __construct(string $path = null)
36
    {
37 6
        $this->path = $path;
38 6
    }
39
40
    /**
41
     * Recursively copies directory and its contents to destination.
42
     *
43
     * @param string $destination
44
     * @param int $overwrite
45
     * @throws FileNotFoundException
46
     * @throws FileNotReadableException
47
     * @throws FilesystemException
48
     */
49 1
    public function copyTo(string $destination, int $overwrite = self::OVERWRITE_MERGE): void
50
    {
51 1
        if(file_exists($destination) && ($overwrite & self::OVERWRITE_SKIP)) {
52
            return;
53
        }
54 1
        Filesystem::directory($destination)->createIfNotExists(true);
55 1
        $this->getFiles()->copyTo($destination, $overwrite);
56 1
    }
57
58
    /**
59
     * Recursively get the size of all contents in the directory.
60
     *
61
     * @return integer
62
     * @throws FileNotFoundException
63
     * @throws FilesystemException
64
     * @throws FileNotReadableException
65
     */
66 1
    public function getSize() : int
67
    {
68 1
        return $this->getFiles()->getSize();
69
    }
70
71
    /**
72
     * Recursively move a directory and its contents to another location.
73
     *
74
     * @param string $destination
75
     * @param int $overwrite
76
     * @throws FileNotFoundException
77
     * @throws FileNotReadableException
78
     * @throws FilesystemException
79
     */
80 1
    public function moveTo(string $destination, int $overwrite = self::OVERWRITE_MERGE) : void
81
    {
82 1
        if(file_exists($destination) && ($overwrite & self::OVERWRITE_SKIP)) {
83
            return;
84
        }
85 1
        Filesystem::directory($destination)->createIfNotExists(true);
86 1
        $this->getFiles()->moveTo($destination, $overwrite);
87 1
        $this->delete();
88 1
        $this->path = $destination;
89 1
    }
90
91
    /**
92
     * Create the directory pointed to by path.
93
     *
94
     * @param int $permissions
95
     * @return Directory
96
     * @throws FileAlreadyExistsException
97
     * @throws FileNotWriteableException
98
     */
99 2
    public function create($recursive=false, $permissions = 0755)
100
    {
101 2
        Filesystem::checkNotExists($this->path);
102 2
        $parent = $this->path;
103 2
        if($recursive) {
104 2
            $segments = explode(DIRECTORY_SEPARATOR, $this->path);
105 2
            $parent = "";
106 2
            foreach($segments as $segment) {
107 2
                $parent .= $segment . DIRECTORY_SEPARATOR;
108 2
                if(!is_dir($parent)) {
109 2
                    break;
110
                }
111
            }
112
        }
113 2
        $parent = dirname($parent);
114
        // Loop deeper to make sure the parent directory exists.
115 2
        if($recursive) {
116 2
            while(!is_dir($parent)) {
117
                $parent = dirname($parent);
118
            }    
119
        }
120
        
121 2
        Filesystem::checkWritable($parent == "" ? '.' : $parent);
122 2
        mkdir($this->path, $permissions, true);
123
124 2
        return $this;
125
    }
126
127 2
    public function createIfNotExists($recursive=false, $permissions = 0755)
128
    {
129
        try {
130 2
            $this->create($recursive, $permissions);
131
        } catch (FileAlreadyExistsException $exception) {
132
            // Do nothing
133
        }
134 2
        return $this;
135
    }
136
137
    /**
138
     * Recursively delete the directory and all its contents.
139
     *
140
     * @throws FileNotFoundException
141
     * @throws FilesystemException
142
     * @throws FileNotReadableException
143
     */
144 2
    public function delete() : void
145
    {
146 2
        $this->getFiles()->delete();
147 2
        rmdir($this->path);
148 2
    }
149
150
    /**
151
     * Get the path of the directory.
152
     *
153
     * @return string
154
     */
155 1
    public function getPath() : string
156
    {
157 1
        return $this->path;
158
    }
159
160
    /**
161
     * Get the files in the directory.
162
     *
163
     * @param
164
     *
165
     * @throws FilesystemException
166
     * @throws FileNotFoundException
167
     * @throws FileNotReadableException
168
     * @return FileCollection | array<string>
169
     */
170 5
    public function getFiles(bool $recursive=false, $returnStrings=false)
171
    {
172 5
        Filesystem::checkExists($this->path);
173 5
        Filesystem::checkReadable($this->path);
174 5
        $paths = [];
175
176 5
        $files = scandir($this->path);
177 5
        foreach ($files as $file) {
178 5
            if($file == '.' || $file == '..') continue;
179 5
            $path = "$this->path/$file";
180 5
            if(is_dir($path) && $recursive) {
181
                $paths = array_merge($paths, Filesystem::directory($path)->getFiles(true, true));
182
            }
183 5
            $paths[] = $path;
184
        }
185 5
        return $returnStrings ? $paths : new FileCollection($paths);
186
    }
187
188
    public function deleteIfExists(): void
189
    {
190
        if (file_exists($this->path)) {
191
            $this->delete();
192
        }
193
    }    
194
195 3
    public function __toString()
196
    {
197 3
        return $this->path;
198
    }
199
}
200