diff --git a/Output.php b/Output.php index debd5e9..6ce7cde 100644 --- a/Output.php +++ b/Output.php @@ -16,6 +16,9 @@ class Output /** @var array */ protected $files; + /** @var Path|false|null */ + protected $openPathMapper = null; + public function __construct(\Doku_Renderer $renderer, $basedir, $webdir, $files) { @@ -307,6 +310,8 @@ class Output return; } + $path = $this->mapOpenPath($path); + global $conf; /** @var \Doku_Renderer_xhtml $renderer */ $renderer = $this->renderer; @@ -336,6 +341,31 @@ class Output $renderer->doc .= $renderer->_formatLink($link); } + /** + * Map a filesystem path to an alias path (if configured). + * + * @param string $path + * @return string + */ + protected function mapOpenPath($path) + { + if ($this->openPathMapper === false) return $path; + + if ($this->openPathMapper === null) { + $syntax = plugin_load('syntax', 'luxtools'); + $pathConfig = $syntax ? (string)$syntax->getConf('paths') : ''; + + if (trim($pathConfig) === '') { + $this->openPathMapper = false; + return $path; + } + + $this->openPathMapper = new Path($pathConfig); + } + + return $this->openPathMapper->mapToAliasPath($path); + } + /** * Render a file link on the XHTML renderer */ diff --git a/Path.php b/Path.php index 3c4c323..40eee0e 100644 --- a/Path.php +++ b/Path.php @@ -103,6 +103,49 @@ class Path return $pathInfo; } + /** + * Map a real filesystem path back to a configured alias, if available. + * + * Example: root "/share/Datascape/" with alias "/Scape/" maps + * "/share/Datascape/some/folder" -> "/Scape/some/folder". + * + * If no alias matches, the input path is returned unchanged (except for + * normalization of slashes and dot-segments). + * + * @param string $path + * @return string + */ + public function mapToAliasPath($path) + { + if (!is_string($path) || $path === '') return $path; + + // normalize input for matching, but do not force a trailing slash + $normalized = static::cleanPath($path, false); + + // collect root->alias mappings (avoid alias keys that reference the same config) + $mappings = []; + foreach ($this->paths as $key => $info) { + if (!isset($info['root']) || $key !== $info['root']) continue; + if (empty($info['alias'])) continue; + $mappings[$info['root']] = $info['alias']; + } + + if ($mappings === []) return $normalized; + + // Prefer the longest matching root (handles nested/overlapping roots) + uksort($mappings, static fn($a, $b) => strlen($b) - strlen($a)); + + foreach ($mappings as $root => $alias) { + if (str_starts_with($normalized, $root)) { + $suffix = substr($normalized, strlen($root)); + $alias = static::cleanPath($alias, true); + return rtrim($alias, '/') . '/' . $suffix; + } + } + + return $normalized; + } + /** * Clean a path for better comparison * diff --git a/_test/PathTest.php b/_test/PathTest.php index 397c301..4c1d738 100644 --- a/_test/PathTest.php +++ b/_test/PathTest.php @@ -110,4 +110,13 @@ EOT $this->expectExceptionMessageMatches('/Path not allowed/'); $this->path->getPathInfo($path); } + + public function testMapToAliasPath() + { + $mapped = $this->path->mapToAliasPath('/linux/another/path/some/folder'); + $this->assertEquals('alias/some/folder', $mapped); + + $unmapped = $this->path->mapToAliasPath('/linux/file/path/example.txt'); + $this->assertEquals('/linux/file/path/example.txt', $unmapped); + } } diff --git a/_test/SyntaxTest.php b/_test/SyntaxTest.php index d1b4e11..2481aed 100644 --- a/_test/SyntaxTest.php +++ b/_test/SyntaxTest.php @@ -29,7 +29,7 @@ class plugin_luxtools_test extends DokuWikiTest parent::setUp(); // Setup config so that access to the TMP directory will be allowed - $conf ['plugin']['luxtools']['paths'] = TMP_DIR . '/filelistdata/' . "\n" . 'W> http://localhost/'; + $conf ['plugin']['luxtools']['paths'] = TMP_DIR . '/filelistdata/' . "\n" . 'A> /Scape' . "\n" . 'W> http://localhost/'; } @@ -288,6 +288,6 @@ class plugin_luxtools_test extends DokuWikiTest $this->assertStringNotContainsString('example2.txt', $xhtml); // Directory row should trigger the same behaviour as {{open>...}} for that folder - $this->assertStringContainsString('data-path="' . TMP_DIR . '/filelistdata/exampledir"', $xhtml); + $this->assertStringContainsString('data-path="/Scape/exampledir"', $xhtml); } }