diff --git a/include/class.json.php b/include/class.json.php index ad5ac65c12e3da2c939faecdb67dfec3f049c635..66edb7623e4944cc4ab30b763740993294652f5a 100644 --- a/include/class.json.php +++ b/include/class.json.php @@ -21,25 +21,39 @@ include_once "JSON.php"; class JsonDataParser { - function parse($stream) { + function parse($stream, $tidy=false) { if (is_resource($stream)) { $contents = ''; while (!feof($stream)) $contents .= fread($stream, 8192); } else $contents = $stream; + + if ($contents && $tidy) + $contents = self::tidy($contents); + return self::decode($contents); } - function decode($contents) { - if (function_exists("json_decode")) { - return json_decode($contents, true); - } else { - # Create associative arrays rather than 'objects' - $decoder = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); - return $decoder->decode($contents); - } + static function decode($contents, $assoc=true) { + if (function_exists("json_decode")) + return json_decode($contents, $assoc); + + $decoder = new Services_JSON($assoc ? SERVICES_JSON_LOOSE_TYPE : 0); + return $decoder->decode($contents); } + + static function tidy($content) { + + // Clean up doubly quoted JSON + $content = str_replace( + array(':"{', '}"', '\"'), + array(':{', '}', '"'), + $content); + // return trimmed content. + return trim($content); + } + function lastError() { if (function_exists("json_last_error")) { $errors = array( diff --git a/include/class.queue.php b/include/class.queue.php index b037d4eee0769d5e7ad4d291e1cc5e24d1b9537e..284853a4412dea0b370935835be42cfa5c3a89e0 100644 --- a/include/class.queue.php +++ b/include/class.queue.php @@ -123,7 +123,9 @@ class CustomQueue extends VerySimpleModel { && !isset($this->criteria['conditions']) ) { // TODO: Upgrade old ORM path names - $this->criteria = $this->isolateCriteria($this->criteria); + // Parse criteria out of JSON if any. + $this->criteria = self::isolateCriteria($this->criteria, + $this->getRoot()); } } $criteria = $this->criteria ?: array(); @@ -460,11 +462,13 @@ class CustomQueue extends VerySimpleModel { * field name being search, the method used for searhing, and the method- * specific data entered in the UI. */ - function isolateCriteria($criteria, $root=null) { - $searchable = static::getSearchableFields($root ?: $this->getRoot()); - $items = array(); + static function isolateCriteria($criteria, $base='Ticket') { + if (!is_array($criteria)) return null; + + $items = array(); + $searchable = static::getSearchableFields($base); foreach ($criteria as $k=>$v) { if (substr($k, -7) === '+method') { list($name,) = explode('+', $k, 2); @@ -477,9 +481,8 @@ class CustomQueue extends VerySimpleModel { // Lookup the field to search this condition list($label, $field) = $searchable[$name]; - - // Get the search method and value - $method = $v; + // Get the search method + $method = is_array($v) ? key($v) : $v; // Not all search methods require a value $value = $criteria["{$name}+{$method}"]; @@ -1154,7 +1157,8 @@ class CustomQueue extends VerySimpleModel { } else { $this->config = JsonDataEncoder::encode([ - 'criteria' => $this->isolateCriteria($form->getClean()), + 'criteria' => self::isolateCriteria($form->getClean(), + $this->getRoot()), 'conditions' => $conditions, ]); // Clear currently set criteria.and conditions. @@ -1650,8 +1654,8 @@ class QueueColumnCondition { * field name being search, the method used for searhing, and the method- * specific data entered in the UI. */ - static function isolateCriteria($criteria, $root='Ticket') { - $searchable = CustomQueue::getSearchableFields($root); + static function isolateCriteria($criteria, $base='Ticket') { + $searchable = CustomQueue::getSearchableFields($base); foreach ($criteria as $k=>$v) { if (substr($k, -7) === '+method') { list($name,) = explode('+', $k, 2); diff --git a/include/mysqli.php b/include/mysqli.php index 998d286590d08ff8f8ea6c78ad072b28ee7600f2..efb459f334b9d8a6ffc7899fca51caf08d2f25cc 100644 --- a/include/mysqli.php +++ b/include/mysqli.php @@ -234,7 +234,7 @@ function db_fetch_field($res) { return ($res) ? $res->fetch_field() : NULL; } -function db_assoc_array($res, $mode=false) { +function db_assoc_array($res, $mode=MYSQLI_ASSOC) { $result = array(); if($res && db_num_rows($res)) { while ($row=db_fetch_array($res, $mode)) diff --git a/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php b/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php index 29a3a4b8c71c1a2cfbf191f03f8cb8fc2fb032c8..886bcf6ebb0a7f53102efc66672e18073a032e29 100644 --- a/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php +++ b/include/upgrader/streams/core/934b8db8-ad9d0a5f.task.php @@ -9,14 +9,32 @@ class QueueSortCreator extends MigrationTask { foreach ($columns as $C) { QueueColumn::__create($C); } - // Make room for the new queues starting at ID 1 - $id = new SqlField('id'); - CustomQueue::objects()->update(['id' => $id->plus(30)]); + + // Save old records + $old = db_assoc_array(db_query('SELECT * FROM '.QUEUE_TABLE)); + // Truncate Queue table - make room for the new queues starting at ID 1 + db_query('TRUNCATE TABLE '.QUEUE_TABLE); $queues = $i18n->getTemplate('queue.yaml')->getData(); foreach ($queues as $C) { CustomQueue::__create($C); } + // Re-insert old saved searches + foreach ($old ?: array() as $row) { + // Only save entries with "valid" criteria + if (!$row['title'] + || !($config = JsonDataParser::parse($row['config'], true)) + || !($criteria = CustomQueue::isolateCriteria($criteria))) + continue; + + $row['config'] = JsonDataEncoder::encode(array( + 'criteria' => $criteria, 'conditions' => array())); + $row['root'] = 'T'; + CustomQueue::__create(array_intersect_key($row, array_flip( + array('staff_id', 'title', 'config', 'flags', + 'root', 'created', 'updated')))); + } + $columns = $i18n->getTemplate('queue_sort.yaml')->getData(); foreach ($columns as $C) { QueueSort::__create($C);