<repo_name>mrjgreen/formbuilder<file_sep>/lib/Fieldset/Element/Checkbox.php
<?php namespace Fieldset\Element;

class Checkbox extends \Fieldset\Element {

    /**
     * Create a form input
     *
     * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
     * @param   string
     * @param   array
     * @return  string
     */
    public function draw($field, $value = null, array $attributes = array()) {
        if (is_array($field)) {
            $attributes = $field;
        } else {
            $attributes['name'] = (string) $field;
        }
        
        array_key_exists('value', $attributes) or $attributes['value'] = 1;
        
        if($value == $attributes['value']){
            $attributes['checked'] = 'checked';
        }
        else{
            unset($attributes['checked']);
        }

        $attributes['type'] = empty($attributes['type']) ? 'text' : $attributes['type'];
        return '<input type="hidden" value="0" name="'.$attributes['name'].'"><input ' . $this->attrToString($attributes) . '>';
    }
}
<file_sep>/lib/Fieldset/ElementInterface.php
<?php

namespace Fieldset;

interface ElementInterface {
    public function getName();
    public function populate($data);
    public function getRules();
    public function setErrors($errors);
}
<file_sep>/lib/Fieldset/Element.php
<?php

namespace Fieldset;

/**
 * Input Element Class
 *
 * Helper for creating input elements with support for creating dynamic form objects.
 *
 */
class Element implements ElementInterface, \ArrayAccess {

    /**
     * @var  string  Name of this field
     */
    protected $_name = '';

    /**
     * @var  string  Field type for form generation, false to prevent it showing
     */
    protected $_type = 'text';

    /**
     * @var  string  Field label for validation errors and form label generation
     */
    protected $_label = '';

    /**
     * @var  mixed  (Default) value of this field
     */
    protected $_value;

    /**
     * @var  array  Rules for validation
     */
    protected $_rules = array();

    /**
     * @var  array  Errors for validation
     */
    protected $_errors = array();

    /**
     * @var  array  Attributes for form generation
     */
    protected $_attributes = array();

    /**
     * @var  array  Options, only available for select, radio & checkbox types
     */
    protected $_options = array();

    /**
     * @var  string  Template for form building
     */
    protected $_defaultTemplate = '{label}{element}{error}';

    /**
     * @var  string  Template for form building
     */
    protected $_defaultErrorTemplate = '<p class="error">{message}</p>';

    /**
     * @var  string  Template for form building
     */
    protected $_defaultLabelClass = '';

    /**
     * 
     * @var string 
     */
    protected $_labelClass;

    /**
     * @var  string  Template for form building
     */
    protected $_template;

    /**
     * @var  string  Template for form building
     */
    protected $_errorTemplate;

    /**
     *
     * @param array $settings 
     */
    public function __construct(array $settings = array()) {
        foreach ($settings as $key => $setting) {
            $this->set($key, $setting);
        }
    }

