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

FormGenerator::getConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\Formgenerator;
5
6
use SKien\Config\ConfigInterface;
0 ignored issues
show
Bug introduced by
The type SKien\Config\ConfigInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use SKien\Config\NullConfig;
0 ignored issues
show
Bug introduced by
The type SKien\Config\NullConfig was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
9
/**
10
 * Container for all form 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
class FormGenerator extends FormContainer
22
{
23
    /** JS code to close dialog */
24
    const CMD_CLOSE_DLG = "parent.document.getElementById('dialog').innerHTML = '';";
25
    
26
    /** @var int last tab position in the form   */
27
    protected int $iLastTabindex = 0;
28
    /** @var bool set the whole form to readonly  */
29
    protected bool $bReadOnly = false;
30
    /** @var bool set debug mode to output more information  */
31
    protected bool $bDebugMode = false;
32
    /** @var string JS handler for onsubmit  */
33
    protected string $strOnSubmit = '';
34
    /** @var string JS handler for oncancel  */
35
    protected string $strOnCancel = '';
36
    /** @var int explicit width of the form in pixel  */
37
    protected int $iWidth = -1;
38
    /** @var FormFlags global flags for all form elements  */
39
    protected FormFlags $oGlobalFlags;
40
    /** @var array elements that creates dynamic script */
41
    protected array $aScriptElements = [];
42
    /** @var array elements that creates dynamic CSS styles */
43
    protected array $aStyleElements = [];
44
    /** @var string path to the images  */
45
    protected string $strImgPath;
46
    /** @var string URL params for the form action  */
47
    protected string $strAction;
48
    /** @var string form target  */
49
    protected string $strFormTarget = '';
50
    /** @var array array to hold elements for validation  */
51
    protected array $aValidate;
52
    /** @var FormDataInterface data provider     */
53
    protected FormDataInterface $oData;
54
    /** @var ConfigInterface configuration     */
55
    protected ConfigInterface $oConfig;
56
57
    /**
58
     * Create a FormGenerator.
59
     * Set some values to default.
60
     */
61
    public function __construct(?FormDataInterface $oData, string $strID = 'FormGenerator') 
62
    {
63
        $this->oFG = $this;
64
        $this->oData = $oData ?? new NullFormData();
65
        $this->oConfig = new NullConfig();
66
        $this->oGlobalFlags = new FormFlags();
67
        $this->strID = $strID;
68
        $this->aValidate = array('aMand' => array(), 'aEdit' => array(), 'aDate' => array(), 'aInt' => array(), 'aCur' => array(), 'aTime' => array());
69
        $this->strOnSubmit = "validateForm();";
70
        $this->strOnCancel = "javascript:history.back();";
71
        $this->strImgPath = '../images/';
72
        $this->strAction = $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
73
        $this->bDebugMode = (error_reporting() & (E_USER_ERROR | E_USER_WARNING)) != 0; 
74
    }
75
    
76
    /**
77
     * @return \SKien\Formgenerator\FormDataInterface
78
     */
79
    public function getData() : FormDataInterface
80
    {
81
        return $this->oData;
82
    }
83
    
84
    /**
85
     * @return \SKien\Config\ConfigInterface
86
     */
87
    public function getConfig() : ConfigInterface
88
    {
89
        return $this->oConfig;
90
    }
91
    
92
    /**
93
     * @param \SKien\Formgenerator\FormDataInterface $oData
94
     */
95
    public function setData(FormDataInterface $oData) : void
96
    {
97
        $this->oData = $oData;
98
    }
99
    
100
    /**
101
     * @param \SKien\Config\ConfigInterface $oConfig
102
     */
103
    public function setConfig(ConfigInterface $oConfig) : void
104
    {
105
        $this->oConfig = $oConfig;
106
    }
107
    
108
    /**
109
     * Set the action executed when submit the form.
110
     * If not changed here, <i><b>$_SERVER['QUERY_STRING']</b></i> is used.
111
     * @param string $strAction (default = '')
112
     */
113
    public function setAction(string $strAction) : void
114
    {
115
        $this->strAction = $strAction;
116
    }
117
118
    /**
119
     * Set the path to images.
120
     * @param string $strPath
121
     */
122
    public function setImagePath(string $strPath) : void 
