Input Forms

Saturn Tables provides an input or edit form structure based on hooks and arrays to easily construct custom input forms with validation, notices and processing. It is done in a waterfall passing successive variables to callbacks with return values similar to WordPress filters. Each callback takes in several values as parameters but only alters and returns one array value. Saturn tables callbacks are more isolated than WordPress filters, they are based on WordPress administration menu structure which utilizes callbacks.

The menu input form definition callback is here:

function saturn_tables_cars_add_edit_car_func() {

    $id = isset($_GET['id']) ? $_GET['id'] : 0;
    $input_form_definitions['menu_title'] = $id > 0 ? '<h1  class="wp-heading-inline">Edit Car</h1> <strong>[ID:' . $id . ']</strong>' : '<h1>Add Car</h1>';
    $input_form_definitions['header'] = $id > 0 ? '<p>Edit car below with this form.</p>' : '<p>Input new car with this form.</p>';
    $input_form_definitions['form_definition'] = 'saturn_tables_cars_input_form_definition';
    $input_form_definitions['form_validation'] = 'saturn_tables_cars_input_form_validation';
    $input_form_definitions['run_query'] = 'saturn_tables_cars_run_query';
    $input_form_definitions['set_notices'] = 'saturn_tables_cars_set_notices';
    $input_form_definitions['process_post_vars'] = 'saturn_tables_cars_process_post_vars';
    $input_form_definitions['footer'] = '<p>Powered by <a href="https://saturntables.com/" target="_blank">Saturn Tables</a></p>';  

    return $input_form_definitions;
}

The waterfall starts with these values.

$validation = false;        
$query_return = false;
$notices = false;
$post_vars = $_POST;

Menu Title (string)

array key: menu_title

The Saturn Tables input forms callable menu title array item will override the menu title defined in the menu declaration if set. This allows menu titles to be dynamic or to be removed if desired.

Behavior:

menu_title not set: Default menu from menu declaration
menu_title set and blank: No menu title displayed
menu_title defined: Overrides default menu title

Menu title in sample input form:

$id = isset($_GET['id']) ? $_GET['id'] : 0;
$input_form_definitions['menu_title'] = $id > 0 ? '<h1  class="wp-heading-inline">Edit Car</h1> <strong>[ID:' . $id . ']</strong>' : '<h1>Add Car</h1>';

Header (string)

array key: header

The header array item is a HTML string that is displayed between the menu title and the input form. It is displayed within the form so form variables can be embedded, any HTML content will be displayed. HTML is recommended and conditional logic may be used.

$id = isset($_GET['id']) ? $_GET['id'] : 0;
$input_form_definitions['header'] = $id > 0 ? '<p>Edit car below with this form.</p>' : '<p>Input new car with this form.</p>';

Form Definition (callable)

array key: form_definition
returns PHP array defining form inputs

The form_definition callable is called returning array $input_form at the beginning of the form input waterfall. In general, the $input_form array has some values which are used to define the form inputs and then other values become HTML input form tag attributes. Empty array values that are key only become singleton attributes. Specifically the key of the array becomes the name of the input, textarea or dropdown. The label and required_label fields define the input labels and required labels. Furthermore type is either an HTML5 input type, or a textarea or select. If the definition array is a select option the usekey boolean defines whether the select options will have value attributes or not, the options array is an array to populate select options and values. Finally, the array can always be set to a callback for other input form scenarios.

HTML5 types will validate data well and setting the required attribute with a blank value will make the HTML5 input required.

The form_definition sets the $input_form variable used in the waterfall.

function saturn_tables_cars_input_form_definition() {

    global $wpdb;

    $countries = $wpdb->get_col( "SELECT DISTINCT country FROM saturn_tables_cars ORDER BY country" );

    $input_form['action'] = array('type'=>"hidden", "value" => "postback" );
    $input_form['make'] = array('label'=> "Make", "required_label" => "", 'type'=>"text", "required" => "" );
    $input_form['model'] = array( 'label'=> "Model", "required_label" => "", 'type'=>"textarea", 'rows'=>"5", 'cols'=>"30", 'style'=>"max-width: 500px;", "required" => "");
    $input_form['mpg'] = array ('label'=> "MPG", "required_label" => "", 'type' => "number", 'step'=>".1", "required" => "");
    $input_form['cylinders'] = array ('label'=> "Cylinders", "required_label" => "", 'type' => "number", 'step'=>"1", "required" => "");
    $input_form['weight'] = array ('label'=> "Weight", "required_label" => "", 'type' => "number", 'step'=>"1", "required" => "");
    $input_form['model_year'] = array ('label'=> "Model Year", "required_label" => "", 'type' => "number", 'step'=>"1", "required" => "");
    $input_form['country'] = array ('label'=> "Country", "required_label" => "", 'type' => "select", 'options' => $countries, "required" => "" , 'usekey' => false);

    return $input_form;

}

