Ansico-diagnosekoder/ansico-diagnosekoder/includes/class-ansico-diagnosekoder-rest.php
2026-04-19 00:06:24 +02:00

387 lines
13 KiB
PHP

<?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);
}
}