<?php
require_once('fishhtml.class.php');
require_once(
'fishtext.class.php');
require_once(
'fishargs.class.php');
class 
FishForms
{

    function 
get_field_value($name='',$default='',$value=NULL,$source='')
    {
        if (
$value !== NULL)
        {
            return 
$value;
        }

        if (empty(
$name))
        {
            return 
$default;
        }

        if (
$source === NULL)
        {
            
$source =& $_REQUEST;
        }

        
$i strpos($name,'[');
        if (
$i === FALSE)
        {
            
$value FishUtil::array_key_value($source,$name,$default);
        }
        else
        {
            
$prefix substr($name,0,$i);
            
$suffix substr($name,$i);
            
// fix non-numeric key values
            
$suffix preg_replace('/\[([^\]]*[a-z][^\]]*)\]/''["$1"]'$suffix);
            $
$prefix FishUtil::array_key_value($source,$prefix,$default);
            if (
is_array($$prefix))
            {
                
$expr '$value = isset($'.$prefix.$suffix.') ? $'.$prefix.$suffix.' : $default;';
                eval(
$expr);
            }
            else
            {
                
$value = $$prefix;
            }
        }
        return 
$value;
    }

    
// string input_field ([string name [, string value [, int size [, int maximum length]]]])

    // This function returns an HTML text input field. The default size
    // of the field is 10. A value and maximum data length for the field
    // may be supplied.
    
function input_field()
    {
        static 
$_defaults = array(
            
'name' => 'inputfield'
            
'type' => 'text'
            
'value' => NULL
            
'allowed' => array('Common','accept','accesskey','alt','checked'
                
'disabled','maxlength','name','readonly','size','src'
                
'tabindex','type','value','align','ismap'
            
)
        );
        static 
$_simple = array('name','value');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        
$attlist FishHTML::get_attlist($p);
        
$output "<input $attlist>";
        return 
$output;
    }

    
// string checkbox_field ([string name [, string value [, string label [, string match]]]])

    
function checkbox_field()
    {
        static 
$_defaults = array(
            
'type' => 'checkbox'
            
'name' => 'checkboxfield'
            
'value' => ''
            
'label' => NULL
            
'match' => NULL
            
'default' => NULL
            
'checked' => NULL
            
'source' => NULL
            
'prefix' => '<nobr>'
            
'suffix' => '</nobr>'
            
'label_match' => TRUE
            
'skip_selection' => FALSE
        
);
        static 
$_simple = array('name','value','label');

        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
$p['label'] === NULL)
        {
            
$p['label'] = FishText::labelize($p['value']);
        }
        if (!
$p['skip_selection'])
        {
            
$p['value'] = FishForms::get_field_value($p['name'],$p['default'],$p['value'],$p['source']);
            
$p['checked'] = (
                
in_array($p['value'],(array)$p['match']) 
                || (
                    
$p['label_match'
                    && 
in_array($p['label'],(array)$p['match'])
                )
            ) ? 
STANDALONE NULL ;
            if (
$p['checked'] === NULL)
            {
//                FishError::trace('value=', $p['value'], ' is not in ', (array)$p['match']);
            
}
        }
        
$output $p['prefix'].FishForms::input_field($p).' '.$p['label'].$p['suffix'];

        return 
$output;
    }

    function 
checkbox_group()
    {
        static 
$_defaults = array(
            
'values' => array()
            , 
'name' => 'checkboxfield'
            
'sep' => "&nbsp;\n"
            
'match' => NULL
            
'default' => NULL
            
'source' => NULL
            
'group_prefix' => ''
            
'group_label' => NULL
            
'group_suffix' => ''
            
'format' => NULL
        
);
        static 
$_simple = array('name','values');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
$p['group_label'] === NULL)
        {
            
$p['group_label'] = FishText::labelize($p['name']);
        }
        
$outarr = array();
        foreach (
$p['values'] as $p['value'] => $p['label'])
        {
            
$outarr[] = FishForms::checkbox_field($p);
        }
        if (
$p['format'] == 'array')
        {
            return 
$outarr;
        }
        
$output $p['group_prefix']
            . 
$p['group_label']
            . 
' '
            
implode($p['sep'],$outarr)
            . 
$p['group_suffix']
        ;
        return 
$output;
    }


    
// string end_form(void)

    // This function returns an HTML </form> tag.

    
function end_form()
    {
        
$output = <<<EOQ
    </form>
EOQ;
        return 
$output;
    }


    function 
