Inital implementation of image listing

This commit is contained in:
2026-01-05 10:49:00 +01:00
parent fe8d0bbffb
commit 9a067eca16
5 changed files with 390 additions and 128 deletions

189
syntax/images.php Normal file
View File

@@ -0,0 +1,189 @@
<?php
use dokuwiki\Extension\SyntaxPlugin;
use dokuwiki\plugin\filetools\Crawler;
use dokuwiki\plugin\filetools\Output;
use dokuwiki\plugin\filetools\Path;
/**
* File Tools Plugin: Image gallery syntax.
*
* Renders a thumbnail gallery of images matching a glob pattern.
*/
class syntax_plugin_filetools_images extends SyntaxPlugin
{
/** @inheritdoc */
public function getType()
{
return 'substition';
}
/** @inheritdoc */
public function getPType()
{
return 'block';
}
/** @inheritdoc */
public function getSort()
{
return 222;
}
/** @inheritdoc */
public function connectTo($mode)
{
$this->Lexer->addSpecialPattern('\{\{images>.+?\}\}', $mode, 'plugin_filetools_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,
];
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') . ']');
return true;
}
$crawler = new Crawler($this->getConf('extensions'));
$crawler->setSortBy($params['sort']);
$crawler->setSortReverse($params['order'] === 'desc');
$result = $crawler->crawl(
$pathInfo['root'],
$pathInfo['local'],
$pattern,
$params['recursive'],
$params['titlefile']
);
$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') . ']');
return true;
}
$output = new Output($renderer, $pathInfo['root'], $pathInfo['web'], $items);
if ($format == 'xhtml') {
$output->renderAsGallery($params);
return true;
}
// Fallback for non-XHTML formats: render as a list of links
$params['style'] = 'list';
$params['showsize'] = 0;
$params['showdate'] = 0;
$params['listsep'] = ', ';
$output->renderAsList($params);
return true;
}
/**
* Flattens the crawl result tree into a list of file items.
*
* @param array $items
* @param string $prefix
* @return array
*/
protected function flattenResultTree($items, $prefix = '')
{
$result = [];
foreach ($items as $file) {
if ($file['children'] !== false) {
$result = array_merge(
$result,
$this->flattenResultTree($file['children'], $prefix . $file['name'] . '/')
);
} else {
$file['name'] = $prefix . $file['name'];
$result[] = $file;
}
}
return $result;
}
/**
* Keep only image files.
*
* @param array $items
* @return array
*/
protected function filterImages($items)
{
$images = [];
foreach ($items as $item) {
if (!isset($item['path']) || !is_string($item['path'])) continue;
if (!is_file($item['path'])) continue;
try {
[, $mime,] = mimetype($item['path'], false);
} catch (Throwable $e) {
continue;
}
if (is_string($mime) && str_starts_with($mime, 'image/')) {
$images[] = $item;
}
}
return $images;
}
}