From 4a9908d9aa3d0f50d4907eb25e6fc1d317061484 Mon Sep 17 00:00:00 2001
From: Malf Furious <m@lfurio.us>
Date: Tue, 27 Jun 2017 01:35:26 -0400
Subject: Add form class

---
 app/class/form.class.php | 179 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 179 insertions(+)
 create mode 100644 app/class/form.class.php

(limited to 'app/class')

diff --git a/app/class/form.class.php b/app/class/form.class.php
new file mode 100644
index 0000000..8f9d936
--- /dev/null
+++ b/app/class/form.class.php
@@ -0,0 +1,179 @@
+<?php
+
+/*
+ * SCROTT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to UNLICENSE
+ */
+
+/*
+ * Model web-forms and simplify the process of accepting, validating, and
+ * sanitizing user input.
+ */
+class form
+{
+    /*
+     * These arrays track the meta-data of all fields defined on this
+     * form.  This mainly includes their type, range (if numeric), and
+     * whether or not the field is required.
+     */
+    private $textFields = array();
+    private $numbFields = array();
+    private $enumFields = array();
+
+    /*
+     * Add new text field to this form
+     */
+    public function text(string $name, bool $required = true,
+        string $deflt = "") : void
+    {
+        $this->textFields[] = array(
+            'name' => $name,
+            'required' => $required,
+            'default' => $deflt,
+        );
+    }
+
+    /*
+     * Add new numeric field to this form
+     */
+    public function numeric(string $name, ?int $min = NULL, ?int $max = NULL,
+        int $deflt = 0, bool $isInt = true, bool $required = true) : void
+    {
+        $this->numbFields[] = array(
+            'name' => $name,
+            'min' => $min,
+            'max' => $max,
+            'default' => $deflt,
+            'isInt' => $isInt,
+            'required' => $required,
+        );
+    }
+
+    /*
+     * Add new enumeration field to this form
+     */
+    public function enum(string $name, array $values, $deflt = NULL,
+        bool $required = true) : void
+    {
+        $this->enumFields[] = array(
+            'name' => $name,
+            'values' => $values,
+            'default' => $deflt,
+            'required' => $required,
+        );
+    }
+
+    /*
+     * Add new boolean field to this form
+     */
+    public function flag(string $name) : void
+    {
+        $this->enum($name, array("1", "0"), "0", false);
+    }
+
+    /*
+     * Populate this form with input data from web page.  If an error
+     * is encountered, or a required field is missing, false is returned.
+     */
+    public function populate(array $input) : bool
+    {
+        /* detect duplicate names */
+        $names = array();
+
+        foreach ($this->textFields as $field)
+            $names[] = $field['name'];
+
+        foreach ($this->numbFields as $field)
+            $names[] = $field['name'];
+
+        foreach ($this->enumFields as $field)
+            $names[] = $field['name'];
+
+        if (count(array_unique($names)) != count($names))
+            throw new Exception("Internal error: Duplicate field names defined in form");
+
+        /* init text fields */
+        foreach ($this->textFields as $field)
+        {
+            if (isset($input[$field['name']]) && $input[$field['name']] != "")
+                $this->{$field['name']} = htmlentities($input[$field['name']], ENT_QUOTES);
+
+            else if ($field['required'])
+                logError(ERROR, $field['name'] . " is required");
+
+            else
+                $this->{$field['name']} = $field['default'];
+        }
+
+        /* init numeric fields */
+        foreach ($this->numbFields as $field)
+        {
+            if (isset($input[$field['name']]) && $input[$field['name']] != "")
+            {
+                if (!is_numeric($input[$field['name']]))
+                {
+                    logError(ERROR, $field['name'] . " must be numeric");
+                    continue;
+                }
+
+                if ($field['isInt'] && (floor($input[$field['name']]) != $input[$field['name']]))
+                {
+                    logError(ERROR, $field['name'] . " must be an integer");
+                    continue;
+                }
+
+                if (!is_null($field['min']) && ($input[$field['name']] < $field['min']))
+                {
+                    logError(ERROR, $field['name'] . " must be no less than " . $field['min']);
+                    continue;
+                }
+
+                if (!is_null($field['max']) && ($input[$field['name']] > $field['max']))
+                {
+                    logError(ERROR, $field['name'] . " must be no more than " . $field['max']);
+                    continue;
+                }
+
+                $this->{$field['name']} = $input[$field['name']];
+            }
+
+            else if ($field['required'])
+                logError(ERROR, $field['name'] . " is required");
+
+            else
+                $this->{$field['name']} = $field['default'];
+        }
+
+        /* init enum fields */
+        foreach ($this->enumFields as $field)
+        {
+            if (isset($input[$field['name']]) && $input[$field['name']] != "")
+            {
+                if (array_search($input[$field['name']], $field['values']) === false)
+                {
+                    logError(ERROR, $field['name'] . " is not an appropriate value");
+                    continue;
+                }
+
+                $this->{$field['name']} = $input[$field['name']];
+            }
+
+            else if ($field['required'])
+                logError(ERROR, $field['name'] . " is required");
+
+            else
+                $this->{$field['name']} = $field['default'];
+        }
+
+        return !isError(ERROR);
+    }
+}
+
+?>
-- 
cgit v1.2.3