Completed
Push — master ( c4ac52...523efa )
by Roman
01:58
created

Collection::sum()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace kartavik\Designer;
4
use kartavik\Designer\Tests\Mocks\Element;
5
6
/**
7
 * Class Collection
8
 * @package kartavik\Designer
9
 */
10
abstract class Collection extends \ArrayObject implements \JsonSerializable
11
{
12
    /** @var string */
13
    protected $type = null;
14
15
    /**
16
     * Collection constructor.
17
     *
18
     * @param array  $elements
19
     * @param string $type
20
     * @param int    $flags
21
     * @param string $iteratorClass
22
     */
23
    public function __construct(
24
        array $elements = [],
25
        string $type = null,
26
        int $flags = 0,
27
        string $iteratorClass = \ArrayIterator::class
28
    ) {
29
        $this->type = $type;
30
31
        foreach ($elements as $element) {
32
            $this->instanceOfType($element);
33
        }
34
35
        parent::__construct($elements, $flags, $iteratorClass);
36
    }
37
38
    abstract public function type(): string;
39
40
    /**
41
     * @param mixed $value
42
     *
43
     * @throws InvalidElementException
44
     */
45
    public function append($value): void
46
    {
47
        $this->instanceOfType($value);
48
49
        parent::append($value);
50
    }
51
52
    /**
53
     * @param mixed $index
54
     * @param mixed $value
55
     *
56
     * @throws InvalidElementException
57
     */
58
    public function offsetSet($index, $value): void
59
    {
60
        $this->instanceOfType($value);
61
62
        parent::offsetSet($index, $value);
63
    }
64
65
    public function jsonSerialize(): array
66
    {
67
        return (array)$this;
68
    }
69
70
    /**
71
     * @param $object
72
     *
73
     * @throws InvalidElementException
74
     */
75
    public function instanceOfType($object): void
76
    {
77
        $type = $this->type();
78
79
        if (!$object instanceof $type) {
80
            throw new InvalidElementException($object, $type);
81
        }
82
    }
83
84
    public function map(callable $function, Collection ...$arrays): Collection
85
    {
86
        $mappedType = get_class(call_user_func(
87
            $function,
88
            $this->offsetGet(0)
89
        ));
90
91
        return Collection::{$mappedType}(array_map(
92
            $function,
93
            $this->jsonSerialize(),
94
            $arrays
95
        ));
96
    }
97
98
    public function chunk(int $size): Collection
99
    {
100
        $mappedType = get_class($this->offsetGet(0));
101
        /** @var Collection $collection */
102
        $collection = Collection::{Collection::class}();
103
        $chunked = array_chunk($this->jsonSerialize(), $size);
104
105
        foreach ($chunked as $index => $chunk) {
106
            $collection->append(Collection::{$mappedType}());
107
108
            foreach ($chunk as $item) {
109
                $collection[$index]->append($item);
110
            }
111
        }
112
113
        return $collection;
114
    }
115
116
    public function column(string $getter, callable $function = null): Collection
117
    {
118
        $getterType = get_class($this->offsetGet(0)->{$getter}());
119
120
        if (!is_null($function)) {
121
            /** @var Collection $collection */
122
            $collection = Collection::{$getterType}();
123
124
            foreach ($this->jsonSerialize() as $item) {
125
                $collection->append(call_user_func($function, $item->{$getter}()));
126
            }
127
128
            return $collection;
129
        } else {
130
            return Collection::{$getterType}(array_map(
131
                function ($item) use ($getter) {
132
                    return $item->{$getter}();
133
                },
134
                $this->jsonSerialize()
135
            ));
136
        }
137
    }
138
139
    public function pop()
140
    {
141
        $element = $this->offsetGet($this->count() - 1);
142
        $this->offsetUnset($this->count() - 1);
143
144
        return $element;
145
    }
146
147
    public function sum(callable $function)
148
    {
149
        $sum = 0;
150
151
        foreach ($this as $element) {
152
            $sum += call_user_func($function, $element);
153
        }
154
155
        return $sum;
156
    }
157
158
    /**
159
     * @param $name
160
     * @param $arguments
161
     *
162
     * @return Collection
163
     */
164
    public static function __callStatic($name, $arguments)
165
    {
166
        if (!empty($arguments) && is_array($arguments[0])) {
167
            $arguments = $arguments[0];
168
        }
169
170
        if (!class_exists($name)) {
171
            throw new \BadMethodCallException("Class with name {$name} does not exist!");
172
        }
173
174
        return new class($arguments, $name) extends Collection
175
        {
176
            public function type(): string
177
            {
178
                return $this->type;
179
            }
180
        };
181
    }
182
}
183