Completed
Push — master ( ad513f...7b5cd5 )
by Julián
01:23
created

AbstractDTOCollection   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 108
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 3

Importance

Changes 0
Metric Value
wmc 14
lcom 0
cbo 3
dl 0
loc 108
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
A fromElements() 0 4 1
A getElements() 0 4 1
A getIterator() 0 4 1
B verifyElementsType() 0 25 8
A outputElements() 0 4 1
getAllowedType() 0 1 ?
A getAllowedInterfaces() 0 4 1
1
<?php
2
3
/*
4
 * dto (https://github.com/phpgears/dto).
5
 * General purpose immutable Data Transfer Objects for PHP.
6
 *
7
 * @license MIT
8
 * @link https://github.com/phpgears/dto
9
 * @author Julián Gutiérrez <[email protected]>
10
 */
11
12
declare(strict_types=1);
13
14
namespace Gears\DTO;
15
16
use Gears\DTO\Exception\InvalidCollectionTypeException;
17
use Gears\DTO\Exception\InvalidParameterException;
18
use Gears\Immutability\ImmutabilityBehaviour;
19
20
/**
21
 * Abstract immutable Data Transfer Object collection.
22
 */
23
abstract class AbstractDTOCollection implements DTOCollection, \IteratorAggregate
24
{
25
    use ImmutabilityBehaviour, PayloadBehaviour {
26
        PayloadBehaviour::__call insteadof ImmutabilityBehaviour;
27
        __call as private payloadCall;
28
    }
29
30
    /**
31
     * DTOCollection constructor.
32
     *
33
     * @param array<string, mixed> $elements
34
     */
35
    final protected function __construct(array $elements)
36
    {
37
        $this->checkImmutability();
38
39
        $this->verifyElementsType($elements);
40
41
        $this->setPayload(['elements' => \array_values($elements)]);
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    final public static function fromElements(array $elements): DTOCollection
48
    {
49
        return new static($elements);
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55
    public function getElements(): \Traversable
56
    {
57
        return $this->get('elements');
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    final public function getIterator(): \Traversable
64
    {
65
        return $this->get('elements');
66
    }
67
68
    /**
69
     * Verify collection elements type.
70
     *
71
     * @param mixed[] $elements
72
     *
73
     * @throws InvalidCollectionTypeException
74
     * @throws InvalidParameterException
75
     */
76
    private function verifyElementsType(array $elements): void
77
    {
78
        $allowedType = $this->getAllowedType();
79
        if ($allowedType !== DTO::class
80
            && (!\class_exists($allowedType) || !\in_array(DTO::class, \class_implements($allowedType), true))
81
        ) {
82
            throw new InvalidCollectionTypeException(\sprintf(
83
                'Allowed class type for %s should be a %s, %s given',
84
                static::class,
85
                DTO::class,
86
                $allowedType
87
            ));
88
        }
89
90
        foreach ($elements as $element) {
91
            if (!\is_object($element) || !\is_a($element, $allowedType)) {
92
                throw new InvalidParameterException(\sprintf(
93
                    'All elements of %s should be instances of %s, %s given',
94
                    static::class,
95
                    $allowedType,
96
                    \is_object($element) ? \get_class($element) : \gettype($element)
97
                ));
98
            }
99
        }
100
    }
101
102
    /**
103
     * Transform collection elements for output.
104
     *
105
     * @param mixed[] $elements
106
     *
107
     * @return \Traversable
108
     */
109
    final protected function outputElements(array $elements): \Traversable
110
    {
111
        return new \ArrayIterator($elements);
112
    }
113
114
    /**
115
     * Get allowed DTO type for collection elements.
116
     *
117
     * @return string
118
     */
119
    abstract protected function getAllowedType(): string;
120
121
    /**
122
     * {@inheritdoc}
123
     *
124
     * @return string[]
125
     */
126
    final protected function getAllowedInterfaces(): array
127
    {
128
        return [DTOCollection::class, \IteratorAggregate::class];
129
    }
130
}
131