/**
* Method to move a row in the ordering sequence of a group of rows defined by an SQL WHERE clause.
*
* Negative numbers move the row up in the sequence and positive numbers move it down.
*
* @param integer $delta The direction and magnitude to move the row in the ordering sequence.
* @param string $where WHERE clause to use for limiting the selection of rows to compact the ordering values.
*
* @return boolean True on success.
*
* @since 1.7.0
* @throws \UnexpectedValueException
*/
public function move($delta, $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)));
}
$orderingField = $this->getColumnAlias('ordering');
$quotedOrderingField = $this->_db->quoteName($orderingField);
// If the change is none, do nothing.
if (empty($delta)) {
return true;
}
$row = null;
$query = $this->_db->getQuery(true);
// Select the primary key and ordering values from the table.
$query->select(implode(',', $this->_tbl_keys) . ', ' . $quotedOrderingField)->from($this->_tbl);
// If the movement delta is negative move the row up.
if ($delta < 0) {
$query->where($quotedOrderingField . ' < ' . (int) $this->{$orderingField})->order($quotedOrderingField . ' DESC');
} elseif ($delta > 0) {
$query->where($quotedOrderingField . ' > ' . (int) $this->{$orderingField})->order($quotedOrderingField . ' ASC');
}
// Add the custom WHERE clause if set.
if ($where) {
$query->where($where);
}
// Pre-processing by observers
$event = AbstractEvent::create('onTableBeforeMove', ['subject' => $this, 'query' => $query, 'delta' => $delta, 'where' => $where]);
$this->getDispatcher()->dispatch('onTableBeforeMove', $event);
// Select the first row with the criteria.
$query->setLimit(1);
$this->_db->setQuery($query);
$row = $this->_db->loadObject();
// If a row is found, move the item.
if (!empty($row)) {
// Update the ordering field for this instance to the row's ordering value.
$query->clear()->update($this->_tbl)->set($quotedOrderingField . ' = ' . (int) $row->{$orderingField});
$this->appendPrimaryKeys($query);
$this->_db->setQuery($query);
$this->_db->execute();
// Update the ordering field for the row to this instance's ordering value.
$query->clear()->update($this->_tbl)->set($quotedOrderingField . ' = ' . (int) $this->{$orderingField});
$this->appendPrimaryKeys($query, $row);
$this->_db->setQuery($query);
$this->_db->execute();
// Update the instance value.
$this->{$orderingField} = $row->{$orderingField};
} else {
// Update the ordering field for this instance.
$query->clear()->update($this->_tbl)->set($quotedOrderingField . ' = ' . (int) $this->{$orderingField});
$this->appendPrimaryKeys($query);
$this->_db->setQuery($query);
$this->_db->execute();
}
// Post-processing by observers
$event = AbstractEvent::create('onTableAfterMove', ['subject' => $this, 'row' => $row, 'delta' => $delta, 'where' => $where]);
$this->getDispatcher()->dispatch('onTableAfterMove', $event);
return true;
}