diff --git a/functions-5-2.php b/functions-5-2.php index f30fcb3..ed12dea 100644 --- a/functions-5-2.php +++ b/functions-5-2.php @@ -478,14 +478,21 @@ class PDOSQLiteUDFS { * @return unsigned integer */ public function field() { + global $wpdb; $numArgs = func_num_args(); if ($numArgs < 2 or is_null(func_get_arg(0))) { return 0; + } else { + $arg_list = func_get_args(); } - $arr = func_get_args(); - $searchString = strtolower(array_shift($arr)); + $searchString = array_shift($arg_list); + $str_to_check = substr($searchString, 0, strpos($searchString, '.')); + $str_to_check = str_replace($wpdb->prefix, '', $str_to_check); + if ($str_to_check && in_array(trim($str_to_check), $wpdb->tables)) return; for ($i = 0; $i < $numArgs-1; $i++) { - if ($searchString === strtolower($arr[$i])) return $i + 1; + if ($searchString === strtolower($arg_list[$i])) { + return $i + 1; + } } return 0; } diff --git a/functions.php b/functions.php index f9f3b28..c491116 100644 --- a/functions.php +++ b/functions.php @@ -442,6 +442,7 @@ class PDOSQLiteUDFS { * @return unsigned integer */ public function field() { + global $wpdb; $numArgs = func_num_args(); if ($numArgs < 2 or is_null(func_get_arg(0))) { return 0; @@ -449,6 +450,9 @@ class PDOSQLiteUDFS { $arg_list = func_get_args(); } $searchString = array_shift($arg_list); + $str_to_check = substr($searchString, 0, strpos($searchString, '.')); + $str_to_check = str_replace($wpdb->prefix, '', $str_to_check); + if ($str_to_check && in_array(trim($str_to_check), $wpdb->tables)) return; for ($i = 0; $i < $numArgs-1; $i++) { if ($searchString === strtolower($arg_list[$i])) { return $i + 1; diff --git a/pdoengine.class.php b/pdoengine.class.php index ac284b0..a3401c5 100644 --- a/pdoengine.class.php +++ b/pdoengine.class.php @@ -26,6 +26,12 @@ class PDOEngine extends PDO { * @var unsigned integer */ public $found_rows_result = null; + /** + * Class variable used for query with ORDER BY FIELD() + * + * @var array of the object + */ + public $pre_ordered_results = null; /** * Class variable to store the rewritten queries. * @@ -370,6 +376,12 @@ class PDOEngine extends PDO { default: $engine = $this->prepare_engine($this->query_type); $this->rewritten_query = $engine->rewrite_query($query, $this->query_type); + if (!is_null($this->pre_ordered_results)) { + $this->results = $this->pre_ordered_results; + $this->num_rows = $this->return_value = count($this->results); + $this->pre_ordered_results = null; + break; + } $this->queries[] = "Rewritten:\n$this->rewritten_query"; $this->extract_variables(); $statement = $this->prepare_query(); diff --git a/query.class.php b/query.class.php index ac222e8..658e081 100644 --- a/query.class.php +++ b/query.class.php @@ -54,6 +54,12 @@ class PDOSQLiteDriver { * @var integer */ private $num_of_rewrite_between = 0; + /** + * Variable to check order by field() with column data. + * + * @var boolean + */ + private $orderby_field = false; /** * Method to rewrite a query string for SQLite to execute. * @@ -97,6 +103,7 @@ class PDOSQLiteDriver { //$this->rewrite_boolean(); $this->fix_date_quoting(); $this->rewrite_between(); + $this->handle_orderby_field(); break; case 'insert': //$this->safe_strip_backticks(); @@ -192,6 +199,9 @@ class PDOSQLiteDriver { $this->rewrite_between = true; $this->num_of_rewrite_between++; } + if (stripos($token, 'ORDER BY FIELD') !== false) { + $this->orderby_field = true; + } } } $query_string .= $token; @@ -726,6 +736,45 @@ class PDOSQLiteDriver { $this->num_of_rewrite_between--; } while ($this->num_of_rewrite_between > 0); } + /** + * Method to handle ORDER BY FIELD() clause. + * + * When FIELD() function has column name to compare, we can't rewrite it with + * use defined functions. When this function detect column name in the argument, + * it creates another instance, does the query withuot ORDER BY clause and gives + * the result array sorted to the main instance. + * + * If FIELD() function doesn't have column name, it will use the user defined + * function. usort() function closure function to compare the items. + * + * @access private + */ + private function handle_orderby_field() { + if (!$this->orderby_field) return; + global $wpdb; + $pattern = '/\\s+ORDER\\s+BY\\s+FIELD\\s*\(\\s*([^\)]+?)\\s*\)/i'; + if (preg_match($pattern, $this->_query, $match)) { + global $flipped; + $params = explode(',', $match[1]); + $params = array_map('trim', $params); + $tbl_col = array_shift($params); + $flipped = array_flip($params); + $tbl_name = substr($tbl_col, 0, strpos($tbl_col, '.')); + $tbl_name = str_replace($wpdb->prefix, '', $tbl_name); + if ($tbl_name && in_array($tbl_name, $wpdb->tables)) { + $query = str_replace($match[0], '', $this->_query); + $_wpdb = new PDODB(); + $results = $_wpdb->get_results($query); + $_wpdb = null; + $compare = function($a, $b) { + global $flipped; + return $flipped[$a->ID] - $flipped[$b->ID]; + }; + usort($results, $compare); + } + $wpdb->dbh->pre_ordered_results = $results; + } + } /** * Method to avoid DELETE with JOIN statement. *