Passed
Push — master ( 48c4ea...d64961 )
by Tom
02:50
created

LibFsPath::normalize()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 16
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 16
ccs 8
cts 8
cp 1
crap 3
rs 10
1
<?php
2
3
/* this file is part of pipelines */
4
5
namespace Ktomk\Pipelines;
6
7
/**
8
 * Class LibFsPath - path utility functions
9
 *
10
 * @package Ktomk\Pipelines
11
 */
12
class LibFsPath
13
{
14
    /**
15
     * check if path is absolute
16
     *
17
     * @param string $path
18
     *
19
     * @return bool
20
     */
21 8
    public static function isAbsolute($path)
22
    {
23
        // TODO: a variant with PHP stream wrapper prefix support
24
        /* @see LibFsStream::isUri */
25
26 8
        $count = strspn($path, '/', 0, 3) % 2;
27
28 8
        return (bool)$count;
29
    }
30
31
    /**
32
     * check if path is basename
33
     *
34
     * @param string $path
35
     *
36
     * @return bool
37
     */
38 5
    public static function isBasename($path)
39
    {
40 5
        if (in_array($path, array('', '.', '..'), true)) {
41 1
            return false;
42
        }
43
44 4
        if (false !== strpos($path, '/')) {
45 3
            return false;
46
        }
47
48 1
        return true;
49
    }
50
51
    /**
52
     * Resolve relative path segments in a path on it's own
53
     *
54
     * This is not realpath, not resolving any links.
55
     *
56
     * @param string $path
57
     *
58
     * @return string
59
     */
60 17
    public static function normalizeSegments($path)
61
    {
62 17
        if ('' === $path) {
63 1
            return $path;
64
        }
65
66 16
        $buffer = $path;
67
68 16
        $prefix = '';
69 16
        $len = strspn($buffer, '/');
70 16
        if (0 < $len) {
71 8
            $prefix = substr($buffer, 0, $len);
72 8
            $buffer = substr($buffer, $len);
73
        }
74
75 16
        $buffer = rtrim($buffer, '/');
76
77 16
        if (in_array($buffer, array('', '.'), true)) {
78 4
            return $prefix;
79
        }
80
81 12
        $pos = strpos($buffer, '/');
82 12
        if (false === $pos) {
83 2
            return $prefix . $buffer;
84
        }
85
86 10
        $buffer = preg_replace('~/+~', '/', $buffer);
87
88 10
        $segments = explode('/', $buffer);
89 10
        $stack = array();
90 10
        foreach ($segments as $segment) {
91 10
            $i = count($stack) - 1;
92 10
            if ('.' === $segment) {
93 2
                continue;
94
            }
95
96 10
            if ('..' !== $segment) {
97 10
                $stack[] = $segment;
98
99 10
                continue;
100
            }
101
102 8
            if (($i > -1) && '..' !== $stack[$i]) {
103 8
                array_pop($stack);
104
105 8
                continue;
106
            }
107
108 1
            $stack[] = $segment;
109
        }
110
111 10
        return $prefix . implode('/', $stack);
112
    }
113
114
    /**
115
     * Normalize a path as/if common in PHP
116
     *
117
     * E.g. w/ phar:// in front which means w/ stream wrappers in
118
     * mind.
119
     *
120
     * @param string $path
121
     *
122
     * @return string
123
     */
124 5
    public static function normalize($path)
125
    {
126 5
        $buffer = $path;
127
128 5
        $scheme = '';
129
        // TODO support for all supported stream wrappers (w/ absolute/relative notation?)
130
        /* @see LibFsStream::isUri */
131
        /* @see LibFsPath::isAbsolute */
132 5
        if (0 === strpos($buffer, 'phar://') || 0 === strpos($buffer, 'file://')) {
133 4
            $scheme = substr($buffer, 0, 7);
134 4
            $buffer = substr($buffer, 7);
135
        }
136
137 5
        $normalized = self::normalizeSegments($buffer);
138
139 5
        return $scheme . $normalized;
140
    }
141
}
142