FileHandler::__invoke()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
nc 4
nop 1
dl 0
loc 18
ccs 7
cts 7
cp 1
crap 5
rs 9.6111
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
/*
4
 * This file is part of Flight Routing.
5
 *
6
 * PHP version 8.0 and above required
7
 *
8
 * @author    Divine Niiquaye Ibok <[email protected]>
9
 * @copyright 2019 Divine Niiquaye Ibok (https://divinenii.com/)
10
 * @license   https://opensource.org/licenses/BSD-3-Clause License
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 */
15
16
namespace Flight\Routing\Handlers;
17
18
use Flight\Routing\Exceptions\InvalidControllerException;
19
use Psr\Http\Message\{ResponseFactoryInterface, ResponseInterface};
20
21
/**
22
 * Returns the contents from a file.
23
 *
24
 * @author Divine Niiquaye Ibok <[email protected]>
25
 */
26
final class FileHandler
27
{
28
    public const MIME_TYPE = [
29
        'txt' => 'text/plain',
30
        'htm' => 'text/html',
31
        'html' => 'text/html',
32
        'php' => 'text/html',
33
        'css' => 'text/css',
34
        'js' => 'application/javascript',
35
        'json' => 'application/json',
36
        'xml' => 'text/xml',
37
        'swf' => 'application/x-shockwave-flash',
38
        'flv' => 'video/x-flv',
39
        // images
40
        'png' => 'image/png',
41
        'jpe' => 'image/jpeg',
42
        'jpeg' => 'image/jpeg',
43
        'jpg' => 'image/jpeg',
44
        'gif' => 'image/gif',
45
        'bmp' => 'image/bmp',
46
        'ico' => 'image/vnd.microsoft.icon',
47
        'tiff' => 'image/tiff',
48
        'tif' => 'image/tiff',
49
        'svg' => 'image/svg+xml',
50
        'svgz' => 'image/svg+xml',
51
        // archives
52
        'zip' => 'application/zip',
53
        'rar' => 'application/x-rar-compressed',
54
        'exe' => 'application/x-msdownload',
55
        'msi' => 'application/x-msdownload',
56
        'cab' => 'application/vnd.ms-cab-compressed',
57
        // audio/video
58
        'mp3' => 'audio/mpeg',
59
        'qt' => 'video/quicktime',
60
        'mov' => 'video/quicktime',
61
        // adobe
62
        'pdf' => 'application/pdf',
63
        'psd' => 'image/vnd.adobe.photoshop',
64
        'ai' => 'application/postscript',
65
        'eps' => 'application/postscript',
66
        'ps' => 'application/postscript',
67
        // ms office
68
        'doc' => 'application/msword',
69
        'rtf' => 'application/rtf',
70
        'xls' => 'application/vnd.ms-excel',
71
        'ppt' => 'application/vnd.ms-powerpoint',
72
        'docx' => 'application/msword',
73
        'xlsx' => 'application/vnd.ms-excel',
74
        'pptx' => 'application/vnd.ms-powerpoint',
75
        // open office
76
        'odt' => 'application/vnd.oasis.opendocument.text',
77
        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
78
    ];
79
80 1
    public function __construct(private string $filename, private ?string $mimeType = null)
81
    {
82
    }
83
84 1
    public function __invoke(ResponseFactoryInterface $factory): ResponseInterface
85
    {
86 1
        if (!\file_exists($view = $this->filename) || !$contents = \file_get_contents($view)) {
87 1
            throw new InvalidControllerException(\sprintf('Failed to fetch contents from file "%s"', $view));
88
        }
89
90 1
        if (empty($mime = $this->mimeType ?? self::MIME_TYPE[\pathinfo($view, \PATHINFO_EXTENSION)] ?? null)) {
91
            $mime = (new \finfo(\FILEINFO_MIME_TYPE))->file($view); // @codeCoverageIgnoreStart
92
93
            if (false === $mime) {
94
                throw new InvalidControllerException(\sprintf('Failed to detect mime type of file "%s"', $view));
95
            } // @codeCoverageIgnoreEnd
96
        }
97
98 1
        $response = $factory->createResponse()->withHeader('Content-Type', $mime);
99 1
        $response->getBody()->write($contents);
100
101 1
        return $response;
102
    }
103
}
104