123
    {
124
        $this->strImgPath = $strPath;
125
    }
126
127
    /**
128
     * @return string current image path
129
     */
130
    public function getImagePath() : string
131
    {
132
        return $this->strImgPath;
133
    }
134
    
135
    /**
136
     * Get the global flags.
137
     * @return int
138
     */
139
    public function getGlobalFlags() : int
140
    {
141
        return $this->oGlobalFlags->getFlags();
142
    }
143
    
144
    /**
145
     * Set the target
146
     * @param string $strFormTarget
147
     */
148
    public function setTarget(string $strFormTarget) : void 
149
    {
150
        $this->strFormTarget = $strFormTarget;
151
    }
152
    
153
    /**
154
     * Set explicit width of the form.
155
     * @param int $iWidth    width (-1 for default)
156
     */
157
    public function setFormWidth(int $iWidth) : void 
158
    {
159
        $this->iWidth = $iWidth;
160
    }
161
    
162
    /**
163
     * Sets the whole form to readonly. 
164
     * All elements of the form set to disabled, Save/Cancel-Buttons are replaced 
165
     * with Close-Button
166
     * @param bool $bReadOnly
167
     */
168
    public function setReadOnly(bool $bReadOnly) : void 
169
    {
170
        $this->bReadOnly = $bReadOnly;
171
        if ($bReadOnly) {
172
            $this->oGlobalFlags->add(FormFlags::READ_ONLY);
173
        } else {
174
            $this->oGlobalFlags->remove(FormFlags::READ_ONLY);
175
        }
176
    }
177
    
178
    /**
179
     * Sets the debug mode to output more information.
180
     * Especialy for some elements, that need additional JS it can be helpfull to
181
     * turn on the debug mode. 
182
     * @param bool $bDebugMode
183
     */
184
    public function setDebugMode(bool $bDebugMode) : void
185
    {
186
        // Even if we plan to integrate a logger, we keep the debug mode alive because the 
187
        // logger do not cover the JS side (missing scripts, ...) and developers often 
188
        // forget to take a look at the Browser console.
189
        $this->bDebugMode = $bDebugMode;
190
    }
191
    
192
    /**
193
     * Get state of the debug mode.
194
     * @return bool
195
     */
196
    public function getDebugMode() : bool
197
    {
198
        return $this->bDebugMode;
199
    }
200
    
201
    /**
202
     * Specify the form as an 'Dialog'.
203
     * Dialog means, the form runs inside of an dynamic iframe created in the
204
     * dialog - DIV of the parent. <br/>
205
     * The cancel can easy be done by clear the content of that dialog-DIV.
206
     */
207
    public function setDialog() : void
208
    {
209
        $this->setOnCancel(self::CMD_CLOSE_DLG);
210
    }
211
    
212
    /**
213
     * Change JS handler for form submit from default "ValidateForm();";<br/><br/>
214
     * Hide button, if set to empty string.<br/><br/>
215
     * <b>!! Attention !!</b>
216
     * don't use double quotes in function!
217
     * @param string $strOnSubmit
218
     */
219
    public function setOnSubmit(string $strOnSubmit) : void 
220
    {
221
        $this->strOnSubmit = $strOnSubmit;
222
    }
223
224
    /**
225
     * Change JS handler for cancel/close - button from default "javascript:history.back();";<br/><br/>
226
     * Hide button, if set to empty string.<br/><br/>
227
     * <b>!! Attention !!</b>
228
     * don't use double quotes in function!
229
     * @param string $strOnCancel
230
     */
231
    public function setOnCancel(string $strOnCancel) : void 
232
    {
233
        $this->strOnCancel = $strOnCancel;
234
    }
235
    
236
    /**
237
     * Add any element to the form.
238
     * @param FormElement $oElement
239
     */
240
    public function addElement(FormElement $oElement) : void 
241
    {
242
        $this->iLastTabindex += $oElement->setTabindex($this->iLastTabindex + 1);
243
        if (!$oElement->oFlags->isSet(FormFlags::HIDDEN)) {
244
            if (!empty($oElement->strValidate)) {
245
                array_push($this->aValidate[$oElement->strValidate], $oElement->strName);
246
            }
247
            if ($oElement->oFlags->isSet(FormFlags::MANDATORY)) {
248
                array_push($this->aValidate['aMand'], $oElement->strName);
249
            }
250
        }
251
        if ($oElement->bCreateScript) {
252
            $this->aScriptElements[] = $oElement;
253
        }
254
        if ($oElement->bCreateStyle) {
255
            $this->aStyleElements[] = $oElement;
256
        }
257
    }
