1<?php
2
3namespace dokuwiki\File;
4
5/**
6 * Creates an absolute page ID from a relative one
7 */
8class PageResolver extends Resolver
9{
10    /**
11     * Resolves a given ID to be absolute
12     *
13     * This handles all kinds of relative shortcuts, startpages and autoplurals
14     * @inheritDoc
15     */
16    public function resolveId($id, $rev = '', $isDateAt = false)
17    {
18        global $conf;
19        $id = (string) $id;
20
21        // pages may have a hash attached, we separate it on resolving
22        if (strpos($id, '#') !== false) {
23            [$id, $hash] = sexplode('#', $id, 2);
24            $hash = cleanID($hash);
25        } else {
26            $hash = '';
27        }
28
29        if ($id !== '') {
30            $id = parent::resolveId($id, $rev, $isDateAt);
31            $id = $this->resolveStartPage($id, $rev, $isDateAt);
32            if ($conf['autoplural']) {
33                $id = $this->resolveAutoPlural($id, $rev, $isDateAt);
34            }
35        } else {
36            $id = $this->contextID;
37        }
38
39        $id = cleanID($id); // FIXME always? or support parameter
40        // readd hash if any
41        if ($hash !== '') $id .= "#$hash";
42        return $id;
43    }
44
45    /**
46     * IDs ending in :
47     *
48     * @param string $id
49     * @param string|int|false $rev
50     * @param bool $isDateAt
51     * @return string
52     */
53    protected function resolveStartPage($id, $rev, $isDateAt)
54    {
55        global $conf;
56
57        if ($id === '' || $id[-1] !== ':') return $id;
58
59        if (page_exists($id . $conf['start'], $rev, true, $isDateAt)) {
60            // start page inside namespace
61            return $id . $conf['start'];
62        } elseif (page_exists($id . noNS(cleanID($id)), $rev, true, $isDateAt)) {
63            // page named like the NS inside the NS
64            return $id . noNS(cleanID($id));
65        } elseif (page_exists(substr($id, 0, -1), $rev, true, $isDateAt)) {
66            // page named like the NS outside the NS
67            return substr($id, 0, -1);
68        }
69
70        // fall back to default start page
71        return $id . $conf['start'];
72    }
73
74    /**
75     * Try alternative plural/singular form
76     *
77     * @param string $id
78     * @param int $rev
79     * @param bool $isDateAt
80     * @return string
81     */
82    protected function resolveAutoPlural($id, $rev, $isDateAt)
83    {
84        if (page_exists($id, $rev, $isDateAt)) return $id;
85
86        if ($id[-1] === 's') {
87            $try = substr($id, 0, -1);
88        } else {
89            $try = $id . 's';
90        }
91
92        if (page_exists($try, $rev, true, $isDateAt)) {
93            return $try;
94        }
95        return $id;
96    }
97}
98