Location: PHPKode > scripts > Submission Script > bastianallgeier-submission-cf80919/submission.php
<?php 

if(!class_exists('Closure')) die('The Submission Class is not compatible with your PHP version. Closures must be available');

/*
 * Submission Class
 *
 * Makes it easy to handle 
 * form submission
 *
 * Usage: 
 * 
 * <code>
 *
 * // a simple contact form 
 * $submission = new Submission(array(
 *   // list of required fields
 *   'required' => array('name', 'email', 'text'),
 * 
 *   // validation event 
 *   'validate' => function() {
 *     if(!filter_var($self->value('email'), FILTER_VALIDATE_EMAIL)) $self->addInvalid('email');
 *   },  
 * 
 *   // form action event
 *   'action' => function($self) {
 *     // get all sanitized data with $self->data()
 *     // send your email here
 *   },
 *   
 *   // yay, success
 *   'success' => function() {
 *     // send the user to a thank you page or something like that
 *   },
 *
 *   // react on errors
 *   'error' => function() {
 *     // maybe log the error or do something else here
 *   }
 *
 * ));
 *
 * </code>
 *
 *
 * @version   1.0
 * @author    Bastian Allgeier <http://bastianallgeier.com>
 * @copyright Copyright 2012 Bastian Allgeier
 * @license   http://www.opensource.org/licenses/mit-license.php MIT License
 * 
 */
class Submission {

  var $defaults  = array();
  var $options   = array();  
  var $data      = array();  
  var $input     = array();
  var $missing   = array();
  var $invalid   = array();
  var $errors    = array();
  var $error     = false;
  var $alert     = false;
  var $response  = array();
  var $triggered = array();
  var $submitted = false;

  /*
   * Initializes the class
   * It's also responsible for triggering 
   * the first event (request)
   * 
   * @param array $params An array of parameters and events
   */
  public function __construct($params = array()) {

    $this->defaults();
    $this->options($params);
    $this->trigger('request');
        
  }

