Completed
Push — master ( 65570c...bf6ec7 )
by Arne
03:29 queued 12s
created

IndexObject::equalsOnDisk()   B

Complexity

Conditions 9
Paths 129

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 18
rs 7
c 0
b 0
f 0
cc 9
eloc 12
nc 129
nop 1
1
<?php
2
3
namespace Storeman\Index;
4
5
use Storeman\Exception\Exception;
6
7
/**
8
 * An index object is the representation of one of this filesystem primitives contained in the index.
9
 */
10
class IndexObject
11
{
12
    public const TYPE_DIR = 1;
13
    public const TYPE_FILE = 2;
14
    public const TYPE_LINK = 3;
15
16
17
    /**
18
     * @var string
19
     */
20
    protected $relativePath;
21
22
    /**
23
     * @var int
24
     */
25
    protected $type;
26
27
    /**
28
     * @var int
29
     */
30
    protected $mtime;
31
32
    /**
33
     * @var int
34
     */
35
    protected $ctime;
36
37
    /**
38
     * @var int
39
     */
40
    protected $mode;
41
42
    /**
43
     * @var int
44
     */
45
    protected $size;
46
47
    /**
48
     * @var string
49
     */
50
    protected $linkTarget;
51
52
    /**
53
     * @var string
54
     */
55
    protected $blobId;
56
57
    /**
58
     * Prevent construction not using static factory methods.
59
     */
60
    protected function __construct() {}
61
62
    public function getRelativePath(): string
63
    {
64
        return $this->relativePath;
65
    }
66
67
    public function getBasename(): string
68
    {
69
        $pos = strrpos($this->relativePath, DIRECTORY_SEPARATOR);
70
71
        return ($pos === false) ? $this->relativePath : substr($this->relativePath, $pos + 1);
72
    }
73
74
    public function getType(): int
75
    {
76
        return $this->type;
77
    }
78
79
    public function isDirectory(): bool
80
    {
81
        return $this->type === static::TYPE_DIR;
82
    }
83
84
    public function isFile(): bool
85
    {
86
        return $this->type === static::TYPE_FILE;
87
    }
88
89
    public function isLink(): bool
90
    {
91
        return $this->type === static::TYPE_LINK;
92
    }
93
94
    public function getMtime(): int
95
    {
96
        return $this->mtime;
97
    }
98
99
    public function getCtime(): int
100
    {
101
        return $this->ctime;
102
    }
103
104
    public function getMode(): int
105
    {
106
        return $this->mode;
107
    }
108
109
    public function getSize(): ?int
110
    {
111
        return $this->size;
112
    }
113
114
    public function getLinkTarget(): ?string
115
    {
116
        return $this->linkTarget;
117
    }
118
119
    public function getBlobId(): ?string
120
    {
121
        return $this->blobId;
122
    }
123
124
    public function setBlobId(string $blobId): IndexObject
125
    {
126
        $this->blobId = $blobId;
127
128
        return $this;
129
    }
130
131
    /**
132
     * Equality check with all attributes.
133
     *
134
     * @param IndexObject $other
135
     * @return bool
136
     */
137
    public function equals(?IndexObject $other): bool
138
    {
139
        if (!$this->equalsOnDisk($other))
140
        {
141
            return false;
142
        }
143
144
        $equals = true;
145
        $equals = $equals && ($this->blobId === $other->blobId);
146
147
        return $equals;
148
    }
149
150
    /**
151
     * Comparison without blobId.
152
     *
153
     * @param IndexObject $other
154
     * @return bool
155
     */
156
    public function equalsOnDisk(?IndexObject $other): bool
157
    {
158
        if ($other === null)
159
        {
160
            return false;
161
        }
162
163
        $equal = true;
164
        $equal = $equal && ($this->relativePath === $other->relativePath);
165
        $equal = $equal && ($this->type === $other->type);
166
        $equal = $equal && ($this->mtime === $other->mtime);
167
        $equal = $equal && ($this->ctime === $other->ctime);
168
        $equal = $equal && ($this->mode === $other->mode);
169
        $equal = $equal && ($this->size === $other->size);
170
        $equal = $equal && ($this->linkTarget === $other->linkTarget);
171
172
        return $equal;
173
    }
174
175
    public function toScalarArray(): array
176
    {
177
        return [
178
            $this->relativePath,
179
            $this->type,
180
            $this->mtime,
181
            $this->ctime,
182
            $this->mode,
183
            $this->size,
184
            $this->blobId,
185
            $this->linkTarget,
186
        ];
187
    }
188
189
    public static function fromScalarArray(array $array): IndexObject
190
    {
191
        $object = new static;
192
        $object->relativePath = $array[0];
193
        $object->type = (int)$array[1];
194
        $object->mtime = (int)$array[2];
195
        $object->ctime = (int)$array[3];
196
        $object->mode = (int)$array[4];
197
        $object->size = (int)$array[5];
198
        $object->blobId = $array[6];
199
        $object->linkTarget = $array[7];
200
201
        return $object;
202
    }
203
204
    /**
205
     * Returns an instance representing the filesystem object that can be found under the given path.
206
     *
207
     * @param string $basePath
208
     * @param string $relativePath
209
     * @return IndexObject
210
     */
211
    public static function fromPath(string $basePath, string $relativePath): IndexObject
212
    {
213
        $absolutePath = rtrim($basePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $relativePath;
214
215
        clearstatcache(null, $absolutePath);
216
217
        if (!($stat = @lstat($absolutePath)))
218
        {
219
            throw new Exception("lstat() failed for {$absolutePath}");
220
        }
221
222
        $object = new static;
223
        $object->relativePath = $relativePath;
224
        $object->mtime = $stat['mtime'];
225
        $object->ctime = $stat['ctime'];
226
        $object->mode = $stat['mode'];
227
228
        if (is_link($absolutePath))
229
        {
230
            $object->type = static::TYPE_LINK;
231
            $object->linkTarget = str_replace($basePath, '', readlink($absolutePath));
232
        }
233
        elseif (is_file($absolutePath))
234
        {
235
            $object->type = static::TYPE_FILE;
236
            $object->size = (int)$stat['size'];
237
        }
238
        elseif (is_dir($absolutePath))
239
        {
240
            $object->type = static::TYPE_DIR;
241
        }
242
        else
243
        {
244
            throw new \LogicException();
245
        }
246
247
        return $object;
248
    }
249
}
250