FrameCollection   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 68
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 21
c 1
b 0
f 0
dl 0
loc 68
rs 10
wmc 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A lastIndex() 0 12 2
A __construct() 0 5 1
A assertFrame() 0 8 2
A get() 0 3 1
A initialize() 0 8 2
A assertIsNotEmpty() 0 4 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace AlecRabbit\Spinner\Core;
6
7
use AlecRabbit\Spinner\Contract\IFrame;
8
use AlecRabbit\Spinner\Core\Contract\IFrameCollection;
9
use AlecRabbit\Spinner\Exception\InvalidArgument;
10
use AlecRabbit\Spinner\Exception\LogicException;
11
use ArrayObject;
12
use Traversable;
13
14
/**
15
 * @template T of IFrame
16
 *
17
 * @extends ArrayObject<int,T>
18
 *
19
 * @implements IFrameCollection<T>
20
 */
21
final class FrameCollection extends ArrayObject implements IFrameCollection
22
{
23
    private const COLLECTION_IS_EMPTY = 'Collection is empty.';
24
25
    /**
26
     * @throws InvalidArgument
27
     */
28
    public function __construct(Traversable $frames)
29
    {
30
        parent::__construct();
31
        $this->initialize($frames);
32
        self::assertIsNotEmpty($this);
33
    }
34
35
    /**
36
     * @throws InvalidArgument
37
     */
38
    private function initialize(Traversable $frames): void
39
    {
40
        /**
41
         * @var T $frame
42
         */
43
        foreach ($frames as $frame) {
44
            self::assertFrame($frame);
45
            $this->append($frame);
46
        }
47
    }
48
49
    /**
50
     * @throws InvalidArgument
51
     */
52
    private static function assertFrame(mixed $frame): void
53
    {
54
        if (!$frame instanceof IFrame) {
55
            throw new InvalidArgument(
56
                sprintf(
57
                    '"%s" expected, "%s" given.',
58
                    IFrame::class,
59
                    get_debug_type($frame)
60
                )
61
            );
62
        }
63
    }
64
65
    private static function assertIsNotEmpty(IFrameCollection $collection): void
66
    {
67
        if ($collection->count() === 0) {
68
            throw new InvalidArgument(self::COLLECTION_IS_EMPTY);
69
        }
70
    }
71
72
    public function lastIndex(): int
73
    {
74
        $index = array_key_last($this->getArrayCopy());
75
76
        // @codeCoverageIgnoreStart
77
        if ($index === null) {
78
            // should not be thrown
79
            throw new LogicException(self::COLLECTION_IS_EMPTY);
80
        }
81
        // @codeCoverageIgnoreEnd
82
83
        return $index;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $index could return the type string which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
84
    }
85
86
    public function get(int $index): IFrame
87
    {
88
        return $this->offsetGet($index);
89
    }
90
}
91