Permalink
Browse files

FEATURE: implement SS_Sortable->reverse()

API CHANGE: SQLQuery:: now an array object rather than string. Existing strings will continue to work
  • Loading branch information...
1 parent cbc5d3c commit 9938b64cf6ed0e05583633f1b894f89bd1e9f71f @wilr wilr committed with sminnee Apr 15, 2012
View
@@ -293,7 +293,18 @@ public function column($colName = 'ID') {
public function canSortBy($by) {
return true;
}
-
+
+ /**
+ * Reverses an {@link ArrayList}
+ *
+ * @return ArrayList
+ */
+ public function reverse() {
+ $this->items = array_reverse($this->items);
+
+ return $this;
+ }
+
/**
* Sorts this list by one or more fields. You can either pass in a single
* field name and direction, or a map of field names to sort directions.
View
@@ -37,6 +37,7 @@ class DataList extends ViewableData implements SS_List, SS_Filterable, SS_Sortab
public function __construct($dataClass) {
$this->dataClass = $dataClass;
$this->dataQuery = new DataQuery($this->dataClass);
+
parent::__construct();
}
@@ -148,51 +149,48 @@ public function limit($limit, $offset = 0) {
/**
* Set the sort order of this data list
*
- * @return DataList
* @see SS_List::sort()
+ * @see SQLQuery::orderby
+ *
* @example $list->sort('Name'); // default ASC sorting
* @example $list->sort('Name DESC'); // DESC sorting
* @example $list->sort('Name', 'ASC');
* @example $list->sort(array('Name'=>'ASC,'Age'=>'DESC'));
+ *
+ * @return DataList
*/
public function sort() {
- if(count(func_get_args())==0){
+ if(count(func_get_args()) == 0) {
return $this;
}
- if(count(func_get_args())>2){
+
+ if(count(func_get_args()) > 2) {
throw new InvalidArgumentException('This method takes zero, one or two arguments');
}
- // sort('Name','Desc')
- if(count(func_get_args())==2){
+ if(count(func_get_args()) == 2) {
+ // sort('Name','Desc')
if(!in_array(strtolower(func_get_arg(1)),array('desc','asc'))){
user_error('Second argument to sort must be either ASC or DESC');
}
- $this->dataQuery->sort(func_get_arg(0).' '.func_get_arg(1));
- return $this;
+
+ $this->dataQuery->sort(func_get_arg(0), func_get_arg(1));
}
-
- // sort('Name') - default to ASC sorting if not specified
- if(is_string(func_get_arg(0)) && func_get_arg(0)){
+ else if(is_string(func_get_arg(0)) && func_get_arg(0)){
// sort('Name ASC')
- if(stristr(func_get_arg(0), ' asc') || stristr(func_get_arg(0), ' desc')){
+ if(stristr(func_get_arg(0), ' asc') || stristr(func_get_arg(0), ' desc')) {
$this->dataQuery->sort(func_get_arg(0));
} else {
- $this->dataQuery->sort(func_get_arg(0).' ASC');
+ $this->dataQuery->sort(func_get_arg(0), 'ASC');
}
-
- return $this;
}
-
- // sort(array('Name'=>'desc'));
- $argumentArray = func_get_arg(0);
- if(is_array($argumentArray)){
- $sort = array();
- foreach($argumentArray as $column => $direction) {
- $sort[]= ''.$this->getRelationName($column).' '.$direction;
+ else if(is_array(func_get_arg(0))) {
+ // sort(array('Name'=>'desc'));
+ $this->dataQuery->sort(null, null); // wipe the sort
+
+ foreach(func_get_arg(0) as $col => $dir) {
+ $this->dataQuery->sort($this->getRelationName($col), $dir, false);
}
- $this->dataQuery->sort(implode(',', $sort));
- return $this;
}
return $this;
@@ -201,15 +199,17 @@ public function sort() {
/**
* Filter the list to include items with these charactaristics
*
- * @return DataList
* @see SS_List::filter()
+ *
* @example $list->filter('Name', 'bob'); // only bob in the list
* @example $list->filter('Name', array('aziz', 'bob'); // aziz and bob in list
* @example $list->filter(array('Name'=>'bob, 'Age'=>21)); // bob with the age 21
* @example $list->filter(array('Name'=>'bob, 'Age'=>array(21, 43))); // bob with the Age 21 or 43
* @example $list->filter(array('Name'=>array('aziz','bob'), 'Age'=>array(21, 43))); // aziz with the age 21 or 43 and bob with the Age 21 or 43
*
* @todo extract the sql from $customQuery into a SQLGenerator class
+ *
+ * @return DataList
*/
public function filter() {
$numberFuncArgs = count(func_get_args());
@@ -284,9 +284,8 @@ private function applyFilterContext($field, $comparisators, $value) {
}
/**
- * Exclude the list to not contain items with these charactaristics
+ * Exclude the list to not contain items with these characteristics
*
- * @return DataList
* @see SS_List::exclude()
* @example $list->exclude('Name', 'bob'); // exclude bob from list
* @example $list->exclude('Name', array('aziz', 'bob'); // exclude aziz and bob from list
@@ -295,6 +294,8 @@ private function applyFilterContext($field, $comparisators, $value) {
* @example $list->exclude(array('Name'=>array('bob','phil'), 'Age'=>array(21, 43))); // bob age 21 or 43, phil age 21 or 43 would be excluded
*
* @todo extract the sql from this method into a SQLGenerator class
+ *
+ * @return DataList
*/
public function exclude(){
$numberFuncArgs = count(func_get_args());
@@ -338,6 +339,7 @@ public function subtract(SS_List $list) {
$newlist = clone $this;
$newlist->dataQuery->subtract($list->dataQuery());
+
return $newlist;
}
@@ -351,6 +353,7 @@ public function subtract(SS_List $list) {
*/
public function innerJoin($table, $onClause, $alias = null) {
$this->dataQuery->innerJoin($table, $onClause, $alias);
+
return $this;
}
@@ -364,6 +367,7 @@ public function innerJoin($table, $onClause, $alias = null) {
*/
public function leftJoin($table, $onClause, $alias = null) {
$this->dataQuery->leftJoin($table, $onClause, $alias);
+
return $this;
}
@@ -377,9 +381,11 @@ public function toArray() {
$query = $this->dataQuery->query();
$rows = $query->execute();
$results = array();
+
foreach($rows as $row) {
$results[] = $this->createDataObject($row);
}
+
return $results;
}
@@ -390,6 +396,7 @@ public function toArray() {
*/
public function toNestedArray() {
$result = array();
+
foreach($this as $item) {
$result[] = $item->toMap();
}
@@ -399,6 +406,7 @@ public function toNestedArray() {
public function debug() {
$val = "<h2>" . $this->class . "</h2><ul>";
+
foreach($this->toNestedArray() as $item) {
$val .= "<li style=\"list-style-type: disc; margin-left: 20px\">" . Debug::text($item) . "</li>";
}
@@ -574,6 +582,7 @@ public function find($key, $value) {
public function byIDs(array $ids) {
$baseClass = ClassInfo::baseDataClass($this->dataClass);
$this->where("\"$baseClass\".\"ID\" IN (" . implode(',', $ids) .")");
+
return $this;
}
@@ -586,6 +595,7 @@ public function byIDs(array $ids) {
public function byID($id) {
$baseClass = ClassInfo::baseDataClass($this->dataClass);
$clone = clone $this;
+
return $clone->where("\"$baseClass\".\"ID\" = " . (int)$id)->First();
}
@@ -755,7 +765,18 @@ public function removeByID($itemID) {
$item = $this->byID($itemID);
if($item) return $item->delete();
}
-
+
+ /**
+ * Reverses a list of items.
+ *
+ * @return DataList
+ */
+ public function reverse() {
+ $this->dataQuery->reverseSort();
+
+ return $this;
+ }
+
/**
* This method won't function on DataLists due to the specific query that it represent
*
View
@@ -3,14 +3,31 @@
/**
* An object representing a query of data from the DataObject's supporting database.
* Acts as a wrapper over {@link SQLQuery} and performs all of the query generation.
- * Used extensively by DataList.
+ * Used extensively by {@link DataList}.
+ *
+ * @subpackage model
+ * @package sapphire
*/
class DataQuery {
+
+ /**
+ * @var String
+ */
protected $dataClass;
+
+ /**
+ * @var SQLQuery
+ */
protected $query;
+ /**
+ * @var array
+ */
protected $collidingFields = array();
+ /**
+ * @var Boolean
+ */
private $queryFinalised = false;
// TODO: replace subclass_access with this
@@ -20,7 +37,8 @@ class DataQuery {
/**
* Create a new DataQuery.
- * @param $dataClass The name of the DataObject class that you wish to query
+ *
+ * @param String The name of the DataObject class that you wish to query
*/
function __construct($dataClass) {
$this->dataClass = $dataClass;
@@ -172,49 +190,50 @@ protected function ensureSelectContainsOrderbyColumns($query) {
$baseClass = array_shift($tableClasses);
if($query->orderby) {
- $orderByFields = explode(',', $query->orderby);
- foreach($orderByFields as $ob => $col) {
- $col = trim($col);
-
- // don't touch functions in the ORDER BY or function calls selected as fields
- if(strpos($col, '(') !== false || preg_match('/_SortColumn/', $col)) continue;
-
- $columnParts = explode(' ', $col);
- if (count($columnParts) == 2) {
- $col = $columnParts[0];
- $dir = $columnParts[1];
- } else {
- $dir = 'ASC';
- }
+ $orderby = $query->getOrderBy();
- $orderByFields[$ob] = $col . ' ' . $dir;
- $col = str_replace('"', '', $col);
+ foreach($orderby as $k => $dir) {
+ // don't touch functions in the ORDER BY or function calls
+ // selected as fields
+ if(strpos($k, '(') !== false || preg_match('/_SortColumn/', $k))
+ continue;
+
+ $col = str_replace('"', '', trim($k));
$parts = explode('.', $col);
if(count($parts) == 1) {
$databaseFields = DataObject::database_fields($baseClass);
- // database_fields() doesn't return ID, so we need to manually add it here
+
+ // database_fields() doesn't return ID, so we need to
+ // manually add it here
$databaseFields['ID'] = true;
-
+
if(isset($databaseFields[$parts[0]])) {
$qualCol = "\"$baseClass\".\"{$parts[0]}\"";
- $orderByFields[$ob] = trim($qualCol . " " . $dir);
+
+ // remove original sort
+ unset($orderby[$k]);
+
+ // add new columns sort
+ $orderby[$qualCol] = $dir;
+
} else {
$qualCol = "\"$parts[0]\"";
}
-
- if(!isset($query->select[$parts[0]]) && !in_array($qualCol, $query->select)) {
+
+ if(!isset($query->select[$col]) && !in_array($qualCol, $query->select)) {
$query->select[] = $qualCol;
}
} else {
$qualCol = '"' . implode('"."', $parts) . '"';
+
if(!in_array($qualCol, $query->select)) {
$query->select[] = $qualCol;
}
}
}
- $query->orderby = implode(',', $orderByFields);
+ $query->orderby = $orderby;
}
}
@@ -357,17 +376,28 @@ function whereAny($filter) {
/**
* Set the ORDER BY clause of this query
+ *
+ * @see SQLQuery::orderby()
+ *
+ * @return DataQuery
*/
- function sort($sort) {
- if($sort) {
- $clone = $this;
- // Add quoting to sort expression if it's a simple column name
- if(!is_array($sort) && preg_match('/^[A-Z][A-Z0-9_]*$/i', $sort)) $sort = "\"$sort\"";
- $clone->query->orderby($sort);
- return $clone;
- } else {
- return $this;
- }
+ function sort($sort = null, $direction = null, $clear = true) {
+ $clone = $this;
+ $clone->query->orderby($sort, $direction, $clear);
+
+ return $clone;
+ }
+
+ /**
+ * Reverse order by clause
+ *
+ * @return DataQuery
+ */
+ function reverseSort() {
+ $clone = $this;
+
+ $clone->query->reverseOrderBy();
+ return $clone;
}
/**
Oops, something went wrong.

0 comments on commit 9938b64

Please sign in to comment.