258
    
259
    /**
260
     * Create HTML for defined form.
261
     * @return string
262
     */
263
    public function getForm() : string
264
    {
265
        $strHTML = PHP_EOL;
266
        $strHTML .= '<!-- start autogenerated form -->' . PHP_EOL;
267
        $strHTML .= '<form';
268
        if (!empty($this->strAction)) {
269
            $strHTML .= ' action="';
270
            $strHTML .= $this->strAction . '"';
271
        }
272
        if (!empty($this->strFormTarget)) {
273
            $strHTML .= ' target="' . $this->strFormTarget . '"';
274
        }
275
        if ($this->aAttrib != null) {
276
            foreach ($this->aAttrib as $strName => $strValue) {
277
                $strHTML .= ' ' . $strName . '="' . $strValue . '"';
278
            }
279
        }
280
        $strHTML .= $this->buildStyle();
281
        $strHTML .= ' method="post" id=' . $this->strID . ' onsubmit="return ' . $this->strOnSubmit . '">' . PHP_EOL;
282
        $iCnt = count($this->aChild);
283
        for ($i = 0; $i < $iCnt; $i++) {
284
            $strHTML .= $this->aChild[$i]->GetHTML();
285
        }
286
        
287
        $strHTML .= '</form>' . PHP_EOL;
288
        $strHTML .= '<!-- end autogenerated form -->' . PHP_EOL;
289
        $strHTML .= PHP_EOL;
290
        
291
        return $strHTML;
292
    }
293
    
294
    /**
295
     * Build needed JS script.
296
     * - for validation
297
     * - scripts of all childs that have own script
298
     * @return string
299
     */
300
    public function getScript() : string
301
    {
302
        $strScript = '';
303
        if ($this->getDebugMode()) {
304
            // in debug environment we give alert if scriptfile is missing!
305
            $strScript  = "if (typeof FormDataValidator === 'undefined') {";
306
            $strScript .= "    alert('You must include <FormDataValidator.js> for Form Validation!');";
307
            $strScript .= "}" . PHP_EOL;
308
        }
309
        
310
        $aArrays = array('aMand', 'aDate', 'aTime', 'aInt', 'aCur');
311
        
312
        $strScript .= 'function validateForm() {' . PHP_EOL;
313
        $iArrays = count($aArrays);
314
        for ($j = 0; $j < $iArrays; $j++) {
315
            $sep = '';
316
            $strScript .= '    var ' . $aArrays[$j] . ' = new Array(';
317
            $iCnt = count($this->aValidate[$aArrays[$j]]);
318
            for ($i = 0; $i < $iCnt; $i++) {
319
                $strScript .= $sep . '"' . $this->aValidate[$aArrays[$j]][$i] . '"';
320
                $sep = ', ';
321
            }
322
            $strScript .= ');' . PHP_EOL;
323
        }
324
        
325
        $strScript .= PHP_EOL;
326
        $strScript .= '    var FDV = new FormDataValidator(aMand, aDate, aTime, aInt, aCur);' . PHP_EOL;
327
        $strScript .= '    return FDV.validate();' . PHP_EOL;
328
        $strScript .= '}' . PHP_EOL;
329
        
330
        foreach ($this->aScriptElements as $oElement) {
331
            $strScript .= $oElement->getScript();
332
        }
333
        return $strScript;
334
    }
335
    
336
    /**
337
     * Build needed CSS styles.
338
     * - body, if form width defined (TODO: better set width of form-element??)
339
     * - styles of all childs that have own styles
340
     * @return string
341
     */
342
    public function getStyle() : string 
343
    {
344
        $strStyle = '';
345
        if ($this->iWidth > 0) {
346
            $strStyle  = "body { width: " . $this->iWidth . "px;}" . PHP_EOL;
347
        }
348
        foreach ($this->aStyleElements as $oElement) {
349
            $strStyle .= $oElement->getStyle();
350
        }
351
        return $strStyle;   
352
    }
353
}
354