TypedCollection::validateItem()   A
last analyzed

Complexity

Conditions 3
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 0
Metric Value
cc 3
eloc 6
nc 1
nop 1
dl 0
loc 11
ccs 5
cts 6
cp 0.8333
crap 3.0416
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Pitchart\Collection;
4
5
/**
6
 * A collection to manage objects of the same type
7
 *
8
 * @author Julien VITTE <[email protected]>
9
 */
10
class TypedCollection extends Collection
11
{
12
    /**
13
     * The class name required for any element of the collection
14
     *
15
     * @var string
16
     */
17
    protected $itemType;
18
19
    /**
20
     * @param array  $items    the items list
21
     * @param string $itemType the class name for the collection elements
22
     */
23 6
    public function __construct(array $items, $itemType)
24
    {
25 6
        self::validateItems($items, $itemType);
26
27 4
        $this->itemType = $itemType;
28 4
        parent::__construct($items);
29 4
    }
30
31
    /**
32
     * Builder for TypedCollection objects
33
     *
34
     * @param  iterable $iterable
35
     * @return TypedCollection
36
     */
37 2
    public static function from($iterable)
38
    {
39 2
        if ($iterable instanceof \Iterator) {
40
            $items = iterator_to_array($iterable);
41
        }
42 2
        if (is_array($iterable)
43
            || $iterable instanceof \IteratorAggregate
44 2
        ) {
45 2
            $items = (array) $iterable;
46 2
        }
47
48 2
        if (empty($items)) {
49
            throw new \InvalidArgumentException(sprintf('Can\'t build [%s] from an empty array.', static::class));
50
        }
51
52 2
        if (!is_object($items[0])) {
53
            throw new \InvalidArgumentException(sprintf('Invalid type [%s] for value [%s].', gettype($items[0]), $items[0]));
54
        }
55
56 2
        return new static($items, get_class($items[0]));
57
    }
58
59
60
    /**
61
     * @param $itemType
62
     * @return $this
63
     */
64
    public function setItemType($itemType)
65
    {
66
        $this->itemType = $itemType;
67
        return $this;
68
    }
69
70
    /**
71
     * @param object $item
72
     */
73 2
    public function add($item)
74
    {
75 2
        $validator = self::validateItem($this->itemType);
76 2
        $validator($item);
77 1
        $this->append($item);
78 1
    }
79
80
    /**
81
     * @param array  $items
82
     * @param string $itemType
83
     *
84
     * @throws \InvalidArgumentException
85
     */
86 6
    protected static function validateItems(array $items, $itemType)
87
    {
88 6
        $validateItem = static::validateItem($itemType);
89 6
        array_map(
90
            function ($item) use ($validateItem) {
91 3
                $validateItem($item);
92 6
            },
93
            $items
94 6
        );
95 4
    }
96
97
    /**
98
     * @param  string $type An object class name
99
     *
100
     * @return \Closure     A function to validate the data type
101
     * @throws \InvalidArgumentException
102
     */
103
    protected static function validateItem($type)
104
    {
105 6
        return function ($item) use ($type) {
106 5
            if (!is_object($item)) {
107
                throw new \InvalidArgumentException(sprintf('Invalid type [%s], expected [%s].', gettype($item), $type));
108
            }
109 5
            if (!is_a($item, $type)) {
110 3
                throw new \InvalidArgumentException(sprintf('Invalid type [%s], expected [%s].', get_class($item), $type));
111
            }
112 6
        };
113
    }
114
}
115