<?php
/**
 * formslib.php - library of classes for creating forms in Moodle, based on PEAR QuickForms.
 * THIS IS NOT YET PART OF THE MOODLE API, IT IS HERE FOR TESTING ONLY
 * @author  Jamie Pratt
 * @version $Id: formslib.php,v 1.10 2006/10/09 11:34:43 jamiesensei Exp $
 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
 */

//point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else.
if (FALSE===strstr(ini_get('include_path'), $CFG->libdir.'/pear' )){
    ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path'));
}
require_once 'HTML/QuickForm.php';
require_once 'HTML/QuickForm/DHTMLRulesTableless.php';
require_once 'HTML/QuickForm/Renderer/Tableless.php';

if ($CFG->debug >= DEBUG_ALL){
    PEAR::setErrorHandling(PEAR_ERROR_PRINT);
}

class moodleform_wrapper {
    var $_form;       // quickform object definition
    var $_customdata;

    function moodleform_wrapper($action, $customdata=null, $method='post', $target='', $attributes=null) {
        $this->_form =& new moodleform(get_class($this), $method, $action, $target, $attributes);
        $this->_customdata = $customdata;
        $this->form_definition();
        $this->_process_submission($method); // we have to know all input types before processing submission
        // TODO: proccess uploaded files
    }

    function _process_submission($method) {
        $submission = array();
        if ($method == 'post') {
            if (!empty($_POST)) {
                $submission = $_POST;
            }
        } else {
            $submission = array_merge_recursive($_GET, $_POST); // emulate handling of parameters in xxxx_param()
        }
        $this->_form->updateSubmission($submission);
        return $this->_form->isSubmitted();
    }

    function set_defaults($default_values, $slashed=false) {
        if (is_object($default_values)) {
            $default_values = (array)$default_values; // backwards compatibility
        }
        $filter = $slashed ? 'stripslashes' : NULL;
        $this->_form->setDefaults($default_values, $filter);
    }

    function use_values_as_defaults() {
        $this->set_defaults($this->export_values(false));
    }

    function is_submitted() {
        return $this->_form->isSubmitted();
    }

    function is_valid() {
        return $this->_form->validate();
    }

    function export_values($slashed=true) {
        return $this->_form->exportValues(null, $slashed);
    }

    function display() {
        $this->_form->display();
    }

    // abstract method
    function form_definition() {
        error('Abstract definition() method in class '.get_class($this).' must be overriden, please fix the code.');
    }

}

class moodleform extends HTML_QuickForm_DHTMLRulesTableless {
    var $_types = array();

    function setType($elementname, $paramtype) {
        $this->_types[$elementname] = $paramtype;
    }

    function updateSubmission($submission) {
        if (empty($submission)) {
            $this->_submitValues = array();
            $this->_flagSubmitted = false;
        } else {
            foreach ($submission as $key=>$s) {
                if (array_key_exists($key, $this->_types)) {
                    $submission[$key] = clean_param($s, $this->_types[$key]);
                } else {
                    $submission[$key] = clean_param($s, PARAM_CLEAN); // watch out may not always prevent XSS and SQL injections
                }
            }
            $this->_submitValues = $this->_recursiveFilter('stripslashes', $submission);
            $this->_flagSubmitted = true;
        }
    }
    /**
     * Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless
     * @param    string      $formName          Form's name.
     * @param    string      $method            (optional)Form's method defaults to 'POST'
     * @param    string      $action            (optional)Form's action
     * @param    string      $target            (optional)Form's target defaults to none
     * @param    mixed       $attributes        (optional)Extra attributes for <form> tag
     * @param    bool        $trackSubmit       (optional)Whether to track if the form was submitted by adding a special hidden field
     * @access   public
     */
    function moodleform($formName, $method, $action, $target='', $attributes=null){
        global $CFG;
        HTML_Common::HTML_Common($attributes);
        $target = empty($target) ? array() : array('target' => $target);
        //no 'name' atttribute for form in xhtml strict :
        $attributes = array('action'=>$action, 'method'=>$method, 'id'=>$formName) + $target;
        $this->updateAttributes($attributes);

        //this is custom stuff for Moodle :
        $oldclass=   $this->getAttribute('class');
        if (!empty($oldclass)){
            $this->updateAttributes(array('class'=>$oldclass.' mform'));
        }else {
            $this->updateAttributes(array('class'=>'mform'));
        }
        $this->_helpImageURL="$CFG->wwwroot/lib/form/req.gif";
        $this->_reqHTML =
            helpbutton('requiredelement', get_string('requiredelement', 'form'),'moodle',
                 true, false, '', true, '<img alt="'.get_string('requiredelement', 'form').'" src="'.
                    $this->_helpImageURL.'" />');
        $this->setRequiredNote(get_string('denotesreq', 'form', $this->getReqHTML()));
    }


    function getReqHTML(){
        return $this->_reqHTML;
    }
    /**
     * Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless
     * @param    array       $buttons          An associative array representing help button to attach to
     *                                          to the form. keys of array correspond to names of elements in form.
     *
     * @access   public
    */
    function setHelpButtons($buttons, $suppresscheck=false){

        foreach ($this->_elements as $no => $element){
            if (array_key_exists($element->getName(), $buttons)){

                if (method_exists($element, 'setHelpButton')){
                    $this->_elements[$no]->setHelpButton($buttons[$element->getName()]);
                }else{
                    $a=new object();
                    $a->name=$element->getName();
                    $a->classname=get_class($element);
                    print_error('nomethodforaddinghelpbutton', 'form', '', $a);
                }
                unset($buttons[$element->getName()]);
            }

        }
        if (count($buttons)&& !$suppresscheck){
            print_error('nonexistentformelements', 'form', '', join(', ', array_keys($buttons)));
        }
    }
    function exportValues($elementList= null, $addslashes=true){
        $unfiltered=parent::exportValues($elementList);
        if ($addslashes){
            return $this->_recursiveFilter('addslashes',$unfiltered);
        } else {
            return $unfiltered;
        }
    }

}

