Unlinking

This commit is contained in:
2026-02-02 21:55:35 +01:00
parent e1102d9f06
commit 47a8bfa50a
3 changed files with 160 additions and 8 deletions

View File

@@ -41,22 +41,26 @@
return '/';
}
function ensurePageLink() {
function requestPageLink(cmd, params) {
var pageId = getPageId();
if (!pageId) return false;
var endpoint = getBaseUrl() + 'lib/plugins/luxtools/pagelink.php';
var params = new window.URLSearchParams();
params.set('cmd', 'ensure');
params.set('id', pageId);
params.set('sectok', getSectok());
var payload = new window.URLSearchParams();
payload.set('cmd', cmd);
payload.set('id', pageId);
if (params && typeof params === 'object') {
Object.keys(params).forEach(function (key) {
payload.set(key, String(params[key]));
});
}
window.fetch(endpoint, {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' },
body: params.toString()
body: payload.toString()
}).then(function (res) {
return res.json().catch(function () { return null; }).then(function (body) {
if (!res.ok || !body || body.ok !== true) {
@@ -66,13 +70,25 @@
});
}).catch(function (err) {
if (window.console && window.console.warn) {
window.console.warn('PageLink creation failed:', err);
window.console.warn('PageLink request failed:', err);
}
});
return false;
}
function fetchInfo() {
return requestPageLink('info', {});
}
function ensurePageLink() {
return requestPageLink('ensure', { sectok: getSectok() });
}
function unlinkPageLink() {
return requestPageLink('unlink', { sectok: getSectok() });
}
function copyToClipboard(text) {
if (!text) return;
if (window.navigator && window.navigator.clipboard && window.navigator.clipboard.writeText) {
@@ -126,7 +142,37 @@
window.addBtnActionLuxtoolsPageLink = function ($btn, props, edid) {
$btn.on('click', function () {
ensurePageLink();
var pageId = getPageId();
if (!pageId) return false;
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) {
if (window.confirm('Unlink page?')) {
unlinkPageLink();
}
return;
}
ensurePageLink();
}).catch(function (err) {
if (window.console && window.console.warn) {
window.console.warn('PageLink info failed:', err);
}
ensurePageLink();
});
return false;
});
return 'luxtools-pagelink';

View File

@@ -54,6 +54,35 @@ if (auth_quickaclcheck($pageId) < AUTH_EDIT) {
luxtools_pagelink_json(403, ['ok' => false, 'error' => 'forbidden']);
}
if ($cmd === 'info') {
$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) {
luxtools_pagelink_json(200, [
'ok' => true,
'uuid' => null,
'linked' => false,
'folder' => null,
'multiple' => false,
]);
}
$info = $pageLink->resolveUuid($uuid);
$folder = $info['folder'] ?? null;
$multiple = !empty($info['multiple']);
luxtools_pagelink_json(200, [
'ok' => true,
'uuid' => $uuid,
'linked' => is_string($folder) && $folder !== '',
'folder' => is_string($folder) ? $folder : null,
'multiple' => $multiple,
]);
}
if ($cmd === 'ensure') {
if (strtoupper($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
luxtools_pagelink_json(405, ['ok' => false, 'error' => 'method not allowed']);
@@ -83,4 +112,26 @@ if ($cmd === 'ensure') {
luxtools_pagelink_json(200, ['ok' => true, 'uuid' => $uuid, 'created' => true]);
}
if ($cmd === 'unlink') {
if (strtoupper($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
luxtools_pagelink_json(405, ['ok' => false, 'error' => 'method not allowed']);
}
if (!checkSecurityToken()) {
luxtools_pagelink_json(403, ['ok' => false, 'error' => 'bad token']);
}
$depth = (int)$syntax->getConf('pagelink_search_depth');
if ($depth < 0) $depth = 0;
$pageLink = new PageLink((string)$syntax->getConf('paths'), $depth);
$result = $pageLink->unlinkPage($pageId);
luxtools_pagelink_json(200, [
'ok' => true,
'uuid' => $result['uuid'] ?? null,
'folder' => $result['folder'] ?? null,
]);
}
luxtools_pagelink_json(400, ['ok' => false, 'error' => 'unknown command']);

View File

@@ -87,6 +87,46 @@ class PageLink
return (bool)p_set_metadata($pageId, [self::META_KEY => $uuid]);
}
/**
* Remove the pagelink UUID from page metadata.
*/
public function removePageUuid(string $pageId): bool
{
if ($pageId === '') return false;
if (!function_exists('p_set_metadata')) return false;
return (bool)p_set_metadata($pageId, [self::META_KEY => '']);
}
/**
* Unlink a page: remove UUID, delete linked .pagelink file if present, and clear cache.
*
* @param string $pageId
* @return array{ok: bool, uuid: string|null, folder: string|null}
*/
public function unlinkPage(string $pageId): array
{
$uuid = $this->getPageUuid($pageId);
if ($uuid === null) {
return ['ok' => true, 'uuid' => null, 'folder' => null];
}
$linkInfo = $this->resolveUuid($uuid);
$folder = $linkInfo['folder'] ?? null;
if (is_string($folder) && $folder !== '') {
$file = rtrim($folder, '/\\') . '/.pagelink';
if (is_file($file) && !is_link($file)) {
@unlink($file);
}
}
$this->removeCacheEntry($uuid);
$this->removePageUuid($pageId);
return ['ok' => true, 'uuid' => $uuid, 'folder' => is_string($folder) ? $folder : null];
}
/**
* Resolve a pagelink UUID to a linked folder (if any).
*
@@ -177,6 +217,21 @@ class PageLink
$this->cacheDirty = false;
}
/**
* Remove a specific UUID from cache.
*/
public function removeCacheEntry(string $uuid): void
{
$uuid = self::normalizeUuid($uuid);
if ($uuid === null) return;
$cache = $this->loadCache();
if (!isset($cache[$uuid])) return;
unset($cache[$uuid]);
$this->writeCache($cache);
}
/**
* Get cache file path for pagelink mappings.
*/