diff --git a/model/ArrayList.php b/model/ArrayList.php index b15e3b04c..8b6b07bcb 100644 --- a/model/ArrayList.php +++ b/model/ArrayList.php @@ -348,8 +348,8 @@ class ArrayList extends ViewableData implements SS_List, SS_Filterable, SS_Sorta /** * Parses a specified column into a sort field and direction * - * @param type $column String to parse containing the column name - * @param type $direction Optional Additional argument which may contain the direction + * @param string $column String to parse containing the column name + * @param string $direction Optional Additional argument which may contain the direction * @return array Sort specification in the form array("Column", SORT_ASC). */ protected function parseSortColumn($column, $direction = null) { diff --git a/model/DataObject.php b/model/DataObject.php index d8498e565..ae4958ea9 100644 --- a/model/DataObject.php +++ b/model/DataObject.php @@ -3405,25 +3405,23 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity } if ($sort && is_string($sort)) { - $sort = preg_split('/,(?![^()]*+\\))/', $sort); + $sort = preg_split('/,(?![^()]*+\\))/', $sort); foreach ($sort as $value) { - $value = trim($value); - if(strpos($value, ' ') !== false) { - $parts = explode(' ', $value, 2); - $column = $parts[0]; - } else { - $column = $value; - } - if (substr($column, 0, 1) === '"') { - $column = substr($column, 1, strlen($column)-1); - } - if (substr($column, -1, 1) === '"') { - $column = substr($column, 0, -1); - } - if ($this->hasOwnTableDatabaseField($column) && !array_key_exists($column, $indexes)) { - $indexes[$column] = true; - } + try { + list ($table, $column) = $this->parseSortColumn(trim($value)); + + $table = trim($table, '"'); + $column = trim($column, '"'); + + if ($table && strtolower($table) !== strtolower($this->class)) { + continue; + } + + if ($this->hasOwnTableDatabaseField($column) && !array_key_exists($column, $indexes)) { + $indexes[$column] = true; + } + } catch (InvalidArgumentException $e) { } } } @@ -3434,6 +3432,25 @@ class DataObject extends ViewableData implements DataObjectInterface, i18nEntity return $indexes; } + /** + * Parses a specified column into a sort field and direction + * + * @param string $column String to parse containing the column name + * @return array Resolved table and column. + */ + protected function parseSortColumn($column) { + // Parse column specification, considering possible ansi sql quoting + // Note that table prefix is allowed, but discarded + if(preg_match('/^("?(?[^"\s]+)"?\\.)?"?(?[^"\s]+)"?(\s+(?((asc)|(desc))(ending)?))?$/i', $column, $match)) { + $table = $match['table']; + $column = $match['column']; + } else { + throw new InvalidArgumentException("Invalid sort() column"); + } + + return array($table, $column); + } + /** * Check the database schema and update it as necessary. * diff --git a/tests/model/DataObjectSchemaGenerationTest.php b/tests/model/DataObjectSchemaGenerationTest.php index 80f590210..2641c2268 100644 --- a/tests/model/DataObjectSchemaGenerationTest.php +++ b/tests/model/DataObjectSchemaGenerationTest.php @@ -195,6 +195,12 @@ class DataObjectSchemaGenerationTest extends SapphireTest { $this->assertArrayHasKey('Sort', $indexes); $this->assertTrue($indexes['Sort']); + + Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"DataObjectSchemaGenerationTest_Sorted"."Sort" ASC'); + $indexes = $object->databaseIndexes(); + $this->assertArrayHasKey('Sort', $indexes); + $this->assertTrue($indexes['Sort']); + Config::inst()->update('DataObjectSchemaGenerationTest_Sorted', 'default_sort', '"Sort" DESC, "Title" ASC'); $indexes = $object->databaseIndexes(); $this->assertArrayHasKey('Sort', $indexes);