Files
JuConnect/juconnect-strict-theme-v3/juconnect-strict/functions.php

359 lines
11 KiB
PHP

<?php
if (!defined('ABSPATH')) exit;
function juconnect_setup() {
add_theme_support('title-tag');
add_theme_support('post-thumbnails');
add_theme_support('site-icon');
add_theme_support('custom-logo', [
'height' => 120,
'width' => 120,
'flex-height' => true,
'flex-width' => true,
]);
register_nav_menus([
'primary' => __('Primary Navigation', 'juconnect'),
'footer' => __('Footer Navigation', 'juconnect'),
]);
}
add_action('after_setup_theme', 'juconnect_setup');
/**
* Fallback favicon when no Site Icon is set in WordPress.
*/
function juconnect_favicon_fallback() {
if (has_site_icon()) {
return;
}
$icon_light_mode = get_template_directory_uri() . '/assets/img/juconnect_icon.svg';
$icon_dark_mode = get_template_directory_uri() . '/assets/img/juconnect_icon_light.svg';
// Use the light icon in dark browser UI and the default icon in light UI.
echo '<link rel="icon" href="' . esc_url($icon_light_mode) . '" media="(prefers-color-scheme: light)" type="image/svg+xml" />' . "\n";
echo '<link rel="icon" href="' . esc_url($icon_dark_mode) . '" media="(prefers-color-scheme: dark)" type="image/svg+xml" />' . "\n";
echo '<link rel="icon" href="' . esc_url($icon_light_mode) . '" type="image/svg+xml" />' . "\n";
}
add_action('wp_head', 'juconnect_favicon_fallback');
/**
* Avoid duplicate SEO tags when a dedicated SEO plugin is active.
*/
function juconnect_has_external_seo_plugin() {
return (
class_exists('WPSEO_Frontend') || // Yoast SEO
defined('RANK_MATH_VERSION') || // Rank Math
defined('AIOSEO_VERSION') || // All in One SEO
defined('SEOPRESS_VERSION') || // SEOPress
defined('THE_SEO_FRAMEWORK_VERSION')
);
}
function juconnect_get_meta_description() {
$description = '';
if (is_front_page() || is_home()) {
$description = get_bloginfo('description', 'display');
} elseif (is_singular()) {
if (has_excerpt()) {
$description = get_the_excerpt();
} else {
$content = get_post_field('post_content', get_queried_object_id());
$description = wp_strip_all_tags(strip_shortcodes((string) $content));
}
} elseif (is_category() || is_tag() || is_tax()) {
$description = wp_strip_all_tags(term_description());
} elseif (is_post_type_archive()) {
$description = wp_strip_all_tags(get_the_archive_description());
}
if ($description === '') {
$description = get_bloginfo('description', 'display');
}
$description = preg_replace('/\s+/', ' ', trim((string) $description));
return wp_html_excerpt($description, 155, '...');
}
function juconnect_get_canonical_url() {
$paged = max(1, (int) get_query_var('paged'));
if (is_404()) {
return '';
}
if (is_singular()) {
if (function_exists('wp_get_canonical_url')) {
$canonical = wp_get_canonical_url();
if ($canonical) {
return $canonical;
}
}
return get_permalink();
}
if (is_front_page()) {
if ($paged > 1) {
return get_pagenum_link($paged);
}
return home_url('/');
}
if (is_home()) {
if ($paged > 1) {
return get_pagenum_link($paged);
}
$posts_page_id = (int) get_option('page_for_posts');
if ($posts_page_id > 0) {
return get_permalink($posts_page_id);
}
}
return get_pagenum_link($paged);
}
function juconnect_get_social_image_url() {
if (is_singular() && has_post_thumbnail()) {
$image = wp_get_attachment_image_url(get_post_thumbnail_id(), 'full');
if ($image) {
return $image;
}
}
if (has_site_icon()) {
$site_icon = get_site_icon_url(512);
if ($site_icon) {
return $site_icon;
}
}
return get_template_directory_uri() . '/assets/img/juconnect_icon.svg';
}
function juconnect_output_seo_meta() {
if (juconnect_has_external_seo_plugin() || is_feed()) {
return;
}
$title = wp_get_document_title();
$description = juconnect_get_meta_description();
$canonical = juconnect_get_canonical_url();
$site_name = get_bloginfo('name', 'display');
$locale = str_replace('-', '_', get_locale());
$og_type = is_singular('post') ? 'article' : 'website';
$social_image = juconnect_get_social_image_url();
if ($description !== '') {
echo '<meta name="description" content="' . esc_attr($description) . '" />' . "\n";
}
// Core prints singular canonicals already via rel_canonical.
if (!is_singular() && $canonical !== '') {
echo '<link rel="canonical" href="' . esc_url($canonical) . '" />' . "\n";
}
echo '<meta property="og:locale" content="' . esc_attr($locale) . '" />' . "\n";
echo '<meta property="og:type" content="' . esc_attr($og_type) . '" />' . "\n";
echo '<meta property="og:title" content="' . esc_attr($title) . '" />' . "\n";
if ($description !== '') {
echo '<meta property="og:description" content="' . esc_attr($description) . '" />' . "\n";
}
if ($canonical !== '') {
echo '<meta property="og:url" content="' . esc_url($canonical) . '" />' . "\n";
}
echo '<meta property="og:site_name" content="' . esc_attr($site_name) . '" />' . "\n";
if ($social_image !== '') {
echo '<meta property="og:image" content="' . esc_url($social_image) . '" />' . "\n";
}
echo '<meta name="twitter:card" content="' . esc_attr($social_image !== '' ? 'summary_large_image' : 'summary') . '" />' . "\n";
echo '<meta name="twitter:title" content="' . esc_attr($title) . '" />' . "\n";
if ($description !== '') {
echo '<meta name="twitter:description" content="' . esc_attr($description) . '" />' . "\n";
}
if ($social_image !== '') {
echo '<meta name="twitter:image" content="' . esc_url($social_image) . '" />' . "\n";
}
}
add_action('wp_head', 'juconnect_output_seo_meta', 5);
function juconnect_robots_directives($robots) {
if (juconnect_has_external_seo_plugin()) {
return $robots;
}
if (get_option('blog_public') === '0') {
return [
'noindex' => true,
'nofollow' => true,
];
}
if (is_search() || is_404() || is_attachment()) {
unset($robots['index']);
$robots['noindex'] = true;
}
return $robots;
}
add_filter('wp_robots', 'juconnect_robots_directives');
function juconnect_output_json_ld() {
if (juconnect_has_external_seo_plugin() || is_feed()) {
return;
}
$home_url = home_url('/');
$site_name = get_bloginfo('name', 'display');
$site_logo = '';
$custom_logo_id = (int) get_theme_mod('custom_logo');
if ($custom_logo_id > 0) {
$site_logo = wp_get_attachment_image_url($custom_logo_id, 'full');
} elseif (has_site_icon()) {
$site_logo = get_site_icon_url(512);
}
$schema_graph = [];
$organization = [
'@type' => 'Organization',
'@id' => $home_url . '#organization',
'name' => $site_name,
'url' => $home_url,
];
if ($site_logo) {
$organization['logo'] = $site_logo;
}
$schema_graph[] = $organization;
$website = [
'@type' => 'WebSite',
'@id' => $home_url . '#website',
'url' => $home_url,
'name' => $site_name,
'publisher' => ['@id' => $home_url . '#organization'],
'potentialAction' => [
'@type' => 'SearchAction',
'target' => home_url('/?s={search_term_string}'),
'query-input' => 'required name=search_term_string',
],
];
$schema_graph[] = $website;
if (is_singular()) {
$canonical = juconnect_get_canonical_url();
$webpage = [
'@type' => 'WebPage',
'@id' => $canonical . '#webpage',
'url' => $canonical,
'name' => single_post_title('', false),
'isPartOf' => ['@id' => $home_url . '#website'],
'description' => juconnect_get_meta_description(),
];
$schema_graph[] = $webpage;
if (is_singular('post')) {
$article = [
'@type' => 'Article',
'@id' => $canonical . '#article',
'mainEntityOfPage' => ['@id' => $canonical . '#webpage'],
'headline' => single_post_title('', false),
'datePublished' => get_post_time(DATE_W3C, true),
'dateModified' => get_post_modified_time(DATE_W3C, true),
'author' => [
'@type' => 'Person',
'name' => get_the_author_meta('display_name', (int) get_post_field('post_author', get_queried_object_id())),
],
'publisher' => ['@id' => $home_url . '#organization'],
];
$image = juconnect_get_social_image_url();
if ($image) {
$article['image'] = [$image];
}
$schema_graph[] = $article;
}
}
$json_ld = [
'@context' => 'https://schema.org',
'@graph' => $schema_graph,
];
echo '<script type="application/ld+json">' . wp_json_encode($json_ld, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . '</script>' . "\n";
}
add_action('wp_head', 'juconnect_output_json_ld', 6);
function juconnect_assets() {
$theme_ver = wp_get_theme()->get('Version');
$style_ver = filemtime(get_stylesheet_directory() . '/style.css');
$script_ver = filemtime(get_template_directory() . '/assets/js/app.js');
if (!$style_ver) {
$style_ver = $theme_ver;
}
if (!$script_ver) {
$script_ver = $theme_ver;
}
wp_enqueue_style('juconnect-style', get_stylesheet_uri(), [], $style_ver);
wp_enqueue_script('juconnect-app', get_template_directory_uri().'/assets/js/app.js', [], $script_ver, true);
}
add_action('wp_enqueue_scripts', 'juconnect_assets');
/**
* Render primary nav in strict styleguide markup:
* - groups = top-level items
* - links = children + optionally the parent itself
*/
function juconnect_render_sidenav_nav() {
$locations = get_nav_menu_locations();
if (!isset($locations['primary'])) return;
$menu_obj = wp_get_nav_menu_object($locations['primary']);
if (!$menu_obj) return;
$items = wp_get_nav_menu_items($menu_obj->term_id);
if (!$items) return;
$by_parent = [];
foreach ($items as $it) {
$pid = (int)$it->menu_item_parent;
if (!isset($by_parent[$pid])) $by_parent[$pid] = [];
$by_parent[$pid][] = $it;
}
$top = $by_parent[0] ?? [];
foreach ($top as $parent) {
echo '<div class="navgroup">';
echo '<div class="navgroup__title">'.esc_html($parent->title).'</div>';
// Parent link as first item (optional but useful)
if (!empty($parent->url) && $parent->url !== '#') {
echo '<a class="navlink" href="'.esc_url($parent->url).'">'.esc_html('Übersicht').'</a>';
}
$children = $by_parent[(int)$parent->ID] ?? [];
foreach ($children as $child) {
echo '<a class="navlink" href="'.esc_url($child->url).'">'.esc_html($child->title).'</a>';
}
echo '</div>';
}
}
// Add styleguide classes to WP menus
function juconnect_nav_link_attributes($atts, $item, $args, $depth){
if (!empty($args->theme_location) && in_array($args->theme_location, ['primary', 'footer'], true)){
$existing = isset($atts['class']) ? $atts['class'].' ' : '';
$atts['class'] = $existing . 'navlink';
}
return $atts;
}
add_filter('nav_menu_link_attributes', 'juconnect_nav_link_attributes', 10, 4);
function juconnect_nav_menu_submenu_class($classes, $args, $depth){
if (!empty($args->theme_location) && $args->theme_location === 'primary'){
$classes[] = 'topnav__submenu';
}
return $classes;
}
add_filter('nav_menu_submenu_css_class', 'juconnect_nav_menu_submenu_class', 10, 3);