Completed
Push — master ( ad9675...44a00f )
by Arne
02:30
created

IndexObject   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 293
Duplicated Lines 0 %

Coupling/Cohesion

Components 5
Dependencies 0

Importance

Changes 0
Metric Value
wmc 39
lcom 5
cbo 0
dl 0
loc 293
rs 9.28
c 0
b 0
f 0

26 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 19 2
A getRelativePath() 0 4 1
A getBasename() 0 6 2
A getType() 0 4 1
A getTypeName() 0 4 1
A isDirectory() 0 4 1
A isFile() 0 4 1
A isLink() 0 4 1
A getMtime() 0 4 1
A getCtime() 0 4 1
A getPermissions() 0 4 1
A getPermissionsString() 0 4 1
A getSize() 0 4 1
A getInode() 0 4 1
A getLinkTarget() 0 4 1
A getHashes() 0 4 1
A getBlobId() 0 4 1
A setBlobId() 0 8 1
B equals() 0 25 7
A offsetExists() 0 4 1
A offsetGet() 0 6 1
A offsetSet() 0 4 1
A offsetUnset() 0 4 1
A __clone() 0 7 2
A __toString() 0 32 5
A getTypeNameMap() 0 8 1
1
<?php
2
3
namespace Storeman\Index;
4
5
use Storeman\Hash\HashContainer;
6
7
/**
8
 * An index object is the representation of one of this filesystem primitives contained in the index.
9
 */
