Completed
Push — master ( b2e536...a4e6dd )
by Arne
02:05
created

Index::getObjectByBlobId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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