Completed
Push — master ( 2cde75...6c52d6 )
by Arne
02:04
created

Index::addObject()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 21
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 21
rs 9.0534
c 0
b 0
f 0
cc 4
eloc 9
nc 4
nop 1
1
<?php
2
3
namespace Storeman;
4
5
use Storeman\Exception\Exception;
6
use Ramsey\Uuid\Uuid;
7
8
/**
9
 * As the name suggests an index is a representation of the vault at some point in time.
10
 * It is implemented as a map from relative paths to object details.
11
 */
12
class Index implements \Countable, \IteratorAggregate
13
{
14
    /**
15
     * @var IndexObject[]
16
     */
17
    protected $pathMap = [];
18
19
    /**
20
     * Adds the given object to the index.
21
     *
22
     * @param IndexObject $indexObject
23
     * @return Index
24
     * @throws Exception
25
     */
26
    public function addObject(IndexObject $indexObject): Index
27
    {
28
        // ensure existence of containing directory
29
        if (substr_count($indexObject->getRelativePath(), DIRECTORY_SEPARATOR))
30
        {
31
            $parent = $this->getObjectByPath(dirname($indexObject->getRelativePath()));
32
33
            if ($parent === null)
34
            {
35
                throw new Exception();
36
            }
37
            elseif (!$parent->isDirectory())
38
            {
39
                throw new Exception();
40
            }
41
        }
42
43
        $this->pathMap[$indexObject->getRelativePath()] = $indexObject;
44
45
        return $this;
46
    }
47
48
    /**
49
     * Returns an index object by a given relative path.
50
     *
51
     * @param string $path
52
     * @return IndexObject|null
53
     */
54
    public function getObjectByPath(string $path): ?IndexObject
55
    {
56
        return isset($this->pathMap[$path]) ? $this->pathMap[$path] : null;
57
    }
58
59
    /**
60
     * Returns an index object by a given blob id.
61
     *
62
     * @param string $blobId
63
     * @return IndexObject|null
64
     */
65
    public function getObjectByBlobId(string $blobId): ?IndexObject
66
    {
67
        foreach ($this->pathMap as $object)
68
        {
69
            if ($object->getBlobId() === $blobId)
70
            {
71
                return $object;
72
            }
73
        }
74
75
        return null;
76
    }
77
78
    /**
79
     * Returns a new blob id not already present in this index.
80
     *
81
     * @return string
82
     */
83
    public function generateNewBlobId(): string
84
    {
85
        do
86
        {
87
            $blobId = Uuid::uuid4()->toString();
88
        }
89
        while ($this->getObjectByBlobId($blobId) !== null);
90
91
        return $blobId;
92
    }
93
94
    /**
95
     * Compares this index to the given index and returns the comparison result as boolean indicator.
96
     *
97
     * @param Index|null $other
98
     * @return bool
99
     */
100
    public function equals(Index $other = null): bool
101
    {
102
        if ($other === null)
103
        {
104
            return false;
105
        }
106
107
        return $this->isSubsetOf($other) && $other->isSubsetOf($this);
108
    }
109
110
    /**
111
     * Returns true if this index is a subset of the given index.
112
     *
113
     * @param Index $other
114
     * @return bool
115
     */
116
    public function isSubsetOf(Index $other): bool
117
    {
118
        foreach ($this as $indexObject)
119
        {
120
            /** @var IndexObject $indexObject */
121
122
            // we explicitly want to use equality instead of identity
123
            if ($other->getObjectByPath($indexObject->getRelativePath()) != $indexObject)
124
            {
125
                return false;
126
            }
127
        }
128
129
        return true;
130
    }
131
132
    /**
133
     * {@inheritdoc}
134
     */
135
    public function count(): int
136
    {
137
        return count($this->pathMap);
138
    }
139
140
    /**
141
     * {@inheritdoc}
142
     */
143
    public function getIterator(): \Traversable
144
    {
145
        return new \ArrayIterator($this->pathMap);
146
    }
147
}
148