table_name = $wpdb->prefix . KGV_TERMINE_TABLE; register_activation_hook(KGV_TERMINE_FILE, array($this, 'activate')); add_action('admin_menu', array($this, 'register_admin_menu')); add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets')); add_action('wp_enqueue_scripts', array($this, 'enqueue_front_assets')); add_action('init', array($this, 'register_shortcodes')); add_action('admin_post_kgv_save_termin', array($this, 'handle_save_termin')); add_action('admin_post_kgv_delete_termin', array($this, 'handle_delete_termin')); add_filter('query_vars', array($this, 'register_query_vars')); } public function activate() { $this->create_table(); } private function create_table() { global $wpdb; require_once ABSPATH . 'wp-admin/includes/upgrade.php'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE {$this->table_name} ( id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, title VARCHAR(255) NOT NULL, event_date DATETIME NOT NULL, owner VARCHAR(255) NULL, location VARCHAR(255) NULL, summary TEXT NULL, description LONGTEXT NULL, is_published TINYINT(1) NOT NULL DEFAULT 1, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, PRIMARY KEY (id), KEY event_date (event_date), KEY is_published (is_published) ) {$charset_collate};"; dbDelta($sql); } public function enqueue_admin_assets($hook) { if (strpos((string) $hook, 'kgv-termine') === false) { return; } wp_enqueue_style( 'kgv-termine-admin-style', KGV_TERMINE_URL . 'assets/css/admin.css', array(), '1.0.2' ); } public function enqueue_front_assets() { wp_enqueue_style( 'kgv-termine-front-style', KGV_TERMINE_URL . 'assets/css/front.css', array(), '1.0.2' ); } public function register_query_vars($vars) { $vars[] = 'kgv_termin'; return $vars; } public function register_admin_menu() { add_menu_page( 'Termine', 'Termine', 'manage_options', 'kgv-termine', array($this, 'render_list_page'), 'dashicons-calendar-alt', 25 ); add_submenu_page( 'kgv-termine', 'Alle Termine', 'Alle Termine', 'manage_options', 'kgv-termine', array($this, 'render_list_page') ); add_submenu_page( 'kgv-termine', 'Neuer Termin', 'Neuer Termin', 'manage_options', 'kgv-termine-new', array($this, 'render_form_page') ); } public function register_shortcodes() { add_shortcode('kgv_termine', array($this, 'render_termine_shortcode')); add_shortcode('kgv_termin_detail', array($this, 'render_detail_shortcode')); add_shortcode('kgv_termine_sidebar', array($this, 'render_sidebar_shortcode')); } public function handle_save_termin() { if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); } check_admin_referer('kgv_save_termin'); $this->save_termin_from_request(); } public function handle_delete_termin() { if (!current_user_can('manage_options')) { wp_die('Keine Berechtigung.'); } $id = isset($_GET['termin_id']) ? absint($_GET['termin_id']) : 0; if (!$id || !isset($_GET['_wpnonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_GET['_wpnonce'])), 'kgv_delete_termin_' . $id)) { wp_safe_redirect(admin_url('admin.php?page=kgv-termine&message=delete_failed')); exit; } global $wpdb; $wpdb->delete($this->table_name, array('id' => $id), array('%d')); wp_safe_redirect(admin_url('admin.php?page=kgv-termine&message=deleted')); exit; } private function save_termin_from_request() { global $wpdb; $id = isset($_POST['termin_id']) ? absint($_POST['termin_id']) : 0; $title = sanitize_text_field(wp_unslash($_POST['title'] ?? '')); $event_date = sanitize_text_field(wp_unslash($_POST['event_date'] ?? '')); $owner = sanitize_text_field(wp_unslash($_POST['owner'] ?? '')); $location = sanitize_text_field(wp_unslash($_POST['location'] ?? '')); $summary = sanitize_textarea_field(wp_unslash($_POST['summary'] ?? '')); $description = wp_kses_post(wp_unslash($_POST['description'] ?? '')); $is_published = isset($_POST['is_published']) ? (int) wp_unslash($_POST['is_published']) : 1; $is_published = $is_published === 1 ? 1 : 0; if ($title === '' || $event_date === '' || strtotime($event_date) === false) { $target = $id ? admin_url('admin.php?page=kgv-termine-new&termin_id=' . $id . '&message=missing') : admin_url('admin.php?page=kgv-termine-new&message=missing'); wp_safe_redirect($target); exit; } $mysql_date = date('Y-m-d H:i:s', strtotime($event_date)); $now = current_time('mysql'); $data = array( 'title' => $title, 'event_date' => $mysql_date, 'owner' => $owner, 'location' => $location, 'summary' => $summary, 'description' => $description, 'is_published' => $is_published, 'updated_at' => $now, ); $formats = array('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s'); if ($id) { $wpdb->update($this->table_name, $data, array('id' => $id), $formats, array('%d')); wp_safe_redirect(admin_url('admin.php?page=kgv-termine&message=updated')); exit; } $data['created_at'] = $now; $wpdb->insert($this->table_name, $data, array('%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s')); wp_safe_redirect(admin_url('admin.php?page=kgv-termine&message=created')); exit; } public function render_list_page() { global $wpdb; $rows = $wpdb->get_results("SELECT * FROM {$this->table_name} ORDER BY event_date ASC, id ASC"); $message = isset($_GET['message']) ? sanitize_text_field(wp_unslash($_GET['message'])) : ''; ?>

Termine

Neuen Termin anlegen
render_notice($message); ?>
Titel Datum Verantwortlich Ort Status Aktionen
Noch keine Termine angelegt.
title); ?> event_date))); ?> owner ?: '—'); ?> location ?: '—'); ?> is_published === 1 ? 'Veröffentlicht' : 'Entwurf'; ?> Bearbeiten | Löschen
get_row($wpdb->prepare("SELECT * FROM {$this->table_name} WHERE id = %d", $id)); } $title = $row ? $row->title : ''; $event_date = $row ? date('Y-m-d\TH:i', strtotime($row->event_date)) : ''; $owner = $row ? $row->owner : ''; $location = $row ? $row->location : ''; $summary = $row ? $row->summary : ''; $description = $row ? $row->description : ''; $is_published = $row ? (int) $row->is_published : 1; ?>

