From dd3f569ede8ee53737d0643a515dfd3a2084e934 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur <eldy@destailleur.fr> Date: Fri, 6 Mar 2015 20:34:00 +0100 Subject: [PATCH] NEW: Enhance the natural_search function so we can use it to search numeric fields with criteria with operator <>= inside (< 100, >= 1000) --- htdocs/core/lib/functions.lib.php | 68 ++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 19 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 438f0ee22ca..c5d8d509b08 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -4946,34 +4946,64 @@ function dol_getmypid() /** - * Natural search - * - * @param mixed $fields String or array of strings filled with the fields names in the SQL query - * @param string $value The value to look for (example: "keyword1 keyword2") - * @return string $res The statement to append to the SQL query - */ -function natural_search($fields, $value) -{ - global $db; + * Generate natural SQL search string + * + * @param string|string[] $fields String or array of strings, filled with the name of fields in the SQL query + * @param string $value The value to look for. + * If param $numeric is 0, can contains several keywords separated with a space, like "keyword1 keyword2" = We want record field like keyword1 and field like keyword2 + * If param $numeric is 1, can contains an operator <>= like "<10" or ">=100.5 < 1000" + * @param string $number 0=value is list of keywords, 1=value is a numeric test + * @return string $res The statement to append to the SQL query + */ +function natural_search($fields, $value, $numeric=0) +{ + global $db,$langs; + + if ($numeric) + { + $value=preg_replace('/([<>=]+)\s([0-9'.preg_quote($langs->trans("DecimalSeparator"),'/').'])/','\1\2',$value); // Clean string '< 10' into '<10' so we can the explode on space to get all tests to do + } $crits = explode(' ', $value); $res = ''; if (! is_array($fields)) $fields = array($fields); - $end = count($fields); + $nboffields = count($fields); $end2 = count($crits); $j = 0; - foreach ($crits as $crit) { - $i = 0; - foreach ($fields as $field) { - if ( $i > 0 && $i < $end) $res .= " OR "; - $res .= $field . " LIKE '%" . $db->escape(trim($crit)) . "%'"; + foreach ($crits as $crit) + { + $i = 0; $i2 = 0; + $newres = ''; + foreach ($fields as $field) + { + if ($numeric) + { + $operator='='; + $newcrit = preg_replace('/([<>=]+)/','',trim($crit)); + + preg_match('/([<>=]+)/',trim($crit), $reg); + if ($reg[1]) + { + $operator = $reg[1]; + } + if ($newcrit != '') + { + $newres .= ($i2 > 0 ? ' OR ' : '') . $field . ' '.$operator.' '.price2num($newcrit); + $i2++; // a criteria was added to string + } + } + else + { + $newres .= ($i2 > 0 ? ' OR ' : '') . $field . " LIKE '%" . $db->escape(trim($crit)) . "%'"; + $i2++; // a criteria was added to string + } $i++; } - if ($end > 1) $res .= ')'; - if ($j < $end2 - 1) $res .= " AND "; - if ($end > 1 && $j < $end2 - 1) $res .= '('; + if ($newres) $res = $res . ($res ? ' AND ' : '') . ($i2 > 1 ? '(' : '') .$newres . ($i2 > 1 ? ')' : ''); $j++; } - return " AND " . ($end > 1? '(' : '') . $res; + $res = " AND (" . $res . ")"; + //print 'xx'.$res.'yy'; + return $res; } -- GitLab