404 lines
13 KiB
PHP
404 lines
13 KiB
PHP
<?php
|
|
/**
|
|
* Gutschein-Verwaltung für Skrift Konfigurator
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) { exit; }
|
|
|
|
final class Skrift_Konfigurator_Vouchers {
|
|
|
|
const OPTION_KEY = 'skrift_konfigurator_vouchers';
|
|
|
|
public function __construct() {
|
|
add_action('admin_menu', [$this, 'add_menu_page']);
|
|
add_action('admin_init', [$this, 'register_settings']);
|
|
add_action('admin_post_sk_add_voucher', [$this, 'handle_add_voucher']);
|
|
add_action('admin_post_sk_delete_voucher', [$this, 'handle_delete_voucher']);
|
|
add_action('rest_api_init', [$this, 'register_rest_routes']);
|
|
}
|
|
|
|
public function add_menu_page(): void {
|
|
add_submenu_page(
|
|
'options-general.php',
|
|
'Skrift Gutscheine',
|
|
'Skrift Gutscheine',
|
|
'manage_options',
|
|
'skrift-vouchers',
|
|
[$this, 'render_vouchers_page']
|
|
);
|
|
}
|
|
|
|
public function register_settings(): void {
|
|
register_setting('skrift_vouchers', self::OPTION_KEY, [
|
|
'type' => 'array',
|
|
'sanitize_callback' => [$this, 'sanitize_vouchers'],
|
|
]);
|
|
}
|
|
|
|
public function sanitize_vouchers($input) {
|
|
if (!is_array($input)) {
|
|
return [];
|
|
}
|
|
|
|
$sanitized = [];
|
|
foreach ($input as $code => $voucher) {
|
|
// Verwende den originalen Code (in Großbuchstaben) als Key
|
|
$voucherCode = strtoupper(sanitize_text_field($voucher['code'] ?? ''));
|
|
$sanitized[$voucherCode] = [
|
|
'code' => $voucherCode,
|
|
'type' => in_array($voucher['type'] ?? '', ['percent', 'fixed']) ? $voucher['type'] : 'percent',
|
|
'value' => floatval($voucher['value'] ?? 0),
|
|
'expiry_date' => sanitize_text_field($voucher['expiry_date'] ?? ''),
|
|
'usage_limit' => intval($voucher['usage_limit'] ?? 0),
|
|
'usage_count' => intval($voucher['usage_count'] ?? 0),
|
|
];
|
|
}
|
|
|
|
return $sanitized;
|
|
}
|
|
|
|
public function handle_add_voucher(): void {
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die('Keine Berechtigung');
|
|
}
|
|
|
|
check_admin_referer('sk_add_voucher');
|
|
|
|
$vouchers = get_option(self::OPTION_KEY, []);
|
|
$code = strtoupper(sanitize_text_field($_POST['voucher_code'] ?? ''));
|
|
|
|
if (empty($code)) {
|
|
wp_redirect(add_query_arg(['page' => 'skrift-vouchers', 'error' => 'empty_code'], admin_url('options-general.php')));
|
|
exit;
|
|
}
|
|
|
|
if (isset($vouchers[$code])) {
|
|
wp_redirect(add_query_arg(['page' => 'skrift-vouchers', 'error' => 'duplicate'], admin_url('options-general.php')));
|
|
exit;
|
|
}
|
|
|
|
$vouchers[$code] = [
|
|
'code' => $code,
|
|
'type' => sanitize_text_field($_POST['voucher_type'] ?? 'percent'),
|
|
'value' => floatval($_POST['voucher_value'] ?? 0),
|
|
'expiry_date' => sanitize_text_field($_POST['voucher_expiry'] ?? ''),
|
|
'usage_limit' => intval($_POST['voucher_limit'] ?? 0),
|
|
'usage_count' => 0,
|
|
];
|
|
|
|
update_option(self::OPTION_KEY, $vouchers);
|
|
|
|
wp_redirect(add_query_arg(['page' => 'skrift-vouchers', 'success' => 'added'], admin_url('options-general.php')));
|
|
exit;
|
|
}
|
|
|
|
public function handle_delete_voucher(): void {
|
|
if (!current_user_can('manage_options')) {
|
|
wp_die('Keine Berechtigung');
|
|
}
|
|
|
|
check_admin_referer('sk_delete_voucher');
|
|
|
|
$code = sanitize_text_field($_GET['code'] ?? '');
|
|
$vouchers = get_option(self::OPTION_KEY, []);
|
|
|
|
if (isset($vouchers[$code])) {
|
|
unset($vouchers[$code]);
|
|
update_option(self::OPTION_KEY, $vouchers);
|
|
}
|
|
|
|
wp_redirect(add_query_arg(['page' => 'skrift-vouchers', 'success' => 'deleted'], admin_url('options-general.php')));
|
|
exit;
|
|
}
|
|
|
|
public function render_vouchers_page(): void {
|
|
if (!current_user_can('manage_options')) {
|
|
return;
|
|
}
|
|
|
|
$vouchers = get_option(self::OPTION_KEY, []);
|
|
?>
|
|
<div class="wrap">
|
|
<h1>Gutschein-Verwaltung</h1>
|
|
|
|
<?php if (isset($_GET['success'])): ?>
|
|
<div class="notice notice-success is-dismissible">
|
|
<p>
|
|
<?php
|
|
if ($_GET['success'] === 'added') {
|
|
echo 'Gutschein erfolgreich hinzugefügt!';
|
|
} elseif ($_GET['success'] === 'deleted') {
|
|
echo 'Gutschein erfolgreich gelöscht!';
|
|
}
|
|
?>
|
|
</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (isset($_GET['error'])): ?>
|
|
<div class="notice notice-error is-dismissible">
|
|
<p>
|
|
<?php
|
|
if ($_GET['error'] === 'empty_code') {
|
|
echo 'Gutscheincode darf nicht leer sein!';
|
|
} elseif ($_GET['error'] === 'duplicate') {
|
|
echo 'Dieser Gutscheincode existiert bereits!';
|
|
}
|
|
?>
|
|
</p>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div style="background: white; padding: 20px; margin-top: 20px; border: 1px solid #ccc;">
|
|
<h2>Neuen Gutschein erstellen</h2>
|
|
<form method="post" action="<?php echo admin_url('admin-post.php'); ?>">
|
|
<input type="hidden" name="action" value="sk_add_voucher">
|
|
<?php wp_nonce_field('sk_add_voucher'); ?>
|
|
|
|
<table class="form-table">
|
|
<tr>
|
|
<th scope="row"><label for="voucher_code">Gutscheincode *</label></th>
|
|
<td>
|
|
<input type="text" id="voucher_code" name="voucher_code" class="regular-text" required
|
|
style="text-transform: uppercase;" placeholder="z.B. SOMMER2025">
|
|
<p class="description">Code wird automatisch in Großbuchstaben umgewandelt</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><label for="voucher_type">Rabatt-Art *</label></th>
|
|
<td>
|
|
<select id="voucher_type" name="voucher_type" required>
|
|
<option value="percent">Prozent (%)</option>
|
|
<option value="fixed">Festbetrag (€)</option>
|
|
</select>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><label for="voucher_value">Rabatt-Wert *</label></th>
|
|
<td>
|
|
<input type="number" id="voucher_value" name="voucher_value" step="0.01" min="0" required
|
|
class="small-text">
|
|
<p class="description">Bei Prozent: z.B. 10 für 10% | Bei Festbetrag: z.B. 5.00 für 5€</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><label for="voucher_expiry">Ablaufdatum</label></th>
|
|
<td>
|
|
<input type="date" id="voucher_expiry" name="voucher_expiry" class="regular-text">
|
|
<p class="description">Leer lassen für unbegrenzte Gültigkeit</p>
|
|
</td>
|
|
</tr>
|
|
|
|
<tr>
|
|
<th scope="row"><label for="voucher_limit">Einlöse-Limit</label></th>
|
|
<td>
|
|
<input type="number" id="voucher_limit" name="voucher_limit" min="0" class="small-text" value="0">
|
|
<p class="description">0 = Unbegrenzt oft einlösbar</p>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<?php submit_button('Gutschein erstellen'); ?>
|
|
</form>
|
|
</div>
|
|
|
|
<div style="background: white; padding: 20px; margin-top: 20px; border: 1px solid #ccc;">
|
|
<h2>Vorhandene Gutscheine</h2>
|
|
|
|
<?php if (empty($vouchers)): ?>
|
|
<p>Noch keine Gutscheine vorhanden.</p>
|
|
<?php else: ?>
|
|
<table class="wp-list-table widefat fixed striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Code</th>
|
|
<th>Typ</th>
|
|
<th>Wert</th>
|
|
<th>Ablaufdatum</th>
|
|
<th>Limit</th>
|
|
<th>Eingelöst</th>
|
|
<th>Status</th>
|
|
<th>Aktionen</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($vouchers as $code => $voucher):
|
|
$is_expired = !empty($voucher['expiry_date']) && strtotime($voucher['expiry_date']) < time();
|
|
$is_used_up = $voucher['usage_limit'] > 0 && $voucher['usage_count'] >= $voucher['usage_limit'];
|
|
$is_active = !$is_expired && !$is_used_up;
|
|
?>
|
|
<tr>
|
|
<td><strong><?php echo esc_html($voucher['code']); ?></strong></td>
|
|
<td><?php echo $voucher['type'] === 'percent' ? 'Prozent' : 'Festbetrag'; ?></td>
|
|
<td>
|
|
<?php
|
|
if ($voucher['type'] === 'percent') {
|
|
echo number_format($voucher['value'], 1) . ' %';
|
|
} else {
|
|
echo number_format($voucher['value'], 2, ',', '.') . ' €';
|
|
}
|
|
?>
|
|
</td>
|
|
<td>
|
|
<?php
|
|
if (!empty($voucher['expiry_date'])) {
|
|
echo date('d.m.Y', strtotime($voucher['expiry_date']));
|
|
} else {
|
|
echo '—';
|
|
}
|
|
?>
|
|
</td>
|
|
<td><?php echo $voucher['usage_limit'] > 0 ? $voucher['usage_limit'] : 'Unbegrenzt'; ?></td>
|
|
<td><?php echo $voucher['usage_count']; ?></td>
|
|
<td>
|
|
<?php if ($is_active): ?>
|
|
<span style="color: green; font-weight: bold;">✓ Aktiv</span>
|
|
<?php elseif ($is_expired): ?>
|
|
<span style="color: red;">✗ Abgelaufen</span>
|
|
<?php elseif ($is_used_up): ?>
|
|
<span style="color: orange;">✗ Limit erreicht</span>
|
|
<?php endif; ?>
|
|
</td>
|
|
<td>
|
|
<a href="<?php echo wp_nonce_url(
|
|
admin_url('admin-post.php?action=sk_delete_voucher&code=' . urlencode($code)),
|
|
'sk_delete_voucher'
|
|
); ?>"
|
|
class="button button-small"
|
|
onclick="return confirm('Gutschein <?php echo esc_js($code); ?> wirklich löschen?');">
|
|
Löschen
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
/**
|
|
* Öffentliche Funktion um Gutscheine abzurufen
|
|
*/
|
|
public static function get_vouchers() {
|
|
return get_option(self::OPTION_KEY, []);
|
|
}
|
|
|
|
/**
|
|
* Validiert einen Gutschein
|
|
*/
|
|
public static function validate_voucher($code) {
|
|
$vouchers = self::get_vouchers();
|
|
$code = strtoupper(trim($code));
|
|
|
|
if (!isset($vouchers[$code])) {
|
|
return ['valid' => false, 'error' => 'Gutschein nicht gefunden'];
|
|
}
|
|
|
|
$voucher = $vouchers[$code];
|
|
|
|
// Ablaufdatum prüfen
|
|
if (!empty($voucher['expiry_date']) && strtotime($voucher['expiry_date']) < time()) {
|
|
return ['valid' => false, 'error' => 'Gutschein ist abgelaufen'];
|
|
}
|
|
|
|
// Nutzungslimit prüfen
|
|
if ($voucher['usage_limit'] > 0 && $voucher['usage_count'] >= $voucher['usage_limit']) {
|
|
return ['valid' => false, 'error' => 'Gutschein wurde bereits zu oft eingelöst'];
|
|
}
|
|
|
|
return [
|
|
'valid' => true,
|
|
'voucher' => $voucher
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Markiert einen Gutschein als verwendet
|
|
*/
|
|
public static function use_voucher($code) {
|
|
$vouchers = self::get_vouchers();
|
|
$code = strtoupper(trim($code));
|
|
|
|
if (isset($vouchers[$code])) {
|
|
$vouchers[$code]['usage_count']++;
|
|
update_option(self::OPTION_KEY, $vouchers);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* REST API Routen registrieren
|
|
*/
|
|
public function register_rest_routes() {
|
|
register_rest_route('skrift/v1', '/voucher/use', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'rest_use_voucher'],
|
|
'permission_callback' => ['Skrift_Konfigurator_Admin_Settings', 'rest_api_key_permission'],
|
|
]);
|
|
|
|
register_rest_route('skrift/v1', '/voucher/validate', [
|
|
'methods' => 'POST',
|
|
'callback' => [$this, 'rest_validate_voucher'],
|
|
'permission_callback' => ['Skrift_Konfigurator_Admin_Settings', 'rest_api_key_permission'],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* REST API Endpoint: Gutschein validieren
|
|
*/
|
|
public function rest_validate_voucher($request) {
|
|
$code = $request->get_param('code');
|
|
|
|
if (empty($code)) {
|
|
return new WP_Error('missing_code', 'Gutschein-Code fehlt', ['status' => 400]);
|
|
}
|
|
|
|
$result = self::validate_voucher($code);
|
|
|
|
if ($result['valid']) {
|
|
return [
|
|
'valid' => true,
|
|
'voucher' => [
|
|
'code' => $result['voucher']['code'],
|
|
'type' => $result['voucher']['type'],
|
|
'value' => $result['voucher']['value'],
|
|
]
|
|
];
|
|
} else {
|
|
return [
|
|
'valid' => false,
|
|
'error' => $result['error']
|
|
];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* REST API Endpoint: Gutschein als verwendet markieren
|
|
*/
|
|
public function rest_use_voucher($request) {
|
|
$code = $request->get_param('code');
|
|
|
|
if (empty($code)) {
|
|
return new WP_Error('missing_code', 'Gutschein-Code fehlt', ['status' => 400]);
|
|
}
|
|
|
|
$result = self::use_voucher($code);
|
|
|
|
if ($result) {
|
|
return ['success' => true, 'message' => 'Gutschein wurde als verwendet markiert'];
|
|
} else {
|
|
return new WP_Error('invalid_code', 'Ungültiger Gutschein-Code', ['status' => 404]);
|
|
}
|
|
}
|
|
}
|
|
|
|
new Skrift_Konfigurator_Vouchers();
|