protected function getNewPosition($mode, $pid = null, $insertInto = false)
{
// If there is pid and sorting
if ($this->Database->fieldExists('pid', $this->strTable) && $this->Database->fieldExists('sorting', $this->strTable)) {
// PID is not set - only valid for duplicated records, as they get the same parent ID as the original record!
if ($pid === null && $this->intId && $mode == 'copy') {
$pid = $this->intId;
}
// PID is set (insert after or into the parent record)
if (is_numeric($pid)) {
$newPID = null;
$newSorting = null;
$filter = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4 ? $this->strTable . '_' . CURRENT_ID : $this->strTable;
/** @var SessionInterface $objSession */
$objSession = \System::getContainer()->get('session');
$session = $objSession->all();
// Consider the pagination menu when inserting at the top (see #7895)
if ($insertInto && isset($session['filter'][$filter]['limit'])) {
$limit = substr($session['filter'][$filter]['limit'], 0, strpos($session['filter'][$filter]['limit'], ','));
if ($limit > 0) {
$objInsertAfter = $this->Database->prepare("SELECT id FROM " . $this->strTable . " WHERE pid=? ORDER BY sorting")->limit(1, $limit - 1)->execute($pid);
if ($objInsertAfter->numRows) {
$insertInto = false;
$pid = $objInsertAfter->id;
}
}
}
// Insert the current record at the beginning when inserting into the parent record
if ($insertInto) {
$newPID = $pid;
$objSorting = $this->Database->prepare("SELECT MIN(sorting) AS sorting FROM " . $this->strTable . " WHERE pid=?")->execute($pid);
// Select sorting value of the first record
if ($objSorting->numRows) {
$curSorting = $objSorting->sorting;
// Resort if the new sorting value is not an integer or smaller than 1
if ($curSorting % 2 != 0 || $curSorting < 1) {
$objNewSorting = $this->Database->prepare("SELECT id FROM " . $this->strTable . " WHERE pid=? ORDER BY sorting")->execute($pid);
$count = 2;
$newSorting = 128;
while ($objNewSorting->next()) {
$this->Database->prepare("UPDATE " . $this->strTable . " SET sorting=? WHERE id=?")->limit(1)->execute($count++ * 128, $objNewSorting->id);
}
} else {
$newSorting = $curSorting / 2;
}
} else {
$newSorting = 128;
}
} elseif ($pid > 0) {
$objSorting = $this->Database->prepare("SELECT pid, sorting FROM " . $this->strTable . " WHERE id=?")->limit(1)->execute($pid);
// Set parent ID of the current record as new parent ID
if ($objSorting->numRows) {
$newPID = $objSorting->pid;
$curSorting = $objSorting->sorting;
// Do not proceed without a parent ID
if (is_numeric($newPID)) {
$objNextSorting = $this->Database->prepare("SELECT MIN(sorting) AS sorting FROM " . $this->strTable . " WHERE pid=? AND sorting>?")->execute($newPID, $curSorting);
// Select sorting value of the next record
if ($objNextSorting->sorting !== null) {
$nxtSorting = $objNextSorting->sorting;
// Resort if the new sorting value is no integer or bigger than a MySQL integer
if (($curSorting + $nxtSorting) % 2 != 0 || $nxtSorting >= 4294967295) {
$count = 1;
$objNewSorting = $this->Database->prepare("SELECT id, sorting FROM " . $this->strTable . " WHERE pid=? ORDER BY sorting")->execute($newPID);
while ($objNewSorting->next()) {
$this->Database->prepare("UPDATE " . $this->strTable . " SET sorting=? WHERE id=?")->execute($count++ * 128, $objNewSorting->id);
if ($objNewSorting->sorting == $curSorting) {
$newSorting = $count++ * 128;
}
}
} else {
$newSorting = ($curSorting + $nxtSorting) / 2;
}
} else {
$newSorting = $curSorting + 128;
}
}
} else {
$newPID = $pid;
$newSorting = 128;
}
}
// Set new sorting and new parent ID
$this->set['pid'] = intval($newPID);
$this->set['sorting'] = intval($newSorting);
}
} elseif ($this->Database->fieldExists('pid', $this->strTable)) {
// PID is not set - only valid for duplicated records, as they get the same parent ID as the original record!
if ($pid === null && $this->intId && $mode == 'copy') {
$pid = $this->intId;
}
// PID is set (insert after or into the parent record)
if (is_numeric($pid)) {
// Insert the current record into the parent record
if ($insertInto) {
$this->set['pid'] = $pid;
} elseif ($pid > 0) {
$objParentRecord = $this->Database->prepare("SELECT pid FROM " . $this->strTable . " WHERE id=?")->limit(1)->execute($pid);
if ($objParentRecord->numRows) {
$this->set['pid'] = $objParentRecord->pid;
}
}
}
} elseif ($this->Database->fieldExists('sorting', $this->strTable)) {
// ID is set (insert after the current record)
if ($this->intId) {
$objCurrentRecord = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")->limit(1)->execute($this->intId);
// Select current record
if ($objCurrentRecord->numRows) {
$newSorting = null;
$curSorting = $objCurrentRecord->sorting;
$objNextSorting = $this->Database->prepare("SELECT MIN(sorting) AS sorting FROM " . $this->strTable . " WHERE sorting>?")->execute($curSorting);
// Select sorting value of the next record
if ($objNextSorting->numRows) {
$nxtSorting = $objNextSorting->sorting;
// Resort if the new sorting value is no integer or bigger than a MySQL integer field
if (($curSorting + $nxtSorting) % 2 != 0 || $nxtSorting >= 4294967295) {
$count = 1;
$objNewSorting = $this->Database->execute("SELECT id, sorting FROM " . $this->strTable . " ORDER BY sorting");
while ($objNewSorting->next()) {
$this->Database->prepare("UPDATE " . $this->strTable . " SET sorting=? WHERE id=?")->execute($count++ * 128, $objNewSorting->id);
if ($objNewSorting->sorting == $curSorting) {
$newSorting = $count++ * 128;
}
}
} else {
$newSorting = ($curSorting + $nxtSorting) / 2;
}
} else {
$newSorting = $curSorting + 128;
}
// Set new sorting
$this->set['sorting'] = intval($newSorting);
return;
}
}
// ID is not set or not found (insert at the end)
$objNextSorting = $this->Database->execute("SELECT MAX(sorting) AS sorting FROM " . $this->strTable);
$this->set['sorting'] = intval($objNextSorting->sorting) + 128;
}
}