From 81bcb80a0d04d8e7e14f36a2ec195856bf370279 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Tue, 29 Oct 2013 14:02:53 +0000
Subject: [PATCH] Allow both internal and required fields

Previously, clients would not be able to create tickets if an internal,
required field existed on any of the forms presented to the user. Instead,
they would be stuck at permanent validation failure because there was no
data for a required field not shown.

This patch adds a feature to the form and dynamicFormEntry objects'
isValid() method to receive a callable to filter which fields' errors should
be added to the form's errors list. This allows for more complex validation
where in some cases, validation errors should not be considered on some
fields.

Fixes #45
---
 include/class.dynamic_forms.php | 11 +++++++++--
 include/class.forms.php         | 11 +++++++++--
 include/class.ticket.php        | 15 ++++++++++++++-
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index e0a2f1e86..cdb2606dd 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -375,12 +375,19 @@ class DynamicFormEntry extends VerySimpleModel {
         return $this->_fields;
     }
 
-    function isValid() {
+    /**
+     * Validate the form and indicate if there no errors.
+     *
+     * Parameters:
+     * $filter - (callback) function to receive each field and return
+     *      boolean true if the field's errors are significant
+     */
+    function isValid($include=false) {
         if (!is_array($this->_errors)) {
             $this->_errors = array();
             $this->getClean();
             foreach ($this->getFields() as $field)
-                if ($field->errors())
+                if ($field->errors() && (!$include || $include($field)))
                     $this->_errors[$field->get('id')] = $field->errors();
         }
         return !$this->_errors;
diff --git a/include/class.forms.php b/include/class.forms.php
index 6385f4190..4250e258c 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -53,12 +53,19 @@ class Form {
     function getInstructions() { return $this->instructions; }
     function getSource() { return $this->_source; }
 
-    function isValid() {
+    /**
+     * Validate the form and indicate if there no errors.
+     *
+     * Parameters:
+     * $filter - (callback) function to receive each field and return
+     *      boolean true if the field's errors are significant
+     */
+    function isValid($include=false) {
         if (!is_array($this->_errors)) {
             $this->_errors = array();
             $this->getClean();
             foreach ($this->getFields() as $field)
-                if ($field->errors())
+                if ($field->errors() && (!$include || $include($field)))
                     $this->_errors[$field->get('id')] = $field->errors();
         }
         return !$this->_errors;
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 82cc169a5..5684d3f48 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -1901,7 +1901,20 @@ class Ticket {
         }
 
         // Don't enforce form validation for email
-        if (!$form->isValid() && strtolower($origin) != 'email')
+        $field_filter = function($f) use ($origin) {
+            // Ultimately, only offer validation errors for web for
+            // non-internal fields. For email, no validation can be
+            // performed. For other origins, validate as usual
+            switch (strtolower($origin)) {
+            case 'email':
+                return false;
+            case 'web':
+                return !$f->get('private');
+            default:
+                return true;
+            }
+        };
+        if (!$form->isValid($field_filter))
             $errors += $form->errors();
 
         // Unpack dynamic variables into $vars for filter application
-- 
GitLab