    /**
     *
     * @param type $name 
     */
    public function setName($name) {
        $this->_name = $name;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getName() {
        return preg_replace('/\[.*\]$/', '', $this->_name);
    }

    /**
     *
     * @param type $value 
     */
    public function setValue($value) {
        $this->_value = $value;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getValue() {
        return $this->_value;
    }

    /**
     *
     * @param type $type 
     */
    public function setType($type) {
        $this->_type = $type;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getType() {
        return $this->_type;
    }

    /**
     *
     * @param type $options 
     */
    public function setOptions($options) {
        $this->_options = $options;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getOptions() {
        return $this->_options;
    }

    /**
     *
     * @param type $label 
     */
    public function setLabel($label) {
        $this->_label = $label;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getLabel() {
        return $this->_label;
    }


    /**
     * if the elements are in array notation form ie something[34], we can set the index to be a value of our choice
     * @param mixed $id 
     */
    public function setOrdinal($id) {
        $this->_name = preg_replace('/\[.*\]$/', '[' . $id . ']', $this->_name);
        return $this;
    }

    /**
     * if the elements are in array notation form ie something[34], we can get the index in this case, 34
     * @return mixed $id 
     */
    public function getOrdinal() {
        $array = array();
        if (preg_match('/\[(.*)\]$/', $this->_name, $array) === 1) {
            return $array[1];
        }
        return null;
    }

    /**
     *
     * @param type $name
     * @param type $value 
     */
    public function setAttribute($name, $value) {
        $this->_attributes[$name] = $value;
        return $this;
    }

    /**
     *
     * @param type $name
     * @param type $value 
     */
    public function appendAttribute($name, $value) {
        $this->_attributes[$name] .= ' ' . $value;
        return $this;
    }

    /**
     *
     * @param type $name
     * @return type 
     */
    public function getAttribute($name) {
        return isset($this->_attributes[$name]) ? $this->_attributes[$name] : false;
    }

    /**
     *
     * @param type $attr 
     */
    public function setAttributes($attr) {
        $this->_attributes = $attr;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getAttributes() {
        return $this->_attributes;
    }

    /**
     *
     * @param type $rules 
     */
    public function setRules($rules) {
        $this->_rules = $rules;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getRules() {
        return $this->_rules;
    }

    public function setLabelClass($class) {
        $this->_labelClass = $class;
        return $this;
    }

    /**
     *
     * @param type $template 
     */
    public function setTemplate($template) {
        $this->_template = $template;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getTemplate() {
        return $this->_template;
    }

    /**
     *
     * @param type $template 
     */
    public function setErrorTemplate($template) {
        $this->_errorTemplate = $template;
        return $this;
    }

    /**
     *
     * @return type 
     */
    public function getErrorTemplate() {
        return $this->_errorTemplate;
    }

    /**
     *
     * @return array 
     */
    public function setErrors($errors) {
            $this->_errors = $errors->get($this->getName());
            return $this;
    }


    /**
     *
     * @param type $name
     * @param type $error 
     */
    public function addError($name, $error) {
        $this->_errors[$name] = $error;
        return $this;
    }


    public function populate($data) {

        if (is_array($data)) {
            $name = $this->getName();
            if (!isset($data[$name])) {
                return $this;
            }
            $data = $data[$name];
        }
        $this->_value = $data;
        return $this;
    }

    /**
     *
     * @param type $template 
     */
    public function setDefaultTemplate($template) {
        $this->_defaultTemplate = $template;
    }

    /**
     *
     * @param type $template 
     */
    public function setDefaultErrorTemplate($template) {
        $this->_defaultErrorTemplate = $template;
    }

    /**
     *
     * @param type $template 
     */
    public function setDefaultLabelClass($class) {
        $this->_defaultLabelClass = $class;
    }
    
    public function hasErrors(){
        return count($this->_errors);
    }

    /**
     * Place the element and label into the template and return the HTML
     * @return string HTML label and element inside the specified template 
     */
    public function build() {
        $template = $this->_template === null ? $this->_defaultTemplate : $this->_template;
        $search = array('{label}','{label_raw}','{element}', '{error}','{value}','{error-class}');
        $replace = array(
            $this->_buildLabel(),
            $this->_label,
            $this->_buildElement(),
            $this->_buildError(),
            $this->_value,
            $this->hasErrors() ? 'error' : ''
        );

        return str_replace($search, $replace, $template);
    }

    public function _buildError() {
        $str = '';
        $template = $this->_errorTemplate === null ? $this->_defaultErrorTemplate : $this->_errorTemplate;
        foreach ($this->_errors as $error) {
            $str .= str_replace('{message}', $error, $template);
            break; //#GOTCHA only show one error message at a time
        }
        return $str;
    }

    protected function _rulesClass() {
        $str = '';
        foreach ($this->_rules as $rulename) {
            if (is_array($rulename)) {
                $class = array_shift($rulename);
                $class.= '[' . implode(',', $rulename) . ']';
            } else {
                $class = $rulename;
            }

            $str .= ' ' . $class;
        }
        return $str;
    }

    /**
     * 
     * @return string The HTML element ready for print 
     */
    protected function _buildElement() {

        if (!isset($this->_attributes['class'])) {
            $this->_attributes['class'] = '';
        }
        
        if($validate = $this->_rulesClass()){
            isset($this->_attributes['data-validate']) or $this->_attributes['data-validate'] = '';
            $this->_attributes['data-validate'] .= $validate;
        }

        if ($this instanceof Element\Select || $this instanceof Element\MultiRadio) { //special select element parameter format due to the additional "options" parameter
            return $this->draw($this->_name, $this->_value, $this->_options, $this->_attributes);
        }
        
        $this->_attributes['type'] = $this->_type;
        return $this->draw($this->_name, $this->_value, $this->_attributes);
    }

    public static function forge(array $settings) {
        isset($settings['type']) or $settings['type'] = 'text';

        $class = __NAMESPACE__ . '\\Element\\' . ucwords($settings['type']);
        if (@class_exists($class)) { //quietly for loaders that MAKE NOISE!
            return new $class($settings);
        }
        return new Element\Input($settings);
        //throw new \Exception("Element $class could not be loaded.");
    }

    /**
     * The HTML label element ready for print
     * @return string 
     */
    protected function _buildLabel() {
        return $this->_label ? $this->label($this->_label) : '';
    }

    /**
     * Magic serializer
     * @return string 
     */
    public function __toString() {
        return $this->build();
    }

    /**
     * Create a label field
     *
     * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
     * @param   string
     * @param   array
     * @return  string
     */
    public function label($label) {
        if (is_array($label)) {
            $attributes = $label;
            $label = $attributes['label'];
        }
        $attributes = array();

        isset($this->_attributes['id']) and $attributes['for'] = $this->_attributes['id'];
        $attributes['class'] = isset($this->_labelClass) ? $this->_labelClass : $this->_defaultLabelClass;

        return '<label ' . $this->attrToString($attributes) . '>' . $label . '</label>';
    }

    /**
     * Prep Value
     *
     * Prepares the value for display in the form
     *
     * @param   string
     * @return  string
     */
    public function prep_value($value) {
        return str_replace(array("'", '"'), array("&#39;", "&quot;"), htmlspecialchars($value));
    }

    /**
     * Attr to String
     *
     * Wraps the global attributes function and does some form specific work
     *
     * @param   array  $attr
     * @return  string
     */
    public function attrToString($attr) {
        $string = "";
        foreach ($attr as $k => $v) {
            $v !== null and $string .= is_numeric($k) ? $v : sprintf($k . '="%s" ', $v);
        }
        return $string;
    }

    public function set($key, $setting) {
        $method = 'set' . ucwords($key);
        if (method_exists($this, $method)) {
            $this->$method($setting);
        } else {
            $this->setAttribute($key, $setting);
        }
    }

    public function get($key) {
        $method = 'get' . ucwords($key);
        if (method_exists($this, $method)) {
            return $this->$method();
        } elseif (isset($this->_attributes[$key])) {
            return $this->_attributes[$key];
        }
        return null;
    }

    public function __get($name) {
        return $this->get($name);
    }

    public function __set($name, $value) {
        return $this->set($name, $value);
    }

    public function offsetSet($offset, $value) {
        is_null($offset) or $this->set($offset, $value);
    }

    public function offsetExists($offset) {
        $val = $this->get($offset);
        return isset($val);
    }

    public function offsetUnset($offset) {
        $this->set($offset, null);
    }

    public function offsetGet($offset) {
        return $this->get($offset);
    }
    

}<file_sep>/lib/Fieldset/Element/Multiradio.php
<?php
namespace Fieldset\Element;

class Multiradio extends Input {

    public function draw($field, $value = null, array $options = array(), array $attributes = array()) {
        $inputs = '<div class="radio-group">';
        if (is_array($field)) {
            $this->_attributes = $field;
        } else {
            $this->_attributes = $attributes;
            $this->_attributes['name'] = (string) $field;
            $this->_attributes['value'] = (string) $value;

        }
        $this->_attributes['type'] = 'radio';
        $i = 0;

        foreach ($options as $label => $option) {
            $inputs .= '<div class="radio-element">';
            $attributes = $this->_attributes;
            $attributes['label'] = $option;
            $attributes['value'] = $label;
            $attributes['template'] = isset($attributes['elementTemplate'])?$attributes['elementTemplate']:'{element} {error}{label}';
            $attributes['id'] = $field.'-'.$i++;
            $attributes['checked'] = ($value == $label ? 'checked' : null);
            $attributes['labelClass'] = ($value == $label ? 'active' : null);
            unset($attributes['help'],$attributes['elementTemplate']);
            $inputs .= \Fieldset\Element::forge($attributes);
            $inputs .= '</div>';
        }
        return $inputs.'</div>';
    }

}<file_sep>/lib/Fieldset/Element/Heading.php
<?php
namespace Fieldset\Element;

class Heading extends \Fieldset\Element {
    
    public function draw($field, $values = null, array $attributes = array()) {
        if (is_array($field)) {
            $attributes = $field;
        }
        unset($attributes['value']);
        isset($attributes['class']) or $attributes['class'] = '';
        $attributes['class'] .= ' cman-heading';
        return '<h2 ' . $this->attrToString($attributes) . '>'.$this->label.'</h2>';
    }

}<file_sep>/lib/Fieldset/Element/Plain.php
<?php
namespace Fieldset\Element;

class Plain extends \Fieldset\Element {
    
    public function draw($field, $values = null, array $attributes = array()) {
        return $values;
    }

}<file_sep>/lib/Fieldset/Element/Select.php
<?php
namespace Fieldset\Element;

class Select extends \Fieldset\Element {
   
    /**
	 * Select
	 *
	 * Generates a html select element based on the given parameters
	 *
	 * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
	 * @param   string  selected value(s)
	 * @param   array   array of options and option groups
	 * @param   array
	 * @return  string
	 */
	public function draw($field, $values = null, array $options = array(), array $attributes = array())
	{
		if (is_array($field))
		{
			$attributes = $field;

			if ( ! isset($attributes['selected']))
			{
				$attributes['selected'] = ! isset($attributes['value']) ? null : $attributes['value'];
			}
		}
		else
		{
			$attributes['name'] = (string) $field;
			$attributes['selected'] = $values;
			$attributes['options'] = $options;
		}
		unset($attributes['value']);

		if ( ! isset($attributes['options']) || ! is_array($attributes['options']))
		{
			throw new \InvalidArgumentException(sprintf('Select element "%s" is either missing the "options" or "options" is not array.', $attributes['name']));
		}
		// Get the options then unset them from the array
		$options = $attributes['options'];
		unset($attributes['options']);

		// Get the selected options then unset it from the array
		// and make sure they're all strings to avoid type conversions
		$selected = ! isset($attributes['selected']) ? array() : array_map(function($a) { return (string) $a; }, array_values((array) $attributes['selected']));

		unset($attributes['selected']);

		// workaround to access the current object context in the closure
		$current_obj =& $this;

		// closure to recusively process the options array
		$listoptions = function (array $options, $selected, $level = 1) use (&$listoptions, &$current_obj, &$attributes)
		{
			$input = PHP_EOL;
			foreach ($options as $key => $val)
			{
				if (is_array($val))
				{
					$optgroup = $listoptions($val, $selected, $level + 1);
					$optgroup .= str_repeat("\t", $level);
					$input .= str_repeat("\t", $level).'<optgroup label="'.$key.'" style="text-indent:'.(10*($level-1)).'px;">'. $optgroup.'</optgroup>'.PHP_EOL;
				}
				else
				{
					$opt_attr = array('value' => $key, 'style' => 'text-indent: '.(10*($level-1)).'px;');
					(in_array((string)$key, $selected, true)) && $opt_attr[] = 'selected';
					$input .= str_repeat("\t", $level);
                                        $opt_attr['value'] = (empty($attributes['dont_prep'])) ?
                                                $current_obj->prep_value($opt_attr['value']) : $opt_attr['value'];
                                        $input .= '<option ' . $current_obj->attrToString($opt_attr) . '>' . $val . '</option>' . PHP_EOL;
				}
			}
			unset($attributes['dont_prep']);

			return $input;
		};

		// generate the select options list
		$input = $listoptions($options, $selected).str_repeat("\t", 0);

		return '<select ' . $this->attrToString($attributes) . '>' . $input . '</select>';
	}
}

<file_sep>/lib/Fieldset/Element/Button.php
<?php namespace Fieldset\Element;

class Button extends Fieldset\Element {

    /**
     * Create a button
     *
     * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
     * @param   string
     * @param   array
     * @return  string
     */
    public function draw($field, $value = null, array $attributes = array()) {
        if (is_array($field)) {
            $attributes = $field;
            $value = isset($attributes['value']) ? $attributes['value'] : $value;
        } else {
            $attributes['name'] = (string) $field;
            $value = isset($value) ? $value : $attributes['name'];
        }
        $attributes['type'] = 'submit';
        return '<button ' . $this->attrToString($attributes) . '>' . $value . '</button>';
    }

}
<file_sep>/lib/Fieldset/Element/Multicheckbox.php
<?php
#NOT WORKING!
namespace Jg\Fieldset\Element;

class MultiCheckbox extends \Jg\Fieldset\Element {
   
    /**
	 * Select
	 *
	 * Generates a html select element based on the given parameters
	 *
	 * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
	 * @param   string  selected value(s)
	 * @param   array   array of options and option groups
	 * @param   array
	 * @return  string
	 */
	public function draw($field, $values = null, array $options = array(), array $attributes = array())
	{
		unset($attributes['array']);
		$inputs = '';        
		if (is_array($field)) {
		    $this->_attributes = $field;
		} else {
		    $this->_attributes = $attributes;
		    $this->_attributes['name'] = (string) $field;
		    $this->_attributes['value'] = (string) $values;
		}
		$this->_type = 'checkbox';

		foreach ($options as $label => $option) {
		    $this->_label = $label;
		    $this->_value = $option;
		    $this->_attributes['selected'] = $values == $option ? 'selected' : false;
		    $inputs .= $this->build();
		}
		return $inputs;
	}
}

<file_sep>/lib/Fieldset/Element/Imagepicker.php
<?php
namespace Fieldset\Element;

class Imagepicker extends \Fieldset\Element {

    /**
     * Create a form input
     *
     * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
     * @param   string
     * @param   array
     * @return  string
     */
    public function draw($field, $value = null, array $attributes = array()) {
        
        $tag = $value ? basename($value) : "No Image Selected";
        $src = $value ?: "http://placehold.it/250x150";
        return 
	'<input type="hidden" name="'.$field.'" value="'.$value.'">' .
        '<span class="imagepicker-tag">'.$tag.'</span> <a href="#" class="clearImage">(Clear Image)</a>' .
        '<img  src="'.$src.'@maxWidth-225" class="imagepicker" >';
    }
}
<file_sep>/lib/Fieldset/Element/Textarea.php
<?php

namespace Fieldset\Element;

class Textarea extends \Fieldset\Element {

    /**
     * Create a textarea field
     *
     * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
     * @param   string
     * @param   array
     * @return  string
     */
    public function draw($field, $value = null, array $attributes = array()) {
        if (is_array($field)) {
            $attributes = $field;
        } else {
            $attributes['name'] = (string) $field;
            $attributes['value'] = (string) $value;
        }

        $value = empty($attributes['value']) ? '' : $attributes['value'];
        unset($attributes['value']);

        if (empty($attributes['dont_prep'])) {
            $value = $this->prep_value($value);
            unset($attributes['dont_prep']);
        }

        return '<textarea ' . $this->attrToString($attributes) . '>' . $value . '</textarea>';
    }

}
<file_sep>/lib/Fieldset/Element/Input.php
<?php
namespace Fieldset\Element;

class Input extends \Fieldset\Element {
    
    /**
     * Valid types for input tags (including HTML5)
     */
    protected $_valid_inputs = array(
        'button', 'checkbox', 'color', 'date', 'datetime',
        'datetime-local', 'email', 'file', 'hidden', 'image',
        'month', 'number', 'password', 'radio', 'range',
        'reset', 'search', 'submit', 'tel', 'text', 'time',
        'url', 'week'
    );
    
    /**
     * Create a form input
     *
     * @param   string|array  either fieldname or full attributes array (when array other params are ignored)
     * @param   string
     * @param   array
     * @return  string
     */
    public function draw($field, $value = null, array $attributes = array()) {
        if (is_array($field)) {
            $attributes = $field;
            array_key_exists('value', $attributes) or $attributes['value'] = '';
        } else {
            $attributes['name'] = (string) $field;
            $attributes['value'] = (string) $value;
        }
        
        $attributes['type'] = empty($attributes['type']) ? 'text' : $attributes['type'];

        if (!in_array($attributes['type'], $this->_valid_inputs)) {
            throw new \Exception(sprintf('"%s" is not a valid input type.', $attributes['type']));
        }

        if (empty($attributes['dont_prep'])) {
            $attributes['value'] = $this->prep_value($attributes['value']);
            unset($attributes['dont_prep']);
        }
        return '<input ' . $this->attrToString($attributes) . '>';
    }
}