Form Validation (callable)

Next the validation function is called returning $validation with $input_form and $post_vars and passed in continuing the waterfall.

The array values $validation[input_form_key]['error'] and $validation[input_form_key]['message'] as reserved for later use. Currently it is recommended that HTML5 form validation be used through input field types and the required attribute.

function saturn_tables_cars_input_form_validation($input_form, $validation, $post_vars) {

    return $validation;

}

Run Query (callable)

array key: run_query
returns a variable of choice

Then the query callable is run either inserting or updating based on the $validation return, $post_vars and the $input_form definition. A false return value might imply query errors. The sample code will return 1 on insert and update with change, 0 on an update with no change, and false if there is a query error.

function saturn_tables_cars_run_query($input_form, $validation, $post_vars, $query_return) {

    global $wpdb;

    if (isset($post_vars['action']) && $post_vars['action'] == "postback") {

        $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

        if ($id == 0) {

             $data = array('make' => $post_vars['make'], 'model' => $post_vars['model'], 'mpg' => $post_vars['mpg'], 'cylinders' => $post_vars['cylinders'], 'weight' => $post_vars['weight'], 'model_year' => $post_vars['model_year'], 'country' => $post_vars['country']);
             $formats = array('%s','%s','%f','%d','%d','%d','%s');   
             $query_return = $wpdb->insert('saturn_tables_cars', $data, $formats);

        } elseif ($id > 0) {

            $data = array('make' => $post_vars['make'], 'model' => $post_vars['model'], 'mpg' => $post_vars['mpg'], 'cylinders' => $post_vars['cylinders'], 'weight' => $post_vars['weight'], 'model_year' => $post_vars['model_year'], 'country' => $post_vars['country']);
            $where = array('id' => $id);                
            $data_formats =  $formats = array('%s','%s','%f','%d','%d','%d','%s');              
            $where_formats = array('%d');               
            $query_return = $wpdb->update('saturn_tables_cars', $data, $where, $data_formats, $where_formats );         
        }   
    }   
    return $query_return;
}

Notices (callable)

array key: notices
echos out notices

Once the query is run then the the waterfall continues rendering the notices. This time there are four values passed in $input_form, $validation, $post_vars and $query_return. Notices are set to echo out just like typical WordPress notices.

function saturn_tables_cars_set_notices($input_form, $validation, $post_vars, $query_return) {      

    if (isset($post_vars['action']) && $post_vars['action'] == "postback") {        

        $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

        if (($id == 0) && $query_return === false) {            
            echo '<div class="notice notice-error is-dismissible"><p>' . __("There was a problem with the record insert.") . '</p></div>';          
        } elseif (($id > 0) && $query_return === false) {           
            echo '<div class="notice notice-error is-dismissible"><p>' . __("There was a problem with the record update.") . '</p></div>';          
        } elseif (($id == 0) && $query_return !== false) {          
            echo '<div class="notice notice-success is-dismissible"><p>' . __("A record was inserted.") . '</p></div>';         
        } elseif (($id > 0) && $query_return !== false) {           
            echo '<div class="notice notice-success is-dismissible"><p>' . __("Record updated.") . '</p></div>';            
        }   
    }
}

Process Post Vars (array)

array key: process_post_vars
returns array of values to populate or not populate the form

The final step in the waterfall is readying and processing the $post_vars, if entering the form anew as an edit the form will need to be populated. The $post_vars are used to populate the form, usually during editing of records.

function saturn_tables_cars_process_post_vars($input_form, $validation, $post_vars, $query_return) {

    global $wpdb;

    $id = isset($_GET['id']) ? (int)$_GET['id'] : 0;

    if (($id == 0) && $query_return) {      
         $post_vars = array();       
    } elseif (($id > 0) && ($query_return || !isset($post_vars['action']))) {       
        $post_vars = $wpdb->get_row($wpdb->prepare("SELECT make, model, mpg, cylinders, weight, model_year, country FROM saturn_tables_cars WHERE id = %d", $id), ARRAY_A);
    }

    return $post_vars;
}

Footer (string)

array key: footer

The footer array item is a HTML string that is displayed after the input form. It is displayed within the form so form variables can be embedded, any HTML content will be displayed. HTML is recommended and conditional logic may be used.

$input_form_definitions['footer'] = '<p>Powered by <a href="https://saturntables.com/" target="_blank">Saturn Tables</a></p>';