From ce2be28750ad608be15a59fa1715dc5aa340f4e1 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Thu, 16 Jan 2014 16:45:53 -0600
Subject: [PATCH] forms: Fix ambiguous id / value for typeahead

If a dynamic list is displayed as a typeahead box, the value, when saved,
will be confused with the corresponding ID field for the list. MySQL
supports numeric comparison between the INT id column and the textual value
column. Therefore, if a typeahead field has the value of '01 - GooGoo', then
record will match the ListItem<id=1>, regardless of which list the item is
defined for.

This patch resolves the issue by submitting the ID number of the list
selection in the HTTP form.
---
 include/class.dynamic_forms.php | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/include/class.dynamic_forms.php b/include/class.dynamic_forms.php
index ccfe4d27e..8e4df839a 100644
--- a/include/class.dynamic_forms.php
+++ b/include/class.dynamic_forms.php
@@ -878,11 +878,16 @@ class SelectionField extends FormField {
     }
 
     function parse($value) {
-        return $this->to_php($value);
+        $config = $this->getConfiguration();
+        if (is_int($value) || !$config['typeahead'])
+            return $this->to_php(null, (int) $value);
+        else
+            return $this->to_php($value);
     }
 
     function to_php($value, $id=false) {
-        $item = DynamicListItem::lookup($id ? $id : $value);
+        if ($id && is_int($id))
+            $item = DynamicListItem::lookup($id);
         # Attempt item lookup by name too
         if (!$item) {
             $item = DynamicListItem::lookup(array(
@@ -951,7 +956,7 @@ class SelectionWidget extends ChoicesWidget {
         $source = array();
         foreach ($this->field->getList()->getItems() as $i)
             $source[] = array(
-                'value' => $i->get('value'),
+                'value' => $i->get('value'), 'id' => $i->get('id'),
                 'info' => $i->get('value')." -- ".$i->get('extra'),
             );
         ?>
@@ -959,6 +964,8 @@ class SelectionWidget extends ChoicesWidget {
         <input type="text" size="30" name="<?php echo $this->name; ?>"
             id="<?php echo $this->name; ?>" value="<?php echo $name; ?>"
             autocomplete="off" />
+        <input type="hidden" name="<?php echo $this->name;
+            ?>_id" id="<?php echo $this->name; ?>_id" value="<?php echo $value; ?>"/>
         <script type="text/javascript">
         $(function() {
             $('input#<?php echo $this->name; ?>').typeahead({
@@ -966,6 +973,7 @@ class SelectionWidget extends ChoicesWidget {
                 property: 'info',
                 onselect: function(item) {
                     $('input#<?php echo $this->name; ?>').val(item['value'])
+                    $('input#<?php echo $this->name; ?>_id').val(item['id'])
                 }
             });
         });
@@ -973,5 +981,13 @@ class SelectionWidget extends ChoicesWidget {
         </span>
         <?php
     }
+
+    function getValue() {
+        $data = $this->field->getSource();
+        // Search for HTML form name first
+        if (isset($data[$this->name.'_id']))
+            return (int) $data[$this->name.'_id'];
+        return parent::getValue();
+    }
 }
 ?>
-- 
GitLab