Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
91.67% covered (success)
91.67%
22 / 24
80.00% covered (warning)
80.00%
4 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
ImportFileStorage
91.67% covered (success)
91.67%
22 / 24
80.00% covered (warning)
80.00%
4 / 5
11.07
0.00% covered (danger)
0.00%
0 / 1
 disk
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 pathFor
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 storeUpload
85.71% covered (warning)
85.71%
12 / 14
0.00% covered (danger)
0.00%
0 / 1
4.05
 absolutePath
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 verifyHash
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace ImovelZapAi\Importing\Application\Services;
6
7use Illuminate\Http\UploadedFile;
8use Illuminate\Support\Facades\Storage;
9use ImovelZapAi\Importing\Domain\Exceptions\ImportException;
10
11final class ImportFileStorage
12{
13    public function disk(): string
14    {
15        return (string) config('importing.disk', 'local');
16    }
17
18    public function pathFor(string $tenantId, string $importId): string
19    {
20        return "imports/{$tenantId}/{$importId}/source.xml";
21    }
22
23    /**
24     * @return array{path: string, sha256: string, size_bytes: int, mime_type: string}
25     */
26    public function storeUpload(string $tenantId, string $importId, UploadedFile $file): array
27    {
28        $path = $this->pathFor($tenantId, $importId);
29        $absolute = $file->getRealPath();
30
31        if ($absolute === false) {
32            throw ImportException::fileMissing();
33        }
34
35        $sha256 = hash_file('sha256', $absolute);
36        if ($sha256 === false) {
37            throw ImportException::fileMissing();
38        }
39
40        Storage::disk($this->disk())->put($path, fopen($absolute, 'rb'));
41
42        return [
43            'path' => $path,
44            'sha256' => $sha256,
45            'size_bytes' => (int) $file->getSize(),
46            'mime_type' => (string) ($file->getMimeType() ?: 'application/xml'),
47        ];
48    }
49
50    public function absolutePath(string $path): string
51    {
52        $full = Storage::disk($this->disk())->path($path);
53
54        if (! is_file($full)) {
55            throw ImportException::fileMissing();
56        }
57
58        return $full;
59    }
60
61    public function verifyHash(string $path, string $expectedSha256): void
62    {
63        $absolute = $this->absolutePath($path);
64        $actual = hash_file('sha256', $absolute);
65
66        if ($actual === false || ! hash_equals($expectedSha256, $actual)) {
67            throw ImportException::hashMismatch();
68        }
69    }
70}