New_Micro_Learning/backend/app/Modules/Taxonomy/Http/ContentMappingController.php

105 خطوط
4.1 KiB
PHP

<?php
namespace App\Modules\Taxonomy\Http;
use App\Http\Controllers\Controller;
use App\Modules\Taxonomy\Application\ContentMappingService;
use App\Modules\Taxonomy\Domain\ContentTaxonomyMapping;
use App\Modules\Taxonomy\Domain\Enums\MappableType;
use App\Modules\Taxonomy\Domain\Enums\MappingSource;
use App\Modules\Taxonomy\Domain\Enums\MappingType;
use App\Modules\Taxonomy\Http\Requests\StoreContentMappingRequest;
use App\Modules\Taxonomy\Policies\TaxonomyPolicy;
use App\Modules\Tenancy\Application\TenantContext;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Validation\ValidationException;
final class ContentMappingController extends Controller
{
public function __construct(
private readonly TenantContext $tenant,
private readonly TaxonomyPolicy $policy,
private readonly ContentMappingService $service,
) {}
public function index(Request $request): JsonResponse
{
abort_unless($this->policy->view($request->user()), 403);
$request->validate([
'mappableType' => ['required', Rule::enum(MappableType::class)],
'mappableId' => ['required', 'string'],
]);
$mappings = ContentTaxonomyMapping::query()
->with('taxonomyNode.type')
->where('organization_id', $this->tenant->id())
->where('mappable_type', $request->string('mappableType'))
->where('mappable_id', $request->string('mappableId'))
->get()
->map(fn (ContentTaxonomyMapping $mapping) => $this->payload($mapping));
return response()->json(['data' => $mappings]);
}
public function store(StoreContentMappingRequest $request): JsonResponse
{
abort_unless($this->policy->manage($request->user()), 403);
$data = $request->validated();
$mapping = $this->service->create(
$this->tenant->id(),
$data['courseVersionId'],
MappableType::from($data['mappableType']),
$data['mappableId'],
$data['taxonomyNodeId'],
MappingType::from($data['mappingType']),
$data['masteryLevel'] ?? null,
(float) $data['weight'],
MappingSource::from($data['source']),
isset($data['confidence']) ? (float) $data['confidence'] : null,
$request->user(),
);
return response()->json(['data' => $this->payload($mapping->load('taxonomyNode.type'))], 201);
}
public function destroy(Request $request, string $mapping): JsonResponse
{
abort_unless($this->policy->manage($request->user()), 403);
$model = ContentTaxonomyMapping::query()
->where('organization_id', $this->tenant->id())
->findOrFail($mapping);
if ($model->courseVersion->status->value === 'published') {
throw ValidationException::withMessages(['courseVersionId' => ['Published course version mappings are immutable.']]);
}
$model->delete();
return response()->json(status: 204);
}
private function payload(ContentTaxonomyMapping $mapping): array
{
return [
'id' => $mapping->getKey(),
'courseVersionId' => $mapping->course_version_id,
'entityType' => $mapping->mappable_type->value,
'entityId' => $mapping->mappable_id,
'mappingType' => $mapping->mapping_type->value,
'masteryLevel' => $mapping->mastery_level,
'weight' => (float) $mapping->weight,
'source' => $mapping->source->value,
'confidence' => $mapping->confidence === null ? null : (float) $mapping->confidence,
'confirmationStatus' => $mapping->confirmation_status->value,
'direct' => true,
'inheritedFrom' => null,
'taxonomyNode' => [
'id' => $mapping->taxonomyNode->getKey(),
'name' => $mapping->taxonomyNode->name,
'code' => $mapping->taxonomyNode->code,
'type' => $mapping->taxonomyNode->type->key,
],
];
}
}