Passed
Push — master ( ec8530...db772b )
by Stéphane
23:29
created

DauxHelper::getTheme()   C

Complexity

Conditions 14
Paths 76

Size

Total Lines 82
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 210

Importance

Changes 0
Metric Value
cc 14
eloc 46
nc 76
nop 2
dl 0
loc 82
ccs 0
cts 38
cp 0
crap 210
rs 6.2666
c 0
b 0
f 0

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 namespace Todaymade\Daux;
2
3
use Todaymade\Daux\Exception\LinkNotFoundException;
4
use Todaymade\Daux\Tree\Builder;
5
use Todaymade\Daux\Tree\Directory;
6
use Todaymade\Daux\Tree\Entry;
7
8
class DauxHelper
9
{
10
    /**
11
     * Set a new base_url for the configuration.
12
     *
13
     * @param string $base_url
14
     */
15
    public static function rebaseConfiguration(Config $config, $base_url)
16
    {
17
        // Avoid changing the url if it is already correct
18
        if ($config->getBaseUrl() == $base_url && !empty($config->getTheme())) {
19
            return;
20
        }
21
22
        // Change base url for all links on the pages
23
        $config['base_url'] = $base_url;
24
        $config['theme'] = static::getTheme($config, $base_url);
25
        $config['image'] = str_replace('<base_url>', $base_url, $config->getImage());
26
    }
27
28
    /**
29
     * @param string $current_url
30
     *
31
     * @return array
32
     */
33
    protected static function getTheme(Config $config, $current_url)
34
    {
35
        static $cache = [];
36
37
        $htmlTheme = $config->getHTML()->getTheme();
38
39
        $theme_folder = $config->getThemesPath() . DIRECTORY_SEPARATOR . $htmlTheme;
40
        $theme_url = $config->getBaseUrl() . 'themes/' . $htmlTheme . '/';
41
42
        $cache_key = "$current_url-$htmlTheme";
43
        if (array_key_exists($cache_key, $cache)) {
44
            return $cache[$cache_key];
45
        }
46
47
        $theme = [];
48
        if (is_file($theme_folder . DIRECTORY_SEPARATOR . 'config.json')) {
49
            $theme = json_decode(file_get_contents($theme_folder . DIRECTORY_SEPARATOR . 'config.json'), true);
50
            if (!$theme) {
51
                $theme = [];
52
            }
53
        }
54
55
        // Default parameters for theme
56
        $theme += [
57
            'name' => $htmlTheme,
58
            'css' => [],
59
            'js' => [],
60
            'fonts' => [],
61
            'favicon' => '<base_url>themes/daux/img/favicon.png',
62
            'templates' => $theme_folder . DIRECTORY_SEPARATOR . 'templates',
63
            'variants' => [],
64
            'with_search' => $config->getHTML()->hasSearch()
65
        ];
66
67
        if ($config->getHTML()->hasThemeVariant()) {
68
            $variant = $config->getHTML()->getThemeVariant();
69
            if (!array_key_exists($variant, $theme['variants'])) {
70
                throw new Exception("Variant '$variant' not found for theme '$theme[name]'");
71
            }
72
73
            // These will be replaced
74
            foreach (['templates', 'favicon'] as $element) {
75
                if (array_key_exists($element, $theme['variants'][$variant])) {
76
                    $theme[$element] = $theme['variants'][$variant][$element];
77
                }
78
            }
79
80
            // These will be merged
81
            foreach (['css', 'js', 'fonts'] as $element) {
82
                if (array_key_exists($element, $theme['variants'][$variant])) {
83
                    $theme[$element] = array_merge($theme[$element], $theme['variants'][$variant][$element]);
84
                }
85
            }
86
        }
87
88
        if ($theme['with_search']) {
89
            $theme['css'][] = '<base_url>daux_libraries/search.css';
90
        }
91
92
        if (is_file($config->getDocumentationDirectory() . DIRECTORY_SEPARATOR . 'style.css')) {
93
            $theme['css'][]= '<base_url>style.css';
94
        }
95
96
        $substitutions = [
97
            '<local_base>' => $config->getLocalBase(),
98
            '<base_url>' => $current_url,
99
            '<theme_url>' => $theme_url,
100
        ];
101
102
        // Substitute some placeholders
103
        $theme['templates'] = strtr($theme['templates'], $substitutions);
104
        $theme['favicon'] = utf8_encode(strtr($theme['favicon'], $substitutions));
105
106
        foreach (['css', 'js', 'fonts'] as $element) {
107
            foreach ($theme[$element] as $key => $value) {
108
                $theme[$element][$key] = utf8_encode(strtr($value, $substitutions));
109
            }
110
        }
111
112
        $cache[$cache_key] = $theme;
113
114
        return $theme;
115
    }
116
117
    /**
118
     * Remove all '/./' and '/../' in a path, without actually checking the path.
119
     *
120
     * @param string $path
121
     *
122
     * @return string
123
     */
124
    public static function getCleanPath($path)
125
    {
126
        $path = str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $path);
127
        $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
128
        $absolutes = [];
129
        foreach ($parts as $part) {
130
            if ('.' == $part) {
131
                continue;
132 16
            }
133
            if ('..' == $part) {
134 16
                array_pop($absolutes);
135
            } else {
136 16
                $absolutes[] = $part;
137 16
            }
138
        }
139 16
140
        return implode(DIRECTORY_SEPARATOR, $absolutes);
141
    }
