Sync folders

This commit is contained in:
Andreas Andersen 2026-04-19 00:06:24 +02:00
parent 25d2ec43ca
commit 32c69d30c4
9 changed files with 2693 additions and 0 deletions

View file

@ -0,0 +1,37 @@
=== Ansico Diagnosekoder ===
Contributors: aphandersen
Tags: icd-10, diagnosis, gutenberg, search
Requires at least: 6.2
Tested up to: 6.5
Stable tag: 1.0.0
License: GPLv3 or later
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Et WordPress-plugin der tilføjer Gutenberg-blokke til søgning i ICD-10 diagnosekoder baseret på en uploadet tekstfil.
== Beskrivelse ==
- Tilføjer blokken "Ansico Diagnosekoder" med live resultater
- Tilføjer blokken "Ansico Diagnosekoder Søgefelt" til sidebar eller andre kompakte områder
- Tilføjer blokken "Ansico Diagnosekoder Kodekort" til visning af side-tilknyttede koder
- Backend-side under Indstillinger
- Upload af ny tekstfil erstatter eksisterende datagrundlag
- Søger kun i felterne kode og tekst
- Søgeord highlightes i resultaterne
- Klik på et resultat kopierer diagnosekoden
== Installation ==
1. Upload plugin-mappen til /wp-content/plugins/ eller installer ZIP-filen via WordPress.
2. Aktivér pluginet.
3. Gå til Indstillinger → Ansico Diagnosekoder.
4. Upload din tekstfil.
5. Indsæt blokken "Ansico Diagnosekoder" på en side.
== Changelog ==
= 1.0.0 =
* Første stabile release.
== Support ==
Support: https://ansico.dk/Ansico/Ansico-diagnosekoder

View file

@ -0,0 +1,55 @@
<?php
/**
* Plugin Name: Ansico Diagnosekoder
* Plugin URI: https://ansico.dk/Ansico/Ansico-diagnosekoder
* Description: Gutenberg-blokke og backend-import til søgning i ICD-10 diagnosekoder fra en uploadet tekstfil.
* Version: 1.0.0
* Author: Andreas Andersen (Ansico)
* Author URI: https://ansico.dk
* License: GPL-3.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
* Text Domain: ansico-diagnosekoder
*/
if (!defined('ABSPATH')) {
exit;
}
define('ANSICO_DIAGNOSEKODER_VERSION', '1.0.0');
define('ANSICO_DIAGNOSEKODER_PAGE_LINKS_META', 'ansico_diagnosekoder_page_links');
define('ANSICO_DIAGNOSEKODER_PAGE_FAVORITES_META', 'ansico_diagnosekoder_page_favorites');
define('ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL', 'ansico_diagnosekoder_results_url');
define('ANSICO_DIAGNOSEKODER_PLUGIN_FILE', __FILE__);
define('ANSICO_DIAGNOSEKODER_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('ANSICO_DIAGNOSEKODER_PLUGIN_URL', plugin_dir_url(__FILE__));
define('ANSICO_DIAGNOSEKODER_OPTION_DATA', 'ansico_diagnosekoder_data');
define('ANSICO_DIAGNOSEKODER_OPTION_META', 'ansico_diagnosekoder_meta');
require_once ANSICO_DIAGNOSEKODER_PLUGIN_DIR . 'includes/class-ansico-diagnosekoder-parser.php';
require_once ANSICO_DIAGNOSEKODER_PLUGIN_DIR . 'includes/class-ansico-diagnosekoder-admin.php';
require_once ANSICO_DIAGNOSEKODER_PLUGIN_DIR . 'includes/class-ansico-diagnosekoder-rest.php';
require_once ANSICO_DIAGNOSEKODER_PLUGIN_DIR . 'includes/class-ansico-diagnosekoder-block.php';
Ansico_Diagnosekoder_Admin::init();
Ansico_Diagnosekoder_REST::init();
Ansico_Diagnosekoder_Block::init();
add_action('template_redirect', function () {
$results_url = (string) get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '');
$results_page_id = $results_url !== '' ? absint(url_to_postid($results_url)) : 0;
$current_page_id = function_exists('get_queried_object_id') ? absint(get_queried_object_id()) : 0;
if (($results_page_id && $current_page_id === $results_page_id) || isset($_GET['q'])) {
nocache_headers();
}
});
register_activation_hook(__FILE__, function () {
if (false === get_option(ANSICO_DIAGNOSEKODER_OPTION_DATA, false)) {
add_option(ANSICO_DIAGNOSEKODER_OPTION_DATA, []);
}
if (false === get_option(ANSICO_DIAGNOSEKODER_OPTION_META, false)) {
add_option(ANSICO_DIAGNOSEKODER_OPTION_META, []);
}
});

View file

@ -0,0 +1,438 @@
.ansico-diagnosekoder {
border: 1px solid #dcdcde;
border-radius: 8px;
padding: 16px;
background: #fff;
}
.ansico-diagnosekoder__search {
margin-bottom: 16px;
}
.ansico-diagnosekoder__search--inline {
display: flex;
gap: 8px;
align-items: center;
margin-bottom: 0;
}
.ansico-diagnosekoder__input {
width: 100%;
padding: 10px 12px;
border: 1px solid #8c8f94;
border-radius: 6px;
font-size: 16px;
}
.ansico-diagnosekoder__message {
margin: 0;
color: #50575e;
}
.ansico-diagnosekoder__list {
list-style: none;
margin: 0;
padding: 0;
}
.ansico-diagnosekoder__item {
border-top: 1px solid #f0f0f1;
}
.ansico-diagnosekoder__item:first-child {
border-top: 0;
}
.ansico-diagnosekoder__code {
font-weight: 700;
}
.ansico-diagnosekoder__separator {
color: #50575e;
}
.ansico-diagnosekoder__text {
color: #1d2327;
}
.ansico-diagnosekoder__highlight {
padding: 0 0.12em;
background: #fff2a8;
}
.ansico-diagnosekoder-editor-preview {
border: 1px dashed #c3c4c7;
border-radius: 8px;
padding: 16px;
background: #f6f7f7;
}
.ansico-diagnosekoder--search-only {
padding: 0;
border: 0;
background: transparent;
}
.ansico-diagnosekoder__submit {
white-space: nowrap;
padding: 10px 14px;
border: 1px solid #2271b1;
border-radius: 6px;
background: #2271b1;
color: #fff;
cursor: pointer;
}
.ansico-diagnosekoder__submit:hover {
background: #135e96;
border-color: #135e96;
}
.ansico-diagnosekoder__row {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 8px 0;
}
.ansico-diagnosekoder__entry-link,
.ansico-diagnosekoder__entry-link:visited {
color: inherit;
text-decoration: none;
flex: 1 1 auto;
min-width: 0;
display: block;
}
.ansico-diagnosekoder__entry-link:hover,
.ansico-diagnosekoder__entry-link:focus-visible {
color: inherit;
text-decoration: none;
}
.ansico-diagnosekoder__entry {
min-width: 0;
flex: 1 1 auto;
line-height: 1.4;
}
.ansico-diagnosekoder__linked-badge {
display: inline-block;
margin-left: 8px;
font-size: 12px;
color: #50575e;
}
.ansico-diagnosekoder__actions {
display: flex;
align-items: center;
gap: 6px;
flex: 0 0 auto;
}
.ansico-diagnosekoder__icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: 1px solid #dcdcde;
border-radius: 999px;
background: #fff;
color: #50575e;
cursor: pointer;
position: relative;
font-size: 16px;
transition: transform 120ms ease, background-color 120ms ease, border-color 120ms ease, box-shadow 120ms ease, color 120ms ease;
}
.ansico-diagnosekoder__icon-button:hover,
.ansico-diagnosekoder__icon-button:focus-visible {
background: #f6f7f7;
outline: none;
}
.ansico-diagnosekoder__icon-button.is-feedback-visible::after {
content: attr(aria-label);
position: absolute;
top: calc(100% + 6px);
right: 0;
white-space: nowrap;
background: #1d2327;
color: #fff;
font-size: 12px;
line-height: 1.2;
padding: 4px 6px;
border-radius: 4px;
z-index: 10;
}
.ansico-diagnosekoder__icon-button.is-pressed,
.ansico-diagnosekoder__icon-button:active {
transform: scale(0.92);
background: #e9f2f9;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
.ansico-diagnosekoder__icon-button svg {
width: 18px;
height: 18px;
display: block;
fill: currentColor;
}
.ansico-diagnosekoder__copy-button.is-pressed,
.ansico-diagnosekoder__copy-button:active {
background: #dfeffb;
border-color: #2271b1;
color: #2271b1;
}
.ansico-diagnosekoder__favorite-button.is-active {
color: #111111;
border-color: #111111;
background: #f3f4f5;
}
.ansico-diagnosekoder__favorite-button.is-active svg {
fill: #111111 !important;
stroke: none;
}
.ansico-diagnosekoder__link-button.is-active {
color: #b32d2e;
border-color: #b32d2e;
background: #fff1f1;
}
@media (max-width: 600px) {
.ansico-diagnosekoder__search--inline {
flex-direction: column;
align-items: stretch;
}
.ansico-diagnosekoder__row {
align-items: flex-start;
}
}
.ansico-diagnosekoder__favorite-button svg {
fill: none;
stroke: currentColor;
stroke-width: 1.8;
}
.ansico-diagnosekoder__favorite-button.is-active svg {
fill: #111111 !important;
stroke: #111111;
stroke-width: 0;
}
.ansico-diagnosekoder__item.has-link .ansico-diagnosekoder__entry-link {
font-weight: 500;
}
.ansico-diagnosekoder__item[data-is-favorite="0"] .ansico-diagnosekoder__favorite-button svg {
fill: none !important;
stroke: currentColor !important;
stroke-width: 1.8;
}
.ansico-diagnosekoder__item[data-is-favorite="1"] .ansico-diagnosekoder__favorite-button svg {
fill: #111111 !important;
stroke: #111111 !important;
stroke-width: 0;
}
.ansico-diagnosekoder__item.has-link {
background: #f6f7f7;
}
.ansico-diagnosekoder__item.has-link:hover {
background: #eef0f1;
}
.ansico-diagnosekoder__modal[hidden] {
display: none;
}
.ansico-diagnosekoder__modal {
position: fixed;
inset: 0;
z-index: 999999;
}
.ansico-diagnosekoder__modal-backdrop {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.45);
}
.ansico-diagnosekoder__modal-dialog {
position: relative;
max-width: 720px;
margin: 8vh auto 0;
background: #fff;
border-radius: 12px;
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.2);
overflow: hidden;
}
.ansico-diagnosekoder__modal-header,
.ansico-diagnosekoder__modal-footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 16px 20px;
border-bottom: 1px solid #f0f0f1;
}
.ansico-diagnosekoder__modal-footer {
border-bottom: 0;
border-top: 1px solid #f0f0f1;
justify-content: flex-end;
}
.ansico-diagnosekoder__modal-body {
padding: 20px;
}
.ansico-diagnosekoder__modal-title {
margin: 0;
font-size: 20px;
}
.ansico-diagnosekoder__modal-close {
appearance: none;
border: 0;
background: transparent;
font-size: 28px;
line-height: 1;
cursor: pointer;
color: #50575e;
}
.ansico-diagnosekoder__modal-field {
margin-bottom: 16px;
}
.ansico-diagnosekoder__modal-label {
display: block;
margin-bottom: 6px;
font-weight: 600;
color: #1d2327;
}
.ansico-diagnosekoder__modal-input {
width: 100%;
padding: 10px 12px;
border: 1px solid #8c8f94;
border-radius: 6px;
font-size: 15px;
}
.ansico-diagnosekoder__modal-hint,
.ansico-diagnosekoder__modal-message {
margin: 0 0 16px;
color: #50575e;
}
.ansico-diagnosekoder__modal-search-results {
max-height: 240px;
overflow: auto;
border: 1px solid #dcdcde;
border-radius: 8px;
background: #fff;
}
.ansico-diagnosekoder__modal-result-list {
list-style: none;
margin: 0;
padding: 0;
}
.ansico-diagnosekoder__modal-result-item + .ansico-diagnosekoder__modal-result-item {
border-top: 1px solid #f0f0f1;
}
.ansico-diagnosekoder__modal-result-button {
display: block;
width: 100%;
padding: 12px 14px;
border: 0;
background: #fff;
text-align: left;
cursor: pointer;
}
.ansico-diagnosekoder__modal-result-button:hover,
.ansico-diagnosekoder__modal-result-button:focus {
background: #f6f7f7;
}
.ansico-diagnosekoder__modal-result-title {
display: block;
font-weight: 600;
color: #1d2327;
}
.ansico-diagnosekoder__modal-result-meta {
display: block;
margin-top: 4px;
color: #50575e;
font-size: 13px;
word-break: break-all;
}
.ansico-diagnosekoder__modal-button {
appearance: none;
border: 1px solid #2271b1;
border-radius: 6px;
padding: 10px 14px;
cursor: pointer;
font-weight: 600;
}
.ansico-diagnosekoder__modal-button--primary {
background: #2271b1;
color: #fff;
}
.ansico-diagnosekoder__modal-button--secondary {
background: #fff;
color: #2271b1;
}
body.ansico-diagnosekoder-modal-open {
overflow: hidden;
}
.ansico-diagnosekoder-kodekort {
margin: 0;
}
.ansico-diagnosekoder-kodekort__list {
display: grid;
gap: 10px;
}
.ansico-diagnosekoder-kodekort__item {
padding: 12px 14px;
border: 1px solid #dcdcde;
border-radius: 8px;
background: #f6f7f7;
line-height: 1.5;
color: #1d2327;
}
.ansico-diagnosekoder-kodekort__code {
font-weight: 700;
}
.ansico-diagnosekoder-kodekort__separator {
color: #50575e;
}

