Source for file options.php

Documentation is available at options.php

  1. <?php
  2.  
  3. /**
  4.  * options.php
  5.  *
  6.  * Functions needed to display the options pages.
  7.  *
  8.  * @copyright 1999-2020 The SquirrelMail Project Team
  9.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  10.  * @version $Id: options.php 14845 2020-01-07 08:09:34Z pdontthink $
  11.  * @package squirrelmail
  12.  * @subpackage prefs
  13.  */
  14.  
  15. /**
  16.  * SquirrelOption: An option for SquirrelMail.
  17.  *
  18.  * @package squirrelmail
  19.  * @subpackage prefs
  20.  */
  21. class SquirrelOption {
  22.     /**
  23.      * The original option configuration array
  24.      * @var array 
  25.      */
  26.     var $raw_option_array;
  27.     /**
  28.      * The name of this setting
  29.      * @var string 
  30.      */
  31.     var $name;
  32.     /**
  33.      * The text that prefaces setting on the preferences page
  34.      * @var string 
  35.      */
  36.     var $caption;
  37.     /**
  38.      * Whether or not the caption text is allowed to wrap
  39.      * @var boolean 
  40.      */
  41.     var $caption_wrap;
  42.     /**
  43.      * The type of INPUT element
  44.      *
  45.      * See SMOPT_TYPE_* defines
  46.      * @var integer 
  47.      */
  48.     var $type;
  49.     /**
  50.      * Indicates if a link should be shown to refresh part
  51.      * or all of the window
  52.      *
  53.      * See SMOPT_REFRESH_* defines
  54.      * @var integer 
  55.      */
  56.     var $refresh_level;
  57.     /**
  58.      * Specifies the size of certain input items
  59.      *
  60.      * See SMOPT_SIZE_* defines
  61.      * @var integer 
  62.      */
  63.     var $size;
  64.     /**
  65.      * Text that follows a text input or
  66.      * select list input on the preferences page
  67.      *
  68.      * useful for indicating units, meanings of special values, etc.
  69.      * @var string 
  70.      */
  71.     var $trailing_text;
  72.     /**
  73.      * Indicates that the widget's "trailing text"
  74.      * should be displayed in a smaller sized font
  75.      *
  76.      * @var boolean 
  77.      */
  78.     var $trailing_text_small;
  79.     /**
  80.      * Indicates that the widget's "trailing text"
  81.      * contains HTML and should not thus be
  82.      * sanitized (encoded)
  83.      *
  84.      * @var boolean 
  85.      */
  86.     /**
  87.      * Text that overrides the "Yes" label for boolean
  88.      * radio option widgets
  89.      *
  90.      * @var string 
  91.      */
  92.     var $yes_text;
  93.     /**
  94.      * Text that overrides the "No" label for boolean
  95.      * radio option widgets
  96.      *
  97.      * @var string 
  98.      */
  99.     var $no_text;
  100.     /**
  101.      * Some widgets support more than one layout type
  102.      *
  103.      * @var int 
  104.      */
  105.     var $layout_type;
  106.     /**
  107.      * Indicates if the Add widget should be included
  108.      * with edit lists.
  109.      *
  110.      * @var boolean 
  111.      */
  112.     var $use_add_widget;
  113.     /**
  114.      * Indicates if the Delete widget should be included
  115.      * with edit lists.
  116.      *
  117.      * @var boolean 
  118.      */
  119.     var $use_delete_widget;
  120.     /**
  121.      * associative array, treated the same as $possible_values
  122.      * (see its documentation below), but usually expected to
  123.      * have its first value contain a list of IMAP folders, an
  124.      * array itself in the format as passed back by
  125.      * sqimap_mailbox_list(). Used to display folder selector
  126.      * for possible values of an associative edit list option
  127.      * widget
  128.      *
  129.      * @since 1.5.2
  130.      * @var array 
  131.      */
  132.     var $poss_value_folders;
  133.     /**
  134.      * text displayed to the user
  135.      *
  136.      * Used with SMOPT_TYPE_COMMENT options
  137.      * @var string 
  138.      */
  139.     var $comment;
  140.     /**
  141.      * additional javascript or other widget attributes added to the
  142.      * user input; must be an array where keys are attribute names
  143.      * ("onclick", etc) and values are the attribute values.
  144.      * @var array 
  145.      */
  146.     var $aExtraAttribs;
  147.     /**
  148.      * script (usually Javascript) that will be placed after (outside of)
  149.      * the INPUT tag
  150.      * @var string 
  151.      */
  152.     var $post_script;
  153.  
  154.     /**
  155.      * The name of the Save Function for this option.
  156.      * @var string 
  157.      */
  158.     var $save_function;
  159.  
  160.     /* The various 'values' for this options. */
  161.     /**
  162.      * default/preselected value for this option
  163.      * @var mixed 
  164.      */
  165.     var $value;
  166.     /**
  167.      * new option value
  168.      * @var mixed 
  169.      */
  170.     var $new_value;
  171.     /**
  172.      * associative array, where each key is an actual input value
  173.      * and the corresponding value is what is displayed to the user
  174.      * for that list item in the drop-down list
  175.      * @var array 
  176.      */
  177.     var $possible_values;
  178.     /**
  179.      * disables html sanitizing.
  180.      *
  181.      * WARNING - don't use it, if user input is possible in option
  182.      * or use own sanitizing functions. Currently only works for SMOPT_TYPE_STRLIST.
  183.      * @var bool 
  184.      */
  185.     var $htmlencoded=false;
  186.     /**
  187.      * Controls folder list limits in SMOPT_TYPE_FLDRLIST and
  188.      * SMOPT_TYPE_FLDRLIST_MULTI widgets as well as the optional
  189.      * embedded folder lists provided for inputting values for
  190.      * the SMOPT_TYPE_EDIT_LIST and SMOPT_TYPE_EDIT_LIST_ASSOCIATIVE
  191.      * :idgets.
  192.      * See $flag argument in sqimap_mailbox_option_list() function.
  193.      * @var string 
  194.      * @since 1.5.1
  195.      */
  196.     var $folder_filter='noselect';
  197.  
  198.     /**
  199.      * Constructor (PHP5 style, required in some future version of PHP)
  200.      * @param array $raw_option_array 
  201.      * @param string $name 
  202.      * @param string $caption 
  203.      * @param integer $type 
  204.      * @param integer $refresh_level 
  205.      * @param mixed $initial_value 
  206.      * @param array $possible_values 
  207.      * @param bool $htmlencoded 
  208.      */
  209.     function __construct
  210.     ($raw_option_array$name$caption$type$refresh_level$initial_value ''$possible_values ''$htmlencoded false{
  211.         /* Set the basic stuff. */
  212.         $this->raw_option_array = $raw_option_array;
  213.         $this->name = $name;
  214.         $this->caption = $caption;
  215.         $this->caption_wrap = TRUE;
  216.         $this->type = $type;
  217.         $this->refresh_level = $refresh_level;
  218.         $this->possible_values = $possible_values;
  219.         $this->htmlencoded = $htmlencoded;
  220.         $this->size = SMOPT_SIZE_NORMAL;
  221.         $this->trailing_text = '';
  222.         $this->trailing_text_small = FALSE;
  223.         $this->trailing_text_is_html = FALSE;
  224.         $this->yes_text = '';
  225.         $this->no_text = '';
  226.         $this->comment = '';
  227.         $this->layout_type = 0;
  228.         $this->use_add_widget = TRUE;
  229.         $this->use_delete_widget = TRUE;
  230.         $this->poss_value_folders = '';
  231.         $this->aExtraAttribs = array();
  232.         $this->post_script = '';
  233.  
  234.         //Check for a current value.  
  235.         if (isset($GLOBALS[$name])) {
  236.             $this->value = $GLOBALS[$name];
  237.         // TODO: This code should be something more like the following, but who knows what would break if it was changed at this point
  238.         // } else if (initial_value !== '') {
  239.         else if (!empty($initial_value)) {
  240.             $this->value = $initial_value;
  241.         else {
  242.             $this->value = '';
  243.         }
  244.  
  245.         /* Check for a new value. */
  246.         if !sqgetGlobalVar("new_$name"$this->new_valueSQ_POST ) ) {
  247.             $this->new_value = NULL;
  248.         }
  249.  
  250.         /* Set the default save function. */
  251.         if ($type != SMOPT_TYPE_HIDDEN
  252.          && $type != SMOPT_TYPE_INFO
  253.          && $type != SMOPT_TYPE_COMMENT{
  254.             $this->save_function = SMOPT_SAVE_DEFAULT;
  255.         else {
  256.             $this->save_function = SMOPT_SAVE_NOOP;
  257.         }
  258.     }
  259.  
  260.     /**
  261.      * Constructor (PHP4 style, kept for compatibility reasons)
  262.      * @param array $raw_option_array 
  263.      * @param string $name 
  264.      * @param string $caption 
  265.      * @param integer $type 
  266.      * @param integer $refresh_level 
  267.      * @param mixed $initial_value 
  268.      * @param array $possible_values 
  269.      * @param bool $htmlencoded 
  270.      */
  271.     function SquirrelOption
  272.     ($raw_option_array$name$caption$type$refresh_level$initial_value ''$possible_values ''$htmlencoded false{
  273.         self::__construct($raw_option_array$name$caption$type$refresh_level$initial_value$possible_values$htmlencoded);
  274.     }
  275.  
  276.     /** Convenience function that identifies which types of
  277.         widgets are stored as (serialized) array values. */
  278.     function is_multiple_valued({
  279.         return ($this->type == SMOPT_TYPE_FLDRLIST_MULTI
  280.              || $this->type == SMOPT_TYPE_STRLIST_MULTI
  281.              || $this->type == SMOPT_TYPE_EDIT_LIST
  282.              || $this->type == SMOPT_TYPE_EDIT_LIST_ASSOCIATIVE);
  283.     }
  284.  
  285.     /**
  286.      * Set the value for this option.
  287.      * @param mixed $value 
  288.      */
  289.     function setValue($value{
  290.         $this->value = $value;
  291.     }
  292.  
  293.     /**
  294.      * Set the new value for this option.
  295.      * @param mixed $new_value 
  296.      */
  297.     function setNewValue($new_value{
  298.         $this->new_value = $new_value;
  299.     }
  300.  
  301.     /**
  302.      * Set whether the caption is allowed to wrap for this option.
  303.      * @param boolean $caption_wrap 
  304.      */
  305.     function setCaptionWrap($caption_wrap{
  306.         $this->caption_wrap = $caption_wrap;
  307.     }
  308.  
  309.     /**
  310.      * Set the size for this option.
  311.      * @param integer $size 
  312.      */
  313.     function setSize($size{
  314.         $this->size = $size;
  315.     }
  316.  
  317.     /**
  318.      * Set the trailing_text for this option.
  319.      * @param string $trailing_text 
  320.      */
  321.     function setTrailingText($trailing_text{
  322.         $this->trailing_text = $trailing_text;
  323.     }
  324.  
  325.     /**
  326.      * Set the trailing_text_small for this option.
  327.      * @param boolean $trailing_text_small 
  328.      */
  329.     function setTrailingTextSmall($trailing_text_small{
  330.         $this->trailing_text_small = $trailing_text_small;
  331.     }
  332.  
  333.     /**
  334.      * Set the trailing_text_is_html for this option.
  335.      * @param boolean $trailing_text_is_html 
  336.      */
  337.     function setTrailingTextIsHtml($trailing_text_is_html{
  338.         $this->trailing_text_is_html = $trailing_text_is_html;
  339.     }
  340.  
  341.     /**
  342.      * Set the yes_text for this option.
  343.      * @param string $yes_text 
  344.      */
  345.     function setYesText($yes_text{
  346.         $this->yes_text = $yes_text;
  347.     }
  348.  
  349.     /**
  350.      * Set the no_text for this option.
  351.      * @param string $no_text 
  352.      */
  353.     function setNoText($no_text{
  354.         $this->no_text = $no_text;
  355.     }
  356.  
  357.     /* Set the "use add widget" value for this option. */
  358.     function setUseAddWidget($use_add_widget{
  359.         $this->use_add_widget = $use_add_widget;
  360.     }
  361.  
  362.     /* Set the "use delete widget" value for this option. */
  363.     function setUseDeleteWidget($use_delete_widget{
  364.         $this->use_delete_widget = $use_delete_widget;
  365.     }
  366.  
  367.     /* Set the "poss value folders" value for this option.
  368.        See the associative edit list widget, which uses this
  369.        to offer folder list selection for the values */
  370.     function setPossValueFolders($poss_value_folders{
  371.         $this->poss_value_folders = $poss_value_folders;
  372.     }
  373.  
  374.     /**
  375.      * Set the layout type for this option.
  376.      * @param int $layout_type 
  377.      */
  378.     function setLayoutType($layout_type{
  379.         $this->layout_type = $layout_type;
  380.     }
  381.  
  382.     /**
  383.      * Set the comment for this option.
  384.      * @param string $comment 
  385.      */
  386.     function setComment($comment{
  387.         $this->comment = $comment;
  388.     }
  389.  
  390.     /**
  391.      * Set the extra attributes for this option.
  392.      * @param array $aExtraAttribs 
  393.      */
  394.     function setExtraAttributes($aExtraAttribs{
  395.         $this->aExtraAttribs = $aExtraAttribs;
  396.     }
  397.  
  398.     /**
  399.      * Set the "post script" for this option.
  400.      * @param string $post_script 
  401.      */
  402.     function setPostScript($post_script{
  403.         $this->post_script = $post_script;
  404.     }
  405.  
  406.     /**
  407.      * Set the save function for this option.
  408.      * @param string $save_function 
  409.      */
  410.     function setSaveFunction($save_function{
  411.         $this->save_function = $save_function;
  412.     }
  413.  
  414.     /**
  415.      * Set the folder_filter for this option.
  416.      * @param string $folder_filter 
  417.      * @since 1.5.1
  418.      */
  419.     function setFolderFilter($folder_filter{
  420.         $this->folder_filter = $folder_filter;
  421.     }
  422.  
  423.     /**
  424.      * Creates fields on option pages according to option type
  425.      *
  426.      * This is the function that calls all other createWidget* functions.
  427.      *
  428.      * @return string The formated option field
  429.      *
  430.      */
  431.     function createWidget({
  432.         global $color;
  433.  
  434.         // Use new value if available
  435.         if (!is_null($this->new_value)) {
  436.             $tempValue $this->value;
  437.             $this->value = $this->new_value;
  438.         }
  439.  
  440.         /* Get the widget for this option type. */
  441.         switch ($this->type{
  442.             case SMOPT_TYPE_PASSWORD:
  443.                 $result $this->createWidget_String(TRUE);
  444.                 break;
  445.             case SMOPT_TYPE_STRING:
  446.                 $result $this->createWidget_String();
  447.                 break;
  448.             case SMOPT_TYPE_STRLIST:
  449.                 $result $this->createWidget_StrList();
  450.                 break;
  451.             case SMOPT_TYPE_TEXTAREA:
  452.                 $result $this->createWidget_TextArea();
  453.                 break;
  454.             case SMOPT_TYPE_INTEGER:
  455.                 $result $this->createWidget_Integer();
  456.                 break;
  457.             case SMOPT_TYPE_FLOAT:
  458.                 $result $this->createWidget_Float();
  459.                 break;
  460.             case SMOPT_TYPE_BOOLEAN:
  461.                 $result $this->createWidget_Boolean();
  462.                 break;
  463.             case SMOPT_TYPE_BOOLEAN_CHECKBOX:
  464.                 $result $this->createWidget_Boolean(TRUE);
  465.                 break;
  466.             case SMOPT_TYPE_BOOLEAN_RADIO:
  467.                 $result $this->createWidget_Boolean(FALSE);
  468.                 break;
  469.             case SMOPT_TYPE_HIDDEN:
  470.                 $result $this->createWidget_Hidden();
  471.                 break;
  472.             case SMOPT_TYPE_COMMENT:
  473.                 $result $this->createWidget_Comment();
  474.                 break;
  475.             case SMOPT_TYPE_FLDRLIST:
  476.                 $result $this->createWidget_FolderList();
  477.                 break;
  478.             case SMOPT_TYPE_FLDRLIST_MULTI:
  479.                 $result $this->createWidget_FolderList(TRUE);
  480.                 break;
  481.             case SMOPT_TYPE_EDIT_LIST:
  482.                 $result $this->createWidget_EditList();
  483.                 break;
  484.             case SMOPT_TYPE_EDIT_LIST_ASSOCIATIVE:
  485.                 $result $this->createWidget_EditListAssociative();
  486.                 break;
  487.             case SMOPT_TYPE_STRLIST_MULTI:
  488.                 $result $this->createWidget_StrList(TRUE);
  489.                 break;
  490.             case SMOPT_TYPE_STRLIST_RADIO:
  491.                 $result $this->createWidget_StrList(FALSETRUE);
  492.                 break;
  493.             case SMOPT_TYPE_SUBMIT:
  494.                 $result $this->createWidget_Submit();
  495.                 break;
  496.             case SMOPT_TYPE_INFO:
  497.                 $result $this->createWidget_Info();
  498.                 break;
  499.             default:
  500.                 error_box 
  501.                     sprintf(_("Option Type '%s' Not Found")$this->type)
  502.                     );
  503.         }
  504.  
  505.         /* Add the "post script" for this option. */
  506.         $result .= $this->post_script;
  507.  
  508.         // put correct value back if need be
  509.         if (!is_null($this->new_value)) {
  510.             $this->value = $tempValue;
  511.         }
  512.  
  513.         /* Now, return the created widget. */
  514.         return $result;
  515.     }
  516.  
  517.     /**
  518.      * Creates info block
  519.      * @return string html formated output
  520.      */
  521.     function createWidget_Info({
  522.         // return sq_htmlspecialchars($this->value);
  523.         // like COMMENT, allow HTML here
  524.         return $this->value;
  525.     }
  526.  
  527.     /**
  528.      * Create string field
  529.      *
  530.      * @param boolean $password When TRUE, the text in the input
  531.      *                           widget will be obscured (OPTIONAL;
  532.      *                           default = FALSE).
  533.      *
  534.      * @return string html formated option field
  535.      *
  536.      */
  537.     function createWidget_String($password=FALSE{
  538.         switch ($this->size{
  539.             case SMOPT_SIZE_TINY:
  540.                 $width 5;
  541.                 break;
  542.             case SMOPT_SIZE_SMALL:
  543.                 $width 12;
  544.                 break;
  545.             case SMOPT_SIZE_LARGE:
  546.                 $width 38;
  547.                 break;
  548.             case SMOPT_SIZE_HUGE:
  549.                 $width 50;
  550.                 break;
  551.             case SMOPT_SIZE_NORMAL:
  552.             default:
  553.                 $width 25;
  554.         }
  555.  
  556. //TODO: might be better to have a separate template file for all widgets, because then the layout of the widget and the "trailing text" can be customized - they are still hard coded here (also, we have <small> tags here; don't want HTML here!)
  557.         if ($password)
  558.             return addPwField('new_' $this->name$this->value$width0$this->aExtraAttribs' ' ($this->trailing_text_small ? '<small>' ''($this->trailing_text_is_html ? $this->trailing_text : sm_encode_html_special_chars($this->trailing_text)) ($this->trailing_text_small ? '</small>' '');
  559.         else
  560.             return addInput('new_' $this->name$this->value$width0$this->aExtraAttribs' ' ($this->trailing_text_small ? '<small>' ''($this->trailing_text_is_html ? $this->trailing_text : sm_encode_html_special_chars($this->trailing_text)) ($this->trailing_text_small ? '</small>' '');
  561.     }
  562.  
  563.     /**
  564.      * Create selection box or radio button group
  565.      *
  566.      * When $this->htmlencoded is TRUE, the keys and values in
  567.      * $this->possible_values are assumed to be display-safe.
  568.      * Use with care!
  569.      *
  570.      * Note that when building radio buttons instead of a select
  571.      * widget, if the "size" attribute is SMOPT_SIZE_TINY, the
  572.      * radio buttons will be output one after another without
  573.      * linebreaks between them.  Otherwise, each radio button
  574.      * goes on a line of its own.
  575.      *
  576.      * @param boolean $multiple_select When TRUE, the select widget
  577.      *                                  will allow multiple selections
  578.      *                                  (OPTIONAL; default is FALSE
  579.      *                                  (single select list))
  580.      * @param boolean $radio_buttons   When TRUE, the widget will
  581.      *                                  instead be built as a group
  582.      *                                  of radio buttons (and
  583.      *                                  $multiple_select will be
  584.      *                                  forced to FALSE) (OPTIONAL;
  585.      *                                  default is FALSE (select widget))
  586.      *
  587.      * @return string html formated selection box or radio buttons
  588.      *
  589.      */
  590.     function createWidget_StrList($multiple_select=FALSE$radio_buttons=FALSE{
  591. //FIXME: Currently, $this->htmlencoded is ignored here -- was removed when changing to template-based output; a fix is available as part of proposed centralized sanitizing patch
  592.  
  593.         // radio buttons instead of select widget?
  594.         //
  595.         if ($radio_buttons{
  596.  
  597.             global $br$nbsp;
  598.             $result '';
  599.             foreach ($this->possible_values as $real_value => $disp_value{
  600.                 $result .= addRadioBox('new_' $this->name($this->value == $real_value)$real_valuearray_merge(array('id' => 'new_' $this->name . '_' $real_value)$this->aExtraAttribs)) $nbsp create_label($disp_value'new_' $this->name . '_' $real_value);
  601.                 if ($this->size != SMOPT_SIZE_TINY)
  602.                     $result .= $br;
  603.             }
  604.  
  605.             return $result;
  606.         }
  607.  
  608.  
  609.         // everything below applies to select widgets
  610.         //
  611.         switch ($this->size{
  612. //FIXME: not sure about these sizes... seems like we could add another on the "large" side...
  613.             case SMOPT_SIZE_TINY:
  614.                 $height 3;
  615.                 break;
  616.             case SMOPT_SIZE_SMALL:
  617.                 $height 8;
  618.                 break;
  619.             case SMOPT_SIZE_LARGE:
  620.                 $height 15;
  621.                 break;
  622.             case SMOPT_SIZE_HUGE:
  623.                 $height 25;
  624.                 break;
  625.             case SMOPT_SIZE_NORMAL:
  626.             default:
  627.                 $height 5;
  628.         }
  629.  
  630.         return addSelect('new_' $this->name$this->possible_values$this->valueTRUE$this->aExtraAttribs$multiple_select$height!$this->htmlencoded($this->trailing_text_small ? '<small>' ''($this->trailing_text_is_html ? $this->trailing_text : sm_encode_html_special_chars($this->trailing_text)) ($this->trailing_text_small ? '</small>' '');
  631.  
  632.     }
  633.  
  634.     /**
  635.      * Create folder selection box
  636.      *
  637.      * @param boolean $multiple_select When TRUE, the select widget
  638.      *                                  will allow multiple selections
  639.      *                                  (OPTIONAL; default is FALSE
  640.      *                                  (single select list))
  641.      *
  642.      * @return string html formated selection box
  643.      *
  644.      */
  645.     function createWidget_FolderList($multiple_select=FALSE{
  646.  
  647.         switch ($this->size{
  648. //FIXME: not sure about these sizes... seems like we could add another on the "large" side...
  649.             case SMOPT_SIZE_TINY:
  650.                 $height 3;
  651.                 break;
  652.             case SMOPT_SIZE_SMALL:
  653.                 $height 8;
  654.                 break;
  655.             case SMOPT_SIZE_LARGE:
  656.                 $height 15;
  657.                 break;
  658.             case SMOPT_SIZE_HUGE:
  659.                 $height 25;
  660.                 break;
  661.             case SMOPT_SIZE_NORMAL:
  662.             default:
  663.                 $height 5;
  664.         }
  665.  
  666.         // possible values might include a nested array of 
  667.         // possible values (list of folders)
  668.         //
  669.         $option_list array();
  670.         foreach ($this->possible_values as $value => $text{
  671.  
  672.             // list of folders (boxes array)
  673.             //
  674.             if (is_array($text)) {
  675.               $option_list array_merge($option_listsqimap_mailbox_option_array(00$text$this->folder_filter));
  676.  
  677.             // just one option here
  678.             //
  679.             else {
  680.               $option_list array_merge($option_listarray($value => $text));
  681.             }
  682.  
  683.         }
  684.         if (empty($option_list))
  685.             $option_list array('ignore' => _("unavailable"));
  686.  
  687.  
  688.         return addSelect('new_' $this->name$option_list$this->valueTRUE$this->aExtraAttribs$multiple_select$height($this->trailing_text_small ? '<small>' ''($this->trailing_text_is_html ? $this->trailing_text : sm_encode_html_special_chars($this->trailing_text)) ($this->trailing_text_small ? '</small>' '');
  689.  
  690.     }
  691.  
  692.     /**
  693.      * Creates textarea
  694.      * @return string html formated textarea field
  695.      */
  696.     function createWidget_TextArea({
  697.         switch ($this->size{
  698.             case SMOPT_SIZE_TINY:  $rows 3$cols =  10break;
  699.             case SMOPT_SIZE_SMALL$rows 4$cols =  30break;
  700.             case SMOPT_SIZE_LARGE$rows 10$cols =  60break;
  701.             case SMOPT_SIZE_HUGE:  $rows 20$cols =  80break;
  702.             case SMOPT_SIZE_NORMAL:
  703.             default$rows 5$cols =  50;
  704.         }
  705.         return addTextArea('new_' $this->name$this->value$cols$rows$this->aExtraAttribs);
  706.     }
  707.  
  708.     /**
  709.      * Creates field for integer
  710.      *
  711.      * Difference from createWidget_String is visible only when javascript is enabled
  712.      * @return string html formated option field
  713.      */
  714.     function createWidget_Integer({
  715.  
  716.         // add onChange javascript handler to a regular string widget
  717.         // which will strip out all non-numeric chars
  718.         if (checkForJavascript())
  719.            $this->aExtraAttribs['onchange''origVal=this.value; newVal=\'\'; '
  720.                     . 'for (i=0;i<origVal.length;i++) { if (origVal.charAt(i)>=\'0\' '
  721.                     . '&& origVal.charAt(i)<=\'9\') newVal += origVal.charAt(i); } '
  722.                     . 'this.value=newVal;';
  723.  
  724.         return $this->createWidget_String();
  725.     }
  726.  
  727.     /**
  728.      * Creates field for floating number
  729.      * Difference from createWidget_String is visible only when javascript is enabled
  730.      * @return string html formated option field
  731.      */
  732.     function createWidget_Float({
  733.  
  734.         // add onChange javascript handler to a regular string widget
  735.         // which will strip out all non-numeric (period also OK) chars
  736.         if (checkForJavascript())
  737.            $this->aExtraAttribs['onchange''origVal=this.value; newVal=\'\'; '
  738.                     . 'for (i=0;i<origVal.length;i++) { if ((origVal.charAt(i)>=\'0\' '
  739.                     . '&& origVal.charAt(i)<=\'9\') || origVal.charAt(i)==\'.\') '
  740.                     . 'newVal += origVal.charAt(i); } this.value=newVal;';
  741.  
  742.         return $this->createWidget_String();
  743.     }
  744.  
  745.     /**
  746.      * Create boolean widget
  747.      *
  748.      * When creating Yes/No radio buttons, the "yes_text"
  749.      * and "no_text" option attributes are used to override
  750.      * the typical "Yes" and "No" text.
  751.      *
  752.      * @param boolean $checkbox When TRUE, the widget will be
  753.      *                           constructed as a checkbox,
  754.      *                           otherwise it will be a set of
  755.      *                           Yes/No radio buttons (OPTIONAL;
  756.      *                           default is TRUE (checkbox)).
  757.      *
  758.      * @return string html formated boolean widget
  759.      *
  760.      */
  761.     function createWidget_Boolean($checkbox=TRUE{
  762.  
  763.         global $oTemplate$nbsp;
  764.  
  765.  
  766.         // checkbox...
  767.         //
  768.         if ($checkbox{
  769. //TODO: Why isn't trailing_text being sanitized with sm_encode_special_chars()???  If this is a bug, add that, then add the option to display unsanitized if $this->trailing_text_is_html is enabled
  770.             $result addCheckbox('new_' $this->name($this->value != SMPREF_NO)SMPREF_YESarray_merge(array('id' => 'new_' $this->name)$this->aExtraAttribs)) $nbsp create_label(($this->trailing_text_small ? '<small>' ''$this->trailing_text . ($this->trailing_text_small ? '</small>' '')'new_' $this->name);
  771.         }
  772.  
  773.         // radio buttons...
  774.         //
  775.         else {
  776.  
  777.             /* Build the yes choice. */
  778.             $yes_option addRadioBox('new_' $this->name($this->value != SMPREF_NO)SMPREF_YESarray_merge(array('id' => 'new_' $this->name . '_yes')$this->aExtraAttribs)) $nbsp create_label((!empty($this->yes_text$this->yes_text : _("Yes"))'new_' $this->name . '_yes');
  779.  
  780.             /* Build the no choice. */
  781.             $no_option addRadioBox('new_' $this->name($this->value == SMPREF_NO)SMPREF_NOarray_merge(array('id' => 'new_' $this->name . '_no')$this->aExtraAttribs)) $nbsp create_label((!empty($this->no_text$this->no_text : _("No"))'new_' $this->name . '_no');
  782.  
  783.             /* Build the combined "boolean widget". */
  784.             $result "$yes_option$nbsp$nbsp$nbsp$nbsp$no_option ($this->trailing_text_small ? '<small>' ''($this->trailing_text_is_html ? $this->trailing_text : sm_encode_html_special_chars($this->trailing_text)) ($this->trailing_text_small ? '</small>' '');
  785.  
  786.         }
  787.  
  788.         return ($result);
  789.     }
  790.  
  791.     /**
  792.      * Creates hidden field
  793.      * @return string html formated hidden input field
  794.      */
  795.     function createWidget_Hidden({
  796.         return addHidden('new_' $this->name$this->value$this->aExtraAttribs);
  797.     }
  798.  
  799.     /**
  800.      * Creates comment
  801.      * @return string comment
  802.      */
  803.     function createWidget_Comment({
  804.         $result $this->comment;
  805.         return ($result);
  806.     }
  807.  
  808.     /**
  809.      * Creates a (non-associative) edit list
  810.      *
  811.      * Note that multiple layout types are supported for this widget.
  812.      * $this->layout_type must be one of the SMOPT_EDIT_LIST_LAYOUT_*
  813.      * constants.
  814.      *
  815.      * @return string html formated list of edit fields and
  816.      *                 their associated controls
  817.      */
  818.     function createWidget_EditList({
  819.  
  820.         global $oTemplate;
  821.  
  822.         switch ($this->size{
  823.             case SMOPT_SIZE_TINY:
  824.                 $height 3;
  825.                 break;
  826.             case SMOPT_SIZE_SMALL:
  827.                 $height 8;
  828.                 break;
  829.             case SMOPT_SIZE_MEDIUM:
  830.                 $height 15;
  831.                 break;
  832.             case SMOPT_SIZE_LARGE:
  833.                 $height 25;
  834.                 break;
  835.             case SMOPT_SIZE_HUGE:
  836.                 $height 40;
  837.                 break;
  838.             case SMOPT_SIZE_NORMAL:
  839.             default:
  840.                 $height 5;
  841.         }
  842.  
  843.         if (empty($this->possible_values)) $this->possible_values = array();
  844.         if (!is_array($this->possible_values)) $this->possible_values = array($this->possible_values);
  845.  
  846. //FIXME: $this->aExtraAttribs probably should only be used in one place
  847.         $oTemplate->assign('input_widget'addInput('add_' $this->name''380$this->aExtraAttribs));
  848.         $oTemplate->assign('use_input_widget'$this->use_add_widget);
  849.         $oTemplate->assign('use_delete_widget'$this->use_delete_widget);
  850.  
  851.         $oTemplate->assign('trailing_text'$this->trailing_text);
  852.         $oTemplate->assign('trailing_text_small'$this->trailing_text_small);
  853.         $oTemplate->assign('trailing_text_is_html'$this->trailing_text_is_html);
  854.         $oTemplate->assign('possible_values'$this->possible_values);
  855.         $oTemplate->assign('current_value'$this->value);
  856.         $oTemplate->assign('select_widget'addSelect('new_' $this->name$this->possible_values$this->valueFALSE!checkForJavascript($this->aExtraAttribs : array_merge(array('onchange' => 'if (typeof(window.addinput_' $this->name . ') == \'undefined\') { var f = document.forms.length; var i = 0; var pos = -1; while( pos == -1 && i < f ) { var e = document.forms[i].elements.length; var j = 0; while( pos == -1 && j < e ) { if ( document.forms[i].elements[j].type == \'text\' && document.forms[i].elements[j].name == \'add_' $this->name . '\' ) { pos = j; i=f-1; j=e-1; } j++; } i++; } if( pos >= 0 ) { window.addinput_' $this->name . ' = document.forms[i-1].elements[pos]; } } for (x = 0; x < this.length; x++) { if (this.options[x].selected) { window.addinput_' $this->name . '.value = this.options[x].text; break; } }')$this->aExtraAttribs)TRUE$height));
  857. // NOTE: i=f-1; j=e-1 is in lieu of break 2
  858.         $oTemplate->assign('checkbox_widget'addCheckBox('delete_' $this->nameFALSESMPREF_YESarray_merge(array('id' => 'delete_' $this->name)$this->aExtraAttribs)));
  859.         $oTemplate->assign('name'$this->name);
  860.  
  861.         switch ($this->layout_type{
  862.             case SMOPT_EDIT_LIST_LAYOUT_SELECT:
  863.                 return $oTemplate->fetch('edit_list_widget.tpl');
  864.             case SMOPT_EDIT_LIST_LAYOUT_LIST:
  865.                 return $oTemplate->fetch('edit_list_widget_list_style.tpl');
  866.             default:
  867.                 error_box(sprintf(_("Edit List Layout Type '%s' Not Found")$this->layout_type));
  868.         }
  869.  
  870.     }
  871.  
  872.     /**
  873.      * Creates an associative edit list
  874.      *
  875.      * Note that multiple layout types are supported for this widget.
  876.      * $this->layout_type must be one of the SMOPT_EDIT_LIST_LAYOUT_*
  877.      * constants.
  878.      *
  879.      * @return string html formated list of edit fields and
  880.      *                 their associated controls
  881.      */
  882.     function createWidget_EditListAssociative({
  883.  
  884.         global $oTemplate;
  885.  
  886.         switch ($this->size{
  887.             case SMOPT_SIZE_TINY:
  888.                 $height 3;
  889.                 break;
  890.             case SMOPT_SIZE_SMALL:
  891.                 $height 8;
  892.                 break;
  893.             case SMOPT_SIZE_MEDIUM:
  894.                 $height 15;
  895.                 break;
  896.             case SMOPT_SIZE_LARGE:
  897.                 $height 25;
  898.                 break;
  899.             case SMOPT_SIZE_HUGE:
  900.                 $height 40;
  901.                 break;
  902.             case SMOPT_SIZE_NORMAL:
  903.             default:
  904.                 $height 5;
  905.         }
  906.  
  907.  
  908.         // ensure correct format of current value(s)
  909.         //
  910.         if (empty($this->possible_values)) $this->possible_values = array();
  911.         if (!is_array($this->possible_values)) $this->possible_values = array($this->possible_values);
  912.  
  913.  
  914.         $oTemplate->assign('name'$this->name);
  915.         $oTemplate->assign('current_value'$this->value);
  916.         $oTemplate->assign('possible_values'$this->possible_values);
  917.         $oTemplate->assign('poss_value_folders'$this->poss_value_folders);
  918.         $oTemplate->assign('folder_filter'$this->folder_filter);
  919.  
  920.         $oTemplate->assign('use_input_widget'$this->use_add_widget);
  921.         $oTemplate->assign('use_delete_widget'$this->use_delete_widget);
  922.  
  923.         $oTemplate->assign('checkbox_widget'addCheckBox('delete_' $this->nameFALSESMPREF_YESarray_merge(array('id' => 'delete_' $this->name)$this->aExtraAttribs)));
  924.  
  925. //FIXME: $this->aExtraAttribs probably should only be used in one place
  926.         $oTemplate->assign('input_key_widget'addInput('add_' $this->name . '_key'''220$this->aExtraAttribs));
  927.         $oTemplate->assign('input_value_widget'addInput('add_' $this->name . '_value'''120$this->aExtraAttribs));
  928.  
  929.         $oTemplate->assign('select_height'$height);
  930.  
  931.         $oTemplate->assign('aAttribs'$this->aExtraAttribs);
  932.  
  933.         $oTemplate->assign('trailing_text'$this->trailing_text);
  934.         $oTemplate->assign('trailing_text_small'$this->trailing_text_small);
  935.         $oTemplate->assign('trailing_text_is_html'$this->trailing_text_is_html);
  936.  
  937.         switch ($this->layout_type{
  938.             case SMOPT_EDIT_LIST_LAYOUT_SELECT:
  939.                 return $oTemplate->fetch('edit_list_associative_widget.tpl');
  940.             case SMOPT_EDIT_LIST_LAYOUT_LIST:
  941.                 return $oTemplate->fetch('edit_list_associative_widget_list_style.tpl');
  942.             default:
  943.                 error_box(sprintf(_("Associative Edit List Layout Type '%s' Not Found")$this->layout_type));
  944.         }
  945.  
  946.     }
  947.  
  948.     /**
  949.      * Creates a submit button
  950.      *
  951.      * @return string html formated submit button widget
  952.      *
  953.      */
  954.     function createWidget_Submit({
  955.  
  956.         return addSubmit($this->comment$this->name$this->aExtraAttribs($this->trailing_text_small ? '<small>' ''($this->trailing_text_is_html ? $this->trailing_text : sm_encode_html_special_chars($this->trailing_text)) ($this->trailing_text_small ? '</small>' '');
  957.  
  958.     }
  959.  
  960.     /**
  961.      *
  962.      */
  963.     function save({
  964.         $function $this->save_function;
  965.         $function($this);
  966.     }
  967.  
  968.     /**
  969.      *
  970.      */
  971.     function changed({
  972.  
  973.         // edit lists have a lot going on, so we'll always process them
  974.         //
  975.         if ($this->type == SMOPT_TYPE_EDIT_LIST
  976.          || $this->type == SMOPT_TYPE_EDIT_LIST_ASSOCIATIVE)
  977.             return TRUE;
  978.  
  979.         return ($this->value != $this->new_value);
  980.     }
  981. /* End of SquirrelOption class*/
  982.  
  983. /**
  984.  * Saves the option value (this is the default save function
  985.  * unless overridden by the user)
  986.  *
  987.  * @param object $option object that holds option name and new_value
  988.  */
  989. function save_option($option{
  990.  
  991.     // Can't save the pref if we don't have the username
  992.     //
  993.     if !sqgetGlobalVar('username'$usernameSQ_SESSION ) ) {
  994.         return;
  995.     }
  996.  
  997.     // if the widget is a selection list, make sure the new
  998.     // value is actually in the selection list and is not an
  999.     // injection attack
  1000.     //
  1001.     if ($option->type == SMOPT_TYPE_STRLIST
  1002.      && !array_key_exists($option->new_value$option->possible_values))
  1003.         return;
  1004.  
  1005.  
  1006.     // all other widgets except TEXTAREAs should never be allowed to have newlines
  1007.     //
  1008.     else if ($option->type != SMOPT_TYPE_TEXTAREA)
  1009.         $option->new_value str_replace(array("\r""\n")''$option->new_value);
  1010.  
  1011.  
  1012.     global $data_dir;
  1013.  
  1014.     // edit lists: first add new elements to list, then
  1015.     // remove any selected ones (note that we must add
  1016.     // before deleting because the javascript that populates
  1017.     // the "add" textbox when selecting items in the list
  1018.     // (for deletion))
  1019.     //
  1020.     if ($option->type == SMOPT_TYPE_EDIT_LIST{
  1021.  
  1022.         if (empty($option->possible_values)) $option->possible_values array();
  1023.         if (!is_array($option->possible_values)) $option->possible_values array($option->possible_values);
  1024.  
  1025.         // add element if given
  1026.         //
  1027.         if ((isset($option->use_add_widget&& $option->use_add_widget)
  1028.          && sqGetGlobalVar('add_' $option->name$new_elementSQ_POST)) {
  1029.             $new_element trim($new_element);
  1030.             if (!empty($new_element)
  1031.              && !in_array($new_element$option->possible_values))
  1032.                 $option->possible_values[$new_element;
  1033.         }
  1034.         
  1035.         // delete selected elements if needed
  1036.         //
  1037.         if ((isset($option->use_delete_widget&& $option->use_delete_widget)
  1038.          && is_array($option->new_value)
  1039.          && sqGetGlobalVar('delete_' $option->name$ignoreSQ_POST))
  1040.             $option->possible_values array_diff($option->possible_values$option->new_value);
  1041.  
  1042.         // save full list (stored in "possible_values")
  1043.         //
  1044.         setPref($data_dir$username$option->nameserialize($option->possible_values));
  1045.  
  1046.     // associative edit lists are handled similar to
  1047.     // non-associative ones
  1048.     //
  1049.     else if ($option->type == SMOPT_TYPE_EDIT_LIST_ASSOCIATIVE{
  1050.  
  1051.         if (empty($option->possible_values)) $option->possible_values array();
  1052.         if (!is_array($option->possible_values)) $option->possible_values array($option->possible_values);
  1053.  
  1054.         // add element if given
  1055.         //
  1056.         $new_element_key '';
  1057.         $new_element_value '';
  1058.         $retrieve_key sqGetGlobalVar('add_' $option->name '_key'$new_element_keySQ_POST);
  1059.         $retrieve_value sqGetGlobalVar('add_' $option->name '_value'$new_element_valueSQ_POST);
  1060.  
  1061.         if ((isset($option->use_add_widget&& $option->use_add_widget)
  1062.          && ($retrieve_key || $retrieve_value)) {
  1063.             $new_element_key trim($new_element_key);
  1064.             $new_element_value trim($new_element_value);
  1065.             if ($option->poss_value_folders && empty($new_element_key))
  1066.                 $new_element_value '';
  1067.             if (!empty($new_element_key|| !empty($new_element_value)) {
  1068.                 if (empty($new_element_key)) $new_element_key '0';
  1069.                 $option->possible_values[$new_element_key$new_element_value;
  1070.             }
  1071.         }
  1072.  
  1073.         // delete selected elements if needed
  1074.         //
  1075.         if ((isset($option->use_delete_widget&& $option->use_delete_widget)
  1076.          && is_array($option->new_value)
  1077.          && sqGetGlobalVar('delete_' $option->name$ignoreSQ_POST)) {
  1078.  
  1079.             if ($option->layout_type == SMOPT_EDIT_LIST_LAYOUT_SELECT{
  1080.                 foreach ($option->new_value as $key)
  1081.                     unset($option->possible_values[urldecode($key)]);
  1082.             }
  1083.             else
  1084.                 $option->possible_values array_diff($option->possible_values$option->new_value);
  1085.         }
  1086.  
  1087.         // save full list (stored in "possible_values")
  1088.         //
  1089.         setPref($data_dir$username$option->nameserialize($option->possible_values));
  1090.  
  1091.     // Certain option types need to be serialized because
  1092.     // they are not scalar
  1093.     //
  1094.     else if ($option->is_multiple_valued())
  1095.         setPref($data_dir$username$option->nameserialize($option->new_value));
  1096.  
  1097.     // Checkboxes, when unchecked, don't submit anything in
  1098.     // the POST, so set to SMPREF_OFF if not found
  1099.     //
  1100.     else if (($option->type == SMOPT_TYPE_BOOLEAN
  1101.            || $option->type == SMOPT_TYPE_BOOLEAN_CHECKBOX)
  1102.           && empty($option->new_value)) 
  1103.         setPref($data_dir$username$option->nameSMPREF_OFF);
  1104.  
  1105.     // For integer fields, make sure we only have digits...
  1106.     // We'll be nice and instead of just converting to an integer,
  1107.     // we'll physically remove each non-digit in the string.
  1108.     //
  1109.     else if ($option->type == SMOPT_TYPE_INTEGER{
  1110.         $option->new_value preg_replace('/[^0-9]/'''$option->new_value);
  1111.         setPref($data_dir$username$option->name$option->new_value);
  1112.     }
  1113.  
  1114.     else
  1115.         setPref($data_dir$username$option->name$option->new_value);
  1116.  
  1117.  
  1118.     // if a checkbox or multi select is zeroed/cleared out, it
  1119.     // needs to have an empty value pushed into its "new_value" slot
  1120.     //
  1121.     if (($option->type == SMOPT_TYPE_STRLIST_MULTI
  1122.       || $option->type == SMOPT_TYPE_BOOLEAN_CHECKBOX)
  1123.      && is_null($option->new_value))
  1124.         $option->new_value '';
  1125.  
  1126. }
  1127.  
  1128. /**
  1129.  * save function that does not save
  1130.  * @param object $option 
  1131.  */
  1132. function save_option_noop($option{
  1133.     /* Do nothing here... */
  1134. }
  1135.  
  1136. /**
  1137.  * Create hidden 'optpage' input field with value set by argument
  1138.  * @param string $optpage identification of option page
  1139.  * @return string html formated hidden input field
  1140.  */
  1141. function create_optpage_element($optpage{
  1142.     return addHidden('optpage'$optpage);
  1143. }
  1144.  
  1145. /**
  1146.  * Create hidden 'optmode' input field with value set by argument
  1147.  * @param string $optmode 
  1148.  * @return string html formated hidden input field
  1149.  */
  1150. function create_optmode_element($optmode{
  1151.     return addHidden('optmode'$optmode);
  1152. }
  1153.  
  1154. /**
  1155.  * @param array $optgrps 
  1156.  * @param array $optvals 
  1157.  * @return array 
  1158.  */
  1159. function create_option_groups($optgrps$optvals{
  1160.     /* Build a simple array with which to start. */
  1161.     $result array();
  1162.  
  1163.     /* Create option group for each option group name. */
  1164.     foreach ($optgrps as $grpkey => $grpname{
  1165.         $result[$grpkeyarray();
  1166.         $result[$grpkey]['name'$grpname;
  1167.         $result[$grpkey]['options'array();
  1168.     }
  1169.  
  1170.      /* Create a new SquirrelOption for each set of option values. */
  1171.     foreach ($optvals as $grpkey => $grpopts{
  1172.         foreach ($grpopts as $optset{
  1173.             /* Create a new option with all values given. */
  1174.             $next_option new SquirrelOption(
  1175.                     $optset,
  1176.                     $optset['name'],
  1177.                     $optset['caption'],
  1178.                     $optset['type'],
  1179.                     (isset($optset['refresh']$optset['refresh'SMOPT_REFRESH_NONE),
  1180.                     (isset($optset['initial_value']$optset['initial_value'''),
  1181.                     (isset($optset['posvals']$optset['posvals'''),
  1182.                     (isset($optset['htmlencoded']$optset['htmlencoded'false)
  1183.                     );
  1184.  
  1185.             /* If provided, set if the caption is allowed to wrap for this option. */
  1186.             if (isset($optset['caption_wrap'])) {
  1187.                 $next_option->setCaptionWrap($optset['caption_wrap']);
  1188.             }
  1189.  
  1190.             /* If provided, set the size for this option. */
  1191.             if (isset($optset['size'])) {
  1192.                 $next_option->setSize($optset['size']);
  1193.             }
  1194.  
  1195.             /* If provided, set the trailing_text for this option. */
  1196.             if (isset($optset['trailing_text'])) {
  1197.                 $next_option->setTrailingText($optset['trailing_text']);
  1198.             }
  1199.  
  1200.             /* If provided, set the trailing_text_small for this option. */
  1201.             if (isset($optset['trailing_text_small'])) {
  1202.                 $next_option->setTrailingTextSmall($optset['trailing_text_small']);
  1203.             }
  1204.  
  1205.             /* If provided, set the trailing_text_is_html for this option. */
  1206.             if (isset($optset['trailing_text_is_html'])) {
  1207.                 $next_option->setTrailingTextIsHtml($optset['trailing_text_is_html']);
  1208.             }
  1209.  
  1210.             /* If provided, set the yes_text for this option. */
  1211.             if (isset($optset['yes_text'])) {
  1212.                 $next_option->setYesText($optset['yes_text']);
  1213.             }
  1214.  
  1215.             /* If provided, set the no_text for this option. */
  1216.             if (isset($optset['no_text'])) {
  1217.                 $next_option->setNoText($optset['no_text']);
  1218.             }
  1219.  
  1220.             /* If provided, set the poss_value_folders value for this option. */
  1221.             if (isset($optset['poss_value_folders'])) {
  1222.                 $next_option->setPossValueFolders($optset['poss_value_folders']);
  1223.             }
  1224.  
  1225.             /* If provided, set the layout type for this option. */
  1226.             if (isset($optset['layout_type'])) {
  1227.                 $next_option->setLayoutType($optset['layout_type']);
  1228.             }
  1229.  
  1230.             /* If provided, set the use_add_widget value for this option. */
  1231.             if (isset($optset['use_add_widget'])) {
  1232.                 $next_option->setUseAddWidget($optset['use_add_widget']);
  1233.             }
  1234.  
  1235.             /* If provided, set the use_delete_widget value for this option. */
  1236.             if (isset($optset['use_delete_widget'])) {
  1237.                 $next_option->setUseDeleteWidget($optset['use_delete_widget']);
  1238.             }
  1239.  
  1240.             /* If provided, set the comment for this option. */
  1241.             if (isset($optset['comment'])) {
  1242.                 $next_option->setComment($optset['comment']);
  1243.             }
  1244.  
  1245.             /* If provided, set the save function for this option. */
  1246.             if (isset($optset['save'])) {
  1247.                 $next_option->setSaveFunction($optset['save']);
  1248.             }
  1249.  
  1250.             /* If provided, set the extra attributes for this option. */
  1251.             if (isset($optset['extra_attributes'])) {
  1252.                 $next_option->setExtraAttributes($optset['extra_attributes']);
  1253.             }
  1254.  
  1255.             /* If provided, set the "post script" for this option. */
  1256.             if (isset($optset['post_script'])) {
  1257.                 $next_option->setPostScript($optset['post_script']);
  1258.             }
  1259.  
  1260.             /* If provided, set the folder_filter for this option. */
  1261.             if (isset($optset['folder_filter'])) {
  1262.                 $next_option->setFolderFilter($optset['folder_filter']);
  1263.             }
  1264.  
  1265.             /* Add this option to the option array. */
  1266.             $result[$grpkey]['options'][$next_option;
  1267.         }
  1268.     }
  1269.  
  1270.     /* Return our resulting array. */
  1271.     return ($result);
  1272. }

Documentation generated on Mon, 13 Jan 2020 04:23:14 +0100 by phpDocumentor 1.4.3