/**
* Method to compact the ordering values of rows in a group of rows defined by an SQL WHERE clause.
*
* @param string $where WHERE clause to use for limiting the selection of rows to compact the ordering values.
*
* @return mixed Boolean True on success.
*
* @since 1.7.0
* @throws \UnexpectedValueException
*/
public function reorder($where = '')
{
// Check if there is an ordering field set
if (!$this->hasField('ordering')) {
throw new \UnexpectedValueException(sprintf('%s does not support ordering.', \get_class($this)));
}
$quotedOrderingField = $this->_db->quoteName($this->getColumnAlias('ordering'));
$subquery = $this->_db->getQuery(true)->from($this->_tbl)->selectRowNumber($quotedOrderingField, 'new_ordering');
$query = $this->_db->getQuery(true)->update($this->_tbl)->set($quotedOrderingField . ' = sq.new_ordering');
$innerOn = array();
// Get the primary keys for the selection.
foreach ($this->_tbl_keys as $i => $k) {
$subquery->select($this->_db->quoteName($k, 'pk__' . $i));
$innerOn[] = $this->_db->quoteName($k) . ' = sq.' . $this->_db->quoteName('pk__' . $i);
}
// Setup the extra where and ordering clause data.
if ($where) {
$subquery->where($where);
$query->where($where);
}
$subquery->where($quotedOrderingField . ' >= 0');
$query->where($quotedOrderingField . ' >= 0');
$query->innerJoin('(' . (string) $subquery . ') AS sq ');
foreach ($innerOn as $key) {
$query->where($key);
}
// Pre-processing by observers
$event = AbstractEvent::create('onTableBeforeReorder', ['subject' => $this, 'query' => $query, 'where' => $where]);
$this->getDispatcher()->dispatch('onTableBeforeReorder', $event);
$this->_db->setQuery($query);
$this->_db->execute();
// Post-processing by observers
$event = AbstractEvent::create('onTableAfterReorder', ['subject' => $this, 'where' => $where]);
$this->getDispatcher()->dispatch('onTableAfterReorder', $event);
return true;
}