View file

@ -0,0 +1,66 @@
(function (blocks, element, i18n) {
var el = element.createElement;
var __ = i18n.__;
blocks.registerBlockType('ansico/diagnosekoder', {
title: __('Ansico Diagnosekoder', 'ansico-diagnosekoder'),
icon: 'search',
category: 'widgets',
description: __('Søgefelt med live søgeresultater i ICD-10 diagnosekoder.', 'ansico-diagnosekoder'),
edit: function () {
return el(
'div',
{ className: 'ansico-diagnosekoder-editor-preview' },
[
el('strong', {}, __('Ansico Diagnosekoder', 'ansico-diagnosekoder')),
el('p', {}, __('Denne blok viser et søgefelt og søgeresultater på forsiden.', 'ansico-diagnosekoder'))
]
);
},
save: function () {
return null;
}
});
blocks.registerBlockType('ansico/diagnosekoder-kodekort', {
title: __('Ansico Diagnosekoder Kodekort', 'ansico-diagnosekoder'),
icon: 'index-card',
category: 'widgets',
description: __('Viser kode og beskrivelse på sider, der er tilknyttet en diagnosekode via pluginets URL-kobling.', 'ansico-diagnosekoder'),
edit: function () {
return el(
'div',
{ className: 'ansico-diagnosekoder-editor-preview' },
[
el('strong', {}, __('Ansico Diagnosekoder Kodekort', 'ansico-diagnosekoder')),
el('p', {}, __('Denne blok vises kun på frontend, hvis den aktuelle side er koblet til en diagnosekode via en URL-tilknytning.', 'ansico-diagnosekoder'))
]
);
},
save: function () {
return null;
}
});
blocks.registerBlockType('ansico/diagnosekoder-soegefelt', {
title: __('Ansico Diagnosekoder Søgefelt', 'ansico-diagnosekoder'),
icon: 'search',
category: 'widgets',
description: __('Kompakt søgefelt, der sender brugeren til en valgt resultatside.', 'ansico-diagnosekoder'),
edit: function () {
return el(
'div',
{ className: 'ansico-diagnosekoder-editor-preview' },
[
el('strong', {}, __('Ansico Diagnosekoder Søgefelt', 'ansico-diagnosekoder')),
el('p', {}, __('Denne blok viser kun søgefeltet og sender brugeren videre til resultatsiden angivet i pluginets indstillinger.', 'ansico-diagnosekoder'))
]
);
},
save: function () {
return null;
}
});
})(window.wp.blocks, window.wp.element, window.wp.i18n);

View file

