diff --git a/src/ORM/DataList.php b/src/ORM/DataList.php index e9f65b04dc0..e253daefc7f 100644 --- a/src/ORM/DataList.php +++ b/src/ORM/DataList.php @@ -321,9 +321,35 @@ public function distinct($value) * @param string|array Escaped SQL statement. If passed as array, all keys and values are assumed to be escaped. * @return static */ - public function sort() + public function sort(...$args) { - $count = func_num_args(); + return $this->sortInner(false, $args); + } + + /** + * The same as sort(), though allows raw SQL to be used for sorting + * + * Return a new DataList instance as a copy of this data list with the sort + * order set. + * + * @see SS_List::sort() + * @see SQLSelect::orderby + * @example $list = $list->sort('Name'); // default ASC sorting + * @example $list = $list->sort('Mod(ID, 3) ASC, Name ASC'); // Raw SQL sort + * @example $list = $list->sort('Name', 'ASC'); + * @example $list = $list->sort(array('Name'=>'ASC', 'Age'=>'DESC')); + * + * @param string|array Escaped SQL statement. If passed as array, all keys and values are assumed to be escaped. + * @return static + */ + public function sortRaw(...$args) + { + return $this->sortInner(true, $args); + } + + private function sortInner(bool $allowRawSql, array $args) + { + $count = count($args); if ($count == 0) { return $this; @@ -336,7 +362,7 @@ public function sort() if ($count == 2) { $col = null; $dir = null; - list($col, $dir) = func_get_args(); + list($col, $dir) = $args; // Validate direction if (!in_array(strtolower($dir ?? ''), ['desc', 'asc'])) { @@ -345,12 +371,16 @@ public function sort() $sort = [$col => $dir]; } else { - $sort = func_get_arg(0); + $sort = $args[0]; } return $this->alterDataQuery(function (DataQuery $query, DataList $list) use ($sort) { if (is_string($sort) && $sort) { + // TODO: + // this is raw sql - validate it matches "Name ASC, ID DESC" style if !$allowRawSql + // also validate that column exists - note: "This is a - (legit) column name" so + // regex will not work for validation if (false !== stripos($sort ?? '', ' asc') || false !== stripos($sort ?? '', ' desc')) { $query->sort($sort); } else { diff --git a/src/ORM/DataQuery.php b/src/ORM/DataQuery.php index 89e9dae7442..bd4b2a4a632 100644 --- a/src/ORM/DataQuery.php +++ b/src/ORM/DataQuery.php @@ -722,6 +722,7 @@ public function whereAny($filter) * @param string $direction Direction ("ASC" or "DESC", escaped SQL statement) * @param bool $clear Clear existing values * @return $this + * */ public function sort($sort = null, $direction = null, $clear = true) {