142
143
    /**
144
     * Get the possible output file names for a source file.
145
     *
146
     * @param string $part
147
     *
148
     * @return string[]
149 17
     */
150
    public static function getFilenames(Config $config, $part)
151 17
    {
152 17
        $extensions = implode('|', array_map('preg_quote', $config->getValidContentExtensions())) . '|html';
153
154
        $raw = preg_replace('/(.*)?\\.(' . $extensions . ')$/', '$1', $part);
155 17
        $raw = Builder::removeSortingInformations($raw);
156 1
157
        return ["$raw.html", $raw];
158
    }
159
160 17
    /**
161 3
     * Locate a file in the tree. Returns the file if found or false.
162
     *
163
     * @param Directory $tree
164 17
     * @param string $request
165 2
     *
166 2
     * @return false|Tree\Content|Tree\Raw
167
     */
168
    public static function getFile($tree, $request)
169
    {
170
        $request = explode('/', $request);
171
        foreach ($request as $node) {
172 17
            // If the element we're in currently is not a
173 17
            // directory, we failed to find the requested file
174 17
            if (!$tree instanceof Directory) {
175
                return false;
176
            }
177
178 12
            // Some relative paths may start with ./
179 12
            if ($node == '.') {
180
                continue;
181
            }
182
183
            if ($node == '..') {
184
                $tree = $tree->getParent();
185
186
                continue;
187 12
            }
188 12
189 12
            // if the node exists in the current request tree,
190 12
            // change the $tree variable to reference the new
191
            // node and proceed to the next url part
192
            if (isset($tree->getEntries()[$node])) {
193
                $tree = $tree->getEntries()[$node];
194
195
                continue;
196
            }
197 3
198 3
            // We try a second time by decoding the url
199
            $node = DauxHelper::slug(urldecode($node));
200
            if (isset($tree->getEntries()[$node])) {
201
                $tree = $tree->getEntries()[$node];
202
203
                continue;
204
            }
205 17
206 17
            // if the node doesn't exist, we can try
207
            // two variants of the requested file:
208
            // with and w/o the .html extension
209
            foreach (static::getFilenames($tree->getConfig(), $node) as $filename) {
210
                if (isset($tree->getEntries()[$filename])) {
211
                    $tree = $tree->getEntries()[$filename];
212
213
                    continue 2;
214
                }
215
            }
216
217
            // At this stage, we're in a directory, but no
218
            // sub-item matches, so the current node must
219
            // be an index page or we failed
220
            if ($node !== 'index' && $node !== 'index.html') {
221
                return false;
222
            }
223
224 34
            return $tree->getIndexPage();
225
        }
226
227 34
        // If the entry we found is not a directory, we're done
228 34
        if (!$tree instanceof Directory) {
229
            return $tree;
230
        }
231 34
232
        if ($index = $tree->getIndexPage()) {
233
            return $index;
234 34
        }
235
236 34
        return false;
237
    }
238 34
239
    /**
240
     * Generate a URL friendly "slug" from a given string.
241
     *
242 34
     * Taken from Stringy
243
     *
244
     * @param  string $title
245 34
     *
246
     * @return string
247 34
     */
248
    public static function slug($title)
249
    {
250
        // Convert to ASCII
251
        if (function_exists('transliterator_transliterate')) {
252
            $title = transliterator_transliterate('Any-Latin; NFD; [:Nonspacing Mark:] Remove; NFC;', $title);
253
        }
254
255 12
        $title = iconv('utf-8', 'ASCII//TRANSLIT//IGNORE', $title);
256
257
        // Remove unsupported characters
258 12
        $title = preg_replace('/[^\x20-\x7E]/u', '', $title);
259 12
260 12
        $separator = '_';
261 12
        // Convert all dashes into underscores
262
        $title = preg_replace('![' . preg_quote('-') . ']+!u', $separator, $title);
263 12
264 12
        // Remove all characters that are not valid in a URL:
265 12
        // $-_.+!*'(), separator, letters, numbers, or whitespace.
266
        $title = preg_replace('![^-' . preg_quote($separator) . '\!\'\(\),\.\+\*\$\pL\pN\s]+!u', '', $title);
267 12
268
        // Replace all separator characters and whitespace by a single separator
269 12
        $title = preg_replace('![' . preg_quote($separator) . '\s]+!u', $separator, $title);
270
271 8
        return trim($title, $separator);
272
    }
