AbstractInput::updateInstance()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 8
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 0
crap 6
1
<?php
2
3
/**
4
 * This file is part of slick/form package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Form\Input;
11
12
use Slick\Form\Element\AbstractElement;
13
use Slick\Form\Element\Label;
14
use Slick\Form\ElementInterface;
15
use Slick\Form\Exception\InvalidArgumentException;
16
use Slick\Form\InputInterface;
17
use Slick\Form\Renderer\Input;
18
use Slick\I18n\TranslateMethods;
19
20
/**
21
 * Abstract Input: base input interface implementations
22
 *
23
 * @package Slick\Form\Input
24
 * @author  Filipe Silva <[email protected]>
25
 */
26
abstract class AbstractInput extends AbstractElement
27
{
28
29
    /**
30
     * @var int int
31
     */
32
    protected $instances = 0;
33
34
    /**
35
     * @var string used in input id generation
36
     */
37
    protected static $idPrefix = 'input-';
38
39
    /**
40
     * @var Label|ElementInterface
41
     */
42
    protected $label;
43
44
    /**
45
     * @var bool
46
     */
47
    protected $required = false;
48
49
    /**
50
     * Add validation methods
51
     */
52
    use ValidationAwareMethods;
53
54
    /**
55
     * Add filter methods
56
     */
57
    use FilterAwareMethods;
58
59
    /**
60
     * Needed for label translation
61
     */
62
    use TranslateMethods;
63
64
    /**
65
     * @var string Renderer class
66
     */
67
    protected $rendererClass = Input::class;
68
69
    /**
70
     * Get input name
71
     *
72
     * @return mixed
73
     */
74 66
    public function getName()
75
    {
76 66
        return trim($this->getAttribute('name'), '][');
77
    }
78
79
    /**
80
     * Sets input name
81
     *
82
     * @param string $name
83
     *
84
     * @return self|$this|InputInterface|AbstractInput
85
     */
86 60
    public function setName($name)
87
    {
88 60
        $attrName = $this->isMultiple()
89 60
            ? "{$name}[]"
90 60
            : $name;
91 60
        $this->setAttribute('name', $attrName);
92 60
        $this->name = $name;
93 60
        if ($label = $this->getLabel()) {
0 ignored issues
show
Unused Code introduced by
$label is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
94 2
            $this->getLabel()->setAttribute('for', $this->generateId());
95 2
        }
96 60
        return $this;
97
    }
98
99
    /**
100
     * Sets the input label
101
     *
102
     * Label parameter can be a string or a element interface.
103
     * If a string is provided then an ElementInterface MUST be created.
104
     * This element MUST result in a <label> HTML tag when rendering and
105
     * as you may define your own implementation it is advisable that you
106
     * use the Slick\Form\Element\Label object.
107
     *
108
     * @param string|ElementInterface $label
109
     *
110
     * @return self|$this|InputInterface
111
     *
112
     * @throws InvalidArgumentException If the provided label is not a string
113
     *      or is not an object of a class implementing the ElementInterface.
114
     */
115 62
    public function setLabel($label)
116
    {
117 62
        $this->label = $this->checkLabel($label);
118 56
        $class = $this->label->getAttribute('class');
119 56
        $this->label->setAttribute('for', $this->generateId())
120 56
            ->setAttribute('class', trim("control-label {$class}"));
121 56
        return $this;
122
    }
123
124
    /**
125
     * Gets the input label element
126
     *
127
     * @return ElementInterface|Label
128
     */
129 66
    public function getLabel()
130
    {
131 66
        return $this->label;
132
    }
133
134
    /**
135
     * Returns the input value as user entered it, without filtering
136
     *
137
     * @return mixed
138
     */
139 28
    public function getRawValue()
140
    {
141 28
        return $this->value;
142
    }
143
144
    /**
145
     * Overrides the default behavior to add the value attribute
146
     * 
147
     * @param mixed $value
148
     * 
149
     * @return mixed
150
     */
151 34
    public function setValue($value)
152
    {
153 34
        return parent::setValue($value);
154
    }
155
156
    /**
157
     * Generate input id based on provided name
158
     *
159
     * @return string
160
     */
161 56
    protected function generateId()
162
    {
163 56
        $inputId = static::$idPrefix . $this->getName();
164 56
        if ($this->isMultiple()) {
165
            $inputId = "{$inputId}-{$this->instances}";
166
        }
167 56
        $this->setAttribute('id', $inputId);
168 56
        return $inputId;
169
    }
170
171
    /**
172
     * Check provided label
173
     *
174
     * @param string|ElementInterface $label
175
     *
176
     * @return ElementInterface|Label
177
     */
178 62
    protected function checkLabel($label)
179
    {
180 62
        if ($label instanceof ElementInterface) {
181 34
            return $label;
182
        }
183
184 58
        return $this->createLabel($this->translate($label));
185
    }
186
187
    /**
188
     * Creates label from string
189
     *
190
     * @param string $label
191
     *
192
     * @return ElementInterface|Label
193
     */
194 58
    protected function createLabel($label)
195
    {
196 58
        if (!is_string($label)) {
197 4
            throw new InvalidArgumentException(
198
                "Provided label is not a string or an ElementInterface ".
199
                "interface object."
200 4
            );
201
        }
202
203 54
        $element = class_exists($label)
204 54
            ? $this->createLabelFromClass($label)
205 52
            : new Label('', $label);
206
207 52
        return $element;
208
    }
209
210
    /**
211
     * Instantiates the provided ElementInterface  class
212
     *
213
     * @param string $class
214
     *
215
     * @return ElementInterface|Label
216
     */
217 4
    protected function createLabelFromClass($class)
218
    {
219 4
        if (! is_subclass_of($class, ElementInterface::class)) {
220 2
            throw new InvalidArgumentException(
221 2
                "Class '{$class}' does not implements ElementInterface and ".
222
                "cannot be used as input label."
223 2
            );
224
        }
225
226 2
        $label = new $class('', ucfirst($this->getName()));
227 2
        return $label;
228
    }
229
230
    /**
231
     * Check if this input is required to be filled
232
     *
233
     * @return bool
234
     */
235 42
    public function isRequired()
236
    {
237 42
        return $this->required;
238
    }
239
240
    /**
241
     * Sets the required flag for this input
242
     *
243
     * @param boolean $required
244
     *
245
     * @return $this|self|InputInterface
246
     */
247 38
    public function setRequired($required)
248
    {
249 38
        $this->required = (boolean) $required;
250 38
        if ($this->isRequired()) {
251 36
            $this->setAttribute('required');
252 36
            return $this;
253
        }
254
255 2
        if ($this->getAttributes()->containsKey('required')) {
256 2
                $this->getAttributes()->remove('required');
257 2
        }
258 2
        return $this;
259
    }
260
261
    /**
262
     * Check if this input is for multiple usage
263
     * 
264
     * @return boolean
265
     */
266 66
    public function isMultiple()
267
    {
268 66
        return $this->settings['multiple'];
269
    }
270
    
271
    /**
272
     * If input is multiple get the instance it belongs
273
     *
274
     * @return int
275
     */
276
    public function getInstance()
277
    {
278
        return $this->instances;
279
    }
280
281
    /**
282
     * If input is multiple get the instance value of it
283
     *
284
     * @return mixed
285
     */
286 10
    public function getInstanceValue()
287
    {
288 10
        $value = $this->getValue();
289
        if (
290 10
            is_array($value) &&
291
            array_key_exists($this->instances, $this->value)
292 10
        ) {
293
            $value = $value[$this->instances];
294
        }
295 10
        return $value;
296
    }
297
298
    /**
299
     * Returns the HTML string for current element
300
     *
301
     * @param array $context
302
     *
303
     * @return string
304
     */
305 10
    public function render($context = [])
306
    {
307 10
        $this->setAttribute('value', $this->getInstanceValue());
308 10
        $data = parent::render($context);
309 10
        if ($this->isMultiple()) {
310
            $this->updateInstance();
311
        }
312 10
        return $data;
313
    }
314
315
    /**
316
     * Updates input id and link it to its label
317
     * 
318
     * @return self|AbstractInput
319
     */
320
    protected function updateInstance()
321
    {
322
        $this->instances++;
323
        $id = $this->generateId();
324
        $this->setAttribute($id, $id);
325
        if ($label = $this->getLabel()) {
326
            $label->setAttribute('for', $id);
327
        }
328
        
329
        return $this;
330
    }
331
}
332