72 lines
2.6 KiB
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;
|
|
}
|
|
} |