From f3445b6b02cb95ef9f6fc4ce500f1a588ee2b1b3 Mon Sep 17 00:00:00 2001 From: Chuck Scott Date: Fri, 19 Dec 2014 13:54:27 -0500 Subject: [PATCH] Added more images and replacent HTML capability --- controllers/admin.php | 14 +- lib/glmInputOutputSupport.php | 484 ++++++++++++++++++++++++++++ models/admin/add/index.php | 60 +++- models/admin/prototypes/display.php | 2 + models/admin/prototypes/edit.php | 45 ++- views/admin/add/index.html | 32 ++ views/admin/prototypes/display.html | 9 +- views/admin/prototypes/edit.html | 31 ++ views/admin/prototypes/index.html | 14 +- 9 files changed, 683 insertions(+), 8 deletions(-) create mode 100644 lib/glmInputOutputSupport.php diff --git a/controllers/admin.php b/controllers/admin.php index 7675e31..3eb77bb 100644 --- a/controllers/admin.php +++ b/controllers/admin.php @@ -350,6 +350,13 @@ class glmProtoAdmin // Get suggested view $view = $results['view']; + // Check for view supplied as text + $viewText = false; + if (isset($results['viewText']) && $results['viewText'] != '') { + $view = $results['viewText']; + $viewText = true; + } + // If there's a general model failure use the error view if (! $results['status']) { $view = 'admin/error/index.html'; @@ -380,7 +387,12 @@ class glmProtoAdmin // echo "
".print_r($x,1)."
"; // Generate output from model data and view - $smarty->template->display($view); + if ($viewText) { + $smarty->template->display('string:'.$view); + } else { + $smarty->template->display($view); + } + } } diff --git a/lib/glmInputOutputSupport.php b/lib/glmInputOutputSupport.php new file mode 100644 index 0000000..921cfb8 --- /dev/null +++ b/lib/glmInputOutputSupport.php @@ -0,0 +1,484 @@ + +* @license http://www.gaslightmedia.com Gaslightmedia +*/ + +/* + * This class provides general I/O support for GLM WordPress plugins. Services + * available include... + * + * inputValidate() - Validate/sanitize a specific input field + * + * inputValidateArray() - Validate/sanitize a list of input fields + * + * The available field types include ... + * + * * integer + * float + * money + * percent + * pointer + * list + * bitmap + * * text + * password + * checkbox + * email + * date + * time + * phone + * image + * latitude + * longitude + * + * + */ +abstract class glmInputOutputSupport +{ + /** + * Current Status Value + * + * Used to provide a status value where method returns a simple value + * + * @var $status + * @access private + */ + private $status = false; + + /** + * Status strings for defined status values + * + * Not intended to be modified + * + * @var $glmIoStatus + * @access private + */ + private $glmIoStatus = array( + 'UNPROCESSED' => 'Input not yet processed.', + 'CLEAN' => 'Valid user input.', + 'MISSING' => 'Field is missing from form or name is incorrect.', + 'NOT_SUPPLIED' => 'No value was supplied but was not required.', + 'REQUIRED_NOT_SUPPLIED' => 'A required value was not supplied.', + 'INVALID' => 'Supplied input is not valid.', + 'INVALID_VALUE' => 'The value supplied for this field is not permitted.', + 'TOO_SHORT' => 'Supplied input is too short.', + 'TOO_LONG' => 'Supplied input is too long.', + 'TOO_LOW' => 'Supplied input is too low.', + 'TOO_HIGH' => 'Supplied input is too high.', + 'NAME_NOT_SUPPLIED' => 'Field name was not supplied. Most likely a programming error.', + 'INVALID_SOURCE' => 'The source for a field was not specified. Most likely a programming error.', + 'INVALID_TYPE' => 'The specified field type is invalid. Most likely a programming error.', + 'INVALID_FILTER_SPEC' => 'The filter specification for this field is invalid. Most likely a programming error.' + ); + + /** + * Input Sources + * + * Not intended to be modified + * + * @var $glmIoSources + * @access private + */ + private $glmIoSources = array( + 'REQUEST', + 'GET', + 'POST', + 'COOKIE', + 'SERVER', + 'ENV' + ); + + /** + * Input Options + * + * Not intended to be modified + * + * @var $glmIoFilters + * @access private + */ + private $glmIoOptions = array( + // None at this time + ); + + /** + * Current Input Field Filter Options + * + * @var $filter array + * @access private + */ + private $filter; + + /** + * Current Field Value/Status Array + * + * Used to build return values for a field + * + * @var $field array + * @access private + */ + private $field; + + /* + * Validate an array of input fields + * + * This method calls the inputValidate() method for each of an array + * of field names and filter specifications + * + * @var $fieldSpecs array Array of field name and filter specifications + * Field name is key and specifications array is value. + * + * @return array Array of field results (see inputValidate() method) + */ + public function inputValidateArray($fieldSpecs) + { + // Destination array for all input results + $clean = array(); + + // If $fields is not an array or has not contents, then fail + if (!is_array($fieldSpecs) || count($fieldSpecs) == 0) { + return false; + } + + // For each field + foreach ($fieldSpecs as $fieldSpec) { + + // Validate this field + $this->inputValidate($fieldSpec); + + // Place results in the clean input array + $clean[$fieldSpec['name']] = $this->field; + } + + return $clean; + + } + + /* + * Validate/sanitize a specific input field + * + * This method is provided a field name, field type, and possible options. + * It then validates and/or sanitizes the input field according to the + * supplied + * field type and any supplied options and returns with an array that + * includes the + * clean value, a status flag, and a possible error reason code and string. + * + * Input to this method is based loosely on the PHP filter_input_array() + * function + * parameters, but is not compatible with it. For this method, only one + * field is processed per call. + * + * @fieldSpec mixed Array defining how the field is to be processed + * + * Paramater Required Description + * 'name' Name of the input field + * 'type' Type of data to be input - Requireed + * 'source' Input Source (See $glmIoSources) - Required + * 'required' Boolean, whether a value is required + * 'min_length' Minimum length for a string + * 'max_length' Maximum length for a string + * 'min_value' Minimum value (for scalar and date types) + * 'max_value' Maximum value (for scalar and date types) + * 'values' Array that is a simple list of acceptable values + * 'options' Array of options and possibly values listed above + * + * @return array The current + * 'name' string Name of the field + * 'value' string Clean value for this field + * 'status' boolean Success/fail status + * 'message' string Text message for error value + * + */ + public function inputValidate($fieldSpec) + { + // Save current field settings +// $this->fieldSpec = $fieldSpec; + + // Clear input return values array + $this->resetCurrentField($fieldSpec['name']); + + // Check for required field specifications and add defaults + $fs = $this->validateFieldSpec($fieldSpec); + if (!$fs) { + $this->field['status'] = 'INVALID_FILTER_SPEC'; + } else { + + // Attempt to get field input + $in = $this->getInputValue($fs); + + // If we don't have a problem getting the value + if ($in !== false) { + + // Build filter method to use + $filterFunc = 'filter_'.$fs['type']; + + // Check if that method exists + if (!method_exists($this, $filterFunc)) { + $this->field['status'] = 'INVALID_TYPE'; + } else { + + // It does, so execute the input filter + call_user_method($filterFunc, $this, $in, $fs); + + // Check for if a list of valid values is supplied + if ($fs['values'] !== false) { + if (!in_array($in, $fs['values'])) { + $this->field['status'] = 'INVALID_VALUE'; + } + } + + } + + } + + } + // Set value and text status message + $this->field['value'] = $in; + $this->field['message'] = $this->glmIoStatus[$this->field['status']]; + + return $this->field; + + } + + /* + * Validate Filter Settings + * + * Checks $fieldSpec to make sure required values are supplied and sets + * defaults for values not supplied. + * + * A return of false from this method should be considered a programming + * error and fatal. + * + * + * @return boolean True if all OK, otherwise false + * + */ + private function validateFieldSpec($fieldSpec) + { + + $fs = $fieldSpec; + + // Check for required filter type + if (!isset($fs['type']) || $fs['type'] == '') { + return false; + } + + // Check for required filter source + if (!isset($fs['source']) || $fs['source'] == '') { + return false; + } + + /* + * Values of $fs replace values with the same key in the default field + * definition array. This results in an array with the desired values + * including defaults for all parameters not provided in $fs. + */ + $fs = array_replace($this->createFieldDefArray(), $fs); + + return fs; + } + + /* + * Create empty field definition array with all features + * + * @var $field string Optional new field name - Defaults to none (false) + * @var $type string Optional type of field - defaults to text + * @var $required boolean Optional input required flag + * @var $source string Optional source type - defaults to REQUEST + * @var $min_length mixed Optional minimum input length in characters + * @var $max_length mixed Optional maximum input length in characters + * @var $min_value mixed Optional minimum numeric value (int, or float) + * @var $max_value mixed Optional maximum numeric value (int, or float) + * @var $min_length mixed Optional minimum input length in characters + * @var $values array Optional array of valid input values + * @var $options array Optional array of option flags + * + * + * @return array Field definition array + * + */ + public function createFieldDefArray( + $field = false, + $type = 'text', + $required = false, + $source = 'REQUEST', + $min_length = false, + $max_length = false, + $min_value = false, + $max_value = false, + $values = false, + $options = array() + ) + { + + return array( + 'name' => $field, + 'type' => $type, + 'required' => false, + 'source' => false, + 'min_length' => false, + 'max_length' => false, + 'min_value' => false, + 'max_value' => false, + 'values' => array(), + 'options' => array() + ); + + } + + /* + * Reset Current Field Values + * + * @var $field string Name of input field + * + * @return void + */ + private function resetCurrentField($field) { + + $this->field = array( + 'name' => $field, + 'value' => false, + 'status' => false, + 'message' => false + ); + + } + + /* + * Get input from specified source + * + * @field string Name of field + * @source string Source for field + * + * @return mixed Value from field or false. Also sets $this->status + * + */ + private function getInputValue($fieldSpec) + { + + // Check if field name supplied + if (trim($fieldSpec['name']) == '') { + $this->field['status'] = 'NAME_NOT_SUPPLIED'; + return false; + } + + // Check if source is valid + if (!in_array($fieldSpec['source'], $this->glmIoSources)) { + $this->field['status'] = 'INVALID_SOURCE'; + return false; + } + + // Check if field exists + if (!isset($GLOBALS['_'.$source][$fieldSpec['name']])) { + $this->field['status'] = 'MISSING'; + return false; + } + + // Get trimmed input from field + $in = trim($GLOBALS['_'.$source][$fieldSpec['name']]); + + // Check if input wasn't supplied + if (trim($in) == '') { + $this->field['status'] = 'NOT_SUPPLIED'; + return false; + } + + $this->field['status'] = 'UNPROCESSED'; + return $in; + } + + + /* + * Process Filter: integer + * + * Gets additional filter parameters and options from $fieldSpec + * + * @in mixed Raw input value + * @var $fieldSpec Field Specification Array + * + * @return void Sets $this->status values + * + */ + private function filter_integer($in, $fieldSpec) + { + // Validate supplied value as an integer using PHP filter + $i = filter_var($in, FILTER_VALIDATE_INT); + + // Assume we're going to have a clean value when we're done + $this->field['status'] = 'CLEAN'; + + // Check if filter failed + if ($i === false) { + $this->field['status'] = 'INVALID'; + + // Otherwise Check valid minimum value + } elseif ($fieldSpec['min_value'] != false && $fieldSpec['min_value'] > $i) { + $this->field['status'] = 'TOO_LOW'; + + // Otherwise check maximum value + } elseif ($fieldSpec['max_value'] != false && $fieldSpec['max_value'] < $i) { + $this->field['status'] = 'TOO_HIGH'; + } + + // Make darn'd sure value is an integer + $i = $i - 0; + + // Save value to current field information + $this->field['value'] = $i; + + return; + } + + /* + * Process Filter: text + * + * Gets additional filter parameters and options from $fieldSpec + * + * @var $in mixed Raw input value + * @var $fieldSpec Field Specification Array + * + * @return void Sets $this->status values + * + */ + private function filter_text($in, $fieldSpec) + { + // Check for text filter options + if ($fieldSpec['options']) + + // Validate supplied value as a string using PHP filter + $i = filter_var($in, FILTER_SANITIZE_STRING); + + // Assume we're going to have a clean value when we're done + $this->field['status'] = 'CLEAN'; + + // Check if filter failed + if ($i === false) { + $this->field['status'] = 'INVALID'; + + // Otherwise Check valid minimum value + } elseif ($fieldSpec['min_length'] != false && $fieldSpec['min_length'] > strlen($i)) { + $this->field['status'] = 'TOO_SHORT'; + + // Otherwise check maximum value + } elseif ($fieldSpec['max_length'] != false && $fieldSpec['max_length'] < strlen($i)) { + $this->field['status'] = 'TOO_LONG'; + } + + // Save value to current field information + $this->field['value'] = $i; + + return; + } + + +} +?> \ No newline at end of file diff --git a/models/admin/add/index.php b/models/admin/add/index.php index 80d23c3..8228b57 100644 --- a/models/admin/add/index.php +++ b/models/admin/add/index.php @@ -14,6 +14,9 @@ * @link http://dev.gaslightmedia.com/ */ +// include Input/Output support class +require_once GLM_PROTO_PLUGIN_DIR.'/lib/glmInputOutputSupport.php'; + /* * This class performs the work needed to add a new prototype. * @@ -27,7 +30,7 @@ * post_type 'glm_proto' * */ -class glmProtoAdmin_add_index +class glmProtoAdmin_add_index extends glmInputoutputSupport { /** @@ -97,10 +100,18 @@ class glmProtoAdmin_add_index 'glm_proto_width_error' => '', 'glm_proto_height' => '1200', 'glm_proto_height_error' => '', + 'glm_proto_html' => '', + 'glm_proto_html_error' => '', 'glm_proto_background' => '', 'glm_proto_background_error' => '', 'glm_proto_prototype' => '', - 'glm_proto_prototype_error' => '' + 'glm_proto_prototype_error' => '', + 'glm_proto_image3' => '', + 'glm_proto_image3_error' => '', + 'glm_proto_image4' => '', + 'glm_proto_image4_error' => '', + 'glm_proto_image5' => '', + 'glm_proto_image5_error' => '' ); /* @@ -110,6 +121,17 @@ class glmProtoAdmin_add_index $submitted = false; if (isset($_REQUEST['glm_proto_title'])) { +/* Work on this later + // Test input validation + $fields = array( + $this->createFieldDefArray('glm_proto_title', 'text', true, false, 4, 9), + $this->createFieldDefArray('glm_proto_width', 'integer', true), + $this->createFieldDefArray('glm_proto_height', 'integer', true) + ); + + $clean = $this->inputValidateArray($fields); +*/ + // Clean up all input $content['glm_proto_title'] = sanitize_text_field( $_REQUEST['glm_proto_title']); @@ -117,10 +139,17 @@ class glmProtoAdmin_add_index $_REQUEST['glm_proto_width']); $content['glm_proto_height'] = sanitize_text_field( $_REQUEST['glm_proto_height']); + $content['glm_proto_html'] = stripslashes($_REQUEST['glm_proto_html']); $content['glm_proto_background'] = sanitize_text_field( $_REQUEST['glm_proto_background']); $content['glm_proto_prototype'] = sanitize_text_field( $_REQUEST['glm_proto_prototype']); + $content['glm_proto_image3'] = sanitize_text_field( + $_REQUEST['glm_proto_image3']); + $content['glm_proto_image4'] = sanitize_text_field( + $_REQUEST['glm_proto_image4']); + $content['glm_proto_image5'] = sanitize_text_field( + $_REQUEST['glm_proto_image5']); // Check title field if ($content['glm_proto_title'] == '') { @@ -160,6 +189,27 @@ class glmProtoAdmin_add_index } } + // Check image #3 - Not required but must exist if provided + if ($content['glm_proto_image3'] != '' && ! $this->glmProtoIsUploaded( + $content['glm_proto_image3'])) { + $content['glm_proto_image3_error'] = 'Supplied image #3 does not exists'; + $submitError = true; + } + + // Check image #4 - Not required but must exist if provided + if ($content['glm_proto_image4'] != '' && ! $this->glmProtoIsUploaded( + $content['glm_proto_image4'])) { + $content['glm_proto_image4_error'] = 'Supplied image #4 does not exists'; + $submitError = true; + } + + // Check image #5 - Not required but must exist if provided + if ($content['glm_proto_image5'] != '' && ! $this->glmProtoIsUploaded( + $content['glm_proto_image5'])) { + $content['glm_proto_image3_error'] = 'Supplied image #5 does not exists'; + $submitError = true; + } + if (! $submitError) { // Prepair data for storage @@ -174,8 +224,12 @@ class glmProtoAdmin_add_index 'title' => $content['glm_proto_title'], 'width' => $content['glm_proto_width'], 'height' => $content['glm_proto_height'], + 'html' => $content['glm_proto_html'], 'background' => $content['glm_proto_background'], - 'prototype' => $content['glm_proto_prototype'] + 'prototype' => $content['glm_proto_prototype'], + 'image3' => $content['glm_proto_image3'], + 'image4' => $content['glm_proto_image4'], + 'image5' => $content['glm_proto_image5'] )); // Store into wp_posts table diff --git a/models/admin/prototypes/display.php b/models/admin/prototypes/display.php index 922ff6e..d9bf081 100644 --- a/models/admin/prototypes/display.php +++ b/models/admin/prototypes/display.php @@ -110,11 +110,13 @@ class glmProtoAdmin_prototypes_display } // Return status, any suggested view, and any data to controller + // If 'viewText' exists, it's parsed as smarty template source for output rather than the 'view' file. return array( 'status' => $success, 'menuItemRedirect' => false, 'modelRedirect' => false, 'view' => 'admin/prototypes/display.html', + 'viewText' => stripslashes($d['html']), 'data' => array( 'content' => $res['content'] ) diff --git a/models/admin/prototypes/edit.php b/models/admin/prototypes/edit.php index ba82e56..3c61a66 100644 --- a/models/admin/prototypes/edit.php +++ b/models/admin/prototypes/edit.php @@ -124,10 +124,18 @@ class glmProtoAdmin_prototypes_edit 'glm_proto_width_error' => '', 'glm_proto_height' => $content['height'], 'glm_proto_height_error' => '', + 'glm_proto_html' => stripslashes($content['html']), + 'glm_proto_html_error' => '', 'glm_proto_background' => $content['background'], 'glm_proto_background_error' => '', 'glm_proto_prototype' => $content['prototype'], - 'glm_proto_prototype_error' => '' + 'glm_proto_prototype_error' => '', + 'glm_proto_image3' => $content['image3'], + 'glm_proto_image3_error' => '', + 'glm_proto_image4' => $content['image4'], + 'glm_proto_image4_error' => '', + 'glm_proto_image5' => $content['image5'], + 'glm_proto_image5_error' => '' ); /* @@ -144,10 +152,17 @@ class glmProtoAdmin_prototypes_edit $_REQUEST['glm_proto_width']); $content['glm_proto_height'] = sanitize_text_field( $_REQUEST['glm_proto_height']); + $content['glm_proto_html'] = $_REQUEST['glm_proto_html']; $content['glm_proto_background'] = sanitize_text_field( $_REQUEST['glm_proto_background']); $content['glm_proto_prototype'] = sanitize_text_field( $_REQUEST['glm_proto_prototype']); + $content['glm_proto_image3'] = sanitize_text_field( + $_REQUEST['glm_proto_image3']); + $content['glm_proto_image4'] = sanitize_text_field( + $_REQUEST['glm_proto_image4']); + $content['glm_proto_image5'] = sanitize_text_field( + $_REQUEST['glm_proto_image5']); // Check title field if ($content['glm_proto_title'] == '') { @@ -187,6 +202,28 @@ class glmProtoAdmin_prototypes_edit } } + // Check image #3 - Not required but must exist if provided + if ($content['glm_proto_image3'] != '' && ! $this->glmProtoIsUploaded( + $content['glm_proto_image3'])) { + $content['glm_proto_image3_error'] = 'Supplied image #3 does not exists'; + $submitError = true; + } + + // Check image #4 - Not required but must exist if provided + if ($content['glm_proto_image4'] != '' && ! $this->glmProtoIsUploaded( + $content['glm_proto_image4'])) { + $content['glm_proto_image4_error'] = 'Supplied image #4 does not exists'; + $submitError = true; + } + + // Check image #5 - Not required but must exist if provided + if ($content['glm_proto_image5'] != '' && ! $this->glmProtoIsUploaded( + $content['glm_proto_image5'])) { + $content['glm_proto_image3_error'] = 'Supplied image #5 does not exists'; + $submitError = true; + } + + if (! $submitError) { // Prepair data for storage @@ -201,8 +238,12 @@ class glmProtoAdmin_prototypes_edit 'title' => $content['glm_proto_title'], 'width' => $content['glm_proto_width'], 'height' => $content['glm_proto_height'], + 'html' => $content['glm_proto_html'], 'background' => $content['glm_proto_background'], - 'prototype' => $content['glm_proto_prototype'] + 'prototype' => $content['glm_proto_prototype'], + 'image3' => $content['glm_proto_image3'], + 'image4' => $content['glm_proto_image4'], + 'image5' => $content['glm_proto_image5'] )); // Store into wp_posts table diff --git a/views/admin/add/index.html b/views/admin/add/index.html index 713453d..f4018d9 100644 --- a/views/admin/add/index.html +++ b/views/admin/add/index.html @@ -26,6 +26,14 @@ {if $content.glm_proto_height_error != ''}
{$content.glm_proto_height_error}{/if} + + + + + {if $content.glm_proto_html_error != ''}
{$content.glm_proto_html_error}{/if} +
Optional. If not supplied a standard page for background and foreground prototype will be used. + + @@ -42,6 +50,30 @@ {if $content.glm_proto_prototype_error != ''}
{$content.glm_proto_prototype_error}{/if} + + + + + + {if $content.glm_proto_image3_error != ''}
{$content.glm_proto_image3_error}{/if} + + + + + + + + {if $content.glm_proto_image4_error != ''}
{$content.glm_proto_image4_error}{/if} + + + + + + + + {if $content.glm_proto_image5_error != ''}
{$content.glm_proto_image5_error}{/if} + +   diff --git a/views/admin/prototypes/display.html b/views/admin/prototypes/display.html index 7689f9e..87123cf 100644 --- a/views/admin/prototypes/display.html +++ b/views/admin/prototypes/display.html @@ -1,11 +1,18 @@ + +{if $content.html != ''} + {$content.html} +{else} + Prototype: {$content.title} - +
+ +{/if} \ No newline at end of file diff --git a/views/admin/prototypes/edit.html b/views/admin/prototypes/edit.html index 5d627b7..636db31 100644 --- a/views/admin/prototypes/edit.html +++ b/views/admin/prototypes/edit.html @@ -26,6 +26,13 @@ {if $content.glm_proto_height_error != ''}
{$content.glm_proto_height_error}{/if} + + + + {if $content.glm_proto_html_error != ''}
{$content.glm_proto_html_error}{/if} +
Optional. If not supplied a standard page for background and foreground prototype will be used. + + @@ -42,6 +49,30 @@ {if $content.glm_proto_prototype_error != ''}
{$content.glm_proto_prototype_error}{/if} + + + + + + {if $content.glm_proto_image3_error != ''}
{$content.glm_proto_image3_error}{/if} + + + + + + + + {if $content.glm_proto_image4_error != ''}
{$content.glm_proto_image4_error}{/if} + + + + + + + + {if $content.glm_proto_image5_error != ''}
{$content.glm_proto_image5_error}{/if} + +   diff --git a/views/admin/prototypes/index.html b/views/admin/prototypes/index.html index 6afe6dc..26a8843 100644 --- a/views/admin/prototypes/index.html +++ b/views/admin/prototypes/index.html @@ -10,7 +10,7 @@

List of Prototypes

- +
@@ -18,11 +18,23 @@ + + + + + + + {if $haveData} + {assign var="i" value="0"} {foreach $prototypes as $p} + {if $i++ is odd by 1} + {else} + + {/if}
Date 
DatePrototype Name 
{$p.p_date} {$p.post_title} -- 2.17.1