@ -0,0 +1,774 @@
(function () {
var favoriteCodes = [];
var codeLinks = {};
function getPageId(root) {
var value = root && root.getAttribute ? root.getAttribute('data-page-id') : '';
var pageId = parseInt(value || '0', 10);
if (!Number.isFinite(pageId) || pageId <= 0) {
var stateNode = root ? root.querySelector('.ansico-diagnosekoder__page-state') : null;
if (stateNode) {
try {
var state = JSON.parse(stateNode.textContent || '{}');
pageId = parseInt(state.pageId || '0', 10);
} catch (error) {}
}
}
if ((!Number.isFinite(pageId) || pageId <= 0) && typeof AnsicoDiagnosekoderConfig.resultsPageId !== 'undefined') {
pageId = parseInt(AnsicoDiagnosekoderConfig.resultsPageId || '0', 10);
}
if ((!Number.isFinite(pageId) || pageId <= 0) && document.body) {
var match = (document.body.className || '').match(/(?:^|\s)page-id-(\d+)(?:\s|$)/);
if (match) {
pageId = parseInt(match[1], 10);
}
}
return Number.isFinite(pageId) && pageId > 0 ? pageId : 0;
}
function preloadPageState(root) {
if (!root || !root.getAttribute) {
return;
}
var stateNode = root.querySelector('.ansico-diagnosekoder__page-state');
if (stateNode) {
try {
var state = JSON.parse(stateNode.textContent || '{}');
if (Array.isArray(state.favorites)) {
favoriteCodes = state.favorites.map(normalizeCode);
}
if (state.links && typeof state.links === 'object') {
codeLinks = {};
Object.keys(state.links).forEach(function (code) {
codeLinks[normalizeCode(code)] = state.links[code];
});
}
if (state.pageId && root.getAttribute('data-page-id') !== String(state.pageId)) {
root.setAttribute('data-page-id', String(state.pageId));
}
return;
} catch (error) {}
}
var favoritesRaw = root.getAttribute('data-page-favorites') || '[]';
var linksRaw = root.getAttribute('data-page-links') || '{}';
try {
var parsedFavorites = JSON.parse(favoritesRaw);
if (Array.isArray(parsedFavorites)) {
favoriteCodes = parsedFavorites.map(normalizeCode);
}
} catch (error) {}
try {
var parsedLinks = JSON.parse(linksRaw);
if (parsedLinks && typeof parsedLinks === 'object') {
codeLinks = {};
Object.keys(parsedLinks).forEach(function (code) {
codeLinks[normalizeCode(code)] = parsedLinks[code];
});
}
} catch (error) {}
}
function debounce(fn, delay) {
var timer;
return function () {
var context = this;
var args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
};
}
function escapeHtml(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#039;');
}
function escapeRegExp(str) {
return String(str).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function normalizeCode(code) {
return String(code || '').replace(/\s+/g, '').toUpperCase();
}
function highlightText(text, query) {
var safeText = escapeHtml(text);
var trimmedQuery = String(query || '').trim();
if (!trimmedQuery) {
return safeText;
}
var parts = trimmedQuery.split(/\s+/).filter(Boolean);
if (!parts.length) {
return safeText;
}
var pattern = parts.map(escapeRegExp).join('|');
return safeText.replace(new RegExp('(' + pattern + ')', 'gi'), '<mark class="ansico-diagnosekoder__highlight">$1</mark>');
}
function getCopyIcon() {
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M16 1H6c-1.1 0-2 .9-2 2v12h2V3h10V1zm3 4H10c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h9c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H10V7h9v14z"></path></svg>';
}
function getStarIcon(isActive) {
if (isActive) {
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="currentColor"></path></svg>';
}
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"></path></svg>';
}
function getPlusIcon() {
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 11H13V5h-2v6H5v2h6v6h2v-6h6z"></path></svg>';
}
function getMinusIcon() {
return '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 11H5v2h14z"></path></svg>';
}
function isFavorite(code) {
return favoriteCodes.indexOf(normalizeCode(code)) !== -1;
}
function getLinkedUrl(code, fallback) {
var normalized = normalizeCode(code);
if (normalized && typeof codeLinks[normalized] === 'string' && codeLinks[normalized]) {
return codeLinks[normalized];
}
return fallback || '';
}
function setTemporaryLabel(button, label, duration) {
var originalLabel = button.getAttribute('data-label-default') || button.getAttribute('aria-label') || '';
button.setAttribute('aria-label', label);
button.classList.add('is-feedback-visible');
window.setTimeout(function () {
button.setAttribute('aria-label', originalLabel);
button.classList.remove('is-feedback-visible');
}, duration || 1400);
}
function pulseButton(button) {
button.classList.remove('is-pressed');
void button.offsetWidth;
button.classList.add('is-pressed');
window.setTimeout(function () {
button.classList.remove('is-pressed');
}, 220);
}
function copyText(value, button) {
var successLabel = button.getAttribute('data-label-success') || button.getAttribute('aria-label') || '';
var errorLabel = button.getAttribute('data-label-error') || button.getAttribute('aria-label') || '';
pulseButton(button);
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(value).then(function () {
setTemporaryLabel(button, successLabel, 1400);
}).catch(function () {
setTemporaryLabel(button, errorLabel, 1400);
});
return;
}
try {
var temp = document.createElement('textarea');
temp.value = value;
temp.setAttribute('readonly', 'readonly');
temp.style.position = 'absolute';
temp.style.left = '-9999px';
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
setTemporaryLabel(button, successLabel, 1400);
} catch (error) {
setTemporaryLabel(button, errorLabel, 1400);
}
}
function searchInternalContent(query) {
if (!AnsicoDiagnosekoderConfig.contentSearchUrl) {
return Promise.resolve([]);
}
var url = AnsicoDiagnosekoderConfig.contentSearchUrl + '?q=' + encodeURIComponent(query) + '&limit=8';
return fetch(url, {
credentials: 'same-origin',
headers: {
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
},
cache: 'no-store'
}).then(function (response) {
if (!response.ok) {
throw new Error('Internal content search failed');
}
return response.json();
}).then(function (data) {
return Array.isArray(data.results) ? data.results : [];
});
}
function ensureLinkModal() {
var existing = document.getElementById('ansico-diagnosekoder-link-modal');
if (existing) {
return existing;
}
var wrapper = document.createElement('div');
wrapper.id = 'ansico-diagnosekoder-link-modal';
wrapper.className = 'ansico-diagnosekoder__modal';
wrapper.setAttribute('hidden', 'hidden');
wrapper.innerHTML = '' +
'<div class="ansico-diagnosekoder__modal-backdrop" data-modal-close="1"></div>' +
'<div class="ansico-diagnosekoder__modal-dialog" role="dialog" aria-modal="true" aria-labelledby="ansico-diagnosekoder-link-modal-title">' +
'<div class="ansico-diagnosekoder__modal-header">' +
'<h3 id="ansico-diagnosekoder-link-modal-title" class="ansico-diagnosekoder__modal-title"></h3>' +
'<button type="button" class="ansico-diagnosekoder__modal-close" data-modal-close="1" aria-label="Luk">×</button>' +
'</div>' +
'<div class="ansico-diagnosekoder__modal-body">' +
'<div class="ansico-diagnosekoder__modal-field">' +
'<label class="ansico-diagnosekoder__modal-label" for="ansico-diagnosekoder-link-modal-code"></label>' +
'<input id="ansico-diagnosekoder-link-modal-code" class="ansico-diagnosekoder__modal-input" type="text" readonly />' +
'</div>' +
'<p class="ansico-diagnosekoder__modal-hint"></p>' +
'<div class="ansico-diagnosekoder__modal-field">' +
'<label class="ansico-diagnosekoder__modal-label" for="ansico-diagnosekoder-link-modal-url"></label>' +
'<input id="ansico-diagnosekoder-link-modal-url" class="ansico-diagnosekoder__modal-input" type="url" />' +
'</div>' +
'<div class="ansico-diagnosekoder__modal-field">' +
'<label class="ansico-diagnosekoder__modal-label" for="ansico-diagnosekoder-link-modal-search"></label>' +
'<input id="ansico-diagnosekoder-link-modal-search" class="ansico-diagnosekoder__modal-input" type="search" />' +
'</div>' +
'<div class="ansico-diagnosekoder__modal-search-results"></div>' +
'</div>' +
'<div class="ansico-diagnosekoder__modal-footer">' +
'<button type="button" class="ansico-diagnosekoder__modal-button ansico-diagnosekoder__modal-button--secondary" data-modal-cancel="1"></button>' +
'<button type="button" class="ansico-diagnosekoder__modal-button ansico-diagnosekoder__modal-button--primary" data-modal-save="1"></button>' +
'</div>' +
'</div>';
document.body.appendChild(wrapper);
return wrapper;
}
function openLinkModal(code, currentUrl) {
var modal = ensureLinkModal();
var titleNode = modal.querySelector('.ansico-diagnosekoder__modal-title');
var labels = modal.querySelectorAll('.ansico-diagnosekoder__modal-label');
var hintNode = modal.querySelector('.ansico-diagnosekoder__modal-hint');
var codeInput = modal.querySelector('#ansico-diagnosekoder-link-modal-code');
var urlInput = modal.querySelector('#ansico-diagnosekoder-link-modal-url');
var searchInput = modal.querySelector('#ansico-diagnosekoder-link-modal-search');
var resultsNode = modal.querySelector('.ansico-diagnosekoder__modal-search-results');
var cancelButton = modal.querySelector('[data-modal-cancel="1"]');
var saveButton = modal.querySelector('[data-modal-save="1"]');
var closeButtons = modal.querySelectorAll('[data-modal-close="1"]');
var activeSearchToken = 0;
titleNode.textContent = currentUrl ? AnsicoDiagnosekoderConfig.strings.linkModalTitleEdit : AnsicoDiagnosekoderConfig.strings.linkModalTitleAdd;
labels[0].textContent = AnsicoDiagnosekoderConfig.strings.linkModalCodeLabel;
labels[1].textContent = AnsicoDiagnosekoderConfig.strings.linkModalUrlLabel;
labels[2].textContent = AnsicoDiagnosekoderConfig.strings.linkModalSearchLabel;
hintNode.textContent = AnsicoDiagnosekoderConfig.strings.linkModalHint;
cancelButton.textContent = AnsicoDiagnosekoderConfig.strings.linkModalCancel;
saveButton.textContent = AnsicoDiagnosekoderConfig.strings.linkModalSave;
codeInput.value = code || '';
urlInput.value = currentUrl || '';
urlInput.placeholder = AnsicoDiagnosekoderConfig.strings.linkPromptDefault || 'https://';
searchInput.value = '';
searchInput.placeholder = AnsicoDiagnosekoderConfig.strings.linkModalSearchPlaceholder;
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkModalSearchEmpty) + '</p>';
modal.removeAttribute('hidden');
document.body.classList.add('ansico-diagnosekoder-modal-open');
function closeModal() {
modal.setAttribute('hidden', 'hidden');
document.body.classList.remove('ansico-diagnosekoder-modal-open');
saveButton.onclick = null;
cancelButton.onclick = null;
closeButtons.forEach(function (button) { button.onclick = null; });
searchInput.oninput = null;
document.removeEventListener('keydown', onKeyDown);
}
function onKeyDown(event) {
if (event.key === 'Escape') {
closeModal();
}
}
function renderSearchResults(items) {
if (!items.length) {
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkModalSearchNone) + '</p>';
return;
}
var html = '<ul class="ansico-diagnosekoder__modal-result-list">';
items.forEach(function (item) {
html += '<li class="ansico-diagnosekoder__modal-result-item">';
html += '<button type="button" class="ansico-diagnosekoder__modal-result-button" data-url="' + escapeHtml(item.url || '') + '">';
html += '<span class="ansico-diagnosekoder__modal-result-title">' + escapeHtml(item.title || item.url || '') + '</span>';
html += '<span class="ansico-diagnosekoder__modal-result-meta">' + escapeHtml(item.url || '') + '</span>';
html += '</button></li>';
});
html += '</ul>';
resultsNode.innerHTML = html;
resultsNode.querySelectorAll('.ansico-diagnosekoder__modal-result-button').forEach(function (button) {
button.addEventListener('click', function () {
urlInput.value = button.getAttribute('data-url') || '';
});
});
}
searchInput.oninput = debounce(function () {
var query = searchInput.value.trim();
activeSearchToken += 1;
var token = activeSearchToken;
if (!query) {
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkModalSearchEmpty) + '</p>';
return;
}
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.loading) + '</p>';
searchInternalContent(query).then(function (items) {
if (token !== activeSearchToken) {
return;
}
renderSearchResults(items);
}).catch(function () {
resultsNode.innerHTML = '<p class="ansico-diagnosekoder__modal-message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.linkSearchError) + '</p>';
});
}, 180);
var resolver;
var promise = new Promise(function (resolve) {
resolver = resolve;
});
saveButton.onclick = function () {
resolver(String(urlInput.value || '').trim());
closeModal();
};
cancelButton.onclick = function () {
resolver(null);
closeModal();
};
closeButtons.forEach(function (button) {
button.onclick = function () {
resolver(null);
closeModal();
};
});
document.addEventListener('keydown', onKeyDown);
window.setTimeout(function () { urlInput.focus(); urlInput.select(); }, 0);
return promise;
}
function fetchPageState(pageId) {
if (!pageId || !AnsicoDiagnosekoderConfig.pageStateUrl) {
return Promise.resolve({ favorites: favoriteCodes, links: codeLinks, page_id: pageId || 0 });
}
var url = AnsicoDiagnosekoderConfig.pageStateUrl + '?page_id=' + encodeURIComponent(pageId) + '&_ansico_ts=' + Date.now();
return fetch(url, {
credentials: 'same-origin',
cache: 'no-store'
}).then(function (response) {
if (!response.ok) {
throw new Error('Page state failed');
}
return response.json();
}).then(function (data) {
syncClientCollections(data || {});
return data || {};
}).catch(function () {
return { favorites: favoriteCodes, links: codeLinks, page_id: pageId || 0 };
});
}
function mergeAndSortResults(results) {
var merged = (Array.isArray(results) ? results : []).map(function (item, index) {
var normalizedCode = normalizeCode(item.code);
var favorite = isFavorite(normalizedCode) || !!item.is_favorite;
var linkedUrl = getLinkedUrl(normalizedCode, item.linked_url || '');
return Object.assign({}, item, {
is_favorite: favorite,
linked_url: linkedUrl,
_normalized_code: normalizedCode,
_render_index: index
});
});
merged.sort(function (a, b) {
if (!!a.is_favorite !== !!b.is_favorite) {
return a.is_favorite ? -1 : 1;
}
return a._render_index - b._render_index;
});
return merged;
}
function renderResults(container, results, query) {
if (!results.length) {
container.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.noResults) + '</p>';
return;
}
var sortedResults = mergeAndSortResults(results);
var html = '<ul class="ansico-diagnosekoder__list">';
sortedResults.forEach(function (item) {
var normalizedCode = item._normalized_code || normalizeCode(item.code);
var favorite = !!item.is_favorite;
var linkedUrl = item.linked_url || '';
var hasLink = !!linkedUrl;
var copyValue = item.code + ' - ' + item.text;
var copyAria = AnsicoDiagnosekoderConfig.strings.copyCodeAria.replace('%s', copyValue);
var favoriteAria = favorite ? AnsicoDiagnosekoderConfig.strings.removeFavorite : AnsicoDiagnosekoderConfig.strings.addFavorite;
var linkAria = hasLink ? AnsicoDiagnosekoderConfig.strings.removeLink : AnsicoDiagnosekoderConfig.strings.addLink;
var entryTagStart = hasLink ? '<a class="ansico-diagnosekoder__entry-link" href="' + escapeHtml(linkedUrl) + '">' : '';
var entryTagEnd = hasLink ? '</a>' : '';
html += '<li class="ansico-diagnosekoder__item' + (favorite ? ' is-favorite' : '') + (hasLink ? ' has-link' : '') + '" data-code="' + escapeHtml(normalizedCode) + '" data-is-favorite="' + (favorite ? '1' : '0') + '" data-has-link="' + (hasLink ? '1' : '0') + '">';
html += '<div class="ansico-diagnosekoder__row">';
html += entryTagStart + '<div class="ansico-diagnosekoder__entry">';
html += '<span class="ansico-diagnosekoder__code">' + highlightText(item.code, query) + '</span>';
html += '<span class="ansico-diagnosekoder__separator"> </span>';
html += '<span class="ansico-diagnosekoder__text">' + highlightText(item.text, query) + '</span>';
if (hasLink) {
html += '<span class="ansico-diagnosekoder__linked-badge">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.openLink) + '</span>';
}
html += '</div>' + entryTagEnd;
html += '<div class="ansico-diagnosekoder__actions">';
html += '<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__copy-button" data-copy-value="' + escapeHtml(copyValue) + '"';
html += ' data-label-default="' + escapeHtml(copyAria) + '"';
html += ' data-label-success="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.copied) + '"';
html += ' data-label-error="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.copyError) + '"';
html += ' aria-label="' + escapeHtml(copyAria) + '" title="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.copyIcon) + '">';
html += getCopyIcon() + '</button>';
if (AnsicoDiagnosekoderConfig.isLoggedIn) {
html += '<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__favorite-button' + (favorite ? ' is-active' : '') + '" data-code="' + escapeHtml(normalizedCode) + '" aria-pressed="' + (favorite ? 'true' : 'false') + '" data-label-default="' + escapeHtml(favoriteAria) + '" aria-label="' + escapeHtml(favoriteAria) + '" title="' + escapeHtml(AnsicoDiagnosekoderConfig.strings.favoriteIcon) + '">';
html += getStarIcon(favorite) + '</button>';
html += '<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__link-button' + (hasLink ? ' is-active' : '') + '" data-code="' + escapeHtml(normalizedCode) + '" data-current-url="' + escapeHtml(linkedUrl) + '" data-label-default="' + escapeHtml(linkAria) + '" aria-label="' + escapeHtml(linkAria) + '" title="' + escapeHtml(hasLink ? AnsicoDiagnosekoderConfig.strings.removeLinkIcon : AnsicoDiagnosekoderConfig.strings.addLinkIcon) + '">';
html += hasLink ? getMinusIcon() : getPlusIcon();
html += '</button>';
}
html += '</div></div></li>';
});
html += '</ul>';
container.innerHTML = html;
}
function getQueryParam(name) {
var params = new URLSearchParams(window.location.search);
return params.get(name) || '';
}
function getSelectorEscaped(value) {
if (window.CSS && typeof window.CSS.escape === 'function') {
return window.CSS.escape(value);
}
return String(value).replace(/"/g, '\\"');
}
function updateFavoriteButtons(code, isFav, pageId) {
var normalizedCode = normalizeCode(code);
var selector = '.ansico-diagnosekoder__favorite-button[data-code="' + getSelectorEscaped(normalizedCode) + '"]';
if (pageId) {
selector = '.ansico-diagnosekoder[data-page-id="' + getSelectorEscaped(String(pageId)) + '"] ' + selector;
}
var buttons = document.querySelectorAll(selector);
buttons.forEach(function (button) {
var label = isFav ? AnsicoDiagnosekoderConfig.strings.removeFavorite : AnsicoDiagnosekoderConfig.strings.addFavorite;
button.classList.toggle('is-active', isFav);
button.setAttribute('aria-pressed', isFav ? 'true' : 'false');
button.setAttribute('aria-label', label);
button.setAttribute('data-label-default', label);
button.innerHTML = getStarIcon(isFav);
var item = button.closest('.ansico-diagnosekoder__item');
if (item) {
item.classList.toggle('is-favorite', isFav);
item.setAttribute('data-is-favorite', isFav ? '1' : '0');
}
});
}
function updateLinkButtons(code, url) {
var normalizedCode = normalizeCode(code);
var buttons = document.querySelectorAll('.ansico-diagnosekoder__link-button[data-code="' + getSelectorEscaped(normalizedCode) + '"]');
var hasLink = !!url;
buttons.forEach(function (button) {
var label = hasLink ? AnsicoDiagnosekoderConfig.strings.removeLink : AnsicoDiagnosekoderConfig.strings.addLink;
button.classList.toggle('is-active', hasLink);
button.setAttribute('aria-label', label);
button.setAttribute('data-label-default', label);
button.setAttribute('data-current-url', url || '');
button.setAttribute('title', hasLink ? AnsicoDiagnosekoderConfig.strings.removeLinkIcon : AnsicoDiagnosekoderConfig.strings.addLinkIcon);
button.innerHTML = hasLink ? getMinusIcon() : getPlusIcon();
var item = button.closest('.ansico-diagnosekoder__item');
if (item) {
item.classList.toggle('has-link', hasLink);
item.setAttribute('data-has-link', hasLink ? '1' : '0');
}
});
}
function syncClientCollections(data) {
if (Array.isArray(data.favorites)) {
favoriteCodes = data.favorites.map(normalizeCode);
}
if (data.links && typeof data.links === 'object') {
codeLinks = {};
Object.keys(data.links).forEach(function (code) {
codeLinks[normalizeCode(code)] = data.links[code];
});
}
}
function toggleFavorite(code, button, refreshCallback, pageId) {
fetch(AnsicoDiagnosekoderConfig.favoritesUrl, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
},
body: JSON.stringify({ code: normalizeCode(code), page_id: pageId || 0 })
}).then(function (response) {
if (!response.ok) {
throw new Error('Favorite toggle failed');
}
return response.json();
}).then(function (data) {
syncClientCollections(data);
pulseButton(button);
updateFavoriteButtons(code, !!data.is_favorite, pageId || 0);
if (typeof refreshCallback === 'function') {
refreshCallback();
}
}).catch(function () {
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.favoriteError, 1400);
});
}
function saveCodeLink(code, url, button, refreshCallback, pageId) {
fetch(AnsicoDiagnosekoderConfig.linksUrl, {
method: 'POST',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
},
body: JSON.stringify({ code: normalizeCode(code), url: url, page_id: pageId || 0 })
}).then(function (response) {
if (!response.ok) {
throw new Error('Link save failed');
}
return response.json();
}).then(function (data) {
syncClientCollections(data);
pulseButton(button);
updateLinkButtons(code, data.url || '');
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkSaved, 1200);
if (typeof refreshCallback === 'function') {
refreshCallback();
}
}).catch(function () {
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkError, 1400);
});
}
function removeCodeLink(code, button, refreshCallback, pageId) {
var url = AnsicoDiagnosekoderConfig.linksUrl + '?code=' + encodeURIComponent(normalizeCode(code)) + '&page_id=' + encodeURIComponent(pageId || 0);
fetch(url, {
method: 'DELETE',
credentials: 'same-origin',
headers: {
'X-WP-Nonce': AnsicoDiagnosekoderConfig.nonce
}
}).then(function (response) {
if (!response.ok) {
throw new Error('Link removal failed');
}
return response.json();
}).then(function (data) {
syncClientCollections(data);
pulseButton(button);
updateLinkButtons(code, '');
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkRemoved, 1200);
if (typeof refreshCallback === 'function') {
refreshCallback();
}
}).catch(function () {
setTemporaryLabel(button, AnsicoDiagnosekoderConfig.strings.linkError, 1400);
});
}
function initResultsBlock(root) {
preloadPageState(root);
var input = root.querySelector('.ansico-diagnosekoder__input');
var results = root.querySelector('.ansico-diagnosekoder__results');
var hasData = root.getAttribute('data-has-data') === '1';
if (!input || !results || !hasData) {
return;
}
var runSearch = function () {
var query = input.value.trim();
if (!query) {
results.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.empty) + '</p>';
return;
}
results.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.loading) + '</p>';
var pageId = getPageId(root);
var url = AnsicoDiagnosekoderConfig.restUrl + '?q=' + encodeURIComponent(query) + '&limit=50&page_id=' + encodeURIComponent(pageId) + '&_ansico_ts=' + Date.now();
fetchPageState(pageId).then(function () {
return fetch(url, {
credentials: 'same-origin',
cache: 'no-store'
});
})
.then(function (response) {
if (!response.ok) {
throw new Error('Request failed');
}
return response.json();
})
.then(function (data) {
syncClientCollections(data);
if (
(!Array.isArray(data.favorites) || !data.favorites.length) &&
(!data.links || !Object.keys(data.links).length) &&
(!favoriteCodes.length && !Object.keys(codeLinks).length)
) {
preloadPageState(root);
}
renderResults(results, data.results || [], query);
})
.catch(function () {
results.innerHTML = '<p class="ansico-diagnosekoder__message">' + escapeHtml(AnsicoDiagnosekoderConfig.strings.error) + '</p>';
});
};
var debouncedSearch = debounce(runSearch, 200);
input.addEventListener('input', debouncedSearch);
results.addEventListener('click', function (event) {
var copyButton = event.target.closest('.ansico-diagnosekoder__copy-button');
if (copyButton) {
copyText(copyButton.getAttribute('data-copy-value') || '', copyButton);
return;
}
var favoriteButton = event.target.closest('.ansico-diagnosekoder__favorite-button');
if (favoriteButton) {
toggleFavorite(favoriteButton.getAttribute('data-code') || '', favoriteButton, runSearch, getPageId(root));
return;
}
var linkButton = event.target.closest('.ansico-diagnosekoder__link-button');
if (linkButton) {
var code = linkButton.getAttribute('data-code') || '';
var currentUrl = linkButton.getAttribute('data-current-url') || '';
if (currentUrl) {
removeCodeLink(code, linkButton, runSearch, getPageId(root));
return;
}
openLinkModal(code, currentUrl).then(function (enteredUrl) {
if (enteredUrl === null) {
return;
}
enteredUrl = String(enteredUrl).trim();
if (!enteredUrl) {
return;
}
saveCodeLink(code, enteredUrl, linkButton, runSearch, getPageId(root));
});
}
});
var stateNode = root.querySelector('.ansico-diagnosekoder__page-state');
var hasServerRenderedResults = false;
if (stateNode) {
try {
var initialState = JSON.parse(stateNode.textContent || '{}');
hasServerRenderedResults = !!(initialState && initialState.hasInitialResults);
} catch (error) {}
}
fetchPageState(getPageId(root)).then(function () {
var presetQuery = getQueryParam('q');
if (presetQuery) {
input.value = presetQuery;
if (!hasServerRenderedResults) {
runSearch();
}
}
});
}
function initSearchOnlyBlock(form) {
form.addEventListener('submit', function (event) {
var input = form.querySelector('.ansico-diagnosekoder__input');
var query = input ? input.value.trim() : '';
var resultsUrl = form.getAttribute('data-results-url') || AnsicoDiagnosekoderConfig.resultsUrl || '';
if (!resultsUrl) {
event.preventDefault();
var message = form.querySelector('.ansico-diagnosekoder__message');
if (message) {
message.textContent = AnsicoDiagnosekoderConfig.strings.missingResultsUrl;
}
return;
}
if (!query) {
event.preventDefault();
return;
}
event.preventDefault();
var url = new URL(resultsUrl, window.location.origin);
url.searchParams.set('q', query);
window.location.href = url.toString();
});
}
document.addEventListener('DOMContentLoaded', function () {
var resultsBlocks = document.querySelectorAll('.wp-block-ansico-diagnosekoder.ansico-diagnosekoder');
resultsBlocks.forEach(initResultsBlock);
var searchOnlyBlocks = document.querySelectorAll('.wp-block-ansico-diagnosekoder-soegefelt.ansico-diagnosekoder--search-only');
searchOnlyBlocks.forEach(initSearchOnlyBlock);
});
})();

