spivurno
9/13/2012 - 10:11 PM

Gravity Wiz // Require All Columns of List Field

Gravity Wiz // Require All Columns of List Field

<?php
/**
 * Require All Columns of List Field
 * http://gravitywiz.com/require-all-columns-of-list-field/
 */
class GWRequireListColumns {

	private $field_ids;

	public static $fields_with_req_cols = array();

	function __construct($form_id = '', $field_ids = array(), $required_cols = array()) {

		$this->field_ids = ! is_array( $field_ids ) ? array( $field_ids ) : $field_ids;
		$this->required_cols = ! is_array( $required_cols ) ? array( $required_cols ) : $required_cols;

		if( ! empty( $this->required_cols ) ) {

			// convert values from 1-based index to 0-based index, allows users to enter "1" for column "0"
			$this->required_cols = array_map( function( $value ) {
				return $value - 1;
			}, $this->required_cols );

			if( ! isset( self::$fields_with_req_cols[$form_id] ) )
				self::$fields_with_req_cols[$form_id] = array();

			// keep track of which forms/fields have special require columns so we can still apply GWRequireListColumns
			// to all list fields and then override with require columns for specific fields as well
			self::$fields_with_req_cols[$form_id] = array_merge( self::$fields_with_req_cols[$form_id], $this->field_ids );

		}

		$form_filter = $form_id ? "_{$form_id}" : $form_id;
		add_filter("gform_validation{$form_filter}", array(&$this, 'require_list_columns'));

	}

	function require_list_columns($validation_result) {

		$form = $validation_result['form'];
		$new_validation_error = false;

		foreach($form['fields'] as &$field) {

			if(!$this->is_applicable_field($field, $form))
				continue;

			$values = rgpost("input_{$field['id']}");

			// If we got specific fields, loop through those only
			if( count( $this->required_cols ) ) {

				foreach($this->required_cols as $required_col) {
					if(empty($values[$required_col])) {
						$new_validation_error = true;
						$field['failed_validation'] = true;
						$field['validation_message'] = $field['errorMessage'] ? $field['errorMessage'] : 'All inputs must be filled out.';
					}
				}

			} else {

				// skip fields that have req cols specified by another GWRequireListColumns instance
				$fields_with_req_cols = rgar( self::$fields_with_req_cols, $form['id'] );
				if( is_array( $fields_with_req_cols ) && in_array( $field['id'], $fields_with_req_cols ) )
					continue;

				foreach($values as $value) {
					if(empty($value)) {
						$new_validation_error = true;
						$field['failed_validation'] = true;
						$field['validation_message'] = $field['errorMessage'] ? $field['errorMessage'] : 'All inputs must be filled out.';
					}
				}

			}
		}

		$validation_result['form'] = $form;
		$validation_result['is_valid'] = $new_validation_error ? false : $validation_result['is_valid'];

		return $validation_result;
	}

	function is_applicable_field($field, $form) {

		if($field['pageNumber'] != GFFormDisplay::get_source_page($form['id']))
			return false;

		if( GFFormsModel::get_input_type( $field ) != 'list' || RGFormsModel::is_field_hidden($form, $field, array()))
			return false;

		// if the field has already failed validation, we don't need to fail it again
		if(!$field['isRequired'] || $field['failed_validation'])
			return false;

		if(empty($this->field_ids))
			return true;

		return in_array($field['id'], $this->field_ids);
	}

}

// accepted parameters
// new GWRequireListColumns($form_id, $field_ids);
 
// apply to all list fields on all forms
new GWRequireListColumns();
 
// apply to all list fields on a specific form
# new GWRequireListColumns(4);
 
// apply to specific list field on a specific form
# new GWRequireListColumns(4, 2);
 
// apply to specific list fields (plural) on a specific form
# new GWRequireListColumns(4, array(2,3));

// require specific field columns on a specific form
new GWRequireListColumns( 240, 1, array( 2, 3 ) );