@ 2013-07-30T13:27:08Z <?php
class Stuff
{
public static function countObjTypes( array $data, array $types )
{
$return['Other'] = 0;
foreach ( $types as $type )
$return[$type] = 0;
foreach ( ( array ) $data as $obj ) {
$set = false;
array_walk( $types, function( $type ) use ( $obj, &$return, &$set )
{
if ( is_a( $obj, $type ) ) {
$return[$type]++;
$set = true;
}
} );
if ( !$set )
$return['Other']++;
}
return $return;
}
public static function getArrayValueByPath($array, $path) {
#$path = (array) array_filter( $path );
if( !empty( $path ) ) {
foreach ( $path as $key ) if( !isset( $array[$key] ) ) return NULL; $array = $array[$key];
return $array;
} else {
return false;
}
}
}
class formRenderer {
protected $dom;
public function __construct() { $this->dom = new DOMDocument; }
public function checkData( $data ) {
if( isset( $data[ 'node' ] ) )
throw new Exception('Invalid data, contained node');
return $data;
}
public function save( $type = 'HTML' ) {
$function = 'save'.strtoupper( $type );
return $this->dom->$function();
}
public function base( $data ) {
extract( $this->checkData( $data ) );
$node = $this->dom->createElement( 'input' );
$node->setAttribute( 'name', $name );
$node->setAttribute( 'id', $name );
$node->setAttribute( 'type', $type );
if( isset( $classes ) )
$node->setAttribute( 'class', $classes );
if( isset ( $value ) )
$node->setAttribute( 'value', $value );
if( isset ( $autocomplete ) )
$node->setAttribute( 'autocomplete', $autocomplete );
$this->form->appendChild( $node );
return $this->dom;
}
public function Label( $data ) {
extract( $this->checkData( $data ) );
$node = $this->dom->createElement( 'label' );
$node->setAttribute( 'for', $for );
$textNode = $this->dom->createDocumentFragment();
$textNode->appendXML( $value );
$node->appendChild( $textNode );
$this->form->appendChild( $node );
return $this->dom;
}
public function Form( $data ) {
extract( $this->checkData( $data ) );
$this->form = $this->dom->createElement( 'form' );
$this->form->setAttribute( 'method', $method );
$this->form->setAttribute( 'name', $name );
$this->dom->appendChild( $this->form );
return $this->dom;
}
public function HTML( $data ) {
extract( $this->checkData( $data ) );
$node = $this->dom->createDocumentFragment();
$node->appendXML( $html );
$this->form->appendChild( $node );
return $this->dom;
}
}
class Form
{
protected $name;
protected $type;
protected $data;
protected $structure;
protected $formRenderer;
public function __construct( $name , $method = 'POST' )
{
$cleanMethod = strtoupper( $method );
if ( $cleanMethod == 'POST' || $cleanMethod == 'GET' ) {
$this->method = $cleanMethod;
}
else
throw new Exception( "Unknown method requested for form $name");
$this->name = $name;
$this->collectData( );
}
private function collectData( )
{
$dataVar = '_'.$this->method;
if ( !empty( $GLOBALS[$dataVar] ) )
$this->data = $GLOBALS[$dataVar][$this->name];
}
public function addField( Field $field )
{
return $this->structure[] = $field->setForm( $this->name, $this->data );
}
public function addGroup( Group $group )
{
return $this->structure[] = $group->setForm( $this->name, $this->data );
}
public function render( formRenderer $renderer = NULL ) {
$this->renderer = ( isset( $renderer ) ) ? $renderer : new formRenderer;
$this->renderer->Form( array( 'method' => $this->method, 'name' => $this->name ) );
$renderer = $this->renderer;
foreach( $this->structure as $structure )
$renderer = $structure->render( $renderer );
return $renderer->save();
}
public function isSubmitted( )
{
// Check whether we have GET/POST data for some stuff, which will tell us if it was submitted
return ( isset( $this->data ) );
}
public function validate( )
{
foreach( $this->structure as $structure )
$structure->validate();
// Loop through validators. Pass in $data['FieldName'];
// Or maybe, get fields to validate themself, using validators. Point is, each $data == a value for a $this->fields
}
}
abstract class Group
{
protected $data;
protected $structure = array();
public function addFeild( Field $field )
{
$this->structure[] = $field;
}
public function setForm( $name, $data ) {
$this->data = $data;
foreach( $this->structure as $obj ) $obj->setForm( $name, $data );
return $this;
}
public function render( $renderer ) {
$dataCount = array();
foreach( $this->structure as $obj ) $dataCount[] = $obj->getDataGroup( true );
$iterations = ( max( $dataCount ) === 0 ) ? 1 : max( $dataCount ) ;
for ( $i = 0; $i < $iterations ; $i++ ) {
foreach( $this->structure as $obj ) { $obj->setIteration( $i ); $obj->render( $renderer ); }
}
return $renderer;
}
public function validate( ) {
foreach( $this->structure as $obj ) $obj->validate( );
}
}
class QuestionGroup extends Group
{
public function __construct( LabelField $label, Field $input ) {
$this->structure[0] = $label;
$this->structure[1] = $input;
}
}
class HoneyPotGroup extends Group
{
public function __construct( HoneyPotField $timeCheck, HoneyPotField $empty ) {
$this->structure[0] = $timeCheck;
$this->structure[1] = $empty;
}
}
abstract class Field
{
protected $vars = array();
private static $id = 0;
private $iteration = 0;
private $validators = array( );
private $staticValue = FALSE;
private $validate = FALSE;
private $data;
final public function setName( ) {
if( !isset( $this->vars['name'] ) )
{
$this->uid = self::$id++;
return $this->vars['name'] = $this->formName.'['.$this->uid.'][]';
}
else
{
throw new Exception("Attempted to create unique, unique already excists");
}
}
final public function setData( ) {
$this->data = Stuff::getArrayValueByPath( $this->formData, array( $this->uid ) );
}
final public function setIteration( $iteration = NULL) {
$this->iteration = $iteration;
}
final public function getDataGroup( $count = FALSE ) {
if( $count )
return count( array_filter( (array) $this->data ) );
else
return $this->data;
}
public function setType( $type )
{
$this->vars['type'] = $type;
}
public function setValue( $value, $type = NULL )
{
if( isset( $type ) )
$this->vars['value'.ucfirst( $type )] = $value;
else
$this->vars['value'] = $value;
}
public function getValue( $type = NULL )
{
if( isset( $type ) )
{
if( isset( $this->vars['value'.ucfirst( $type )] ) )
{
return $this->vars['value'.ucfirst( $type )];
}
} else {
return $this->vars['value'];
}
return NULL;
}
public function getValidatorValue() {
$value = $this->getValue( 'validator' );
if( isset( $value ) ) return $this->getValue( 'validator' );
else return $this->getValue();
}
public function setStaticValue( $value ) {
$this->staticValue = TRUE;
$this->setValue( $value );
}
public function setForm( $name, $data )
{
$this->formData = $data;
$this->formName = $name;
$this->setName();
$this->setData();
return $this;
}
public function validator( Validator $validator )
{
$this->validators[] = $validator;
}
public function validate( )
{
$this->validate = TRUE;
// if( $this->data )
// {
// foreach( $this->data as $value ) {
// foreach ( $this->validators as $validator ) {
// $validator->setValue( $value );
// $validator->validate( );
// }
// }
// }
}
public function render( $renderer ) {
$function = ucwords( $this->vars['type'] );
$value = Stuff::getArrayValueByPath( $this->data, array( $this->iteration ) );
if( $this->staticValue === FALSE ) $this->setValue( $value );
else $this->setValue( $value, 'validator' );
if( $this->validate )
{
foreach( $this->validators as $validator )
{
$validator->setValue( $this->getValidatorValue() );
var_dump( $validator->validate() );
}
}
if( method_exists( $renderer, $function ) )
$renderer->$function( $this->vars );
else
$renderer->base( $this->vars );
return $renderer;
}
}
class ActionField extends Field
{
public function __construct( $value = NULL )
{
$this->vars['type'] = 'submit';
if( isset( $value ) )
$this->vars['value'] = $value;
}
}
class UploadField extends Field {
public function __construct() {
$this->vars['type'] = 'file';
}
}
class LabelField extends Field {
public function __construct( $text = 'Untitled' ) {
$this->vars['type'] = 'label';
$this->setStaticValue( $text );
}
public function setForm( $name, $data )
{
parent::setForm( $name, $data );
$this->vars['for'] = $this->formName.'['.($this->uid + 1).'][]';
return $this;
}
}
class TextField extends Field {
public function __construct() {
$this->vars['type'] = 'text';
}
}
class HtmlField extends Field {
public function __construct( $html ) {
$this->vars['type'] = 'html';
$this->vars['html'] = $html;
}
}
class HiddenField extends Field {
public function __construct() {
$this->vars['type'] = 'hidden';
}
}
class HoneyPotField extends Field {
public function __construct( $value = NULL ) {
$this->vars['type'] = 'text';
$this->vars['classes'] = 'hc';
$this->vars['autocomplete'] = 'off';
$this->setStaticValue( $value );
}
}
class InputField extends Field {
public function __construct( $type ) {
$this->vars['type'] = $type;
}
}
class Validator
{
protected $failureText = array( );
protected $results = array( );
protected $rules = array( );
private $valid = TRUE;
final public function __construct( Rule $rule )
{
$this->rules[] = $rule;
return $this;
}
final public function addRule( Rule $rule )
{
$this->rules[] = $rule;
return $this;
}
public function valid( $returnFailureText = false )
{
return ( $returnFailureText ) ? $this->failureText[] = $returnFailureText : $this->valid;
}
private function invalidate( $failureText )
{
$this->valid( $failureText );
$this->valid = false;
}
public function setValue( $value )
{
foreach( $this->rules as $rule ) $rule->setValue( $value );
}
public function validate( )
{
foreach ( $this->rules as $rule ) {
$result = $this->results[] = $rule->validate( );
if ( $result === FALSE ) {
$this->invalidate( $rule->getFailureText() );
}
}
$this->getErrors();
return $this->valid;
}
public function getErrors() {
return $this->failureText;
}
}
abstract class Rule
{
protected $limit;
protected $value;
protected $failureText;
final public function __construct( $failureText, $limit = NULL, $value = NULL )
{
$this->failureText = $failureText;
$this->limit = $limit;
$this->value = $value;
}
final public function setValue( $value )
{
$this->value = $value;
return $this;
}
final public function getFailureText() {
return $this->failureText;
}
}
class GreaterThanRule extends Rule
{
public function validate( )
{
return $this->result = ( $this->value > $this->limit );
}
}
class LessThanRule extends Rule
{
public function validate( )
{
return $this->result = ( $this->value < $this->limit );
}
}
class ValidEmailRule extends Rule
{
public function validate( )
{
return $this->result = filter_var( $this->value, FILTER_VALIDATE_EMAIL );
}
}
class ValidUrlRule extends Rule
{
public function validate( )
{
return $this->result = filter_var( $this->value, FILTER_VALIDATE_URL );
}
}
class ValidNameRule extends Rule
{
public function validate( )
{
return $this->result = ctype_print( $this->value );
}
}
class NumericRule extends Rule
{
public function validate( )
{
return $this->result = is_numeric( $this->value );
}
}
class TextRule extends Rule
{
public function validate( )
{
return $this->result = ctype_alpha( $this->value );
}
}
class StringLengthGreaterThanRule extends Rule
{
public function validate( )
{
return $this->result = ( strlen( $this->value ) > $this->limit );
}
}
class StringLengthLessThanRule extends Rule
{
public function validate( )
{
return $this->result = ( strlen( $this->value ) < $this->limit );
}
}
class DateCheckRule extends Rule
{
public function validate( )
{
return $this->result = strtotime( $this->value );
}
}
class HoneyPotTimeRule extends Rule
{
public function validate( )
{
$limit = ( isset( $this->limit ) ) ? $this->limit : 2;
return $this->result = ( ( $this->value + $limit ) <= time() );
}
}
class EqualRule extends Rule
{
public function validate( )
{
return $this->result = ( $this->value === $this->limit );
}
}
// An example of how to use it
$form = new Form( 'Form', 'post' );
$honeyPot1 = new HoneyPotField( time() );
$honeyPot1->validator( new Validator( new HoneyPotTimeRule( 'This form was filled in too quickly, assumed bot, please allow 2 seconds to fill in the form' ) ) );
$honeyPot2 = new HoneyPotField();
$honeyPot2->validator( new Validator( new EqualRule( 'This field was unexpectedly filled in, assumed bot', '' ) ) );
$q1l = new LabelField( 'Question 1' );
$q1 = new InputField( 'text' );
$q2l = new LabelField( 'Question 2' );
$q2 = new InputField( 'text' );
$form->addGroup( new HoneyPotGroup( $honeyPot1, $honeyPot2 ) );
$form->addGroup( new QuestionGroup( $q1l, $q1 ) );
$form->addGroup( new QuestionGroup( $q2l, $q2 ) );
$form->addField( new UploadField( 'text' ) );
$form->addField( new ActionField( 'Send' ) );
if( $form->isSubmitted() )
$form->validate( );
echo $form->render( ); // outputs the form + elements
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).
Version System time (s) User time (s) Memory (MiB) 7.1.0 0.010 0.063 22.54 7.0.14 0.007 0.063 22.21 7.0.11 0.007 0.083 20.24 7.0.10 0.010 0.077 20.25 7.0.9 0.017 0.070 20.20 7.0.8 0.013 0.073 20.19 7.0.7 0.017 0.040 20.21 7.0.6 0.003 0.090 20.31 7.0.5 0.010 0.073 20.34 7.0.4 0.007 0.070 19.80 7.0.3 0.013 0.073 19.86 7.0.2 0.020 0.070 19.82 7.0.1 0.007 0.083 19.73 7.0.0 0.003 0.083 19.85 5.6.28 0.007 0.073 21.36 5.6.26 0.013 0.073 20.89 5.6.25 0.010 0.050 20.83 5.6.24 0.007 0.083 20.75 5.6.23 0.013 0.073 20.99 5.6.22 0.003 0.090 20.80 5.6.21 0.010 0.070 20.84 5.6.20 0.003 0.093 20.85 5.6.19 0.010 0.040 20.90 5.6.18 0.000 0.090 20.86 5.6.17 0.007 0.080 20.83 5.6.16 0.013 0.063 20.94 5.6.15 0.010 0.070 20.73 5.6.14 0.010 0.067 20.86 5.6.13 0.003 0.083 20.85 5.6.12 0.013 0.080 20.78 5.6.11 0.007 0.080 20.78 5.6.10 0.007 0.087 20.78 5.6.9 0.017 0.067 20.77 5.6.8 0.003 0.077 20.28 5.6.7 0.010 0.070 20.23 5.6.6 0.007 0.077 20.29 5.6.5 0.017 0.063 20.23 5.6.4 0.013 0.057 20.15 5.6.3 0.010 0.077 20.29 5.6.2 0.003 0.080 20.20 5.6.1 0.013 0.040 20.14 5.6.0 0.003 0.087 20.19 5.5.38 0.010 0.077 20.75 5.5.37 0.013 0.077 20.59 5.5.36 0.007 0.040 20.74 5.5.35 0.010 0.080 20.76 5.5.34 0.023 0.067 21.27 5.5.33 0.027 0.030 21.19 5.5.32 0.003 0.043 21.05 5.5.31 0.013 0.077 21.06 5.5.30 0.007 0.073 21.13 5.5.29 0.013 0.043 21.22 5.5.28 0.003 0.090 20.94 5.5.27 0.007 0.067 21.15 5.5.26 0.007 0.050 21.14 5.5.25 0.007 0.083 21.00 5.5.24 0.017 0.073 20.62 5.5.23 0.007 0.077 20.62 5.5.22 0.007 0.080 20.42 5.5.21 0.007 0.080 20.61 5.5.20 0.007 0.077 20.50 5.5.19 0.003 0.080 20.54 5.5.18 0.003 0.077 20.29 5.5.16 0.013 0.067 20.54 5.5.15 0.007 0.067 20.43 5.5.14 0.000 0.077 20.58 5.5.13 0.010 0.073 20.49 5.5.12 0.007 0.067 20.40 5.5.11 0.017 0.073 20.39 5.5.10 0.017 0.067 20.49 5.5.9 0.007 0.077 20.49 5.5.8 0.003 0.057 20.23 5.5.7 0.007 0.080 20.21 5.5.6 0.010 0.047 20.37 5.5.5 0.010 0.083 20.25 5.5.4 0.007 0.050 20.21 5.5.3 0.017 0.077 20.36 5.5.2 0.013 0.077 20.36 5.5.1 0.013 0.073 20.50 5.5.0 0.010 0.077 20.46 5.4.45 0.007 0.083 19.52 5.4.44 0.013 0.073 19.84 5.4.43 0.010 0.073 19.49 5.4.42 0.007 0.080 19.50 5.4.41 0.003 0.047 19.32 5.4.40 0.007 0.073 19.36 5.4.39 0.010 0.073 19.14 5.4.38 0.010 0.070 19.27 5.4.37 0.007 0.060 19.16 5.4.36 0.010 0.067 19.18 5.4.35 0.010 0.063 19.46 5.4.34 0.017 0.070 19.26 5.4.32 0.013 0.060 19.14 5.4.31 0.013 0.073 19.23 5.4.30 0.023 0.060 19.17 5.4.29 0.007 0.047 19.35 5.4.28 0.013 0.040 19.19 5.4.27 0.003 0.080 19.14 5.4.26 0.007 0.057 19.10 5.4.25 0.013 0.040 19.45 5.4.24 0.007 0.067 19.46 5.4.23 0.013 0.063 19.28 5.4.22 0.013 0.077 19.19 5.4.21 0.007 0.080 19.45 5.4.20 0.010 0.077 19.19 5.4.19 0.003 0.077 19.27 5.4.18 0.003 0.080 19.45 5.4.17 0.007 0.073 19.45 5.4.16 0.010 0.067 19.36 5.4.15 0.007 0.073 19.15 5.4.14 0.010 0.067 16.55 5.4.13 0.003 0.047 16.68 5.4.12 0.000 0.080 16.63 5.4.11 0.007 0.070 16.71 5.4.10 0.010 0.073 16.86 5.4.9 0.003 0.073 16.77 5.4.8 0.000 0.080 16.75 5.4.7 0.003 0.043 16.79 5.4.6 0.020 0.060 16.66 5.4.5 0.003 0.047 16.66 5.4.4 0.017 0.033 16.77 5.4.3 0.010 0.063 16.49 5.4.2 0.013 0.073 16.61 5.4.1 0.007 0.070 16.72 5.4.0 0.013 0.070 16.18 5.3.29 0.010 0.060 15.31 5.3.28 0.010 0.067 15.09 5.3.27 0.003 0.047 15.16 5.3.26 0.003 0.073 15.21 5.3.25 0.003 0.073 15.12 5.3.24 0.013 0.070 15.11 5.3.23 0.010 0.077 15.03 5.3.22 0.013 0.073 15.06 5.3.21 0.003 0.083 15.00 5.3.20 0.000 0.073 14.96 5.3.19 0.010 0.077 15.21 5.3.18 0.013 0.063 14.99 5.3.17 0.013 0.060 15.11 5.3.16 0.007 0.073 14.98 5.3.15 0.010 0.067 15.05 5.3.14 0.003 0.077 14.95 5.3.13 0.007 0.073 15.04 5.3.12 0.007 0.047 15.05 5.3.11 0.000 0.053 15.08 5.3.10 0.000 0.083 14.59 5.3.9 0.010 0.040 14.45 5.3.8 0.013 0.063 14.55 5.3.7 0.007 0.057 14.43 5.3.6 0.000 0.050 14.64 5.3.5 0.010 0.070 14.36 5.3.4 0.017 0.070 14.36 5.3.3 0.010 0.070 14.39 5.3.2 0.013 0.063 14.27 5.3.1 0.007 0.073 14.27 5.3.0 0.013 0.070 14.27
preferences:dark mode live preview
1556.59 ms | 1398 KiB | 21 Q