Passed
Push — main ( f05cfd...29a9c1 )
by Stefan
02:38
created

FormElement::buildTabindex()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\Formgenerator;
5
6
/**
7
 * Base-class for all elements of a form.
8
 * Starting with a FormGenerator-element, the form can contain any count 
9
 * of elements.
10
 * The elements usuallay be arranged within FormFieldSet- and FormLine-elements
11
 *
12
 * #### History
13
 * - *2020-05-12*   initial version
14
 * - *2021-01-07*   PHP 7.4
15
 *
16
 * @package Formgenerator
17
 * @version 1.1.0
18
 * @author Stefanius <[email protected]>
19
 * @copyright MIT License - see the LICENSE file for details
20
 */
21
abstract class FormElement
22
{
23
    // TODO: Find a more general way of defining standard images. (possibly via a config)
24
    /** standard delete image */
25
    const IMG_DELETE            = 1;
26
    /** standard delete image */
27
    const IMG_SEARCH            = 2;
28
    /** standard image for date picker */
29
    const IMG_DATE_PICKER       = 3;
30
    /** standard image for time picker */
31
    const IMG_TIME_PICKER       = 4;
32
    /** standard image for dtu insert (DTU: Date,Time,User) */
33
    const IMG_DTU               = 5;
34
    
35
    /** @var FormGenerator the FormGenerator this element belongs to     */
36
    protected FormGenerator $oFG;
37
    /** @var FormContainer the parent element - only FormGenerator must has no parent     */
38
    protected ?FormContainer $oParent = null;
39
    /** @var int tab index of the element if it can get focus     */
40
    protected int $iTabindex = -1;
41
    /** @var int col inside current line     */
42
    protected int $iCol = 0;
43
    /** @var string element name     */
44
    protected string $strName = '';
45
    /** @var string element id     */
46
    protected string $strID = '';
47
    /** @var string CSS class of the element     */
48
    protected string $strClass = '';
49
    /** @var string validation for the element     */
50
    protected string $strValidate = '';
51
    /** @var FormFlags flags that specify the appearance and behaviour     */
52
    protected FormFlags $oFlags;
53
    /** @var array attributes of the element     */
54
    protected ?array $aAttrib = null;
55
    /** @var array (CSS) styles of the element     */
56
    protected ?array $aStyle = null;
57
    /** @var bool set to true, if element creates some JS     */
58
    protected bool $bCreateScript = false;
59
    /** @var bool set to true, if element creates some CSS style     */
60
    protected bool $bCreateStyle = false;
61
    
62
    /**
63
     * @param int $wFlags
64
     */
65
    public function __construct(int $wFlags)
66
    {
67
        $this->oFlags = new FormFlags($wFlags);
68
    }
69
70
    /**
71
     * Return the FormGenerator this element belongs to.
72
     * @return FormGenerator
73
     */
74
    public function getFG() : ?FormGenerator
75
    {
76
        return $this->oFG;
77
    }
78
79
    /**
80
     * Set the parent of this element.
81
     * The Formgenerator of the parent is adopted for this element. 
82
     * If there are global flags set for the FormGenerator, this flags are added.
83
     * @param FormContainer $oParent
84
     */
85
    public function setParent(FormContainer $oParent) : void 
86
    {
87
        $this->oParent = $oParent;
88
        $this->oFG = $oParent->oFG;
89
        $this->addFlags($this->oFG->getGlobalFlags());
90
        $this->onParentSet();
91
    }
92
    
93
    /**
94
     * Set the current col.
95
     * If this element is added as a child of a FormLine, the column is set in 
96
     * order to be able to calculate the correct width of the element.
97
     * @param int $iCol
98
     */
99
    public function setCol(int $iCol) : void
100
    {
101
        $this->iCol = $iCol;
102
    }
103
    
104
    /**
105
     * Set ID for the element.
106
     * @param string $strID
107
     */
108
    public function setID(string $strID) : void 
109
    {
110
        $this->strID = $strID;
111
    }
112
    
113
    /**
114
     * Set text for the elements title attribute.
115
     * @param string $strTitle
116
     */
117
    public function setTitle(string $strTitle) : void 
118
    {
119
        if (strlen($strTitle) > 0) {
120
            $this->addAttribute('title', $strTitle);
121
        }
122
    }
123
    
124
    /**
125
     * Set the tab index of the element.
126
     * Method is called from the PageGenerator after an element is added to the form.
127
     * @param int $iTabindex
128
     * @return int the number of indexes, the element needs
129
     */
130
    public function setTabindex(int $iTabindex) : int
0 ignored issues
show
Unused Code introduced by
The parameter $iTabindex is not used and could be removed. ( Ignorable by Annotation )

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

130
    public function setTabindex(/** @scrutinizer ignore-unused */ int $iTabindex) : int

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
131
    {
132
        return 0;
133
    }
134
    
135
    /**
136
     * Add flags to element. 
137
     * @param int $wFlags
138
     */
139
    public function addFlags(int $wFlags) : void 
140
    {
141
        $this->oFlags->add($wFlags);
142
    }
143
    
144
    /**
145
     * Add any attribute.
146
     * If the attribute allready exist, the value will be overwritten.
147
     * @param string $strName
148
     * @param string $strValue
149
     */
150
    public function addAttribute(string $strName, string $strValue = '') : void 
151
    {
152
        $strName = strtolower($strName);
153
        if ($this->aAttrib == null) {
154
            $this->aAttrib = array();
155
        }
156
        if ($strName == 'style') {
157
            // style should no longer be set through AddAttribute()
158
            trigger_error('use AddStyle() to define additional styles for element!', E_USER_ERROR);
159
        }
160
        $this->aAttrib[$strName] = $strValue;
161
    }
162
163
    /**
164
     * Add any style.
165
     * If the attribute allready exist, the value will be overwritten.
166
     * @param string $strName
167
     * @param string $strValue
168
     */
169
    public function addStyle(string $strName, string $strValue) : void 
170
    {
171
        $strName = strtolower($strName);
172
        if ($this->aStyle == null) {
173
            $this->aStyle = array();
174
        }
175
        $this->aStyle[$strName] = $strValue;
176
    }
177
178
    /**
179
     * Set the CSS class of the element.
180
     * Any previously setting will be overwritten.
181
     * @param string $strClass
182
     */
183
    public function setClass(string $strClass) : void 
184
    {
185
        $this->strClass = $strClass;
186
    }
187
    
188
    /**
189
     * Add additional class to element.
190
     * Class is added to the existing classname separated with a blank <br/>
191
     * Generates a notice, if no class set so far!
192
     * @param string $strClass
193
     */
194
    public function addClass(string $strClass) : void 
195
    {
196
        if (strlen($this->strClass) == 0) {
197
            trigger_error('no class set so far!', E_USER_NOTICE);
198
        }
199
        $this->strClass .= ' ' . $strClass;
200
    }
201
    
202
    /**
203
     * Get JS script related to this element.
204
     * This method gives each element the chance to add special JS script to the 
205
     * current page. <br/>
206
     * <b>This method is only called for elements having member bCreateScript set to true!</b>
207
     * @return string
208
     */
209
    public function getScript() : string
210
    {
211
        return '';
212
    }
213
    
214
    /**
215
     * Get styles related to this element.
216
     * This method gives each element the chance to add special styles to the 
217
     * current page. <br/>
218
     * <b>This method is only called for elements having member bCreateStyle set to true!</b>
219
     * @return string
220
     */
221
    public function getStyle() : string
222
    {
223
        return '';
224
    }
225
226
    /**
227
     * @return string
228
     */
229
    abstract public function getHTML() : string;
230
231
    /**
232
     * Method called, after parent amd formgenerator is set properly.
233
     * Enhancing classes can use this method, to initialize properties that
234
     * nneds the parent or formgenerator (... configuration, global settings) 
235
     */
236
    protected function onParentSet() : void
237
    {
238
    }
239
    
240
    /**
241
     * Build the 'container' div arround the current element.
242
     * Additional styles (alignment, ...) can be passed.
243
     * @param string $strStyle
244
     * @return string
245
     */
246
    protected function buildContainerDiv(string $strStyle = '') : string
247
    {
248
        if (strpos($strStyle, 'float') === false) {
249
            $strStyle = 'float: left; ' . $strStyle;
250
        }
251
        $strWidth = ($this->oParent ? $this->oParent->getColWidth($this->iCol) : '');
252
        if (!empty($strWidth)) {
253
            $strStyle = rtrim($strStyle, ';');
254
            $strStyle .= '; width: ' . $strWidth . ';';
255
        }
256
        $strHTML = '<div style="' . $strStyle . '">';
257
258
        return $strHTML;
259
    }
260
    
261
    /**
262
     * Build the style attribute for the element.
263
     * @return string
264
     */
265
    protected function buildStyle() : string
266
    {
267
        $strStyle = '';
268
        if ($this->aStyle != null) {
269
            $strStyle = ' style="';
270
            foreach ($this->aStyle as $strName => $strValue) {
271
                $strStyle .= ' ' . $strName . ': ' . $strValue . ';';
272
            }
273
            $strStyle .= '"';
274
        }
275
        return $strStyle;
276
    }
277
278
    /**
279
     * Build all defined attributes for the element.
280
     * @return string
281
     */
282
    protected function buildAttributes() : string
283
    {
284
        $strAttrib = '';
285
        if ($this->aAttrib != null) {
286
            foreach ($this->aAttrib as $strName => $strValue) {
287
                $strAttrib .= ' ' . $strName;
288
                if (strlen($strValue) > 0) {
289
                    $strAttrib .= '="' . $strValue . '"';
290
                }
291
            }
292
        }
293
        return $strAttrib;
294
    }
295
    
296
    /**
297
     * Build the markup for the value attribute.
298
     * Retrieve value for the element from the FormData. 
299
     * @return string Empty string if no value set, complete attribute if set
300
     */
301
    protected function buildValue() : string
302
    {
303
        $strHTML = '';
304
        $strValue = $this->oFG->oData->getValue($this->strName);
0 ignored issues
show
Bug introduced by
The property oData is declared protected in SKien\Formgenerator\FormGenerator and cannot be accessed from this context.
Loading history...
305
        
306
        if ($this->oFlags->isSet(FormFlags::TRIM)) {
307
            $strValue = trim($strValue);
308
        }
309
        if (!$this->oFlags->isSet(FormFlags::NO_ZERO) || ($strValue != 0 && $strValue != '0')) {
310
            $strHTML = ' value="' . str_replace('"', '&quot;', $strValue) . '"';
311
        }
312
        return $strHTML;
313
    }
314
315
    /**
316
     * Build the markup for the class attribute.
317
     * @return string Empty string if no class set, complete attribute if set
318
     */
319
    protected function buildClass() : string
320
    {
321
        $strClass = '';
322
        if (!empty($this->strClass)) {
323
            $strClass .= ' class="' . $this->strClass . '"';
324
        }
325
        return $strClass;
326
    }
327
328
    /**
329
     * Build the markup for the ID attribute.
330
     * @return string Empty string if no id set, complete attribute if set
331
     */
332
    protected function buildID() : string
333
    {
334
        $strID = '';
335
        if (!empty($this->strID)) {
336
            $strID .= ' id=' . $this->strID;
337
        }
338
        return $strID;
339
    }
340
    
341
    /**
342
     * Build the markup for the tabindex attribute.
343
     * @return string Empty string if $iTabindex = 0, complete attribute if set
344
     */
345
    protected function buildTabindex() : string
346
    {
347
        $strTabindex = '';
348
        if ($this->iTabindex > 0) {
349
            $strTabindex = ' tabindex="' . $this->iTabindex . '"';
350
        }
351
        return $strTabindex;
352
    }
353
    
354
    /**
355
     * Get filename for predifined standard images
356
     * @param int $iImage
357
     * @return string
358
     */
359
    protected function getStdImage(int $iImage) : string
360
    {
361
        // TODO: Find a more general way of defining standard images. (possibly via a config)
362
        $strPath = '../images/';
363
        if ($this->oFG !== null) {
364
            $strPath = $this->oFG->getImagePath();
365
        }
366
        $aImage = array(
367
            self::IMG_DELETE                => '16x16/admin_delete.png',
368
            self::IMG_SEARCH                => '16x16/search.png',
369
            self::IMG_DATE_PICKER           => '16x16/datepicker.png',
370
            self::IMG_TIME_PICKER           => '16x16/timepicker.png',
371
            self::IMG_DTU                   => '16x16/admin_dtu.png',
372
        );
373
        
374
        $strImg = '';
375
        if (isset($aImage[$iImage])) {
376
            $strImg = $strPath . $aImage[$iImage];
377
        }
378
        return $strImg;
379
    }
380
    
381
    /**
382
     * Parse a given style attribute into the components it contains.
383
     * @param string $strStyle
384
     * @return array
385
     */
386
    static public function parseStyle($strStyle) : array
387
    {
388
        $aStyle = array();
389
        $aStyles = explode(';', trim($strStyle));
390
        foreach ($aStyles as $strStyleDef) {
391
            $aStyleDef = explode(':', trim($strStyleDef));
392
            if (count($aStyleDef) == 2) {
393
                $strName = trim($aStyleDef[0]);
394
                $strValue = trim($aStyleDef[1]);
395
                $strValue = rtrim($strValue, ';');
396
                $aStyle[$strName] = $strValue;
397
            }
398
        }
399
        return $aStyle;
400
    }
401
    
402
}
403
404