Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
UploadProvidedDocumentAction
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
2 / 2
3
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __invoke
100.00% covered (success)
100.00%
21 / 21
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace App\Action\Document\Provided\Admin;
6
7use App\Domain\Document\Provided\Service\ProvidedDocumentService;
8use App\Domain\Exception\BadRequestException;
9use App\Renderer\JsonRenderer;
10use App\Support\Row;
11use Psr\Http\Message\ResponseInterface;
12use Psr\Http\Message\ServerRequestInterface;
13use Psr\Http\Message\UploadedFileInterface;
14
15/**
16 * Admin uploads a document FOR an investor (FSC-57).
17 *
18 * Expected multipart form fields:
19 *   - title        (string, required)
20 *   - description  (string, optional)
21 *   - file         (single uploaded file under the field name "file")
22 */
23final readonly class UploadProvidedDocumentAction
24{
25    public function __construct(
26        private ProvidedDocumentService $service,
27        private JsonRenderer $renderer,
28    ) {}
29
30    /**
31     * @param array<string, string> $args
32     * @param ServerRequestInterface $request
33     * @param ResponseInterface $response
34     */
35    public function __invoke(
36        ServerRequestInterface $request,
37        ResponseInterface $response,
38        array $args,
39    ): ResponseInterface {
40        $investorId = (int)$args['investorId'];
41        $userId = Row::int($request->getAttributes(), 'userId');
42
43        $body = (array)$request->getParsedBody();
44        $title = Row::nullableString($body, 'title') ?? '';
45        $description = Row::nullableString($body, 'description');
46
47        $files = $request->getUploadedFiles();
48        $file = $files['file'] ?? null;
49        if (!$file instanceof UploadedFileInterface) {
50            throw new BadRequestException('A file is required (form field "file").');
51        }
52
53        $document = $this->service->uploadForInvestor(
54            investorId: $investorId,
55            userId: $userId,
56            title: $title,
57            description: $description,
58            file: $file,
59        );
60
61        return $this->renderer->json($response, [
62            'success' => true,
63            'message' => 'Document provided to investor.',
64            'data' => ['document' => $document->toArray()],
65        ], 201);
66    }
67}