field_group()
    {
        static 
$_defaults = array(
            
'values' => array()
            , 
'format' => NULL
        
);
        static 
$_simple = array('values');

        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);

        
$outarr = array();
        foreach (
$p['values'] as $p['label'] => $p['value'])
        {
            if (
FishUtil::is_assoc($p['value']))
            {
                
$p['value'] = FishForms::text_field($p);
            }
            
$outarr[] = array(FishHTML::table_header_cell($p['label']),$p['value']);
        }
        if (
$p['format'] == 'array')
        {
            return 
$outarr;
        }
        
$p['rows']=$outarr;
        
$output FishHTML::table($p);
        return 
$output;
    }

    
// string file_field ([string name])

    // This function returns an HTML file field. These are used to specify
    // files on the user's local hard drive, typically for uploading as
    // part of the form. (See http://www.zend.com/manual/features.file-upload.php
    // for more information about this subject.)

    
function file_field()
    {
        static 
$_defaults = array(
            
'type' => 'file'
            
'name' => 'filefield'
            
'allowed' => array('Common','name','type')
        );
        static 
$_simple = array('name');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        return 
FishForms::input_field($p);
        return 
$output;
    }


    
// string hidden_field ([string name [, string value]])

    // This function returns an HTML hidden field. A value may be supplied.

    
function hidden_field()
    {
        static 
$_defaults = array(
            
'name'=>'hiddenfield'
            
'value'=>NULL
            
'default'=>NULL
            
'source'=>NULL
        
);
        static 
$_simple = array('name','value');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
//        FishError::trace('before FishForms::get_field_value: value=', $p['value']);
        
$p['value'] = FishForms::get_field_value($p['name'],$p['default'],$p['value'],$p['source']);
//        FishError::trace('after FishForms::get_field_value: value=', $p['value']);
        
$output "<input type='hidden' name='{$p['name']}' value='{$p['value']}'>";
        return 
$output;
    }


    
// string image_field ([string name [, string src [, string value]]])

    // This function returns an HTML image field. An image field works
    // likes a submit field, except that the image specified by the URL
    // given in the second argument is displayed instead of a button.

    
function image_field()
    {
        static 
$_defaults = array(
            
'type' => 'image'
            
'name' => 'imagefield'
        
);
        static 
$_simple = array('name','src');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        return 
FishForms::input_field($p);
    }

    function 
option_tag()
    {
        static 
$_defaults = array(
            
'value' => NULL
            
'name' => 'selectfield'
            
'label' => NULL
            
'match' => NULL
            
'default' => NULL
            
'source' => NULL
            
'label_match' => TRUE
            
'skip_selection' => NULL
            
'allowed' => array('Common','selected','value','disabled')
        );
        static 
$_simple = array('value','label','match');

        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);

        if (
$p['label'] === NULL)
        {
            
$p['label'] = FishText::labelize($p['value']);
        }
        if (
$p['skip_selection'] === NULL && !array_key_exists('selected',$p))
        {
            if (
$p['match'] === NULL)
            {
                
$p['match'] = FishForms::get_field_value(
                    
$p['name']
                    , 
$p['default']
                    , 
$p['match']
                    , 
$p['source']
                );
            }
            
$p['selected'] = NULL;
            if (
$p['value'] == $p['match'
                || (
$p['label_match'] && $p['label'] == $p['match'])
            )
            {
                
$p['selected'] = STANDALONE;
            }
        }
        
$output '<option '.FishHTML::get_attlist($p).'>'.$p['label']."</option>\n";
        return 
$output;
    }


    
// string password_field ([string name [, string value [, int size [, int maximum length]]]])

    // This function returns an HTML password field. This is like a text field,
    // but the value of the field is obscured (only stars or bullets are visible
    // for each character).  The default size of the field is 10.  A starting
    // value and maximum data length may be supplied.

    
function password_field()
    {
        static 
$_defaults = array(
            
'type' => 'password'
            
'name' => 'passwordfield'
            
'value' => NULL
            
'default' => NULL
            
'source' => NULL
        
);
        static 
$_simple = array('name');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        
$p['value'] = FishForms::get_field_value($p['name'],$p['default'],$p['value'],$p['source']);
        return 
FishForms::input_field($p);
    }


    
