1<?php
2
3
4namespace ComboStrap;
5
6
7use renderer_plugin_combo_analytics;
8
9class Mime
10{
11
12    public const JSON = "application/json";
13    public const HTML = "text/html";
14    public const XHTML = "text/xhtml";
15    const PLAIN_TEXT = "text/plain";
16    public const SVG = "image/svg+xml";
17    public const JAVASCRIPT = "text/javascript";
18    const PNG = "image/png";
19    const GIF = "image/gif";
20    const JPEG = "image/jpeg";
21    const BMP = "image/bmp";
22    const WEBP = "image/webp";
23    const CSS = "text/css";
24    const MARKDOWN = "text/markdown";
25    const PDF = "application/pdf";
26    const BINARY_MIME = "application/octet-stream";
27    public const RASTER_MIMES = [
28        Mime::BMP,
29        Mime::WEBP,
30        Mime::JPEG,
31        Mime::GIF,
32        MIME::PNG
33    ];
34
35    const XML = "text/xml";
36    const INSTRUCTIONS = "text/i";
37    const META = "text/meta";
38    const HANDLEBARS = "text/hbs";
39
40    /**
41     * @var array|null
42     */
43    private static ?array $knownTypes;
44
45    /**
46     * @var string
47     */
48    private $mime;
49
50    /**
51     * Mime constructor.
52     */
53    public function __construct(string $mime)
54    {
55        if (trim($mime) === "") {
56            LogUtility::msg("The mime should not be an empty string");
57        }
58        $this->mime = $mime;
59    }
60
61    public static function create(string $mime): Mime
62    {
63        return new Mime($mime);
64    }
65
66    /**
67     * @throws ExceptionNotFound
68     */
69    public static function createFromExtension($extension): Mime
70    {
71        switch ($extension) {
72            case FetcherSvg::EXTENSION:
73                /**
74                 * Svg is authorized when viewing but is not part
75                 * of the {@link File::getKnownMime()}
76                 */
77                return new Mime(Mime::SVG);
78            case "js":
79                return new Mime(Mime::JAVASCRIPT);
80            case renderer_plugin_combo_analytics::RENDERER_NAME_MODE:
81            case Json::EXTENSION:
82                return new Mime(Mime::JSON);
83            case "md":
84                return new Mime(Mime::MARKDOWN);
85            case "txt":
86                return new Mime(Mime::PLAIN_TEXT);
87            case "xhtml":
88                return new Mime(Mime::XHTML);
89            case "html":
90                return new Mime(Mime::HTML);
91            case "png":
92                return new Mime(Mime::PNG);
93            case "css":
94                return new Mime(Mime::CSS);
95            case "jpg":
96            case "jpeg":
97                return new Mime(Mime::JPEG);
98            case "webp":
99                return new Mime(Mime::WEBP);
100            case "bmp":
101                return new Mime(Mime::BMP);
102            case "gif":
103                return new Mime(Mime::GIF);
104            case "pdf":
105                return new Mime(Mime::PDF);
106            case MarkupRenderer::INSTRUCTION_EXTENSION:
107                // text storage, array memory
108                return new Mime(self::INSTRUCTIONS);
109            case MarkupRenderer::METADATA_EXTENSION:
110                // text storage, array memory
111                return new Mime(self::META);
112            case TemplateEngine::EXTENSION_HBS:
113                // handlebars
114                return new Mime(self::HANDLEBARS);
115            default:
116                $mtypes = getMimeTypes();
117                $mimeString = $mtypes[$extension] ?? null;
118                if ($mimeString === null) {
119                    throw new ExceptionNotFound("No mime was found for the extension ($extension)");
120                } else {
121                    /**
122                     * Delete the special dokuwiki character `!`
123                     * that means that the media should be downloaded
124                     */
125                    if ($mimeString[0] === "!") {
126                        $mimeString = substr($mimeString, 1);
127                    }
128                    return new Mime($mimeString);
129                }
130
131        }
132    }
133
134    public static function getJson(): Mime
135    {
136        try {
137            return Mime::createFromExtension("json");
138        } catch (ExceptionNotFound $e) {
139            throw new ExceptionRuntime("Json is a known extension and should not throw. Error :{$e->getMessage()}");
140        }
141    }
142
143    public static function getHtml(): Mime
144    {
145        try {
146            return Mime::createFromExtension("html");
147        } catch (ExceptionNotFound $e) {
148            throw new ExceptionRuntime("Html is a known extension and should not throw. Error :{$e->getMessage()}");
149        }
150    }
151
152    public static function getText(): Mime
153    {
154        try {
155            return Mime::createFromExtension("txt");
156        } catch (ExceptionNotFound $e) {
157            throw new ExceptionRuntime("Txt is a known extension and should not throw. Error :{$e->getMessage()}");
158        }
159    }
160
161    public static function getBinary(): Mime
162    {
163        return new Mime(self::BINARY_MIME);
164    }
165
166    public static function getXml()
167    {
168        return new Mime(self::XML);
169    }
170
171    public function __toString()
172    {
173        return $this->mime;
174    }
175
176    public function isKnown(): bool
177    {
178
179        if (self::$knownTypes === null) {
180            self::$knownTypes = getMimeTypes();
181        }
182        return array_search($this->mime, self::$knownTypes) !== false;
183
184    }
185
186    public function isTextBased(): bool
187    {
188        if ($this->getFirstPart() === "text") {
189            return true;
190        }
191        if (in_array($this->mime, [self::SVG, self::JSON])) {
192            return true;
193        }
194        return false;
195    }
196
197    private function getFirstPart()
198    {
199        return explode("/", $this->mime)[0];
200    }
201
202    public function isImage(): bool
203    {
204        return substr($this->mime, 0, 5) === 'image';
205    }
206
207    public function toString(): string
208    {
209        return $this->__toString();
210    }
211
212    public function getExtension()
213    {
214
215        $secondPart = explode("/", $this->mime)[1];
216        // case such as "image/svg+xml";
217        return explode("+", $secondPart)[0];
218
219    }
220
221    public function isSupportedRasterImage(): bool
222    {
223        return in_array($this->mime, Mime::RASTER_MIMES);
224    }
225
226
227}
228