@@ -698,7 +698,6 @@ public function get($query, $db = null)
698698 }
699699 }
700700 $ group_columns = $ selected_columns ;
701- $ prefix_columns = $ this ->auth ->addSelectPermissions ($ prefix_columns , $ table , $ prefix , $ db );
702701 $ select_columns = implode (', ' , $ prefix_columns );
703702 }
704703
@@ -842,21 +841,21 @@ public function get($query, $db = null)
842841 // bind WHERE values
843842 if (!empty ($ where_values ) && count ($ where_values ) > 0 ) {
844843 foreach ($ where_values as $ key => $ value ) {
845- $ value = $ this ->cleanConditionValue ($ value , $ query ['table ' ], $ key , $ db );
844+ $ value = $ this ->parseValue ($ value , $ query ['table ' ], $ key , $ db );
846845 $ type = self ::detectPDOType ($ value );
847846 $ key = ': ' . $ key ;
848- $ sql_compiled = self ::debugCompileSQL ($ sql_compiled , $ key , $ value );
847+ $ sql_compiled = self ::getPartialCompiledQuery ($ sql_compiled , $ key , $ value );
849848 $ sth ->bindValue ($ key , $ value , $ type );
850849 }
851850 }
852851
853852 // bind JOIN values
854853 if (!empty ($ join_values ) && count ($ join_values ) > 0 ) {
855854 foreach ($ join_values as $ key => $ value ) {
856- $ value = $ this ->cleanConditionValue ($ value , $ query ['table ' ], $ key , $ db );
855+ $ value = $ this ->parseValue ($ value , $ query ['table ' ], $ key , $ db );
857856 $ type = self ::detectPDOType ($ value );
858857 $ key = ': ' . $ key ;
859- $ sql_compiled = self ::debugCompileSQL ($ sql_compiled , $ key , $ value );
858+ $ sql_compiled = self ::getPartialCompiledQuery ($ sql_compiled , $ key , $ value );
860859 $ sth ->bindValue ($ key , $ value , $ type );
861860 }
862861 }
@@ -1133,18 +1132,18 @@ public function patch($query, $db = null, $skipChecks = false)
11331132
11341133 // bind PUT values
11351134 foreach ($ column_values as $ key => $ value ) {
1136- $ value = $ this ->cleanConditionValue ($ value , $ table , $ key , $ db );
1135+ $ value = $ this ->parseValue ($ value , $ table , $ key , $ db );
11371136 $ key = ': ' . $ key ;
1138- $ sql_compiled = self ::debugCompileSQL ($ sql_compiled , $ key , $ value );
1137+ $ sql_compiled = self ::getPartialCompiledQuery ($ sql_compiled , $ key , $ value );
11391138 $ sth ->bindValue ($ key , $ value );
11401139 }
11411140
11421141 // bind WHERE values
11431142 if (!empty ($ where_values ) && count ($ where_values ) > 0 ) {
11441143 foreach ($ where_values as $ key => $ value ) {
1145- $ value = $ this ->cleanConditionValue ($ value , $ table , $ key , $ db );
1144+ $ value = $ this ->parseValue ($ value , $ table , $ key , $ db );
11461145 $ key = ': ' . $ key ;
1147- $ sql_compiled = self ::debugCompileSQL ($ sql_compiled , $ key , $ value );
1146+ $ sql_compiled = self ::getPartialCompiledQuery ($ sql_compiled , $ key , $ value );
11481147 $ sth ->bindValue ($ key , $ value );
11491148 }
11501149 }
@@ -1211,6 +1210,10 @@ public function delete($query, $db = null)
12111210 $ where_additional = $ this ->hooks ->apply_filters ('delete_query_additional_where ' , '' , $ query ['table ' ]);
12121211 $ where_additional_table = $ this ->hooks ->apply_filters ('delete_query_additional_where_ ' . strtolower ($ query ['table ' ]), '' , $ query ['table ' ]);
12131212
1213+ if (empty (trim ($ restriction ))) {
1214+ $ restriction = "'1' = '1' " ;
1215+ }
1216+
12141217 $ sql .= ($ where_exists ? ' AND ' : ' WHERE ' ) . ' ( ' . $ restriction . ') ' ;
12151218 $ sql .= (!empty ($ where_additional ) ? ' AND ( ' . $ where_additional . ') ' : '' );
12161219 $ sql .= (!empty ($ where_additional_table ) ? ' AND ( ' . $ where_additional_table . ') ' : '' );
@@ -1223,10 +1226,10 @@ public function delete($query, $db = null)
12231226 // bind WHERE values
12241227 if (!empty ($ where_values ) && count ($ where_values ) > 0 ) {
12251228 foreach ($ where_values as $ key => $ value ) {
1226- $ value = $ this ->cleanConditionValue ($ value , $ query ['table ' ], $ key , $ db );
1229+ $ value = $ this ->parseValue ($ value , $ query ['table ' ], $ key , $ db );
12271230 $ type = self ::detectPDOType ($ value );
12281231 $ key = ': ' . $ key ;
1229- $ sql_compiled = self ::debugCompileSQL ($ sql_compiled , $ key , $ value );
1232+ $ sql_compiled = self ::getPartialCompiledQuery ($ sql_compiled , $ key , $ value );
12301233 $ sth ->bindValue ($ key , $ value , $ type );
12311234 }
12321235 }
@@ -1288,10 +1291,10 @@ private function executeInsert($table, $columns, $db)
12881291
12891292 // bind POST values
12901293 foreach ($ columns as $ column => $ value ) {
1291- $ value = $ this ->cleanConditionValue ($ value , $ table , $ column );
1294+ $ value = $ this ->parseValue ($ value , $ table , $ column );
12921295 $ column = ': ' . $ column ;
12931296 $ sth ->bindValue ($ column , $ value );
1294- $ sql_compiled = self ::debugCompileSQL ($ sql_compiled , $ column , $ value );
1297+ $ sql_compiled = self ::getPartialCompiledQuery ($ sql_compiled , $ column , $ value );
12951298 }
12961299
12971300 $ this ->logger ->debug ($ sql_compiled );
@@ -1334,34 +1337,100 @@ public function render($data)
13341337 * @param $simple_encode
13351338 * @param $query
13361339 */
1337- public function renderJson ($ data , $ simple_encode = false )
1340+ public function renderJson ($ data , $ simple_encode = false , $ complex = false )
13381341 {
1339- @header ('Content-type: application/json ' );
1340-
1341- if (is_multi_array ($ data ) && !$ simple_encode ) {
1342- $ prefix = '' ;
1343- $ output = '[ ' ;
1344- foreach ($ data as $ key => $ row ) {
1345- $ output .= $ prefix . json_encode ($ row );
1346- $ prefix = ', ' ;
1347- }
1348- $ output .= '] ' ;
1342+ if ($ complex ) {
1343+ $ output = $ this ->jsonStringify ($ data );
13491344 } else {
1350- $ output = json_encode ($ data );
1345+ // TODO: replace with jsonStringify method, need to do some checks
1346+ if (is_multi_array ($ data ) && !$ simple_encode ) {
1347+ $ prefix = '' ;
1348+ $ output = '[ ' ;
1349+ foreach ($ data as $ row ) {
1350+ $ output .= $ prefix . json_encode ($ row );
1351+ $ prefix = ', ' ;
1352+ }
1353+ $ output .= '] ' ;
1354+ } else {
1355+ $ output = json_encode ($ data );
1356+ }
13511357 }
13521358
13531359 // Prepare a JSONP callback.
13541360 $ callback = jsonp_callback_filter ($ this ->query ['callback ' ]);
13551361
13561362 // Only send back JSONP if that's appropriate for the request.
13571363 if ($ callback ) {
1358- echo "{$ callback }( $ output); " ;
1364+ $ output = "{$ callback }( $ output); " ;
1365+ }
13591366
1360- return ;
1367+ $ compressed = gzencode ($ output );
1368+
1369+ ob_clean ();
1370+
1371+ @header ('Content-Type: application/json ' );
1372+ @header ('Content-Encoding: gzip ' );
1373+ @header ('Content-Length: ' . strlen ($ compressed ));
1374+
1375+ exit ($ compressed );
1376+ }
1377+
1378+ /**
1379+ * Encode large amount of data into JSON.
1380+ *
1381+ * @param mixed $data
1382+ *
1383+ * @return string
1384+ */
1385+ public function jsonStringify ($ data , $ path = 'json ' )
1386+ {
1387+ if (is_array ($ data ) || is_object ($ data )) {
1388+ if (is_object ($ data )) {
1389+ $ isNamedKey = true ;
1390+ } else {
1391+ $ isNamedKey = (is_string (key ($ data )));
1392+ }
1393+ if ($ isNamedKey ) {
1394+ $ output = '{ ' ;
1395+ $ prefix = '' ;
1396+ foreach ($ data as $ key => $ value ) {
1397+ $ nextPath = $ path . ". $ key " ;
1398+ if (!is_numeric ($ key )) {
1399+ $ key = '" ' . $ key . '" ' ;
1400+ }
1401+ $ stringify = $ this ->hooks ->apply_filters ('render_json_process ' , true , $ nextPath );
1402+ if ($ stringify ) {
1403+ $ content = $ this ->jsonStringify ($ value , $ nextPath );
1404+ $ content = $ this ->hooks ->apply_filters ('render_json_content ' , $ content , $ nextPath );
1405+ } else {
1406+ $ content = $ this ->hooks ->apply_filters ('render_json_result ' , 'null ' , $ nextPath );
1407+ }
1408+ $ output .= $ prefix . $ key . ': ' . $ content ;
1409+ $ prefix = ', ' ;
1410+ }
1411+ $ output .= '} ' ;
1412+ } else {
1413+ $ output = '[ ' ;
1414+ $ prefix = '' ;
1415+ foreach ($ data as $ key => $ value ) {
1416+ $ nextPath = $ path . "[ $ key] " ;
1417+ $ stringify = $ this ->hooks ->apply_filters ('render_json_process ' , true , $ nextPath );
1418+ if ($ stringify ) {
1419+ $ content = $ this ->jsonStringify ($ value , $ nextPath );
1420+ $ content = $ this ->hooks ->apply_filters ('render_json_content ' , $ content , $ nextPath );
1421+ } else {
1422+ $ content = $ this ->hooks ->apply_filters ('render_json_result ' , 'null ' , $ nextPath );
1423+ }
1424+ $ output .= $ prefix . $ content ;
1425+ $ prefix = ', ' ;
1426+ }
1427+ $ output .= '] ' ;
1428+ }
1429+ } else {
1430+ $ output = json_encode ($ data );
13611431 }
1362- // If not JSONP, send back the data.
1363- echo $ output ;
1364- exit ();
1432+
1433+ return (string )$ output ;
13651434 }
13661435
13671436 /**
@@ -1637,10 +1706,11 @@ private function getTableColumnsMeta($table, $db = null)
16371706 * @param $table
16381707 * @param $key
16391708 * @param $db
1709+ * @param $forceNullable
16401710 *
16411711 * @return mixed
16421712 */
1643- private function cleanConditionValue ($ value , $ table , $ key , $ db = null )
1713+ public function parseValue ($ value , $ table , $ key , $ db = null , $ forceNullable = false )
16441714 {
16451715 if (is_array ($ value )) {
16461716 $ value = serialize ($ value );
@@ -1663,6 +1733,8 @@ private function cleanConditionValue($value, $table, $key, $db = null)
16631733 ];
16641734 if (in_array ($ dataType , $ numericDataType )) {
16651735 $ value = ($ isNullable ) ? null : (float )$ default ;
1736+ } elseif ($ forceNullable ) {
1737+ $ value = null ;
16661738 }
16671739 }
16681740 }
@@ -1896,7 +1968,7 @@ private function parseWhere($main_table, $where, $sql)
18961968 $ special_value = [$ special_value ];
18971969 }
18981970 foreach ($ special_value as $ v ) {
1899- $ clean_value = $ this ->cleanConditionValue ($ v , $ table , $ column );
1971+ $ clean_value = $ this ->parseValue ($ v , $ table , $ column );
19001972 if ($ clean_value === null ) {
19011973 $ clean_value = '' ; // Don't accept null
19021974 }
@@ -1938,7 +2010,7 @@ private function parseWhere($main_table, $where, $sql)
19382010 if (is_null ($ value )) {
19392011 $ index_value = "'' " ;
19402012 } else {
1941- $ clean_value = $ this ->cleanConditionValue ($ value , $ table , $ column );
2013+ $ clean_value = $ this ->parseValue ($ value , $ table , $ column );
19422014 if ($ clean_value === null ) {
19432015 $ clean_value = '' ; // Don't accept null
19442016 }
@@ -1965,7 +2037,7 @@ private function parseWhere($main_table, $where, $sql)
19652037 if (count ($ _value_split ) > 1 && $ this ->checkColumn (@$ _value_split [1 ], @$ _value_split [0 ])) {
19662038 $ index_value = $ _value_split [0 ] . '. ' . $ _value_split [1 ];
19672039 } else {
1968- $ clean_value = $ this ->cleanConditionValue ($ value , $ table , $ column );
2040+ $ clean_value = $ this ->parseValue ($ value , $ table , $ column );
19692041 if ($ clean_value === null ) {
19702042 $ clean_value = '' ; // Don't accept null
19712043 }
@@ -2130,19 +2202,85 @@ private static function detectPDOType($value)
21302202 }
21312203
21322204 /**
2133- * Compile PDO prepare .
2205+ * Returns the partial emulated SQL string .
21342206 *
21352207 * @param $string
21362208 * @param $key
21372209 * @param $value
21382210 *
2139- * @return string|string[]|null
2211+ * @return string
2212+ */
2213+ public static function getPartialCompiledQuery ($ query , $ key , $ value )
2214+ {
2215+ $ value = self ::getCompiledParamValue ($ value );
2216+
2217+ return preg_replace ('/ ' . $ key . "([,]|\s|$|\))/i " , $ value , $ query );
2218+ }
2219+
2220+ /**
2221+ * Returns the emulated SQL string.
2222+ *
2223+ * @param string $query
2224+ * @param array $parameters
2225+ *
2226+ * @return string
2227+ */
2228+ public static function getCompiledQuery ($ query , $ parameters = [])
2229+ {
2230+ $ keys = [];
2231+ $ values = [];
2232+
2233+ /**
2234+ * Get longest keys first, so the regex replacement doesn't cut markers
2235+ * (ex : replace ":username" with "marco.cesarato" if we have a param name :user ).
2236+ */
2237+ $ isNamedMarkers = false ;
2238+ if (count ($ parameters ) && is_string (key ($ parameters ))) {
2239+ uksort ($ parameters , function ($ k1 , $ k2 ) {
2240+ return strlen ($ k2 ) - strlen ($ k1 );
2241+ });
2242+ $ isNamedMarkers = true ;
2243+ }
2244+ foreach ($ parameters as $ key => $ value ) {
2245+ // Check if named parameters (':param') or anonymous parameters ('?') are used
2246+ if (is_string ($ key )) {
2247+ $ keys [] = '/: ' . ltrim ($ key , ': ' ) . '/ ' ;
2248+ } else {
2249+ $ keys [] = '/[?]/ ' ;
2250+ }
2251+ $ values [] = self ::getCompiledParamValue ($ value );
2252+ }
2253+ if ($ isNamedMarkers ) {
2254+ return preg_replace ($ keys , $ values , $ query );
2255+ }
2256+
2257+ return preg_replace ($ keys , $ values , $ query , 1 , $ count );
2258+ }
2259+
2260+ /**
2261+ * Bring parameter value into human-readable format.
2262+ *
2263+ * @param mixed $rawValue
2264+ *
2265+ * @return string
21402266 */
2141- public static function debugCompileSQL ( $ string , $ key , $ value )
2267+ public static function getCompiledParamValue ( $ rawValue )
21422268 {
2143- $ string = preg_replace ('/ ' . $ key . "([,]|\s|$|\))/i " , ($ value === null ? 'NULL$1 ' : "' " . $ value . "'$1 " ), $ string );
2269+ if (is_string ($ rawValue )) {
2270+ $ value = "' " . addslashes ($ rawValue ) . "' " ;
2271+ } elseif (is_numeric ($ rawValue )) {
2272+ $ value = (string )$ rawValue ;
2273+ } elseif (is_array ($ rawValue )) {
2274+ $ value = implode (', ' , $ rawValue );
2275+ } elseif (is_null ($ rawValue )) {
2276+ $ value = 'NULL ' ;
2277+ } elseif (is_bool ($ rawValue )) {
2278+ $ value = (string )($ rawValue );
2279+ } else {
2280+ $ value = (string )($ rawValue );
2281+ }
21442282
2145- return $ string ;
2283+ return $ value ;
21462284 }
21472285
21482286 /**
0 commit comments