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