View file

@ -0,0 +1,388 @@
<?php
if (!defined('ABSPATH')) {
exit;
}
class Ansico_Diagnosekoder_Admin {
public static function init() {
add_action('admin_menu', [__CLASS__, 'register_admin_page']);
add_action('admin_post_ansico_diagnosekoder_save_settings', [__CLASS__, 'handle_save_settings']);
add_action('admin_post_ansico_diagnosekoder_import_data', [__CLASS__, 'handle_import_data']);
add_action('admin_post_ansico_diagnosekoder_remove_data', [__CLASS__, 'handle_remove_data']);
add_action('admin_post_ansico_diagnosekoder_remove_favorite', [__CLASS__, 'handle_remove_favorite']);
add_action('admin_post_ansico_diagnosekoder_remove_link', [__CLASS__, 'handle_remove_link']);
}
public static function register_admin_page() {
add_options_page(
__('Ansico Diagnosekoder', 'ansico-diagnosekoder'),
__('Ansico Diagnosekoder', 'ansico-diagnosekoder'),
'manage_options',
'ansico-diagnosekoder',
[__CLASS__, 'render_admin_page']
);
}
public static function render_admin_page() {
if (!current_user_can('manage_options')) {
return;
}
$meta = get_option(ANSICO_DIAGNOSEKODER_OPTION_META, []);
$results_url = get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '');
$status = isset($_GET['status']) ? sanitize_key(wp_unslash($_GET['status'])) : '';
$favorite_rows = self::get_results_page_favorite_rows();
$link_rows = self::get_results_page_link_rows();
?>
<div class="wrap">
<h1><?php esc_html_e('Ansico Diagnosekoder', 'ansico-diagnosekoder'); ?></h1>
<?php if ($status === 'success') : ?>
<div class="notice notice-success is-dismissible"><p><?php esc_html_e('Filen blev importeret.', 'ansico-diagnosekoder'); ?></p></div>
<?php elseif ($status === 'settings_saved') : ?>
<div class="notice notice-success is-dismissible"><p><?php esc_html_e('Indstillingerne blev gemt.', 'ansico-diagnosekoder'); ?></p></div>
<?php elseif ($status === 'data_removed') : ?>
<div class="notice notice-success is-dismissible"><p><?php esc_html_e('Datakilden blev fjernet.', 'ansico-diagnosekoder'); ?></p></div>
<?php elseif ($status === 'no_file') : ?>
<div class="notice notice-warning is-dismissible"><p><?php esc_html_e('Vælg en ny fil for at importere og erstatte det eksisterende datagrundlag.', 'ansico-diagnosekoder'); ?></p></div>
<?php elseif ($status === 'favorite_removed') : ?>
<div class="notice notice-success is-dismissible"><p><?php esc_html_e('Favoritten blev fjernet.', 'ansico-diagnosekoder'); ?></p></div>
<?php elseif ($status === 'link_removed') : ?>
<div class="notice notice-success is-dismissible"><p><?php esc_html_e('URL-tilknytningen blev fjernet.', 'ansico-diagnosekoder'); ?></p></div>
<?php elseif ($status === 'error') : ?>
<div class="notice notice-error is-dismissible"><p><?php echo esc_html(get_transient('ansico_diagnosekoder_admin_error') ?: __('Importen mislykkedes.', 'ansico-diagnosekoder')); ?></p></div>
<?php endif; ?>
<h2><?php esc_html_e('Favoritter på resultatsiden', 'ansico-diagnosekoder'); ?></h2>
<?php if (!empty($favorite_rows)) : ?>
<table class="widefat striped" style="max-width: 1100px; margin-bottom: 24px;">
<thead>
<tr>
<th><?php esc_html_e('Kode', 'ansico-diagnosekoder'); ?></th>
<th><?php esc_html_e('Beskrivelse', 'ansico-diagnosekoder'); ?></th>
<th style="width: 120px;"><?php esc_html_e('Handling', 'ansico-diagnosekoder'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($favorite_rows as $row) : ?>
<tr>
<td><strong><?php echo esc_html($row['code']); ?></strong></td>
<td><?php echo esc_html($row['text']); ?></td>
<td>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<?php wp_nonce_field('ansico_diagnosekoder_remove_favorite_' . $row['code']); ?>
<input type="hidden" name="action" value="ansico_diagnosekoder_remove_favorite" />
<input type="hidden" name="code" value="<?php echo esc_attr($row['code']); ?>" />
<?php submit_button(__('Fjern', 'ansico-diagnosekoder'), 'secondary small', '', false); ?>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else : ?>
<p><?php esc_html_e('Der er endnu ikke gemt nogen side-favoritter for den valgte resultatside.', 'ansico-diagnosekoder'); ?></p>
<?php endif; ?>
<h2><?php esc_html_e('Kode-URL-tilknytninger på resultatsiden', 'ansico-diagnosekoder'); ?></h2>
<?php if (!empty($link_rows)) : ?>
<table class="widefat striped" style="max-width: 1200px; margin-bottom: 24px;">
<thead>
<tr>
<th><?php esc_html_e('Kode', 'ansico-diagnosekoder'); ?></th>
<th><?php esc_html_e('Beskrivelse', 'ansico-diagnosekoder'); ?></th>
<th><?php esc_html_e('URL', 'ansico-diagnosekoder'); ?></th>
<th style="width: 120px;"><?php esc_html_e('Handling', 'ansico-diagnosekoder'); ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($link_rows as $row) : ?>
<tr>
<td><strong><?php echo esc_html($row['code']); ?></strong></td>
<td><?php echo esc_html($row['text']); ?></td>
<td><a href="<?php echo esc_url($row['url']); ?>"><?php echo esc_html($row['url']); ?></a></td>
<td>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<?php wp_nonce_field('ansico_diagnosekoder_remove_link_' . $row['code']); ?>
<input type="hidden" name="action" value="ansico_diagnosekoder_remove_link" />
<input type="hidden" name="code" value="<?php echo esc_attr($row['code']); ?>" />
<?php submit_button(__('Fjern', 'ansico-diagnosekoder'), 'secondary small', '', false); ?>
</form>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php else : ?>
<p><?php esc_html_e('Der er endnu ikke gemt nogen kode-URL-tilknytninger for den valgte resultatside.', 'ansico-diagnosekoder'); ?></p>
<?php endif; ?>
<h2><?php esc_html_e('Aktuelt datagrundlag', 'ansico-diagnosekoder'); ?></h2>
<?php if (!empty($meta)) : ?>
<table class="widefat striped" style="max-width: 900px;">
<tbody>
<tr>
<td><strong><?php esc_html_e('Kilde', 'ansico-diagnosekoder'); ?></strong></td>
<td><?php echo esc_html($meta['source_name'] ?? ''); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e('Importeret', 'ansico-diagnosekoder'); ?></strong></td>
<td><?php echo esc_html($meta['imported_at'] ?? ''); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e('Antal rækker', 'ansico-diagnosekoder'); ?></strong></td>
<td><?php echo esc_html((string) ($meta['row_count'] ?? 0)); ?></td>
</tr>
<tr>
<td><strong><?php esc_html_e('Header fundet', 'ansico-diagnosekoder'); ?></strong></td>
<td><?php echo !empty($meta['header_found']) ? esc_html__('Ja', 'ansico-diagnosekoder') : esc_html__('Nej', 'ansico-diagnosekoder'); ?></td>
</tr>
</tbody>
</table>
<?php else : ?>
<p><?php esc_html_e('Ingen data importeret endnu.', 'ansico-diagnosekoder'); ?></p>
<?php endif; ?>
<h2><?php esc_html_e('Datakilde', 'ansico-diagnosekoder'); ?></h2>
<p><?php esc_html_e('Upload en tekstfil med SKS/ICD-10 koder. En ny import erstatter kun det eksisterende datagrundlag, hvis der er valgt en ny fil.', 'ansico-diagnosekoder'); ?></p>
<div style="display:flex; align-items:flex-end; gap:8px; flex-wrap:wrap; margin-bottom:40px;">
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" enctype="multipart/form-data" style="margin:0;">
<?php wp_nonce_field('ansico_diagnosekoder_import_data'); ?>
<input type="hidden" name="action" value="ansico_diagnosekoder_import_data" />
<table class="form-table" role="presentation">
<tr>
<th scope="row"><label for="ansico_diagnosekoder_file"><?php esc_html_e('Datafil', 'ansico-diagnosekoder'); ?></label></th>
<td>
<input type="file" name="ansico_diagnosekoder_file" id="ansico_diagnosekoder_file" accept=".txt,.csv,text/plain" />
<p class="description"><?php esc_html_e('Forventet format: semikolon-separeret tekstfil med kolonnerne "Kode" og "Tekst".', 'ansico-diagnosekoder'); ?></p>
</td>
</tr>
</table>
<?php submit_button(__('Importer datakilde', 'ansico-diagnosekoder'), 'primary', 'submit', false); ?>
</form>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" onsubmit="return confirm('<?php echo esc_js(__('Er du sikker på, at du vil fjerne datakilden?', 'ansico-diagnosekoder')); ?>');" style="margin:0 0 8px 0;">
<?php wp_nonce_field('ansico_diagnosekoder_remove_data'); ?>
<input type="hidden" name="action" value="ansico_diagnosekoder_remove_data" />
<?php submit_button(__('Fjern datakilde', 'ansico-diagnosekoder'), 'delete', 'submit', false); ?>
</form>
</div>
<h2><?php esc_html_e('Opsætning', 'ansico-diagnosekoder'); ?></h2>
<form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
<?php wp_nonce_field('ansico_diagnosekoder_save_settings'); ?>
<input type="hidden" name="action" value="ansico_diagnosekoder_save_settings" />
<table class="form-table" role="presentation">
<tr>
<th scope="row"><label for="ansico_diagnosekoder_results_url"><?php esc_html_e('URL til resultatside', 'ansico-diagnosekoder'); ?></label></th>
<td>
<input type="url" name="ansico_diagnosekoder_results_url" id="ansico_diagnosekoder_results_url" class="regular-text code" value="<?php echo esc_attr($results_url); ?>" placeholder="https://example.dk/diagnosekoder/" />
<p class="description"><?php esc_html_e('Bruges af blokken med kun søgefelt. Ved submit sendes brugeren til denne side med søgetermen i URL-parameteren q.', 'ansico-diagnosekoder'); ?></p>
</td>
</tr>
</table>
<?php submit_button(__('Gem indstillinger', 'ansico-diagnosekoder')); ?>
</form>
</div>
<?php
delete_transient('ansico_diagnosekoder_admin_error');
}
public static function handle_save_settings() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Du har ikke rettigheder til dette.', 'ansico-diagnosekoder'));
}
check_admin_referer('ansico_diagnosekoder_save_settings');
$results_url = isset($_POST['ansico_diagnosekoder_results_url']) ? esc_url_raw(wp_unslash($_POST['ansico_diagnosekoder_results_url'])) : '';
update_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, $results_url, false);
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'settings_saved',
], admin_url('options-general.php')));
exit;
}
public static function handle_import_data() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Du har ikke rettigheder til dette.', 'ansico-diagnosekoder'));
}
check_admin_referer('ansico_diagnosekoder_import_data');
if (empty($_FILES['ansico_diagnosekoder_file']) || empty($_FILES['ansico_diagnosekoder_file']['tmp_name'])) {
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'no_file',
], admin_url('options-general.php')));
exit;
}
$file = $_FILES['ansico_diagnosekoder_file'];
$overrides = [
'test_form' => false,
'mimes' => [
'txt' => 'text/plain',
'csv' => 'text/plain',
],
];
require_once ABSPATH . 'wp-admin/includes/file.php';
$uploaded = wp_handle_upload($file, $overrides);
if (!empty($uploaded['error'])) {
self::redirect_with_error($uploaded['error']);
}
$parsed = Ansico_Diagnosekoder_Parser::parse_file($uploaded['file']);
if (!empty($parsed['meta']['error'])) {
self::redirect_with_error($parsed['meta']['error']);
}
if (empty($parsed['rows'])) {
self::redirect_with_error(__('Filen indeholdt ingen importerbare diagnosekoder.', 'ansico-diagnosekoder'));
}
update_option(ANSICO_DIAGNOSEKODER_OPTION_DATA, $parsed['rows'], false);
update_option(ANSICO_DIAGNOSEKODER_OPTION_META, $parsed['meta'], false);
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'success',
], admin_url('options-general.php')));
exit;
}
public static function handle_remove_data() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Du har ikke rettigheder til dette.', 'ansico-diagnosekoder'));
}
check_admin_referer('ansico_diagnosekoder_remove_data');
delete_option(ANSICO_DIAGNOSEKODER_OPTION_DATA);
delete_option(ANSICO_DIAGNOSEKODER_OPTION_META);
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'data_removed',
], admin_url('options-general.php')));
exit;
}
public static function handle_remove_favorite() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Du har ikke rettigheder til dette.', 'ansico-diagnosekoder'));
}
$code = isset($_POST['code']) ? sanitize_text_field(wp_unslash($_POST['code'])) : '';
if ($code === '') {
self::redirect_with_error(__('Der mangler en kode.', 'ansico-diagnosekoder'));
}
check_admin_referer('ansico_diagnosekoder_remove_favorite_' . $code);
$results_page_id = self::get_results_page_id();
if (!$results_page_id) {
self::redirect_with_error(__('Resultatsiden kunne ikke findes.', 'ansico-diagnosekoder'));
}
$favorites = Ansico_Diagnosekoder_REST::get_page_favorites($results_page_id);
$normalized_code = strtoupper(preg_replace('/\s+/', '', $code));
$favorites = array_values(array_filter($favorites, static function ($item) use ($normalized_code) {
return $item !== $normalized_code;
}));
update_post_meta($results_page_id, ANSICO_DIAGNOSEKODER_PAGE_FAVORITES_META, $favorites);
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'favorite_removed',
], admin_url('options-general.php')));
exit;
}
public static function handle_remove_link() {
if (!current_user_can('manage_options')) {
wp_die(esc_html__('Du har ikke rettigheder til dette.', 'ansico-diagnosekoder'));
}
$code = isset($_POST['code']) ? sanitize_text_field(wp_unslash($_POST['code'])) : '';
if ($code === '') {
self::redirect_with_error(__('Der mangler en kode.', 'ansico-diagnosekoder'));
}
check_admin_referer('ansico_diagnosekoder_remove_link_' . $code);
$results_page_id = self::get_results_page_id();
if (!$results_page_id) {
self::redirect_with_error(__('Resultatsiden kunne ikke findes.', 'ansico-diagnosekoder'));
}
$normalized_code = strtoupper(preg_replace('/\s+/', '', $code));
$links = Ansico_Diagnosekoder_REST::get_page_links($results_page_id);
unset($links[$normalized_code]);
update_post_meta($results_page_id, ANSICO_DIAGNOSEKODER_PAGE_LINKS_META, $links);
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'link_removed',
], admin_url('options-general.php')));
exit;
}
protected static function get_results_page_favorite_rows() {
$results_page_id = self::get_results_page_id();
if (!$results_page_id) {
return [];
}
return Ansico_Diagnosekoder_Parser::get_rows_by_codes(Ansico_Diagnosekoder_REST::get_page_favorites($results_page_id));
}
protected static function get_results_page_id() {
$results_url = (string) get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '');
if ($results_url === '') {
return 0;
}
$page_id = url_to_postid($results_url);
return absint($page_id);
}
protected static function get_results_page_link_rows() {
$results_page_id = self::get_results_page_id();
if (!$results_page_id) {
return [];
}
$links = Ansico_Diagnosekoder_REST::get_page_links($results_page_id);
if (empty($links)) {
return [];
}
$rows = Ansico_Diagnosekoder_Parser::get_rows_by_codes(array_keys($links));
foreach ($rows as &$row) {
$row['url'] = isset($links[$row['code']]) ? $links[$row['code']] : '';
}
unset($row);
return $rows;
}
protected static function redirect_with_error($message) {
set_transient('ansico_diagnosekoder_admin_error', wp_strip_all_tags((string) $message), 60);
wp_safe_redirect(add_query_arg([
'page' => 'ansico-diagnosekoder',
'status' => 'error',
], admin_url('options-general.php')));
exit;
}
}

