Completed
Push — IncomprehensibleFinder/SandraA... ( c60dee )
by Albert
02:20
created

validateCollectionClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 11
c 0
b 0
f 0
ccs 0
cts 10
cp 0
rs 9.9
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Kata\Core;
4
5
abstract class IndexedByPrimitiveCollection implements Collection
6
{
7
    /**
8
     * @var array
9
     */
10
    protected $all_items;
11
12
    /**
13
     * @param array $some_items
14
     */
15
    public function __construct(array $some_items = [])
16
    {
17
        $this->all_items = [];
18
19
        foreach ($some_items as $an_item) {
20
            $this->addItem($an_item);
21
        }
22
    }
23
24
    private function validateItemClass($an_item)
25
    {
26
        $valid_class = $this->collectionItemsClassName();
27
28
        if (!$an_item instanceof $valid_class) {
29
            throw new \InvalidArgumentException(
30
                "You must specify an array of instances of '$valid_class' instead of '" . \get_class($an_item) . "' while creating a '" . static::class . "'."
31
            );
32
        }
33
    }
34
35
    private function validateCollectionClass(Collection $a_collection)
36
    {
37
        $a_collection_class    = \get_class($a_collection);
38
        $this_collection_class = static::class;
39
40
        if ($a_collection_class != $this_collection_class) {
41
            throw new \InvalidArgumentException(
42
                "You can't operate with different kind of collections. You have a '$this_collection_class' and you're specifying a '$a_collection_class'."
43
            );
44
        }
45
    }
46
47
    public function implode($glue = ',')
48
    {
49
        return \implode($glue, $this->allItems());
50
    }
51
52
    // Methods to set, unset and get items.
53
54
    final public function setItemByKey($an_item_key, $an_item)
55
    {
56
        $this->validateItemClass($an_item);
57
58
        $this->all_items[$an_item_key] = $an_item;
59
    }
60
61
    final public function unsetItemByKey($an_item_key)
62
    {
63
        if ($this->hasItemWithKey($an_item_key)) {
64
            unset($this->all_items[$an_item_key]);
65
        }
66
    }
67
68
    final public function addItem($an_item)
69
    {
70
        $this->validateItemClass($an_item);
71
72
        $item_key = $this->nextItemKey($an_item);
73
74
        $this->all_items[$item_key] = $an_item;
75
    }
76
77
    final public function itemsIndexes()
78
    {
79
        return \array_keys($this->all_items);
80
    }
81
82
    final public function itemWithKey($an_item_key)
83
    {
84
        if (!$this->hasItemWithKey($an_item_key)) {
85
            $collection_class = $this->collectionItemsClassName();
86
87
            throw new \OutOfBoundsException("You're trying to get a non existent item with the key $an_item_key from a $collection_class collection.");
88
        }
89
90
        return $this->all_items[$an_item_key];
91
    }
92
93
    final public function allItems()
94
    {
95
        return $this->all_items;
96
    }
97
98
    final public function hasItemWithKey($an_item_key)
99
    {
100
        return \array_key_exists($an_item_key, $this->all_items);
101
    }
102
103
    // Set theory methods.
104
105
    public function union(Collection $a_collection)
106
    {
107
        $this->validateCollectionClass($a_collection);
108
109
        $other_items = $a_collection->allItems();
110
111
        $this->all_items = $other_items + $this->allItems();
112
    }
113
114
    // Iterator methods.
115
116
    final public function current()
117
    {
118
        return \current($this->all_items);
119
    }
120
121
    final public function next()
122
    {
123
        \next($this->all_items);
124
    }
125
126
    final public function key()
127
    {
128
        return \key($this->all_items);
129
    }
130
131
    final public function valid()
132
    {
133
        return \current($this->all_items);
134
    }
135
136
    final public function rewind()
137
    {
138
        \reset($this->all_items);
139
    }
140
141
    final public function count()
142
    {
143
        return \count($this->all_items);
144
    }
145
146
    // Methods to override.
147
148
    /**
149
     * @return string The namespace of the class of each item contained in the {@see $all_items} array. Use the '::class' keyword.
150
     */
151
    abstract protected function collectionItemsClassName();
152
153
    /**
154
     * You can override this method and it'll be called each time you add an item through the {@see addItem} method.
155
     * It returns the next array index by default.
156
     *
157
     * @param mixed $an_item Item of the {@see collectionItemsClassName} class.
158
     *
159
     * @return integer|string the collection key to insert the {@see $an_item}
160
     */
161
    abstract protected function nextItemKey($an_item);
162
}
163