Passed
Push — master ( 1459b5...2be244 )
by mon
02:42
created

MapUpdater::applyOverrides()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
nc 3
nop 1
dl 0
loc 14
rs 10
c 0
b 0
f 0
ccs 8
cts 8
cp 1
crap 3
1
<?php
2
3
namespace FileEye\MimeMap;
4
5
use FileEye\MimeMap\Map\AbstractMap;
6
7
/**
8
 * Compiles the MIME type to file extension map.
9
 */
10
class MapUpdater
11
{
12
    /**
13
     * The default, empty, base map to use for update.
14
     */
15
    const DEFAULT_BASE_MAP_CLASS = '\FileEye\MimeMap\Map\EmptyMap';
16
17
    /**
18
     * The AbstractMap object to update.
19
     *
20
     * @var AbstractMap
21
     */
22
    protected $map;
23
24
    /**
25
     * Returns the default file with override commands to be executed.
26
     *
27
     * The YAML file provides an array of calls to MapHandler methods to be
28
     * executed sequentially. Each entry indicates the method to be invoked and
29
     * the arguments to be passed in.
30
     *
31
     * @return string
32
     */
33 1
    public static function getDefaultMapBuildFile()
34
    {
35 1
        return __DIR__ . '/../resources/default_map_build.yml';
36
    }
37
38
    /**
39
     * Returns the AbstractMap object being updated.
40
     *
41
     * @return AbstractMap
42
     */
43 8
    public function getMap()
44
    {
45 8
        return $this->map;
46
    }
47
48
    /**
49
     * Sets the AbstractMap object to update.
50
     *
51
     * @param string $map_class
52
     *   The FQCN of the map to be updated.
53
     *
54
     * @return $this
55
     */
56 8
    public function selectBaseMap($map_class)
57
    {
58 8
        $this->map = MapHandler::map($map_class);
59 8
        $this->map->backup();
60 8
        return $this;
61
    }
62
63
    /**
64
     * Loads a new type-to-extension map reading from a file in Apache format.
65
     *
66
     * @param string $source_file
67
     *   The source file. The file must conform to the format in the Apache
68
     *   source code repository file where MIME types and file extensions are
69
     *   associated.
70
     *
71
     * @return string[]
72
     *   An array of error messages.
73
     *
74
     * @throws \RuntimeException
75
     *   If it was not possible to access the file.
76
     */
77 3
    public function loadMapFromApacheFile($source_file)
78
    {
79 3
        $errors = [];
80
81 3
        $lines = @file($source_file);
82 3
        if ($lines === false) {
83
            throw new \RuntimeException("Failed accessing {$source_file}");
84
        }
85 3
        foreach ($lines as $line) {
86 2
            if ($line[0] == '#') {
87 2
                continue;
88
            }
89 2
            $line = preg_replace("#\\s+#", ' ', trim($line));
90 2
            $parts = explode(' ', $line);
91 2
            $type = array_shift($parts);
92 2
            foreach ($parts as $extension) {
93 2
                $this->map->addTypeExtensionMapping($type, $extension);
94
            }
95
        }
96 3
        $this->map->sort();
97
98 3
        return $errors;
99
    }
100
101
    /**
102
     * Loads a new type-to-extension map reading from a Freedesktop.org file.
103
     *
104
     * @param string $source_file
105
     *   The source file. The file must conform to the format in the
106
     *   Freedesktop.org database.
107
     *
108
     * @return string[]
109
     *   An array of error messages.
110
     */
111 3
    public function loadMapFromFreedesktopFile($source_file)
112
    {
113 3
        $errors = [];
114 3
        $xml = simplexml_load_string(file_get_contents($source_file));
115 3
        $aliases = [];
116
117 3
        foreach ($xml as $node) {
118 2
            $exts = [];
119 2
            foreach ($node->glob as $glob) {
120 2
                $pattern = (string) $glob['pattern'];
121 2
                if ('*' != $pattern[0] || '.' != $pattern[1]) {
122 2
                    continue;
123
                }
124 2
                $exts[] = substr($pattern, 2);
125
            }
126 2
            if (empty($exts)) {
127 2
                continue;
128
            }
129
130 2
            $type = (string) $node['type'];
131
132
            // Add description.
133 2
            if (isset($node->comment)) {
134 2
                $this->map->addTypeDescription($type, (string) $node->comment[0]);
135
            }
136 2
            if (isset($node->acronym)) {
137 2
                $acronym = (string) $node->acronym;
138 2
                if (isset($node->{'expanded-acronym'})) {
139 2
                    $acronym .= ': ' . (string) $node->{'expanded-acronym'};
140
                }
141 2
                $this->map->addTypeDescription($type, $acronym);
142
            }
143
144
            // Add extensions.
145 2
            foreach ($exts as $ext) {
146 2
                $this->map->addTypeExtensionMapping($type, $ext);
147
            }
148
149
            // All aliases are accumulated and processed at the end of the
150
            // cycle to allow proper consistency checking on the completely
151
            // developed list of types.
152 2
            foreach ($node->alias as $alias) {
153 2
                $aliases[$type][] = (string) $alias['type'];
154
            }
155
        }
156
157
        // Add all the aliases, provide logging of errors.
158 3
        foreach ($aliases as $type => $a) {
159 2
            foreach ($a as $alias) {
160
                try {
161 2
                    $this->map->addTypeAlias($type, $alias);
162 1
                } catch (MappingException $e) {
163 2
                    $errors[] = $e->getMessage();
164
                }
165
            }
166
        }
167 3
        $this->map->sort();
168
169 3
        return $errors;
170
    }
171
172
    /**
173
     * Applies to the map an array of overrides.
174
     *
175
     * @param array $overrides
176
     *   The overrides to be applied.
177
     *
178
     * @return string[]
179
     *   An array of error messages.
180
     */
181 3
    public function applyOverrides(array $overrides)
182
    {
183 3
        $errors = [];
184
185 3
        foreach ($overrides as $command) {
186
            try {
187 3
                call_user_func_array([$this->map, $command[0]], $command[1]);
188 1
            } catch (MappingException $e) {
189 3
                $errors[] = $e->getMessage();
190
            }
191
        }
192 3
        $this->map->sort();
193
194 3
        return $errors;
195
    }
196
197
    /**
198
     * Updates the map at a destination PHP file.
199
     *
200
     * @return $this
201
     */
202 1
    public function writeMapToPhpClassFile($file)
203
    {
204 1
        $content = preg_replace(
205 1
            '#protected static \$map = (.+?);#s',
206 1
            "protected static \$map = " . var_export($this->map->getMapArray(), true) . ";",
207 1
            file_get_contents($file)
208
        );
209 1
        file_put_contents($file, $content);
210 1
        return $this;
211
    }
212
}
213