Completed
Push — master ( ef5bef...038c42 )
by Arne
02:22
created

IndexObject::equals()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 25
rs 9.52
c 0
b 0
f 0
cc 3
nc 3
nop 2
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
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
19
20
    /**
21
     * @var string
22
     */
23
    protected $relativePath;
24
25
    /**
26
     * @var int
27
     */
28
    protected $type;
29
30
    /**
31
     * @var int
32
     */
33
    protected $mtime;
34
35
    /**
36
     * @var int
37
     */
38
    protected $ctime;
39
40
    /**
41
     * mode & 0777
42
     *
43
     * @var int
44
     */
45
    protected $permissions;
46
47
    /**
48
     * @var int
49
     */
50
    protected $size;
51
52
    /**
53
     * @var int
54
     */
55
    protected $inode;
56
57
    /**
58
     * @var string
59
     */
60
    protected $linkTarget;
61
62
    /**
63
     * Content hashes for file index objects.
64
     *
65
     * @var HashContainer
66
     */
67
    protected $hashes;
68
69
    /**
70
     * @var string
71
     */
72
    protected $blobId;
73
74
    public function __construct(string $relativePath, int $type, int $mtime, int $ctime, int $permissions, ?int $size, ?int $inode, ?string $linkTarget, ?string $blobId, ?HashContainer $hashContainer)
75
    {
76
        assert(($type === static::TYPE_FILE) ^ ($size === null));
77
        assert(($type === static::TYPE_FILE) || ($blobId === null));
78
        assert(($type === static::TYPE_FILE) ^ ($hashContainer === null));
79
        assert(($type === static::TYPE_LINK) ^ ($linkTarget === null));
80
        assert(!($permissions & ~0777));
81
82
        $this->relativePath = $relativePath;
83
        $this->type = $type;
84
        $this->mtime = $mtime;
85
        $this->ctime = $ctime;
86
        $this->permissions = $permissions;
87
        $this->size = $size;
88
        $this->inode = $inode;
89
        $this->linkTarget = $linkTarget;
90
        $this->blobId = $blobId;
91
        $this->hashes = $hashContainer;
92
    }
93
94
    public function getRelativePath(): string
95
    {
96
        return $this->relativePath;
97
    }
98
99
    public function getBasename(): string
100
    {
101
        $pos = strrpos($this->relativePath, '/');
102
103
        return ($pos === false) ? $this->relativePath : substr($this->relativePath, $pos + 1);
104
    }
105
106
    public function getType(): int
107
    {
108
        return $this->type;
109
    }
110
111
    public function getTypeName(): string
112
    {
113
        return static::getTypeNameMap()[$this->type];
114
    }
115
116
    public function isDirectory(): bool
117
    {
118
        return $this->type === static::TYPE_DIR;
119
    }
120
121
    public function isFile(): bool
122
    {
123
        return $this->type === static::TYPE_FILE;
124
    }
125
126
    public function isLink(): bool
127
    {
128
        return $this->type === static::TYPE_LINK;
129
    }
130
131
    public function getMtime(): int
132
    {
133
        return $this->mtime;
134
    }
135
136
    public function getCtime(): int
137
    {
138
        return $this->ctime;
139
    }
140
141
    public function getPermissions(): int
142
    {
143
        return $this->permissions;
144
    }
145
146
    public function getPermissionsString(): string
147
    {
148
        return decoct($this->permissions);
149
    }
150
151
    public function getSize(): ?int
152
    {
153
        return $this->size;
154
    }
155
156
    public function getInode(): ?int
157
    {
158
        return $this->inode;
159
    }
160
161
    public function getLinkTarget(): ?string
162
    {
163
        return $this->linkTarget;
164
    }
165
166
    public function getHashes(): ?HashContainer
167
    {
168
        return $this->hashes;
169
    }
170
171
    public function getBlobId(): ?string
172
    {
173
        return $this->blobId;
174
    }
175
176
    public function setBlobId(string $blobId): IndexObject
177
    {
178
        $this->blobId = $blobId;
179
180
        return $this;
181
    }
182
183
    /**
184
     * Equality check with all attributes.
185
     *
186
     * @param IndexObject $other
187
     * @param int $options
188
     * @return bool
189
     */
190
    public function equals(?IndexObject $other, int $options = 0): bool
191
    {
192
        if ($other === null)
193
        {
194
            return false;
195
        }
196
197
        $equals = true;
198
        $equals &= $this->relativePath === $other->relativePath;
199
        $equals &= $this->type === $other->type;
200
        $equals &= $this->mtime === $other->mtime;
201
        $equals &= $this->ctime === $other->ctime;
202
        $equals &= $this->permissions === $other->permissions;
203
        $equals &= $this->size === $other->size;
204
        $equals &= ($options & static::CMP_IGNORE_INODE) | ($this->inode === $other->inode);
205
        $equals &= $this->linkTarget === $other->linkTarget;
206
        $equals &= ($options & static::CMP_IGNORE_BLOBID) | ($this->blobId === $other->blobId);
207
208
        if ($this->hashes)
209
        {
210
            $equals = $equals & $this->hashes->equals($other->hashes);
211
        }
212
213
        return $equals;
214
    }
215
216
    public function __toString(): string
217
    {
218
        $inode = $this->inode ?: '-';
219
220
        $parts = [
221
            $this->getTypeName(),
222
            "mtime: {$this->mtime}",
223
            "ctime: {$this->ctime}",
224
            "permissions: {$this->getPermissionsString()}",
225
            "inode: {$inode}"
226
        ];
227
228
        if ($this->isFile())
229
        {
230
            $blobId = $this->blobId ?: '-';
231
232
            $parts = array_merge($parts, [
233
                "size: {$this->size}",
234
                "blobId: {$blobId}",
235
            ]);
236
        }
237
        elseif ($this->isLink())
238
        {
239
            $parts = array_merge($parts, [
240
                "target: {$this->linkTarget}",
241
            ]);
242
        }
243
244
        $attributesString = implode(', ', $parts);
245
246
        return "{$this->relativePath} ({$attributesString})";
247
    }
248
249
    public static function getTypeNameMap(): array
250
    {
251
        return [
252
            static::TYPE_DIR => 'DIR',
253
            static::TYPE_FILE => 'FILE',
254
            static::TYPE_LINK => 'LINK',
255
        ];
256
    }
257
}
258