Allow downloading the pagelink file directly

This commit is contained in:
2026-02-04 09:53:43 +01:00
parent 70a9f30336
commit a5c44e106e
3 changed files with 78 additions and 4 deletions

View File

@@ -26,6 +26,7 @@ luxtools provides DokuWiki syntax that:
- Provides "open this folder/path" links for local workflows - Provides "open this folder/path" links for local workflows
- Embeds file-backed scratchpads with a minimal inline editor (no wiki revisions) - Embeds file-backed scratchpads with a minimal inline editor (no wiki revisions)
- Links a page to a media folder via a UUID (.pagelink), enabling a `blobs/` alias - Links a page to a media folder via a UUID (.pagelink), enabling a `blobs/` alias
- Adds a Page ID download link in the page info area to fetch a `.pagelink` file
It also ships a small file-serving endpoint (`lib/plugins/luxtools/file.php`) used It also ships a small file-serving endpoint (`lib/plugins/luxtools/file.php`) used
to deliver files and generate cached thumbnails. to deliver files and generate cached thumbnails.

View File

@@ -127,6 +127,45 @@
}); });
} }
function attachDocInfoLink() {
var container = document.querySelector('.docInfo');
if (!container || !container.getAttribute) return;
if (container.getAttribute('data-luxtools-pagelink-docinfo') === '1') return;
container.setAttribute('data-luxtools-pagelink-docinfo', '1');
var pageId = getPageId();
if (!pageId) return;
var endpoint = getBaseUrl() + 'lib/plugins/luxtools/pagelink.php';
var query = endpoint + '?cmd=info&id=' + encodeURIComponent(pageId);
window.fetch(query, {
method: 'GET',
credentials: 'same-origin'
}).then(function (res) {
return res.json().catch(function () { return null; }).then(function (body) {
if (!res.ok || !body || body.ok !== true) {
throw new Error('request failed');
}
return body;
});
}).then(function (info) {
if (!info || !info.uuid) return;
var link = document.createElement('a');
link.href = endpoint + '?cmd=download&id=' + encodeURIComponent(pageId);
link.textContent = 'Page ID: ' + String(info.uuid);
var first = container.firstChild;
container.insertBefore(link, first);
if (first) {
container.insertBefore(document.createTextNode(' · '), first);
}
}).catch(function () {
// ignore failures
});
}
window.addBtnActionLuxtoolsPageLink = function ($btn, props, edid) { window.addBtnActionLuxtoolsPageLink = function ($btn, props, edid) {
$btn.on('click', function () { $btn.on('click', function () {
var pageId = getPageId(); var pageId = getPageId();
@@ -165,5 +204,8 @@
return 'luxtools-pagelink'; return 'luxtools-pagelink';
}; };
document.addEventListener('DOMContentLoaded', attachCopyTargets, false); document.addEventListener('DOMContentLoaded', function () {
attachCopyTargets();
attachDocInfoLink();
}, false);
})(); })();

View File

@@ -46,12 +46,19 @@ if ($cmd === '' || $pageId === '') {
luxtools_pagelink_json(400, ['ok' => false, 'error' => 'missing parameters']); luxtools_pagelink_json(400, ['ok' => false, 'error' => 'missing parameters']);
} }
if (!function_exists('auth_quickaclcheck') || !defined('AUTH_EDIT')) { if (!function_exists('auth_quickaclcheck')) {
luxtools_pagelink_json(403, ['ok' => false, 'error' => 'forbidden']); luxtools_pagelink_json(403, ['ok' => false, 'error' => 'forbidden']);
} }
if (auth_quickaclcheck($pageId) < AUTH_EDIT) { $acl = auth_quickaclcheck($pageId);
luxtools_pagelink_json(403, ['ok' => false, 'error' => 'forbidden']); if ($cmd === 'info' || $cmd === 'download') {
if (!defined('AUTH_READ') || $acl < AUTH_READ) {
luxtools_pagelink_json(403, ['ok' => false, 'error' => 'forbidden']);
}
} else {
if (!defined('AUTH_EDIT') || $acl < AUTH_EDIT) {
luxtools_pagelink_json(403, ['ok' => false, 'error' => 'forbidden']);
}
} }
if ($cmd === 'info') { if ($cmd === 'info') {
@@ -83,6 +90,30 @@ if ($cmd === 'info') {
]); ]);
} }
if ($cmd === 'download') {
$depth = (int)$syntax->getConf('pagelink_search_depth');
if ($depth < 0) $depth = 0;
$pageLink = new PageLink((string)$syntax->getConf('paths'), $depth);
$uuid = $pageLink->getPageUuid($pageId);
if ($uuid === null || $uuid === '') {
http_status(404);
header('Content-Type: text/plain; charset=utf-8');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
echo 'not linked';
exit;
}
http_status(200);
header('Content-Type: text/plain; charset=utf-8');
header('Content-Disposition: attachment; filename=".pagelink"');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Pragma: no-cache');
echo $uuid;
exit;
}
if ($cmd === 'ensure') { if ($cmd === 'ensure') {
if (strtoupper($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') { if (strtoupper($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
luxtools_pagelink_json(405, ['ok' => false, 'error' => 'method not allowed']); luxtools_pagelink_json(405, ['ok' => false, 'error' => 'method not allowed']);