AzuraCast/src/Controller/Api/Traits/CanSortResults.php

105 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Controller\Api\Traits;
use App\Http\ServerRequest;
use App\Utilities\Types;
use Doctrine\Common\Collections\Order;
use Doctrine\ORM\QueryBuilder;
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
trait CanSortResults
{
use UsesPropertyAccessor;
protected function sortQueryBuilder(
ServerRequest $request,
QueryBuilder $queryBuilder,
array $sortLookup,
?string $defaultSort,
Order $defaultSortOrder = Order::Ascending
): QueryBuilder {
[$sort, $sortOrder] = $this->getSortFromRequest($request, $defaultSortOrder);
$sortValue = (null !== $sort && isset($sortLookup[$sort]))
? $sortLookup[$sort]
: $defaultSort;
if (null === $sortValue) {
return $queryBuilder;
}
return $queryBuilder->addOrderBy($sortValue, $sortOrder->value);
}
protected function sortArray(
ServerRequest $request,
array $results,
array $sortLookup,
?string $defaultSort = null,
Order $defaultSortOrder = Order::Ascending
): array {
[$sort, $sortOrder] = $this->getSortFromRequest($request, $defaultSortOrder);
$sortValue = (null !== $sort && isset($sortLookup[$sort]))
? $sortLookup[$sort]
: $defaultSort;
if (null === $sortValue) {
return $results;
}
$propertyAccessor = self::getPropertyAccessor();
usort(
$results,
static fn(mixed $a, mixed $b) => self::sortByDotNotation($a, $b, $propertyAccessor, $sortValue, $sortOrder)
);
return $results;
}
/**
* @return array{string|null, Order}
*/
protected function getSortFromRequest(
ServerRequest $request,
Order $defaultSortOrder = Order::Ascending
): array {
$sortOrder = Types::stringOrNull($request->getParam('sortOrder'), true);
$orderEnum = (null !== $sortOrder)
? Order::tryFrom(strtoupper($sortOrder)) ?? $defaultSortOrder
: $defaultSortOrder;
return [
Types::stringOrNull($request->getParam('sort'), true),
$orderEnum,
];
}
protected static function sortByDotNotation(
object|array $a,
object|array $b,
PropertyAccessorInterface $propertyAccessor,
string $sortValue,
Order $sortOrder = Order::Ascending
): int {
$aVal = $propertyAccessor->getValue($a, $sortValue);
$bVal = $propertyAccessor->getValue($b, $sortValue);
if (is_string($aVal)) {
$aVal = mb_strtolower($aVal, 'UTF-8');
}
if (is_string($bVal)) {
$bVal = mb_strtolower($bVal, 'UTF-8');
}
return (Order::Ascending === $sortOrder)
? $aVal <=> $bVal
: $bVal <=> $aVal;
}
}