HakimCh/Form

View on GitHub
Form.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
namespace HakimCh\Form;

class Form
{
    /**
     * Submitted datas
     * @var array
     */
    public $datas = [];

    /**
     * Tag attributes
     * @var array
     */
    public $attributes = [];

    /**
     * Form action url
     * @var string
     */
    private $action = '';

    /**
     * Form CSRF token
     * @var string
     */
    private $token = '';

    /**
     * Class instance
     * @var object
     */
    private static $instance;

    /**
     * Class's Instance
     * @return object
     */
    public static function init()
    {
        if(is_null(self::$instance)) {
            self::$instance = new Form();
        }
        return self::$instance;
    }

    /**
     * Setup the class provided from a framework or script
     * @param array $datas Submitted data (GET, POST)
     * @param string $token CSRF token
     * @param string $action Url action
     */
    public function setup($datas=[], $token='', $action='')
    {
        $this->datas  = $datas;
        $this->token  = $token;
        $this->action = $action;
    }

    /**
     * Create Form tag
     * @param string $method
     * @param string $action form url
     * @return string
     */
    public function open($method = 'POST', $action = '')
    {
        if(empty($action)) {
            $action = $this->action;
        }
        $html = '<form action="'.$action.'" method="'.$method.'"'.$this->attributesToHtml().'>';
        if(!empty($this->token)) {
            $html .= $this->addAttr('value', $this->token)->input('token', 'hidden');
        }
        return $html;
    }

    /**
     * Create label
     * @param string|integer $value
     * @param boolean $required
     * @return string
     */
    public function label($value, $required = null)
    {
        $labelValue = ucfirst($value);
        if($required) {
            $labelValue .= ' <span class="required">*</span>';
        }
        return $this->addTag('label', $labelValue);
    }

    /**
     * Create Select tag
     * @param string $fieldName
     * @param array $options
     * @return string
     */
    public function select($fieldName, $options = [])
    {
        $fieldOptions = '';
        if(!empty($options)) {
            $fieldValue = $this->get($fieldName);
            foreach($options as $value => $text) {
                $selected = $fieldValue != $value ? '' : ' selected="selected"';
                $fieldOptions .= '<option value="'.$value.'"'.$selected.'>'.ucfirst($text).'</option>';
            }
        }
        return $this->addTag('select', $fieldOptions);
    }

    /**
     * Create Textarea tag
     * @param string $fieldName
     * @return string
     */
    public function textarea($fieldName)
    {
        $fieldValue = $this->get($fieldName);
        return $this->addTag('textarea', $fieldValue);
    }

    /**
     * Create submit button
     * @param string  $value field text
     * @param string|null $iconClass the icon class from (fontawsome, ionicons...)
     * @return string
     */
    public function button($value = 'Submit', $iconClass = null)
    {
        if($iconClass){
            $value .= ' <i class="'.$iconClass.'"></i>';
        }
        return $this->addTag('button', $value);
    }

    /**
     * Create submit button
     * @param string $value  Field value
     * @return string
     */
    public function submit($value = 'Submit')
    {
        return $this->addAttr('value', $value)->input('submit', 'submit');
    }

    /**
     * Add an attribute to the field
     * @param String|Array $key attribute name
     * @param Integer|String $value attribute value
     * @return Form
     */
    public function addAttr($key, $value = null)
    {
        if(is_array($key))
            $this->attributes += $key;
        else
            $this->attributes[$key] = $value;
        return $this;
    }

    /**
     * Get element by key from the user datas
     * @param string $key the field name
     * @param string $source source of datas (datas, files, attributes)
     * @return mixed
     */
    public function get($key = '', $source = 'datas')
    {
        if(property_exists($this, $source)) {
            $property = $this->$source;
            if(!empty($property) && array_key_exists($key, $property))
                return $property[$key];
        }
        return null;
    }

    /**
     * Create Input field
     * @param string $fieldName Field name
     * @param string $type field type (text, password...)
     * @return string
     */
    protected function input($fieldName, $type) {
        $value = $this->get($fieldName);
        if(!is_null($value)) {
            $this->attributes['value'] = $this->get($fieldName);
        }
        return '<input type="'.$type.'" name="'.$fieldName.'"'.$this->attributesToHtml().'>';
    }

    /**
     * Create a radio/checkbox field
     * @param string $fieldName field name
     * @param string $fieldLabel field label
     * @param string $type field type
     * @return string
     */
    protected function box($fieldName, $fieldLabel = '', $type = '')
    {
        $fieldValue = $this->get($fieldName);
        $value = $this->get('value', 'attrs');
        if($fieldValue && $value){
            $checked = is_array($fieldValue) ? array_key_exists($value, array_flip($fieldValue)) : $fieldValue == $value;
            if($checked){
                $this->attributes['checked'] = 'checked';
            }
        }
        return $this->input($fieldName, $type) . " " . $fieldLabel;
    }

    /**
     * Add an HTML Form tag
     * @param string $tagType Tag type (label, textarea, select...)
     * @param string|integer $tagContent Tag content or value
     * @return string
     */
    protected function addTag($tagType, $tagContent)
    {
        $attributes = $this->attributesToHtml();
        return '<'.$tagType.' '.$attributes.'>'.$tagContent.'</'.$tagType.'>';
    }

    /**
     * Generate field's attributes
     * @param string $html
     * @return string
     */
    private function attributesToHtml($html = '')
    {
        if(!empty($this->attributes)) {
            foreach($this->attributes as $key => $value) {
                $value = is_array($value) ? implode(' ', $value) : $value;
                $html .= is_numeric($key) ? $value.' ' : $key.'="'.$value.'" ';
            }
        }
        $this->attributes = [];
        return $html;
    }

    /**
     * Magic methods call
     * @param $tagName
     * @param $methodParams
     * @return string
     */
    public function __call($tagName, $methodParams)
    {
        $method = null;
        if(in_array($tagName, ['text','password','date','time','file','hidden','reset'])) {
            array_push($methodParams, $tagName);
            $method = "input";
        }
        elseif(in_array($tagName, ['checkbox','radio'])) {
            array_push($methodParams, $tagName);
            $method = "box";
        }
        elseif($tagName == 'close') {
            return '</form>';
        }
        elseif($tagName == 'reset') {
            $this->datas = [];
        }
        $handler = [$this, $method];
        return !is_null($method) && is_callable($handler) ? call_user_func_array($handler, $methodParams) : '';
    }
}