Passed
Push — master ( 5c25b8...502eee )
by Gabor
05:16
created

ServiceAdapter::getElement()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 0
cts 13
cp 0
rs 9.2
c 0
b 0
f 0
cc 3
eloc 13
nc 3
nop 1
crap 12
1
<?php
2
/**
3
 * WebHemi.
4
 *
5
 * PHP version 7.1
6
 *
7
 * @copyright 2012 - 2017 Gixx-web (http://www.gixx-web.com)
8
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
9
 *
10
 * @link      http://www.gixx-web.com
11
 */
12
declare(strict_types = 1);
13
14
namespace WebHemi\Form\ServiceAdapter\Base;
15
16
use JsonSerializable;
17
use RuntimeException;
18
use InvalidArgumentException;
19
use WebHemi\Form\ElementInterface;
20
use WebHemi\Form\ServiceInterface;
21
use WebHemi\StringLib;
22
23
/**
24
 * Class ServiceAdapter.
25
 */
26
class ServiceAdapter implements ServiceInterface, JsonSerializable
27
{
28
    /** @var string */
29
    private $name;
30
    /** @var string */
31
    private $action;
32
    /** @var string */
33
    private $method;
34
    /** @var array */
35
    private $formElements = [];
36
37
    /**
38
     * ServiceAdapter constructor.
39
     *
40
     * @param string|null $name
41
     * @param string|null $action
42
     * @param string      $method
43
     */
44 7
    public function __construct(string $name = null, string $action = null, string $method = 'POST')
45
    {
46 7
        $this->name = $name;
47 7
        $this->action = $action;
48 7
        $this->method = $method;
49 7
    }
50
51
    /**
52
     * Initializes the form if it didn't happen in the constructor. (Used mostly in presets).
53
     *
54
     * @param string $name
55
     * @param string $action
56
     * @param string $method
57
     * @throws RuntimeException
58
     * @return ServiceInterface
59
     */
60 1
    public function initialize(string $name, string $action, string $method = 'POST') : ServiceInterface
61
    {
62 1
        if (isset($this->name) || isset($this->action)) {
63 1
            throw new RuntimeException('The form had been already initialized!', 1000);
64
        }
65
66 1
        $this->name = $name;
67 1
        $this->action = $action;
68 1
        $this->method = $method;
69
70 1
        return $this;
71
    }
72
73
    /**
74
     * Gets form name.
75
     *
76
     * @return string
77
     */
78 1
    public function getName() : string
79
    {
80 1
        return $this->name;
81
    }
82
83
    /**
84
     * Gets form action.
85
     *
86
     * @return string
87
     */
88 1
    public function getAction() : string
89
    {
90 1
        return $this->action;
91
    }
92
93
    /**
94
     * Gets form method.
95
     *
96
     * @return string
97
     */
98 1
    public function getMethod() : string
99
    {
100 1
        return $this->method;
101
    }
102
103
    /**
104
     * Adds an element to the form.
105
     *
106
     * @param ElementInterface $formElement
107
     * @return ServiceInterface
108
     */
109 2
    public function addElement(ElementInterface $formElement) : ServiceInterface
110
    {
111 2
        $elementName = $formElement->getName();
112
113 2
        if (!isset($this->formElements[$elementName])) {
114 2
            $elementName = $this->name.'['.$elementName.']';
115 2
            $formElement->setName($elementName);
116
        }
117
118 2
        $this->formElements[$elementName] = $formElement;
119
120 2
        return $this;
121
    }
122
123
    /**
124
     * Returns an element
125
     *
126
     * @param string $elementName
127
     * @throws InvalidArgumentException
128
     * @return ElementInterface
129
     */
130
    public function getElement(string $elementName) : ElementInterface
131
    {
132
        $elementNames = array_keys($this->formElements);
133
        $elementName = StringLib::convertNonAlphanumericToUnderscore($elementName);
134
        $matchingElementNames = preg_grep('/.*\['.$elementName.'\]/', $elementNames);
135
136
        if (count($matchingElementNames) > 1) {
137
            throw new InvalidArgumentException(
138
                sprintf('The element "%s" in field list is ambiguous.', $elementName),
139
                1001
140
            );
141
        }
142
143
        if (empty($matchingElementNames)) {
144
            throw new InvalidArgumentException(
145
                sprintf('The element "%s" does not exist in this form.', $elementName),
146
                1002
147
            );
148
        }
149
150
        return $this->formElements[current($matchingElementNames)];
151
    }
152
153
    /**
154
     * Returns all the elements assigned.
155
     *
156
     * @return ElementInterface[]
157
     */
158 3
    public function getElements() : array
159
    {
160 3
        return $this->formElements;
161
    }
162
163
    /**
164
     * Loads data into the form.
165
     *
166
     * @param array $data
167
     * @return ServiceInterface
168
     */
169 1
    public function loadData(array $data) : ServiceInterface
170
    {
171 1
        $formData = $data[$this->name] ?? [];
172
173 1
        foreach ($formData as $elementName => $elementValue) {
174 1
            $fullName = $this->name.'['.$elementName.']';
175
            /** @var ElementInterface $formElement */
176 1
            $formElement = $this->formElements[$fullName] ?? null;
177
178 1
            if ($formElement) {
179 1
                if (!is_array($elementValue)) {
180 1
                    $elementValue = [$elementValue];
181
                }
182 1
                $formElement->setValues($elementValue);
183
            }
184
        }
185
186 1
        return $this;
187
    }
188
189
    /**
190
     * Validates the form.
191
     *
192
     * @return bool
193
     */
194
    public function validate() : bool
195
    {
196
        $isValid = true;
197
198
        /**
199
         * @var string $index
200
         * @var ElementInterface $formElement
201
         */
202
        foreach ($this->formElements as $index => $formElement) {
203
            $this->formElements[$index] = $formElement->validate();
204
205
            if (!empty($formElement->getErrors())) {
206
                $isValid = false;
207
            }
208
        }
209
210
        return $isValid;
211
    }
212
213
    /**
214
     * Defines the data which are presented during the json serialization.
215
     *
216
     * @return array
217
     */
218 1
    public function jsonSerialize() : array
219
    {
220
        $formData = [
221 1
            'name' => $this->name,
222 1
            'action' => $this->action,
223 1
            'method' => $this->method,
224
            'data' => [],
225
            'errors' => []
226
        ];
227
228
        /**
229
         * @var string $elementName
230
         * @var ElementInterface $formElement
231
         */
232 1
        foreach ($this->formElements as $formElement) {
233 1
            $formData['data'][$formElement->getId()] = $formElement->getValues();
234
235 1
            $errors = $formElement->getErrors();
236
237 1
            if (!empty($errors)) {
238 1
                $formData['errors'][$formElement->getId()] = $errors;
239
            }
240
        }
241
242 1
        return $formData;
243
    }
244
}
245