Continued:
[core.git] / framework / main / classes / helper / html / forms / class_HtmlFormHelper.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Helper;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Database\Frontend\User\UserDatabaseFrontend;
8 use Org\Mxchange\CoreFramework\Factory\Object\ObjectFactory;
9 use Org\Mxchange\CoreFramework\Generic\NullPointerException;
10 use Org\Mxchange\CoreFramework\Helper\Template\HelpableTemplate;
11 use Org\Mxchange\CoreFramework\Registry\GenericRegistry;
12 use Org\Mxchange\CoreFramework\Template\CompileableTemplate;
13
14 // Import SPL stuff
15 use \InvalidArgumentException;
16
17 /**
18  * A helper for constructing web forms
19  *
20  * @author              Roland Haeder <webmaster@shipsimu.org>
21  * @version             0.0.0
22  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2021 Core Developer Team
23  * @license             GNU GPL 3.0 or any newer version
24  * @link                http://www.shipsimu.org
25  *
26  * This program is free software: you can redistribute it and/or modify
27  * it under the terms of the GNU General Public License as published by
28  * the Free Software Foundation, either version 3 of the License, or
29  * (at your option) any later version.
30  *
31  * This program is distributed in the hope that it will be useful,
32  * but WITHOUT ANY WARRANTY; without even the implied warranty of
33  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34  * GNU General Public License for more details.
35  *
36  * You should have received a copy of the GNU General Public License
37  * along with this program. If not, see <http://www.gnu.org/licenses/>.
38  */
39 class HtmlFormHelper extends BaseHtmlHelper implements HelpableTemplate {
40         /**
41          * Whether the form tag is opened (keep at false or else your forms will
42          * never work!)
43          */
44         private $formOpened = false;
45
46         /**
47          * Name of current form
48          */
49         private $formName = '';
50
51         /**
52          * Id of current form
53          */
54         private $formId = '';
55
56         /**
57          * Whether form tag is enabled (default: true)
58          */
59         private $formEnabled = true;
60
61         // Class Constants
62         const EXCEPTION_FORM_NAME_INVALID       = 0x120;
63         const EXCEPTION_CLOSED_FORM             = 0x121;
64         const EXCEPTION_OPENED_FORM             = 0x122;
65         const EXCEPTION_UNEXPECTED_CLOSED_GROUP = 0x123;
66
67         /**
68          * Protected constructor
69          *
70          * @return      void
71          */
72         private function __construct () {
73                 // Call parent constructor
74                 parent::__construct(__CLASS__);
75         }
76
77         /**
78          * Creates the helper class with the given template engine instance and form name
79          *
80          * @param       $templateInstance       An instance of a valid template engine
81          * @param       $formName                       Name of the form
82          * @param       $formId                         Value for 'id' attribute (default: $formName)
83          * @param       $withForm                       Whether include the form tag
84          * @return      $helperInstance         A preparedf instance of this helper
85          */
86         public static final function createHtmlFormHelper (CompileableTemplate $templateInstance, string $formName, string $formId = NULL, bool $withForm = true) {
87                 // Get new instance
88                 $helperInstance = new HtmlFormHelper();
89
90                 // Set template instance
91                 $helperInstance->setTemplateInstance($templateInstance);
92
93                 // Is the form id not set?
94                 if (is_null($formId)) {
95                         // Use form id from form name
96                         $formId = $formName;
97                 }
98
99                 // Set form name
100                 $helperInstance->setFormName($formName);
101
102                 // A form-less field may say 'false' here...
103                 if ($withForm === true) {
104                         // Create the form
105                         $helperInstance->addFormTag($formName, $formId);
106                 } else {
107                         // Disable form
108                         $helperInstance->enableForm(false);
109                 }
110
111                 // Return the prepared instance
112                 return $helperInstance;
113         }
114
115         /**
116          * Add the form tag or close it an already opened form tag
117          *
118          * @param       $formName       Name of the form (default: false)
119          * @param       $formId         Id of the form (attribute 'id'; default: false)
120          * @return      void
121          * @throws      InvalidFormNameException        If the form name is invalid ( = false)
122          * @todo        Add some unique PIN here to bypass problems with some browser and/or extensions
123          */
124         public function addFormTag (string $formName = NULL, string $formId = NULL) {
125                 // When the form is not yet opened at least form name must be valid
126                 if (($this->formOpened === false) && (is_null($formName))) {
127                         // Thrown an exception
128                         throw new InvalidFormNameException ($this, self::EXCEPTION_FORM_NAME_INVALID);
129                 }
130
131                 // Close the form is default
132                 $formContent = '</form>';
133
134                 // Check whether we shall open or close the form
135                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
136                         // Add HTML code
137                         $formContent = sprintf("<form name=\"%s\" class=\"forms\" action=\"%s/%s\" method=\"%s\" target=\"%s\" id=\"%s_form\">",
138                                 $formName,
139                                 FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('base_url'),
140                                 FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('form_action'),
141                                 FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('form_method'),
142                                 FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('form_target'),
143                                 $formId
144                         );
145
146                         // Open the form and remeber the form name and id
147                         $this->formName = $formName;
148                         $this->formId = $formId;
149                         $this->formOpened = true;
150
151                         // Add it to the content
152                         $this->addHeaderContent($formContent);
153                 } else {
154                         // Add the hidden field required to identify safely this form
155                         $this->addInputHiddenField('form', $this->getFormName());
156
157                         // Is a group open?
158                         if ($this->ifGroupOpenedPreviously()) {
159                                 // Then automatically close it here
160                                 $this->addFormGroup();
161                         }
162
163                         // Simply close it
164                         $this->formOpened = false;
165
166                         // Add it to the content
167                         $this->addFooterContent($formContent);
168                 }
169         }
170
171         /**
172          * Add a text input tag to the form or throw an exception if it is not yet
173          * opened. The field's name will be set as id.
174          *
175          * @param       $fieldName              Input field name
176          * @param       $fieldValue             Input default value (default: empty)
177          * @return      void
178          * @throws      FormClosedException             If the form is not yet opened
179          */
180         public function addInputTextField (string $fieldName, string $fieldValue = '') {
181                 // Is the form opened?
182                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
183                         // Throw an exception
184                         throw new FormClosedException (array($this, $fieldName), self::EXCEPTION_CLOSED_FORM);
185                 }
186
187                 // Generate the content
188                 $inputContent = sprintf('<input type="text" class="form-control" id="%s_%s_field" name="%s" value="%s" />',
189                         $this->getFormId(),
190                         $fieldName,
191                         $fieldName,
192                         $fieldValue
193                 );
194
195                 // And add it maybe with a 'li' tag
196                 $this->addContentToPreviousGroup($inputContent);
197         }
198
199         /**
200          * Add a text input tag to the form with pre-loaded default value
201          *
202          * @param       $fieldName      Input field name
203          * @return      void
204          */
205         public function addInputTextFieldWithDefault (string $fieldName) {
206                 // Get the value from instance
207                 $fieldValue = $this->getValueField($fieldName);
208                 //* DEBUG: */ print __METHOD__.':'.$fieldName.'='.$fieldValue."<br />\n";
209
210                 // Add the text field
211                 $this->addInputTextField($fieldName, $fieldValue);
212         }
213
214         /**
215          * Add a password input tag to the form or throw an exception if it is not
216          * yet opened. The field's name will be set as id.
217          *
218          * @param       $fieldName              Input field name
219          * @param       $fieldValue             Input default value (default: empty)
220          * @return      void
221          * @throws      FormClosedException             If the form is not yet opened
222          */
223         public function addInputPasswordField (string $fieldName, string $fieldValue = '') {
224                 // Is the form opened?
225                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
226                         // Throw an exception
227                         throw new FormClosedException (array($this, $fieldName), self::EXCEPTION_CLOSED_FORM);
228                 }
229
230                 // Generate the content
231                 $inputContent = sprintf('<input type="password" class="form-control" id="%s_%s_field" name="%s" value="%s" />',
232                         $this->getFormId(),
233                         $fieldName,
234                         $fieldName,
235                         $fieldValue
236                 );
237
238                 // And add it
239                 $this->addContentToPreviousGroup($inputContent);
240         }
241
242         /**
243          * Add a hidden input tag to the form or throw an exception if it is not
244          * yet opened. The field's name will be set as id.
245          *
246          * @param       $fieldName              Input field name
247          * @param       $fieldValue             Input default value (default: empty)
248          * @return      void
249          * @throws      FormClosedException             If the form is not yet opened
250          */
251         public function addInputHiddenField (string $fieldName, string $fieldValue = '') {
252                 // Is the form opened?
253                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
254                         // Throw an exception
255                         throw new FormClosedException (array($this, $fieldName), self::EXCEPTION_CLOSED_FORM);
256                 }
257
258                 // Generate the content
259                 $inputContent = sprintf('<input type="hidden" name="%s" value="%s" />',
260                         $fieldName,
261                         $fieldValue
262                 );
263
264                 // And add it
265                 $this->addContentToPreviousGroup($inputContent);
266         }
267
268         /**
269          * Add a hidden input tag to the form with pre-loaded default value
270          *
271          * @param       $fieldName      Input field name
272          * @return      void
273          */
274         public function addInputHiddenFieldWithDefault (string $fieldName) {
275                 // Get the value from instance
276                 $fieldValue = $this->getValueField($fieldName);
277                 //* DEBUG: */ print __METHOD__.':'.$fieldName.'='.$fieldValue."<br />\n";
278
279                 // Add the text field
280                 $this->addInputHiddenField($fieldName, $fieldValue);
281         }
282
283         /**
284          * Add a hidden input tag to the form with configuration value
285          *
286          * @param       $fieldName      Input field name
287          * @param       $prefix         Prefix for configuration without trailing _
288          * @return      void
289          */
290         public function addInputHiddenConfiguredField (string $fieldName, string $prefix) {
291                 // Get the value from instance
292                 $fieldValue = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry("{$prefix}_{$fieldName}");
293                 //* DEBUG: */ print __METHOD__.':'.$fieldName.'='.$fieldValue."<br />\n";
294
295                 // Add the text field
296                 $this->addInputHiddenField($fieldName, $fieldValue);
297         }
298
299         /**
300          * Add a checkbox input tag to the form or throw an exception if it is not
301          * yet opened. The field's name will be set as id.
302          *
303          * @param       $fieldName              Input field name
304          * @param       $fieldChecked   Whether the field is checked (defaut: checked)
305          * @return      void
306          * @throws      FormClosedException             If the form is not yet opened
307          */
308         public function addInputCheckboxField (string $fieldName, bool $fieldChecked = true) {
309                 // Is the form opened?
310                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
311                         // Throw an exception
312                         throw new FormClosedException (array($this, $fieldName), self::EXCEPTION_CLOSED_FORM);
313                 }
314
315                 // Set whether the check box is checked...
316                 $checked = ($fieldChecked ? ' checked="checked"' : ' ');
317
318                 // Generate the content
319                 $inputContent = sprintf('<input type="checkbox" name="%s" class="checkbox" id="%s_%s_field" value="1"%s />',
320                         $fieldName,
321                         $this->getFormId(),
322                         $fieldName,
323                         $checked
324                 );
325
326                 // And add it
327                 $this->addContentToPreviousGroup($inputContent);
328         }
329
330         /**
331          * Add a reset input tag to the form or throw an exception if it is not
332          * yet opened. The field's name will be set as id.
333          *
334          * @param       $buttonText             Text displayed on the button
335          * @return      void
336          * @throws      FormClosedException             If the form is not yet opened
337          */
338         public function addInputResetButton (string $buttonText) {
339                 // Is the form opened?
340                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
341                         // Throw an exception
342                         throw new FormClosedException (array($this, 'reset'), self::EXCEPTION_CLOSED_FORM);
343                 }
344
345                 // Generate the content
346                 $inputContent = sprintf('<input type="reset" class="reset_button" id="%s_reset" value="%s" />',
347                         $this->getFormId(),
348                         $buttonText
349                 );
350
351                 // And add it
352                 $this->addContentToPreviousGroup($inputContent);
353         }
354
355         /**
356          * Add a reset input tag to the form or throw an exception if it is not
357          * yet opened. The field's name will be set as id.
358          *
359          * @param       $buttonText             Text displayed on the button
360          * @return      void
361          * @throws      FormClosedException             If the form is not yet opened
362          */
363         public function addInputSubmitButton (string $buttonText) {
364                 // Is the form opened?
365                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
366                         // Throw an exception
367                         throw new FormClosedException (array($this, 'submit'), self::EXCEPTION_CLOSED_FORM);
368                 }
369
370                 // Generate the content
371                 $inputContent = sprintf('<input type="submit" class="submit_button" id="%s_submit" name="%s_submit" value="%s" />',
372                         $this->getFormId(),
373                         $this->getFormId(),
374                         $buttonText
375                 );
376
377                 // And add it
378                 $this->addContentToPreviousGroup($inputContent);
379         }
380
381         /**
382          * Add a form group or close an already opened and open a new one
383          *
384          * @param       $groupId        Name of the group or last opened if empty
385          * @param       $groupText      Text including HTML to show above this group
386          * @return      void
387          * @throws      FormClosedException             If no form has been opened before
388          * @throws      InvalidArgumentException        If $groupId is not set
389          */
390         public function addFormGroup (string $groupId = '', string $groupText = '') {
391                 // Is a form opened?
392                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
393                         // Throw exception here
394                         throw new FormClosedException(array($this, $groupId), self::EXCEPTION_CLOSED_FORM);
395                 } elseif ((empty($groupId)) && ($this->ifGroupOpenedPreviously() === false)) {
396                         // Throw exception here
397                         throw new InvalidArgumentException('Parameter "groupId" is empty but group is not closed');
398                 } elseif (empty($groupId)) {
399                         // Close the last opened
400                         $groupId = $this->getPreviousGroupId();
401                 }
402
403                 // Same group to open?
404                 if (($this->ifGroupOpenedPreviously() === false) && ($groupId === $this->getPreviousGroupId())) {
405                         // Abort here silently
406                         return false;
407                 }
408
409                 // Initialize content with closing div by default
410                 $content = "    </div>\n</div><!-- Group - CLOSE //-->";
411
412                 // Is this group opened?
413                 if ($this->ifGroupOpenedPreviously() === false) {
414                         // Begin the div/span blocks
415                         $content = sprintf("<!-- Group %s - OPEN //-->
416 <div class=\"group_box\" id=\"%s_group_box\">
417         <span class=\"group_text\" id=\"%s_group_text\">
418                 %s
419         </span>
420         <div class=\"group_field\" id=\"%s_group_field\">",
421                                 $groupId,
422                                 $groupId,
423                                 $groupId,
424                                 $groupText,
425                                 $groupId
426                         );
427
428                         // Switch the state
429                         $this->openGroupByIdContent($groupId, $content, "div");
430                 } else {
431                         // Is a sub group opened?
432                         if ($this->ifSubGroupOpenedPreviously()) {
433                                 // Close it here
434                                 $this->addFormSubGroup();
435                         }
436
437                         // Get previous group id
438                         $prevGroupId = $this->getPreviousGroupId();
439
440                         // Switch the state
441                         $this->closePreviousGroupByContent($content);
442
443                         // All call it again if group name is not empty
444                         if ((!empty($groupId)) && ($groupId != $prevGroupId)) {
445                                 //* DEBUG: */ echo $groupId.'/'.$prevGroupId."<br />\n";
446                                 $this->addFormGroup($groupId, $groupText);
447                         }
448                 }
449         }
450
451         /**
452          * Add a form sub group or close an already opened and open a new one or
453          * throws an exception if no group has been opened before or if sub group
454          * name is empty.
455          *
456          * @param       $subGroupId             Name of the group or last opened if empty
457          * @param       $subGroupText   Text including HTML to show above this group
458          * @return      void
459          * @throws      FormFormClosedException         If no group has been opened before
460          * @throws      InvalidArgumentException                If $subGroupId is not set
461          */
462         public function addFormSubGroup (string $subGroupId = '', string $subGroupText = '') {
463                 // Is a group opened?
464                 if ($this->ifGroupOpenedPreviously() === false) {
465                         // Throw exception here
466                         throw new FormFormClosedException(array($this, $subGroupId), self::EXCEPTION_UNEXPECTED_CLOSED_GROUP);
467                 } elseif ((empty($subGroupId)) && ($this->ifSubGroupOpenedPreviously() === false)) {
468                         // Throw exception here
469                         throw new InvalidArgumentException('Parameter "subGroupId" is empty but sub-group is not closed');
470                 } elseif (empty($subGroupId)) {
471                         // Close the last opened
472                         $subGroupId = $this->getPreviousSubGroupId();
473                 }
474
475                 // Same sub group to open?
476                 if (($this->ifSubGroupOpenedPreviously() === false) && ($subGroupId == $this->getPreviousSubGroupId())) {
477                         // Abort here silently
478                         return false;
479                 }
480
481                 // Initialize content with closing div by default
482                 $content = "    </div>\n</div><!-- Sub group- CLOSE //-->";
483
484                 // Is this group opened?
485                 if ($this->ifSubGroupOpenedPreviously() === false) {
486                         // Begin the span block
487                         $content = sprintf("<!-- Sub group %s - OPEN //-->
488 <div class=\"subgroup_box\" id=\"%s_subgroup_box\">
489         <span class=\"subgroup_text\" id=\"%s_subgroup_text\">
490                 %s
491         </span>
492         <div class=\"subgroup_field\" id=\"%s_subgroup_field\">",
493                                 $subGroupId,
494                                 $subGroupId,
495                                 $subGroupId,
496                                 $subGroupText,
497                                 $subGroupId
498                         );
499
500                         // Switch the state and remeber the name
501                         $this->openSubGroupByIdContent($subGroupId, $content, "div");
502                 } else {
503                         // Get previous sub group id
504                         $prevSubGroupId = $this->getPreviousSubGroupId();
505
506                         // Switch the state
507                         $this->closePreviousSubGroupByContent($content);
508
509                         // All call it again if sub group name is not empty
510                         if ((!empty($subGroupId)) && ($subGroupId != $prevSubGroupId)) {
511                                 $this->addFormSubGroup($subGroupId, $subGroupText);
512                         }
513                 }
514         }
515
516         /**
517          * Adds text surrounded by a label tag for given form field
518          *
519          * @param       $fieldName              Field name
520          * @param       $fieldText              Text for the field
521          * @param       $fieldTitle             Optional title for label tag
522          * @return      void
523          * @throws      FormClosedException             If the form is not yet opened
524          */
525         public function addFieldLabel (string $fieldName, string $fieldText, string $fieldTitle = '') {
526                 // Is the form opened?
527                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
528                         // Throw an exception
529                         throw new FormClosedException (array($this, $fieldName), self::EXCEPTION_CLOSED_FORM);
530                 }
531
532                 // Default is no title attribute
533                 $titleAttribute = '';
534
535                 // Is title given?
536                 if (!empty($fieldTitle)) {
537                         // Create title attribute
538                         $titleAttribute = sprintf(' title="%s" data-toggle="tooltip"', $fieldTitle);
539                 }
540
541                 // Generate the content
542                 $inputContent = sprintf('<label class="col-form-label" for="%s_%s_field"%s>
543         %s
544 </label>',
545                         $this->getFormId(),
546                         $fieldName,
547                         $titleAttribute,
548                         $fieldText
549                 );
550
551                 // And add it
552                 $this->addContentToPreviousGroup($inputContent);
553         }
554
555         /**
556          * Add text (notes) surrounded by a div block. Still opened groups or sub
557          * groups will be automatically closed.
558          *
559          * @param       $noteId         Id for this note
560          * @param       $formNotes      The form notes we shell addd
561          * @return      void
562          * @throws      FormClosedException             If the form is not yet opened
563          */
564         public function addFormNote (string $noteId, string $formNotes) {
565                 // Is the form opened?
566                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
567                         // Throw an exception
568                         throw new FormClosedException (array($this, 'form_notes'), self::EXCEPTION_CLOSED_FORM);
569                 }
570
571                 // Generate the content
572                 $inputContent = sprintf("       <div id=\"form_note_%s\">
573                 %s
574         </div>",
575                         $noteId,
576                         $formNotes
577                 );
578
579                 // And add it
580                 $this->addContentToPreviousGroup($inputContent);
581         }
582
583         /**
584          * Adds a selection box as a sub group to the form. Do not box this into
585          * another sub group. Sub-sub groups are not (yet) supported.
586          *
587          * @param       $selectId               Id of the selection box
588          * @param       $firstEntry             Content to be added as first non-selectable entry
589          * @return      void
590          * @throws      FormClosedException             If the form is not yet opened
591          */
592         public function addInputSelectField (string $selectId, string $firstEntry) {
593                 // Is the form group opened?
594                 if (($this->formOpened === false) && ($this->formEnabled === true)) {
595                         // Throw an exception
596                         throw new FormClosedException (array($this, 'form_notes'), self::EXCEPTION_CLOSED_FORM);
597                 }
598
599                 // Shall we close or open the sub group?
600                 if (($this->ifSubGroupOpenedPreviously() === false) && ($this->getPreviousSubGroupId() !== $selectId)) {
601                         // Initialize first entry (which might be non-selectable if content is provided
602                         if (!empty($firstEntry)) {
603                                 // Add selection around it
604                                 $firstEntry = sprintf("<option value=\"invalid\" disabled=\"disabled\">%s</option>\n",
605                                         $firstEntry
606                                 );
607                         }
608
609                         // Construct the opening select tag
610                         $content = sprintf("<select class=\"select_box\" id=\"%s_%s\" name=\"%s\">\n%s",
611                                 $this->getFormName(),
612                                 $selectId,
613                                 $selectId,
614                                 $firstEntry
615                         );
616
617                         // Open the sub group
618                         $this->openSubGroupByIdContent($selectId, $content, "select");
619                 } elseif ($this->getPreviousSubGroupId() != $selectId) {
620                         // Something went wrong!
621                         $this->debugInstance(__METHOD__."(): Previous sub group id {$this->getPreviousSubGroupId()} does not match current id {$selectId}.");
622                 } else {
623                         // Close the sub group
624                         $this->closePreviousSubGroupByContent("</select>");
625                 }
626         }
627
628         /**
629          * Adds a non-selectable sub option to a previously added selection box.
630          * This method does *not* validate if there is already a sub option added
631          * with the same name. We need to finish this here!
632          *
633          * @param       $subName        Name of the sub action
634          * @param       $subValue       Value of the sub action
635          * @return      void
636          * @throws      HelperNoPreviousOpenedSubGroupException If no previously opened sub group was found
637          * @todo        Add checking if sub option is already added
638          */
639         public function addSelectSubOption (string $subName, string $subValue) {
640                 // Is there a sub group (shall be a selection box!)
641                 if ($this->ifSubGroupOpenedPreviously() === false) {
642                         // Then throw an exception here
643                         throw new HelperNoPreviousOpenedSubGroupException(array($this, $content), self::EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED);
644                 }
645
646                 // Render the content
647                 $content = sprintf("<option value=\"invalid\" class=\"suboption suboption_%s\" disabled=\"disabled\">%s</option>\n",
648                         $subName,
649                         $subValue
650                 );
651
652                 // Add the content to the previously opened sub group
653                 $this->addContentToPreviousGroup($content);
654         }
655
656         /**
657          * Adds a selectable option to a previously added selection box. This method
658          * does *not* validate if there is already a sub option added with the same
659          * name. We need to finish this here!
660          *
661          * @param       $optionName     Name of the sub action
662          * @param       $optionValue    Value of the sub action
663          * @return      void
664          * @throws      HelperNoPreviousOpenedSubGroupException If no previously opened sub group was found
665          * @todo        Add checking if sub option is already added
666          */
667         public function addSelectOption (string $optionName, string $optionValue) {
668                 // Is there a sub group (shall be a selection box!)
669                 if ($this->ifSubGroupOpenedPreviously() === false) {
670                         // Then throw an exception here
671                         throw new HelperNoPreviousOpenedSubGroupException(array($this, $content), self::EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED);
672                 }
673
674                 // Render the content
675                 $content = sprintf("<option value=\"%s\" class=\"option option_%s\">%s</option>\n",
676                         $optionName,
677                         $optionName,
678                         $optionValue
679                 );
680
681                 // Add the content to the previously opened sub group
682                 $this->addContentToPreviousGroup($content);
683         }
684
685         /**
686          * Adds a pre-configured CAPTCHA
687          *
688          * @return      void
689          */
690         public function addCaptcha () {
691                 // Init instance
692                 $extraInstance = NULL;
693
694                 try {
695                         // Get last executed pre filter
696                         $extraInstance = GenericRegistry::getRegistry()->getInstance('extra');
697                 } catch (NullPointerException $e) {
698                         // Instance in registry is not set (NULL)
699                         // @TODO We need to log this later
700                 }
701
702                 // Get a configured instance
703                 $captchaInstance = ObjectFactory::createObjectByConfiguredName($this->getFormName() . '_captcha_class', array($this, $extraInstance));
704
705                 // Initiate the CAPTCHA
706                 $captchaInstance->initiateCaptcha();
707
708                 // Render the CAPTCHA code
709                 $captchaInstance->renderCode();
710
711                 // Get the content and add it to the helper
712                 $this->addContentToPreviousGroup($captchaInstance->renderContent());
713         }
714
715         /**
716          * Enables/disables the form tag usage
717          *
718          * @param       $formEnabled    Whether form is enabled or disabled
719          * @return      void
720          */
721         public final function enableForm (bool $formEnabled = true) {
722                 $this->formEnabled = $formEnabled;
723         }
724
725         /**
726          * Setter for form name
727          *
728          * @param       $formName       Name of this form
729          * @return      void
730          */
731         public final function setFormName (string $formName) {
732                 $this->formName = $formName;
733         }
734
735         /**
736          * Getter for form name
737          *
738          * @return      $formName       Name of this form
739          */
740         public final function getFormName () {
741                 return $this->formName;
742         }
743
744         /**
745          * Setter for form id
746          *
747          * @param       $formId Id of this form
748          * @return      void
749          */
750         public final function setFormId (string $formId) {
751                 $this->formId = $formId;
752         }
753
754         /**
755          * Getter for form id
756          *
757          * @return      $formId Id of this form
758          */
759         public final function getFormId () {
760                 return $this->formId;
761         }
762
763         /**
764          * Checks whether the registration requires a valid email address
765          *
766          * @return      $required       Whether the email address is required
767          */
768         public function ifRegisterRequiresEmailVerification () {
769                 $required = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('register_requires_email') == 'Y');
770                 return $required;
771         }
772
773         /**
774          * Checks whether profile data shall be asked
775          *
776          * @return      $required       Whether profile data shall be asked
777          */
778         public function ifRegisterIncludesProfile () {
779                 $required = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('register_includes_profile') == 'Y');
780                 return $required;
781         }
782
783         /**
784          * Checks whether this form is secured by a CAPTCHA
785          *
786          * @return      $isSecured      Whether this form is secured by a CAPTCHA
787          */
788         public function ifFormSecuredWithCaptcha () {
789                 $isSecured = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry($this->getFormName() . '_captcha_secured') == 'Y');
790                 return $isSecured;
791         }
792
793         /**
794          * Checks whether personal data shall be asked
795          *
796          * @return      $required       Whether personal data shall be asked
797          */
798         public function ifRegisterIncludesPersonaData () {
799                 $required = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('register_personal_data') == 'Y');
800                 return $required;
801         }
802
803         /**
804          * Checks whether for birthday shall be asked
805          *
806          * @return      $required       Whether birthday shall be asked
807          */
808         public function ifProfileIncludesBirthDay () {
809                 $required = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('profile_includes_birthday') == 'Y');
810                 return $required;
811         }
812
813         /**
814          * Checks whether email addresses can only be once used
815          *
816          * @return      $isUnique
817          */
818         public function ifEmailMustBeUnique () {
819                 $isUnique = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('register_email_unique') == 'Y');
820                 return $isUnique;
821         }
822
823         /**
824          * Checks whether the specified chat protocol is enabled in this form
825          *
826          * @return      $required       Whether the specified chat protocol is enabled
827          */
828         public function ifChatEnabled (string $chatProtocol) {
829                 $required = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('chat_enabled_' . $chatProtocol) == 'Y');
830                 return $required;
831         }
832
833         /**
834          * Checks whether login is enabled or disabled
835          *
836          * @return      $isEnabled      Whether the login is enabled or disabled
837          */
838         public function ifLoginIsEnabled () {
839                 $isEnabled = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('login_enabled') == 'Y');
840                 return $isEnabled;
841         }
842
843         /**
844          * Checks whether login shall be done by username
845          *
846          * @return      $isEnabled      Whether the login shall be done by username
847          */
848         public function ifLoginWithUsername () {
849                 $isEnabled = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('login_type') == "username");
850                 return $isEnabled;
851         }
852
853         /**
854          * Checks whether login shall be done by email
855          *
856          * @return      $isEnabled      Whether the login shall be done by email
857          */
858         public function ifLoginWithEmail () {
859                 $isEnabled = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('login_type') == "email");
860                 return $isEnabled;
861         }
862
863         /**
864          * Checks whether guest login is allowed
865          *
866          * @return      $isAllowed      Whether guest login is allowed
867          */
868         public function ifGuestLoginAllowed () {
869                 $isAllowed = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('guest_login_allowed') == 'Y');
870                 return $isAllowed;
871         }
872
873         /**
874          * Checks whether the email address change must be confirmed
875          *
876          * @return      $requireConfirm         Whether email change must be confirmed
877          */
878         public function ifEmailChangeRequireConfirmation () {
879                 $requireConfirm = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('email_change_confirmation') == 'Y');
880                 return $requireConfirm;
881         }
882
883         /**
884          * Checks whether the rules has been updated
885          *
886          * @return      $rulesUpdated   Whether rules has been updated
887          * @todo        Implement check if rules have been changed
888          */
889         public function ifRulesHaveChanged () {
890                 return false;
891         }
892
893         /**
894          * Checks whether email change is allowed
895          *
896          * @return      $emailChange    Whether changing email address is allowed
897          */
898         public function ifEmailChangeAllowed () {
899                 $emailChange = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('email_change_allowed') == 'Y');
900                 return $emailChange;
901         }
902
903         /**
904          * Checks whether the user account is unconfirmed
905          *
906          * @return      $isUnconfirmed  Whether the user account is unconfirmed
907          */
908         public function ifUserAccountUnconfirmed () {
909                 $isUnconfirmed = ($this->getValueField(UserDatabaseFrontend::DB_COLUMN_USER_STATUS) === FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('user_status_unconfirmed'));
910                 return $isUnconfirmed;
911         }
912
913         /**
914          * Checks whether the user account is locked
915          *
916          * @return      $isUnconfirmed  Whether the user account is locked
917          */
918         public function ifUserAccountLocked () {
919                 $isUnconfirmed = ($this->getValueField(UserDatabaseFrontend::DB_COLUMN_USER_STATUS) === FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('user_status_locked'));
920                 return $isUnconfirmed;
921         }
922
923         /**
924          * Checks whether the user account is a guest
925          *
926          * @return      $isUnconfirmed  Whether the user account is a guest
927          */
928         public function ifUserAccountGuest () {
929                 $isUnconfirmed = ($this->getValueField(UserDatabaseFrontend::DB_COLUMN_USER_STATUS) === FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('user_status_guest'));
930                 return $isUnconfirmed;
931         }
932
933         /**
934          * Checks whether the refill page is active which should be not the default
935          * on non-web applications.
936          *
937          * @return      $refillActive   Whether the refill page is active
938          */
939         public function ifRefillPageActive () {
940                 $refillActive = (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('refill_page_active') == 'Y');
941                 return $refillActive;
942         }
943
944         /**
945          * Flushs the content out (not yet secured against open forms, etc.!) or
946          * close the form automatically
947          *
948          * @return      void
949          * @throws      FormOpenedException             If the form is still open
950          */
951         public function flushContent () {
952                 // Is the form still open?
953                 if (($this->formOpened === true) && ($this->formEnabled === true)) {
954                         // Close the form automatically
955                         $this->addFormTag();
956                 } elseif ($this->formEnabled === false) {
957                         if ($this->ifSubGroupOpenedPreviously()) {
958                                 // Close sub group
959                                 $this->addFormSubGroup();
960                         } elseif ($this->ifGroupOpenedPreviously()) {
961                                 // Close group
962                                 $this->addFormGroup();
963                         }
964                 }
965
966                 // Send content to template engine
967                 //* DEBUG: */ print __METHOD__.": form=".$this->getFormName().", size=".strlen($this->renderContent())."<br />\n";
968                 $this->getTemplateInstance()->assignVariable($this->getFormName(), $this->renderContent());
969         }
970
971 }