Passed
Push — main ( 2edd53...9e1454 )
by Stefan
02:35
created

FormInput   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 389
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 167
dl 0
loc 389
rs 3.36
c 3
b 0
f 1
wmc 63

20 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 2
A onParentSet() 0 4 2
A setExpandFolder() 0 3 1
A readAdditionalXML() 0 11 4
A setTypeFromFlags() 0 12 5
A setPlaceholder() 0 4 2
A processFlags() 0 11 4
C buildSelectButton() 0 49 12
A setTabindex() 0 7 2
A buildSuffix() 0 11 3
A buildDatalist() 0 14 3
A buildListLink() 0 8 2
A getHTML() 0 27 2
A setSelectImg() 0 4 1
A buildSelectImage() 0 17 5
A setSize() 0 10 5
A buildClass() 0 10 4
A setSuffix() 0 3 1
A setMaxLength() 0 3 1
A fromXML() 0 12 2

How to fix   Complexity   

Complex Class

Complex classes like FormInput often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormInput, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\Formgenerator;
5
6
/**
7
 * Base-class for all elements intended to get user input.
8
 *
9
 * @package Formgenerator
10
 * @author Stefanius <[email protected]>
11
 * @copyright MIT License - see the LICENSE file for details
12
 */
13
class FormInput extends FormElement
14
{
15
    /** @var string value input type    */
16
    protected string $strType = '';
17
    /** @var int|string size as number or as string including dimension ('%', 'px', 'em') */
18
    protected $size = 0;
19
    /** @var string image displayed, if selectbutton is enabled     */
20
    protected string $strSelectImg = '';
21
    /** @var string tooltip for selectbutton     */
22
    protected string $strSelectImgTitle = '';
23
    /** @var string folder to expand when call the filemanager     */
24
    protected string $strExpandFolder = '';
25
    /** @var string suffix directly after the element     */
26
    protected string $strSuffix = '';
27
    
28
    /**
29
     * @param string $strName Name (also used as ID, if not set separate)
30
     * @param int|string $size number set the size-attribute, a string is used for the width attribute
31
     * @param int $wFlags       
32
     */
33
    public function __construct(string $strName, $size, int $wFlags = 0, int $iMaxLength = 0) 
34
    {
35
        parent::__construct($wFlags);
36
        $this->strName = $strName;
37
        $this->size = $size;
38
        $this->strType = 'text';
39
        $this->strSelectImg = '';
40
        $this->strSelectImgTitle = '';
41
        $this->strSuffix = '';
42
        
43
        $this->addFlags($wFlags);
44
        if ($iMaxLength > 0) {
45
            $this->addAttribute('maxlength', (string)$iMaxLength);
46
        }
47
    }
48
    
49
    /**
50
     * {@inheritDoc}
51
     * @see \SKien\Formgenerator\FormElement::fromXML()
52
     */
53
    static public function fromXML(\DOMElement $oXMLElement, FormCollection $oFormParent) : ?FormElement
54
    {
55
        if ($oXMLElement->nodeName !== 'Input') {
56
            trigger_error('Try to create Form' . $oXMLElement->nodeName . ' - Element from XML without defined method!', E_USER_ERROR);
57
        }
58
        $strName = self::getAttribString($oXMLElement, 'name', '');
59
        $strSize = self::getAttribString($oXMLElement, 'size', '');
60
        $wFlags = self::getAttribFlags($oXMLElement);
61
        $oFormElement = new self($strName, $strSize, $wFlags);
62
        $oFormParent->add($oFormElement);
63
        $oFormElement->readAdditionalXML($oXMLElement);
64
        return $oFormElement;
65
    }
66
    
67
    /**
68
     * {@inheritDoc}
69
     * @see \SKien\Formgenerator\FormElement::readAdditionalXML()
70
     */
71
    public function readAdditionalXML(\DOMElement $oXMLElement) : void
72
    {
73
        parent::readAdditionalXML($oXMLElement);
74
        if (($strSuffix = self::getAttribString($oXMLElement, 'suffix')) !== null) {
75
            $this->setSuffix($strSuffix);
76
        }
77
        if (($strSelectImg = self::getAttribString($oXMLElement, 'selectimg')) !== null) {
78
            $this->setSelectImg($strSelectImg, self::getAttribString($oXMLElement, 'selectimgtitle', ''));
79
        }
80
        if (($strExpandFolder = self::getAttribString($oXMLElement, 'expandfolder')) !== null) {
81
            $this->setExpandFolder($strExpandFolder);
82
        }
83
    }
84
    
85
    /**
86
     * Set the maxlength attribute of the element.
87
     * @param int $iMaxLength
88
     */
89
    public function setMaxLength(int $iMaxLength) : void
90
    {
91
        $this->addAttribute('maxlength', (string)$iMaxLength);
92
    }
93
    
94
    /**
95
     * Set placeholder to display on empty input element.
96
     * @param string $strPlaceholder
97
     */
98
    public function setPlaceholder(string $strPlaceholder) : void
99
    {
100
        if (strlen($strPlaceholder) > 0) {
101
            $this->addAttribute('placeholder', $strPlaceholder);
102
        }
103
    }
104
    
105
    /**
106
     * set image and title for select-button (leave strImg blank for default 'search')
107
     * @param string $strImg
108
     * @param string $strTitle (default = '')
109
     */
110
    public function setSelectImg(string $strImg, string $strTitle = '') : void
111
    {
112
        $this->strSelectImg = $strImg;
113
        $this->strSelectImgTitle = $strTitle;
114
    }
115
    
116
    /**
117
     * Set the folder to expand when call the filemanager.
118
     * @param string $strExpandFolder
119
     */
120
    public function setExpandFolder(string $strExpandFolder) : void
121
    {
122
        $this->strExpandFolder = $strExpandFolder;
123
    }
124
    
125
    /**
126
     * @param string $strSuffix
127
     */
128
    public function setSuffix(string $strSuffix) : void
129
    {
130
        $this->strSuffix = $strSuffix;
131
    }
132
    
133
    /**
134
     * {@inheritDoc}
135
     * @see \SKien\Formgenerator\FormElement::onParentSet()
136
     */
137
    protected function onParentSet() : void
138
    {
139
        if ($this->oFlags->isSet(FormFlags::BROWSE_SERVER)) {
140
            $this->oFG->addConfigForJS('RichFilemanager', $this->oFG->getConfig()->getArray('RichFilemanager'));
141
        }
142
    }
143
    
144
    /**
145
     * Build the HTML-notation for the input element.
146
     * {@inheritDoc}
147
     * @see \SKien\Formgenerator\FormElement::getHTML()
148
     */
149
    public function getHTML() : string
150
    {
151
        $this->processFlags();
152
        $this->setSize();
153
        $strHTML = $this->buildContainerDiv();
154
        
155
        $this->strID = $this->strID ?: $this->strName;
156
        
157
        $strHTML .= '<input';
158
        $strHTML .= ' type="' . $this->strType . '"';
159
        $strHTML .= ' name="' . $this->strName . '"';
160
        $strHTML .= $this->buildClass();
161
        $strHTML .= $this->buildID();
162
        $strHTML .= $this->buildStyle();
163
        $strHTML .= $this->buildTabindex();
164
        $strHTML .= $this->buildValue();
165
        $strHTML .= $this->buildAttributes();
166
        $strHTML .= $this->buildListLink();
167
        $strHTML .= '>';
168
        
169
        $strHTML .= $this->buildSelectButton();
170
        $strHTML .= $this->buildSuffix();
171
        $strHTML .= $this->buildDatalist();
172
        
173
        $strHTML .= '</div>' . PHP_EOL;
174
        
175
        return $strHTML;
176
    }
177
    
178
    /**
179
     * Set the tab index of the element.
180
     * Method is called from the PageGenerator after an element is added to the form.
181
     * @param int $iTabindex
182
     * @return int the number of indexes, the element needs
183
     */
184
    public function setTabindex(int $iTabindex) : int
185
    {
186
        if ($this->oFlags->isSet(FormFlags::HIDDEN | FormFlags::READ_ONLY | FormFlags::DISABLED)) {
187
            return 0;
188
        }
189
        $this->iTabindex = $iTabindex;
190
        return 1;
191
    }
192
    
193
    /**
194
     * Process the current flags before the HTML is generated.
195
     */
196
    protected function processFlags() : void
197
    {
198
        $this->setTypeFromFlags();
199
        
200
        if ($this->oFlags->isSet(FormFlags::MANDATORY)) {
201
            $this->addAttribute('required');
202
        }
203
        if ($this->oFlags->isSet(FormFlags::READ_ONLY)) {
204
            $this->addAttribute('readonly');
205
        } else if ($this->oFlags->isSet(FormFlags::DISABLED)) {
206
            $this->addAttribute('disabled');
207
        }
208
    }
209
210
    /**
211
     * Set the type depending on some flags
212
     */
213
    protected function setTypeFromFlags() : void
214
    {
215
        if ($this->oFlags->isSet(FormFlags::HIDDEN)) {
216
            $this->strType = 'hidden';
217
        }
218
        if ($this->oFlags->isSet(FormFlags::PASSWORD)) {
219
            $this->strType = 'password';
220
        }
221
        if ($this->oFlags->isSet(FormFlags::FILE)) {
222
            $this->strType = 'file';
223
            if ($this->oFlags->isSet(FormFlags::HIDDEN)) {
224
                $this->addStyle('visibility', 'hidden');
225
            }
226
        }
227
    }
228
    
229
    /**
230
     * Set the size of the element.
231
     * If property $size contains numeric value, the HTML attrib 'size' is set, in case of a
232
     * string a width information including dimension (px, em, ...) is assumed.
233
     * 
234
     */
235
    protected function setSize() : void
236
    {
237
        if ($this->oFlags->isSet(FormFlags::HIDDEN)) {
238
            $this->size = '';
239
        }
240
        if ((is_numeric($this->size)) && ($this->size > 0)) {
241
            $this->addAttribute('size', (string)$this->size);
242
        } else if (!empty($this->size)) {
243
            // size given as string including dimension
244
            $this->addStyle('width', $this->size);
245
        }
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     * @see \SKien\Formgenerator\FormElement::buildClass()
251
     */
252
    protected function buildClass() : string
253
    {
254
        if (!empty($this->strClass)) {
255
            $this->strClass .= ' ';
256
        }
257
        $this->strClass .= ($this->oFlags->isSet(FormFlags::MANDATORY)) ? ' inputMand' : ' inputOK';
258
        if ($this->oFlags->isSet(FormFlags::ALIGN_RIGHT)) {
259
            $this->strClass .= '_R';
260
        }
261
        return parent::buildClass();
262
    }
263
    
264
    /**
265
     * Build the markup for a suffix succeeding the input element.
266
     * @return string
267
     */
268
    protected function buildSuffix() : string
269
    {
270
        $strHTML = '';
271
        if (!empty($this->strSuffix)) {
272
            if ($this->oFlags->isSet(FormFlags::READ_ONLY)) {
273
                $strHTML .= '&nbsp;<span class="readonly">' . $this->strSuffix . '</span>';
274
            } else {
275
                $strHTML .= '&nbsp;' . $this->strSuffix;
276
            }
277
        }
278
        return $strHTML;
279
    }
280
    
281
    /**
282
     * Build attrib for associated datalist.
283
     * If the dataprovider contains a datalist in the selectoptions with the same name
284
     * as the element, we add the attrib to conect to this list.
285
     * @return string
286
     */
287
    protected function buildListLink() : string
288
    {
289
        $strLink = '';
290
        $aOptions = $this->oFG->getData()->getSelectOptions($this->strName);
291
        if (count($aOptions) > 0) {
292
            $strLink = ' list="list' . $this->strName . '"';
293
        }
294
        return $strLink;
295
    }
296
    
297
    /**
298
     * Build the markup for associated datalist.
299
     * If the dataprovider contains a datalist in the selectoptions with the same name 
300
     * as the element, we build this datalist.
301
     * @return string
302
     */
303
    protected function buildDatalist() : string
304
    {
305
        $strHTML = '';
306
        $aOptions = $this->oFG->getData()->getSelectOptions($this->strName);
307
        if (count($aOptions) > 0) {
308
            $strHTML .= '<datalist id="list' . $this->strName . '">' . PHP_EOL;
309
            foreach ($aOptions as $strValue) {
310
                $strHTML .= '    ';
311
                $strHTML .= '<option ';
312
                $strHTML .= 'value="' . $strValue . '">' . PHP_EOL;
313
            }
314
            $strHTML .= '</datalist>' . PHP_EOL;
315
        }
316
        return $strHTML;
317
    }
318
    
319
    /**
320
     * Build the markup for the select button(s).
321
     * If input  is set to readonly, an additional 'delete' button is appended.
322
     * @param string $strCssClass
323
     * @return string
324
     */
325
    protected function buildSelectButton(string $strCssClass = 'picker') : string
326
    {
327
        $wButtonFlags = $this->oFlags->getButtonFlags();
328
        if ($wButtonFlags === 0 || $this->oFlags->isSet(FormFlags::HIDDEN)) {
329
            return '';
330
        }
331
        
332
        $strImg = '';
333
        $strTitle = '';
334
        $strOnClick = '';
335
        $strID = '';
336
        
337
        // only one of the button flags is allowed - so we can use switch-case!
338
        switch ($wButtonFlags) {
339
        case FormFlags::ADD_DTU:
340
            $strUsername = $this->oFG->getData()->getValue('username');
341
            [$strImg, $strTitle] = $this->oFG->getStdImage(FormImage::IMG_DTU);
342
            $strOnClick = "onInsertDateTimeUser('" . $this->strName . "', '" . $strUsername . "')";
343
            $strID = $this->strName . 'DTU';
344
            break;
345
        case FormFlags::ADD_DATE_PICKER:
346
            [$strImg, $strTitle] = $this->oFG->getStdImage(FormImage::IMG_DATE_PICKER);
347
            break;
348
        case FormFlags::ADD_TIME_PICKER:
349
            [$strImg, $strTitle] = $this->oFG->getStdImage(FormImage::IMG_TIME_PICKER);
350
            break;
351
        case FormFlags::BROWSE_SERVER:
352
            [$strImg, $strTitle] = $this->oFG->getStdImage(FormImage::IMG_BROWSE);
353
            $strOnClick = "browseServer('" . $this->strName . "','','" . $this->strExpandFolder . "')";
354
            $strID = $this->strName . 'BS';
355
            break;
356
        case FormFlags::ADD_SELBTN:
357
            [$strImg, $strTitle] = $this->oFG->getStdImage(FormImage::IMG_SEARCH);
358
            $strOnClick = "onSelect('" . $this->strName . "')";
359
            $strID = $this->strName . 'SB';
360
            $strImg = $this->strSelectImg ?: $strImg;
361
            $strTitle = $this->strSelectImgTitle ?: $strTitle;
362
            break;
363
        default:
364
            trigger_error('Only one of the button-flags can be set!', E_USER_ERROR);
365
        }
366
        $strHTML = $this->buildSelectImage($strImg, $strTitle, $strOnClick, $strID, $strCssClass);
367
        if (!empty($strHTML) && $this->oFlags->isSet(FormFlags::READ_ONLY)) {
368
            [$strImg, $strTitle] = $this->oFG->getStdImage(FormImage::IMG_DELETE);
369
            $strOnClick = "resetElement('" . $this->strName . "')";
370
            $strID = $this->strName . 'Del';
371
            $strHTML .= $this->buildSelectImage($strImg, $strTitle, $strOnClick, $strID, $strCssClass);
372
        }
373
        return $strHTML;
374
    }
375
    
376
    /**
377
     * Build the markup for a selectimage.
378
     * @param string $strImg
379
     * @param string $strTitle
380
     * @param string $strOnClick
381
     * @param string $strID
382
     * @param string $strCssClass
383
     * @return string
384
     */
385
    protected function buildSelectImage(string $strImg, string $strTitle, string $strOnClick, string $strID, string $strCssClass) : string
386
    {
387
        $strHTML = '';
388
        if (!empty($strImg)) {
389
            $strHTML = '<img class="' . $strCssClass . '" src="' . $strImg . '" alt="[?]"';
390
            if (!empty($strID)) {
391
                $strHTML .= ' id="' . $strID . '"';
392
            }
393
            if (!empty($strTitle)) {
394
                $strHTML .= ' title="' . $strTitle . '"';
395
            }
396
            if (!empty($strOnClick)) {
397
                $strHTML .= ' onclick="' . $strOnClick . '"';
398
            }
399
            $strHTML .= '>';
400
        }
401
        return $strHTML;
402
    }
403
}
404