Failed Conditions
Push — refactorResolving ( 1356e5 )
by Andreas
03:03
created

Resolver::resolveId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 3
dl 0
loc 14
rs 9.7998
c 0
b 0
f 0
1
<?php
2
3
namespace dokuwiki\Utils;
4
5
/**
6
 * Resolving relative IDs to absolute ones
7
 */
8
abstract class Resolver
9
{
10
11
    /** @var string context page ID */
12
    protected $contextID;
13
    /** @var string namespace of context page ID */
14
    protected $contextNS;
15
16
    /**
17
     * @param string $contextID the current pageID that's the context to resolve relative IDs to
18
     */
19
    public function __construct($contextID)
20
    {
21
        $this->contextID = $contextID;
22
        $this->contextNS = (string)getNS($contextID);
23
    }
24
25
    /**
26
     * Resolves a given ID to be absolute
27
     *
28
     * @param string $id The ID to resolve
29
     * @param string|int|false $rev The revision time to use when resolving
30
     * @param bool $isDateAt Is the given revision only a datetime hint not an exact revision?
31
     * @return string
32
     */
33
    public function resolveId($id, $rev = '', $isDateAt = false)
34
    {
35
        global $conf;
36
37
        // some pre cleaning for useslash:
38
        if ($conf['useslash']) $id = str_replace('/', ':', $id);
39
        // on some systems, semicolons might be used instead of colons:
40
        $id = str_replace(';', ':', $id);
41
42
        $id = $this->resolvePrefix($id);
43
        $id = $this->resolveRelatives($id);
44
45
        return $id;
46
    }
47
48
    /**
49
     * Handle IDs starting with . or ~ and prepend the proper prefix
50
     *
51
     * @param string $id
52
     * @return string
53
     */
54
    protected function resolvePrefix($id)
55
    {
56
        // relative to current page (makes the current page a start page)
57
        if ($id[0] === '~') {
58
            $id = $this->contextID . ':' . $id;
59
        }
60
61
        // relative to current namespace
62
        if ($id[0] === '.') {
63
            // normalize initial dots without a colon
64
            // FIXME do we need this or would this be cleaned later in resolveRelatives?
65
            $id = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/', '\1\3:', $id);
66
            $id = $this->contextNS . ':' . $id;
67
        }
68
69
        return $id;
70
    }
71
72
    /**
73
     * Handle . and .. within IDs
74
     *
75
     * @param string $id
76
     * @return string
77
     */
78
    protected function resolveRelatives($id)
79
    {
80
        // cleanup relatives
81
        $result = array();
82
        $parts = explode(':', $id);
83
        if (!$parts[0]) $result[] = ''; // FIXME is this necessary? what's it for? should it be type checked?
84
        foreach ($parts AS $key => $dir) {
85
            if ($dir == '..') {
86
                if (end($result) == '..') {
87
                    $result[] = '..';
88
                } elseif (!array_pop($result)) {
89
                    $result[] = '..';
90
                }
91
            } elseif ($dir && $dir != '.') {
92
                $result[] = $dir;
93
            }
94
        }
95
        if (!end($parts)) $result[] = '';
96
        $id = implode(':', $result);
97
98
        return $id;
99
    }
100
101
}
102