Attainly/backend/database/seeders/ElementSeeder.php

214 lines
6 KiB
PHP

<?php
namespace Database\Seeders;
use App\Element\CreateElementDto;
use App\Element\Element;
use App\Element\ElementRepository;
use App\Set\Set;
use App\Set\SetLevel;
use App\Set\SetLevelRepository;
use App\Set\SetRepository;
use Illuminate\Database\Seeder;
use RuntimeException;
class ElementSeeder extends Seeder
{
private const array ELEMENTS_BY_SET = [
'Bible' => [
[
'name' => 'Genesis',
'children' => [
[
'name' => 'Creation',
'children' => [
[
'name' => 'Chapter 1',
'children' => [],
],
[
'name' => 'Chapter 2',
'children' => [],
],
],
],
[
'name' => 'Noah',
'children' => [],
],
],
],
[
'name' => 'Exodus',
'children' => [
[
'name' => 'Shemot',
'children' => [],
],
],
],
],
'Course' => [
[
'name' => 'Foundations',
'children' => [
[
'name' => 'Welcome',
'children' => [],
],
[
'name' => 'Core Concepts',
'children' => [],
],
],
],
[
'name' => 'Applied Practice',
'children' => [
[
'name' => 'Guided Exercise',
'children' => [],
],
[
'name' => 'Final Review',
'children' => [],
],
],
],
],
'Fitness Program' => [
[
'name' => 'Foundation Phase',
'children' => [
[
'name' => 'Strength Day',
'children' => [
[
'name' => 'Squat',
'children' => [],
],
[
'name' => 'Push-up',
'children' => [],
],
],
],
[
'name' => 'Mobility Day',
'children' => [
[
'name' => 'Hip Flow',
'children' => [],
],
],
],
],
],
[
'name' => 'Build Phase',
'children' => [
[
'name' => 'Full Body Circuit',
'children' => [],
],
],
],
],
];
public function run(): void
{
$elementRepository = app(ElementRepository::class);
$setLevelRepository = app(SetLevelRepository::class);
foreach (app(SetRepository::class)->all() as $set) {
$definitions = self::ELEMENTS_BY_SET[$set->getName()] ?? null;
if ($definitions === null) {
continue;
}
$this->seedChildren(
repository: $elementRepository,
set: $set,
levels: $setLevelRepository->findBySet($set),
depth: 0,
parentElement: null,
definitions: $definitions,
);
}
}
/**
* @param list<array{
* name: string,
* children: list<mixed>
* }> $definitions
* @param list<SetLevel> $levels
*/
private function seedChildren(
ElementRepository $repository,
Set $set,
array $levels,
int $depth,
?Element $parentElement,
array $definitions,
): void {
if ($definitions === []) {
return;
}
$level = $levels[$depth] ?? null;
if ($level === null) {
throw new RuntimeException('element level not defined');
}
$siblings = $parentElement === null
? $repository->findTopLevelBySet($set)
: $repository->findByParentElement($parentElement);
foreach ($definitions as $definition) {
$element = $this->findSibling(
siblings: $siblings,
name: $definition['name'],
level: $level,
);
if ($element === null) {
$element = $repository->create(new CreateElementDto(
name: $definition['name'],
level: $level,
parentElement: $parentElement,
));
$siblings[] = $element;
}
$this->seedChildren(
repository: $repository,
set: $set,
levels: $levels,
depth: $depth + 1,
parentElement: $element,
definitions: $definition['children'],
);
}
}
/**
* @param list<Element> $siblings
*/
private function findSibling(
array $siblings,
string $name,
SetLevel $level,
): ?Element {
foreach ($siblings as $sibling) {
if (
$sibling->getName() === $name
&& $sibling->getLevel()->getId() === $level->getId()
) {
return $sibling;
}
}
return null;
}
}