Improve QueryBuilder for basic sort request
Examples sorts : [ 'created_at' => 'DESC', 'id' => 'ASC' ]

@param Doctrine\ORM\QueryBuilder
@param array $sorts
@return Doctrine\ORM\QueryBuilder
424493
protected function _sort(QueryBuilder $qb, array $sorts = [])
    {
        foreach ($sorts as $field => $direction) {
            $qb->addOrderBy('e.'.$field, $direction);
        }
        return $qb;
    }
1262226
protected static function convertSort($sort)
  {
    /** @var RSort $convertedSort */
    $convertedSort = null;
    if (!empty($sort)) {
      $convertedSort = new RSort();
      $convertedSort->setField($sort->getField());
      switch ($sort->getOrder()) {
        case MSort\Order::Ascending:
          $convertedSort->setOrder(RSort\Order::Ascending);
          break;
        case MSort\Order::Descending:
          $convertedSort->setOrder(RSort\Order::Descending);
          break;
      }
    }
    return $convertedSort;
  }
1049743
protected function getQueryBuilder(array $filters = [], array $sorting = [])
    {
        $queryBuilder = $this->getBaseQueryBuilder();
        if (!empty($filters)) {
            $this->addFilters($queryBuilder, $filters);
        }

        if (empty($sorting)) {
            $this->addSorting($queryBuilder, $this->getDefaultSorting());
        } else {
            $this->addSorting($queryBuilder, $sorting);
        }

        return $queryBuilder;
    }
541003
private function parseSort(array $sort)
    {
        $out = '';
        if (!empty($sort)) {
            $conditions = [];
            foreach ($sort as $field => $direction) {
                $direction = $direction ? 'DESC' : 'ASC';
                $conditions[] = sprintf('%s %s', $field, $direction);
            }
            $out = sprintf(' ORDER BY %s', implode(', ', $conditions));
        }
        return $out;
    }
247264
public function searchBy(
        $conditions = [],
        $sorts = [],
        $joins = [],
        $pager = null,
        $mode = 'and',
        $expression = null
    ) {
        if (!$expression) {
            return $this->search($conditions, $sorts, $joins, $pager, $mode);
        }

        $queryBuilder = $this->createQueryBuilder('o')->select('o');

        $this->queryBuilderExpressionAndConditions($queryBuilder, $conditions, $expression, $mode);
        $this->queryBuilderSorts($queryBuilder, $sorts);
        $this->queryBuilderJoins($queryBuilder, $joins);
        $this->queryBuilderPager($queryBuilder, $pager);

        return $queryBuilder->getQuery()->getResult();
    }
150470
public function sort($sort = null)
    {
        if ($sort !== null && ! is_int($sort)) {
            throw new \InvalidArgumentException(
                'Invalid sort type. Sort type must ne integer.',
                E_USER_ERROR
            );
        }

        return $sort === null
            ? sort($this->storedData)
            : sort($this->storedData, $sort);
    }
859721
public function sort_by($sort, $ord = self::ORD_ASC)
    {
        $this->sort[$sort] = $ord;

        return $this;
    }
3652
public function sortRecords(array $sorting)
    {
        $this->flushCacheBeforeChange();

        $result = parent::sortRecords($sorting);
        $this->flushCacheAfterChange();

        return $result;
    }
628070
public function rSort($sort = null)
    {
        if ($sort !== null && ! is_int($sort)) {
            throw new \InvalidArgumentException(
                'Invalid sort type. Sort type must ne integer.',
                E_USER_ERROR
            );
        }

        return $sort === null
            ? rsort($this->storedData)
            : rsort($this->storedData, $sort);
    }
313617
public function getSort($sortName): ?OrderBy
    {
        [$name, $sorts] = $this->getArrayAndKeyName($sortName, 'sorts');

        return array_first($sorts, function ($sort) use ($name) {
            return $sort->getName() === $name;
        });
    }
642639
public function addSort($sort)
    {
        if (!$this->sorts->contains($sort)) {
            $this->sorts[] = $sort;
        }

        return $this;
    }
209168
public function orderBy($field, $sort)
    {
        $this->orderBy = $field;
        $this->sortBy  = $sort;
        return $this;
    }
747532
private function orderQueryBuilderBy(QueryBuilder $queryBuilder, TableInterface $table, $sort)
    {
        if (!is_array($sort)) {
            $sort = array($sort => $table->getOption('order', 'DESC'));
        }

        foreach ($sort as $fieldName => $order) {
            // Check field is sortable
            $field = $table->getField($fieldName);
            if (!$field->getOption('sortable')) {
                throw new InvalidArgumentException("Field $fieldName is not sortable in table " . $table->getName());
            }

            foreach ((array)$field->getOption('order_path') as $orderBy) {
                $queryBuilder->addOrderBy($this->fixQueryPath($orderBy, $field), $order);
            }
        }
    }
27081
public function sort($sorts)
    {
        usort($this->rows, 
            function ($a, $b) use ($sorts) {
                $cmp = 0;
                foreach ($sorts as $sort => $direction) {
                    if (is_string($direction)) {
                        $cmp = is_numeric($a[$sort]) && is_numeric($b[$sort]) ? 
                            $a[$sort] - $b[$sort] : strcmp($a[$sort], $b[$sort]);
                        $cmp = $direction === 'asc' ? $cmp : - $cmp;
                    } else if (is_callable($direction)) {
                        $cmp = $direction($a[$sort], $b[$sort]);
                    }
                    if ($cmp !== 0) {
                        break;
                    }
                }
                return $cmp;
            }
        );
        return $this;
    }
532526
protected function addSort(QueryBuilder $queryBuilder, $sortField, $sortAscending)
    {
        if ($sortField !== null) {

            $type = $this->definition->getType($sortField);
            if ($type === 'many') {
                $sortField = $this->definition->getInitialSortField();
            }

            $order = $sortAscending === true ? 'ASC' : 'DESC';
            $queryBuilder->orderBy('`'.$sortField.'`', $order);
        }
    }
51820
protected function sortOrderQuery(
        array $sortOrderCondition = [],
        string $sortOrderAttribute = 'sortOrder'
    ): ActiveQuery {
        return static::find()
            ->andWhere($sortOrderCondition)
            ->orderBy([
                $sortOrderAttribute => SORT_ASC,
                'dateUpdated' => SORT_DESC
            ]);
    }
737632
public function addSort(BuilderInterface $sort)
    {
        $this->getEndpoint(SortEndpoint::NAME)->add($sort);

        return $this;
    }