View file

@ -0,0 +1,350 @@
<?php
if (!defined('ABSPATH')) {
exit;
}
class Ansico_Diagnosekoder_Block {
public static function init() {
add_action('init', [__CLASS__, 'register_assets']);
add_action('init', [__CLASS__, 'register_block']);
}
public static function register_assets() {
wp_register_script(
'ansico-diagnosekoder-block-editor',
ANSICO_DIAGNOSEKODER_PLUGIN_URL . 'assets/js/block.js',
['wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n', 'wp-block-editor'],
ANSICO_DIAGNOSEKODER_VERSION,
true
);
wp_register_script(
'ansico-diagnosekoder-frontend',
ANSICO_DIAGNOSEKODER_PLUGIN_URL . 'assets/js/frontend.js',
[],
ANSICO_DIAGNOSEKODER_VERSION,
true
);
wp_localize_script('ansico-diagnosekoder-frontend', 'AnsicoDiagnosekoderConfig', [
'restUrl' => esc_url_raw(rest_url('ansico-diagnosekoder/v1/search')),
'favoritesUrl' => esc_url_raw(rest_url('ansico-diagnosekoder/v1/favorites')),
'pageStateUrl' => esc_url_raw(rest_url('ansico-diagnosekoder/v1/page-state')),
'contentSearchUrl' => esc_url_raw(rest_url('ansico-diagnosekoder/v1/content-search')),
'linksUrl' => esc_url_raw(rest_url('ansico-diagnosekoder/v1/links')),
'resultsUrl' => esc_url_raw((string) get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '')),
'nonce' => wp_create_nonce('wp_rest'),
'isLoggedIn' => is_user_logged_in(),
'resultsPageId' => self::get_results_page_id(),
'strings' => [
'placeholder' => __('Søg efter diagnosekode eller beskrivelse', 'ansico-diagnosekoder'),
'empty' => __('Skriv for at søge i diagnosekoder.', 'ansico-diagnosekoder'),
'noResults' => __('Ingen resultater fundet.', 'ansico-diagnosekoder'),
'loading' => __('Søger...', 'ansico-diagnosekoder'),
'error' => __('Der opstod en fejl under søgningen.', 'ansico-diagnosekoder'),
'goToResults' => __('Gå til søgeresultater', 'ansico-diagnosekoder'),
'missingResultsUrl' => __('Resultatsidens URL er ikke angivet i pluginets indstillinger.', 'ansico-diagnosekoder'),
'copyCode' => __('Kopiér kode og beskrivelse', 'ansico-diagnosekoder'),
'copied' => __('Kopieret', 'ansico-diagnosekoder'),
'copyError' => __('Kunne ikke kopiere', 'ansico-diagnosekoder'),
'copyCodeAria' => __('Kopiér %s', 'ansico-diagnosekoder'),
'addFavorite' => __('Tilføj til favoritter', 'ansico-diagnosekoder'),
'removeFavorite' => __('Fjern fra favoritter', 'ansico-diagnosekoder'),
'favoriteAdded' => __('Favorit gemt', 'ansico-diagnosekoder'),
'favoriteRemoved' => __('Favorit fjernet', 'ansico-diagnosekoder'),
'favoriteError' => __('Kunne ikke gemme favorit', 'ansico-diagnosekoder'),
'copyIcon' => __('Kopiér', 'ansico-diagnosekoder'),
'favoriteIcon' => __('Favorit', 'ansico-diagnosekoder'),
'addLink' => __('Tilknyt URL', 'ansico-diagnosekoder'),
'removeLink' => __('Fjern URL-tilknytning', 'ansico-diagnosekoder'),
'linkSaved' => __('URL gemt', 'ansico-diagnosekoder'),
'linkRemoved' => __('URL fjernet', 'ansico-diagnosekoder'),
'linkError' => __('Kunne ikke gemme URL', 'ansico-diagnosekoder'),
'linkPrompt' => __('Indtast URL for %s', 'ansico-diagnosekoder'),
'linkPromptDefault' => __('https://', 'ansico-diagnosekoder'),
'openLink' => __('Åbn link', 'ansico-diagnosekoder'),
'linkIcon' => __('Link', 'ansico-diagnosekoder'),
'addLinkIcon' => __('Tilknyt URL', 'ansico-diagnosekoder'),
'removeLinkIcon' => __('Fjern URL', 'ansico-diagnosekoder'),
'linkModalTitleAdd' => __('Tilknyt link til kode', 'ansico-diagnosekoder'),
'linkModalTitleEdit' => __('Rediger link til kode', 'ansico-diagnosekoder'),
'linkModalCodeLabel' => __('Diagnosekode', 'ansico-diagnosekoder'),
'linkModalUrlLabel' => __('URL-adresse', 'ansico-diagnosekoder'),
'linkModalSearchLabel' => __('Søg efter interne sider', 'ansico-diagnosekoder'),
'linkModalSearchPlaceholder' => __('Søg efter side eller indlæg', 'ansico-diagnosekoder'),
'linkModalSearchEmpty' => __('Skriv for at søge efter interne sider.', 'ansico-diagnosekoder'),
'linkModalSearchNone' => __('Ingen interne sider fundet.', 'ansico-diagnosekoder'),
'linkModalChoose' => __('Vælg', 'ansico-diagnosekoder'),
'linkModalCancel' => __('Annuller', 'ansico-diagnosekoder'),
'linkModalSave' => __('Gem link', 'ansico-diagnosekoder'),
'linkModalOpen' => __('Åbn link-dialog', 'ansico-diagnosekoder'),
'linkModalHint' => __('Du kan enten indsætte en URL eller vælge en intern side.', 'ansico-diagnosekoder'),
'linkSearchError' => __('Kunne ikke søge efter interne sider.', 'ansico-diagnosekoder'),
],
]);
wp_register_style(
'ansico-diagnosekoder-style',
ANSICO_DIAGNOSEKODER_PLUGIN_URL . 'assets/css/style.css',
[],
ANSICO_DIAGNOSEKODER_VERSION
);
}
public static function register_block() {
register_block_type('ansico/diagnosekoder', [
'api_version' => 2,
'editor_script' => 'ansico-diagnosekoder-block-editor',
'style' => 'ansico-diagnosekoder-style',
'script' => 'ansico-diagnosekoder-frontend',
'render_callback' => [__CLASS__, 'render_block'],
]);
register_block_type('ansico/diagnosekoder-soegefelt', [
'api_version' => 2,
'editor_script' => 'ansico-diagnosekoder-block-editor',
'style' => 'ansico-diagnosekoder-style',
'script' => 'ansico-diagnosekoder-frontend',
'render_callback' => [__CLASS__, 'render_search_form_block'],
]);
register_block_type('ansico/diagnosekoder-kodekort', [
'api_version' => 2,
'editor_script' => 'ansico-diagnosekoder-block-editor',
'style' => 'ansico-diagnosekoder-style',
'render_callback' => [__CLASS__, 'render_linked_code_block'],
]);
}
public static function render_block($attributes = [], $content = '', $block = null) {
$meta = get_option(ANSICO_DIAGNOSEKODER_OPTION_META, []);
$input_id = wp_unique_id('ansico-diagnosekoder-input-');
$page_id = self::get_current_page_id();
if (!$page_id) {
$page_id = self::get_results_page_id();
}
$favorites = Ansico_Diagnosekoder_REST::get_page_favorites($page_id);
$links = Ansico_Diagnosekoder_REST::get_page_links($page_id);
$page_state = wp_json_encode([
'pageId' => absint($page_id),
'favorites' => array_values($favorites),
'links' => $links,
]);
$preset_query = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
$initial_results = $preset_query !== '' ? Ansico_Diagnosekoder_Parser::search($preset_query, 50, $favorites, $links) : [];
ob_start();
?>
<div class="wp-block-ansico-diagnosekoder ansico-diagnosekoder" data-has-data="<?php echo !empty($meta['row_count']) ? '1' : '0'; ?>" data-page-id="<?php echo esc_attr((string) absint($page_id)); ?>" data-page-favorites='<?php echo esc_attr(wp_json_encode(array_values($favorites))); ?>' data-page-links='<?php echo esc_attr(wp_json_encode($links)); ?>'>
<script type="application/json" class="ansico-diagnosekoder__page-state"><?php echo wp_json_encode([
'pageId' => absint($page_id),
'favorites' => array_values($favorites),
'links' => $links,
'query' => $preset_query,
'results' => $initial_results,
'hasInitialResults' => $preset_query !== '' && !empty($initial_results),
]); ?></script>
<div class="ansico-diagnosekoder__search">
<label class="screen-reader-text" for="<?php echo esc_attr($input_id); ?>"><?php esc_html_e('Søg diagnosekode', 'ansico-diagnosekoder'); ?></label>
<input
id="<?php echo esc_attr($input_id); ?>"
type="search"
class="ansico-diagnosekoder__input"
placeholder="<?php esc_attr_e('Søg efter diagnosekode eller beskrivelse', 'ansico-diagnosekoder'); ?>"
autocomplete="off"
value="<?php echo esc_attr($preset_query); ?>"
/>
</div>
<div class="ansico-diagnosekoder__results" aria-live="polite">
<?php if ($preset_query !== '' && !empty($initial_results)) : ?>
<ul class="ansico-diagnosekoder__list">
<?php foreach ($initial_results as $item) :
$normalized_code = strtoupper(preg_replace('/\s+/', '', (string) $item['code']));
$is_favorite = !empty($item['is_favorite']);
$linked_url = !empty($item['linked_url']) ? (string) $item['linked_url'] : '';
$has_link = $linked_url !== '';
$copy_value = (string) $item['code'] . ' - ' . (string) $item['text'];
$copy_aria = sprintf(__('Kopiér %s', 'ansico-diagnosekoder'), $copy_value);
?>
<li class="ansico-diagnosekoder__item<?php echo $is_favorite ? ' is-favorite' : ''; ?><?php echo $has_link ? ' has-link' : ''; ?>" data-code="<?php echo esc_attr($normalized_code); ?>" data-is-favorite="<?php echo $is_favorite ? '1' : '0'; ?>" data-has-link="<?php echo $has_link ? '1' : '0'; ?>">
<div class="ansico-diagnosekoder__row">
<?php if ($has_link) : ?><a class="ansico-diagnosekoder__entry-link" href="<?php echo esc_url($linked_url); ?>"><?php endif; ?>
<div class="ansico-diagnosekoder__entry">
<span class="ansico-diagnosekoder__code"><?php echo esc_html($item['code']); ?></span>
<span class="ansico-diagnosekoder__separator"> </span>
<span class="ansico-diagnosekoder__text"><?php echo esc_html($item['text']); ?></span>
<?php if ($has_link) : ?><span class="ansico-diagnosekoder__linked-badge"><?php esc_html_e('Åbn link', 'ansico-diagnosekoder'); ?></span><?php endif; ?>
</div>
<?php if ($has_link) : ?></a><?php endif; ?>
<div class="ansico-diagnosekoder__actions">
<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__copy-button" data-copy-value="<?php echo esc_attr($copy_value); ?>" data-label-default="<?php echo esc_attr($copy_aria); ?>" data-label-success="<?php esc_attr_e('Kopieret', 'ansico-diagnosekoder'); ?>" data-label-error="<?php esc_attr_e('Kunne ikke kopiere', 'ansico-diagnosekoder'); ?>" aria-label="<?php echo esc_attr($copy_aria); ?>" title="<?php esc_attr_e('Kopiér', 'ansico-diagnosekoder'); ?>">
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M16 1H6c-1.1 0-2 .9-2 2v12h2V3h10V1zm3 4H10c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h9c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H10V7h9v14z"></path></svg>
</button>
<?php if (is_user_logged_in()) : ?>
<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__favorite-button<?php echo $is_favorite ? ' is-active' : ''; ?>" data-code="<?php echo esc_attr($normalized_code); ?>" aria-pressed="<?php echo $is_favorite ? 'true' : 'false'; ?>" data-label-default="<?php echo esc_attr($is_favorite ? __('Fjern fra favoritter', 'ansico-diagnosekoder') : __('Tilføj til favoritter', 'ansico-diagnosekoder')); ?>" aria-label="<?php echo esc_attr($is_favorite ? __('Fjern fra favoritter', 'ansico-diagnosekoder') : __('Tilføj til favoritter', 'ansico-diagnosekoder')); ?>" title="<?php esc_attr_e('Favorit', 'ansico-diagnosekoder'); ?>">
<?php if ($is_favorite) : ?><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="currentColor"></path></svg><?php else : ?><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" fill="none"><path d="M12 17.27 18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"></path></svg><?php endif; ?>
</button>
<button type="button" class="ansico-diagnosekoder__icon-button ansico-diagnosekoder__link-button<?php echo $has_link ? ' is-active' : ''; ?>" data-code="<?php echo esc_attr($normalized_code); ?>" data-current-url="<?php echo esc_attr($linked_url); ?>" data-label-default="<?php echo esc_attr($has_link ? __('Fjern URL-tilknytning', 'ansico-diagnosekoder') : __('Tilknyt URL', 'ansico-diagnosekoder')); ?>" aria-label="<?php echo esc_attr($has_link ? __('Fjern URL-tilknytning', 'ansico-diagnosekoder') : __('Tilknyt URL', 'ansico-diagnosekoder')); ?>" title="<?php echo esc_attr($has_link ? __('Fjern URL', 'ansico-diagnosekoder') : __('Tilknyt URL', 'ansico-diagnosekoder')); ?>">
<?php if ($has_link) : ?><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 11H5v2h14z"></path></svg><?php else : ?><svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M19 11H13V5h-2v6H5v2h6v6h2v-6h6z"></path></svg><?php endif; ?>
</button>
<?php endif; ?>
</div>
</div>
</li>
<?php endforeach; ?>
</ul>
<?php else : ?>
<p class="ansico-diagnosekoder__message">
<?php
if ($preset_query !== '') {
esc_html_e('Ingen resultater fundet.', 'ansico-diagnosekoder');
} elseif (!empty($meta['row_count'])) {
esc_html_e('Skriv for at søge i diagnosekoder.', 'ansico-diagnosekoder');
} else {
esc_html_e('Der er endnu ikke importeret et datagrundlag i pluginets indstillinger.', 'ansico-diagnosekoder');
}
?>
</p>
<?php endif; ?>
</div>
</div>
<?php
return ob_get_clean();
}
public static function render_search_form_block($attributes = [], $content = '', $block = null) {
$results_url = (string) get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '');
$input_id = wp_unique_id('ansico-diagnosekoder-form-input-');
ob_start();
?>
<form class="wp-block-ansico-diagnosekoder-soegefelt ansico-diagnosekoder ansico-diagnosekoder--search-only" data-results-url="<?php echo esc_url($results_url); ?>">
<div class="ansico-diagnosekoder__search ansico-diagnosekoder__search--inline">
<label class="screen-reader-text" for="<?php echo esc_attr($input_id); ?>"><?php esc_html_e('Søg diagnosekode', 'ansico-diagnosekoder'); ?></label>
<input
id="<?php echo esc_attr($input_id); ?>"
type="search"
name="q"
class="ansico-diagnosekoder__input"
placeholder="<?php esc_attr_e('Søg efter diagnosekode eller beskrivelse', 'ansico-diagnosekoder'); ?>"
autocomplete="off"
/>
<button type="submit" class="ansico-diagnosekoder__submit"><?php esc_html_e('Søg', 'ansico-diagnosekoder'); ?></button>
</div>
<?php if (empty($results_url)) : ?>
<p class="ansico-diagnosekoder__message"><?php esc_html_e('Angiv først URL til resultatsiden under Indstillinger → Ansico Diagnosekoder.', 'ansico-diagnosekoder'); ?></p>
<?php endif; ?>
</form>
<?php
return ob_get_clean();
}
public static function render_linked_code_block($attributes = [], $content = '', $block = null) {
$current_page_id = self::get_current_page_id();
if (!$current_page_id) {
return '';
}
$current_url = self::normalize_url(get_permalink($current_page_id));
if ($current_url === '') {
return '';
}
$results_page_id = self::get_results_page_id();
if (!$results_page_id) {
return '';
}
$links = Ansico_Diagnosekoder_REST::get_page_links($results_page_id);
if (empty($links) || !is_array($links)) {
return '';
}
$matched_codes = [];
foreach ($links as $code => $url) {
if (self::normalize_url($url) === $current_url) {
$matched_codes[] = $code;
}
}
if (empty($matched_codes)) {
return '';
}
$rows = Ansico_Diagnosekoder_Parser::get_rows_by_codes($matched_codes);
if (empty($rows)) {
return '';
}
ob_start();
?>
<div class="wp-block-ansico-diagnosekoder-kodekort ansico-diagnosekoder-kodekort">
<div class="ansico-diagnosekoder-kodekort__list">
<?php foreach ($rows as $row) : ?>
<div class="ansico-diagnosekoder-kodekort__item">
<span class="ansico-diagnosekoder-kodekort__code"><?php echo esc_html($row['code']); ?></span>
<span class="ansico-diagnosekoder-kodekort__separator"> </span>
<span class="ansico-diagnosekoder-kodekort__text"><?php echo esc_html($row['text']); ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<?php
return ob_get_clean();
}
protected static function normalize_url($url) {
$url = trim((string) $url);
if ($url === '') {
return '';
}
$url = esc_url_raw($url);
if ($url === '') {
return '';
}
$parts = wp_parse_url($url);
if (!is_array($parts) || empty($parts['host'])) {
return untrailingslashit($url);
}
$scheme = !empty($parts['scheme']) ? strtolower($parts['scheme']) : 'https';
$host = strtolower($parts['host']);
$port = !empty($parts['port']) ? ':' . (int) $parts['port'] : '';
$path = isset($parts['path']) ? untrailingslashit($parts['path']) : '';
$query = isset($parts['query']) && $parts['query'] !== '' ? '?' . $parts['query'] : '';
return $scheme . '://' . $host . $port . $path . $query;
}
protected static function get_results_page_id() {
$results_url = (string) get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '');
if ($results_url === '') {
return 0;
}
return absint(url_to_postid($results_url));
}
protected static function get_current_page_id() {
$page_id = 0;
if (function_exists('get_queried_object_id')) {
$page_id = absint(get_queried_object_id());
}
if (!$page_id) {
$page_id = absint(get_the_ID());
}
global $post;
if (!$page_id && isset($post->ID)) {
$page_id = absint($post->ID);
}
return $page_id;
}
}