10
class IndexObject implements \ArrayAccess
11
{
12
    public const TYPE_DIR = 1;
13
    public const TYPE_FILE = 2;
14
    public const TYPE_LINK = 3;
15
16
    public const CMP_IGNORE_BLOBID = 1;
17
    public const CMP_IGNORE_INODE = 2;
18
    public const CMP_IGNORE_CTIME = 4;
19
20
21
    /**
22
     * @var string
23
     */
24
    protected $relativePath;
25
26
    /**
27
     * @var int
28
     */
29
    protected $type;
30
31
    /**
32
     * @var float
33
     */
34
    protected $mtime;
35
36
    /**
37
     * @var float
38
     */
39
    protected $ctime;
40
41
    /**
42
     * mode & 0777
43
     *
44
     * @var int
45
     */
46
    protected $permissions;
47
48
    /**
49
     * @var int
50
     */
51
    protected $size;
52
53
    /**
54
     * @var int
55
     */
56
    protected $inode;
57
58
    /**
59
     * @var string
60
     */
61
    protected $linkTarget;
62
63
    /**
64
     * Content hashes for file index objects.
65
     *
66
     * @var HashContainer
67
     */
68
    protected $hashes;
69
70
    /**
71
     * @var string
72
     */
73
    protected $blobId;
74
75
    public function __construct(string $relativePath, int $type, float $mtime, float $ctime, int $permissions, ?int $size, ?int $inode, ?string $linkTarget, ?string $blobId, ?HashContainer $hashContainer)
76
    {
77
        assert(($type === static::TYPE_FILE) ^ ($size === null));
78
        assert(($type === static::TYPE_FILE) || ($blobId === null));
79
        assert(($type === static::TYPE_FILE) ^ ($hashContainer === null));
80
        assert(($type === static::TYPE_LINK) ^ ($linkTarget === null));
81
        assert(!($permissions & ~0777));
82
83
        $this->relativePath = $relativePath;
84
        $this->type = $type;
85
        $this->mtime = $mtime;
86
        $this->ctime = $ctime;
87
        $this->permissions = $permissions;
88
        $this->size = $size;
89
        $this->inode = $inode;
90
        $this->linkTarget = $linkTarget;
91
        $this->blobId = $blobId;
92
        $this->hashes = $hashContainer;
93
    }
94
95
    public function getRelativePath(): string
96
    {
97
        return $this->relativePath;
98
    }
99
100
    public function getBasename(): string
101
    {
102
        $pos = strrpos($this->relativePath, '/');
103
104
        return ($pos === false) ? $this->relativePath : substr($this->relativePath, $pos + 1);
105
    }
106
107
    public function getType(): int
108
    {
109
        return $this->type;
110
    }
111
112
    public function getTypeName(): string
113
    {
114
        return static::getTypeNameMap()[$this->type];
115
    }
116
117
    public function isDirectory(): bool
118
    {
119
        return $this->type === static::TYPE_DIR;
120
    }
121
122
    public function isFile(): bool
123
    {
124
        return $this->type === static::TYPE_FILE;
125
    }
126
127
    public function isLink(): bool
128
    {
129
        return $this->type === static::TYPE_LINK;
130
    }
131
132
    public function getMtime(): float
133
    {
134
        return $this->mtime;
135
    }
136
137
    public function getCtime(): float
138
    {
139
        return $this->ctime;
140
    }
141
142
    public function getPermissions(): int
143
    {
144
        return $this->permissions;
145
    }
146
147
    public function getPermissionsString(): string
148
    {
149
        return decoct($this->permissions);
150
    }
151
152
    public function getSize(): ?int
153
    {
154
        return $this->size;
155
    }
156
157
    public function getInode(): ?int
158
    {
159
        return $this->inode;
160
    }
161
162
    public function getLinkTarget(): ?string
163
    {
164
        return $this->linkTarget;
165
    }
166
167
    public function getHashes(): ?HashContainer
168
    {
169
        return $this->hashes;
170
    }
171
172
    public function getBlobId(): ?string
173
    {
174
        return $this->blobId;
175
    }
176
177
    public function setBlobId(string $blobId): IndexObject
178
    {
179
        assert($this->blobId === null);
180
181
        $this->blobId = $blobId;
182
183
        return $this;
184
    }
185
186
    /**
187
     * Equality check with all attributes.
188
     *
189
     * @param IndexObject $other
190
     * @param int $options
191
     * @return bool
192
     */
193
    public function equals(?IndexObject $other, int $options = 0): bool
194
    {
195
        if ($other === null)
196
        {
197
            return false;
198
        }
199
200
        $equals = true;
201
        $equals &= $this->relativePath === $other->relativePath;
202
        $equals &= $this->type === $other->type;
203
        $equals &= $this->mtime === $other->mtime;
204
        $equals &= ($options & static::CMP_IGNORE_CTIME) || ($this->ctime === $other->ctime);
205
        $equals &= $this->permissions === $other->permissions;
206
        $equals &= $this->size === $other->size;
207
        $equals &= ($options & static::CMP_IGNORE_INODE) || ($this->inode === $other->inode);
208
        $equals &= $this->linkTarget === $other->linkTarget;
209
        $equals &= ($options & static::CMP_IGNORE_BLOBID) || ($this->blobId === $other->blobId);
210
211
        if ($this->hashes && $other->hashes)
212
        {
213
            $equals &= $this->hashes->equals($other->hashes);
214
        }
215
216
        return $equals;
217
    }
218
219
    /**
220
     * @inheritdoc
221
     */
222
    public function offsetExists($offset)
223
    {
224
        return method_exists($this, 'get' . ucfirst($offset));
225
    }
226
227
    /**
228
     * @inheritdoc
229
     */
230
    public function offsetGet($offset)
231
    {
232
        assert(method_exists($this, 'get' . ucfirst($offset)));
233
234
        return call_user_func([$this, 'get' . ucfirst($offset)]);
235
    }
236
237
    /**
238
     * @inheritdoc
239
     */
240
    public function offsetSet($offset, $value)
241
    {
242
        throw new \LogicException();
243
    }
244
245
    /**
246
     * @inheritdoc
247
     */
248
    public function offsetUnset($offset)
249
    {
250
        throw new \LogicException();
251
    }
252
253
    public function __clone()
254
    {
255
        if ($this->hashes !== null)
256
        {
257
            $this->hashes = clone $this->hashes;
258
        }
259
    }
260
261
    public function __toString(): string
262
    {
263
        $inode = $this->inode ?: '-';
264
265
        $parts = [
266
            $this->getTypeName(),
267
            "mtime: {$this->mtime}",
268
            "ctime: {$this->ctime}",
269
            "permissions: {$this->getPermissionsString()}",
270
            "inode: {$inode}"
271
        ];
272
273
        if ($this->isFile())
274
        {
275
            $blobId = $this->blobId ?: '-';
276
277
            $parts = array_merge($parts, [
278
                "size: {$this->size}",
279
                "blobId: {$blobId}",
280
            ]);
281
        }
282
        elseif ($this->isLink())
283
        {
284
            $parts = array_merge($parts, [
285
                "target: {$this->linkTarget}",
286
            ]);
287
        }
288
289
        $attributesString = implode(', ', $parts);
290
291
        return "{$this->relativePath} ({$attributesString})";
292
    }
293
294
    public static function getTypeNameMap(): array
295
    {
296
        return [
297
            static::TYPE_DIR => 'DIR',
298
            static::TYPE_FILE => 'FILE',
299
            static::TYPE_LINK => 'LINK',
300
        ];
301
    }
302
}
303