xref: /plugin/catmenu/helper/namespace.php (revision aa591c9040aa9d58df44eaf65df693766613dc9f)
1<?php
2/**
3 * Plugin catmenu — Helper partagé pour la résolution des namespaces
4 *
5 * Regroupe les utilitaires de navigation dans les namespaces DokuWiki
6 * utilisés à la fois par le rendu syntaxique et l'intégration ProseMirror.
7 *
8 * Auteur: Lortetv
9 */
10
11use dokuwiki\Extension\Plugin;
12
13class helper_plugin_catmenu_namespace extends Plugin
14{
15    /**
16     * Retourne le chemin filesystem d'un namespace DokuWiki.
17     */
18    public function namespaceDir(string $namespace): string
19    {
20        global $conf;
21        return rtrim((string)$conf['datadir'], '/') . '/' . utf8_encodeFN(str_replace(':', '/', $namespace));
22    }
23
24    /**
25     * Décompose un namespace en ses composants (page, parent, etc.).
26     *
27     * @return array{pageID: string, parentNamespace: string, parentID: string}
28     */
29    public function getPageNamespaceInfo(string $namespace): array
30    {
31        $parts = explode(':', $namespace);
32        $pageID = (string)array_pop($parts);
33        $parentNamespace = implode(':', $parts);
34        $parentID = '';
35        if ($parentNamespace !== '') {
36            $parentParts = explode(':', $parentNamespace);
37            $parentID = (string)array_pop($parentParts);
38        }
39        return [
40            'pageID'          => $pageID,
41            'parentNamespace' => $parentNamespace,
42            'parentID'        => $parentID,
43        ];
44    }
45
46    /**
47     * Indique si un identifiant de page correspond à une page d'accueil
48     * (page de démarrage ou page homonyme du namespace parent).
49     */
50    public function isHomepage(string $pageID, string $parentID): bool
51    {
52        global $conf;
53        $startPageID = (string)$conf['start'];
54        return $pageID === $startPageID || ($parentID !== '' && $pageID === $parentID);
55    }
56
57    /**
58     * Résout le namespace courant pour une page hôte donnée.
59     * Remonte d'un niveau si la page hôte est elle-même une page d'accueil.
60     */
61    public function getCurrentNamespace(string $hostPageID): string
62    {
63        if (!is_dir($this->namespaceDir($hostPageID))) {
64            $info = $this->getPageNamespaceInfo($hostPageID);
65            if ($this->isHomepage($info['pageID'], $info['parentID'])) {
66                return $info['parentNamespace'];
67            }
68        }
69        return $hostPageID;
70    }
71
72    /**
73     * Résout une expression de namespace (`.`, `~relatif`, ou absolu)
74     * par rapport à la page hôte courante.
75     */
76    public function resolveNamespaceExpression(string $expr, string $hostPageID): string
77    {
78        $expr = trim($expr);
79        if ($expr === '.') {
80            return $this->getCurrentNamespace($hostPageID);
81        }
82        if ($expr !== '' && $expr[0] === '~') {
83            $rel  = cleanID(ltrim($expr, '~'));
84            $base = $this->getCurrentNamespace($hostPageID);
85            return cleanID($base !== '' ? ($base . ':' . $rel) : $rel);
86        }
87        return cleanID($expr);
88    }
89
90    /**
91     * Indique si une page cible appartient à un namespace donné.
92     */
93    public function isTargetInNamespace(string $targetPage, string $namespace): bool
94    {
95        if ($namespace === '') return true;
96        $targetPage = cleanID($targetPage);
97        $namespace  = cleanID($namespace);
98        if ($targetPage === '' || $namespace === '') return false;
99        return ($targetPage === $namespace) || (strpos($targetPage . ':', $namespace . ':') === 0);
100    }
101}
102