contextID = $contextID; $this->contextNS = (string)getNS($contextID); } /** * Resolves a given ID to be absolute * * @param string $id The ID to resolve * @param string|int|false $rev The revision time to use when resolving * @param bool $isDateAt Is the given revision only a datetime hint not an exact revision? * @return string */ public function resolveId($id, $rev = '', $isDateAt = false) { global $conf; // some pre cleaning for useslash: if ($conf['useslash']) $id = str_replace('/', ':', $id); // on some systems, semicolons might be used instead of colons: $id = str_replace(';', ':', $id); $id = $this->resolvePrefix($id); return $this->resolveRelatives($id); } /** * Handle IDs starting with . or ~ and prepend the proper prefix * * @param string $id * @return string */ protected function resolvePrefix($id) { if ($id === '') return $id; // relative to current page (makes the current page a start page) if ($id[0] === '~') { $id = $this->contextID . ':' . substr($id, 1); } // relative to current namespace if ($id[0] === '.') { // normalize initial dots without a colon $id = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/', '\1\3:', $id); $id = $this->contextNS . ':' . $id; } // auto-relative, because there is a context namespace but no namespace in the ID if ($this->contextID !== '' && strpos($id, ':') === false) { $id = $this->contextNS . ':' . $id; } return $id; } /** * Handle . and .. within IDs * * @param string $id * @return string */ protected function resolveRelatives($id) { $id = rtrim($id, '.'); // trailing dots are invalid if ($id === '') return ''; $trail = ($id[-1] === ':') ? ':' : ''; // keep trailing colon $result = []; $parts = explode(':', $id); foreach ($parts as $dir) { if ($dir === '.') continue; if ($dir === '') continue; if ($dir === '..') { array_pop($result); continue; } $result[] = $dir; } $id = implode(':', $result); $id .= $trail; return $id; } }