Attainly/backend/app/Set/UseCases/GetSetLayout/GetSetLayout.php

93 lines
2.7 KiB
PHP

<?php
namespace App\Set\UseCases\GetSetLayout;
use App\Element\Element;
use App\Element\ElementRepository;
use App\Exceptions\NotFoundException;
use App\Set\SetRepository;
use App\Set\SetLevelRepository;
class GetSetLayout
{
public function __construct(
private SetRepository $setRepository,
private SetLevelRepository $setLevelRepository,
private ElementRepository $elementRepository,
) {}
/**
* @throws NotFoundException
*/
public function execute(GetSetLayoutRequest $request): SetLayout
{
$set = $this->setRepository->find($request->setId);
if ($set === null) {
throw new NotFoundException('set not found');
}
$elements = $this->elementRepository->findBySet($set);
$elementsByParentId = [];
$elementCountsByLevelId = [];
foreach ($elements as $element) {
$parentId = $element->getParentElement()?->getId() ?? 0;
$elementsByParentId[$parentId][] = $element;
$levelId = $element->getLevel()->getId();
$elementCountsByLevelId[$levelId]
= ($elementCountsByLevelId[$levelId] ?? 0) + 1;
}
foreach ($elementsByParentId as &$siblings) {
usort($siblings, function (
Element $first,
Element $second,
): int {
$positionComparison = $first->getPosition()
<=> $second->getPosition();
if ($positionComparison !== 0) {
return $positionComparison;
}
return $first->getId() <=> $second->getId();
});
}
unset($siblings);
$layoutLevels = [];
foreach ($this->setLevelRepository->findBySet($set) as $level) {
$layoutLevels[] = new SetLayoutLevel(
level: $level,
elementCount: $elementCountsByLevelId[$level->getId()] ?? 0,
);
}
return new SetLayout(
set: $set,
levels: $layoutLevels,
elements: $this->buildNodes(0, $elementsByParentId),
);
}
/**
* @param array<int, list<Element>> $elementsByParentId
* @return list<ElementLayoutNode>
*/
private function buildNodes(
int $parentId,
array $elementsByParentId,
): array {
$nodes = [];
foreach ($elementsByParentId[$parentId] ?? [] as $element) {
$nodes[] = new ElementLayoutNode(
element: $element,
children: $this->buildNodes(
$element->getId(),
$elementsByParentId,
),
);
}
return $nodes;
}
}