diff --git a/syntax.php b/syntax.php index f460c97..8df6ac7 100644 --- a/syntax.php +++ b/syntax.php @@ -1,5 +1,6 @@ getSyntaxKeyword(); + $pattern = '\{\{' . $keyword . '>.+?\}\}'; + $this->Lexer->addSpecialPattern($pattern, $mode, 'plugin_luxtools_' . $keyword); + } + + /** @inheritdoc */ + public function handle($match, $state, $pos, Doku_Handler $handler) + { + global $INPUT; + + // Do not allow the syntax in discussion plugin comments + if (!$this->getConf('allow_in_comments') && $INPUT->has('comment')) { + return false; + } + + $keyword = $this->getSyntaxKeyword(); + $match = substr($match, strlen('{{' . $keyword . '>'), -2); + [$path, $flags] = array_pad(explode('&', $match, 2), 2, ''); + + $params = $this->parseFlags($flags); + $pathData = $this->processPath($path); + + return ['pathData' => $pathData, 'params' => $params]; + } + + /** @inheritdoc */ + public function render($format, Doku_Renderer $renderer, $data) + { + if ($data === false) { + return false; + } + + if ($format !== 'xhtml' && $format !== 'odt') { + return false; + } + + $pathData = $data['pathData']; + $params = $data['params']; + + // Disable caching if requested + if ($params['cache'] === 0) { + $renderer->nocache(); + } + + return $this->doRender($format, $renderer, $pathData, $params); + } + + /** + * Parse flags string into parameters array. + * + * @param string $flags The flags string from the syntax + * @return array Parsed parameters + */ + protected function parseFlags(string $flags): array + { + // Base defaults shared by all handlers + $baseDefaults = [ + 'sort' => 'name', + 'order' => 'asc', + 'style' => 'list', + 'tableheader' => 0, + 'recursive' => 0, + 'titlefile' => '_title.txt', + 'cache' => 0, + 'randlinks' => 0, + 'showsize' => 0, + 'showdate' => 0, + 'listsep' => ', ', + ]; + + // Merge with handler-specific defaults + $params = array_merge($baseDefaults, $this->getDefaultParams()); + + // Load default config options and combine with provided flags + $flags = $this->getConf('defaults') . '&' . $flags; + $flagList = explode('&', $flags); + + foreach ($flagList as $flag) { + if (empty(trim($flag))) { + continue; + } + [$name, $value] = sexplode('=', $flag, 2, ''); + $params[trim($name)] = trim(trim($value), '"'); // quotes can be used to keep whitespace + } + + return $params; + } + + /** + * Get path info with error handling. + * + * @param string $basePath The base path to resolve + * @param \Doku_Renderer $renderer The renderer for error output + * @return array|false Path info array or false on error + */ + protected function getPathInfoSafe(string $basePath, \Doku_Renderer $renderer) + { + try { + $pathHelper = new Path($this->getConf('paths')); + return $pathHelper->getPathInfo($basePath); + } catch (\Exception $e) { + $this->renderError($renderer, 'error_outsidejail'); + return false; + } + } + + /** + * Create and configure a Crawler instance. + * + * @param array $params The parameters array + * @return Crawler + */ + protected function createCrawler(array $params): Crawler + { + $crawler = new Crawler($this->getConf('extensions')); + $crawler->setSortBy($params['sort']); + $crawler->setSortReverse($params['order'] === 'desc'); + return $crawler; + } + + /** + * Render an error message. + * + * @param \Doku_Renderer $renderer The renderer + * @param string $langKey The language key for the error message + */ + protected function renderError(\Doku_Renderer $renderer, string $langKey): void + { + $renderer->cdata('[n/a: ' . $this->getLang($langKey) . ']'); + } + + /** + * Separate a path into base directory and pattern. + * + * @param string $path The full path with pattern + * @return array [base, pattern] + */ + protected function separatePathAndPattern(string $path): array + { + $path = Path::cleanPath($path, false); + $parts = explode('/', $path); + $pattern = array_pop($parts); + $base = implode('/', $parts) . '/'; + return [$base, $pattern]; + } +} diff --git a/syntax/directory.php b/syntax/directory.php index 84a568b..2b8a9ec 100644 --- a/syntax/directory.php +++ b/syntax/directory.php @@ -1,111 +1,41 @@ Lexer->addSpecialPattern('\{\{directory>.+?\}\}', $mode, 'plugin_luxtools_directory'); - } - - /** @inheritdoc */ - public function handle($match, $state, $pos, Doku_Handler $handler) - { - global $INPUT; - - // do not allow the syntax in discussion plugin comments - if (!$this->getConf('allow_in_comments') && $INPUT->has('comment')) { - return false; - } - - $match = substr($match, strlen('{{directory>'), -2); - [$path, $flags] = explode('&', $match, 2); - - // load default config options - $flags = $this->getConf('defaults') . '&' . $flags; - $flags = explode('&', $flags); - - $params = [ - 'sort' => 'name', - 'order' => 'asc', - 'style' => 'list', - 'tableheader' => 0, - 'recursive' => 0, - 'titlefile' => '_title.txt', - 'cache' => 0, - 'randlinks' => 0, - 'showsize' => 0, - 'showdate' => 0, - 'listsep' => ', ', - ]; - - foreach ($flags as $flag) { - [$name, $value] = sexplode('=', $flag, 2, ''); - $params[trim($name)] = trim(trim($value), '"'); // quotes can be used to keep whitespace - } - - // directory path (no glob/pattern) + // Directory path (no glob/pattern) $path = Path::cleanPath($path, true); - - return [$path, $params]; + return ['path' => $path]; } /** @inheritdoc */ - public function render($format, Doku_Renderer $renderer, $data) + protected function doRender(string $format, \Doku_Renderer $renderer, array $pathData, array $params): bool { - if ($data === false) return false; - [$path, $params] = $data; - - if ($format != 'xhtml' && $format != 'odt') { - return false; - } - - // disable caching - if ($params['cache'] === 0) { - $renderer->nocache(); - } - - try { - $pathHelper = new Path($this->getConf('paths')); - $pathInfo = $pathHelper->getPathInfo($path); - } catch (Exception $e) { - $renderer->cdata('[n/a: ' . $this->getLang('error_outsidejail') . ']'); + $pathInfo = $this->getPathInfoSafe($pathData['path'], $renderer); + if ($pathInfo === false) { return true; } - $crawler = new Crawler($this->getConf('extensions')); - $crawler->setSortBy($params['sort']); - $crawler->setSortReverse($params['order'] === 'desc'); - + $crawler = $this->createCrawler($params); $items = $crawler->listDirectory( $pathInfo['root'], $pathInfo['local'], @@ -113,7 +43,7 @@ class syntax_plugin_luxtools_directory extends SyntaxPlugin ); if ($items == []) { - $renderer->cdata('[n/a: ' . $this->getLang('error_nomatch') . ']'); + $this->renderError($renderer, 'error_nomatch'); return true; } diff --git a/syntax/files.php b/syntax/files.php index b9797c9..e9bc104 100644 --- a/syntax/files.php +++ b/syntax/files.php @@ -1,124 +1,48 @@ separatePathAndPattern($path); + return ['base' => $base, 'pattern' => $pattern]; } /** @inheritdoc */ - public function getSort() + protected function doRender(string $format, \Doku_Renderer $renderer, array $pathData, array $params): bool { - return 222; - } - - /** @inheritdoc */ - public function connectTo($mode) - { - $this->Lexer->addSpecialPattern('\{\{files>.+?\}\}', $mode, 'plugin_luxtools_files'); - } - - /** @inheritdoc */ - public function handle($match, $state, $pos, Doku_Handler $handler) - { - global $INPUT; - - // do not allow the syntax in discussion plugin comments - if (!$this->getConf('allow_in_comments') && $INPUT->has('comment')) { - return false; - } - - $match = substr($match, strlen('{{files>'), -2); - [$path, $flags] = explode('&', $match, 2); - - // load default config options - $flags = $this->getConf('defaults') . '&' . $flags; - $flags = explode('&', $flags); - - $params = [ - 'sort' => 'name', - 'order' => 'asc', - 'style' => 'list', - 'tableheader' => 0, - 'recursive' => 0, - 'titlefile' => '_title.txt', - 'cache' => 0, - 'randlinks' => 0, - 'showsize' => 0, - 'showdate' => 0, - 'listsep' => ', ', - ]; - foreach ($flags as $flag) { - [$name, $value] = sexplode('=', $flag, 2, ''); - $params[trim($name)] = trim(trim($value), '"'); // quotes can be use to keep whitespace - } - - // separate path and pattern - $path = Path::cleanPath($path, false); - $parts = explode('/', $path); - $pattern = array_pop($parts); - $base = implode('/', $parts) . '/'; - - return [$base, $pattern, $params]; - } - - /** - * Create output - */ - public function render($format, Doku_Renderer $renderer, $data) - { - [$base, $pattern, $params] = $data; - - if ($format != 'xhtml' && $format != 'odt') { - return false; - } - - // disable caching - if ($params['cache'] === 0) { - $renderer->nocache(); - } - - try { - $pathHelper = new Path($this->getConf('paths')); - $pathInfo = $pathHelper->getPathInfo($base); - } catch (Exception $e) { - $renderer->cdata('[n/a: ' . $this->getLang('error_outsidejail') . ']'); + $pathInfo = $this->getPathInfoSafe($pathData['base'], $renderer); + if ($pathInfo === false) { return true; } - $crawler = new Crawler($this->getConf('extensions')); - $crawler->setSortBy($params['sort']); - $crawler->setSortReverse($params['order'] === 'desc'); - + $crawler = $this->createCrawler($params); $result = $crawler->crawl( $pathInfo['root'], $pathInfo['local'], - $pattern, + $pathData['pattern'], $params['recursive'], $params['titlefile'] ); - // if we got nothing back, display a message if ($result == []) { - $renderer->cdata('[n/a: ' . $this->getLang('error_nomatch') . ']'); + $this->renderError($renderer, 'error_nomatch'); return true; } diff --git a/syntax/images.php b/syntax/images.php index a870d66..02b66f9 100644 --- a/syntax/images.php +++ b/syntax/images.php @@ -1,113 +1,55 @@ Lexer->addSpecialPattern('\{\{images>.+?\}\}', $mode, 'plugin_luxtools_images'); - } - - /** @inheritdoc */ - public function handle($match, $state, $pos, Doku_Handler $handler) - { - global $INPUT; - - // do not allow the syntax in discussion plugin comments - if (!$this->getConf('allow_in_comments') && $INPUT->has('comment')) { - return false; - } - - $match = substr($match, strlen('{{images>'), -2); - [$path, $flags] = explode('&', $match, 2); - - // load default config options - $flags = $this->getConf('defaults') . '&' . $flags; - $flags = explode('&', $flags); - - $params = [ - 'sort' => 'name', - 'order' => 'asc', - 'recursive' => 0, - 'titlefile' => '_title.txt', - 'cache' => 0, - 'randlinks' => 0, + // Images syntax doesn't use some of the common params + return [ + 'style' => null, + 'tableheader' => null, + 'showsize' => null, + 'showdate' => null, + 'listsep' => null, ]; - - foreach ($flags as $flag) { - [$name, $value] = sexplode('=', $flag, 2, ''); - $params[trim($name)] = trim(trim($value), '"'); // quotes can be use to keep whitespace - } - - // separate path and pattern - $path = Path::cleanPath($path, false); - $parts = explode('/', $path); - $pattern = array_pop($parts); - $base = implode('/', $parts) . '/'; - - return [$base, $pattern, $params]; } - /** - * Create output - */ - public function render($format, Doku_Renderer $renderer, $data) + /** @inheritdoc */ + protected function processPath(string $path): array { - [$base, $pattern, $params] = $data; + [$base, $pattern] = $this->separatePathAndPattern($path); + return ['base' => $base, 'pattern' => $pattern]; + } - if ($format != 'xhtml' && $format != 'odt') { - return false; - } - - // disable caching - if ($params['cache'] === 0) { - $renderer->nocache(); - } - - try { - $pathHelper = new Path($this->getConf('paths')); - $pathInfo = $pathHelper->getPathInfo($base); - } catch (Exception $e) { - $renderer->cdata('[n/a: ' . $this->getLang('error_outsidejail') . ']'); + /** @inheritdoc */ + protected function doRender(string $format, \Doku_Renderer $renderer, array $pathData, array $params): bool + { + $pathInfo = $this->getPathInfoSafe($pathData['base'], $renderer); + if ($pathInfo === false) { return true; } - $crawler = new Crawler($this->getConf('extensions')); - $crawler->setSortBy($params['sort']); - $crawler->setSortReverse($params['order'] === 'desc'); - + $crawler = $this->createCrawler($params); $result = $crawler->crawl( $pathInfo['root'], $pathInfo['local'], - $pattern, + $pathData['pattern'], $params['recursive'], $params['titlefile'] ); @@ -115,9 +57,8 @@ class syntax_plugin_luxtools_images extends SyntaxPlugin $items = $this->flattenResultTree($result); $items = $this->filterImages($items); - // if we got nothing back, display a message if ($items == []) { - $renderer->cdata('[n/a: ' . $this->getLang('error_nomatch') . ']'); + $this->renderError($renderer, 'error_nomatch'); return true; }