* @license GPLv2 or later * @link http://holisticnetworking.net/easy-inputs-wordpress/ */ namespace EasyInputs; use ReflectionMethod; /** * A class defining the HTML form element. * * The Input class of Easy Inputs is instatiated with every new input created. What is * returned is always a string. The create() function is used as the main entry point * to the Input class, calling the function specified by the $args element 'type'. As * a default, all Inputs are created as text inputs unless a specfic type is requested * in that element. */ class Input { /** * The name of the instance of EasyInputs\Form\Input */ public $name; /** * Text, textarea, radio, etc. */ public $type; /** * A value to assign the input, or the selected element of a radio, checkbox * or select. */ public $value; /** * An optional array of HTML attributes to apply to the element. */ public $attrs; /** * Data attribute/value pairs. * * For any data-* attributes you may wish to add to the element, this array provides * an attribute/value pair. Attribute names need not include "data-" prefix. * @var array */ public $data; /** * For elements requiring options, they are held here. */ public $options; /** * A comma-separated list of nested groups */ public $group; /** * A validating function callback. */ public $validate; /** * A sprintf-compatible wrapper for the input. */ public $wrapper; /** * Setting this value to "true" will append the input's name with [], * thereby making it capable of holding multiple values. */ public $multiple; /** * List of supported attributes with regexes to validate against. */ public $supported_attributes = [ 'accesskey' => '/^[a-zA-Z\-_.]{1}$/', 'class' => '/^[a-zA-Z\-_.]{1,200}$/', 'tabindex' => '/[0-9]{1,20}/', 'width' => '/[0-9]{1,20}/', 'height' => '/[0-9]{1,20}/', 'size' => '/[0-9]{1,20}/', 'maxlength' => '/[0-9]{1,20}/', 'autocomplete' => '/on|off/', 'autofocus' => '/autofocus/', 'autosave' => '/^[a-zA-Z\-_.]{1,200}$/', 'results' => '/[0-9]{1,20}/', 'list' => '/^[a-zA-Z\-_.]{1,200}$/', 'min' => '/[0-9\-\/]{1,20}/', 'max' => '/[0-9\-\/]{1,20}/', 'placeholder' => '/^[a-zA-Z\-_. \?!,:]{1,200}$/', 'required' => '/required/', 'step' => '/[0-9]{1,20}/' ]; /** * This function creates the HTML for the required input element. */ public function create() { $label = null; $input = null; // Do nothing unless a valid type exists: $function = $this->toCamelCase($this->type); if (method_exists(__NAMESPACE__ . '\Input', $function)) : $reflector = new ReflectionMethod(__NAMESPACE__ . '\Input::' . $function); // If a public method exists that matches the type property: if ($reflector->isPublic()) : $input = $this->{$function}(); // Generic text input. else : $input = $this->generic(); endif; // To wrap or not to wrap: if(in_array($this->type, ['button', 'nonce', 'nonceVerify'])) : return $input; else : return $this->wrap($input); endif; endif; return __NAMESPACE__ . '\Input::' . $function; } /** * Return a WP Settings API nonce field. * * Port of the wp_nonce_field function. Don't over-think it. * Just let WordPress handle creating the nonce. This function returns, * rather than outputs, the nonce, in case we need to do something further * before output. * * @param $name mixed|string * * @return string The output of the wp_nonce_field function. */ public function nonce() { return wp_nonce_field( $this->Form->name, $this->name, true, false ); } /** * Verify a nonce created by EasyInputs * * Port of the wp_verify_nonce function. * * @return boolean false, 1 or 2 */ public function verifyNonce() { return wp_verify_nonce($_POST[$this->name], $this->Form->name); } /** * An HTML text input */ public function generic() { return sprintf( '', $this->name, $this->type, $this->fieldName(), $this->Form->attrsToString($this->attrs), $this->value ); } /** * A text input */ public function text() { return $this->generic(); } /** * A color picker input */ public function color() { return $this->generic(); } /** * A date picker input */ public function date() { return $this->generic(); } /** * A month picker input */ public function month() { return $this->generic(); } /** * A week picker input */ public function week() { return $this->generic(); } /** * A datetime picker input */ public function datetime() { return $this->generic(); } /** * A datetime-local picker input */ public function datetimeLocal() { return $this->generic(); } /** * A email input */ public function email() { return $this->generic(); } /** * A number input */ public function number() { return $this->generic(); } /** * A range slider input */ public function range() { $range = $this->generic(); $output = $this->output(); return $range.$output; } /** * An output for other values */ public function output() { return sprintf( '', $this->name ); } /** * A search input */ public function search() { return $this->generic(); } /** * A telephone input */ public function tel() { return $this->generic(); } /** * A time input */ public function time() { return $this->generic(); } /** * A url input */ public function url() { return $this->generic(); } /** * An HTML radio button group */ public function radio() { if (empty($this->options)) { return; } $radios = ''; foreach ($this->options as $key => $data) : $radios .= sprintf( '', $data['value'], $this->Form->attrsToString($this->attrs), $data['name'], $this->fieldName(), $this->value == $data['value'] ? 'checked' : null ); endforeach; return $radios; } /** * Output an HTML select box with inputs */ public function select() { if (empty($this->options)) { return; } $select = ''; $options = ''; if (!empty($this->options)) : foreach ($this->options as $value => $data) : $selected = ( !empty($this->value) && $value == $this->value ) ? ' selected ' : ''; $options .= sprintf( '', $data['value'], $selected, $data['name'] ); endforeach; endif; return sprintf( '', $this->name, $this->Form->attrsToString($this->attrs), $this->fieldName($this->name, !empty($this->group) ? $this->group : null), $options ); } /** * Output a group of related HTML checkboxes */ public function checkbox() { if (empty($this->options)) { return; } $boxes = ''; foreach ($this->options as $key => $data) : $fieldname = !empty($this->group) ? $this->group : $this->name; $selected = in_array($data['value'], (array)$this->value) ? 'checked' : null; $input = sprintf( '', $data['value'], $data['name'], $this->fieldName() . '[]', $selected ); $boxes .= sprintf('
%s
', $input); endforeach; return $boxes; } /** * Return an HTML textarea element. */ public function textarea() { return sprintf( '', $this->fieldName($this->name, !empty($this->group) ? $this->group : null), $this->Form->attrsToString($this->attrs), $this->value ); } /** * Return an HTML button */ public function button() { return sprintf( '', $this->name, $this->type, $this->fieldName($this->name, $this->group), $this->Form->attrsToString($this->attrs), $this->value ); } /** * Mimics the native WP submit_button function */ public function submitButton() { return sprintf( '', !empty($this->args['class']) ? $this->args['class'] : 'button button-primary', $this->name, !empty($this->args['id']) ? $this->args['id'] : 'submit', !empty($this->value) ? $this->value : 'Save Changes' ); } /** * Wrapper function to return a wp_editor instance */ public function editor() { return wp_editor($this->value, $this->name); } /** * Creates a media uploader-compatible input. Note that the output HTML will * still require the JS components of the Media Uploader to function. * @see https://codex.wordpress.org/Javascript_Reference/wp.media */ public function uploader() { $label = ''; if(empty($this->value)) : $label = __('Set Image'); else : $image = $this->get_image_id($this->value); $label = wp_get_attachment_image($image, 'thumbnail'); endif; $uploader = sprintf( '
%4$s
Remove Image
', isset($this->id) ? $this->id : $this->name, $this->fieldName($this->name, $this->group), $this->value, $label ); return $uploader; } /** * Return the ID of the full-size image URL given. * @param $image_url * @return mixed */ public function get_image_id($image_url) { global $wpdb; $attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM $wpdb->posts WHERE guid='%s';", $image_url )); return $attachment[0]; } /** * Return a valid field name attribute. * * @return string The combined */ private function fieldName() { $prefix = !empty($this->Form->prefix) ? $this->Form->name : ''; $name = !empty($this->Form->group) || !empty($this->Form->prefix) ? sprintf('[%s]', $this->name) : $this->name; $group = implode( '', array_map( function (&$value) { return sprintf('[%s]', $value); }, $this->group ) ); $multiple = !empty($this->multiple) ? '[]' : ''; return sprintf( '%s%s%s%s', $prefix, $group, $name, $multiple ); } /** * Wrap input in the requested HTML. * * This function performs two essential tasks. The first is to include the requested *