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