<?PHP
#
#   FILE:  HtmlOptionList.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2014-2015 Edward Almasy and Internet Scout Research Group
#   http://scout.wisc.edu/cwis/
#

/**
* Convenience class for generating an HTML select/option form element.
*/
class HtmlOptionList
{

    # ---- PUBLIC INTERFACE --------------------------------------------------

    /**
    * Class constructor.
    * @param string $ResultVar Name of form variable for select element.
    * @param array $Options Array of options, with form values for the
    *       array index and labels for the array values.
    * @param mixed $SelectedValue Currently selected form value or array
    *       of currently selected form values.  (OPTIONAL)
    */
    public function __construct($ResultVar, $Options, $SelectedValue = NULL)
    {
        $this->ResultVar = $ResultVar;
        $this->Options = $Options;
        $this->SelectedValue = $SelectedValue;
    }

    /**
    * Print HTML for list.
    */
    public function PrintHtml()
    {
        print $this->GetHtml();
    }

    /**
    * Get HTML for list.
    * @return string Generated HTML.
    */
    public function GetHtml()
    {
        # start out with empty HTML
        $Html = "";

        # if there are options or we are supposed to print even if no options
        if (count($this->Options) || $this->PrintIfEmpty)
        {
            # begin select element
            $Html .= '<select name="'.$this->ResultVar.'"'
                    .' size="'.$this->Size.'"'
                    .' id="'.$this->ResultVar.'"';
            if ($this->SubmitOnChange)
            {
                if ($this->OnChangeAction)
                    {  $Html .= ' onChange="'.$this->OnChangeAction.'"';  }
                else
                    {  $Html .= ' onChange="submit()"';  }
            }
            if ($this->MultipleAllowed) {  $Html .= ' multiple';  }
            if ($this->Disabled) {  $Html .= ' disabled';  }
            $Html .= ">\n";

            # for each option
            foreach ($this->Options as $Value => $Label)
            {
                # start option element
                $Html .= '    <option value="'.htmlspecialchars($Value).'"';

                # add in selected attribute if appropriate
                if ((is_array($this->SelectedValue)
                                && in_array($Value, $this->SelectedValue))
                        || ($Value == $this->SelectedValue))
                {
                    $Html .= ' selected';
                }

                # add in disabled attribute if appropriate
                if (array_key_exists($Value, $this->DisabledOptions))
                {
                    $Html .= ' disabled';
                }

                # add label and end option element
                $Html .= ">".htmlspecialchars($Label)."</option>\n";
            }

            # end select element
            $Html .= '</select>';
        }

        # return generated HTML to caller
        return $Html;
    }

    /**
    * Get/set disabled options.
    * @param mixed $Options Option or array of options to disable.  If
    *       a single option then it should be the value and will be added
    *       to any existing disabled options, and if an array it should have
    *       the values for the index and will replace the current list of
    *       disabled options.  (OPTIONAL)
    */
    public function DisabledOptions($Options = NULL)
    {
        if ($Options !== NULL)
        {
            if (is_array($Options))
            {
                $this->DisabledOptions = $Options;
            }
            else
            {
                $this->DisabledOptions[$Options] = "X";
            }
        }
        return $this->DisabledOptions;
    }

    /**
    * Get/set currently selected value or array of currently selected values.
    * @param mixed $NewValue Currently selected form value or array
    *       of currently selected form values.  (OPTIONAL)
    * @return mixed Selected value or array of currently selected values.
    */
    public function SelectedValue($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->SelectedValue = $NewValue;
        }
        return $this->SelectedValue;
    }

    /**
    * Get/set the list size (number of visible items).  Defaults to 1.
    * @param int $NewValue Current size.  (OPTIONAL)
    * @return int Current size.
    */
    public function Size($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->Size = intval($NewValue);
        }
        return $this->Size;
    }

    /**
    * Get/set whether multiple items may be selected.  Defaults to FALSE.
    * @param bool $NewValue If TRUE, users will be able to select multiple
    *       items. (OPTIONAL)
    * @return bool TRUE if users can select multiple items, otherwise FALSE.
    */
    public function MultipleAllowed($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->MultipleAllowed = $NewValue ? TRUE : FALSE;

            # adjust form field name (result variable) if needed
            if ($this->MultipleAllowed
                    && (substr($this->ResultVar, -2) != "[]"))
            {
                $this->ResultVar .= "[]";
            }
            elseif (!$this->MultipleAllowed
                    && (substr($this->ResultVar, -2) == "[]"))
            {
                $this->ResultVar .= substr($this->ResultVar, 0, -2);
            }
        }
        return $this->MultipleAllowed;
    }

    /**
    * Get/set whether to submit the form when the list value is changed.
    * Defaults to FALSE.
    * @param bool $NewValue If TRUE, form will be submitted on
    *       change. (OPTIONAL)
    * @return bool TRUE if form will be submitted, otherwise FALSE.
    * @see HtmlOptionList::OnChangeAction()
    */
    public function SubmitOnChange($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->SubmitOnChange = $NewValue ? TRUE : FALSE;
        }
        return $this->SubmitOnChange;
    }

    /**
    * Get/set action to take if form is submitted on change.  Defaults
    * to "submit()" (without the quotes).  No character escaping or other
    * processing is done to this value before it is added to the HTML, so
    * whatever is passed in must be pre-sanitized if needed, including
    * escaping any double quotation marks.  This setting has no effect if
    * SubmitOnChange() is set to FALSE.
    * @param string $NewValue New action.  (OPTIONAL)
    * @return string Current action.
    * @see HtmlOptionList::SubmitOnChange()
    */
    public function OnChangeAction($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->OnChangeAction = $NewValue;
        }
        return $this->OnChangeAction;
    }

    /**
    * Get/set whether list should be output even if there are no items.
    * If this is set to FALSE and there are no items in the list, GetHtml()
    * will return an empty string and PrintHtml() will print nothing.
    * Defaults to TRUE.
    * @param bool $NewValue If TRUE, HTML will be returned/printed even if
    *       there are no items in the list.  (OPTIONAL)
    * @return bool TRUE if empty list will be printed, otherwise FALSE.
    */
    public function PrintIfEmpty($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->PrintIfEmpty = $NewValue ? TRUE : FALSE;
        }
        return $this->PrintIfEmpty;
    }

    /**
    * Get/set whether the whole option list is editable.  NOTE: When the
    * list is not editable, values for it are not submitted with the form.
    * This is distinct from whether individual options are disabled.
    * @param bool $NewValue If TRUE, list is not editable.
    * @return bool TRUE if list will not be editabled, otherwise FALSE.
    */
    public function Disabled($NewValue = NULL)
    {
        if ($NewValue !== NULL)
        {
            $this->Disabled = $NewValue ? TRUE : FALSE;
        }
        return $this->Disabled;
    }


    # ---- PRIVATE INTERFACE -------------------------------------------------

    private $Options;
    private $ResultVar;

    private $Disabled = FALSE;
    private $DisabledOptions = array();
    private $MultipleAllowed = FALSE;
    private $OnChangeAction = "submit()";
    private $PrintIfEmpty = TRUE;
    private $SelectedValue;
    private $Size = 1;
    private $SubmitOnChange = FALSE;
}
