FormFields[ $Field->GetName( ) ] = $Field;
}
public function AddFields( $Fields ) {
foreach( $Fields as $FieldName => $Field ) {
$this->FormFields[ $FieldName ] = $Fields[ $FieldName ];
}
}
public function SetValues( $FormValues ) {
foreach( $this->FormFields as $FieldName => $FieldValue ) {
if( isset( $FormValues[ $FieldName ] ) ) {
$this->FormFields[ $FieldName ]->SetValue( $FormValues[ $FieldName ] );
}
}
}
public function GetValues( ) {
$Values = array( );
foreach( $this->FormFields as $FieldKey => $FieldValue ) {
$Values[ $FieldKey ] = $this->FormFields[ $FieldKey ]->GetValue( );
}
return $Values;
}
public function GetErrors( &$ErrorStrings ) {
$Errors = array( );
foreach( $this->FormFields as $FieldKey => $FieldValue ) {
$Errors[ $FieldKey ] = $this->FormFields[ $FieldKey ]->GetErrors( $ErrorStrings );
}
return $Errors;
}
private $FormFields;
}
// Plain 'ole form field
// Can be used for basically any kind of form field
// text, radio buttons, checkboxes, dropdowns, whatever
class FormField {
function __construct( $Name, $Validators = array( ) ) {
$this->Name = $Name;
if( is_array( $Validators ) ) {
$this->Validators = $Validators;
} else {
$this->Validators = array( $Validators );
}
}
public function GetName( ) {
return $this->Name;
}
public function SetValue( $Value ) {
$this->Value = $Value;
}
public function GetValue( ) {
return $this->Value;
}
public function GetErrors( &$ErrorStrings ) {
$error = false;
foreach( $this->Validators as $Validator ) {
if( !$Validator->ValueIsValid( $this->Value ) ) {
$ErrorStrings[ $this->Name ] = $Validator->GetError( $this->Value );
$error = true;
}
}
return $error;
}
private $Name;
private $Value;
}
// Form field map is a special kind of form field;
// it contains a number of other form fields, each
// associated by a name. In my example, CD is a form
// field that maps to a band name, and an album name.
// it becomes useful only when you have nested form
// fields and in conjunction with FormFieldArray
class FormFieldMap extends FormField {
function __construct( $Name, $InnerFields ) {
parent::__construct( $Name );
foreach( $InnerFields as $InnerField ) {
$this->InnerFields[ $InnerField->GetName( ) ] = $InnerField;
}
}
function __clone( ) {
foreach( $this->InnerFields as $InnerFieldName => $InnerField ) {
$this->InnerFields[ $InnerFieldName ] = clone $this->InnerFields[ $InnerFieldName ];
}
}
public function SetValue( $Values ) {
foreach( $this->InnerFields as $InnerFieldName => $InnerField ) {
if( isset( $Values[ $InnerFieldName ] ) ) {
$this->InnerFields[ $InnerFieldName ]->SetValue( $Values[ $InnerFieldName ] );
}
}
}
public function GetValue( ) {
$Values = array( );
foreach( $this->InnerFields as $InnerFieldName => $InnerField ) {
$Values[ $InnerFieldName ] = $this->InnerFields[ $InnerFieldName ]->GetValue( );
}
return $Values;
}
public function GetErrors( &$ErrorStrings ) {
$errors = array( );
foreach( $this->InnerFields as $InnerFieldName => $InnerField ) {
$errors[ $InnerFieldName ] = $this->InnerFields[ $InnerFieldName ]->GetErrors( $ErrorStrings );
}
return $errors;
}
private $InnerFields;
}
// FormFieldArray is a form field that has one form field inside of it,
// but can have zero to many of that form field. In my example, 'CDs' has
// zero to many 'CD's inside it. Useful if a form can have a variable number
// of fields
class FormFieldArray extends FormField {
function __construct( $Name, $InnerField ) {
parent::__construct( $Name );
$this->InnerField = $InnerField;
$this->InnerFields = array( );
}
function __clone( ) {
$this->InnerField = clone $this->InnerField;
}
public function ValueIsValid( $Values ) {
if( is_array( $Values ) ) {
$isvalid = true;
foreach( $Values as $Value ) {
$isvalid = $isvalid && $this->InnerField->ValueIsValid( $Value );
}
return $isvalid;
} else {
return false;
}
}
public function SetValue( $Values ) {
$this->InnerFields = array( );
if( is_array( $Values ) ) {
foreach( $Values as $Value ) {
$newval = clone $this->InnerField;
$newval->SetValue( $Value );
$this->InnerFields[] = $newval;
}
}
}
public function GetValue( ) {
$Values = array( );
foreach( $this->InnerFields as $InnerField ) {
$Values[] = $InnerField->GetValue( );
}
return $Values;
}
public function GetErrors( &$ErrorString ) {
$errors = array( );
foreach( $this->InnerFields as $InnerField ) {
$errors[] = $InnerField->GetErrors( $ErrorString );
}
return $errors;
}
private $InnerField; // template field
private $InnerFields; // holds actual values
}
// Value Checkers check form fields for their validity
interface ValueChecker {
public function ValueIsValid( $Value );
public function GetError( );
}
// I was going to make more than just one ValueChecker,
// but it turns out that you can pretty much check anything
// with regular expressions
class RegexValueChecker implements ValueChecker {
// MatchCount can be an array of values where at least one must be matched,
// or it can be a scalar that must be matched
function __construct( $Regex, $MatchCount, $ErrorString ) {
$this->Regex = $Regex;
$this->MatchCount = $MatchCount;
$this->ErrorString = $ErrorString;
}
public function ValueIsValid( $Value ) {
$Matches = preg_match_all( $this->Regex, $Value, $Out );
if( is_array( $this->MatchCount ) ) {
$isvalid = false;
foreach( $this->MatchCount as $MatchVal ) {
$isvalid = $isvalid || ( $Matches == $MatchVal );
}
return $isvalid;
} else {
return $Matches == $this->MatchCount;
}
}
public function GetError( ) {
return $this->ErrorString;
}
private $Regex;
private $MatchCount;
private $ErrorString;
}
// create validators
$phonenumChecker = new RegexValueChecker( "/\d/", array( 7, 10, 11 ), "Phone numbers must have 7, 10, or 11 digits" );
$alphanumChecker = new RegexValueChecker( "/[^a-zA-Z0-9_\s]/", 0, "Only alphanumeric characters allowed" );
// create fields
$namefield = new FormField( "Name", $alphanumChecker );
$phonefield = new FormField( "Phone", $phonenumChecker );
$bandfield = new FormField( "Band", $alphanumChecker );
$albumfield = new FormField( "Album", $alphanumChecker );
$cdfield = new FormFieldMap( "CD", array( $bandfield, $albumfield ) );
$cdsfield = new FormFieldArray( "CDs", $cdfield );
// create form
$myform = new Form;
$myform->AddField( $namefield );
$myform->AddField( $phonefield );
$myform->AddField( $cdsfield );
$myform->SetValues( $_GET );
$ErrorStrings = array( );
$Values = $myform->GetValues( );
$Errors = $myform->GetErrors( $ErrorStrings );
$Template = new Smarty;
$Template->template_dir = './smarty/templates';
$Template->compile_dir = './smarty/templates_c';
$Template->cache_dir = './smarty/cache';
$Template->config_dir = './smarty/configs';
if( $_REQUEST[ "submit" ] ) {
$Template->assign( $Values );
$Template->assign( "Errors", $Errors );
$Template->assign( "ErrorStrings", $ErrorStrings );
}
$Template->display( "index.tpl" );
?>