Passed
Push — master ( 04dc1c...221271 )
by mon
02:09
created

MapUpdater::loadMapFromFreedesktopFile()   F

Complexity

Conditions 16
Paths 306

Size

Total Lines 71
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 16.2764

Importance

Changes 0
Metric Value
cc 16
eloc 39
c 0
b 0
f 0
nc 306
nop 1
dl 0
loc 71
rs 3.4083
ccs 35
cts 39
cp 0.8974
crap 16.2764

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 1
    public static function getDefaultMapBuildFile(): string
35
    {
36 1
        return __DIR__ . '/../resources/default_map_build.yml';
37
    }
38
39
    /**
40
     * Returns the map object being updated.
41
     *
42
     * @return MimeMapInterface
43
     */
44 8
    public function getMap(): MimeMapInterface
45
    {
46 8
        return $this->map;
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();
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 3
    public function loadMapFromApacheFile(string $source_file): array
79
    {
80 3
        $errors = [];
81
82 3
        $lines = @file($source_file);
83 3
        if ($lines === false) {
84
            throw new \RuntimeException("Failed accessing {$source_file}");
85
        }
86 3
        foreach ($lines as $line) {
87 2
            if ($line[0] == '#') {
88 2
                continue;
89
            }
90 2
            $line = preg_replace("#\\s+#", ' ', trim($line));
91 2
            $parts = explode(' ', $line);
92 2
            $type = array_shift($parts);
93 2
            foreach ($parts as $extension) {
94 2
                $this->map->addTypeExtensionMapping($type, $extension);
95
            }
96
        }
97 3
        $this->map->sort();
98
99 3
        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 3
    public function loadMapFromFreedesktopFile(string $source_file): array
113
    {
114 3
        $errors = [];
115
116 3
        $contents = file_get_contents($source_file);
117 3
        if ($contents === false) {
118
            $errors[] = 'Failed loading file ' . $source_file;
119
            return $errors;
120
        }
121
122 3
        $xml = simplexml_load_string($contents);
123 3
        if ($xml === false) {
124
            $errors[] = 'Malformed XML in file ' . $source_file;
125
            return $errors;
126
        }
127
128 3
        $aliases = [];
129
130 3
        foreach ($xml as $node) {
131 2
            $exts = [];
132 2
            foreach ($node->glob as $glob) {
133 2
                $pattern = (string) $glob['pattern'];
134 2
                if ('*' != $pattern[0] || '.' != $pattern[1]) {
135 2
                    continue;
136
                }
137 2
                $exts[] = substr($pattern, 2);
138
            }
139 2
            if (empty($exts)) {
140 2
                continue;
141
            }
142
143 2
            $type = (string) $node['type'];
144
145
            // Add description.
146 2
            if (isset($node->comment)) {
147 2
                $this->map->addTypeDescription($type, (string) $node->comment[0]);
148
            }
149 2
            if (isset($node->acronym)) {
150 2
                $acronym = (string) $node->acronym;
151 2
                if (isset($node->{'expanded-acronym'})) {
152 2
                    $acronym .= ': ' . (string) $node->{'expanded-acronym'};
153
                }
154 2
                $this->map->addTypeDescription($type, $acronym);
155
            }
156
157
            // Add extensions.
158 2
            foreach ($exts as $ext) {
159 2
                $this->map->addTypeExtensionMapping($type, $ext);
160
            }
161
162
            // All aliases are accumulated and processed at the end of the
163
            // cycle to allow proper consistency checking on the completely
164
            // developed list of types.
165 2
            foreach ($node->alias as $alias) {
166 2
                $aliases[$type][] = (string) $alias['type'];
167
            }
168
        }
169
170
        // Add all the aliases, provide logging of errors.
171 3
        foreach ($aliases as $type => $a) {
172 2
            foreach ($a as $alias) {
173
                try {
174 2
                    $this->map->addTypeAlias($type, $alias);
175 1
                } catch (MappingException $e) {
176 1
                    $errors[] = $e->getMessage();
177
                }
178
            }
179
        }
180 3
        $this->map->sort();
181
182 3
        return $errors;
183
    }
184
185
    /**
186
     * Applies to the map an array of overrides.
187
     *
188
     * @param array<int,array{0: string, 1: array<string>}> $overrides
189
     *   The overrides to be applied.
190
     *
191
     * @return string[]
192
     *   An array of error messages.
193
     */
194 3
    public function applyOverrides(array $overrides): array
195
    {
196 3
        $errors = [];
197
198 3
        foreach ($overrides as $command) {
199
            try {
200 3
                $callable = [$this->map, $command[0]];
201 3
                assert(is_callable($callable));
202 3
                call_user_func_array($callable, $command[1]);
203 1
            } catch (MappingException $e) {
204 1
                $errors[] = $e->getMessage();
205
            }
206
        }
207 3
        $this->map->sort();
208
209 3
        return $errors;
210
    }
211
212
    /**
213
     * Updates the map at a destination PHP file.
214
     *
215
     * @return $this
216
     */
217 1
    public function writeMapToPhpClassFile(string $file): MapUpdater
218
    {
219 1
        $content = file_get_contents($file);
220 1
        if ($content === false) {
221
            throw new \RuntimeException('Failed loading file ' . $file);
222
        }
223
224 1
        $newContent = preg_replace(
225
            '#protected static \$map = (.+?);#s',
226 1
            "protected static \$map = " . preg_replace('/\s+$/m', '', var_export($this->map->getMapArray(), true)) . ";",
227
            $content
228
        );
229 1
        file_put_contents($file, $newContent);
230
        
231 1
        return $this;
232
    }
233
}
234