PHP Classes

File: SimpleForm.php

Recommend this page to a friend!
  Classes of rudie dirkx   ROW Simple Form   SimpleForm.php   Download  
File: SimpleForm.php
Role: Class source
Content type: text/plain
Description: SimpleForm class
Class: ROW Simple Form
Validate and display HTML forms
Author: By
Last change: remove framework dependancy
Date: 12 years ago
Size: 16,794 bytes
 

Contents

Class file image Download
<?php namespace row\form; use row\core\Options; use row\utils\Inflector; use row\Output; abstract class SimpleForm { public $_elements = array(); // internal cache abstract protected function elements( $defaults = null, $options = array() ); public $input = array(); public $errors = array(); public $output = array(); public $inlineErrors = true; public $elementWrapperTag = 'div'; public function validate( $data ) { $this->input = $data; $elements =& $this->useElements(); $validators = $output = array(); $this->_fire('pre_validate'); function murlencode($name, $k, $arr) { $out = array(); foreach ( $arr AS $k2 => $v ) { $out[] = $name . '['.$k.']['.$k2.']=' . urlencode((string)$v); } return implode('&', $out); } foreach ( $elements AS $name => &$element ) { $element['_name'] = $name; $this->elementTitle($element); if ( is_string($name) ) { // form element if ( !empty($element['required']) ) { if ( !$this->validateRequired($name, $element) ) { $this->errors[$name][] = $this->errorMessage('required', $element); } } if ( !empty($element['regex']) && empty($this->errors[$name]) ) { $match = preg_match('/^'.$element['regex'].'$/', (string)$this->input($name, '')); if ( !$match ) { $this->errors[$name][] = $this->errorMessage('regex', $element); } } if ( !empty($element['validation']) && empty($this->errors[$name]) && !empty($element['required']) ) { $fn = $element['validation']; if ( is_string($fn) ) { $validationFunction = 'validate'.ucfirst($fn); $fn = array($this, $validationFunction); } if ( is_callable($fn) ) { $r = call_user_func($fn, $this, $name); if ( false === $r || is_string($r) ) { $this->errors[$name][] = false === $r ? $this->errorMessage('custom', $element) : $r; } } } if ( isset($this->input[$name]) && !array_key_exists($name, $this->output) ) { $input = $this->input[$name]; $this->output($name, $input); $elName = $this->elementName($element); foreach ( (array)$input AS $k => $v ) { $output[] = is_array($v) ? murlencode($elName, $k, $v) : $elName . '=' . urlencode((string)$v); } } } else if ( isset($element['validation']) ) { // validator $validators[] = $element; } unset($element); } //print_r($output); $output = implode('&', $output); //var_dump($output); parse_str($output, $this->output); if ( 0 == count($this->errors) ) { foreach ( $validators AS $validator ) { if ( empty($validator['require']) || 0 == count(array_intersect((array)$validator['require'], array_keys($this->errors))) ) { //echo "\n do custom validator on [".implode(', ', (array)$validator['fields'])."] ...\n"; $v = $validator['validation']; $r = $v($this); if ( false === $r || is_string($r) ) { $error = false === $r ? $this->errorMessage('custom', $validator) : $r; foreach ( (array)$validator['fields'] AS $name ) { $this->errors[$name][] = $error; } } } } } if ( 0 == count($this->errors) ) { $this->_fire('post_validate'); return true; } return false; } public function validateOptions( $form, $name ) { $element =& $this->useElements(); $value = $this->input($name, ''); $options = $element['options']; foreach ( $options AS $k => $v ) { if ( $this->getOptionValue($k, $v) == $value ) { return true; } } return false; } public function validateEmail( $form, $name ) { $value = $form->input($name); return false !== filter_var($value, FILTER_VALIDATE_EMAIL); } public function validateDate( $form, $name ) { $value = $form->input($name); if ( 0 >= preg_match('/^(\d\d\d\d)-(\d\d?)-(\d\d?)$/', $value, $match) ) { return false; } $date = $match[1] . '-' . str_pad((string)(int)$match[2], 2, '0', STR_PAD_LEFT) . '-' . str_pad((string)(int)$match[3], 2, '0', STR_PAD_LEFT); $this->output($name, $date); } public function validateRequired( $name, $element ) { if ( !isset($this->input[$name]) ) { return false; } $length = is_array($this->input[$name]) ? count($this->input[$name]) : strlen(trim((string)$this->input[$name])); $minlength = isset($element['minlength']) ? (int)$element['minlength'] : 1; return $length >= $minlength; } public function errorMessage( $type, $element ) { $this->elementTitle($element); $title = $element['title']; switch ( $type ) { case 'required': return 'Field "'.$title.'" is required'; break; case 'regex': return 'Field "'.$title.'" has invalid format'; break; case 'custom': $fields = !isset($element['fields']) ? array($element['_name']) : (array)$element['fields']; foreach ( $fields AS &$name ) { $name = $this->_elements[$name]['title']; unset($name); } return isset($element['message']) ? $element['message'] : 'Validation failed for: "'.implode('", "', $fields).'"'; break; } return 'Unknown type of error for field "'.$title.'".'; } public function errors() { $errors = array(); foreach ( $this->errors AS $errs ) { $errors = array_merge($errors, array_filter($errs)); } return array_unique($errors); } public function error( $elementName, $error = ' error', $noError = ' no-error' ) { return isset($this->errors[$elementName]) ? $error : $noError; } public function input( $name, $alt = '' ) { return isset($this->input[$name]) ? $this->input[$name] : $alt; } public function output( $name, $value = null ) { if ( 1 < func_num_args() ) { return $this->output[$name] = $value; } return isset($this->output[$name]) ? $this->output[$name] : ''; } public function splitOutput( $lists ) { $output = array(); foreach ( $lists AS $listName => $fields ) { $output[$listName] = array(); is_array($fields) or $fields = explode(',', $fields); foreach ( $fields AS $fieldName ) { if ( array_key_exists($fieldName, $this->output) ) { $output[$listName][$fieldName] = $this->output[$fieldName]; } } } return $output; } public function renderGridElement( $name, $element ) { $html = "\n".'<table class="grid">'."\n"; $html .= ' <tr>'."\n"; $html .= ' <th class="corner"></th>'."\n"; foreach ( $element['horizontal'][1] AS $k => $hLabel ) { $html .= ' '.$this->renderGridHorizontalTH($element, $hLabel)."\n"; } $html .= ' </tr>'."\n"; foreach ( $element['vertical'][1] AS $vKey => $vLabel ) { $vKey = $this->getOptionValue($vKey, $vLabel); $html .= ' <tr>'."\n"; $html .= ' '.$this->renderGridVerticalTH($element, $vLabel)."\n"; foreach ( $element['horizontal'][1] AS $hKey => $hLabel ) { $hKey = $this->getOptionValue($hKey, $hLabel); $sub = '?'; $fn = 'renderGrid'.$element['subtype']; if ( is_callable($method = array($this, $fn)) ) { list($xValue, $yValue) = empty($element['reverse']) ? array($vKey, $hKey) : array($hKey, $vKey); // $sub = $this->$fn($name.'__'.$xValue.'[]', $yValue); $sub = $this->$fn($element, $xValue, $yValue); } $html .= ' <td>'.$sub.'</td>'."\n"; } $html .= ' </tr>'."\n"; } $html .= '</table>'."\n"; return $this->renderElementWrapperWithTitle($html, $element); } protected function renderGridHorizontalTH( $element, $label ) { $html = '<th class="horizontal">'.$label.'</th>'; return $html; } protected function renderGridVerticalTH( $element, $label ) { $html = '<th class="vertical">'.$label.'</th>'; return $html; } protected function renderGridOptions( $element, $xValue, $yValue ) { $name = $element['_name']; $options = $element['options']; $dummy = isset($element['dummy']) ? $element['dummy'] : ''; $value = isset($this->input[$name][$xValue][$yValue]) ? (array)$this->input[$name][$xValue][$yValue] : array(); $elName = $name."[$xValue][$yValue]"; $html = $this->renderSelect($elName, $options, $value, $dummy); return $html; } protected function renderGridCheckbox( $element, $xValue, $yValue ) { $name = $element['_name']; $value = isset($this->input[$name][$xValue]) ? (array)$this->input[$name][$xValue] : array(); $checked = in_array($yValue, $value) ? ' checked' : ''; $html = '<input type="checkbox" name="'.$name.'['.$xValue.'][]" value="'.$yValue.'"'.$checked.' />'; return $html; } /* public function renderGridCheckboxElement( $elementName, $elementValue ) { $formValue = $this->input(trim($elementName, ']['), array()); $checked = in_array($elementValue, $formValue) ? ' checked' : ''; $html = '<input type="checkbox" name="'.$elementName.'" value="'.$elementValue.'"'.$checked.' />'; return $html; }*/ public function renderRadioElement( $name, $element ) { $type = $element['type']; $elName = $name; $checked = $this->input($name, null); $options = array(); foreach ( (array)$element['options'] AS $k => $v ) { $k = $this->getOptionValue($k, $v); $options[] = '<span class="option"><label><input type="radio" name="'.$elName.'" value="'.$k.'"'.( $checked === $k ? ' checked' : '' ).' /> '.$v.'</label></span>'; } $html = implode(' ', $options); return $this->renderElementWrapperWithTitle($html, $element); } public function renderCheckboxElement( $name, $element ) { $elName = $name; $checked = null !== $this->input($name, null) ? ' checked' : ''; $value = isset($element['value']) ? ' value="'.Output::html($element['value']).'"' : ''; $input = '<label><input type="checkbox" name="'.$elName.'"'.$value.$checked.' /> '.$element['title'].'</label>'; $html = '<span class="input">'.$input.'</span>'; if ( !empty($element['description']) ) { $html .= ' '; $html .= '<span class="description">'.$element['description'].'</span>'; } return $this->renderElementWrapper($html, $element); } public function renderCheckboxesElement( $name, $element ) { $elName = $name.'[]'; $checked = (array)$this->input($name, array()); $options = array(); foreach ( $element['options'] AS $k => $v ) { $k = $this->getOptionValue($k, $v); $options[] = '<span class="option"><label><input type="checkbox" name="'.$elName.'" value="'.$k.'"'.( in_array($k, $checked) ? ' checked' : '' ).' /> '.$v.'</label></span>'; } $html = implode(' ', $options); return $this->renderElementWrapperWithTitle($html, $element); } public function renderDropdownElement( $name, $element, $wrapper = true ) { return $this->renderOptionsElement($name, $element, $wrapper); } public function renderOptionsElement( $name, $element, $wrapper = true ) { $value = $this->input($name, 0); $elName = $name; $dummy = isset($element['dummy']) ? $element['dummy'] : ''; $html = $this->renderSelect($elName, $element['options'], $value, $dummy); return $this->renderElementWrapperWithTitle($html, $element); } protected function renderSelect( $elName, $options, $value = '', $dummy = '' ) { $html = '<select name="'.$elName.'">'; if ( $dummy ) { $html .= '<option value="'.$this->getDummyOptionValue().'">'.$dummy.'</option>'; } foreach ( (array)$options AS $k => $v ) { $k = $this->getOptionValue($k, $v); $html .= '<option value="'.$k.'"'.( (string)$k === $value ? ' selected' : '' ).'>'.$v.'</option>'; } $html .= '</select>'; return $html; } protected function getDummyOptionValue( $element = null ) { return ''; } protected function getOptionValue( $k, $v ) { if ( is_a($v, '\row\database\Model') ) { $k = implode(',', $v->_pkValue()); } return $k; } public function renderTextElement( $name, $element ) { $type = $element['type']; $elName = $name; $value = $this->input($name); $html = '<input type="'.$type.'" name="'.$elName.'" value="'.$value.'" />'; return $this->renderElementWrapperWithTitle($html, $element); } public function renderTextareaElement( $name, $element ) { $value = $this->input($name); $elName = $name; $options = Options::make($element); $rows = $options->rows ? ' rows="'.$options->rows.'"' : ''; $cols = $options->cols ? ' cols="'.$options->cols.'"' : ''; $html = '<textarea'.$rows.$cols.' name="'.$elName.'">'.$value.'</textarea>'; return $this->renderElementWrapperWithTitle($html, $element); } public function renderMarkupElement( $name, $element ) { $options = Options::make(Options::make($element)); $inside = $options->inside ?: $options->text; if ( $inside ) { return '<'.$this->elementWrapperTag.' class="form-element markup '.$name.'">'.$inside.'</'.$this->elementWrapperTag.'>'; } else if ( $options->outside ) { return $options->outside; } return ''; } // This method is now absolutely useless as without it the exact same thing would happen public function renderPasswordElement( $name, $element ) { $element['type'] = 'password'; return $this->renderTextElement($name, $element); } public function &useElements() { if ( !$this->_elements ) { $this->_elements = $this->elements(); } return $this->_elements; } public function render( $withForm = true, $options = array() ) { $elements =& $this->useElements(); // Render 1 element? if ( is_string($withForm) && isset($this->_elements[$withForm]) ) { // First argument is element name, so render only that element return $this->renderElement($withForm, $this->_elements[$withForm]); } $index = 0; $html = ''; foreach ( $elements AS $name => $element ) { if ( is_string($name) || ( isset($element['type']) && in_array($element['type'], array('markup')) ) ) { $element['_name'] = $name; $element['_index'] = $index++; $html .= $this->renderElement($name, $element); $html .= $this->elementSeparator(); } } if ( $withForm ) { $options = Options::make($options); $method = $options->get('action', 'post'); $action = Output::url($this->application->_uri); $html = '<form method="'.$method.'" action="'.$action.'">' . $this->elementSeparator() . $html.$this->renderButtons() . $this->elementSeparator() . '</form>'; } return $html; } public function renderElement( $name, $element ) { $this->elementTitle($element); if ( empty($element['type']) ) { return ''; } $type = $element['type']; $renderFunction = 'render'.ucfirst($type).'Element'; $renderMethod = array($this, $renderFunction); if ( !empty($element['render']) ) { $renderMethod = $element['render']; } if ( is_callable($renderMethod) ) { return call_user_func($renderMethod, $name, $element); } return $this->renderTextElement($name, $element); } public function elementName( $element ) { $name = $element['_name']; if ( isset($element['name']) ) { $name = $element['name']; } else if ( isset($element['type']) && in_array($element['type'], array('checkboxes')) ) { $name .= '[]'; } return $name; } public function renderButtons() { return '<'.$this->elementWrapperTag.' class="form-submit"><input type=submit></'.$this->elementWrapperTag.'>'; } public function renderElementWrapper( $html, $element ) { $name = $element['_name']; $description = empty($element['description']) ? '' : '<span class="description">'.$element['description'].'</span>'; return '<'.$this->elementWrapperTag.' class="form-element '.$element['type'].' '.$name.$this->error($name).'">'.$html.'</'.$this->elementWrapperTag.'>'; } public function renderElementWrapperWithTitle( $input, $element ) { $name = $element['_name']; $description = empty($element['description']) ? '' : '<span class="description">'.$element['description'].'</span>'; $error = $this->inlineErrors && isset($this->errors[$name]) ? '<span class="error">'.$this->errors[$name][0].'</span>' : ''; $html = '<label>'.$element['title'].'</label><span class="input">'.$input.'</span>'.$error.$description; return $this->renderElementWrapper($html, $element); } public function elementSeparator() { return "\n\n"; } public function elementTitle( &$element ) { if ( empty($element['title']) ) { $element['title'] = $this->nameToTitle($element['_name']); } } public function nameToTitle( $name ) { return Inflector::spacify($name); // 'beautify' } public function __tostring() { return $this->render(); } }