/**
 * A renderer for moodleform that only uses XHTML and CSS and no
 * table tags, extends PEAR class HTML_QuickForm_Renderer_Tableless
 *
 * Stylesheet is part of standard theme and should be automatically included.
 *
 * @author      Jamie Pratt <me@jamiep.org>
 * @license    gpl license
 */
class moodleform_Renderer extends HTML_QuickForm_Renderer_Tableless{

    /**
    * Element template array
    * @var      array
    * @access   private
    */
    var $_elementTemplates;

//   uncomment templates below and edit formslib.php for
//   ol li containers for form items.

    /**
    * Template used when opening a hidden fieldset
    * (i.e. a fieldset that is opened when there is no header element)
    * @var      string
    * @access   private
    */
    var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">";
//    var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">\n\t\t<ol>";
//   /**
//    * Header Template string
//    * @var      string
//    * @access   private
//    */
//    var $_headerTemplate =
//        "\n\t\t<legend>{header}</legend>\n\t\t<ol>";
//    var $_headerTemplate =
//        "\n\t\t<legend>{header}</legend>\n\t\t<ol>";
   /**
    * Template used when closing a fieldset
    * @var      string
    * @access   private
    */
    var $_closeFieldsetTemplate = "\n\t\t</fieldset>";
//    var $_closeFieldsetTemplate = "\n\t\t</ol>\n\t</fieldset>";

   /**
    * Required Note template string
    * @var      string
    * @access   private
    */
    var $_requiredNoteTemplate =
        "\n\t\t<div class=\"fdescription\">{requiredNote}</div>";
    function moodleform_Renderer(){
        // switch next two lines for ol li containers for form items.
        //        $this->_elementTemplates=array('default'=>"\n\t\t<li class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class=\"qfelement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></li>");
        $this->_elementTemplates=array('default'=>"\n\t\t<div class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class=\"felement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></div>",
        'fieldset'=>"\n\t\t<div class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><fieldset class=\"felement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</fieldset></div>");

        parent::HTML_QuickForm_Renderer_Tableless();
    }
    function startForm(&$form){
        $this->_reqHTML=$form->getReqHTML();
        $this->_elementTemplates=str_replace('{req}', $this->_reqHTML, $this->_elementTemplates);
        parent::startForm($form);
    }
    function startGroup(&$group, $required, $error){
        if (method_exists($group, 'getElementTemplateType')){
            $html = $this->_elementTemplates[$group->getElementTemplateType()];
        }else{
            $html = $this->_elementTemplates['default'];

        }
        if (method_exists($group, 'getHelpButton')){
            $html =str_replace('{help}', $group->getHelpButton(), $html);
        }else{
            $html =str_replace('{help}', '', $html);

        }
        $html =str_replace('{type}', 'fgroup', $html);

        $this->_templates[$group->getName()]=$html;
        // Fix for bug in tableless quickforms that didn't allow you to stop a
        // fieldset before a group of elements.
        // if the element name indicates the end of a fieldset, close the fieldset
        if (   in_array($group->getName(), $this->_stopFieldsetElements)
            && $this->_fieldsetsOpen > 0
           ) {
            $this->_html .= $this->_closeFieldsetTemplate;
            $this->_fieldsetsOpen--;
        }
        parent::startGroup($group, $required, $error);
    }
    function renderElement(&$element, $required, $error){
        if (method_exists($element, 'getElementTemplateType')){
            $html = $this->_elementTemplates[$element->getElementTemplateType()];
        }else{
            $html = $this->_elementTemplates['default'];

        }
        $html =str_replace('{type}', 'f'.$element->getType(), $html);
        if (method_exists($element, 'getHelpButton')){
            $html=str_replace('{help}', $element->getHelpButton(), $html);
        }else{
            $html=str_replace('{help}', '', $html);

        }
        $this->_templates[$element->getName()]=$html;
        if (!is_null($element->getAttribute('id'))) {
            $id = $element->getAttribute('id');
        } else {
            $id = $element->getName();
        }
        $element->updateAttributes(array('id'=>'id_'.$id));
        parent::renderElement($element, $required, $error);
    }


}


$GLOBALS['_HTML_QuickForm_default_renderer']=& new moodleform_Renderer();

moodleform::registerElementType('checkbox', "$CFG->libdir/form/checkbox.php", 'moodleform_checkbox');
moodleform::registerElementType('file', "$CFG->libdir/form/file.php", 'moodleform_file');
moodleform::registerElementType('group', "$CFG->libdir/form/group.php", 'moodleform_group');
moodleform::registerElementType('password', "$CFG->libdir/form/password.php", 'moodleform_password');
moodleform::registerElementType('radio', "$CFG->libdir/form/radio.php", 'moodleform_radio');
moodleform::registerElementType('select', "$CFG->libdir/form/select.php", 'moodleform_select');
moodleform::registerElementType('text', "$CFG->libdir/form/text.php", 'moodleform_text');
moodleform::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'moodleform_textarea');
moodleform::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'moodleform_date_selector');
moodleform::registerElementType('htmleditor', "$CFG->libdir/form/htmleditor.php", 'moodleform_htmleditor');
moodleform::registerElementType('static', "$CFG->libdir/form/static.php", 'moodleform_static');
moodleform::registerElementType('hidden', "$CFG->libdir/form/hidden.php", 'moodleform_hidden');


?>
