src/Sortable.php
public function deriveSortVal($targetId, $position = 'after', $groupingId = null)
    {
        if (!$position || !in_array($position, ['after', 'before'])) {
            throw new SortableException('You must specify correct position: "after" or "before".');
        }

        $sort = false;

        if ($this->grpColumn) {
            if ($groupingId !== null) {
                $subQueryGroupId = $groupingId;
            }
            else {
                $subQueryGroupId = (new Query())
                    ->select($this->grpColumn)
                    ->from($this->targetTable)
                    ->where([$this->pkColumn => $targetId]);
            }
        }

        $subQuery = (new Query())
            ->select($this->srtColumn)
            ->from($this->targetTable)
            ->where([
                'and',
                $this->grpColumn ? ['=', $this->grpColumn, $subQueryGroupId] : [],
                [$this->pkColumn => $targetId]
            ]);

        $query = (new Query())
            ->select($this->srtColumn)
            ->from($this->targetTable)
            ->where([
                'and',
                $this->grpColumn ? ['=', $this->grpColumn, $subQueryGroupId] : [],
                $position == 'after' ? ['>=', $this->srtColumn, $subQuery] : ['<=', $this->srtColumn, $subQuery],
                $this->skipRowsClause()
            ])
            ->orderBy($position == 'after' ? $this->srtColumn.' ASC' : $this->srtColumn.' DESC')
            ->limit(2);

        $result = $query->all($this->db);
        $result = array_values($result);

        if (!count($result)) {
            $withGrpMsg = $this->grpColumn ? "with spcified {$this->grpColumn}" : '';
            throw new SortableException(
                sprintf('Record [ %d ] %s to calculate a sort value not found', $targetId, $withGrpMsg)
            );
        }

        if (count($result) == 2) {
            $sort = (int)ceil(($result[0][$this->srtColumn] + $result[1][$this->srtColumn]) / 2);
            if ($sort == $result[0][$this->srtColumn] || $sort == $result[1][$this->srtColumn]) $sort = false;
        }
        else if (count($result) == 1) {
            $sort = $position == 'after' ?
                (int)ceil($result[0][$this->srtColumn] + $this->sortGap) : (int)ceil($result[0][$this->srtColumn] / 2);
            if ($sort == $result[0][$this->srtColumn]) $sort = false;
        }

        return $sort;
    }
public function deriveSortVal($targetId, $position = 'after', $groupingId = null)
    {
        if (!$position || !in_array($position, ['after', 'before'])) {
            throw new SortableException('You must specify correct position: "after" or "before".');
        }

        $sort = false;

        if ($this->grpColumn) {
            if ($groupingId !== null) {
                $subQueryGroupId = $groupingId;
            }
            else {
                $subQueryGroupId = (new Query())
                    ->select($this->grpColumn)
                    ->from($this->targetTable)
                    ->where([$this->pkColumn => $targetId]);
            }
        }

        $subQuery = (new Query())
            ->select($this->srtColumn)
            ->from($this->targetTable)
            ->where([
                'and',
                $this->grpColumn ? ['=', $this->grpColumn, $subQueryGroupId] : [],
                [$this->pkColumn => $targetId]
            ]);

        $query = (new Query())
            ->select($this->srtColumn)
            ->from($this->targetTable)
            ->where([
                'and',
                $this->grpColumn ? ['=', $this->grpColumn, $subQueryGroupId] : [],
                $position == 'after' ? ['>=', $this->srtColumn, $subQuery] : ['<=', $this->srtColumn, $subQuery],
                $this->skipRowsClause()
            ])
            ->orderBy($position == 'after' ? $this->srtColumn.' ASC' : $this->srtColumn.' DESC')
            ->limit(2);

        $result = $query->all($this->db);
        $result = array_values($result);

        if (!count($result)) {
            $withGrpMsg = $this->grpColumn ? "with spcified {$this->grpColumn}" : '';
            throw new SortableException(
                sprintf('Record [ %d ] %s to calculate a sort value not found', $targetId, $withGrpMsg)
            );
        }

        if (count($result) == 2) {
            $sort = (int)ceil(($result[0][$this->srtColumn] + $result[1][$this->srtColumn]) / 2);
            if ($sort == $result[0][$this->srtColumn] || $sort == $result[1][$this->srtColumn]) $sort = false;
        }
        else if (count($result) == 1) {
            $sort = $position == 'after' ?
                (int)ceil($result[0][$this->srtColumn] + $this->sortGap) : (int)ceil($result[0][$this->srtColumn] / 2);
            if ($sort == $result[0][$this->srtColumn]) $sort = false;
        }

        return $sort;
    }
Derives sort value. If it not possible (there is an internal logic of the component) to get the value then false
will be returned. So no necessary data modifications happen for maintaining sort values.

@param int $targetId Record id after or before which a new record supposed to be inserted.
@param string $position The possible options are: 'after', 'before'. Specifies how to interpret the $targetId.
@param null|int $groupingId Id of the grouping entity. If it not passed the $targetId will be used in a sub-query
to derived its value. It has sense only if grpColumn is configured.
@return bool|int Returns false if it's not possible to derive a sort value,
thus sort field for all items following $targetId (including $targetId itself if $position == 'before')
must be incremented by $this->sortGap value.
@throws SortableException