Test Failed
Push — extract-attributes ( 6e6144...c9c1de )
by Dmitriy
07:22 queued 12s
created

FileInput::run()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 38
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 17
c 1
b 0
f 0
nc 8
nop 0
dl 0
loc 38
rs 9.7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Form\FormModelInterface;
9
use Yiisoft\Widget\Widget;
10
11
final class FileInput extends Widget
12
{
13
    private FormModelInterface $data;
14
    private string $attribute;
15
    private array $options = [];
16
    private bool $withoutHiddenInput = false;
17
18
    /**
19
     * Generates a file input tag for the given form attribute.
20
     *
21
     * @return string the generated input tag.
22
     */
23
    public function run(): string
24
    {
25
        $new = clone $this;
26
27
        $hiddenOptions = ['id' => false, 'value' => ''];
28
29
        if (isset($new->options['name'])) {
30
            $hiddenOptions['name'] = $new->options['name'];
31
        }
32
33
        /** make sure disabled input is not sending any value */
34
        if (!empty($new->options['disabled'])) {
35
            $hiddenOptions['disabled'] = $new->options['disabled'];
36
        }
37
38
        $hiddenOptions = ArrayHelper::merge($hiddenOptions, ArrayHelper::remove($new->options, 'hiddenOptions', []));
39
40
        /**
41
         * Add a hidden field so that if a form only has a file field, we can still use isset($body[$formClass]) to
42
         * detect if the input is submitted.
43
         * The hidden input will be assigned its own set of html options via `$hiddenOptions`.
44
         * This provides the possibility to interact with the hidden field via client script.
45
         *
46
         * Note: For file-field-only form with `disabled` option set to `true` input submitting detection won't work.
47
         */
48
        $hiddenInput = '';
49
50
        if ($new->withoutHiddenInput === false) {
51
            $hiddenInput = HiddenInput::widget()->config($new->data, $new->attribute, $hiddenOptions)->run();
0 ignored issues
show
Bug introduced by
The method config() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of said class. However, the method does not exist in Yiisoft\Widget\Tests\Stubs\TestWidget or Yiisoft\Widget\Tests\Stubs\TestWidgetA or Yiisoft\Widget\Tests\Stubs\TestInjectionWidget or Yiisoft\Form\Widget\Form or Yiisoft\Widget\Tests\Stubs\ImmutableWidget or Yiisoft\Widget\Tests\Stubs\TestWidgetB. Are you sure you never get one of those? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

51
            $hiddenInput = HiddenInput::widget()->/** @scrutinizer ignore-call */ config($new->data, $new->attribute, $hiddenOptions)->run();
Loading history...
52
        }
53
54
        $new->options['value'] = false;
55
        return
56
            $hiddenInput .
57
            Input::widget()
58
                ->type('file')
0 ignored issues
show
Bug introduced by
The method type() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of Yiisoft\Widget\Widget such as Yiisoft\Form\Widget\ListBox or Yiisoft\Form\Widget\Input or Yiisoft\Form\Widget\ListInput or Yiisoft\Form\Widget\BooleanInput. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

58
                ->/** @scrutinizer ignore-call */ type('file')
Loading history...
59
                ->config($new->data, $new->attribute, $new->options)
60
                ->run();
61
    }
62
63
    /**
64
     * Set form model, name and options for the widget.
65
     *
66
     * @param FormModelInterface $data Form model.
67
     * @param string $attribute Form model property this widget is rendered for.
68
     * @param array $options The HTML attributes for the widget container tag.
69
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
70
     *
71
     * @return self
72
     */
73
    public function config(FormModelInterface $data, string $attribute, array $options = []): self
74
    {
75
        $new = clone $this;
76
        $new->data = $data;
77
        $new->attribute = $attribute;
78
        $new->options = $options;
79
        return $new;
80
    }
81
82
    /**
83
     * The accept attribute value is a string that defines the file types the file input should accept. This string is
84
     * a comma-separated list of unique file type specifiers. Because a given file type may be identified in more than
85
     * one manner, it's useful to provide a thorough set of type specifiers when you need files of a given format.
86
     *
87
     * @param string $value
88
     *
89
     * @return self
90
     */
91
    public function accept(string $value): self
92
    {
93
        $new = clone $this;
94
        $new->options['accept'] = $value;
95
        return $new;
96
    }
97
98
    /**
99
     * Focus on the control (put cursor into it) when the page loads.
100
     * Only one form element could be in focus at the same time.
101
     *
102
     * @param bool $value
103
     *
104
     * @return self
105
     */
106
    public function autofocus(bool $value = true): self
107
    {
108
        $new = clone $this;
109
        $new->options['autofocus'] = $value;
110
        return $new;
111
    }
112
113
    /**
114
     * Set whether the element is disabled or not.
115
     *
116
     * If this attribute is set to `true`, the element is disabled. Disabled elements are usually drawn with grayed-out
117
     * text.
118
     * If the element is disabled, it does not respond to user actions, it cannot be focused, and the command event
119
     * will not fire. In the case of form elements, it will not be submitted. Do not set the attribute to true, as
120
     * this will suggest you can set it to false to enable the element again, which is not the case.
121
     *
122
     * @param bool $value
123
     *
124
     * @return self
125
     */
126
    public function disabled(bool $value = true): self
127
    {
128
        $new = clone $this;
129
        $new->options['disabled'] = $value;
130
        return $new;
131
    }
132
133
    /**
134
     * HiddenOptions parameter which is another set of HTML options array is defined, to be used for the hidden input.
135
     *
136
     * @param array $value
137
     *
138
     * @return self
139
     */
140
    public function hiddenOptions(array $value = []): self
141
    {
142
        $new = clone $this;
143
        $new->options['hiddenOptions'] = $value;
144
        return $new;
145
    }
146
147
    /**
148
     * When the multiple Boolean attribute is specified, the file input allows the user to select more than one file.
149
     *
150
     * @param bool $value
151
     *
152
     * @return self
153
     */
154
    public function multiple(bool $value = true): self
155
    {
156
        $new = clone $this;
157
        $new->options['multiple'] = $value;
158
        return $new;
159
    }
160
161
    /**
162
     * If it is required to fill in a value in order to submit the form.
163
     *
164
     * @param bool $value
165
     *
166
     * @return self
167
     */
168
    public function required(bool $value = true): self
169
    {
170
        $new = clone $this;
171
        $new->options['required'] = $value;
172
        return $new;
173
    }
174
175
    /**
176
     * The tabindex global attribute indicates that its element can be focused, and where it participates in sequential
177
     * keyboard navigation (usually with the Tab key, hence the name).
178
     *
179
     * It accepts an integer as a value, with different results depending on the integer's value:
180
     *
181
     * - A negative value (usually tabindex="-1") means that the element is not reachable via sequential keyboard
182
     * navigation, but could be focused with Javascript or visually. It's mostly useful to create accessible widgets
183
     * with JavaScript.
184
     * - tabindex="0" means that the element should be focusable in sequential keyboard navigation, but its order is
185
     * defined by the document's source order.
186
     * - A positive value means the element should be focusable in sequential keyboard navigation, with its order
187
     * defined by the value of the number. That is, tabindex="4" is focused before tabindex="5", but after tabindex="3".
188
     *
189
     * @param int $value
190
     *
191
     * @return self
192
     */
193
    public function tabIndex(int $value = 0): self
194
    {
195
        $new = clone $this;
196
        $new->options['tabindex'] = $value;
197
        return $new;
198
    }
199
200
    /**
201
     * Allows you to disable hidden input widget.
202
     *
203
     * @param bool $value
204
     *
205
     * @return self
206
     */
207
    public function withoutHiddenInput(bool $value): self
208
    {
209
        $new = clone $this;
210
        $new->withoutHiddenInput = $value;
211
        return $new;
212
    }
213
}
214