Files
alrahma_sunday_school_api/app/Http/Controllers/Api/Messaging/MessagesController.php
T
2026-06-11 11:46:12 -04:00

236 lines
7.5 KiB
PHP

<?php
namespace App\Http\Controllers\Api\Messaging;
use App\Http\Controllers\Api\Core\BaseApiController;
use App\Http\Requests\Messaging\MessageIndexRequest;
use App\Http\Requests\Messaging\MessageSendRequest;
use App\Http\Requests\Messaging\MessageUpdateRequest;
use App\Http\Resources\Messaging\MessageCollection;
use App\Http\Resources\Messaging\MessageResource;
use App\Http\Resources\Messaging\RecipientResource;
use App\Models\Message;
use App\Services\Messaging\MessageCommandService;
use App\Services\Messaging\MessageQueryService;
use App\Services\Messaging\MessageRecipientService;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;
class MessagesController extends BaseApiController
{
public function __construct(
private MessageQueryService $queryService,
private MessageCommandService $commandService,
private MessageRecipientService $recipientService
) {
parent::__construct();
}
public function index(MessageIndexRequest $request): JsonResponse
{
$guard = $this->authenticatedUserIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$filters = $request->validated();
$page = (int) ($filters['page'] ?? 1);
$perPage = (int) ($filters['per_page'] ?? 20);
$this->authorize('viewAny', Message::class);
$role = $this->queryService->getUserRoleName($guard);
$messages = $this->queryService->inbox($guard, $filters, $page, $perPage);
$collection = new MessageCollection($messages);
$meta = $collection->with($request)['meta'] ?? null;
return $this->success([
'role' => $role,
'messages' => $collection->toArray($request),
'meta' => $meta,
]);
}
public function inbox(MessageIndexRequest $request): JsonResponse
{
return $this->listMessages($request, 'inbox');
}
public function sent(MessageIndexRequest $request): JsonResponse
{
return $this->listMessages($request, 'sent');
}
public function drafts(MessageIndexRequest $request): JsonResponse
{
return $this->listMessages($request, 'drafts');
}
public function trash(MessageIndexRequest $request): JsonResponse
{
return $this->listMessages($request, 'trash');
}
public function show(int $id): JsonResponse
{
$message = $this->queryService->findForUser($id);
if (! $message) {
return $this->error('Message not found.', Response::HTTP_NOT_FOUND);
}
$this->authorize('view', $message);
$userId = (int) (auth()->id() ?? 0);
if ($message->recipient_id === $userId) {
$this->commandService->markRead($message);
$message->refresh();
}
return $this->success([
'message' => new MessageResource($message),
]);
}
public function store(MessageSendRequest $request): JsonResponse
{
$guard = $this->authenticatedUserIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$this->authorize('create', Message::class);
try {
$message = $this->commandService->create($guard, $request->validated(), $request->file('attachment'));
} catch (\Throwable $e) {
Log::error('Message send failed: '.$e->getMessage());
return $this->error($e->getMessage(), Response::HTTP_BAD_REQUEST);
}
return $this->success([
'message' => new MessageResource($message->fresh(['sender', 'recipient'])),
], 'Message sent.', Response::HTTP_CREATED);
}
public function receive(): JsonResponse
{
$guard = $this->authenticatedUserIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$messages = $this->queryService->receivedAndMarkRead($guard);
return $this->success([
'messages' => (new MessageCollection(collect($messages)))->toArray(request()),
]);
}
public function recipients(string $type): JsonResponse
{
$type = strtolower(trim($type));
$data = match ($type) {
'teacher' => $this->recipientService->teachers(),
'parent' => $this->recipientService->parents(),
default => null,
};
if ($data === null) {
return $this->error('Invalid recipient type.', Response::HTTP_BAD_REQUEST);
}
$payload = array_map(fn ($row) => (new RecipientResource($row))->toArray(request()), $data);
return $this->success([
'recipients' => $payload,
]);
}
public function update(MessageUpdateRequest $request, int $id): JsonResponse
{
$message = Message::query()->find($id);
if (! $message) {
return $this->error('Message not found.', Response::HTTP_NOT_FOUND);
}
$this->authorize('update', $message);
try {
$updated = $this->commandService->update($message, $request->validated());
} catch (\Throwable $e) {
Log::error('Message update failed: '.$e->getMessage());
return $this->error('Unable to update message.', Response::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->success([
'message' => new MessageResource($updated->load(['sender', 'recipient'])),
], 'Message updated.');
}
public function destroy(int $id): JsonResponse
{
$message = Message::query()->find($id);
if (! $message) {
return $this->error('Message not found.', Response::HTTP_NOT_FOUND);
}
$this->authorize('delete', $message);
try {
$trashed = $this->commandService->trash($message);
} catch (\Throwable $e) {
Log::error('Message delete failed: '.$e->getMessage());
return $this->error('Unable to delete message.', Response::HTTP_INTERNAL_SERVER_ERROR);
}
if (! $trashed) {
return $this->error('Unable to delete message.', Response::HTTP_INTERNAL_SERVER_ERROR);
}
return $this->success(null, 'Message deleted.');
}
private function listMessages(MessageIndexRequest $request, string $bucket): JsonResponse
{
$guard = $this->authenticatedUserIdOrUnauthorized();
if ($guard instanceof JsonResponse) {
return $guard;
}
$filters = $request->validated();
$page = (int) ($filters['page'] ?? 1);
$perPage = (int) ($filters['per_page'] ?? 20);
$this->authorize('viewAny', Message::class);
$paginator = match ($bucket) {
'sent' => $this->queryService->sent($guard, $filters, $page, $perPage),
'drafts' => $this->queryService->drafts($guard, $filters, $page, $perPage),
'trash' => $this->queryService->trash($guard, $filters, $page, $perPage),
default => $this->queryService->inbox($guard, $filters, $page, $perPage),
};
$collection = new MessageCollection($paginator);
$meta = $collection->with($request)['meta'] ?? null;
return $this->success([
'messages' => $collection->toArray($request),
'meta' => $meta,
]);
}
private function authenticatedUserIdOrUnauthorized(): int|JsonResponse
{
$userId = (int) (auth()->id() ?? 0);
if ($userId <= 0) {
return $this->error('Unauthorized.', Response::HTTP_UNAUTHORIZED);
}
return $userId;
}
}