From ba2db321c647b99c51daa4c358164e43ad308095 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Thu, 22 May 2014 10:14:39 -0500
Subject: [PATCH] Add concept of client-only form fields

---
 include/class.dynamic_forms.php               | 77 ++++++++++++++++++-
 include/class.forms.php                       |  2 +-
 include/class.user.php                        |  6 +-
 .../client/templates/dynamic-form.tmpl.php    |  2 +-
 include/staff/dynamic-form.inc.php            | 22 +++---
 include/staff/templates/dynamic-form.tmpl.php |  7 ++
 scp/forms.php                                 |  6 +-
 7 files changed, 100 insertions(+), 22 deletions(-)

diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index b8b040735..2cf45e83c 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -480,6 +480,74 @@ class DynamicFormField extends VerySimpleModel {
         return (($this->get('edit_mask') & 32) == 0);
     }
 
+    function allRequirementModes() {
+        $modes = array(
+            'a' => array('desc' => 'Optional',
+                'private' => 0, 'required' => 0),
+            'b' => array('desc' => 'Required',
+                'private' => 0, 'required' => 1),
+            'c' => array('desc' => 'Required for Users',
+                'private' => 0, 'required' => 2),
+            'd' => array('desc' => 'Required for Agents',
+                'private' => 0, 'required' => 3),
+            'e' => array('desc' => 'Internal, Optional',
+                'private' => 1, 'required' => 0),
+            'f' => array('desc' => 'Internal, Required',
+                'private' => 1, 'required' => 1),
+            'g' => array('desc' => 'For Users Only',
+                'private' => 2, 'required' => 2),
+        );
+
+        if ($this->isPrivacyForced()) {
+            // Required to be internal
+            foreach ($modes as $m=>$info) {
+                if ($info['private'] != $this->get('private'))
+                    unset($modes[$m]);
+            }
+        }
+
+        if ($this->isRequirementForced()) {
+            // Required to be required
+            foreach ($modes as $m=>$info) {
+                if ($info['required'] != $this->get('required'))
+                    unset($modes[$m]);
+            }
+        }
+        return $modes;
+    }
+
+    function getRequirementMode() {
+        foreach ($this->allRequirementModes() as $m=>$info) {
+            if ($this->get('private') == $info['private']
+                    && $this->get('required') == $info['required'])
+                return $m;
+        }
+        return false;
+    }
+
+    function setRequirementMode($mode) {
+        $modes = $this->allRequirementModes();
+        if (!isset($modes[$mode]))
+            return false;
+
+        $info = $modes[$mode];
+        $this->set('required', $info['required']);
+        $this->set('private', $info['private']);
+    }
+
+    function isRequiredForStaff() {
+        return in_array($this->get('required'), array(1, 3));
+    }
+    function isRequiredForUsers() {
+        return in_array($this->get('required'), array(1, 2));
+    }
+    function isVisibleToStaff() {
+        return in_array($this->get('private'), array(0, 1));
+    }
+    function isVisibleToUsers() {
+        return in_array($this->get('private'), array(0, 2));
+    }
+
     /**
      * Used when updating the form via the admin panel. This represents
      * validation on the form field template, not data entered into a form
@@ -652,11 +720,16 @@ class DynamicFormEntry extends VerySimpleModel {
     }
 
     function isValidForClient() {
-
         $filter = function($f) {
-            return !$f->get('private');
+            return !$f->isRequiredForUsers();
         };
+        return $this->isValid($filter);
+    }
 
+    function isValidForStaff() {
+        $filter = function($f) {
+            return !$f->isRequiredForStaff();
+        };
         return $this->isValid($filter);
     }
 
diff --git a/include/class.forms.php b/include/class.forms.php
index 1c1f70178..c80c9a682 100644
--- a/include/class.forms.php
+++ b/include/class.forms.php
@@ -86,7 +86,7 @@ class Form {
         if (!$this->_clean) {
             $this->_clean = array();
             foreach ($this->getFields() as $key=>$field) {
-                if (!$field->hasData())
+                if ($field->isPresentationOnly())
                     continue;
                 $this->_clean[$key] = $this->_clean[$field->get('name')]
                     = $field->getClean();
diff --git a/include/class.user.php b/include/class.user.php
index 19f83efaf..6ec2c5a94 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -194,12 +194,16 @@ class User extends UserModel {
     }
 
     static function fromForm($form) {
+        global $thisstaff;
 
         if(!$form) return null;
 
         //Validate the form
         $valid = true;
-        if (!$form->isValid())
+        $filter = function($f) use ($thisstaff) {
+            return !isset($thisstaff) || $f->isRequiredForStaff();
+        };
+        if (!$form->isValid($filter))
             $valid  = false;
 
         //Make sure the email is not in-use
diff --git a/include/client/templates/dynamic-form.tmpl.php b/include/client/templates/dynamic-form.tmpl.php
index 57f1aa295..12b394407 100644
--- a/include/client/templates/dynamic-form.tmpl.php
+++ b/include/client/templates/dynamic-form.tmpl.php
@@ -16,7 +16,7 @@
     // 'private' are not included in the output for clients
     global $thisclient;
     foreach ($form->getFields() as $field) {
-        if ($field->get('private'))
+        if (!$field->isVisibleToUsers())
             continue;
         ?>
         <tr>
diff --git a/include/staff/dynamic-form.inc.php b/include/staff/dynamic-form.inc.php
index e0bf6a455..44d41081d 100644
--- a/include/staff/dynamic-form.inc.php
+++ b/include/staff/dynamic-form.inc.php
@@ -124,8 +124,7 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
         $id = $f->get('id');
         $deletable = !$f->isDeletable() ? 'disabled="disabled"' : '';
         $force_name = $f->isNameForced() ? 'disabled="disabled"' : '';
-        $force_privacy = $f->isPrivacyForced() ? 'disabled="disabled"' : '';
-        $force_required = $f->isRequirementForced() ? 'disabled="disabled"' : '';
+        $rmode = $f->getRequirementMode();
         $fi = $f->getImpl();
         $ferrors = $f->errors(); ?>
         <tr>
@@ -157,17 +156,14 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                         $.dialog($(this).attr('href').substr(1), [201]);
                         return false;
                     "><i class="icon-edit"></i> <?php echo __('Config'); ?></a>
-            <?php } ?>
-            <div class="error" style="white-space:normal"><?php
-                if ($ferrors['type']) echo $ferrors['type'];
-            ?></div>
-            </td>
-            <td><input type="checkbox" name="private-<?php echo $id; ?>"
-                <?php if ($f->get('private')) echo 'checked="checked"'; ?>
-                <?php echo $force_privacy ?>/></td>
-            <td><input type="checkbox" name="required-<?php echo $id; ?>"
-                <?php if ($f->get('required')) echo 'checked="checked"'; ?>
-                <?php echo $force_required ?>/>
+            <?php } ?></td>
+            <td colspan="2">
+                <select name="requirement-<?php echo $id; ?>">
+<?php foreach ($f->allRequirementModes() as $m=>$info) { ?>
+    <option value="<?php echo $m; ?>" <?php if ($rmode == $m)
+         echo 'selected="selected"'; ?>><?php echo $info['desc']; ?></option>
+<?php } ?>
+                <select>
             </td>
             <td>
                 <input type="text" size="20" name="name-<?php echo $id; ?>"
diff --git a/include/staff/templates/dynamic-form.tmpl.php b/include/staff/templates/dynamic-form.tmpl.php
index 79ebe981b..611306d1b 100644
--- a/include/staff/templates/dynamic-form.tmpl.php
+++ b/include/staff/templates/dynamic-form.tmpl.php
@@ -39,6 +39,13 @@ if (isset($options['entry']) && $options['mode'] == 'edit') { ?>
     <?php
     }
     foreach ($form->getFields() as $field) {
+        try {
+            if (!$field->isVisibleToStaff())
+                continue;
+        }
+        catch (Exception $e) {
+            // Not connected to a DynamicFormField
+        }
         ?>
         <tr><?php if ($field->isBlockLevel()) { ?>
                 <td colspan="2">
diff --git a/scp/forms.php b/scp/forms.php
index dae8ecaf7..5d174d5a3 100644
--- a/scp/forms.php
+++ b/scp/forms.php
@@ -38,10 +38,8 @@ if($_POST) {
                 if (isset($_POST["name-$id"]) && !$field->isNameForced())
                     $field->set('name', $_POST["name-$id"]);
                 # TODO: make sure all help topics still have all required fields
-                if (!$field->isRequirementForced())
-                    $field->set('required', $_POST["required-$id"] == 'on' ?  1 : 0);
-                if (!$field->isPrivacyForced())
-                    $field->set('private', $_POST["private-$id"] == 'on' ?  1 : 0);
+                $field->setRequirementMode($_POST["requirement-$id"]);
+
                 foreach (array('sort','label') as $f) {
                     if (isset($_POST["$f-$id"])) {
                         $field->set($f, $_POST["$f-$id"]);
-- 
GitLab