107 خطوط
5.1 KiB
PHP
107 خطوط
5.1 KiB
PHP
<?php
|
|
|
|
namespace App\Modules\Courses\Application;
|
|
|
|
use App\Modules\Courses\Domain\CourseVersion;
|
|
|
|
final class CourseVersionComparison
|
|
{
|
|
/** @return array<string, mixed> */
|
|
public function compare(CourseVersion $before, CourseVersion $after): array
|
|
{
|
|
$before->loadMissing(['modules.lessons.blocks', 'assessments.questions']);
|
|
$after->loadMissing(['modules.lessons.blocks', 'assessments.questions']);
|
|
|
|
$categories = [
|
|
$this->category('structure', 'ساختار', $this->structure($before), $this->structure($after), $this->structureLabel($before), $this->structureLabel($after)),
|
|
$this->category('content', 'محتوا', $this->content($before), $this->content($after), $this->contentLabel($before), $this->contentLabel($after)),
|
|
$this->category('assessments', 'ارزیابیها', $this->assessments($before), $this->assessments($after), $this->assessmentLabel($before), $this->assessmentLabel($after)),
|
|
$this->category('settings', 'تنظیمات', $this->settings($before), $this->settings($after), 'مشخصات و قوانین نسخه', 'مشخصات و قوانین نسخه'),
|
|
];
|
|
|
|
return [
|
|
'compatible' => true,
|
|
'before' => $this->identity($before),
|
|
'after' => $this->identity($after),
|
|
'changedCategories' => collect($categories)->where('changed', true)->count(),
|
|
'categories' => $categories,
|
|
];
|
|
}
|
|
|
|
public function unpublishedChangeCount(CourseVersion $version): int
|
|
{
|
|
if ($version->status->value !== 'draft') {
|
|
return 0;
|
|
}
|
|
if (! $version->source_version_id) {
|
|
$version->loadMissing(['modules.lessons.blocks', 'assessments.questions']);
|
|
|
|
return $version->modules->count() + $version->lessons->count() + $version->blocks->count() + $version->assessments->count();
|
|
}
|
|
$source = CourseVersion::query()->where('organization_id', $version->organization_id)->where('course_id', $version->course_id)->find($version->source_version_id);
|
|
if (! $source) {
|
|
return 0;
|
|
}
|
|
|
|
return collect($this->compare($source, $version)['categories'])->where('changed', true)->count();
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
private function identity(CourseVersion $version): array
|
|
{
|
|
return ['id' => $version->getKey(), 'number' => $version->version_number, 'status' => $version->status->value];
|
|
}
|
|
|
|
/** @return array<string, mixed> */
|
|
private function category(string $key, string $label, array $before, array $after, string $beforeLabel, string $afterLabel): array
|
|
{
|
|
return compact('key', 'label', 'beforeLabel', 'afterLabel') + ['changed' => $before !== $after];
|
|
}
|
|
|
|
private function structure(CourseVersion $version): array
|
|
{
|
|
return $version->modules->sortBy('position')->map(fn ($module) => [
|
|
'title' => $module->title,
|
|
'position' => $module->position,
|
|
'lessons' => $module->lessons->sortBy('position')->map(fn ($lesson) => ['title' => $lesson->title, 'position' => $lesson->position, 'presentationMode' => $lesson->presentation_mode])->values()->all(),
|
|
])->values()->all();
|
|
}
|
|
|
|
private function content(CourseVersion $version): array
|
|
{
|
|
return $version->modules->sortBy('position')->flatMap(fn ($module) => $module->lessons->sortBy('position')->map(fn ($lesson) => [
|
|
'lessonPosition' => $lesson->position,
|
|
'blocks' => $lesson->blocks->sortBy('position')->map(fn ($block) => ['type' => $block->type, 'schemaVersion' => $block->schema_version, 'data' => $block->data, 'style' => $block->style, 'behavior' => $block->behavior, 'responsive' => $block->responsive, 'accessibility' => $block->accessibility, 'position' => $block->position])->values()->all(),
|
|
]))->values()->all();
|
|
}
|
|
|
|
private function assessments(CourseVersion $version): array
|
|
{
|
|
return $version->assessments->sortBy('created_at')->map(fn ($assessment) => [
|
|
'title' => $assessment->title,
|
|
'settings' => $assessment->settings,
|
|
'questions' => $assessment->questions->sortBy('position')->map(fn ($question) => ['type' => $question->type, 'prompt' => $question->prompt, 'configuration' => $question->configuration, 'position' => $question->position])->values()->all(),
|
|
])->values()->all();
|
|
}
|
|
|
|
private function settings(CourseVersion $version): array
|
|
{
|
|
return ['title' => $version->title, 'description' => $version->description, 'settings' => $version->settings, 'completionRules' => $version->completion_rules];
|
|
}
|
|
|
|
private function structureLabel(CourseVersion $version): string
|
|
{
|
|
return $version->modules->count().' ماژول · '.$version->lessons->count().' درس';
|
|
}
|
|
|
|
private function contentLabel(CourseVersion $version): string
|
|
{
|
|
return $version->blocks->count().' بلوک محتوایی';
|
|
}
|
|
|
|
private function assessmentLabel(CourseVersion $version): string
|
|
{
|
|
return $version->assessments->count().' ارزیابی';
|
|
}
|
|
}
|