736 lines
30 KiB
PHP
736 lines
30 KiB
PHP
<?php
|
|
/**
|
|
* Plugin Name: Restaurant Tür-Status
|
|
* Plugin URI: https://lucas-orth.de
|
|
* Description: Interaktives Voting-Widget mit animierter Tür - Besucher können abstimmen ob ein Restaurant geöffnet oder geschlossen ist
|
|
* Version: 1.1.0
|
|
* Author: Lucas Orth
|
|
* Author URI: https://lucas-orth.de
|
|
* License: GPL v2 or later
|
|
* Text Domain: door-status
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
define('DSV_VERSION', '1.0.0');
|
|
define('DSV_PLUGIN_DIR', plugin_dir_path(__FILE__));
|
|
define('DSV_PLUGIN_URL', plugin_dir_url(__FILE__));
|
|
|
|
class DoorStatusVoting {
|
|
|
|
private static $instance = null;
|
|
|
|
public static function get_instance() {
|
|
if (self::$instance === null) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
private function __construct() {
|
|
// Frontend
|
|
add_shortcode('door_status', [$this, 'render_shortcode']);
|
|
add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_assets']);
|
|
|
|
// AJAX Handlers
|
|
add_action('wp_ajax_dsv_vote', [$this, 'handle_vote']);
|
|
add_action('wp_ajax_nopriv_dsv_vote', [$this, 'handle_vote']);
|
|
add_action('wp_ajax_dsv_remove_vote', [$this, 'handle_remove_vote']);
|
|
add_action('wp_ajax_nopriv_dsv_remove_vote', [$this, 'handle_remove_vote']);
|
|
add_action('wp_ajax_dsv_get_status', [$this, 'get_status']);
|
|
add_action('wp_ajax_nopriv_dsv_get_status', [$this, 'get_status']);
|
|
|
|
// Admin
|
|
add_action('admin_menu', [$this, 'add_admin_menu']);
|
|
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
|
|
add_action('wp_ajax_dsv_save_settings', [$this, 'save_settings']);
|
|
add_action('wp_ajax_dsv_reset_votes', [$this, 'reset_votes']);
|
|
add_action('wp_ajax_dsv_reset_votes_by_type', [$this, 'reset_votes_by_type']);
|
|
add_action('wp_ajax_dsv_update_meta_status', [$this, 'update_meta_status']);
|
|
}
|
|
|
|
// =========================================================================
|
|
// FRONTEND
|
|
// =========================================================================
|
|
|
|
/**
|
|
* Assets für Frontend laden
|
|
*/
|
|
public function enqueue_frontend_assets() {
|
|
wp_enqueue_style(
|
|
'dsv-frontend',
|
|
DSV_PLUGIN_URL . 'assets/css/frontend.css',
|
|
[],
|
|
DSV_VERSION
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'dsv-frontend',
|
|
DSV_PLUGIN_URL . 'assets/js/frontend.js',
|
|
[],
|
|
DSV_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_localize_script('dsv-frontend', 'dsvConfig', [
|
|
'ajaxUrl' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('dsv_nonce')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Shortcode rendern
|
|
*/
|
|
public function render_shortcode($atts) {
|
|
$atts = shortcode_atts([
|
|
'post_id' => get_the_ID()
|
|
], $atts);
|
|
|
|
$post_id = intval($atts['post_id']);
|
|
|
|
// Prüfen ob für diesen Post deaktiviert
|
|
$disabled_posts = get_option('dsv_disabled_posts', []);
|
|
if (in_array($post_id, $disabled_posts)) {
|
|
return '';
|
|
}
|
|
|
|
// Votes laden
|
|
$votes = $this->get_votes($post_id);
|
|
$total = $votes['open'] + $votes['closed'];
|
|
$open_percent = $total > 0 ? round(($votes['open'] / $total) * 100) : 50;
|
|
|
|
// Status ermitteln
|
|
if ($votes['open'] > $votes['closed']) {
|
|
$status = 'open';
|
|
$status_text = 'GEÖFFNET';
|
|
$status_icon = '🟢';
|
|
} elseif ($votes['closed'] > $votes['open']) {
|
|
$status = 'closed';
|
|
$status_text = 'GESCHLOSSEN';
|
|
$status_icon = '🔴';
|
|
} else {
|
|
$status = 'tied';
|
|
$status_text = 'UNKLAR';
|
|
$status_icon = '🟡';
|
|
}
|
|
|
|
// User Vote aus Cookie prüfen
|
|
$cookie_name = 'dsv_vote_' . $post_id;
|
|
$user_vote = isset($_COOKIE[$cookie_name]) ? sanitize_text_field($_COOKIE[$cookie_name]) : null;
|
|
$has_voted = !empty($user_vote);
|
|
|
|
ob_start();
|
|
?>
|
|
<div class="dsv-widget"
|
|
data-post-id="<?php echo esc_attr($post_id); ?>"
|
|
data-status="<?php echo esc_attr($status); ?>"
|
|
data-has-voted="<?php echo $has_voted ? 'true' : 'false'; ?>"
|
|
data-user-vote="<?php echo esc_attr($user_vote); ?>">
|
|
|
|
<h3 class="dsv-title">Ist das Restaurant noch geöffnet?</h3>
|
|
|
|
<div class="dsv-main-row">
|
|
<!-- Tür Container -->
|
|
<div class="dsv-door-container">
|
|
|
|
<!-- Status Badge -->
|
|
<div class="dsv-status-badge dsv-status-<?php echo esc_attr($status); ?>">
|
|
<?php echo $status_icon; ?> <?php echo esc_html($status_text); ?>
|
|
</div>
|
|
|
|
<!-- Türrahmen -->
|
|
<div class="dsv-door-frame">
|
|
|
|
<!-- Licht hinter der Tür -->
|
|
<div class="dsv-light"></div>
|
|
|
|
<!-- Lichtstrahlen -->
|
|
<div class="dsv-light-rays">
|
|
<div class="dsv-ray"></div>
|
|
<div class="dsv-ray"></div>
|
|
<div class="dsv-ray"></div>
|
|
<div class="dsv-ray"></div>
|
|
<div class="dsv-ray"></div>
|
|
</div>
|
|
|
|
<!-- Die Tür -->
|
|
<div class="dsv-door">
|
|
<div class="dsv-door-grain"></div>
|
|
<div class="dsv-door-panel dsv-door-panel-top"></div>
|
|
<div class="dsv-door-panel dsv-door-panel-bottom"></div>
|
|
<div class="dsv-door-handle">
|
|
<div class="dsv-handle-plate"></div>
|
|
<div class="dsv-handle-lever"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Schatten -->
|
|
<div class="dsv-shadow"></div>
|
|
</div>
|
|
|
|
<!-- Rechte Seite: Voting -->
|
|
<div class="dsv-voting-section">
|
|
<!-- Fortschrittsbalken -->
|
|
<div class="dsv-progress-container">
|
|
<div class="dsv-progress-bar">
|
|
<div class="dsv-progress-open" style="width: <?php echo $open_percent; ?>%">
|
|
<?php if ($open_percent > 15): ?>
|
|
<span class="dsv-progress-count"><?php echo $votes['open']; ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="dsv-progress-closed" style="width: <?php echo 100 - $open_percent; ?>%">
|
|
<?php if ((100 - $open_percent) > 15): ?>
|
|
<span class="dsv-progress-count"><?php echo $votes['closed']; ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="dsv-progress-divider"></div>
|
|
</div>
|
|
<div class="dsv-progress-labels">
|
|
<span class="dsv-label-open">Geöffnet (<?php echo $open_percent; ?>%)</span>
|
|
<span class="dsv-label-closed">Geschlossen (<?php echo 100 - $open_percent; ?>%)</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Voting Buttons -->
|
|
<div class="dsv-buttons <?php echo $has_voted ? 'dsv-voted' : ''; ?>">
|
|
<?php if (!$has_voted): ?>
|
|
<button type="button" class="dsv-btn dsv-btn-open" data-vote="open">
|
|
<span class="dsv-btn-icon">✓</span>
|
|
<span class="dsv-btn-text">Geöffnet</span>
|
|
</button>
|
|
<button type="button" class="dsv-btn dsv-btn-closed" data-vote="closed">
|
|
<span class="dsv-btn-icon">✗</span>
|
|
<span class="dsv-btn-text">Geschlossen</span>
|
|
</button>
|
|
<?php else: ?>
|
|
<div class="dsv-voted-message dsv-voted-<?php echo esc_attr($user_vote); ?>">
|
|
<span class="dsv-voted-icon"><?php echo $user_vote === 'open' ? '✓' : '✗'; ?></span>
|
|
<span class="dsv-voted-text">
|
|
Du hast für "<?php echo $user_vote === 'open' ? 'Geöffnet' : 'Geschlossen'; ?>" gestimmt
|
|
</span>
|
|
<button type="button" class="dsv-remove-vote" title="Stimme zurücknehmen">✕</button>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<!-- Teilnehmer Info -->
|
|
<p class="dsv-info">
|
|
<span class="dsv-total"><?php echo $total; ?></span> Besucher haben abgestimmt
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
return ob_get_clean();
|
|
}
|
|
|
|
/**
|
|
* Votes aus Post Meta laden
|
|
*/
|
|
private function get_votes($post_id) {
|
|
$data = get_post_meta($post_id, '_dsv_votes', true);
|
|
if (!is_array($data)) {
|
|
return ['open' => 0, 'closed' => 0];
|
|
}
|
|
|
|
$open = $closed = 0;
|
|
foreach ($data as $vote) {
|
|
if ($vote === 'open') $open++;
|
|
if ($vote === 'closed') $closed++;
|
|
}
|
|
return ['open' => $open, 'closed' => $closed];
|
|
}
|
|
|
|
/**
|
|
* User-Key generieren (IP Hash)
|
|
*/
|
|
private function get_user_key() {
|
|
$ip = '';
|
|
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])) {
|
|
$ip = $_SERVER['HTTP_CF_CONNECTING_IP'];
|
|
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
|
|
$ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
|
|
} else {
|
|
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
|
|
}
|
|
return md5($ip . wp_salt());
|
|
}
|
|
|
|
/**
|
|
* AJAX: Vote speichern
|
|
*/
|
|
public function handle_vote() {
|
|
check_ajax_referer('dsv_nonce', 'nonce');
|
|
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
$vote = sanitize_text_field($_POST['vote'] ?? '');
|
|
|
|
if (!$post_id || !in_array($vote, ['open', 'closed'])) {
|
|
wp_send_json_error(['message' => 'Ungültige Anfrage']);
|
|
}
|
|
|
|
// Prüfen ob deaktiviert
|
|
$disabled_posts = get_option('dsv_disabled_posts', []);
|
|
if (in_array($post_id, $disabled_posts)) {
|
|
wp_send_json_error(['message' => 'Voting deaktiviert']);
|
|
}
|
|
|
|
$user_key = $this->get_user_key();
|
|
$data = get_post_meta($post_id, '_dsv_votes', true);
|
|
if (!is_array($data)) $data = [];
|
|
|
|
// Bereits gevotet? (Server-side Check)
|
|
if (isset($data[$user_key])) {
|
|
wp_send_json_error(['message' => 'Bereits abgestimmt']);
|
|
}
|
|
|
|
// Vote speichern
|
|
$data[$user_key] = $vote;
|
|
update_post_meta($post_id, '_dsv_votes', $data);
|
|
|
|
// Cookie setzen (30 Tage)
|
|
$cookie_name = 'dsv_vote_' . $post_id;
|
|
setcookie($cookie_name, $vote, time() + (30 * DAY_IN_SECONDS), COOKIEPATH, COOKIE_DOMAIN);
|
|
|
|
// Neue Votes zurückgeben
|
|
$votes = $this->get_votes($post_id);
|
|
$total = $votes['open'] + $votes['closed'];
|
|
$open_percent = $total > 0 ? round(($votes['open'] / $total) * 100) : 50;
|
|
|
|
wp_send_json_success([
|
|
'votes' => $votes,
|
|
'total' => $total,
|
|
'openPercent' => $open_percent,
|
|
'status' => $votes['open'] > $votes['closed'] ? 'open' :
|
|
($votes['closed'] > $votes['open'] ? 'closed' : 'tied')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX: Aktuellen Status abrufen
|
|
*/
|
|
public function get_status() {
|
|
$post_id = intval($_GET['post_id'] ?? 0);
|
|
|
|
if (!$post_id) {
|
|
wp_send_json_error(['message' => 'Ungültige Post ID']);
|
|
}
|
|
|
|
$votes = $this->get_votes($post_id);
|
|
$total = $votes['open'] + $votes['closed'];
|
|
$open_percent = $total > 0 ? round(($votes['open'] / $total) * 100) : 50;
|
|
|
|
wp_send_json_success([
|
|
'votes' => $votes,
|
|
'total' => $total,
|
|
'openPercent' => $open_percent,
|
|
'status' => $votes['open'] > $votes['closed'] ? 'open' :
|
|
($votes['closed'] > $votes['open'] ? 'closed' : 'tied')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX: Vote entfernen
|
|
*/
|
|
public function handle_remove_vote() {
|
|
check_ajax_referer('dsv_nonce', 'nonce');
|
|
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
|
|
if (!$post_id) {
|
|
wp_send_json_error(['message' => 'Ungültige Anfrage']);
|
|
}
|
|
|
|
$user_key = $this->get_user_key();
|
|
$data = get_post_meta($post_id, '_dsv_votes', true);
|
|
|
|
if (!is_array($data) || !isset($data[$user_key])) {
|
|
wp_send_json_error(['message' => 'Kein Vote gefunden']);
|
|
}
|
|
|
|
// Vote entfernen
|
|
unset($data[$user_key]);
|
|
update_post_meta($post_id, '_dsv_votes', $data);
|
|
|
|
// Cookie löschen
|
|
$cookie_name = 'dsv_vote_' . $post_id;
|
|
setcookie($cookie_name, '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN);
|
|
|
|
// Neue Votes zurückgeben
|
|
$votes = $this->get_votes($post_id);
|
|
$total = $votes['open'] + $votes['closed'];
|
|
$open_percent = $total > 0 ? round(($votes['open'] / $total) * 100) : 50;
|
|
|
|
wp_send_json_success([
|
|
'votes' => $votes,
|
|
'total' => $total,
|
|
'openPercent' => $open_percent,
|
|
'status' => $votes['open'] > $votes['closed'] ? 'open' :
|
|
($votes['closed'] > $votes['open'] ? 'closed' : 'tied')
|
|
]);
|
|
}
|
|
|
|
// =========================================================================
|
|
// ADMIN
|
|
// =========================================================================
|
|
|
|
/**
|
|
* Admin Menü unter Werkzeuge
|
|
*/
|
|
public function add_admin_menu() {
|
|
add_management_page(
|
|
'Tür-Status Voting',
|
|
'Tür-Status',
|
|
'manage_options',
|
|
'door-status-settings',
|
|
[$this, 'render_admin_page']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Admin Assets laden
|
|
*/
|
|
public function enqueue_admin_assets($hook) {
|
|
if ($hook !== 'tools_page_door-status-settings') {
|
|
return;
|
|
}
|
|
|
|
wp_enqueue_style(
|
|
'dsv-admin',
|
|
DSV_PLUGIN_URL . 'assets/css/admin.css',
|
|
[],
|
|
DSV_VERSION
|
|
);
|
|
|
|
wp_enqueue_script(
|
|
'dsv-admin',
|
|
DSV_PLUGIN_URL . 'assets/js/admin.js',
|
|
['jquery'],
|
|
DSV_VERSION,
|
|
true
|
|
);
|
|
|
|
wp_localize_script('dsv-admin', 'dsvAdmin', [
|
|
'ajaxUrl' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('dsv_admin_nonce')
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Admin Seite rendern
|
|
*/
|
|
public function render_admin_page() {
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die('Keine Berechtigung');
|
|
}
|
|
|
|
$disabled_posts = get_option('dsv_disabled_posts', []);
|
|
|
|
// Alle Posts mit Votes holen
|
|
global $wpdb;
|
|
$posts_with_votes = $wpdb->get_col(
|
|
"SELECT DISTINCT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_dsv_votes'"
|
|
);
|
|
|
|
?>
|
|
<div class="wrap dsv-admin-wrap">
|
|
<h1>🚪 Tür-Status Voting</h1>
|
|
|
|
<div class="dsv-admin-grid">
|
|
|
|
<!-- Shortcode Info -->
|
|
<div class="dsv-admin-card">
|
|
<h2>Shortcode</h2>
|
|
<p>Füge das Voting-Widget mit folgendem Shortcode ein:</p>
|
|
<code class="dsv-shortcode">[door_status]</code>
|
|
<p class="description">
|
|
Der Shortcode verwendet automatisch die aktuelle Post-ID.
|
|
Du kannst ihn in Posts, Seiten oder Page-Builder einfügen.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Deaktivierte Posts -->
|
|
<div class="dsv-admin-card">
|
|
<h2>Voting deaktivieren</h2>
|
|
<p>Gib Post-IDs ein, für die das Voting deaktiviert werden soll (kommagetrennt):</p>
|
|
<form id="dsv-settings-form">
|
|
<textarea
|
|
name="disabled_posts"
|
|
id="dsv-disabled-posts"
|
|
class="large-text"
|
|
rows="3"
|
|
placeholder="z.B. 123, 456, 789"
|
|
><?php echo esc_textarea(implode(', ', $disabled_posts)); ?></textarea>
|
|
<p class="description">
|
|
Der Shortcode wird auf diesen Seiten nichts ausgeben.
|
|
</p>
|
|
<p>
|
|
<button type="submit" class="button button-primary">
|
|
Einstellungen speichern
|
|
</button>
|
|
<span class="dsv-save-status"></span>
|
|
</p>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Statistiken -->
|
|
<div class="dsv-admin-card dsv-admin-card-full">
|
|
<h2>Voting Übersicht</h2>
|
|
|
|
<?php if (empty($posts_with_votes)): ?>
|
|
<p class="dsv-no-data">Noch keine Votes vorhanden.</p>
|
|
<?php else: ?>
|
|
<p>
|
|
<button type="button" id="dsv-filter-mismatch" class="button">
|
|
Nur Abweichungen anzeigen
|
|
</button>
|
|
</p>
|
|
<table class="wp-list-table widefat fixed striped" id="dsv-votes-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Post</th>
|
|
<th>Meta-Status</th>
|
|
<th>Voting-Status</th>
|
|
<th>Geöffnet</th>
|
|
<th>Geschlossen</th>
|
|
<th>Gesamt</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($posts_with_votes as $pid):
|
|
$post = get_post($pid);
|
|
if (!$post) continue;
|
|
|
|
$votes = $this->get_votes($pid);
|
|
$total = $votes['open'] + $votes['closed'];
|
|
$is_disabled = in_array($pid, $disabled_posts);
|
|
|
|
if ($votes['open'] > $votes['closed']) {
|
|
$status_badge = '<span class="dsv-badge dsv-badge-open">Geöffnet</span>';
|
|
} elseif ($votes['closed'] > $votes['open']) {
|
|
$status_badge = '<span class="dsv-badge dsv-badge-closed">Geschlossen</span>';
|
|
} else {
|
|
$status_badge = '<span class="dsv-badge dsv-badge-tied">Unklar</span>';
|
|
}
|
|
|
|
// JetEngine Meta-Feld "status" auslesen
|
|
$meta_status = get_post_meta($pid, 'status', true);
|
|
$meta_status_lower = mb_strtolower(trim($meta_status));
|
|
if (in_array($meta_status_lower, ['geöffnet', 'geoeffnet', 'open', 'offen'])) {
|
|
$meta_badge_class = 'dsv-badge-open';
|
|
$meta_voting_match = ($votes['open'] > $votes['closed']);
|
|
} elseif (in_array($meta_status_lower, ['geschlossen', 'closed', 'zu'])) {
|
|
$meta_badge_class = 'dsv-badge-closed';
|
|
$meta_voting_match = ($votes['closed'] > $votes['open']);
|
|
} elseif (in_array($meta_status_lower, ['neuer betreiber'])) {
|
|
$meta_badge_class = 'dsv-badge-tied';
|
|
$meta_voting_match = false;
|
|
} elseif (!empty($meta_status)) {
|
|
$meta_badge_class = 'dsv-badge-tied';
|
|
$meta_voting_match = false;
|
|
} else {
|
|
$meta_badge_class = '';
|
|
$meta_voting_match = true; // kein Meta = kein Abweichung
|
|
}
|
|
|
|
if (!empty($meta_status)) {
|
|
$meta_status_display = '<span class="dsv-badge ' . $meta_badge_class . '">' . esc_html($meta_status) . '</span>';
|
|
} else {
|
|
$meta_status_display = '<span class="dsv-meta-empty">—</span>';
|
|
}
|
|
|
|
$row_mismatch = !$meta_voting_match;
|
|
?>
|
|
<tr data-post-id="<?php echo esc_attr($pid); ?>"<?php if ($row_mismatch): ?> class="dsv-mismatch"<?php endif; ?>>
|
|
<td>
|
|
<strong><a href="<?php echo get_edit_post_link($pid); ?>" target="_blank"><?php echo esc_html($post->post_title); ?></a></strong>
|
|
<br>
|
|
<small>ID: <?php echo $pid; ?></small>
|
|
<?php if ($is_disabled): ?>
|
|
<br><em class="dsv-disabled-label">Voting deaktiviert</em>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td class="dsv-meta-status-cell">
|
|
<?php echo $meta_status_display; ?>
|
|
<div class="dsv-meta-buttons">
|
|
<button type="button" class="button button-small dsv-meta-set-btn<?php echo ($meta_status_lower === 'geöffnet') ? ' active' : ''; ?>" data-post-id="<?php echo esc_attr($pid); ?>" data-status="geöffnet" title="Geöffnet">🟢</button>
|
|
<button type="button" class="button button-small dsv-meta-set-btn<?php echo ($meta_status_lower === 'geschlossen') ? ' active' : ''; ?>" data-post-id="<?php echo esc_attr($pid); ?>" data-status="geschlossen" title="Geschlossen">🔴</button>
|
|
</div>
|
|
</td>
|
|
<td><?php echo $status_badge; ?></td>
|
|
<td class="dsv-count-open"><?php echo $votes['open']; ?></td>
|
|
<td class="dsv-count-closed"><?php echo $votes['closed']; ?></td>
|
|
<td class="dsv-count-total"><?php echo $total; ?></td>
|
|
<td class="dsv-actions-cell">
|
|
<div class="dsv-action-buttons">
|
|
<button type="button"
|
|
class="button button-small dsv-reset-type-btn"
|
|
data-post-id="<?php echo esc_attr($pid); ?>"
|
|
data-type="open"
|
|
title="Alle 'Geöffnet' Stimmen löschen">
|
|
🟢 Löschen
|
|
</button>
|
|
<button type="button"
|
|
class="button button-small dsv-reset-type-btn"
|
|
data-post-id="<?php echo esc_attr($pid); ?>"
|
|
data-type="closed"
|
|
title="Alle 'Geschlossen' Stimmen löschen">
|
|
🔴 Löschen
|
|
</button>
|
|
<button type="button"
|
|
class="button button-small dsv-reset-btn"
|
|
data-post-id="<?php echo esc_attr($pid); ?>"
|
|
title="Alle Stimmen löschen">
|
|
Alle löschen
|
|
</button>
|
|
<a href="<?php echo get_permalink($pid); ?>"
|
|
target="_blank"
|
|
class="button button-small">
|
|
Ansehen
|
|
</a>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* AJAX: Einstellungen speichern
|
|
*/
|
|
public function save_settings() {
|
|
check_ajax_referer('dsv_admin_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => 'Keine Berechtigung']);
|
|
}
|
|
|
|
$disabled_posts_raw = sanitize_text_field($_POST['disabled_posts'] ?? '');
|
|
$disabled_posts = [];
|
|
|
|
if (!empty($disabled_posts_raw)) {
|
|
$ids = explode(',', $disabled_posts_raw);
|
|
foreach ($ids as $id) {
|
|
$id = intval(trim($id));
|
|
if ($id > 0) {
|
|
$disabled_posts[] = $id;
|
|
}
|
|
}
|
|
}
|
|
|
|
update_option('dsv_disabled_posts', $disabled_posts);
|
|
|
|
wp_send_json_success(['message' => 'Gespeichert']);
|
|
}
|
|
|
|
/**
|
|
* AJAX: Votes zurücksetzen
|
|
*/
|
|
public function reset_votes() {
|
|
check_ajax_referer('dsv_admin_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => 'Keine Berechtigung']);
|
|
}
|
|
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
|
|
if (!$post_id) {
|
|
wp_send_json_error(['message' => 'Ungültige Post ID']);
|
|
}
|
|
|
|
delete_post_meta($post_id, '_dsv_votes');
|
|
|
|
wp_send_json_success(['message' => 'Votes zurückgesetzt']);
|
|
}
|
|
|
|
/**
|
|
* AJAX: Votes nach Typ zurücksetzen (nur open oder nur closed)
|
|
*/
|
|
public function reset_votes_by_type() {
|
|
check_ajax_referer('dsv_admin_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => 'Keine Berechtigung']);
|
|
}
|
|
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
$type = sanitize_text_field($_POST['type'] ?? '');
|
|
|
|
if (!$post_id || !in_array($type, ['open', 'closed'])) {
|
|
wp_send_json_error(['message' => 'Ungültige Parameter']);
|
|
}
|
|
|
|
$data = get_post_meta($post_id, '_dsv_votes', true);
|
|
if (!is_array($data)) {
|
|
wp_send_json_error(['message' => 'Keine Votes vorhanden']);
|
|
}
|
|
|
|
// Nur Votes des angegebenen Typs entfernen
|
|
$removed = 0;
|
|
foreach ($data as $key => $vote) {
|
|
if ($vote === $type) {
|
|
unset($data[$key]);
|
|
$removed++;
|
|
}
|
|
}
|
|
|
|
update_post_meta($post_id, '_dsv_votes', $data);
|
|
|
|
// Neue Zahlen berechnen
|
|
$votes = $this->get_votes($post_id);
|
|
|
|
wp_send_json_success([
|
|
'message' => $removed . ' Stimmen gelöscht',
|
|
'votes' => $votes,
|
|
'removed' => $removed
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX: Meta-Status ändern
|
|
*/
|
|
public function update_meta_status() {
|
|
check_ajax_referer('dsv_admin_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error(['message' => 'Keine Berechtigung']);
|
|
}
|
|
|
|
$post_id = intval($_POST['post_id'] ?? 0);
|
|
$status = sanitize_text_field($_POST['status'] ?? '');
|
|
|
|
if (!$post_id || !in_array($status, ['geöffnet', 'geschlossen'])) {
|
|
wp_send_json_error(['message' => 'Ungültige Parameter']);
|
|
}
|
|
|
|
update_post_meta($post_id, 'status', $status);
|
|
|
|
wp_send_json_success(['message' => 'Status aktualisiert', 'status' => $status]);
|
|
}
|
|
}
|
|
|
|
// Plugin initialisieren
|
|
DoorStatusVoting::get_instance();
|
|
|
|
// Aktivierungs-Hook
|
|
register_activation_hook(__FILE__, function() {
|
|
add_option('dsv_disabled_posts', []);
|
|
});
|
|
|
|
// Deaktivierungs-Hook
|
|
register_deactivation_hook(__FILE__, function() {
|
|
// Optional: Daten behalten oder löschen
|
|
});
|