Some checks failed
Deploy static site to pages / deploy (push) Has been cancelled
365 lines
11 KiB
PHP
365 lines
11 KiB
PHP
<?php
|
|
if (!defined('ABSPATH')) exit;
|
|
|
|
require_once get_template_directory() . '/inc/block-patterns.php';
|
|
|
|
function juconnect_setup() {
|
|
add_theme_support('title-tag');
|
|
add_theme_support('post-thumbnails');
|
|
add_theme_support('site-icon');
|
|
add_theme_support('editor-styles');
|
|
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_editor_style('style.css');
|
|
}
|
|
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);
|
|
|