Issues (10)

src/Guards/Bases/SingleIterableInput.php (2 issues)

1
<?php
2
declare(strict_types=1);
3
4
namespace InputGuard\Guards\Bases;
5
6
use ArrayAccess;
7
use Countable;
8
use Traversable;
9
10
trait SingleIterableInput
11
{
12
    use SingleInput;
13
14
    /**
15
     * @var int
16
     */
17
    private $minCount = 0;
18
19
    /**
20
     * @var int|null;
21
     */
22
    private $maxCount;
23
24
    /**
25
     * @var bool
26
     */
27
    private $allowNullElement = false;
28
29
    /**
30
     * A method to allow extra validation to be done for each element of an iterable.
31
     *
32
     * @param mixed $element
33
     * @param mixed $value
34
     *
35
     * @return bool
36
     */
37
    abstract protected function validateIterableElement($element, &$value): bool;
38
39 2
    public function maxCount(int $max): self
40
    {
41 2
        $this->maxCount = $max;
42
43 2
        return $this;
44
    }
45
46 2
    public function minCount(int $min): self
47
    {
48 2
        $this->minCount = $min;
49
50 2
        return $this;
51
    }
52
53 11
    public function betweenCount(int $min, int $max): self
54
    {
55 11
        $this->minCount = $min;
56 11
        $this->maxCount = $max;
57
58 11
        return $this;
59
    }
60
61 1
    public function allowNullElement(): self
62
    {
63 1
        $this->allowNullElement = true;
64
65 1
        return $this;
66
    }
67
68 40
    public function value(): ?iterable
69
    {
70 40
        $this->success();
71
72 40
        return $this->value;
73
    }
74
75 3
    public function valueAsArray(): array
76
    {
77 3
        $this->success();
78
79 3
        return $this->value instanceof Traversable ? iterator_to_array($this->value) : (array)$this->value;
0 ignored issues
show
Inline IF statements are not allowed
Loading history...
80
    }
81
82
    /**
83
     * @param $input
84
     * @param $value
85
     *
86
     * @return bool
87
     */
88 44
    protected function validation($input, &$value): bool
89
    {
90 44
        if (is_iterable($input) === false) {
91 3
            return false;
92
        }
93
94
        /** @var iterable $input */
95 41
        if ($this->isBetweenCountSize($input) === false) {
96 8
            return false;
97
        }
98
99 33
        $can_be_updated = $this->elementsCanBeUpdated($input);
100
101 33
        foreach ($input as $key => $element) {
102 29
            if ($element === null) {
103 2
                if ($this->allowNullElement) {
104 1
                    continue;
105
                }
106
107 1
                return false;
108
            }
109
110 29
            $element_value = null;
111 29
            if ($this->validateIterableElement($element, $element_value) === false) {
112 7
                return false;
113
            }
114
115 24
            if ($can_be_updated) {
116
                /** @noinspection OffsetOperationsInspection */
117 24
                $input[$key] = $element_value;
118
            }
119
120
            // @todo Make the method return false if strict validation is disabled and the iterable cannot be updated.
121
        }
122
123 25
        $value = $input;
124
125 25
        return true;
126
    }
127
128 41
    private function isBetweenCountSize(iterable $input): bool
129
    {
130
        /** @noinspection PhpParamsInspection */
131 41
        $count = \is_array($input) || $input instanceof Countable ? count($input) : iterator_count($input);
0 ignored issues
show
Inline IF statements are not allowed
Loading history...
132
133 41
        return $this->isMoreThanMinCount($count) && $this->isLessThanMaxCount($count);
134
    }
135
136 41
    private function isMoreThanMinCount(int $count): bool
137
    {
138 41
        return $count >= $this->minCount;
139
    }
140
141 37
    private function isLessThanMaxCount(int $count): bool
142
    {
143 37
        return $this->maxCount === null || $count <= $this->maxCount;
144
    }
145
146 33
    protected function elementsCanBeUpdated(iterable $input): bool
147
    {
148
        // At this time only iterable that are arrays or implement array access can be modified.
149
        // I need to look into using http://www.php.net/manual/en/closure.bind.php or Refection to see if it's
150
        // possible to modify the elements of an object that only implements the Iterator interface.
151 33
        return \is_array($input) || $input instanceof ArrayAccess;
152
    }
153
}
154