$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 '
'; 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 ''; echo esc_html($term->name); if ($show_count) { echo ' (' . intval($term->count) . ')'; } echo ' '; } echo '
'; } else { echo '
'; } 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 ''; } } 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); } ?> $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(); ?>

$post_type_object) : ?>
labels->name); ?>

$taxonomy_object) : ?>
labels->name); ?>

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 = '/(]*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\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\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 '' . $match[3] . ''; }, $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 ''; 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[] = '' . esc_html($source['label']) . ''; } $markup = '
'; $markup .= '' . esc_html__('Citerede kilder:', 'ansico-ln-plugins') . ' '; $markup .= implode(', ', $items) . '.'; $markup .= '
'; 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('/]+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 = '
' . $content . '
'; 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 ''; if (!empty($hidden_results)) { echo '
' . esc_html(sprintf('Vis alle %d resultater', count($results))) . '
'; } return trim(ob_get_clean()); } public static function render_simple_results_list($results) { if (empty($results)) return ''; ob_start(); echo ''; 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 ''; foreach ($groups as $letter => $items) { echo '
'; echo '

' . esc_html($letter) . '

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

' . esc_html__('Der blev ikke fundet nogen resultater.', 'ansico-ln-plugins') . '

'; ?>