Files
SkinbaseNova/app/Services/Academy/AcademyCourseNavigationService.php

72 lines
2.6 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Academy;
use App\Models\AcademyCourse;
use App\Models\AcademyCourseLesson;
use App\Models\AcademyLesson;
use Illuminate\Support\Collection;
final class AcademyCourseNavigationService
{
/**
* @return Collection<int, AcademyCourseLesson>
*/
public function orderedCourseLessons(AcademyCourse $course): Collection
{
return $course->courseLessons()
->with(['section', 'lesson.category'])
->get()
->filter(fn (AcademyCourseLesson $courseLesson): bool => $courseLesson->lesson instanceof AcademyLesson
&& (bool) $courseLesson->lesson->active
&& $courseLesson->lesson->published_at !== null
&& $courseLesson->lesson->published_at->lte(now()))
->sort(fn (AcademyCourseLesson $left, AcademyCourseLesson $right): int => $this->courseLessonSortKey($left) <=> $this->courseLessonSortKey($right))
->values();
}
/**
* @return array<int, int>
*/
private function courseLessonSortKey(AcademyCourseLesson $courseLesson): array
{
$section = $courseLesson->section;
return [
$courseLesson->section_id === null ? 0 : 1,
(int) ($section?->order_num ?? 0),
(int) ($section?->id ?? 0),
(int) ($courseLesson->order_num ?? 0),
(int) $courseLesson->id,
];
}
public function firstPublishedLesson(AcademyCourse $course): ?AcademyCourseLesson
{
return $this->orderedCourseLessons($course)->first();
}
public function findCourseLesson(AcademyCourse $course, AcademyLesson $lesson): ?AcademyCourseLesson
{
return $this->orderedCourseLessons($course)
->first(fn (AcademyCourseLesson $courseLesson): bool => $courseLesson->lesson?->is($lesson) ?? false);
}
public function nextLesson(AcademyCourse $course, AcademyLesson $lesson): ?AcademyCourseLesson
{
$ordered = $this->orderedCourseLessons($course);
$index = $ordered->search(fn (AcademyCourseLesson $courseLesson): bool => $courseLesson->lesson?->is($lesson) ?? false);
return is_int($index) ? $ordered->get($index + 1) : null;
}
public function previousLesson(AcademyCourse $course, AcademyLesson $lesson): ?AcademyCourseLesson
{
$ordered = $this->orderedCourseLessons($course);
$index = $ordered->search(fn (AcademyCourseLesson $courseLesson): bool => $courseLesson->lesson?->is($lesson) ?? false);
return is_int($index) && $index > 0 ? $ordered->get($index - 1) : null;
}
}