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