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 value. Saturn tables callbacks are more isolated the WordPress filters, they are based on WordPress administration menu structure which utilizes callbacks. Before going through the waterfall, there are also menu_title, header and footer definitions similar to Saturn Tables list tables.

The menu definition callback is here:

function my_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'] = 'my_cars_input_form_definition'; $input_form_definitions['form_validation'] = 'my_cars_input_form_validation';
$input_form_definitions['run_query'] = 'my_cars_run_query';
$input_form_definitions['set_notices'] = 'my_cars_set_notices';
$input_form_definitions['process_post_vars'] = 'my_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 menu_title, header and footer are outputted as HTML content and the top and bottom as expected. menu_title will override the default menu_title.

The waterfall is as follows. These variables are then set with initial values.

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

Form Definition (callable)

array key: form_definition
returns array of array

The form_definition callable returns array $input_form for displaying the input form. 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 inputtextarea or dropdown. Use type to define HTML5 inputs for validation.

The label fields define the input labels. If required is set required will be noted in the input label.

Furthermore type is either an HTML5 input type, or a textarea or select.

For 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.

Radio and file inputs not currently supported.

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

function saturn_tables_cars_input_form_definition() {
	
	global $wpdb;
	
	if (count($wpdb->get_var("SHOW TABLES LIKE 'saturn_tables_cars'"))) {
		$countries = $wpdb->get_col( "SELECT DISTINCT country FROM saturn_tables_cars ORDER BY country" );
	} else {
		$countries = array();
	}
	
	$input_form['make'] = array('label'=> "Make", "required" => "", 'type'=>"text" );
	$input_form['model'] = array( 'label'=> "Model", "required" => "", 'type'=>"textarea", 'rows'=>"5", 'cols'=>"30", 'style'=>"max-width: 500px;");
	$input_form['mpg'] = array ('label'=> "MPG", "required" => "", 'type' => "number", 'step'=>".1");
	$input_form['cylinders'] = array ('label'=> "Cylinders", "required" => "", 'type' => "number", 'step'=>"1");
	$input_form['weight'] = array ('label'=> "Weight", "required" => "", 'type' => "number", 'step'=>"1");
	$input_form['model_year'] = array ('label'=> "Model Year", "required" => "", 'type' => "number", 'step'=>"1");
	$input_form['country'] = array ('label'=> "Country", "required" => "", 'type' => "select", 'options' => $countries , 'usekey' => false);
	
	return $input_form;
	
}

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>';

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>';

Notices (callable)

array key: notices
returns string

Once the query is run then the the waterfall continues rendering the notices The default value is an empty string indicating no notice. If notices is populated the value will be displayed above the input form.

function saturn_tables_cars_set_notices($input_form, $query_return, $notices) {	
	
	if (isset($post_vars['submit'])) {
	
		$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
	
		if ((!$id) && $query_return) {
			$notices[] = '<div class="notice notice-error is-dismissible"><p>' . __("There was a problem with the record insert.") . '</p></div>';			
		} elseif (($id) && $query_return) {			
			$notices[] = '<div class="notice notice-error is-dismissible"><p>' . __("There was a problem with the record update.") . '</p></div>';			
		} elseif ((!$id) && !$query_return) {			
			$notices[] = '<div class="notice notice-success is-dismissible"><p>' . __("A record was inserted.") . '</p></div>';			
		} elseif ($id && !$query_return) {
			$notices[] = '<div class="notice notice-success is-dismissible"><p>' . __("Record updated.") . '</p></div>';			
		}	
	}
	
	return $notices;
}

Process Post Vars (array)

array key: process_post_vars
returns array

The final step in the waterfall is readying and processing the $post_vars. If editing the form it will need to be populated. If a new record is entered usually it will be emptied. The $post_vars are used to populate the form.

function saturn_tables_cars_process_post_vars($input_form, $query_return, $post_vars) {
	
	global $wpdb;
	
	$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
	
	if (!$id && $query_return) {
		 //insert
		 $post_vars = array();		 
	} elseif ($id) {
		//update
		if (count($wpdb->get_var("SHOW TABLES LIKE 'saturn_tables_cars'"))) {
			$post_vars = $wpdb->get_row($wpdb->prepare("SELECT id, make, model, mpg, cylinders, weight, model_year, country FROM saturn_tables_cars WHERE id = %d", $id), ARRAY_A);		
		}
	}
	
	return $post_vars;
}

Run Query (callable)

array key: run_query
returns mixed

The query callable is run either inserting or updating data and is the first step in the waterfall. If you want to do PHP or database validation it can be done here. A false return value might imply a successful query, it is the default. If there are errors the return value might hold information for the notices callable which follows.

function saturn_tables_cars_run_query($input_form, $query_return) {
	
	global $wpdb;
	
	if (isset($_POST['submit'])) {
	
		$id = isset($_GET['id']) ? (int)$_GET['id'] : 0;
		
		foreach ($input_form as $key => $value) {
			if (isset($_POST[$key]))
					$post_vars[$key] = sanitize_text_field($_POST[$key]);
			}

		
		if ($id == 0) {
			 //insert new row
			 $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');
			 if (count($wpdb->get_var("SHOW TABLES LIKE 'saturn_tables_cars'"))) {
				$query_return = $wpdb->insert('saturn_tables_cars', $data, $formats);
				return false;
			 }			 
			 
		} elseif ($id > 0) {
			//update row
			$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');
			if (count($wpdb->get_var("SHOW TABLES LIKE 'saturn_tables_cars'"))) {
				$query_return = $wpdb->update('saturn_tables_cars', $data, $where, $data_formats, $where_formats );			
				return false;
			}
		}		
	}	
}