// string radio_field ([string name [, string value [, string label [, string match]]]])

    // This function returns an HTML radio button field. The optional third 
    // argument will be included immediately after the radio button, and the pair
    // is included inside a HTML <nobr> tag - meaning that they will be
    // displayed together on the same line.  If the value of the
    // second or third argument matches that of the fourth argument,
    // the radio button will be 'checked' (i.e., flipped on).

    
function radio_field()
    {
        static 
$_defaults = array(
            
'type' => 'radio'
            
'name' => 'radiofield'
            
'label' => NULL
            
'value' => ''
            
'default' => NULL
            
'match' => NULL
            
'source' => NULL
            
'prefix' => '<nobr>'
            
'suffix' => '</nobr>'
            
'label_match' => TRUE
            
'checked' => NULL
        
);
        static 
$_simple = array('name','value','match');

        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
$p['label'] === NULL)
        {
            
$p['label'] = FishText::labelize($p['name']);
        }

        
$p['match'] = FishForms::get_field_value($p['name'],$p['default'],$p['match'],$p['source']);

        
$p['checked'] = ($p['value'] == $p['match'] || ($p['label_match'] && ($p['label'] == $p['match']))) ? STANDALONE NULL ;

        
$output $p['prefix'].FishForms::input_field($p).' '.$p['label'].$p['suffix'];

        return 
$output;
    }

    function 
radio_group()
    {
        static 
$_defaults = array(
            
'values' => array()
            , 
'name' => 'radiofield'
            
'sep' => "&nbsp;\n"
            
'match' => NULL
            
'default' => NULL
            
'source' => NULL
            
'group_prefix' => ''
            
'group_label' => NULL
            
'group_suffix' => ''
            
'format' => NULL
        
);
        static 
$_simple = array('name','values');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
$p['group_label'] === NULL)
        {
            
$p['group_label'] = FishText::labelize($p['name']);
        }
        
$p['match'] = FishForms::get_field_value($p['name'],$p['default'],$p['match'],$p['source']);
        
$outarr = array();
        foreach (
$p['values'] as $p['value'] => $p['label'])
        {
            
$outarr[] = FishForms::radio_field($p);
        }
        if (
$p['format'] == 'array')
        {
            return 
$outarr;
        }
        
$output $p['group_prefix']
            . 
$p['group_label']
            . 
' '
            
implode($p['sep'],$outarr)
            . 
$p['group_suffix']
        ;
        return 
$output;
    }


    
// string reset_field ([string name [, string value]])

    // This function returns an HTML reset field. A reset field returns
    // the current form to its original state.

    
function reset_field()
    {
        static 
$_defaults = array(
            
'type' => 'reset'
            
'name' => 'reset'
            
'value' => 'Reset'
        
);
        static 
$_simple = array('value','name');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        return 
FishForms::input_field($p);
    }

    
// string select_field ([string name [, array items [, string default value]]])

    // This function returns an HTML select field (a popup field).
    // If the optional second argument is an array, each key in the array
    // will be set to the value of an option of the select field, and
    // the corresponding value from the array will be the displayed string
    // for that option. If the key or the value from the array matches
    // the optional third argument, that option will be designated as the default
    // value of the select field.

    
