Completed
Push — master ( b69952...eb0a2f )
by ignace nyamagana
07:00
created

Dataset::count()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * League.Period (https://period.thephpleague.com)
5
 *
6
 * (c) Ignace Nyamagana Butera <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace League\Period\Chart;
15
16
use League\Period\Chart\Label\LabelGenerator;
17
use League\Period\Chart\Label\LatinLetter;
18
use League\Period\Period;
19
use League\Period\Sequence;
20
use function array_column;
21
use function count;
22
use function gettype;
23
use function is_scalar;
24
use function method_exists;
25
use function strlen;
26
27
final class Dataset implements Data
28
{
29
    /**
30
     * @var array<int, array{0:string, 1:Sequence}>.
31
     */
32
    private $pairs = [];
33
34
    /**
35
     * @var int
36
     */
37
    private $labelMaxLength = 0;
38
39
    /**
40
     * @var Period|null
41
     */
42
    private $boundaries;
43
44
    /**
45
     * constructor.
46
     */
47 39
    public function __construct(iterable $pairs = [])
48
    {
49 39
        $this->appendAll($pairs);
50 33
    }
51
52
    /**
53
     * Creates a new collection from a countable iterable structure.
54
     *
55
     * @param array|(\Countable&iterable) $items
56
     * @param ?LabelGenerator             $labelGenerator
57
     */
58 9
    public static function fromItems($items, ?LabelGenerator $labelGenerator = null): self
59
    {
60 9
        $nbItems = count($items);
61
        $items = (function () use ($items): \Iterator {
62 9
            foreach ($items as $key => $value) {
63 9
                yield $key => $value;
64
            }
65 9
        })();
66
67 9
        $labelGenerator = $labelGenerator ?? new LatinLetter();
68
69 9
        $pairs = new \MultipleIterator(\MultipleIterator::MIT_NEED_ALL|\MultipleIterator::MIT_KEYS_ASSOC);
70 9
        $pairs->attachIterator($labelGenerator->generate($nbItems), '0');
71 9
        $pairs->attachIterator($items, '1');
72
73 9
        return new self($pairs);
74
    }
75
76
    /**
77
     * Creates a new collection from a generic iterable structure.
78
     */
79 15
    public static function fromIterable(iterable $iterable): self
80
    {
81 15
        $dataset = new self();
82 15
        foreach ($iterable as $label => $item) {
83 12
            $dataset->append($label, $item);
84
        }
85
86 15
        return $dataset;
87
    }
88
89
    /**
90
     * {@inheritDoc}
91
     */
92 39
    public function appendAll(iterable $pairs): void
93
    {
94 39
        foreach ($pairs as [$label, $item]) {
95 21
            $this->append($label, $item);
96
        }
97 33
    }
98
99
    /**
100
     * {@inheritDoc}
101
     */
102 33
    public function append($label, $item): void
103
    {
104 33
        if (!is_scalar($label) && !method_exists($label, '__toString')) {
105 3
            throw new \TypeError('The label passed to '.__METHOD__.' must be a scalar or an stringable object, '.gettype($label).' given.');
106
        }
107
108 30
        if ($item instanceof Period) {
109 15
            $item = new Sequence($item);
110
        }
111
112 30
        if (!$item instanceof Sequence) {
113 3
            throw new \TypeError('The item passed to '.__METHOD__.' must be a '.Period::class.' or a '.Sequence::class.' instance, '.gettype($item).' given.');
114
        }
115
116 27
        $label = (string) $label;
117 27
        $this->setLabelMaxLength($label);
118 27
        $this->setBoundaries($item);
119
120 27
        $this->pairs[] = [$label, $item];
121 27
    }
122
123
    /**
124
     * Computes the label maximum length for the dataset.
125
     */
126 27
    private function setLabelMaxLength(string $label): void
127
    {
128 27
        $labelLength = strlen($label);
129 27
        if ($this->labelMaxLength < $labelLength) {
130 27
            $this->labelMaxLength = $labelLength;
131
        }
132 27
    }
133
134
    /**
135
     * Computes the Period boundary for the dataset.
136
     */
137 27
    private function setBoundaries(Sequence $sequence): void
138
    {
139 27
        if (null === $this->boundaries) {
140 27
            $this->boundaries = $sequence->boundaries();
141
142 27
            return;
143
        }
144
145 18
        $this->boundaries = $this->boundaries->merge(...$sequence);
146 18
    }
147
148
    /**
149
     * {@inheritDoc}
150
     */
151 21
    public function count(): int
152
    {
153 21
        return count($this->pairs);
154
    }
155
156
    /**
157
     * {@inheritDoc}
158
     */
159 3
    public function getIterator(): \Iterator
160
    {
161 3
        foreach ($this->pairs as $pair) {
162 3
            yield $pair;
163
        }
164 3
    }
165
166
    /**
167
     * {@inheritDoc}
168
     */
169 3
    public function jsonSerialize(): array
170
    {
171
        $mapper = static function (array $pair): array {
172 3
            return ['label' => $pair[0], 'item' => $pair[1]];
173 3
        };
174
175 3
        return array_map($mapper, $this->pairs);
176
    }
177
178
    /**
179
     * {@inheritDoc}
180
     */
181 18
    public function isEmpty(): bool
182
    {
183 18
        return [] === $this->pairs;
184
    }
185
186
    /**
187
     * {@inheritDoc}
188
     */
189 6
    public function labels(): array
190
    {
191 6
        return array_column($this->pairs, 0);
192
    }
193
194
    /**
195
     * {@inheritDoc}
196
     */
197 9
    public function items(): array
198
    {
199 9
        return array_column($this->pairs, 1);
200
    }
201
202
    /**
203
     * {@inheritDoc}
204
     */
205 15
    public function boundaries(): ?Period
206
    {
207 15
        return $this->boundaries;
208
    }
209
210
    /**
211
     * {@inheritDoc}
212
     */
213 6
    public function labelMaxLength(): int
214
    {
215 6
        return $this->labelMaxLength;
216
    }
217
218
    /**
219
     * {@inheritDoc}
220
     */
221 6
    public function withLabels(LabelGenerator $labelGenerator): Data
222
    {
223 6
        return self::fromItems($this->items(), $labelGenerator);
224
    }
225
}
226