Completed
Branch dev (27a5c9)
by Jakob
02:47
created

Container::append()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 1
1
<?php declare(strict_types=1);
2
3
namespace JSKOS;
4
5
use InvalidArgumentException;
6
7
/**
8
 * Common base class of JSKOS Listing, Set, and LanguageMap.
9
 */
10
abstract class Container extends PrettyJsonSerializable implements \Countable, \ArrayAccess, \IteratorAggregate
11
{
12
    protected $members = [];
13
    protected $closed  = true;
14
15
    /**
16
     * Check whether value can be added as member.
17
     *
18
     * @throws InvalidArgumentException if value is no JSKOS Resource
19
     */
20
    protected static function checkMember($value)
21
    {
22
        if ($value instanceof Resource) {
23
            return $value;
24
        } else {
25
            throw new InvalidArgumentException(get_called_class().' may only contain JSKOS Resources');
26
        }
27
    }
28
29
    /**
30
     * Check whether an equal member alredy exists in this Container.
31
     */
32
    protected function findMember($member)
33
    {
34
        return false;
35
    }
36
37
    /**
38
     * Create a new container, possibly from an array.
39
     */
40
    public function __construct(array $members = [])
41
    {
42
        foreach ($members as $m) {
43
            if (is_null($m)) {
44
                $this->closed = false;
45
            } elseif (!$this->findMember($m)) {
46
                $this->members[] = static::checkMember($m);
47
            }
48
        }
49
    }
50
51
    /**
52
     * Apply a function to each member of this container.
53
     * @param $callback callable
54
     */
55
    public function map(callable $callback): array
56
    {
57
        $result = [];
58
59
        foreach ($this->members as $member) {
60
            $result[] = $callback($member);
61
        }
62
63
        return $result;
64
    }
65
66
    /**
67
     * Return whether this container is empty (no members and closed).
68
     */
69
    public function isEmpty(): bool
70
    {
71
        return $this->closed && !count($this->members);
72
    }
73
74
    /**
75
     * Return whether this container is closed.
76
     */
77
    public function isClosed(): bool
78
    {
79
        return $this->closed;
80
    }
81
82
    /**
83
     * Set whether this container is closed (no unknown members) or not.
84
     * @param Boolean $closed
85
     */
86
    public function setClosed(bool $closed = true)
87
    {
88
        $this->closed = $closed;
89
    }
90
91
    # implements Countable
92
93
    /**
94
     * Return the number of known values in this container (closed or not).
95
     */
96
    public function count(): int
97
    {
98
        return count($this->members);
99
    }
100
101
    # implements ArrayAccess:
102
103
    /**
104
     * Return whether an object exists at the given offset.
105
     * @param mixed $offset
106
     */
107
    public function offsetExists($offset)
108
    {
109
        return isset($this->members[$offset]);
110
    }
111
112
    /**
113
     * Return an object at the given offset.
114
     * @param mixed $offset
115
     */
116
    public function offsetGet($offset)
117
    {
118
        return $this->members[$offset];
119
    }
120
121
    /**
122
     * Set an object at the given offset.
123
     * @param mixed $offset
124
     * @param mixed $object
125
     */
126
    public function offsetSet($offset, $object)
127
    {
128
        if (is_int($offset) && $offset >= 0 && $offset < $this->count()) {
129
            $member = static::checkMember($object);
130
            # TODO: merge if duplicated
131
            if (!$this->findMember($member)) {
132
                $this->members[$offset] = $member;
133
            }
134
        } elseif (is_null($object)) {
135
            $this->closed = false;
136
        } else {
137
            $this->append($object);
138
        }
139
    }
140
141
    /**
142
     * Append an object at the end.
143
     */
144
    public function append($object)
145
    {
146
        $member = static::checkMember($object);
147
        # TODO: merge if duplicated
148
        if (!$this->findMember($member)) {
149
            $this->members[] = $member;
150
        }
151
    }
152
153
    /**
154
     * @throws \BadMethodCallException
155
     */
156
    public function offsetUnset($key)
157
    {
158
        throw new \BadMethodCallException(__METHOD__ . ' is not supported');
159
    }
160
161
    # implements IteratorAggregate:
162
163
    /**
164
     * Return an iterator to iterate all members of the set.
165
     */
166
    public function getIterator()
167
    {
168
        return new \ArrayIterator($this->members);
169
    }
170
171
    # extends PrettyJsonSerializable:
172
173
    /**
174
     * Return a data structure to serialize this container as JSON.
175
     */
176
    public function jsonLDSerialize(string $context=self::DEFAULT_CONTEXT)
177
    {
178
        $set = array_map(function ($m) {
179
            return is_object($m) ? $m->jsonLDSerialize('') : $m;
180
        }, $this->members);
181
182
        if (!$this->closed) {
183
            $set[] = null;
184
        }
185
        return $set;
186
    }
187
}
188