  /*
   * Getter and setter for defaults
   * This also returns the initial set of defaults
   * 
   * @param  mixed $key an optional key to use this method as getter
   * @param  mixed $value an optional value to use this method as setter
   * @return mixed 
   */
  public function defaults($key = null, $value = null) {
    
    if($key !== null && $value !== null) return $this->defaults[$key] = $value;
    if($key !== null) return @$this->defaults[$key];
        
    return $this->defaults = array(
      'method'   => 'post',
      'ajax'     => false,
      'required' => array(), 
      'keep'     => array(), 
            
      // on request event
      'request'  => function($self) {
        
        $requestMethod = strtoupper($_SERVER['REQUEST_METHOD']);
        $formMethod    = strtoupper($self->option('method'));
        
        // check for a valid request method        
        if($requestMethod != $formMethod) return false;

        // check for ajax requests
        if($self->option('ajax') && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) != 'xmlhttprequest') return false;
      
        // assign the request data        
        $self->input = ($requestMethod == 'POST') ? $_POST : $_GET;

        // do some basic sanitizing
        $self->data = $self->input = array_map(array($self, 'sanitize'), $self->input);

        // check for missing fields
        foreach($self->option('required') as $required) {
          if(empty($self->data[$required])) $self->addMissing($required);
        }
        
        // remove unwanted fields from the input
        $keep = $self->option('keep');

        if(!empty($keep)) {
          $cleaned = array();
          foreach($keep as $key) {
            // only add wanted elements to the cleaned array
            $cleaned[$key] = @$self->data[$key];
          }
          $self->data = $cleaned;
        }
        
        // do more filtering
        $self->trigger('filter');
        
        // only submit the form if any data is left
        if(!empty($self->data)) {
        
          // check for invalid fields
          $self->trigger('validate');
          
          // react on missing fields      
          if(!empty($self->missing) || !empty($self->invalid)) return $self->trigger('error');
          $self->submitted = true;
          $self->trigger('submit');
        
        }

      },

      'filter'   => function($self) {},
      'validate' => function($self) {},
      'submit'   => function($self) { return $self->trigger('success'); },
      'success'  => function($self) {},
      'error'    => function($self) {},
    );
  
  }

  /*
   * Getter and setter for options
   * 
   * @param  mixed $key an optional key to use this method as getter
   * @param  mixed $value an optional value to use this method as setter
   * @return mixed 
   */
  public function option($key = null, $value = null) {
    if($key !== null && $value !== null) return $this->options[$key] = $value;
    if($key !== null) return @$this->options[$key];
    return $this->options;
  }

  /*
   * Getter and setter for all options
   * 
   * @param  mixed $key an optional key to use this method as getter
   * @param  mixed $value an optional value to use this method as setter
   * @return mixed 
   */
  public function options($key = null, $value = null) {
    if($key !== null && $value !== null) return $this->options[$key] = $value;
    if($key !== null && is_array($key))  return $this->options = array_merge($this->defaults, $key);
    if($key !== null) return @$this->options[$key];
    return $this->options;
  }
  
  /*
   * Checks if the passed field is required
   * 
   * @param  string $field the name of the field, which should be checked
   * @return boolean
   */
  public function isRequired($field = false) {
    return in_array($field, $this->option('required'));
  }
  
  /*
   * Checks if the passed field is missing
   * 
   * @param  string $field the name of the field, which should be checked
   * @return boolean
   */
  public function isMissing($field) {
    return in_array($field, $this->missing);
  }

  /*
   * Add a field to the list of missing fields
   * 
   * @param  string $field the name of the field, which should be added
   * @return void
   */
  public function addMissing($field) {
    $this->missing[] = $field;
  }
    
  /*
   * Checks if the passed field is invalid
   * 
   * @param  string $field the name of the field, which should be checked
   * @return boolean
   */
  public function isInvalid($field) {
    return in_array($field, $this->invalid);
  }

  /*
   * Add a field to the list of invalid fields
   * 
   * @param  string $field the name of the field, which should be added
   * @return void
   */
  public function addInvalid($field) {
    $this->invalid[] = $field;
  }

  /*
   * Get or set a value from the filtered data
   * 
   * @param  string $key the name of the field
   * @param  string $value optional value to use this as setter
   * @return mixed The content of the field
   */
  public function value($key, $value = null) {
    if($value !== null) return $this->data($key, $value);
    $data = $this->data;
    return @$data[$key];
  }

  /*
   * Retrieves a value from the passed data
   * and converts it to safe html
   *
   * @param  string $field the name of the field
   * @return mixed The sanitized content of the field
   */
  public function htmlValue($field) {
    return htmlentities($this->value($field), ENT_COMPAT, 'UTF-8');  
  }

  /*
   * Checks if a field or the entire form has failed
   *
   * @param  string $field optional name of the field, which should be checked. If no field is passed, it will be checked if the form submission failed or not. 
   * @return boolean
   */
  public function isError($field = false) {
    if($field) return (in_array($field, $this->errors)) ? true : false;
    return $this->error;
  }

  /*
   * Returns an array with all failed fields
   *
   * @return array
   */
  public function errors() {
    return $this->errors;
  }
  
  /* 
   * Checks if the form has been submitted
   * 
   * @return boolean
   */
  public function isSubmitted() {
    return $this->submitted;
  }

  /*
   * Setter and getter for the form alert
   * You can use this to define an alert message, 
   * which can later be used to return an error message
   * to the user on error.
   *
   * @param  string $value optional value for the alert to use this as setter
   * @return string
   */
  public function alert($value = false) {
    if($value) return $this->alert = $value;
    return $this->alert;    
  }

  /*
   * Setter and getter for the submitted and filtered data
   *
   * @param  mixed $key optional key to use this as getter
   * @param  mixed $value optional value to use this as setter
   * @return mixed
   */
  public function data($key = null, $value = null) {
    if($key !== null && $value !== null) return $this->data[$key] = $value;  
    if($key !== null) return @$this->data[$key];
    return $this->data;
  }

  /*
   * Triggers a form event
   *
   * @param  string $event the name of the event
   * @param  array  $args optional array of arguments, which will be passed to the event
   * @return mixed
   */
  public function trigger($event, $args = array()) {
    $func = $this->option($event);
    
    // prepare special error stuff
    if($event == 'error') {
      
      // mark the submission as failed
      $this->error = true;
      
      // collect all error fields
      $this->errors = array_merge($this->missing, $this->invalid);
            
    } 
    
    // check if the event is a function at all    
    if(!is_a($func, 'Closure') && preg_match('/^default\:/', $event)) {
      $event = str_replace('default:', '', $event);      
      $func  = $this->defaults($event);
    }
    
    if(is_a($func, 'Closure')) {
  
      // track all triggered events    
      $this->triggered[$event] = array(
        'name' => $event,
        'func' => $func,
        'args' => $args, 
        'time' => microtime()
      );

      // invoke the function
      $func($this, $args);

    }
    
    return false;

  }

  /*
   * Returns an array of triggered events
   *
   * @param  string $key optional key to get a specific event from the array
   * @return array
   */
  public function triggered($key = null) {
    if($key !== null) return @$this->triggered[$key];
    return $this->triggered;
  }

  /*
   * Resets the passed data
   * This is handy to empty the form after submission
   */
  public function reset() {
    $this->data    = array();  
    $this->input   = array();
    $this->missing = array();
    $this->invalid = array();
    $this->errors  = array();
    $this->error   = false;
  }

  /*
   * Sanitizes request input
   * 
   * @param  mixed $string
   * @return mixed
   */
  public function sanitize($string) {
    if(is_array($string)) {
      return array_map(array($this, 'sanitize'), $string);
    } else {
      return (get_magic_quotes_gpc()) ? trim(stripslashes(stripslashes($string))) : trim($string);
    }
  }
  
}
Return current item: Submission Script