273
274 12
    /**
275 12
     * @param string $from
276
     * @param string $to
277 4
     *
278 4
     * @return string
279 4
     */
280
    public static function getRelativePath($from, $to)
281
    {
282
        // some compatibility fixes for Windows paths
283
        $from = is_dir($from) ? rtrim($from, '\/') . '/' : $from;
284
        $to = is_dir($to) ? rtrim($to, '\/') . '/' : $to;
285
        $from = str_replace('\\', '/', $from);
286 12
        $to = str_replace('\\', '/', $to);
287
288
        $from = explode('/', $from);
289 55
        $to = explode('/', $to);
290
        $relPath = $to;
291 55
292
        foreach ($from as $depth => $dir) {
293
            // find first non-matching dir
294
            if ($dir === $to[$depth]) {
295
                // ignore this directory
296 55
                array_shift($relPath);
297
            } else {
298
                // get number of remaining dirs to $from
299
                $remaining = count($from) - $depth;
300
                if ($remaining > 1) {
301
                    // add traversals up to first matching dir
302 55
                    $padLength = (count($relPath) + $remaining - 1) * -1;
303
                    $relPath = array_pad($relPath, $padLength, '..');
304
305 55
                    break;
306
                }
307
                //$relPath[0] = './' . $relPath[0];
308 55
            }
309
        }
310 55
311 55
        return implode('/', $relPath);
312
    }
313
314
    public static function isAbsolutePath($path)
315
    {
316 55
        if (!is_string($path)) {
317
            $mess = sprintf('String expected but was given %s', gettype($path));
318
319 55
            throw new \InvalidArgumentException($mess);
320 55
        }
321
322
        if (!ctype_print($path)) {
323
            $mess = 'Path can NOT have non-printable characters or be empty';
324 55
325
            throw new \DomainException($mess);
326
        }
327 55
328 55
        // Optional wrapper(s).
329
        $regExp = '%^(?<wrappers>(?:[[:print:]]{2,}://)*)';
330
331
        // Optional root prefix.
332
        $regExp .= '(?<root>(?:[[:alpha:]]:/|/)?)';
333
334
        // Actual path.
335
        $regExp .= '(?<path>(?:[[:print:]]*))$%';
336
337 12
        $parts = [];
338
        if (!preg_match($regExp, $path, $parts)) {
339 12
            $mess = sprintf('Path is NOT valid, was given %s', $path);
340
341
            throw new \DomainException($mess);
342
        }
343
344 12
        return '' !== $parts['root'];
345 4
    }
346
347 4
    public static function getAbsolutePath($path)
348 4
    {
349
        if (DauxHelper::isAbsolutePath($path)) {
350
            return $path;
351 1
        }
352
353
        return getcwd() . '/' . $path;
354
    }
355
356 9
    public static function is($path, $type)
357 8
    {
358
        return ($type == 'dir') ? is_dir($path) : file_exists($path);
359
    }
360
361
    /**
362 3
     * @param Config $config
363
     * @param string $url
364
     *
365
     * @throws LinkNotFoundException
366 3
     *
367
     * @return Entry
368
     */
369 19
    public static function resolveInternalFile($config, $url)
370
    {
371 19
        $triedAbsolute = false;
372
373
        // Legacy absolute paths could start with
374 14
        // "!" In this case we will try to find
375
        // the file starting at the root
376 14
        if ($url[0] == '!' || $url[0] == '/') {
377
            $url = ltrim($url, '!/');
378
379
            if ($file = DauxHelper::getFile($config->getTree(), $url)) {
380
                return $file;
381
            }
382
383
            $triedAbsolute = true;
384
        }
385
386
        // Seems it's not an absolute path or not found,
387
        // so we'll continue with the current folder
388
        if ($file = DauxHelper::getFile($config->getCurrentPage()->getParent(), $url)) {
389
            return $file;
390
        }
391
392
        // If we didn't already try it, we'll
393
        // do a pass starting at the root
394
        if (!$triedAbsolute && $file = DauxHelper::getFile($config->getTree(), $url)) {
395
            return $file;
396
        }
397
398
        throw new LinkNotFoundException("Could not locate file '$url'");
399
    }
400
401
    public static function isValidUrl($url)
402
    {
403
        return !empty($url) && $url[0] != '#';
404
    }
405
406
    public static function isExternalUrl($url)
407
    {
408
        return preg_match('#^(?:[a-z]+:)?//|^mailto:#', $url);
409
    }
410
}
411