Directory::__toString()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
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
    }
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
    }
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
    }
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
        // @todo Confirm that this section is necessary. Doesn't this seem to be a repeat of the above?
116 2
        if($recursive) {
117 2
            while(!is_dir($parent)) {
118
                $parent = dirname($parent);
119
            }    
120
        }
121
        
122 2
        Filesystem::checkWritable($parent == "" ? '.' : $parent);
123 2
        mkdir($this->path, $permissions, true);
124
125 2
        return $this;
126
    }
127
128 2
    public function createIfNotExists($recursive=false, $permissions = 0755)
129
    {
130
        try {
131 2
            $this->create($recursive, $permissions);
132
        } catch (FileAlreadyExistsException $exception) {
133
            // Do nothing
134
        }
135 2
        return $this;
136
    }
137
138
    /**
139
     * Recursively delete the directory and all its contents.
140
     *
141
     * @throws FileNotFoundException
142
     * @throws FilesystemException
143
     * @throws FileNotReadableException
144
     */
145 2
    public function delete() : void
146
    {
147 2
        $this->getFiles()->delete();
148 2
        rmdir($this->path);
149
    }
150
151
    /**
152
     * Get the path of the directory.
153
     *
154
     * @return string
155
     */
156 1
    public function getPath() : string
157
    {
158 1
        return $this->path;
159
    }
160
161
    /**
162
     * Get the files in the directory.
163
     *
164
     * @param
165
     *
166
     * @throws FilesystemException
167
     * @throws FileNotFoundException
168
     * @throws FileNotReadableException
169
     * @return FileCollection | array<string>
170
     */
171 5
    public function getFiles(bool $recursive=false, $returnStrings=false)
172
    {
173 5
        Filesystem::checkExists($this->path);
174 5
        Filesystem::checkReadable($this->path);
175 5
        $paths = [];
176
177 5
        $files = scandir($this->path);
178 5
        foreach ($files as $file) {
179 5
            if($file == '.' || $file == '..') continue;
180 5
            $path = "$this->path/$file";
181 5
            if(is_dir($path) && $recursive) {
182
                $paths = array_merge($paths, Filesystem::directory($path)->getFiles(true, true));
183
            }
184 5
            $paths[] = $path;
185
        }
186 5
        return $returnStrings ? $paths : new FileCollection($paths);
187
    }
188
189
    public function deleteIfExists(): void
190
    {
191
        if (file_exists($this->path)) {
192
            $this->delete();
193
        }
194
    }    
195
196 3
    public function __toString()
197
    {
198 3
        return $this->path;
199
    }
200
}
201