View file

@ -0,0 +1,198 @@
<?php
if (!defined('ABSPATH')) {
exit;
}
class Ansico_Diagnosekoder_Parser {
public static function parse_file($file_path) {
if (!file_exists($file_path) || !is_readable($file_path)) {
return [
'rows' => [],
'meta' => [
'error' => __('Filen kunne ikke læses.', 'ansico-diagnosekoder'),
],
];
}
$handle = fopen($file_path, 'r');
if (!$handle) {
return [
'rows' => [],
'meta' => [
'error' => __('Filen kunne ikke åbnes.', 'ansico-diagnosekoder'),
],
];
}
$rows = [];
$header_found = false;
$line_number = 0;
while (($line = fgets($handle)) !== false) {
$line_number++;
$line = trim($line);
if ($line === '') {
continue;
}
$columns = str_getcsv($line, ';', '"', '\\');
if (!is_array($columns) || count($columns) < 2) {
continue;
}
$col1 = isset($columns[0]) ? trim((string) $columns[0]) : '';
$col2 = isset($columns[1]) ? trim((string) $columns[1]) : '';
if (!$header_found) {
if (strcasecmp($col1, 'Kode') === 0 && strcasecmp($col2, 'Tekst') === 0) {
$header_found = true;
}
continue;
}
if ($col1 === '' || $col2 === '') {
continue;
}
$rows[] = [
'code' => sanitize_text_field($col1),
'text' => sanitize_text_field($col2),
];
}
fclose($handle);
return [
'rows' => $rows,
'meta' => [
'imported_at' => current_time('mysql'),
'row_count' => count($rows),
'source_name' => basename($file_path),
'header_found' => $header_found,
'line_count' => $line_number,
],
];
}
public static function search($query, $limit = 50, $favorite_codes = [], $links = []) {
$query = trim((string) $query);
if ($query === '') {
return [];
}
$data = get_option(ANSICO_DIAGNOSEKODER_OPTION_DATA, []);
if (!is_array($data) || empty($data)) {
return [];
}
$limit = $limit > 0 ? min($limit, 100) : 50;
$query_lower = function_exists('mb_strtolower') ? mb_strtolower($query, 'UTF-8') : strtolower($query);
$favorite_lookup = [];
foreach ((array) $favorite_codes as $favorite_code) {
$favorite_lookup[self::normalize_code($favorite_code)] = true;
}
$link_lookup = is_array($links) ? $links : [];
$results = [];
foreach ($data as $index => $row) {
if (!is_array($row) || empty($row['code']) || empty($row['text'])) {
continue;
}
$code = (string) $row['code'];
$text = (string) $row['text'];
$normalized_code = self::normalize_code($code);
$haystack_code = function_exists('mb_strtolower') ? mb_strtolower($code, 'UTF-8') : strtolower($code);
$haystack_text = function_exists('mb_strtolower') ? mb_strtolower($text, 'UTF-8') : strtolower($text);
if (strpos($haystack_code, $query_lower) === false && strpos($haystack_text, $query_lower) === false) {
continue;
}
$results[] = [
'code' => $code,
'text' => $text,
'is_favorite' => isset($favorite_lookup[$normalized_code]),
'linked_url' => isset($link_lookup[$normalized_code]) ? $link_lookup[$normalized_code] : '',
'_original_index' => $index,
];
}
if (empty($results)) {
return [];
}
usort($results, static function ($a, $b) {
$a_favorite = !empty($a['is_favorite']);
$b_favorite = !empty($b['is_favorite']);
if ($a_favorite !== $b_favorite) {
return $a_favorite ? -1 : 1;
}
return ((int) ($a['_original_index'] ?? 0)) <=> ((int) ($b['_original_index'] ?? 0));
});
foreach ($results as &$result) {
unset($result['_original_index']);
}
unset($result);
return array_slice($results, 0, $limit);
}
public static function get_rows_by_codes($codes = []) {
$normalized_codes = [];
foreach ((array) $codes as $code) {
$normalized = self::normalize_code($code);
if ($normalized !== '') {
$normalized_codes[] = $normalized;
}
}
$normalized_codes = array_values(array_unique($normalized_codes));
if (empty($normalized_codes)) {
return [];
}
$lookup = array_fill_keys($normalized_codes, true);
$data = get_option(ANSICO_DIAGNOSEKODER_OPTION_DATA, []);
if (!is_array($data) || empty($data)) {
return [];
}
$rows = [];
foreach ($data as $row) {
if (!is_array($row) || empty($row['code']) || empty($row['text'])) {
continue;
}
$code = (string) $row['code'];
$normalized_code = self::normalize_code($code);
if (!isset($lookup[$normalized_code])) {
continue;
}
$rows[$normalized_code] = [
'code' => $code,
'text' => (string) $row['text'],
];
}
$ordered = [];
foreach ($normalized_codes as $normalized_code) {
if (isset($rows[$normalized_code])) {
$ordered[] = $rows[$normalized_code];
}
}
return $ordered;
}
protected static function normalize_code($code) {
$code = sanitize_text_field((string) $code);
$code = preg_replace('/\s+/', '', $code);
return strtoupper((string) $code);
}
}

