Passed
Push — fix/media-validation ( 00dba4...732083 )
by Ben
06:54
created

Fields::validate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Thinktomorrow\Chief\Fields;
4
5
use ArrayIterator;
6
use Thinktomorrow\Chief\Fields\Types\Field;
7
8
class Fields implements \ArrayAccess, \IteratorAggregate, \Countable
9
{
10
    /** @var array */
11
    private $fields;
12
13
    final public function __construct(array $fields = [])
14
    {
15
        $this->validateFields($fields);
16
17
        $this->fields = $this->convertToKeyedArray($fields);
18
    }
19
20
    public function all(): array
21
    {
22
        return $this->fields;
23
    }
24
25
    public function first(): ?Field
26
    {
27
        if (!$this->any()) {
28
            return null;
29
        }
30
31
        return reset($this->fields);
32
    }
33
34
    public function any(): bool
35
    {
36
        return count($this->all()) > 0;
37
    }
38
39
    public function isEmpty(): bool
40
    {
41
        return !$this->any();
42
    }
43
44
    public function keys(): array
45
    {
46
        return array_keys($this->fields);
47
    }
48
49
    public function filterBy($key, $value = null)
50
    {
51
        $fields = [];
52
53
        foreach ($this->fields as $i => $field) {
54
            if ($key instanceof \Closure) {
55
                if (true == $key($field)) {
56
                    $fields[] = $field;
57
                }
58
59
                continue;
60
            }
61
62
            $method = 'get' . ucfirst($key);
63
64
            // Reject from list if value does not match expected one
65
            if ($value && $value == $field->$method()) {
66
                $fields[] = $field;
67
            } // Reject from list if key returns null (key not present on field)
68
            elseif (!$value && !is_null($field->$method())) {
69
                $fields[] = $field;
70
            }
71
        }
72
73
        return new static($fields);
74
    }
75
76
    public function add(Field ...$fields): Fields
77
    {
78
        return new Fields(array_merge($this->fields, $fields));
79
    }
80
81
    public function merge(Fields $fields): Fields
82
    {
83
        return new Fields(array_merge($this->fields, $fields->all()));
84
    }
85
86
    public function remove($keys = null)
87
    {
88
        if (!$keys) {
89
            return $this;
90
        }
91
92
        if (is_string($keys)) {
93
            $keys = func_get_args();
94
        }
95
96
        foreach ($this->fields as $k => $field) {
97
            if (in_array($field->getKey(), $keys)) {
98
                unset($this->fields[$k]);
99
            }
100
        }
101
102
        return $this;
103
    }
104
105
    public function offsetExists($offset)
106
    {
107
        return isset($this->fields[$offset]);
108
    }
109
110
    public function offsetGet($offset)
111
    {
112
        return (isset($this->fields[$offset]))
113
            ? $this->fields[$offset]
114
            : null;
115
    }
116
117
    public function offsetSet($offset, $value)
118
    {
119
        if (!$value instanceof Field) {
120
            throw new \InvalidArgumentException('Passed value must be of type ' . Field::class);
121
        }
122
123
        $this->fields[$offset] = $value;
124
    }
125
126
    public function offsetUnset($offset)
127
    {
128
        unset($this->fields[$offset]);
129
    }
130
131
    public function getIterator()
132
    {
133
        return new ArrayIterator($this->fields);
134
    }
135
136
    private function convertToKeyedArray(array $fields): array
137
    {
138
        $keyedFields = [];
139
140
        /** @var Field */
141
        foreach ($fields as $field) {
142
            $keyedFields[$field->getKey()] = $field;
143
        }
144
145
        return $keyedFields;
146
    }
147
148
    private function validateFields(array $fields)
149
    {
150
        array_map(function (Field $field) {
151
        }, $fields);
152
    }
153
154
    public function count()
155
    {
156
        return count($this->fields);
157
    }
158
}
159