Passed
Push — main ( dedf73...0dcdcf )
by Stefan
01:14
created

FormGenerator::setReadOnly()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 2
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
rs 10
1
<?php
2
namespace SKien\Formgenerator;
3
4
use SKien\Formgenerator\FormElement as FE;
5
6
/**
7
 * Container for all form elements.
8
 *
9
 * #### History
10
 * - *2020-05-12*   initial version
11
 * - *2021-01-07*   PHP 7.4
12
 *
13
 * @package Formgenerator
14
 * @version 1.1.0
15
 * @author Stefanius <[email protected]>
16
 * @copyright MIT License - see the LICENSE file for details
17
 */
18
class FormGenerator extends FormElement
19
{
20
    use FormHelperFromSQL;
21
    
22
    /** save/submit button */
23
    const BTN_SAVE      = 'save';
24
    /** cancel/discard button */
25
    const BTN_CANCEL    = 'cancel';
26
    /** close button */
27
    const BTN_CLOSE     = 'close';
28
    
29
    /** JS code to close dialog */
30
    const CMD_CLOSE_DLG = "parent.document.getElementById('dialog').innerHTML = '';";
31
    
32
    /** @var int last tab position in the form   */
33
    protected int $iLastTab = 0;
34
    /** @var string timestamp of last modification  */
35
    protected ?string $tsModified = null;
36
    /** @var string user of last modification  */
37
    protected ?string $strUserModified = null;
38
    /** @var bool set the whole form to readonly  */
39
    protected bool $bReadOnly = false;
40
    /** @var string JS handler for onsubmit  */
41
    protected string $strOnSubmit = '';
42
    /** @var string JS handler for oncancel  */
43
    protected string $strOnCancel = '';
44
    /** @var int explicit width of the form in pixel  */
45
    protected int $iWidth = -1;
46
    /** @var int global flags for all form elements  */
47
    protected int $wGlobalFlags = 0;
48
    /** @var array elements that creates dynamic script */
49
    protected array $aScriptElements = [];
50
    /** @var array elements that creates dynamic CSS styles */
51
    protected array $aStyleElements = [];
52
    /** @var string path to the images  */
53
    protected string $strImgPath;
54
    /** @var string receiver of the form-action  */
55
    protected string $strActionReceiver;
56
    /** @var string URL params for the form action  */
57
    protected string $strAction;
58
    /** @var string form target  */
59
    protected string $strFormTarget = '';
60
    /** @var FormElement hidden element containing the referer of this form */
61
    protected ?FormElement $oReferer = null;
62
    /** @var bool hide the submit/cancel/close buttons  */
63
    protected bool $bHideButtons = false;
64
    /** @var array text for the submit/cancel/close buttons  */
65
    protected array $aBtnText;
66
    /** @var array array to hold elements for validation  */
67
    protected array $aValidate;
68
    
69
    /**
70
     * Create a FormGenerator.
71
     * Set some values to default.
72
     */
73
    public function __construct() 
74
    {
75
        $this->oFG = $this;
76
        $this->strID = 'auto_form';
77
        $this->aValidate = array('aMand' => array(), 'aEdit' => array(), 'aDate' => array(), 'aInt' => array(), 'aCur' => array(), 'aTime' => array());
78
        $this->aBtnText = array('save' => 'Speichern', 'cancel' => 'Abbrechen', 'close' => 'Schließen');
79
        $this->strOnSubmit = "ValidateForm();";
80
        $this->strOnCancel = "javascript:history.back();";
81
        $this->strImgPath = '../images/';
82
        $this->strAction = $_SERVER['QUERY_STRING'];
83
        $this->strActionReceiver = $_SERVER['PHP_SELF'] . '?';
84
        $strReferer = $_SERVER['HTTP_REFERER'] ?? '';
85
        $this->oReferer = $this->add(new FormInput('urlReferer', $strReferer, -1, self::HIDDEN));
86
    }
87
    
88
    /**
89
     * Set the action executed when submit the form.
90
     * If not changed here, <i><b>$_SERVER['QUERY_STRING']</b></i> is used.
91
     * @param string $strAction (default = '')
92
     */
93
    public function setAction(string $strAction) : void
94
    {
95
        $this->strAction = $strAction;
96
    }
97
98
    /**
99
     * Set the receiver of the formaction.
100
     * If not changed here, the current script ($_SERVER['PHP_SELF']) will
101
     * receive the form action.
102
     * @param string $strActionReceiver
103
     */
104
    public function setActionReceiver(string $strActionReceiver) : void 
105
    {
106
        // remove trailing '?' if exist
107
        $strActionReceiver = rtrim($strActionReceiver, '?');
108
        if (strpos($strActionReceiver, '?') !== false) {
109
            // URL params already exist - continue with '&'
110
            $strActionReceiver .= '&';
111
        } else {
112
            $strActionReceiver .= '?';
113
        }
114
        $this->strActionReceiver = $strActionReceiver;
115
    }
116
117
    /**
118
     * Set the path to images.
119
     * @param string $strPath
120
     */
121
    public function setImagePath(string $strPath) : void 
122
    {
123
        $this->strImgPath = $strPath;
124
    }
125
126
    /**
127
     * @return string current image path
128
     */
129
    public function getImagePath() : string
130
    {
131
        return $this->strImgPath;
132
    }
133
    
134
    /**
135
     * Get the global flags.
136
     * @return int
137
     */
138
    public function getGlobalFlags() : int
139
    {
140
        return $this->wGlobalFlags;
141
    }
142
    
143
    /**
144
     * Set the target
145
     * @param string $strFormTarget
146
     */
147
    public function setTarget(string $strFormTarget) : void 
148
    {
149
        $this->strFormTarget = $strFormTarget;
150
    }
151
    
152
    /**
153
     * Set explicit width of the form.
154
     * @param int $iWidth    width (-1 for default)
155
     */
156
    public function setFormWidth(int $iWidth) : void 
157
    {
158
        $this->iWidth = $iWidth;
159
    }
160
    
161
    /**
162
     * Sets the whole form to readonly. 
163
     * All elements of the form set to disabled, Save/Cancel-Buttons are replaced 
164
     * with Close-Button
165
     * @param bool $bReadOnly
166
     */
167
    public function setReadOnly(bool $bReadOnly) : void 
168
    {
169
        $this->bReadOnly = $bReadOnly;
170
        $bReadOnly ? $this->wGlobalFlags |= self::DISABLED : $this->wGlobalFlags &= ~self::DISABLED;
171
    }
172
173
    /**
174
     * Don't create formbuttons save/cancel/close
175
     * @param bool $bHideButtons
176
     */
177
    public function hideButtons($bHideButtons = true) : void 
178
    {
179
        $this->bHideButtons = $bHideButtons;
180
    }
181
    
182
    /**
183
     * Set timestamp and user of last modification
184
     * @param string $tsModified timestamp from database
185
     * @param string $strUserModified
186
     */
187
    public function setLastModified(string $tsModified, string $strUserModified) : void 
188
    {
189
        $this->tsModified = $tsModified;
190
        $this->strUserModified = $strUserModified;
191
    }
192
    
193
    /**
194
     * Specify the form as an 'Dialog'.
195
     * Dialog means, the form runs inside of an dynamic iframe created in the
196
     * dialog - DIV of the parent. <br/>
197
     * The cancel can easy be done by clear the content of that dialog-DIV.
198
     */
199
    public function setDialog() : void
200
    {
201
        $this->setOnCancel(self::CMD_CLOSE_DLG);
202
    }
203
    
204
    /**
205
     * Changes default text for selected button
206
     * defaults:   
207
     * - 'save'     => 'Speichern'
208
     * - 'cancel'   => 'Abbrechen'
209
     * - 'close'    => 'Schließen'
210
     * 
211
     * @param string $strBtn   FormGenerator::BTN_SAVE, FormGenerator::BTN_CANCEL or FormGenerator::BTN_CLOSE
212
     * @param string $strText
213
     */
214
    public function setBtnText(string $strBtn, string $strText) : void 
215
    {
216
        if (isset($this->aBtnText[$strBtn])) {
217
            $this->aBtnText[$strBtn] = $strText;
218
        } else {
219
            trigger_error('invalid Button specified!', E_USER_WARNING);
220
        }
221
    }
222
    
223
    /**
224
     * Change JS handler for form submit from default "ValidateForm();";<br/><br/>
225
     * Hide button, if set to empty string.<br/><br/>
226
     * <b>!! Attention !!</b>
227
     * don't use double quotes in function!
228
     * @param string $strOnSubmit
229
     */
230
    public function setOnSubmit(string $strOnSubmit) : void 
231
    {
232
        $this->strOnSubmit = $strOnSubmit;
233
    }
234
235
    /**
236
     * Change JS handler for cancel/close - button from default "javascript:history.back();";<br/><br/>
237
     * Hide button, if set to empty string.<br/><br/>
238
     * <b>!! Attention !!</b>
239
     * don't use double quotes in function!
240
     * @param string $strOnCancel
241
     */
242
    public function setOnCancel(string $strOnCancel) : void 
243
    {
244
        $this->strOnCancel = $strOnCancel;
245
    }
246
    
247
    /**
248
     * Add any element to the form.
249
     * @param FormElement $oElement
250
     */
251
    public function addElement(FormElement $oElement) : void 
252
    {
253
        if ($oElement->hasTab()) {
254
            $oElement->setTab(++$this->iLastTab);
255
        }
256
        if (!empty($oElement->strValidate) && ($oElement->wFlags & FE::HIDDEN) == 0) {
257
            array_push($this->aValidate[$oElement->strValidate], $oElement->strName);
258
            if (($oElement->wFlags & FE::MANDATORY) != 0) {
259
                array_push($this->aValidate['aMand'], $oElement->strName);
260
            }
261
        }
262
        if ($oElement->bCreateScript) {
263
            $this->aScriptElements[] = $oElement;
264
        }
265
        if ($oElement->bCreateStyle) {
266
            $this->aStyleElements[] = $oElement;
267
        }
268
    }
269
    
270
    /**
271
     * Create HTML for defined form.
272
     * @return string
273
     */
274
    public function getForm() : string
275
    {
276
        $strHTML = PHP_EOL;
277
        $strHTML .= '<!-- start autogenerated form -->' . PHP_EOL;
278
        $strHTML .= '<form';
279
        if (!empty($this->strAction)) {
280
            $strHTML .= ' action="';
281
            $strHTML .= $this->strActionReceiver;
282
            $strHTML .= $this->strAction . '"';
283
        }
284
        if (!empty($this->strFormTarget)) {
285
            $strHTML .= ' target="' . $this->strFormTarget . '"';
286
        }
287
        if ($this->aAttrib != null) {
288
            foreach ($this->aAttrib as $strName => $strValue) {
289
                $strHTML .= ' ' . $strName . '="' . $strValue . '"';
290
            }
291
        }
292
        $strHTML .= $this->buildStyle();
293
        $strHTML .= ' method="post" id=' . $this->strID . ' onsubmit="return ' . $this->strOnSubmit . '">' . PHP_EOL;
294
        $iCnt = count($this->aChild);
295
        for ($i = 0; $i < $iCnt; $i++) {
296
            $strHTML .= $this->aChild[$i]->GetHTML();
297
        }
298
        
299
        if (!$this->bHideButtons) {
300
            $strHTML .= '<div id=formbuttons>' . PHP_EOL;
301
            if (!$this->bReadOnly) {
302
                if (!empty($this->strOnSubmit)) {
303
                    $strHTML .= '   <input id="btnSubmit" type="submit" tabindex="100" value="' . $this->aBtnText['save'] . '">' . PHP_EOL;
304
                }
305
                if (!empty($this->strOnCancel)) {
306
                    $strHTML .= '   <input id="btnCancel" type="button" tabindex="101" value="' . $this->aBtnText['cancel'] . '" onclick="' . $this->strOnCancel . '">' . PHP_EOL;
307
                }
308
            } else {
309
                $strHTML .= '   <input id="btnClose" type="button" tabindex="101" value="' . $this->aBtnText['close'] . '" onclick="' . $this->strOnCancel . '">' . PHP_EOL;
310
            }
311
            
312
            $strHTML .= '</div>' . PHP_EOL;
313
        }
314
        $strHTML .= $this->showLastModified();
315
        
316
        $strHTML .= '</form>' . PHP_EOL;
317
        $strHTML .= '<!-- end autogenerated form -->' . PHP_EOL;
318
        $strHTML .= PHP_EOL;
319
        
320
        return $strHTML;
321
    }
322
    
323
    /**
324
     * Build infos for last modification (if $this->tsModified set)
325
     * @return string
326
     */
327
    protected function showLastModified() : string 
328
    {
329
        $strHTML = '';
330
        if (!empty($this->tsModified)) {
331
            $strHTML .= '<h4>letzte &Auml;nderung am <span class="lastmodified">';
332
            $strHTML .= $this->tsFromSQL('d.m.Y H:i', $this->tsModified);
333
            $strHTML .= '</span> von <span class="lastmodified">';
334
            $strHTML .= $this->strUserModified;
335
            $strHTML .= '</span></h4>' . PHP_EOL;
336
        }
337
        return $strHTML;
338
    }
339
    
340
    /**
341
     * Build needed JS script.
342
     * - for validation
343
     * - scripts of all childs that have own script
344
     * @return string
345
     */
346
    public function getScript() : string
347
    {
348
        $aArrays = array('aMand', 'aDate', 'aTime', 'aInt', 'aCur');
349
        
350
        $strScript  = 'function ValidateForm() {' . PHP_EOL;
351
        $iArrays = count($aArrays);
352
        for ($j = 0; $j < $iArrays; $j++) {
353
            $sep = '';
354
            $strScript .= '    var ' . $aArrays[$j] . ' = new Array(';
355
            $iCnt = count($this->aValidate[$aArrays[$j]]);
356
            for ($i = 0; $i < $iCnt; $i++) {
357
                $strScript .= $sep .  '"' . $this->aValidate[$aArrays[$j]][$i] . '"';
358
                $sep = ', ';
359
            }
360
            $strScript .= ');' . PHP_EOL;
361
        }
362
        
363
        $strScript .= PHP_EOL;
364
        $strScript .= '    return ValidateInput2(aMand, aDate, aTime, aInt, aCur);' . PHP_EOL;
365
        $strScript .= '}' . PHP_EOL;
366
        
367
        foreach ($this->aScriptElements as $oElement) {
368
            $strScript .= $oElement->getScript();
369
        }
370
        return $strScript;
371
    }
372
    
373
    /**
374
     * Build needed CSS styles.
375
     * - body, if form width defined (TODO: better set width of form-element??)
376
     * - styles of all childs that have own styles
377
     * @return string
378
     */
379
    public function getStyle() : string 
380
    {
381
        $strStyle = '';
382
        if ($this->iWidth > 0) {
383
            $strStyle  = "body { width: " . $this->iWidth . "px;}" . PHP_EOL;
384
        }
385
        foreach ($this->aStyleElements as $oElement) {
386
            $strStyle .= $oElement->getStyle();
387
        }
388
        return $strStyle;   
389
    }
390
}
391