View file

@ -0,0 +1,387 @@
<?php
if (!defined('ABSPATH')) {
exit;
}
class Ansico_Diagnosekoder_REST {
public static function init() {
add_action('rest_api_init', [__CLASS__, 'register_routes']);
}
public static function register_routes() {
register_rest_route('ansico-diagnosekoder/v1', '/search', [
'methods' => WP_REST_Server::READABLE,
'callback' => [__CLASS__, 'search'],
'permission_callback' => '__return_true',
'args' => [
'q' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'limit' => [
'type' => 'integer',
'required' => false,
'default' => 50,
'sanitize_callback' => 'absint',
],
'page_id' => [
'type' => 'integer',
'required' => false,
'default' => 0,
'sanitize_callback' => 'absint',
],
],
]);
register_rest_route('ansico-diagnosekoder/v1', '/page-state', [
'methods' => WP_REST_Server::READABLE,
'callback' => [__CLASS__, 'page_state'],
'permission_callback' => '__return_true',
'args' => [
'page_id' => [
'type' => 'integer',
'required' => false,
'default' => 0,
'sanitize_callback' => 'absint',
],
],
]);
register_rest_route('ansico-diagnosekoder/v1', '/content-search', [
'methods' => WP_REST_Server::READABLE,
'callback' => [__CLASS__, 'content_search'],
'permission_callback' => static function () {
return is_user_logged_in();
},
'args' => [
'q' => [
'type' => 'string',
'required' => false,
'sanitize_callback' => 'sanitize_text_field',
],
'limit' => [
'type' => 'integer',
'required' => false,
'default' => 8,
'sanitize_callback' => 'absint',
],
],
]);
register_rest_route('ansico-diagnosekoder/v1', '/favorites', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [__CLASS__, 'toggle_favorite'],
'permission_callback' => static function () {
return is_user_logged_in();
},
'args' => [
'code' => [
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
],
'page_id' => [
'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint',
],
],
]);
register_rest_route('ansico-diagnosekoder/v1', '/links', [
'methods' => WP_REST_Server::CREATABLE,
'callback' => [__CLASS__, 'save_link'],
'permission_callback' => static function () {
return is_user_logged_in();
},
'args' => [
'code' => [
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
],
'url' => [
'type' => 'string',
'required' => true,
],
'page_id' => [
'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint',
],
],
]);
register_rest_route('ansico-diagnosekoder/v1', '/links', [
'methods' => WP_REST_Server::DELETABLE,
'callback' => [__CLASS__, 'remove_link'],
'permission_callback' => static function () {
return is_user_logged_in();
},
'args' => [
'code' => [
'type' => 'string',
'required' => true,
'sanitize_callback' => 'sanitize_text_field',
],
'page_id' => [
'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint',
],
],
]);
}
public static function search(WP_REST_Request $request) {
$query = (string) $request->get_param('q');
$limit = (int) $request->get_param('limit');
$page_id = absint($request->get_param('page_id'));
if (!$page_id) {
$page_id = self::get_results_page_id();
}
$limit = $limit > 0 ? min($limit, 100) : 50;
$favorite_codes = self::get_page_favorites($page_id);
$links = self::get_page_links($page_id);
$response = rest_ensure_response([
'query' => $query,
'results' => Ansico_Diagnosekoder_Parser::search($query, $limit, $favorite_codes, $links),
'meta' => get_option(ANSICO_DIAGNOSEKODER_OPTION_META, []),
'favorites' => $favorite_codes,
'links' => $links,
'is_logged_in' => is_user_logged_in(),
'page_id' => $page_id,
]);
$response->header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
$response->header('Pragma', 'no-cache');
return $response;
}
public static function page_state(WP_REST_Request $request) {
$page_id = absint($request->get_param('page_id'));
if (!$page_id) {
$page_id = self::get_results_page_id();
}
$response = rest_ensure_response([
'page_id' => $page_id,
'favorites' => self::get_page_favorites($page_id),
'links' => self::get_page_links($page_id),
]);
$response->header('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0');
$response->header('Pragma', 'no-cache');
return $response;
}
public static function content_search(WP_REST_Request $request) {
$query = trim((string) $request->get_param('q'));
$limit = (int) $request->get_param('limit');
$limit = $limit > 0 ? min($limit, 20) : 8;
if ($query === '') {
return rest_ensure_response(['results' => []]);
}
$all_post_types = get_post_types([], 'objects');
$excluded_types = ['attachment', 'revision', 'nav_menu_item', 'custom_css', 'customize_changeset', 'oembed_cache', 'user_request', 'wp_block', 'wp_navigation', 'wp_template', 'wp_template_part', 'wp_global_styles', 'wp_font_family', 'wp_font_face'];
$post_types = [];
foreach ($all_post_types as $post_type => $object) {
if (in_array($post_type, $excluded_types, true)) {
continue;
}
if (strpos($post_type, 'wp_') === 0) {
continue;
}
// Include posts, pages, and all custom post types that can reasonably have frontend URLs,
// even when the CPT is excluded from normal WordPress search.
if (!empty($object->public) || !empty($object->publicly_queryable) || !empty($object->show_ui)) {
$post_types[] = $post_type;
}
}
$post_types = array_values(array_unique($post_types));
if (empty($post_types)) {
$post_types = ['page', 'post'];
}
$posts = get_posts([
'post_type' => $post_types,
'post_status' => 'publish',
's' => $query,
'posts_per_page' => $limit,
'orderby' => 'relevance',
'order' => 'DESC',
'suppress_filters' => false,
]);
$results = [];
foreach ($posts as $post) {
$results[] = [
'id' => (int) $post->ID,
'title' => get_the_title($post),
'url' => get_permalink($post),
'type' => get_post_type($post),
];
}
return rest_ensure_response(['results' => $results]);
}
public static function toggle_favorite(WP_REST_Request $request) {
$code = self::normalize_code((string) $request->get_param('code'));
$page_id = absint($request->get_param('page_id'));
if (!$page_id) {
$page_id = self::get_results_page_id();
}
if ($code === '') {
return new WP_Error('ansico_empty_code', __('Der mangler en kode.', 'ansico-diagnosekoder'), ['status' => 400]);
}
if (!$page_id || get_post_status($page_id) === false) {
return new WP_Error('ansico_invalid_page', __('Der mangler en gyldig side.', 'ansico-diagnosekoder'), ['status' => 400]);
}
$favorites = self::get_page_favorites($page_id);
$index = array_search($code, $favorites, true);
$is_favorite = false;
if ($index === false) {
$favorites[] = $code;
$is_favorite = true;
} else {
unset($favorites[$index]);
$favorites = array_values($favorites);
}
update_post_meta($page_id, ANSICO_DIAGNOSEKODER_PAGE_FAVORITES_META, $favorites);
return rest_ensure_response([
'code' => $code,
'is_favorite' => $is_favorite,
'favorites' => $favorites,
'page_id' => $page_id,
]);
}
public static function get_page_favorites($page_id) {
$page_id = absint($page_id);
if (!$page_id) {
return [];
}
$favorites = get_post_meta($page_id, ANSICO_DIAGNOSEKODER_PAGE_FAVORITES_META, true);
if (!is_array($favorites)) {
return [];
}
$favorites = array_map([__CLASS__, 'normalize_code'], $favorites);
return array_values(array_unique(array_filter($favorites)));
}
public static function save_link(WP_REST_Request $request) {
$code = self::normalize_code((string) $request->get_param('code'));
$url = esc_url_raw((string) $request->get_param('url'));
$page_id = absint($request->get_param('page_id'));
if (!$page_id) {
$page_id = self::get_results_page_id();
}
if ($code === '') {
return new WP_Error('ansico_empty_code', __('Der mangler en kode.', 'ansico-diagnosekoder'), ['status' => 400]);
}
if (!$url || !wp_http_validate_url($url)) {
return new WP_Error('ansico_invalid_url', __('URL-adressen er ikke gyldig.', 'ansico-diagnosekoder'), ['status' => 400]);
}
if (!$page_id || get_post_status($page_id) === false) {
return new WP_Error('ansico_invalid_page', __('Der mangler en gyldig side.', 'ansico-diagnosekoder'), ['status' => 400]);
}
$links = self::get_page_links($page_id);
$links[$code] = $url;
update_post_meta($page_id, ANSICO_DIAGNOSEKODER_PAGE_LINKS_META, $links);
return rest_ensure_response([
'code' => $code,
'url' => $url,
'links' => $links,
'page_id' => $page_id,
]);
}
public static function remove_link(WP_REST_Request $request) {
$code = self::normalize_code((string) $request->get_param('code'));
$page_id = absint($request->get_param('page_id'));
if (!$page_id) {
$page_id = self::get_results_page_id();
}
if (!$page_id || get_post_status($page_id) === false) {
return new WP_Error('ansico_invalid_page', __('Der mangler en gyldig side.', 'ansico-diagnosekoder'), ['status' => 400]);
}
$links = self::get_page_links($page_id);
if ($code === '') {
return new WP_Error('ansico_empty_code', __('Der mangler en kode.', 'ansico-diagnosekoder'), ['status' => 400]);
}
unset($links[$code]);
update_post_meta($page_id, ANSICO_DIAGNOSEKODER_PAGE_LINKS_META, $links);
return rest_ensure_response([
'code' => $code,
'links' => $links,
'page_id' => $page_id,
]);
}
public static function get_page_links($page_id) {
$page_id = absint($page_id);
if (!$page_id) {
return [];
}
$links = get_post_meta($page_id, ANSICO_DIAGNOSEKODER_PAGE_LINKS_META, true);
if (!is_array($links)) {
return [];
}
$normalized = [];
foreach ($links as $code => $url) {
$normalized_code = self::normalize_code((string) $code);
$normalized_url = esc_url_raw((string) $url);
if ($normalized_code === '' || $normalized_url === '' || !wp_http_validate_url($normalized_url)) {
continue;
}
$normalized[$normalized_code] = $normalized_url;
}
return $normalized;
}
protected static function get_results_page_id() {
$results_url = (string) get_option(ANSICO_DIAGNOSEKODER_OPTION_RESULTS_URL, '');
if ($results_url === '') {
return 0;
}
return absint(url_to_postid($results_url));
}
protected static function normalize_code($code) {
$code = sanitize_text_field((string) $code);
$code = preg_replace('/\s+/', '', $code);
return strtoupper((string) $code);
}
}