summaryrefslogtreecommitdiff
path: root/modules/gallery/models/item.php
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gallery/models/item.php')
-rw-r--r--modules/gallery/models/item.php97
1 files changed, 70 insertions, 27 deletions
diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php
index a87997c6..ff02daf8 100644
--- a/modules/gallery/models/item.php
+++ b/modules/gallery/models/item.php
@@ -412,39 +412,74 @@ class Item_Model extends ORM_MPTT {
* Find the position of the given child id in this album. The resulting value is 1-indexed, so
* the first child in the album is at position 1.
*/
- public function get_position($child_id) {
+ public function get_position($child) {
if ($this->sort_order == "DESC") {
$comp = ">";
} else {
$comp = "<";
}
-
$db = Database::instance();
- $position = $db->query("
- SELECT COUNT(*) AS position FROM {items}
- WHERE `parent_id` = {$this->id}
- AND `{$this->sort_column}` $comp (SELECT `{$this->sort_column}`
- FROM {items} WHERE `id` = $child_id)")
- ->current()->position;
-
- // We stopped short of our target value in the sort (notice that we're using a < comparator
- // above) because it's possible that we have duplicate values in the sort column. An
- // equality check would just arbitrarily pick one of those multiple possible equivalent
- // columns, which would mean that if you choose a sort order that has duplicates, it'd pick
- // any one of them as the child's "position".
- //
- // Fix this by doing a 2nd query where we iterate over the equivalent columns and add them to
- // our base value.
- $result = $db->query("
- SELECT id FROM {items}
- WHERE `parent_id` = {$this->id}
- AND `{$this->sort_column}` = (SELECT `{$this->sort_column}`
- FROM {items} WHERE `id` = $child_id)
- ORDER BY `id` ASC");
- foreach ($result as $row) {
- $position++;
- if ($row->id == $child_id) {
- break;
+
+ // If the comparison column has NULLs in it, we can't use comparators on it and will have to
+ // deal with it the hard way.
+ $count = $db->from("items")
+ ->where("parent_id", $this->id)
+ ->where($this->sort_column, NULL)
+ ->count_records();
+
+ if (empty($count)) {
+ // There are no NULLs in the sort column, so we can just use it directly.
+ $position = $db->query("
+ SELECT COUNT(*) AS position FROM {items}
+ WHERE `parent_id` = {$this->id}
+ AND `{$this->sort_column}` $comp (SELECT `{$this->sort_column}`
+ FROM {items} WHERE `id` = $child->id)")
+ ->current()->position;
+
+ // We stopped short of our target value in the sort (notice that we're using a < comparator
+ // above) because it's possible that we have duplicate values in the sort column. An
+ // equality check would just arbitrarily pick one of those multiple possible equivalent
+ // columns, which would mean that if you choose a sort order that has duplicates, it'd pick
+ // any one of them as the child's "position".
+ //
+ // Fix this by doing a 2nd query where we iterate over the equivalent columns and add them to
+ // our base value.
+ $result = $db->query("
+ SELECT id FROM {items}
+ WHERE `parent_id` = {$this->id}
+ AND `{$this->sort_column}` = (SELECT `{$this->sort_column}`
+ FROM {items} WHERE `id` = $child->id)
+ ORDER BY `id` ASC");
+ foreach ($result as $row) {
+ $position++;
+ if ($row->id == $child->id) {
+ break;
+ }
+ }
+ } else {
+ // There are NULLs in the sort column, so we can't use MySQL comparators. Fall back to
+ // iterating over every child row to get to the current one. This can be wildly inefficient
+ // for really large albums, but it should be a rare case that the user is sorting an album
+ // with null values in the sort column.
+ //
+ // Reproduce the children() functionality here using Database directly to avoid loading the
+ // whole ORM for each row.
+ $orderby = array($this->sort_column => $this->sort_order);
+ // Use id as a tie breaker
+ if ($this->sort_column != "id") {
+ $orderby["id"] = "ASC";
+ }
+
+ $position = 0;
+ foreach ($db->select("id")
+ ->from("items")
+ ->where("parent_id", $this->id)
+ ->orderby($orderby)
+ ->get() as $row) {
+ $position++;
+ if ($row->id == $child->id) {
+ break;
+ }
}
}
@@ -551,6 +586,10 @@ class Item_Model extends ORM_MPTT {
function children($limit=null, $offset=0, $where=array(), $orderby=null) {
if (empty($orderby)) {
$orderby = array($this->sort_column => $this->sort_order);
+ // Use id as a tie breaker
+ if ($this->sort_column != "id") {
+ $orderby["id"] = "ASC";
+ }
}
return parent::children($limit, $offset, $where, $orderby);
}
@@ -569,6 +608,10 @@ class Item_Model extends ORM_MPTT {
function descendants($limit=null, $offset=0, $where=array(), $orderby=null) {
if (empty($orderby)) {
$orderby = array($this->sort_column => $this->sort_order);
+ // Use id as a tie breaker
+ if ($this->sort_column != "id") {
+ $orderby["id"] = "ASC";
+ }
}
return parent::descendants($limit, $offset, $where, $orderby);
}