Passed
Push — develop ( 728be8...044541 )
by Eric
13:09 queued 45s
created

Builder::getMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Mimey - PHP package for converting file extensions to MIME types and vice versa.
7
 *
8
 * @author    Eric Sizemore <[email protected]>
9
 * @version   2.0.0
10
 * @copyright (C) 2023-2024 Eric Sizemore
11
 * @license   The MIT License (MIT)
12
 *
13
 * Copyright (C) 2023-2024 Eric Sizemore<https://www.secondversion.com/>.
14
 *
15
 * Permission is hereby granted, free of charge, to any person obtaining a copy
16
 * of this software and associated documentation files (the "Software"), to
17
 * deal in the Software without restriction, including without limitation the
18
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
19
 * sell copies of the Software, and to permit persons to whom the Software is
20
 * furnished to do so, subject to the following conditions:
21
 *
22
 * The above copyright notice and this permission notice shall be included in
23
 * all copies or substantial portions of the Software.
24
 *
25
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31
 * THE SOFTWARE.
32
 */
33
34
/**
35
 * Esi\Mimey is a fork of Elephox\Mimey (https://github.com/elephox-dev/mimey) which is:
36
 *     Copyright (c) 2022 Ricardo Boss
37
 * Elephox\Mimey is a fork of ralouphie/mimey (https://github.com/ralouphie/mimey) which is:
38
 *     Copyright (c) 2016 Ralph Khattar
39
 */
40
41
namespace Esi\Mimey\Mapping;
42
43
// Classes
44
use JetBrains\PhpStorm\Pure;
45
46
// Exceptions
47
use JsonException;
48
use RuntimeException;
49
use Throwable;
50
51
// Functions & constants
52
use function array_unshift;
53
use function array_unique;
54
use function json_encode;
55
use function file_put_contents;
56
use function dirname;
57
use function file_get_contents;
58
use function json_decode;
59
60
use const JSON_THROW_ON_ERROR;
61
use const JSON_PRETTY_PRINT;
62
63
/**
64
 * Class for converting MIME types to file extensions and vice versa.
65
 *
66
 * This psalm-type looks gnarly, but it covers just about everything.
67
 *
68
 * @psalm-type MimeTypeMap = array{
69
 *    mimes: array<
70
 *        non-empty-string, list<non-empty-string>
71
 *    >|non-empty-array<
72
 *        string, array<int<0, max>, string>
73
 *    >,
74
 *    extensions: array<
75
 *        non-empty-string, list<non-empty-string>
76
 *    >|non-empty-array<
77
 *        string, array<int<0, max>, string>
78
 *    >|array<
79
 *        string, array<int<0, max>, string>
80
 *    >
81
 * }
82
 */
83
class Builder
84
{
85
    /**
86
     * Create a new mapping builder.
87
     *
88
     * @param MimeTypeMap $mapping An associative array containing two entries. See `MimeTypes` constructor for details.
1 ignored issue
show
Bug introduced by
The type Esi\Mimey\Mapping\MimeTypeMap was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
89
     */
90 5
    private function __construct(
91
        /**
92
         * The Mapping Array
93
         */
94
        protected array $mapping
95 5
    ) {}
96
97
    /**
98
     * Add a conversion.
99
     *
100
     * @param string $mime              The MIME type.
101
     * @param string $extension         The extension.
102
     * @param bool   $prependExtension  Whether this should be the preferred conversion for MIME type to extension.
103
     * @param bool   $prependMime       Whether this should be the preferred conversion for extension to MIME type.
104
     */
105 5
    public function add(string $mime, string $extension, bool $prependExtension = true, bool $prependMime = true): void
106
    {
107 5
        $existingExtensions = $this->mapping['extensions'][$mime] ?? [];
108 5
        $existingMimes      = $this->mapping['mimes'][$extension] ?? [];
109
110 5
        if ($prependExtension) {
111 5
            array_unshift($existingExtensions, $extension);
112
        } else {
113 1
            $existingExtensions[] = $extension;
114
        }
115
116 5
        if ($prependMime) {
117 5
            array_unshift($existingMimes, $mime);
118
        } else {
119 1
            $existingMimes[] = $mime;
120
        }
121
122 5
        $this->mapping['extensions'][$mime] = array_unique($existingExtensions);
123 5
        $this->mapping['mimes'][$extension] = array_unique($existingMimes);
124
    }
125
126
    /**
127
     * Retrieves the current mapping array.
128
     *
129
     * @return MimeTypeMap The mapping.
130
     */
131 5
    public function getMapping(): array
132
    {
133 5
        return $this->mapping;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $this->mapping returns the type array which is incompatible with the documented return type Esi\Mimey\Mapping\MimeTypeMap.
Loading history...
134
    }
135
136
    /**
137
     * Compile the current mapping to PHP.
138
     *
139
     * @param  bool    $pretty  Whether to pretty print the output.
140
     * @return string           The compiled PHP code to save to a file.
141
     *
142
     * @throws JsonException
143
     */
144 1
    public function compile(bool $pretty = false): string
145
    {
146 1
        $mapping = $this->getMapping();
147
148 1
        return json_encode($mapping, flags: JSON_THROW_ON_ERROR | ($pretty ? JSON_PRETTY_PRINT : 0));
149
    }
150
151
    /**
152
     * Save the current mapping to a file.
153
     *
154
     * @param  string     $file     The file to save to.
155
     * @param  int        $flags    Flags for `file_put_contents`.
156
     * @param  resource   $context  Context for `file_put_contents`.
157
     * @return false|int            The number of bytes that were written to the file, or false on failure.
158
     *
159
     * @throws JsonException
160
     */
161 1
    public function save(string $file, int $flags = 0, mixed $context = null): false | int
162
    {
163 1
        return file_put_contents($file, $this->compile(), $flags, $context);
164
    }
165
166
    /**
167
     * Create a new mapping builder based on the built-in types.
168
     *
169
     * @return  Builder  A mapping builder with built-in types loaded.
170
     */
171 1
    public static function create(): Builder
172
    {
173 1
        return self::load(dirname(__DIR__, 2) . '/dist/mime.types.min.json');
174
    }
175
176
    /**
177
     * Create a new mapping builder based on types from a file.
178
     *
179
     * @param  string   $file  The compiled PHP file to load.
180
     * @return Builder         A mapping builder with types loaded from a file.
181
     *
182
     * @throws RuntimeException
183
     */
184 3
    public static function load(string $file): Builder
185
    {
186
        try {
187
            /** @var string $json **/
188 3
            $json = file_get_contents($file);
189
            /** @var MimeTypeMap $json **/
190 3
            $json = json_decode(/** @scrutinizer ignore-type */ $json, true, flags: JSON_THROW_ON_ERROR);
191
192 2
            return new self($json);
1 ignored issue
show
Bug introduced by
$json of type Esi\Mimey\Mapping\MimeTypeMap is incompatible with the type array expected by parameter $mapping of Esi\Mimey\Mapping\Builder::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

192
            return new self(/** @scrutinizer ignore-type */ $json);
Loading history...
193 1
        } catch (Throwable $e) {
194 1
            throw new RuntimeException('Unable to parse built-in types at ' . $file, 0, $e);
195
        }
196
    }
197
198
    /**
199
     * Create a new mapping builder that has no types defined.
200
     *
201
     * @return  Builder  A mapping builder with no types defined.
202
     */
203 4
    #[Pure]
204
    public static function blank(): Builder
205
    {
206 4
        return new self(['mimes' => [], 'extensions' => []]);
207
    }
208
}
209