Test Failed
Pull Request — master (#58)
by mon
01:58
created

MapUpdater::applyOverrides()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 14
ccs 0
cts 8
cp 0
crap 12
rs 10
1
<?php
2
3
namespace FileEye\MimeMap;
4
5
use FileEye\MimeMap\Map\EmptyMap;
6
use FileEye\MimeMap\Map\MimeMapInterface;
7
8
/**
9
 * Compiles the MIME type to file extension map.
10
 */
11
class MapUpdater
12
{
13
    /**
14
     * The default, empty, base map to use for update.
15
     */
16
    const DEFAULT_BASE_MAP_CLASS = EmptyMap::class;
17
18
    /**
19
     * The map object to update.
20
     *
21
     * @var MimeMapInterface
22
     */
23
    protected $map;
24
25
    /**
26
     * Returns the default file with override commands to be executed.
27
     *
28
     * The YAML file provides an array of calls to MapHandler methods to be
29
     * executed sequentially. Each entry indicates the method to be invoked and
30
     * the arguments to be passed in.
31
     *
32
     * @return string
33
     */
34
    public static function getDefaultMapBuildFile(): string
35
    {
36
        return __DIR__ . '/../resources/default_map_build.yml';
37
    }
38
39
    /**
40
     * Returns the map object being updated.
41
     *
42
     * @return MapInterface
43
     */
44 8
    public function getMap(): MapInterface
0 ignored issues
show
Bug introduced by
The type FileEye\MimeMap\MapInterface 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...
45
    {
46 8
        return $this->map;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->map returns the type FileEye\MimeMap\Map\MimeMapInterface which is incompatible with the type-hinted return FileEye\MimeMap\MapInterface.
Loading history...
47
    }
48
49
    /**
50
     * Sets the map object to update.
51
     *
52
     * @param string $map_class
53
     *   The FQCN of the map to be updated.
54
     *
55
     * @return $this
56
     */
57 8
    public function selectBaseMap(string $map_class): MapUpdater
58
    {
59 8
        $this->map = MapHandler::map($map_class);
60 8
        $this->map->backup();
0 ignored issues
show
Bug introduced by
The method backup() does not exist on FileEye\MimeMap\Map\MimeMapInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to FileEye\MimeMap\Map\MimeMapInterface. ( Ignorable by Annotation )

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

60
        $this->map->/** @scrutinizer ignore-call */ 
61
                    backup();
Loading history...
61 8
        return $this;
62
    }
63
64
    /**
65
     * Loads a new type-to-extension map reading from a file in Apache format.
66
     *
67
     * @param string $source_file
68
     *   The source file. The file must conform to the format in the Apache
69
     *   source code repository file where MIME types and file extensions are
70
     *   associated.
71
     *
72
     * @return string[]
73
     *   An array of error messages.
74
     *
75
     * @throws \RuntimeException
76
     *   If it was not possible to access the file.
77
     */
78
    public function loadMapFromApacheFile(string $source_file): array
79
    {
80
        $errors = [];
81
82
        $lines = @file($source_file);
83
        if ($lines === false) {
84
            throw new \RuntimeException("Failed accessing {$source_file}");
85
        }
86
        foreach ($lines as $line) {
87
            if ($line[0] == '#') {
88
                continue;
89
            }
90
            $line = preg_replace("#\\s+#", ' ', trim($line));
91
            $parts = explode(' ', $line);
92
            $type = array_shift($parts);
93
            foreach ($parts as $extension) {
94
                $this->map->addTypeExtensionMapping($type, $extension);
95
            }
96
        }
97
        $this->map->sort();
0 ignored issues
show
Bug introduced by
The method sort() does not exist on FileEye\MimeMap\Map\MimeMapInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to FileEye\MimeMap\Map\MimeMapInterface. ( Ignorable by Annotation )

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

97
        $this->map->/** @scrutinizer ignore-call */ 
98
                    sort();
Loading history...
98
99
        return $errors;
100
    }
101
102
    /**
103
     * Loads a new type-to-extension map reading from a Freedesktop.org file.
104
     *
105
     * @param string $source_file
106
     *   The source file. The file must conform to the format in the
107
     *   Freedesktop.org database.
108
     *
109
     * @return string[]
110
     *   An array of error messages.
111
     */
112
    public function loadMapFromFreedesktopFile(string $source_file): array
113
    {
114
        $errors = [];
115
        $xml = simplexml_load_string(file_get_contents($source_file));
116
        $aliases = [];
117
118
        foreach ($xml as $node) {
119
            $exts = [];
120
            foreach ($node->glob as $glob) {
121
                $pattern = (string) $glob['pattern'];
122
                if ('*' != $pattern[0] || '.' != $pattern[1]) {
123
                    continue;
124
                }
125
                $exts[] = substr($pattern, 2);
126
            }
127
            if (empty($exts)) {
128
                continue;
129
            }
130
131
            $type = (string) $node['type'];
132
133
            // Add description.
134
            if (isset($node->comment)) {
135
                $this->map->addTypeDescription($type, (string) $node->comment[0]);
136
            }
137
            if (isset($node->acronym)) {
138
                $acronym = (string) $node->acronym;
139
                if (isset($node->{'expanded-acronym'})) {
140
                    $acronym .= ': ' . (string) $node->{'expanded-acronym'};
141
                }
142
                $this->map->addTypeDescription($type, $acronym);
143
            }
144
145
            // Add extensions.
146
            foreach ($exts as $ext) {
147
                $this->map->addTypeExtensionMapping($type, $ext);
148
            }
149
150
            // All aliases are accumulated and processed at the end of the
151
            // cycle to allow proper consistency checking on the completely
152
            // developed list of types.
153
            foreach ($node->alias as $alias) {
154
                $aliases[$type][] = (string) $alias['type'];
155
            }
156
        }
157
158
        // Add all the aliases, provide logging of errors.
159
        foreach ($aliases as $type => $a) {
160
            foreach ($a as $alias) {
161
                try {
162
                    $this->map->addTypeAlias($type, $alias);
163
                } catch (MappingException $e) {
164
                    $errors[] = $e->getMessage();
165
                }
166
            }
167
        }
168
        $this->map->sort();
169
170
        return $errors;
171
    }
172
173
    /**
174
     * Applies to the map an array of overrides.
175
     *
176
     * @param array $overrides
177
     *   The overrides to be applied.
178
     *
179
     * @return string[]
180
     *   An array of error messages.
181
     */
182
    public function applyOverrides(array $overrides): array
183
    {
184
        $errors = [];
185
186
        foreach ($overrides as $command) {
187
            try {
188
                call_user_func_array([$this->map, $command[0]], $command[1]);
189
            } catch (MappingException $e) {
190
                $errors[] = $e->getMessage();
191
            }
192
        }
193
        $this->map->sort();
194
195
        return $errors;
196
    }
197
198
    /**
199
     * Updates the map at a destination PHP file.
200
     *
201
     * @return $this
202
     */
203
    public function writeMapToPhpClassFile(string $file): MapUpdater
204
    {
205
        $content = preg_replace(
206
            '#protected static \$map = (.+?);#s',
207
            "protected static \$map = " . preg_replace('/\s+$/m', '', var_export($this->map->getMapArray(), true)) . ";",
0 ignored issues
show
Bug introduced by
The method getMapArray() does not exist on FileEye\MimeMap\Map\MimeMapInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to FileEye\MimeMap\Map\MimeMapInterface. ( Ignorable by Annotation )

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

207
            "protected static \$map = " . preg_replace('/\s+$/m', '', var_export($this->map->/** @scrutinizer ignore-call */ getMapArray(), true)) . ";",
Loading history...
208
            file_get_contents($file)
209
        );
210
        file_put_contents($file, $content);
211
        return $this;
212
    }
213
}
214