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