function select_field()
    {
        static 
$_defaults = array(
            
'values' => array()
            , 
'name' => 'selectfield'
            
'default' => NULL
            
'match' => NULL
            
'source' => NULL
            
'label_match' => FALSE
            
'format' => NULL
            
'allowed' => array('Common','multiple','name','size','tabindex'
                
,'disabled'
            
)
        );
        static 
$_simple = array('name','values');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        
$attlist FishHTML::get_attlist($p);
        
$output "<select $attlist>\n";
        if (
$p['match'] === NULL)
        {
            
$p['match'] = FishForms::get_field_value($p['name'],$p['default'],$p['match'],$p['source']);
        }
        unset(
$p['allowed']);

        
$matchvalue $p['match'];
        
$matchlabel 'NOMATCH'.time();
        if (
$p['label_match'])
        {
            
$matchlabel $p['match'];
        }
        if (
$p['format'] == 'minimal')
        {
            foreach (
$p['values'] as $value => $label)
            {
                
$output .= "<option value='$value'";
                if (
$matchvalue == $value || $matchlabel == $label)
                {
                    
$output .= ' selected';
                }
                 
$output .= ">$label</option>\n";
            }
        }
        else
        {
            
$p['skip_selection'] = TRUE;
        if (
array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        if (
array_key_exists('allowed'$p))
            unset(
$p['allowed']);
            if (!
is_array($p['values']))
            {
                
var_dump($p['values']);
            }
            foreach (
$p['values'] as $p['value'] => $p['label'])
            {
                
$p['selected'] = NULL;
                if (empty(
$matchvalue))
                {
                    if (
$matchvalue === $p['value'])
                    {
                        
$p['selected'] = STANDALONE;
                    }
                }
                elseif (
$matchvalue == $p['value'])
                {
                    
$p['selected'] = STANDALONE;
                }
                elseif (empty(
$matchlabel))
                {
                    if (
$matchlabel === $p['label'])
                    {
                        
$p['selected'] = STANDALONE;
                    }
                }
                elseif (
$matchlabel == $p['label'])
                {
                    
$p['selected'] = STANDALONE;
                }
                
$output .= FishForms::option_tag($p)."\n";
            }
        }
        
$output .= "</select>\n";
        return 
$output;
    }

    function 
start_file_form()
    {
        
$p func_get_args();
        
$p[] = array('enctype' => 'multipart/form-data');
        return 
call_user_func_array(array('FishForms','start_form'),$p);
    }


    
// string start_form ([string action [, array attributes]])

    // This function returns an HTML <form> tag. If the first argument
    // is empty, the value of the predefined PHP variable PHP_SELF
    // is used for the 'action' attribute of the <form> tag. Other
    // attributes for the form can be specified in the optional second
    // argument; the default method of the form is "post".

    
function start_form()
    {
        static 
$_defaults = array(
            
'method' => 'POST'
            
'enctype' => 'application/x-www-form-urlencoded'
            
'allowed' => array('Common','accept','accept-charset','action'
                
'method','enctype','target','name'
            
)
        );
        static 
$_simple = array('action','method');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        
$attlist FishHTML::get_attlist($p);
        
$output "\n<form $attlist>\n";
        return 
$output;
    }


    
// string submit_field ([string name [, string value]])

    // This function returns an HTML submit field. The value of the field
    // will be the string displayed by the button displayed by the user's
    // browser. The default value is "Submit".

    
function submit_field()
    {
        static 
$_defaults = array(
            
'type' => 'submit'
            
'name' => 'submit'
            
'value' => 'Submit'
        
);
        static 
$_simple = array('value','name');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
//        FishError::trace('p=',$p);
        
if (array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        return 
FishForms::input_field($p);
    }


    
// string text_field ([string name [, string value [, int size [, int maximum length]]]])

    // This function returns an HTML text input field. The default size
    // of the field is 10. A value and maximum data length for the field
    // may be supplied.

    
function text_field()
    {
        static 
$_defaults = array(
            
'type' => 'text'
            
'size' => 40
            
'name' => 'textfield'
            
'label' => NULL
            
'default' => NULL
            
'value' => NULL
            
'source' => NULL
        
);
        static 
$_simple = array('name','label','default');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        if (
array_key_exists('_defaults'$p))
            unset(
$p['_defaults']);
        if (
array_key_exists('_simple'$p))
            unset(
$p['_simple']);
        if (
$p['label'] === NULL)
        {
            
$p['label'] = FishText::labelize($p['name']);
        }
        
$p['value'] = FishForms::get_field_value($p['name'],$p['default'],$p['value'],$p['source']);
        return 
FishForms::input_field($p);
    }

    
// string textarea_field([string name [, string value [, int cols [, int rows [, string wrap mode]]]]])

    // This function returns an HTML textarea field. The default size is
    // 50 columns and 10 rows, and the default wrap mode is 'soft', which means 
    // no hard newline characters will be inserted after line breaks in what
    // the user types into the field. The alternative wrap mode is 'hard',
    // which means that hard newlines will be inserted.

    
function textarea_field()
    {
        static 
$_defaults = array(
            
'name' => 'textareafield'
            
'cols' => 50
            
'rows' => 10
            
'wrap' => 'soft'
            
'default' => NULL
            
'value' => NULL
            
'source' => NULL
            
'allowed' => array('Common','wrap','accesskey','cols','name'
                
,'rows','tabindex'
            
)
        );
        static 
$_simple = array('name','default');
        
$p func_get_args();
        
$p FishArgs::parse_arguments($p$_simple$_defaults);
        
$p['value'] = FishForms::get_field_value($p['name'],$p['default'],$p['value'],$p['source']);
        
$attlist FishHTML::get_attlist($p);
        
$output "<textarea $attlist>{$p['value']}</textarea>";
        return 
$output;
    }

}
?>