1294 lines
63 KiB
PHP
1294 lines
63 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: Ansico Lægenoter plugins
|
||
* Plugin URI: https://ansico.dk
|
||
* Support URI: https://ansico.dk/Ansico/Ansico-LN-plugins
|
||
* Description: Plugins til at forbedre lægenoter.
|
||
* Version: 1.0.0
|
||
* Requires at least: 6.0
|
||
* Tested up to: 6.9.4
|
||
* Requires PHP: 7.0
|
||
* Author: Andreas Andersen (Ansico)
|
||
* Author URI: https://ansico.dk
|
||
* Author URI: https://ansico.dk
|
||
* License: GPL v3 or later
|
||
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
||
* Text Domain: ansico-ln-plugins
|
||
*/
|
||
|
||
if (!defined('ABSPATH')) {
|
||
exit;
|
||
}
|
||
|
||
final class Ansico_LN_Plugins {
|
||
const VERSION = '1.0.0';
|
||
const OPTION_KEY = 'ansico_ln_plugins_settings';
|
||
|
||
private static $block_replaced = false;
|
||
private static $toc_assets_needed = false;
|
||
|
||
public function __construct() {
|
||
add_action('init', array($this, 'ensure_default_settings'));
|
||
add_action('init', array($this, 'register_taxonomiliste_block'));
|
||
add_action('pre_get_posts', array($this, 'include_post_types_in_search'));
|
||
add_filter('template_include', array($this, 'template_include'));
|
||
add_filter('render_block', array($this, 'render_block_content'), 10, 2);
|
||
add_filter('the_content', array($this, 'inject_table_of_contents'), 20);
|
||
add_filter('the_content', array($this, 'inject_citations_list'), 30);
|
||
add_filter('author_link', array($this, 'filter_author_link'), 10, 3);
|
||
add_filter('get_the_author_posts_link', array($this, 'filter_author_posts_link'));
|
||
add_filter('the_author_posts_link', array($this, 'filter_author_posts_link'));
|
||
add_filter('get_the_date', array($this, 'filter_the_date'), 10, 3);
|
||
|
||
add_action('wp_enqueue_scripts', array($this, 'register_frontend_assets'));
|
||
add_action('wp_footer', array($this, 'print_toc_assets'), 30);
|
||
add_action('wp_head', array($this, 'print_meta_visibility_css'), 99);
|
||
add_action('wp_footer', array($this, 'print_meta_visibility_script'), 99);
|
||
|
||
add_action('admin_menu', array($this, 'register_settings_page'));
|
||
add_action('admin_init', array($this, 'register_settings'));
|
||
}
|
||
|
||
public function ensure_default_settings() {
|
||
update_option(self::OPTION_KEY, self::get_settings());
|
||
}
|
||
|
||
public function register_frontend_assets() {
|
||
wp_register_style('ansico-ln-frontend', false, array(), self::VERSION);
|
||
}
|
||
|
||
public function print_toc_assets() {
|
||
if (!self::$toc_assets_needed) {
|
||
return;
|
||
}
|
||
?>
|
||
<style id="ansico-ln-toc-style">
|
||
.ansico-ln-toc {
|
||
margin: 2.1rem 0 1.6rem;
|
||
padding: 0.9rem 1rem;
|
||
border: 1px solid rgba(0,0,0,.12);
|
||
border-radius: 8px;
|
||
display: inline-block;
|
||
width: fit-content;
|
||
max-width: calc(100% - 10px);
|
||
background: rgba(0,0,0,.02);
|
||
}
|
||
.ansico-ln-toc details { display:block; }
|
||
.ansico-ln-toc summary {
|
||
cursor: pointer;
|
||
font-weight: 700;
|
||
list-style: none;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: .75rem;
|
||
}
|
||
.ansico-ln-toc summary::-webkit-details-marker { display: none; }
|
||
.ansico-ln-toc-summary-text { flex: 1 1 auto; }
|
||
.ansico-ln-toc-summary-indicator {
|
||
margin-left: auto;
|
||
font-size: .9em;
|
||
flex: 0 0 auto;
|
||
}
|
||
.ansico-ln-toc-nav { margin-top: 0.6rem; }
|
||
.ansico-ln-toc-list { margin: 0; }
|
||
.ansico-ln-toc-list--bullets { padding-left: 1.15rem; list-style: disc; }
|
||
.ansico-ln-toc-list--numbered { padding-left: 0; list-style: none; }
|
||
.ansico-ln-toc-list li { margin: 0.14rem 0; }
|
||
.ansico-ln-toc-list a { text-decoration: none; }
|
||
.ansico-ln-toc-list a:hover { text-decoration: underline; }
|
||
.ansico-ln-toc-level-2 { font-size: 1rem; }
|
||
.ansico-ln-toc-level-3 { font-size: .95rem; }
|
||
.ansico-ln-toc-level-4 { font-size: .9rem; }
|
||
.ansico-ln-toc-level-5 { font-size: .86rem; }
|
||
.ansico-ln-toc-level-6 { font-size: .82rem; }
|
||
.ansico-ln-toc-link.is-active { font-weight: 700; text-decoration: underline; }
|
||
.ansico-ln-taxonomy-list { list-style: none; padding-left: 0; margin: 0; }
|
||
.ansico-ln-taxonomy-list li { margin: .18rem 0; }
|
||
.ansico-ln-taxonomy-cloud { line-height: 1.75; }
|
||
.ansico-ln-taxonomy-cloud a {
|
||
display: inline-block;
|
||
margin: 0 .28rem .28rem 0;
|
||
text-decoration: none;
|
||
padding: .08rem .34rem;
|
||
border-radius: 999px;
|
||
background: rgba(0,0,0,.05);
|
||
}
|
||
.ansico-ln-taxonomy-cloud a:hover { background: rgba(0,0,0,.09); }
|
||
</style>
|
||
<script id="ansico-ln-toc-script">
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
document.querySelectorAll('.ansico-ln-toc details').forEach(function (details) {
|
||
var summary = details.querySelector('summary');
|
||
var indicator = summary ? summary.querySelector('.ansico-ln-toc-summary-indicator') : null;
|
||
var sync = function () {
|
||
if (indicator) indicator.textContent = details.open ? '−' : '+';
|
||
};
|
||
sync();
|
||
details.addEventListener('toggle', sync);
|
||
});
|
||
|
||
var links = Array.prototype.slice.call(document.querySelectorAll('.ansico-ln-toc-link[href^="#"]'));
|
||
if (!links.length || !('IntersectionObserver' in window)) return;
|
||
var byId = {};
|
||
links.forEach(function (link) {
|
||
byId[decodeURIComponent(link.getAttribute('href').slice(1))] = link;
|
||
});
|
||
var observer = new IntersectionObserver(function (entries) {
|
||
entries.forEach(function (entry) {
|
||
var id = entry.target.getAttribute('id');
|
||
var link = byId[id];
|
||
if (!link) return;
|
||
if (entry.isIntersecting) {
|
||
links.forEach(function (item) { item.classList.remove('is-active'); });
|
||
link.classList.add('is-active');
|
||
}
|
||
});
|
||
}, { rootMargin: '0px 0px -72% 0px', threshold: [0, 1] });
|
||
Object.keys(byId).forEach(function (id) {
|
||
var target = document.getElementById(id);
|
||
if (target) observer.observe(target);
|
||
});
|
||
});
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
public function register_taxonomiliste_block() {
|
||
if (!function_exists('register_block_type')) {
|
||
return;
|
||
}
|
||
|
||
$script_handle = 'ansico-ln-taxonomiliste-editor';
|
||
wp_register_script(
|
||
$script_handle,
|
||
plugins_url('blocks/taxonomiliste/editor.js', __FILE__),
|
||
array('wp-blocks', 'wp-element', 'wp-block-editor', 'wp-components', 'wp-i18n', 'wp-server-side-render'),
|
||
self::VERSION,
|
||
true
|
||
);
|
||
|
||
$taxonomies = array();
|
||
foreach (self::get_available_taxonomies_for_block() as $taxonomy) {
|
||
$taxonomies[] = array(
|
||
'slug' => $taxonomy->name,
|
||
'label' => $taxonomy->labels->name,
|
||
);
|
||
}
|
||
wp_localize_script($script_handle, 'AnsicoLNTaxonomilisteData', array('taxonomies' => $taxonomies));
|
||
|
||
register_block_type('ansico-ln/taxonomiliste', array(
|
||
'editor_script' => $script_handle,
|
||
'render_callback' => array($this, 'render_taxonomiliste_block'),
|
||
'attributes' => array(
|
||
'taxonomy' => array('type' => 'string', 'default' => ''),
|
||
'displayType' => array('type' => 'string', 'default' => 'list'),
|
||
'showCount' => array('type' => 'boolean', 'default' => false),
|
||
'showAll' => array('type' => 'boolean', 'default' => true),
|
||
'limit' => array('type' => 'number', 'default' => 20),
|
||
'sortBy' => array('type' => 'string', 'default' => 'alphabetical'),
|
||
),
|
||
));
|
||
}
|
||
|
||
public function render_taxonomiliste_block($attributes) {
|
||
$taxonomy = isset($attributes['taxonomy']) ? sanitize_key($attributes['taxonomy']) : '';
|
||
if (!$taxonomy || !taxonomy_exists($taxonomy)) {
|
||
return '';
|
||
}
|
||
|
||
$show_count = !empty($attributes['showCount']);
|
||
$show_all = !empty($attributes['showAll']);
|
||
$limit = !empty($attributes['limit']) ? max(1, absint($attributes['limit'])) : 20;
|
||
$sort_by = isset($attributes['sortBy']) && $attributes['sortBy'] === 'count' ? 'count' : 'alphabetical';
|
||
$display_type = isset($attributes['displayType']) && $attributes['displayType'] === 'cloud' ? 'cloud' : 'list';
|
||
|
||
$terms = get_terms(array(
|
||
'taxonomy' => $taxonomy,
|
||
'hide_empty' => false,
|
||
'number' => $show_all ? 0 : $limit,
|
||
'orderby' => $sort_by === 'count' ? 'count' : 'name',
|
||
'order' => $sort_by === 'count' ? 'DESC' : 'ASC',
|
||
));
|
||
|
||
if (is_wp_error($terms) || empty($terms)) {
|
||
return '';
|
||
}
|
||
|
||
ob_start();
|
||
if ($display_type === 'cloud') {
|
||
echo '<div class="ansico-ln-taxonomy-cloud">';
|
||
foreach ($terms as $term) {
|
||
$min = 0.92;
|
||
$max = 1.4;
|
||
$count = max(1, (int) $term->count);
|
||
$font_size = $sort_by === 'count'
|
||
? min($max, $min + (log($count + 1) * 0.16))
|
||
: $min + (($count > 1 ? min(3, log($count + 1)) : 0) * 0.08);
|
||
echo '<a href="' . esc_url(get_term_link($term)) . '" style="font-size:' . esc_attr(number_format((float) $font_size, 2, '.', '')) . 'rem;">';
|
||
echo esc_html($term->name);
|
||
if ($show_count) {
|
||
echo ' <span>(' . intval($term->count) . ')</span>';
|
||
}
|
||
echo '</a> ';
|
||
}
|
||
echo '</div>';
|
||
} else {
|
||
echo '<div class="ansico-ln-taxonomy-list-wrap"><ul class="ansico-ln-taxonomy-list">';
|
||
foreach ($terms as $term) {
|
||
echo '<li><a href="' . esc_url(get_term_link($term)) . '">' . esc_html($term->name) . '</a>';
|
||
if ($show_count) {
|
||
echo ' <span>(' . intval($term->count) . ')</span>';
|
||
}
|
||
echo '</li>';
|
||
}
|
||
echo '</ul></div>';
|
||
}
|
||
self::$toc_assets_needed = true;
|
||
return trim(ob_get_clean());
|
||
}
|
||
|
||
public function include_post_types_in_search($query) {
|
||
if (is_admin() || !$query->is_main_query() || !$query->is_search()) {
|
||
return;
|
||
}
|
||
$query->set('post_type', self::get_searchable_post_types());
|
||
}
|
||
|
||
public function template_include($template) {
|
||
if (self::is_block_theme_active()) {
|
||
return $template;
|
||
}
|
||
|
||
if (is_search()) {
|
||
$custom_template = plugin_dir_path(__FILE__) . 'templates/search.php';
|
||
if (file_exists($custom_template)) return $custom_template;
|
||
}
|
||
|
||
if (is_post_type_archive() && self::is_enabled_post_type_archive(self::get_current_archive_post_type())) {
|
||
$custom_template = plugin_dir_path(__FILE__) . 'templates/archive-post-type.php';
|
||
if (file_exists($custom_template)) return $custom_template;
|
||
}
|
||
|
||
if ((is_tax() || is_category() || is_tag()) && self::is_enabled_taxonomy_archive(self::get_current_taxonomy_name())) {
|
||
$custom_template = plugin_dir_path(__FILE__) . 'templates/archive-taxonomy.php';
|
||
if (file_exists($custom_template)) return $custom_template;
|
||
}
|
||
|
||
return $template;
|
||
}
|
||
|
||
public function render_block_content($block_content, $block) {
|
||
if (is_admin() || !self::is_block_theme_active() || empty($block['blockName'])) {
|
||
return $block_content;
|
||
}
|
||
|
||
if (in_array($block['blockName'], array('core/post-author', 'core/post-author-name', 'core/post-date'), true)) {
|
||
$post_id = 0;
|
||
if (!empty($block['attrs']['postId'])) {
|
||
$post_id = absint($block['attrs']['postId']);
|
||
} elseif (get_the_ID()) {
|
||
$post_id = get_the_ID();
|
||
}
|
||
|
||
if ($post_id) {
|
||
$post_type = get_post_type($post_id);
|
||
|
||
if (in_array($block['blockName'], array('core/post-author', 'core/post-author-name'), true) && self::should_hide_author_for_post_type($post_type)) {
|
||
return '';
|
||
}
|
||
|
||
if ($block['blockName'] === 'core/post-date' && self::should_hide_date_for_post_type($post_type)) {
|
||
return '';
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!self::should_replace_block_results()) {
|
||
self::$block_replaced = false;
|
||
return $block_content;
|
||
}
|
||
|
||
if (
|
||
(is_post_type_archive() || is_tax() || is_category() || is_tag()) &&
|
||
in_array($block['blockName'], array('core/query-title', 'core/archive-title', 'core/term-description'), true)
|
||
) {
|
||
return '';
|
||
}
|
||
|
||
if (!self::$block_replaced && $block['blockName'] === 'core/post-template') {
|
||
self::$block_replaced = true;
|
||
return self::get_block_theme_markup();
|
||
}
|
||
|
||
if (self::$block_replaced && in_array($block['blockName'], array('core/query-pagination', 'core/query-no-results'), true)) {
|
||
return '';
|
||
}
|
||
|
||
return $block_content;
|
||
}
|
||
|
||
|
||
public function print_meta_visibility_css() {
|
||
if (is_admin() || !is_singular()) {
|
||
return;
|
||
}
|
||
|
||
$post_type = self::get_context_post_type();
|
||
if (!$post_type) {
|
||
return;
|
||
}
|
||
|
||
$css = '';
|
||
|
||
if (self::should_hide_author_for_post_type($post_type)) {
|
||
$css .= '.author,.byline,.entry-author,.post-author,.wp-block-post-author,.wp-block-post-author-name,[class*="author-meta"],[class*="post-author"],[class*="byline"],[rel="author"],.wp-block-post-author__name,.wp-block-post-author__content{display:none !important;}';
|
||
$css .= '.wp-block-post-author:has(a),.wp-block-post-author:has([rel="author"]),.byline:has(a),.entry-meta:has([rel="author"]),[class*="author"]:has(a[href*="/author/"]){display:none !important;}';
|
||
$css .= '.meta-separator,.entry-meta .separator,.post-meta .separator,.wp-block-post-date + .separator,.wp-block-post-date + .meta-separator,.wp-block-post-date + span.separator,.wp-block-post-date + span.meta-separator,.wp-block-post-date + p,.wp-block-post-date + .wp-block-post-author::before,.wp-block-post-date + .wp-block-post-author-name::before{display:none !important;}';
|
||
}
|
||
|
||
if (self::should_hide_date_for_post_type($post_type)) {
|
||
$css .= '.posted-on,.entry-date,.post-date,.wp-block-post-date,time.entry-date,time.published,[class*="post-date"],[class*="entry-date"]{display:none !important;}';
|
||
}
|
||
|
||
if ($css !== '') {
|
||
echo '<style id="ansico-ln-meta-visibility">' . $css . '</style>';
|
||
}
|
||
}
|
||
|
||
|
||
public function print_meta_visibility_script() {
|
||
if (is_admin() || !is_singular()) {
|
||
return;
|
||
}
|
||
|
||
$post_type = self::get_context_post_type();
|
||
if (!$post_type || !self::should_hide_author_for_post_type($post_type)) {
|
||
return;
|
||
}
|
||
|
||
$author_archive = '';
|
||
$custom_url = trim((string) self::get_setting('author_custom_url', ''));
|
||
$author_id = get_post_field('post_author', get_the_ID());
|
||
if ($author_id) {
|
||
$author_archive = get_author_posts_url($author_id);
|
||
}
|
||
?>
|
||
<script id="ansico-ln-hide-author-script">
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
var selectors = [
|
||
'.wp-block-post-author',
|
||
'.wp-block-post-author-name',
|
||
'.author',
|
||
'.byline',
|
||
'.entry-author',
|
||
'.post-author',
|
||
'[class*="author-meta"]',
|
||
'[class*="post-author"]',
|
||
'[class*="byline"]'
|
||
];
|
||
|
||
selectors.forEach(function (selector) {
|
||
document.querySelectorAll(selector).forEach(function (el) {
|
||
el.style.display = 'none';
|
||
});
|
||
});
|
||
|
||
var possibleLinks = [];
|
||
document.querySelectorAll('a').forEach(function (link) {
|
||
var href = link.getAttribute('href') || '';
|
||
var rel = link.getAttribute('rel') || '';
|
||
if (rel.indexOf('author') !== -1) {
|
||
possibleLinks.push(link);
|
||
return;
|
||
}
|
||
var authorArchive = "";
|
||
var customUrl = "";
|
||
if ((authorArchive && href === authorArchive) || (customUrl && href === customUrl) || href.indexOf('/author/') !== -1) {
|
||
possibleLinks.push(link);
|
||
}
|
||
});
|
||
|
||
possibleLinks.forEach(function (link) {
|
||
var el = link;
|
||
for (var i = 0; i < 4 && el; i++) {
|
||
var cls = (el.className || '').toString();
|
||
if (
|
||
cls.indexOf('author') !== -1 ||
|
||
cls.indexOf('byline') !== -1 ||
|
||
cls.indexOf('meta') !== -1 ||
|
||
el.matches('span,p,div,li')
|
||
) {
|
||
el.style.display = 'none';
|
||
|
||
if (el.previousElementSibling) {
|
||
var prev = el.previousElementSibling;
|
||
var prevText = (prev.textContent || '').trim();
|
||
var prevCls = (prev.className || '').toString();
|
||
if (prevText === '•' || prevCls.indexOf('separator') !== -1 || prevCls.indexOf('meta-separator') !== -1) {
|
||
prev.style.display = 'none';
|
||
}
|
||
}
|
||
|
||
if (el.nextElementSibling) {
|
||
var next = el.nextElementSibling;
|
||
var nextText = (next.textContent || '').trim();
|
||
var nextCls = (next.className || '').toString();
|
||
if (nextText === '•' || nextCls.indexOf('separator') !== -1 || nextCls.indexOf('meta-separator') !== -1) {
|
||
next.style.display = 'none';
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
el = el.parentElement;
|
||
}
|
||
link.style.display = 'none';
|
||
});
|
||
|
||
document.querySelectorAll('.separator, .meta-separator, .wp-block-post-date + p').forEach(function (sep) {
|
||
var text = (sep.textContent || '').trim();
|
||
if (text === '•') {
|
||
var prevVisible = sep.previousElementSibling && getComputedStyle(sep.previousElementSibling).display !== 'none';
|
||
var nextVisible = sep.nextElementSibling && getComputedStyle(sep.nextElementSibling).display !== 'none';
|
||
if (!prevVisible || !nextVisible || (sep.previousElementSibling && sep.previousElementSibling.classList.contains('wp-block-post-date'))) {
|
||
sep.style.display = 'none';
|
||
}
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
public function register_settings_page() {
|
||
add_options_page(__('Ansico LN plugins', 'ansico-ln-plugins'), __('Ansico LN plugins', 'ansico-ln-plugins'), 'manage_options', 'ansico-ln-plugins', array($this, 'render_settings_page'));
|
||
}
|
||
|
||
public function register_settings() {
|
||
register_setting('ansico_ln_plugins_settings_group', self::OPTION_KEY, array($this, 'sanitize_settings'));
|
||
}
|
||
|
||
public function sanitize_settings($input) {
|
||
$existing = self::get_settings();
|
||
$sanitized = $existing;
|
||
|
||
$sanitized['hidden_post_types'] = array();
|
||
$sanitized['archive_post_types'] = array();
|
||
$sanitized['archive_taxonomies'] = array();
|
||
$sanitized['post_type_order'] = array();
|
||
$sanitized['toc_enabled'] = !empty($input['toc_enabled']) ? 1 : 0;
|
||
$sanitized['toc_title'] = isset($input['toc_title']) ? sanitize_text_field($input['toc_title']) : 'INDHOLD';
|
||
$sanitized['toc_post_types'] = array();
|
||
$sanitized['toc_min_headings'] = isset($input['toc_min_headings']) ? max(1, absint($input['toc_min_headings'])) : 3;
|
||
$sanitized['toc_list_type'] = (isset($input['toc_list_type']) && $input['toc_list_type'] === 'numbers') ? 'numbers' : 'bullets';
|
||
$sanitized['toc_collapsible'] = !empty($input['toc_collapsible']) ? 1 : 0;
|
||
$sanitized['toc_scrollspy'] = !empty($input['toc_scrollspy']) ? 1 : 0;
|
||
$sanitized['author_link_mode'] = (isset($input['author_link_mode']) && $input['author_link_mode'] === 'custom') ? 'custom' : 'archive';
|
||
$sanitized['author_custom_url'] = isset($input['author_custom_url']) ? esc_url_raw($input['author_custom_url']) : '';
|
||
$sanitized['hide_author_post_types'] = array();
|
||
$sanitized['hide_date_post_types'] = array();
|
||
$sanitized['modified_date_post_types'] = array();
|
||
$sanitized['citation_post_types'] = array();
|
||
|
||
foreach (self::get_available_post_types() as $post_type_name => $post_type_object) {
|
||
if (!empty($input['hidden_post_types']) && in_array($post_type_name, (array) $input['hidden_post_types'], true)) {
|
||
$sanitized['hidden_post_types'][] = $post_type_name;
|
||
}
|
||
if (!empty($input['archive_post_types']) && in_array($post_type_name, (array) $input['archive_post_types'], true)) {
|
||
$sanitized['archive_post_types'][] = $post_type_name;
|
||
}
|
||
if (!empty($input['toc_post_types']) && in_array($post_type_name, (array) $input['toc_post_types'], true)) {
|
||
$sanitized['toc_post_types'][] = $post_type_name;
|
||
}
|
||
if (!empty($input['hide_author_post_types']) && in_array($post_type_name, (array) $input['hide_author_post_types'], true)) {
|
||
$sanitized['hide_author_post_types'][] = $post_type_name;
|
||
}
|
||
if (!empty($input['hide_date_post_types']) && in_array($post_type_name, (array) $input['hide_date_post_types'], true)) {
|
||
$sanitized['hide_date_post_types'][] = $post_type_name;
|
||
}
|
||
if (!empty($input['modified_date_post_types']) && in_array($post_type_name, (array) $input['modified_date_post_types'], true)) {
|
||
$sanitized['modified_date_post_types'][] = $post_type_name;
|
||
}
|
||
if (!empty($input['citation_post_types']) && in_array($post_type_name, (array) $input['citation_post_types'], true)) {
|
||
$sanitized['citation_post_types'][] = $post_type_name;
|
||
}
|
||
$order = isset($input['post_type_order'][$post_type_name]) ? absint($input['post_type_order'][$post_type_name]) : 9999;
|
||
$sanitized['post_type_order'][$post_type_name] = $order;
|
||
}
|
||
|
||
foreach (self::get_available_taxonomies_for_settings() as $taxonomy_name => $taxonomy_object) {
|
||
if (!empty($input['archive_taxonomies']) && in_array($taxonomy_name, (array) $input['archive_taxonomies'], true)) {
|
||
$sanitized['archive_taxonomies'][] = $taxonomy_name;
|
||
}
|
||
}
|
||
|
||
return $sanitized;
|
||
}
|
||
|
||
public function render_settings_page() {
|
||
if (!current_user_can('manage_options')) return;
|
||
$settings = self::get_settings();
|
||
$post_types = self::get_ordered_available_post_types();
|
||
$taxonomies = self::get_available_taxonomies_for_settings();
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php echo esc_html__('Ansico LN plugins', 'ansico-ln-plugins'); ?></h1>
|
||
<form method="post" action="options.php">
|
||
<?php settings_fields('ansico_ln_plugins_settings_group'); ?>
|
||
|
||
<h2><?php echo esc_html__('Custom post types', 'ansico-ln-plugins'); ?></h2>
|
||
<table class="widefat striped" id="ansico-ln-post-types-table">
|
||
<thead><tr>
|
||
<th><?php echo esc_html__('Rækkefølge', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Post type', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Skjul i søgning', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Alfabetisk arkivside', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Skjul forfatter', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Skjul dato', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Brug opdateringsdato', 'ansico-ln-plugins'); ?></th>
|
||
<th><?php echo esc_html__('Indsæt citater', 'ansico-ln-plugins'); ?></th>
|
||
</tr></thead>
|
||
<tbody>
|
||
<?php $row_index = 1; foreach ($post_types as $post_type_name => $post_type_object) : ?>
|
||
<tr>
|
||
<td>
|
||
<button type="button" class="button ansico-ln-move-up" aria-label="Flyt op">↑</button>
|
||
<button type="button" class="button ansico-ln-move-down" aria-label="Flyt ned">↓</button>
|
||
<input type="hidden" name="<?php echo esc_attr(self::OPTION_KEY); ?>[post_type_order][<?php echo esc_attr($post_type_name); ?>]" value="<?php echo esc_attr($row_index); ?>" class="ansico-ln-order-input" />
|
||
</td>
|
||
<td><strong><?php echo esc_html($post_type_object->labels->name); ?></strong><br><code><?php echo esc_html($post_type_name); ?></code></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[hidden_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['hidden_post_types'], true)); ?>> <?php echo esc_html__('Skjul', 'ansico-ln-plugins'); ?></label></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[archive_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['archive_post_types'], true)); ?>> <?php echo esc_html__('Aktiver', 'ansico-ln-plugins'); ?></label></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[hide_author_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['hide_author_post_types'], true)); ?>> <?php echo esc_html__('Skjul', 'ansico-ln-plugins'); ?></label></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[hide_date_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['hide_date_post_types'], true)); ?>> <?php echo esc_html__('Skjul', 'ansico-ln-plugins'); ?></label></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[modified_date_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['modified_date_post_types'], true)); ?>> <?php echo esc_html__('Vis opdateret', 'ansico-ln-plugins'); ?></label></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[citation_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['citation_post_types'], true)); ?>> <?php echo esc_html__('Aktiver', 'ansico-ln-plugins'); ?></label></td>
|
||
</tr>
|
||
<?php $row_index++; endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
|
||
<h2 style="margin-top:2rem;"><?php echo esc_html__('Forfatter og dato', 'ansico-ln-plugins'); ?></h2>
|
||
<table class="form-table" role="presentation">
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Link på forfatternavn', 'ansico-ln-plugins'); ?></th>
|
||
<td>
|
||
<fieldset>
|
||
<label style="display:block;margin:.2rem 0;">
|
||
<input type="radio" name="<?php echo esc_attr(self::OPTION_KEY); ?>[author_link_mode]" value="archive" <?php checked($settings['author_link_mode'], 'archive'); ?>>
|
||
<?php echo esc_html__('Link til forfatterarkiv', 'ansico-ln-plugins'); ?>
|
||
</label>
|
||
<label style="display:block;margin:.2rem 0;">
|
||
<input type="radio" name="<?php echo esc_attr(self::OPTION_KEY); ?>[author_link_mode]" value="custom" <?php checked($settings['author_link_mode'], 'custom'); ?>>
|
||
<?php echo esc_html__('Link til bestemt side', 'ansico-ln-plugins'); ?>
|
||
</label>
|
||
<p style="margin:.5rem 0 0;">
|
||
<input type="url" class="regular-text" name="<?php echo esc_attr(self::OPTION_KEY); ?>[author_custom_url]" value="<?php echo esc_attr($settings['author_custom_url']); ?>" placeholder="https://example.com/forfattere/">
|
||
</p>
|
||
</fieldset>
|
||
</td>
|
||
</tr>
|
||
</table>
|
||
|
||
<h2 style="margin-top:2rem;"><?php echo esc_html__('Taxonomier', 'ansico-ln-plugins'); ?></h2>
|
||
<table class="widefat striped">
|
||
<thead><tr><th><?php echo esc_html__('Taxonomi', 'ansico-ln-plugins'); ?></th><th><?php echo esc_html__('Alfabetisk arkivside', 'ansico-ln-plugins'); ?></th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($taxonomies as $taxonomy_name => $taxonomy_object) : ?>
|
||
<tr>
|
||
<td><strong><?php echo esc_html($taxonomy_object->labels->name); ?></strong><br><code><?php echo esc_html($taxonomy_name); ?></code></td>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[archive_taxonomies][]" value="<?php echo esc_attr($taxonomy_name); ?>" <?php checked(in_array($taxonomy_name, $settings['archive_taxonomies'], true)); ?>> <?php echo esc_html__('Aktiver', 'ansico-ln-plugins'); ?></label></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
|
||
<h2 style="margin-top:2rem;"><?php echo esc_html__('Indholdsfortegnelse', 'ansico-ln-plugins'); ?></h2>
|
||
<table class="form-table" role="presentation">
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Aktivér automatisk indholdsfortegnelse', 'ansico-ln-plugins'); ?></th>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_enabled]" value="1" <?php checked(!empty($settings['toc_enabled'])); ?>> <?php echo esc_html__('Aktiver', 'ansico-ln-plugins'); ?></label></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Overskrift', 'ansico-ln-plugins'); ?></th>
|
||
<td><input type="text" class="regular-text" name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_title]" value="<?php echo esc_attr($settings['toc_title']); ?>"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Liste-type', 'ansico-ln-plugins'); ?></th>
|
||
<td>
|
||
<select name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_list_type]">
|
||
<option value="bullets" <?php selected($settings['toc_list_type'], 'bullets'); ?>><?php echo esc_html__('Punktopstilling', 'ansico-ln-plugins'); ?></option>
|
||
<option value="numbers" <?php selected($settings['toc_list_type'], 'numbers'); ?>><?php echo esc_html__('Talnummereret', 'ansico-ln-plugins'); ?></option>
|
||
</select>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Mindste antal overskrifter', 'ansico-ln-plugins'); ?></th>
|
||
<td><input type="number" min="1" name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_min_headings]" value="<?php echo esc_attr($settings['toc_min_headings']); ?>"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Gælder for post types', 'ansico-ln-plugins'); ?></th>
|
||
<td>
|
||
<?php foreach ($post_types as $post_type_name => $post_type_object) : ?>
|
||
<label style="display:block;margin:.2rem 0;"><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_post_types][]" value="<?php echo esc_attr($post_type_name); ?>" <?php checked(in_array($post_type_name, $settings['toc_post_types'], true)); ?>> <?php echo esc_html($post_type_object->labels->name); ?></label>
|
||
<?php endforeach; ?>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Foldbar indholdsfortegnelse', 'ansico-ln-plugins'); ?></th>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_collapsible]" value="1" <?php checked(!empty($settings['toc_collapsible'])); ?>> <?php echo esc_html__('Aktiver fold ud/fold sammen', 'ansico-ln-plugins'); ?></label></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row"><?php echo esc_html__('Markér aktiv sektion under scroll', 'ansico-ln-plugins'); ?></th>
|
||
<td><label><input type="checkbox" name="<?php echo esc_attr(self::OPTION_KEY); ?>[toc_scrollspy]" value="1" <?php checked(!empty($settings['toc_scrollspy'])); ?>> <?php echo esc_html__('Aktiver scrollspy', 'ansico-ln-plugins'); ?></label></td>
|
||
</tr>
|
||
</table>
|
||
|
||
<?php submit_button(); ?>
|
||
</form>
|
||
</div>
|
||
<script>
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
const table = document.getElementById('ansico-ln-post-types-table');
|
||
if (!table) return;
|
||
const updateOrder = function () {
|
||
table.querySelectorAll('tbody tr').forEach(function (row, index) {
|
||
const input = row.querySelector('.ansico-ln-order-input');
|
||
if (input) input.value = index + 1;
|
||
});
|
||
};
|
||
table.addEventListener('click', function (event) {
|
||
if (event.target.classList.contains('ansico-ln-move-up')) {
|
||
const row = event.target.closest('tr');
|
||
if (row && row.previousElementSibling) {
|
||
row.parentNode.insertBefore(row, row.previousElementSibling);
|
||
updateOrder();
|
||
}
|
||
}
|
||
if (event.target.classList.contains('ansico-ln-move-down')) {
|
||
const row = event.target.closest('tr');
|
||
if (row && row.nextElementSibling) {
|
||
row.parentNode.insertBefore(row.nextElementSibling, row);
|
||
updateOrder();
|
||
}
|
||
}
|
||
});
|
||
updateOrder();
|
||
});
|
||
</script>
|
||
<?php
|
||
}
|
||
|
||
public function inject_table_of_contents($content) {
|
||
if (is_admin() || !is_singular() || !in_the_loop() || !is_main_query()) {
|
||
return $content;
|
||
}
|
||
|
||
$settings = self::get_settings();
|
||
if (empty($settings['toc_enabled'])) {
|
||
return $content;
|
||
}
|
||
|
||
$post = get_post();
|
||
if (!$post || !in_array($post->post_type, $settings['toc_post_types'], true)) {
|
||
return $content;
|
||
}
|
||
|
||
$headings = self::extract_headings($content);
|
||
if (count($headings) < (int) $settings['toc_min_headings']) {
|
||
return $content;
|
||
}
|
||
|
||
$content_with_ids = self::add_heading_ids($content, $headings);
|
||
$toc_markup = self::build_toc_markup($headings, $settings);
|
||
if (!$toc_markup) {
|
||
return $content;
|
||
}
|
||
|
||
self::$toc_assets_needed = true;
|
||
$first_id = $headings[0]['id'];
|
||
$pattern = '/(<h[2-6][^>]*id="' . preg_quote($first_id, '/') . '"[^>]*>)/i';
|
||
return preg_replace($pattern, $toc_markup . '$1', $content_with_ids, 1);
|
||
}
|
||
|
||
public static function extract_headings($content) {
|
||
$headings = array();
|
||
if (!preg_match_all('/<h([2-6])([^>]*)>(.*?)<\/h\1>/is', $content, $matches, PREG_SET_ORDER)) {
|
||
return $headings;
|
||
}
|
||
$used_ids = array();
|
||
foreach ($matches as $index => $match) {
|
||
$level = (int) $match[1];
|
||
$text = trim(wp_strip_all_tags($match[3]));
|
||
if ($text === '') continue;
|
||
$base_id = sanitize_title($text);
|
||
if ($base_id === '') $base_id = 'overskrift-' . ($index + 1);
|
||
$id = $base_id;
|
||
$suffix = 2;
|
||
while (isset($used_ids[$id])) {
|
||
$id = $base_id . '-' . $suffix;
|
||
$suffix++;
|
||
}
|
||
$used_ids[$id] = true;
|
||
$headings[] = array('level' => $level, 'text' => $text, 'id' => $id);
|
||
}
|
||
return $headings;
|
||
}
|
||
|
||
public static function add_heading_ids($content, $headings) {
|
||
$i = 0;
|
||
return preg_replace_callback('/<h([2-6])([^>]*)>(.*?)<\/h\1>/is', function ($match) use ($headings, &$i) {
|
||
if (!isset($headings[$i])) return $match[0];
|
||
$heading = $headings[$i];
|
||
$attrs = $match[2];
|
||
if (preg_match('/\sid=("|\")(.*?)(\1)/i', $attrs)) {
|
||
$i++;
|
||
return $match[0];
|
||
}
|
||
$i++;
|
||
return '<h' . $match[1] . $attrs . ' id="' . esc_attr($heading['id']) . '">' . $match[3] . '</h' . $match[1] . '>';
|
||
}, $content);
|
||
}
|
||
|
||
public static function build_toc_markup($headings, $settings) {
|
||
if (empty($headings)) return '';
|
||
$title = !empty($settings['toc_title']) ? $settings['toc_title'] : 'INDHOLD';
|
||
$is_numbered = isset($settings['toc_list_type']) && $settings['toc_list_type'] === 'numbers';
|
||
$collapsible = !empty($settings['toc_collapsible']);
|
||
$scrollspy = !empty($settings['toc_scrollspy']);
|
||
|
||
$items = array();
|
||
$counters = array(2 => 0, 3 => 0, 4 => 0, 5 => 0, 6 => 0);
|
||
foreach ($headings as $heading) {
|
||
$level = (int) $heading['level'];
|
||
$counters[$level]++;
|
||
for ($reset = $level + 1; $reset <= 6; $reset++) {
|
||
$counters[$reset] = 0;
|
||
}
|
||
$number = '';
|
||
if ($is_numbered) {
|
||
$parts = array();
|
||
for ($l = 2; $l <= $level; $l++) {
|
||
if ($counters[$l] > 0) $parts[] = $counters[$l];
|
||
}
|
||
$number = implode('.', $parts);
|
||
}
|
||
$items[] = array_merge($heading, array('number' => $number));
|
||
}
|
||
|
||
ob_start();
|
||
echo '<nav class="ansico-ln-toc" aria-label="Indholdsfortegnelse">';
|
||
if ($collapsible) {
|
||
echo '<details open><summary><span class="ansico-ln-toc-summary-text">' . esc_html($title) . '</span><span class="ansico-ln-toc-summary-indicator" aria-hidden="true">−</span></summary><div class="ansico-ln-toc-nav">';
|
||
} else {
|
||
echo '<div class="ansico-ln-toc-title" style="font-weight:700;">' . esc_html($title) . '</div><div class="ansico-ln-toc-nav">';
|
||
}
|
||
|
||
echo $is_numbered ? '<ol class="ansico-ln-toc-list ansico-ln-toc-list--numbered">' : '<ul class="ansico-ln-toc-list ansico-ln-toc-list--bullets">';
|
||
foreach ($items as $item) {
|
||
$level = (int) $item['level'];
|
||
$indent = max(0, $level - 2) * 1.1;
|
||
echo '<li class="ansico-ln-toc-level-' . intval($level) . '" style="margin-left:' . esc_attr(number_format((float) $indent, 2, '.', '')) . 'rem;">';
|
||
echo '<a class="ansico-ln-toc-link' . ($scrollspy ? ' ansico-ln-toc-link--spy' : '') . '" href="#' . esc_attr($item['id']) . '">';
|
||
if ($is_numbered && $item['number'] !== '') {
|
||
echo '<span class="ansico-ln-toc-number">' . esc_html($item['number']) . '</span> ';
|
||
}
|
||
echo esc_html($item['text']) . '</a></li>';
|
||
}
|
||
echo $is_numbered ? '</ol>' : '</ul>';
|
||
echo '</div>';
|
||
if ($collapsible) echo '</details>';
|
||
echo '</nav>';
|
||
return trim(ob_get_clean());
|
||
}
|
||
|
||
|
||
|
||
public function inject_citations_list($content) {
|
||
if (is_admin() || !is_singular() || !in_the_loop() || !is_main_query()) {
|
||
return $content;
|
||
}
|
||
|
||
$post = get_post();
|
||
if (!$post || !self::should_insert_citations_for_post_type($post->post_type)) {
|
||
return $content;
|
||
}
|
||
|
||
$sources = self::extract_external_sources_from_content($content);
|
||
if (empty($sources)) {
|
||
return $content;
|
||
}
|
||
|
||
$items = array();
|
||
foreach ($sources as $source) {
|
||
$items[] = '<a href="' . esc_url($source['url']) . '" target="_blank" rel="noopener noreferrer">' . esc_html($source['label']) . '</a>';
|
||
}
|
||
|
||
$markup = '<div class="ansico-ln-citations" style="margin-top:1.5rem;">';
|
||
$markup .= '<strong>' . esc_html__('Citerede kilder:', 'ansico-ln-plugins') . '</strong> ';
|
||
$markup .= implode(', ', $items) . '.';
|
||
$markup .= '</div>';
|
||
|
||
return $content . $markup;
|
||
}
|
||
|
||
public static function extract_external_sources_from_content($content) {
|
||
$sources = array();
|
||
$home_host = wp_parse_url(home_url(), PHP_URL_HOST);
|
||
$home_host = $home_host ? preg_replace('/^www\./i', '', strtolower($home_host)) : '';
|
||
|
||
if (trim($content) === '') {
|
||
return $sources;
|
||
}
|
||
|
||
if (!class_exists('DOMDocument')) {
|
||
if (preg_match_all('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>/i', $content, $matches)) {
|
||
foreach ($matches[1] as $href) {
|
||
$parsed = self::normalize_external_source($href, $home_host);
|
||
if ($parsed && !empty($parsed['url'])) {
|
||
$sources[$parsed['url']] = $parsed;
|
||
}
|
||
}
|
||
}
|
||
return array_values($sources);
|
||
}
|
||
|
||
$internal_errors = libxml_use_internal_errors(true);
|
||
$doc = new DOMDocument();
|
||
$html = '<?xml encoding="utf-8" ?><div>' . $content . '</div>';
|
||
if ($doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)) {
|
||
foreach ($doc->getElementsByTagName('a') as $link) {
|
||
$href = $link->getAttribute('href');
|
||
$parsed = self::normalize_external_source($href, $home_host);
|
||
if ($parsed && !empty($parsed['url'])) {
|
||
$sources[$parsed['url']] = $parsed;
|
||
}
|
||
}
|
||
}
|
||
libxml_clear_errors();
|
||
libxml_use_internal_errors($internal_errors);
|
||
|
||
return array_values($sources);
|
||
}
|
||
|
||
public static function normalize_external_source($url, $home_host = '') {
|
||
$url = trim((string) $url);
|
||
if ($url === '' || strpos($url, '#') === 0) {
|
||
return null;
|
||
}
|
||
if (preg_match('/^(mailto:|tel:|javascript:)/i', $url)) {
|
||
return null;
|
||
}
|
||
if (strpos($url, '//') === 0) {
|
||
$url = is_ssl() ? 'https:' . $url : 'http:' . $url;
|
||
}
|
||
if (!preg_match('#^https?://#i', $url)) {
|
||
return null;
|
||
}
|
||
|
||
$host = wp_parse_url($url, PHP_URL_HOST);
|
||
if (!$host) {
|
||
return null;
|
||
}
|
||
$normalized_host = preg_replace('/^www\./i', '', strtolower($host));
|
||
if ($home_host && $normalized_host === $home_host) {
|
||
return null;
|
||
}
|
||
|
||
return array(
|
||
'url' => esc_url_raw($url),
|
||
'label' => $normalized_host,
|
||
);
|
||
}
|
||
|
||
public function filter_author_link($link, $author_id, $author_nicename) {
|
||
if (is_admin()) {
|
||
return $link;
|
||
}
|
||
$settings = self::get_settings();
|
||
if (($settings['author_link_mode'] ?? 'archive') === 'custom' && !empty($settings['author_custom_url'])) {
|
||
return esc_url($settings['author_custom_url']);
|
||
}
|
||
return $link;
|
||
}
|
||
|
||
public function filter_author_posts_link($link_html) {
|
||
if (is_admin()) {
|
||
return $link_html;
|
||
}
|
||
$post_type = self::get_context_post_type();
|
||
if ($post_type && self::should_hide_author_for_post_type($post_type)) {
|
||
return '';
|
||
}
|
||
return $link_html;
|
||
}
|
||
|
||
public function filter_the_date($the_date, $format, $post) {
|
||
if (is_admin()) {
|
||
return $the_date;
|
||
}
|
||
$post_obj = $post ? get_post($post) : get_post();
|
||
if (!$post_obj) {
|
||
return $the_date;
|
||
}
|
||
if (self::should_hide_date_for_post_type($post_obj->post_type)) {
|
||
return '';
|
||
}
|
||
if (self::should_use_modified_date_for_post_type($post_obj->post_type)) {
|
||
$format = $format ? $format : get_option('date_format');
|
||
return get_the_modified_date($format, $post_obj);
|
||
}
|
||
return $the_date;
|
||
}
|
||
|
||
public static function get_context_post_type() {
|
||
$post = get_post();
|
||
if ($post && !empty($post->post_type)) {
|
||
return $post->post_type;
|
||
}
|
||
if (is_singular()) {
|
||
$queried = get_queried_object();
|
||
if ($queried && !empty($queried->post_type)) {
|
||
return $queried->post_type;
|
||
}
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public static function should_hide_author_for_post_type($post_type) {
|
||
$settings = self::get_settings();
|
||
return !empty($post_type) && in_array($post_type, (array) $settings['hide_author_post_types'], true);
|
||
}
|
||
|
||
public static function should_hide_date_for_post_type($post_type) {
|
||
$settings = self::get_settings();
|
||
return !empty($post_type) && in_array($post_type, (array) $settings['hide_date_post_types'], true);
|
||
}
|
||
|
||
public static function should_use_modified_date_for_post_type($post_type) {
|
||
$settings = self::get_settings();
|
||
return !empty($post_type) && in_array($post_type, (array) $settings['modified_date_post_types'], true);
|
||
}
|
||
|
||
public static function should_insert_citations_for_post_type($post_type) {
|
||
$settings = self::get_settings();
|
||
return !empty($post_type) && in_array($post_type, (array) $settings['citation_post_types'], true);
|
||
}
|
||
|
||
public static function get_settings() {
|
||
$saved = get_option(self::OPTION_KEY, array());
|
||
$defaults = array(
|
||
'post_type_order' => array(),
|
||
'hidden_post_types' => array(),
|
||
'archive_post_types' => array(),
|
||
'archive_taxonomies' => array(),
|
||
'toc_enabled' => 0,
|
||
'toc_title' => 'INDHOLD',
|
||
'toc_post_types' => array('post', 'page'),
|
||
'toc_min_headings' => 3,
|
||
'toc_list_type' => 'bullets',
|
||
'toc_collapsible' => 1,
|
||
'toc_scrollspy' => 1,
|
||
'author_link_mode' => 'archive',
|
||
'author_custom_url' => '',
|
||
'hide_author_post_types' => array(),
|
||
'hide_date_post_types' => array(),
|
||
'modified_date_post_types'=> array(),
|
||
'citation_post_types' => array(),
|
||
);
|
||
$settings = wp_parse_args(is_array($saved) ? $saved : array(), $defaults);
|
||
foreach (self::get_available_post_types() as $post_type_name => $object) {
|
||
if (!isset($settings['post_type_order'][$post_type_name])) {
|
||
$settings['post_type_order'][$post_type_name] = count($settings['post_type_order']) + 1;
|
||
}
|
||
}
|
||
return $settings;
|
||
}
|
||
|
||
public static function get_available_post_types() {
|
||
$post_types = get_post_types(array('public' => true), 'objects');
|
||
foreach ($post_types as $name => $obj) {
|
||
if ($name === 'attachment' || (!$obj->publicly_queryable && !$obj->show_ui)) {
|
||
unset($post_types[$name]);
|
||
}
|
||
}
|
||
return $post_types;
|
||
}
|
||
|
||
public static function get_ordered_available_post_types() {
|
||
$post_types = self::get_available_post_types();
|
||
$settings = self::get_settings();
|
||
uasort($post_types, function ($a, $b) use ($settings) {
|
||
$order_a = isset($settings['post_type_order'][$a->name]) ? (int) $settings['post_type_order'][$a->name] : 9999;
|
||
$order_b = isset($settings['post_type_order'][$b->name]) ? (int) $settings['post_type_order'][$b->name] : 9999;
|
||
if ($order_a === $order_b) return strnatcasecmp($a->labels->name, $b->labels->name);
|
||
return $order_a - $order_b;
|
||
});
|
||
return $post_types;
|
||
}
|
||
|
||
public static function get_available_taxonomies_for_settings() {
|
||
$taxonomies = get_taxonomies(array('public' => true), 'objects');
|
||
foreach ($taxonomies as $taxonomy_name => $taxonomy_object) {
|
||
if (in_array($taxonomy_name, array('post_format', 'nav_menu', 'link_category'), true)) {
|
||
unset($taxonomies[$taxonomy_name]);
|
||
}
|
||
}
|
||
uasort($taxonomies, function ($a, $b) { return strnatcasecmp($a->labels->name, $b->labels->name); });
|
||
return $taxonomies;
|
||
}
|
||
|
||
public static function get_available_taxonomies_for_block() {
|
||
return self::get_available_taxonomies_for_settings();
|
||
}
|
||
|
||
public static function get_searchable_post_types() {
|
||
$settings = self::get_settings();
|
||
$post_types = self::get_ordered_available_post_types();
|
||
$searchable = array();
|
||
foreach ($post_types as $post_type_name => $obj) {
|
||
if (in_array($post_type_name, $settings['hidden_post_types'], true)) continue;
|
||
if (!empty($obj->exclude_from_search)) continue;
|
||
$searchable[] = $post_type_name;
|
||
}
|
||
return $searchable;
|
||
}
|
||
|
||
public static function get_grouped_search_results() {
|
||
$search_term = get_search_query();
|
||
$grouped_results = array();
|
||
$ordered_post_types = self::get_ordered_available_post_types();
|
||
$selected_post_types = self::get_searchable_post_types();
|
||
if (empty($selected_post_types) || $search_term === '') return array();
|
||
foreach ($ordered_post_types as $post_type_name => $post_type_object) {
|
||
if (in_array($post_type_name, $selected_post_types, true)) {
|
||
$grouped_results[$post_type_name] = array('label' => $post_type_object->labels->name, 'results' => array());
|
||
}
|
||
}
|
||
$search_query = new WP_Query(array(
|
||
'post_type' => $selected_post_types,
|
||
'post_status' => 'publish',
|
||
's' => $search_term,
|
||
'posts_per_page' => -1,
|
||
'orderby' => 'title',
|
||
'order' => 'ASC',
|
||
'ignore_sticky_posts' => true,
|
||
'no_found_rows' => true,
|
||
));
|
||
foreach ($search_query->posts as $post) {
|
||
if (isset($grouped_results[$post->post_type])) {
|
||
$grouped_results[$post->post_type]['results'][] = array('title' => get_the_title($post), 'url' => get_permalink($post));
|
||
}
|
||
}
|
||
wp_reset_postdata();
|
||
foreach ($grouped_results as $post_type_name => $group) {
|
||
if (empty($group['results'])) unset($grouped_results[$post_type_name]);
|
||
}
|
||
return $grouped_results;
|
||
}
|
||
|
||
public static function get_total_results_count($grouped_results = null) {
|
||
if (!is_array($grouped_results)) $grouped_results = self::get_grouped_search_results();
|
||
$total = 0; foreach ($grouped_results as $group) $total += count($group['results']);
|
||
return $total;
|
||
}
|
||
|
||
public static function get_total_results_text($total_results) {
|
||
return ((int) $total_results === 1) ? 'Fandt i alt 1 resultat.' : sprintf('Fandt i alt %d resultater.', (int) $total_results);
|
||
}
|
||
|
||
public static function render_group_results_list($results) {
|
||
if (empty($results)) return '';
|
||
$visible_results = array_slice($results, 0, 10);
|
||
$hidden_results = array_slice($results, 10);
|
||
ob_start();
|
||
echo '<ul>';
|
||
foreach ($visible_results as $result) echo '<li><a href="' . esc_url($result['url']) . '">' . esc_html($result['title']) . '</a></li>';
|
||
echo '</ul>';
|
||
if (!empty($hidden_results)) {
|
||
echo '<details class="ansico-ln-more-results"><summary>' . esc_html(sprintf('Vis alle %d resultater', count($results))) . '</summary><ul>';
|
||
foreach ($hidden_results as $result) echo '<li><a href="' . esc_url($result['url']) . '">' . esc_html($result['title']) . '</a></li>';
|
||
echo '</ul></details>';
|
||
}
|
||
return trim(ob_get_clean());
|
||
}
|
||
|
||
public static function render_simple_results_list($results) {
|
||
if (empty($results)) return '';
|
||
ob_start();
|
||
echo '<ul>';
|
||
foreach ($results as $result) echo '<li><a href="' . esc_url($result['url']) . '">' . esc_html($result['title']) . '</a></li>';
|
||
echo '</ul>';
|
||
return trim(ob_get_clean());
|
||
}
|
||
|
||
public static function get_current_archive_post_type() {
|
||
return is_post_type_archive() ? get_query_var('post_type') : '';
|
||
}
|
||
|
||
public static function get_current_taxonomy_name() {
|
||
if (is_tax() || is_category() || is_tag()) {
|
||
$term = get_queried_object();
|
||
if ($term && !empty($term->taxonomy)) return $term->taxonomy;
|
||
}
|
||
return '';
|
||
}
|
||
|
||
public static function is_enabled_post_type_archive($post_type) {
|
||
$settings = self::get_settings();
|
||
return !empty($post_type) && in_array($post_type, $settings['archive_post_types'], true);
|
||
}
|
||
|
||
public static function is_enabled_taxonomy_archive($taxonomy) {
|
||
$settings = self::get_settings();
|
||
return !empty($taxonomy) && in_array($taxonomy, $settings['archive_taxonomies'], true);
|
||
}
|
||
|
||
public static function get_post_type_label($post_type) {
|
||
$object = get_post_type_object($post_type);
|
||
return $object && !empty($object->labels->name) ? $object->labels->name : $post_type;
|
||
}
|
||
|
||
public static function get_archive_results($post_type) {
|
||
if (empty($post_type)) return array();
|
||
$query = new WP_Query(array('post_type' => $post_type, 'post_status' => 'publish', 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', 'ignore_sticky_posts' => true, 'no_found_rows' => true));
|
||
$results = array();
|
||
foreach ($query->posts as $post) $results[] = array('title' => get_the_title($post), 'url' => get_permalink($post));
|
||
wp_reset_postdata();
|
||
return $results;
|
||
}
|
||
|
||
public static function group_archive_results_by_letter($results) {
|
||
$alphabet = array_merge(array('#'), range('A', 'Z'), array('Æ', 'Ø', 'Å'));
|
||
$grouped = array();
|
||
foreach ($alphabet as $letter) $grouped[$letter] = array();
|
||
foreach ($results as $result) {
|
||
$title = isset($result['title']) ? $result['title'] : '';
|
||
$first = function_exists('mb_substr') ? mb_strtoupper(mb_substr(ltrim($title), 0, 1, 'UTF-8'), 'UTF-8') : strtoupper(substr(ltrim($title), 0, 1));
|
||
if (!in_array($first, $alphabet, true) || preg_match('/^[0-9\W]/u', $first)) $first = '#';
|
||
$grouped[$first][] = $result;
|
||
}
|
||
return array_filter($grouped);
|
||
}
|
||
|
||
public static function render_archive_results_by_letter($results) {
|
||
$groups = self::group_archive_results_by_letter($results);
|
||
if (empty($groups)) return '';
|
||
$all_letters = array_merge(array('#'), range('A', 'Z'), array('Æ', 'Ø', 'Å'));
|
||
ob_start();
|
||
echo '<nav class="ansico-ln-letter-nav" aria-label="Bogstavnavigation" style="margin:0 0 1.5rem;display:flex;flex-wrap:wrap;gap:.45rem;">';
|
||
foreach ($all_letters as $letter) {
|
||
if (isset($groups[$letter])) {
|
||
echo '<a href="#ansico-letter-' . esc_attr(sanitize_title($letter)) . '">' . esc_html($letter) . '</a>';
|
||
} else {
|
||
echo '<span style="opacity:.45;">' . esc_html($letter) . '</span>';
|
||
}
|
||
}
|
||
echo '</nav>';
|
||
foreach ($groups as $letter => $items) {
|
||
echo '<section id="ansico-letter-' . esc_attr(sanitize_title($letter)) . '" style="margin:0 0 1.5rem;">';
|
||
echo '<h2>' . esc_html($letter) . '</h2><ul>';
|
||
foreach ($items as $item) echo '<li><a href="' . esc_url($item['url']) . '">' . esc_html($item['title']) . '</a></li>';
|
||
echo '</ul></section>';
|
||
}
|
||
return trim(ob_get_clean());
|
||
}
|
||
|
||
public static function get_taxonomy_archive_grouped_results() {
|
||
$term = get_queried_object();
|
||
if (!$term || empty($term->taxonomy) || empty($term->term_id)) return array();
|
||
$taxonomy_object = get_taxonomy($term->taxonomy);
|
||
$post_types = !empty($taxonomy_object->object_type) ? (array) $taxonomy_object->object_type : array('post');
|
||
$query = new WP_Query(array(
|
||
'post_type' => $post_types,
|
||
'post_status' => 'publish',
|
||
'posts_per_page' => -1,
|
||
'orderby' => 'title',
|
||
'order' => 'ASC',
|
||
'ignore_sticky_posts' => true,
|
||
'no_found_rows' => true,
|
||
'tax_query' => array(array('taxonomy' => $term->taxonomy, 'field' => 'term_id', 'terms' => $term->term_id)),
|
||
));
|
||
$ordered_post_types = self::get_ordered_available_post_types();
|
||
$groups = array();
|
||
foreach ($ordered_post_types as $post_type_name => $pt_obj) {
|
||
if (in_array($post_type_name, $post_types, true)) {
|
||
$groups[$post_type_name] = array('label' => $pt_obj->labels->name, 'results' => array());
|
||
}
|
||
}
|
||
foreach ($query->posts as $post) {
|
||
if (!isset($groups[$post->post_type])) {
|
||
$groups[$post->post_type] = array('label' => self::get_post_type_label($post->post_type), 'results' => array());
|
||
}
|
||
$groups[$post->post_type]['results'][] = array('title' => get_the_title($post), 'url' => get_permalink($post));
|
||
}
|
||
wp_reset_postdata();
|
||
return array_filter($groups, function ($group) { return !empty($group['results']); });
|
||
}
|
||
|
||
public static function get_current_taxonomy_description() {
|
||
$description = term_description();
|
||
return is_string($description) ? $description : '';
|
||
}
|
||
|
||
private static function should_replace_block_results() {
|
||
if (is_search()) return true;
|
||
if (is_post_type_archive() && self::is_enabled_post_type_archive(self::get_current_archive_post_type())) return true;
|
||
if ((is_tax() || is_category() || is_tag()) && self::is_enabled_taxonomy_archive(self::get_current_taxonomy_name())) return true;
|
||
return false;
|
||
}
|
||
|
||
public static function get_block_theme_markup() {
|
||
ob_start();
|
||
if (is_search()) {
|
||
$grouped_results = self::get_grouped_search_results();
|
||
$total_results = self::get_total_results_count($grouped_results);
|
||
?>
|
||
<div class="wp-block-post-template ansico-ln-search-results-block">
|
||
<header class="ansico-ln-search-header" style="margin-bottom:2rem;">
|
||
<h1 style="margin-bottom:0.5rem;"><?php echo esc_html__('Søgeresultater', 'ansico-ln-plugins'); ?></h1>
|
||
<p style="margin-top:0;"><?php echo esc_html(self::get_total_results_text($total_results)); ?></p>
|
||
</header>
|
||
<?php if (!empty($grouped_results)) : foreach ($grouped_results as $group) : ?>
|
||
<section class="ansico-ln-search-group" style="margin-bottom:2rem;">
|
||
<p><strong><?php echo esc_html($group['label']); ?></strong></p>
|
||
<?php echo self::render_group_results_list($group['results']); ?>
|
||
</section>
|
||
<?php endforeach; else : ?><p><?php echo esc_html__('Der blev ikke fundet nogen resultater.', 'ansico-ln-plugins'); ?></p><?php endif; ?>
|
||
</div>
|
||
<?php
|
||
} elseif (is_post_type_archive()) {
|
||
$post_type = self::get_current_archive_post_type();
|
||
$results = self::get_archive_results($post_type);
|
||
?>
|
||
<div class="wp-block-post-template ansico-ln-archive-results-block">
|
||
<header style="margin-bottom:2rem;"><h1 style="margin-bottom:0.5rem;"><?php echo esc_html(self::get_post_type_label($post_type)); ?></h1></header>
|
||
<?php echo !empty($results) ? self::render_archive_results_by_letter($results) : '<p>' . esc_html__('Der blev ikke fundet nogen resultater.', 'ansico-ln-plugins') . '</p>'; ?>
|
||
</div>
|
||
<?php
|
||
} elseif (is_tax() || is_category() || is_tag()) {
|
||
$grouped = self::get_taxonomy_archive_grouped_results();
|
||
$description = self::get_current_taxonomy_description();
|
||
?>
|
||
<div class="wp-block-post-template ansico-ln-taxonomy-results-block">
|
||
<header style="margin-bottom:2rem;"><h1 style="margin-bottom:0.5rem;"><?php echo esc_html(single_term_title('', false)); ?></h1></header>
|
||
<?php if (!empty($description)) : ?><div class="ansico-ln-taxonomy-description" style="margin-bottom:1.5rem;"><?php echo wp_kses_post($description); ?></div><?php endif; ?>
|
||
<?php if (!empty($grouped)) : foreach ($grouped as $group) : ?>
|
||
<section class="ansico-ln-taxonomy-group" style="margin-bottom:2rem;">
|
||
<p><strong><?php echo esc_html($group['label']); ?></strong></p>
|
||
<?php echo self::render_simple_results_list($group['results']); ?>
|
||
</section>
|
||
<?php endforeach; else : ?><p><?php echo esc_html__('Der blev ikke fundet nogen resultater.', 'ansico-ln-plugins'); ?></p><?php endif; ?>
|
||
</div>
|
||
<?php
|
||
}
|
||
return trim(ob_get_clean());
|
||
}
|
||
|
||
private static function is_block_theme_active() {
|
||
return function_exists('wp_is_block_theme') && wp_is_block_theme();
|
||
}
|
||
}
|
||
|
||
new Ansico_LN_Plugins();
|