render_notice($message); ?>
Abbrechen
array('success', 'Termin wurde angelegt.'), 'updated' => array('success', 'Termin wurde aktualisiert.'), 'deleted' => array('success', 'Termin wurde gelöscht.'), 'delete_failed' => array('error', 'Termin konnte nicht gelöscht werden.'), 'missing' => array('error', 'Titel und Datum sind Pflichtfelder.'), ); if (!isset($map[$message])) { return; } list($type, $text) = $map[$message]; printf('

%2$s

', esc_attr($type), esc_html($text)); } private function get_frontend_rows($limit = 0) { global $wpdb; if ($limit > 0) { return $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE is_published = 1 ORDER BY event_date ASC, id ASC LIMIT %d", $limit )); } return $wpdb->get_results("SELECT * FROM {$this->table_name} WHERE is_published = 1 ORDER BY event_date ASC, id ASC"); } private function get_row($id) { global $wpdb; return $wpdb->get_row($wpdb->prepare("SELECT * FROM {$this->table_name} WHERE id = %d", $id)); } public function render_termine_shortcode($atts) { $atts = shortcode_atts(array( 'limit' => 0, 'detail' => 1, ), $atts, 'kgv_termine'); $detail_id = absint(get_query_var('kgv_termin')); if (!$detail_id && isset($_GET['kgv_termin'])) { $detail_id = absint(wp_unslash($_GET['kgv_termin'])); } $base_url = $this->get_current_page_url(false); if ($detail_id && (int) $atts['detail'] === 1) { return $this->render_detail_by_id($detail_id, $base_url); } $rows = $this->get_frontend_rows(absint($atts['limit'])); if (empty($rows)) { return '
Aktuell sind keine Termine verfügbar.
'; } ob_start(); echo '
'; foreach ($rows as $row) { $link = add_query_arg('kgv_termin', (int) $row->id, $base_url); echo '
'; echo '
'; echo '
' . esc_html(wp_date('d.m.Y H:i', strtotime($row->event_date))) . '
'; echo '

' . esc_html($row->title) . '

'; echo '
'; if (!empty($row->owner)) { echo 'Verantwortlich: ' . esc_html($row->owner) . ''; } if (!empty($row->location)) { echo 'Ort: ' . esc_html($row->location) . ''; } echo '
'; if (!empty($row->summary)) { echo '
' . esc_html($row->summary) . '
'; } echo ''; echo '
'; echo '
'; } echo '
'; return ob_get_clean(); } public function render_detail_shortcode($atts) { $atts = shortcode_atts(array( 'id' => 0, ), $atts, 'kgv_termin_detail'); $id = absint($atts['id']); if (!$id) { return '
Keine Termin-ID übergeben.
'; } return $this->render_detail_by_id($id, ''); } private function render_detail_by_id($id, $back_url = '') { $row = $this->get_row($id); if (!$row || !(int) $row->is_published) { return '
Termin nicht gefunden.
'; } ob_start(); echo '
'; echo '
'; if ($back_url) { echo '← Zurück zur Übersicht'; } echo '
' . esc_html(wp_date('d.m.Y H:i', strtotime($row->event_date))) . '
'; echo '

' . esc_html($row->title) . '

'; echo '
'; if (!empty($row->owner)) { echo 'Verantwortlich: ' . esc_html($row->owner) . ''; } if (!empty($row->location)) { echo 'Ort: ' . esc_html($row->location) . ''; } echo '
'; echo '
'; echo '
'; if (!empty($row->summary)) { echo '

' . esc_html($row->summary) . '

'; } echo '
' . wpautop(wp_kses_post($row->description)) . '
'; echo '
'; echo '
'; return ob_get_clean(); } public function render_sidebar_shortcode($atts) { $atts = shortcode_atts(array( 'limit' => 5, ), $atts, 'kgv_termine_sidebar'); $rows = $this->get_frontend_rows(max(1, min(20, absint($atts['limit'])))); if (empty($rows)) { return '
Keine Termine
'; } $base_url = $this->get_current_page_url(false); ob_start(); echo '
'; echo '

Nächste Termine

'; echo '
'; foreach ($rows as $row) { $link = add_query_arg('kgv_termin', (int) $row->id, $base_url); echo ''; echo '' . esc_html(wp_date('d.m.Y', strtotime($row->event_date))) . ''; echo '' . esc_html($row->title) . ''; echo ''; } echo '
'; echo '
'; return ob_get_clean(); } private function get_current_page_url($with_query = true) { $page_url = ''; if (is_singular() && get_queried_object_id()) { $page_url = get_permalink(get_queried_object_id()); } if (!$page_url) { global $wp; $page_url = home_url(add_query_arg(array(), $wp->request ? '/' . ltrim($wp->request, '/') . '/' : '/')); } if (!$with_query) { return remove_query_arg(array_keys($_GET), $page_url); } return $page_url; } }