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

MapUpdater::loadMapFromFreedesktopFile()   F

Complexity

Conditions 15
Paths 305

Size

Total Lines 66
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 15.0386

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 15
eloc 36
c 1
b 0
f 0
nc 305
nop 1
dl 0
loc 66
rs 3.7708
ccs 34
cts 36
cp 0.9444
crap 15.0386

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
        $aliases = [];
124
125 3
        foreach ($xml as $node) {
126 2
            $exts = [];
127 2
            foreach ($node->glob as $glob) {
128 2
                $pattern = (string) $glob['pattern'];
129 2
                if ('*' != $pattern[0] || '.' != $pattern[1]) {
130 2
                    continue;
131
                }
132 2
                $exts[] = substr($pattern, 2);
133
            }
134 2
            if (empty($exts)) {
135 2
                continue;
136
            }
137
138 2
            $type = (string) $node['type'];
139
140
            // Add description.
141 2
            if (isset($node->comment)) {
142 2
                $this->map->addTypeDescription($type, (string) $node->comment[0]);
143
            }
144 2
            if (isset($node->acronym)) {
145 2
                $acronym = (string) $node->acronym;
146 2
                if (isset($node->{'expanded-acronym'})) {
147 2
                    $acronym .= ': ' . (string) $node->{'expanded-acronym'};
148
                }
149 2
                $this->map->addTypeDescription($type, $acronym);
150
            }
151
152
            // Add extensions.
153 2
            foreach ($exts as $ext) {
154 2
                $this->map->addTypeExtensionMapping($type, $ext);
155
            }
156
157
            // All aliases are accumulated and processed at the end of the
158
            // cycle to allow proper consistency checking on the completely
159
            // developed list of types.
160 2
            foreach ($node->alias as $alias) {
161 2
                $aliases[$type][] = (string) $alias['type'];
162
            }
163
        }
164
165
        // Add all the aliases, provide logging of errors.
166 3
        foreach ($aliases as $type => $a) {
167 2
            foreach ($a as $alias) {
168
                try {
169 2
                    $this->map->addTypeAlias($type, $alias);
170 1
                } catch (MappingException $e) {
171 1
                    $errors[] = $e->getMessage();
172
                }
173
            }
174
        }
175 3
        $this->map->sort();
176
177 3
        return $errors;
178
    }
179
180
    /**
181
     * Applies to the map an array of overrides.
182
     *
183
     * @param array<int,array{0: string, 1: array<string>}> $overrides
184
     *   The overrides to be applied.
185
     *
186
     * @return string[]
187
     *   An array of error messages.
188
     */
189 3
    public function applyOverrides(array $overrides): array
190
    {
191 3
        $errors = [];
192
193 3
        foreach ($overrides as $command) {
194
            try {
195 3
                call_user_func_array([$this->map, $command[0]], $command[1]);
196 1
            } catch (MappingException $e) {
197 1
                $errors[] = $e->getMessage();
198
            }
199
        }
200 3
        $this->map->sort();
201
202 3
        return $errors;
203
    }
204
205
    /**
206
     * Updates the map at a destination PHP file.
207
     *
208
     * @return $this
209
     */
210 1
    public function writeMapToPhpClassFile(string $file): MapUpdater
211
    {
212 1
        $content = preg_replace(
213
            '#protected static \$map = (.+?);#s',
214 1
            "protected static \$map = " . preg_replace('/\s+$/m', '', var_export($this->map->getMapArray(), true)) . ";",
215 1
            file_get_contents($file)
216
        );
217 1
        file_put_contents($file, $content);
218 1
        return $this;
219
    }
220
}
221