Initial commit
This commit is contained in:
943
skrift-configurator/includes/admin-settings.php
Normal file
943
skrift-configurator/includes/admin-settings.php
Normal file
@@ -0,0 +1,943 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin Settings für Skrift Konfigurator
|
||||
* Verwaltung von Produkten, Preisen und Beschreibungen
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) { exit; }
|
||||
|
||||
class Skrift_Konfigurator_Admin_Settings {
|
||||
|
||||
const OPTION_KEY = 'skrift_konfigurator_settings';
|
||||
|
||||
public function __construct() {
|
||||
add_action('admin_menu', [$this, 'add_admin_menu']);
|
||||
add_action('admin_init', [$this, 'register_settings']);
|
||||
}
|
||||
|
||||
public function add_admin_menu(): void {
|
||||
add_options_page(
|
||||
'Skrift Konfigurator Einstellungen',
|
||||
'Skrift Konfigurator',
|
||||
'manage_options',
|
||||
'skrift-konfigurator',
|
||||
[$this, 'render_settings_page']
|
||||
);
|
||||
}
|
||||
|
||||
public function register_settings(): void {
|
||||
register_setting('skrift_konfigurator', self::OPTION_KEY, [
|
||||
'type' => 'array',
|
||||
'sanitize_callback' => [$this, 'sanitize_settings'],
|
||||
]);
|
||||
}
|
||||
|
||||
public function sanitize_settings($input) {
|
||||
$sanitized = [];
|
||||
|
||||
// Produkte sanitieren
|
||||
if (isset($input['products']) && is_array($input['products'])) {
|
||||
$sanitized['products'] = [];
|
||||
foreach ($input['products'] as $key => $product) {
|
||||
$sanitized['products'][sanitize_key($key)] = [
|
||||
'label' => sanitize_text_field($product['label'] ?? ''),
|
||||
'description' => sanitize_textarea_field($product['description'] ?? ''),
|
||||
'base_price' => floatval($product['base_price'] ?? 0),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Preise sanitieren
|
||||
if (isset($input['prices']) && is_array($input['prices'])) {
|
||||
$sanitized['prices'] = [];
|
||||
foreach ($input['prices'] as $key => $value) {
|
||||
$sanitized['prices'][sanitize_key($key)] = floatval($value);
|
||||
}
|
||||
}
|
||||
|
||||
// Dynamische Preisformeln sanitieren
|
||||
if (isset($input['dynamic_pricing'])) {
|
||||
$sanitized['dynamic_pricing'] = [
|
||||
'business_formula' => sanitize_textarea_field($input['dynamic_pricing']['business_formula'] ?? ''),
|
||||
'private_formula' => sanitize_textarea_field($input['dynamic_pricing']['private_formula'] ?? ''),
|
||||
'business_min_quantity' => intval($input['dynamic_pricing']['business_min_quantity'] ?? 0),
|
||||
'private_min_quantity' => intval($input['dynamic_pricing']['private_min_quantity'] ?? 0),
|
||||
'business_normal_quantity' => intval($input['dynamic_pricing']['business_normal_quantity'] ?? 0),
|
||||
'private_normal_quantity' => intval($input['dynamic_pricing']['private_normal_quantity'] ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
// Backend-Verbindung sanitieren
|
||||
if (isset($input['backend_connection'])) {
|
||||
$sanitized['backend_connection'] = [
|
||||
'api_url' => esc_url_raw($input['backend_connection']['api_url'] ?? ''),
|
||||
'api_token' => sanitize_text_field($input['backend_connection']['api_token'] ?? ''),
|
||||
'webhook_url_business' => esc_url_raw($input['backend_connection']['webhook_url_business'] ?? ''),
|
||||
'webhook_url_private' => esc_url_raw($input['backend_connection']['webhook_url_private'] ?? ''),
|
||||
'redirect_url_business' => esc_url_raw($input['backend_connection']['redirect_url_business'] ?? ''),
|
||||
'redirect_url_private' => esc_url_raw($input['backend_connection']['redirect_url_private'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
// REST API Key sanitieren
|
||||
if (isset($input['api_security'])) {
|
||||
$sanitized['api_security'] = [
|
||||
'api_key' => sanitize_text_field($input['api_security']['api_key'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
// PayPal-Verbindung sanitieren
|
||||
if (isset($input['paypal'])) {
|
||||
$sanitized['paypal'] = [
|
||||
'enabled' => !empty($input['paypal']['enabled']),
|
||||
'mode' => sanitize_text_field($input['paypal']['mode'] ?? 'sandbox'),
|
||||
'client_id_sandbox' => sanitize_text_field($input['paypal']['client_id_sandbox'] ?? ''),
|
||||
'client_secret_sandbox' => sanitize_text_field($input['paypal']['client_secret_sandbox'] ?? ''),
|
||||
'client_id_live' => sanitize_text_field($input['paypal']['client_id_live'] ?? ''),
|
||||
'client_secret_live' => sanitize_text_field($input['paypal']['client_secret_live'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
// Schriftmuster und Platzhalter-Hilfe sanitieren
|
||||
if (isset($input['font_sample'])) {
|
||||
$sanitized['font_sample'] = [
|
||||
'url' => esc_url_raw($input['font_sample']['url'] ?? ''),
|
||||
'placeholder_help_url' => esc_url_raw($input['font_sample']['placeholder_help_url'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
public function render_settings_page(): void {
|
||||
if (!current_user_can('manage_options')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = $this->get_settings();
|
||||
?>
|
||||
<style>
|
||||
.sk-admin-wrap { max-width: 1200px; }
|
||||
.sk-admin-section { background: #fff; padding: 20px; margin: 20px 0; border: 1px solid #ccd0d4; box-shadow: 0 1px 1px rgba(0,0,0,.04); }
|
||||
.sk-admin-section h2 { margin-top: 0; padding-bottom: 10px; border-bottom: 1px solid #eee; }
|
||||
.sk-product-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); gap: 20px; margin-top: 20px; }
|
||||
.sk-product-card { background: #f9f9f9; padding: 15px; border: 1px solid #ddd; border-radius: 4px; }
|
||||
.sk-product-card h3 { margin-top: 0; color: #0073aa; font-size: 16px; }
|
||||
.sk-field-row { margin-bottom: 15px; }
|
||||
.sk-field-row label { display: block; font-weight: 600; margin-bottom: 5px; }
|
||||
.sk-field-row input[type="text"], .sk-field-row textarea { width: 100%; }
|
||||
.sk-field-row input[type="number"] { width: 120px; }
|
||||
.sk-price-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 15px; margin-top: 15px; }
|
||||
.sk-price-item { background: #f9f9f9; padding: 12px; border-left: 3px solid #0073aa; }
|
||||
.sk-price-item label { display: flex; justify-content: space-between; align-items: center; }
|
||||
.sk-price-item strong { color: #23282d; }
|
||||
.sk-multiplier-table { width: 100%; border-collapse: collapse; margin-top: 10px; }
|
||||
.sk-multiplier-table th, .sk-multiplier-table td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
|
||||
.sk-multiplier-table th { background: #f0f0f1; font-weight: 600; }
|
||||
.sk-multiplier-table input[type="number"] { width: 100px; }
|
||||
</style>
|
||||
<div class="wrap sk-admin-wrap">
|
||||
<h1><?php echo esc_html(get_admin_page_title()); ?></h1>
|
||||
<form method="post" action="options.php">
|
||||
<?php
|
||||
settings_fields('skrift_konfigurator');
|
||||
do_settings_sections('skrift_konfigurator');
|
||||
?>
|
||||
|
||||
<!-- Produkte -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>📦 Produkte</h2>
|
||||
<p>Verwalten Sie Namen, Beschreibungen und Startpreise für alle Produkte.</p>
|
||||
|
||||
<div class="sk-product-grid">
|
||||
<?php $this->render_product_card('businessbriefe', 'Businessbriefe', $settings); ?>
|
||||
<?php $this->render_product_card('business-postkarten', 'Business Postkarten', $settings); ?>
|
||||
<?php $this->render_product_card('follow-ups', 'Follow-ups', $settings); ?>
|
||||
<?php $this->render_product_card('einladungen', 'Einladungen', $settings); ?>
|
||||
<?php $this->render_product_card('private-briefe', 'Private Briefe', $settings); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Format Aufpreise -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>📐 Format Aufpreise</h2>
|
||||
<p>Aufpreise wenn bei bestimmten Produkten das Format gewechselt wird.</p>
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>A4 Aufpreis (Follow-ups/Einladungen)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][a4_upgrade_surcharge]"
|
||||
value="<?php echo esc_attr($settings['prices']['a4_upgrade_surcharge'] ?? '0.50'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Aufpreis pro Stück wenn bei Postkarten oder Einladungen auf A4 gewechselt wird</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Versand & Umschlag -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>🚚 Versand & Umschlag</h2>
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Porto Inland / Deutschland (pro Stück)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][shipping_domestic]"
|
||||
value="<?php echo esc_attr($settings['prices']['shipping_domestic'] ?? '0.95'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Portokosten für Versand innerhalb Deutschlands (0% MwSt.)</small>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Porto Ausland (pro Stück)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][shipping_international]"
|
||||
value="<?php echo esc_attr($settings['prices']['shipping_international'] ?? '1.25'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Portokosten für Auslandsversand (0% MwSt.)</small>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Serviceaufschlag Versand (pro Stück)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][shipping_service]"
|
||||
value="<?php echo esc_attr($settings['prices']['shipping_service'] ?? '0.95'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Service-Aufschlag für Direktversand (19% MwSt.)</small>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Bulkversand (einmalig)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][shipping_bulk]"
|
||||
value="<?php echo esc_attr($settings['prices']['shipping_bulk'] ?? '4.95'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Kuvert (Grundpreis pro Stück)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][envelope_base]"
|
||||
value="<?php echo esc_attr($settings['prices']['envelope_base'] ?? '0.50'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Grundpreis für Kuvert</small>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Aufschlag Beschriftung (pro Stück)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][envelope_labeling]"
|
||||
value="<?php echo esc_attr($settings['prices']['envelope_labeling'] ?? '0.50'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Aufschlag für Beschriftung des Umschlags (Empfängeradresse oder individueller Text)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Zusatzleistungen -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>✨ Zusatzleistungen</h2>
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Motiv Upload <span style="color: #0073aa; font-size: 12px;">(einmalig)</span></strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][motif_upload]"
|
||||
value="<?php echo esc_attr($settings['prices']['motif_upload'] ?? '0.30'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Bedruckte Karten zusenden (pro Stück)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][motif_printed]"
|
||||
value="<?php echo esc_attr($settings['prices']['motif_printed'] ?? '0.00'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Designservice <span style="color: #0073aa; font-size: 12px;">(einmalig)</span></strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][motif_design]"
|
||||
value="<?php echo esc_attr($settings['prices']['motif_design'] ?? '0.00'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Textservice <span style="color: #0073aa; font-size: 12px;">(einmalig)</span></strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][textservice]"
|
||||
value="<?php echo esc_attr($settings['prices']['textservice'] ?? '0.00'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>API-Anbindung <span style="color: #0073aa; font-size: 12px;">(einmalig)</span></strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][api_connection]"
|
||||
value="<?php echo esc_attr($settings['prices']['api_connection'] ?? '250.00'); ?>"> €
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Einmalige Einrichtungsgebühr für die API-Anbindung</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Follow-ups Mengenstaffel -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>📊 Follow-ups Preis-Multiplikatoren</h2>
|
||||
<p>Die Gesamtkosten pro Schriftstück werden mit diesen Multiplikatoren je nach Menge multipliziert.</p>
|
||||
|
||||
<table class="sk-multiplier-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Menge</th>
|
||||
<th>Multiplikator</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>5 - 49 Stück</strong></td>
|
||||
<td>
|
||||
<input type="number" step="0.1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][followup_mult_5_49]"
|
||||
value="<?php echo esc_attr($settings['prices']['followup_mult_5_49'] ?? '2.0'); ?>">
|
||||
<small style="margin-left: 10px; color: #666;">×</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>50 - 199 Stück</strong></td>
|
||||
<td>
|
||||
<input type="number" step="0.1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][followup_mult_50_199]"
|
||||
value="<?php echo esc_attr($settings['prices']['followup_mult_50_199'] ?? '1.7'); ?>">
|
||||
<small style="margin-left: 10px; color: #666;">×</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>200 - 499 Stück</strong></td>
|
||||
<td>
|
||||
<input type="number" step="0.1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][followup_mult_200_499]"
|
||||
value="<?php echo esc_attr($settings['prices']['followup_mult_200_499'] ?? '1.4'); ?>">
|
||||
<small style="margin-left: 10px; color: #666;">×</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>500 - 999 Stück</strong></td>
|
||||
<td>
|
||||
<input type="number" step="0.1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][followup_mult_500_999]"
|
||||
value="<?php echo esc_attr($settings['prices']['followup_mult_500_999'] ?? '1.2'); ?>">
|
||||
<small style="margin-left: 10px; color: #666;">×</small>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>1000+ Stück</strong></td>
|
||||
<td>
|
||||
<input type="number" step="0.1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][followup_mult_1000_plus]"
|
||||
value="<?php echo esc_attr($settings['prices']['followup_mult_1000_plus'] ?? '1.0'); ?>">
|
||||
<small style="margin-left: 10px; color: #666;">×</small>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Steuern -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>📋 Steuern</h2>
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Mehrwertsteuersatz (%)</strong>
|
||||
<span>
|
||||
<input type="number" step="0.01" min="0" max="100"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[prices][tax_rate]"
|
||||
value="<?php echo esc_attr($settings['prices']['tax_rate'] ?? '19'); ?>"> %
|
||||
</span>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Gilt für alle Positionen inkl. Versand</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dynamische Preisberechnung -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>🧮 Dynamische Preisberechnung</h2>
|
||||
<p>Konfigurieren Sie die dynamische Preisberechnung basierend auf Mengen. Die Formeln unterstützen Platzhalter wie <code>%qty%</code> (aktuelle Menge), <code>%norm_b%</code> (Normalpreis Menge Business), <code>%mind_b%</code> (Mind. Menge Business), <code>%norm_p%</code> (Normalpreis Menge Privat), <code>%mind_p%</code> (Mind. Menge Privat).</p>
|
||||
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-top: 20px;">
|
||||
|
||||
<!-- Business -->
|
||||
<div style="background: #f9f9f9; padding: 20px; border: 1px solid #ddd; border-radius: 4px;">
|
||||
<h3 style="margin-top: 0; color: #0073aa;">Business</h3>
|
||||
|
||||
<div class="sk-field-row">
|
||||
<label><strong>Mindestmenge Business</strong></label>
|
||||
<input type="number" step="1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[dynamic_pricing][business_min_quantity]"
|
||||
value="<?php echo esc_attr($settings['dynamic_pricing']['business_min_quantity'] ?? '50'); ?>"
|
||||
style="width: 150px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Minimale Menge für Business-Bestellungen (außer Follow-ups)</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-field-row" style="margin-top: 15px;">
|
||||
<label><strong>Normalpreis Menge Business</strong></label>
|
||||
<input type="number" step="1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[dynamic_pricing][business_normal_quantity]"
|
||||
value="<?php echo esc_attr($settings['dynamic_pricing']['business_normal_quantity'] ?? '200'); ?>"
|
||||
style="width: 150px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Ab dieser Menge gilt der Normalpreis (Multiplikator = 1)</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-field-row" style="margin-top: 15px;">
|
||||
<label><strong>Dynamische Formel Business</strong></label>
|
||||
<textarea
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[dynamic_pricing][business_formula]"
|
||||
rows="8"
|
||||
style="width: 100%; font-family: monospace; font-size: 12px;"
|
||||
placeholder="(%qty% >= %norm_b%) ? 1 : (2 - Math.sqrt(%qty% / %norm_b%))"><?php echo esc_textarea($settings['dynamic_pricing']['business_formula'] ?? ''); ?></textarea>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">
|
||||
<strong>JavaScript-Formel zur Berechnung des Preis-Multiplikators.</strong><br>
|
||||
Platzhalter verwenden: <code>%qty%</code> für aktuelle Menge, <code>%norm_b%</code> für Normalpreis-Menge Business, <code>%mind_b%</code> für Mindestmenge Business.<br>
|
||||
Beispiel: <code>(%qty% >= %norm_b%) ? 1 : (2 - Math.sqrt(%qty% / %norm_b%))</code><br>
|
||||
Dies bedeutet: Wenn die Menge >= Normalpreis-Menge ist, dann Multiplikator = 1, sonst dynamische Berechnung.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Privat -->
|
||||
<div style="background: #f9f9f9; padding: 20px; border: 1px solid #ddd; border-radius: 4px;">
|
||||
<h3 style="margin-top: 0; color: #0073aa;">Privat</h3>
|
||||
|
||||
<div class="sk-field-row">
|
||||
<label><strong>Mindestmenge Privat</strong></label>
|
||||
<input type="number" step="1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[dynamic_pricing][private_min_quantity]"
|
||||
value="<?php echo esc_attr($settings['dynamic_pricing']['private_min_quantity'] ?? '10'); ?>"
|
||||
style="width: 150px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Minimale Menge für Private Bestellungen</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-field-row" style="margin-top: 15px;">
|
||||
<label><strong>Normalpreis Menge Privat</strong></label>
|
||||
<input type="number" step="1" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[dynamic_pricing][private_normal_quantity]"
|
||||
value="<?php echo esc_attr($settings['dynamic_pricing']['private_normal_quantity'] ?? '50'); ?>"
|
||||
style="width: 150px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Ab dieser Menge gilt der Normalpreis (Multiplikator = 1)</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-field-row" style="margin-top: 15px;">
|
||||
<label><strong>Dynamische Formel Privat</strong></label>
|
||||
<textarea
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[dynamic_pricing][private_formula]"
|
||||
rows="8"
|
||||
style="width: 100%; font-family: monospace; font-size: 12px;"
|
||||
placeholder="(%qty% >= %norm_p%) ? 1 : (2 - Math.sqrt(%qty% / %norm_p%))"><?php echo esc_textarea($settings['dynamic_pricing']['private_formula'] ?? ''); ?></textarea>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">
|
||||
<strong>JavaScript-Formel zur Berechnung des Preis-Multiplikators.</strong><br>
|
||||
Platzhalter verwenden: <code>%qty%</code> für aktuelle Menge, <code>%norm_p%</code> für Normalpreis-Menge Privat, <code>%mind_p%</code> für Mindestmenge Privat.<br>
|
||||
Beispiel: <code>(%qty% >= %norm_p%) ? 1 : (2 - Math.sqrt(%qty% / %norm_p%))</code><br>
|
||||
Dies bedeutet: Wenn die Menge >= Normalpreis-Menge ist, dann Multiplikator = 1, sonst dynamische Berechnung.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px; padding: 15px; background: #fff3cd; border-left: 4px solid #ffc107;">
|
||||
<strong>Verfügbare Platzhalter:</strong>
|
||||
<ul style="margin: 10px 0 0 20px;">
|
||||
<li><code>%qty%</code> - Aktuelle Menge (eingegebene Stückzahl)</li>
|
||||
<li><code>%norm_b%</code> - Normalpreis Menge Business</li>
|
||||
<li><code>%mind_b%</code> - Mindestmenge Business</li>
|
||||
<li><code>%norm_p%</code> - Normalpreis Menge Privat</li>
|
||||
<li><code>%mind_p%</code> - Mindestmenge Privat</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Backend-Verbindung -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>🔌 Backend-Verbindung</h2>
|
||||
<p>Konfigurieren Sie die Verbindung zum Backend-System für erweiterte Funktionen.</p>
|
||||
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>API URL / Domain</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[backend_connection][api_url]"
|
||||
value="<?php echo esc_attr($settings['backend_connection']['api_url'] ?? ''); ?>"
|
||||
placeholder="https://api.example.com"
|
||||
style="width: 100%; margin-top: 8px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Basis-URL des Backend-Systems (z.B. https://api.example.com)</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>API Token / Authentifizierung</strong>
|
||||
</label>
|
||||
<input type="text"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[backend_connection][api_token]"
|
||||
value="<?php echo esc_attr($settings['backend_connection']['api_token'] ?? ''); ?>"
|
||||
placeholder="sk_live_..."
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Authentifizierungs-Token für API-Zugriff</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Webhook URL Geschäftskunden (B2B)</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[backend_connection][webhook_url_business]"
|
||||
value="<?php echo esc_attr($settings['backend_connection']['webhook_url_business'] ?? ''); ?>"
|
||||
placeholder="https://api.example.com/webhooks/order-business"
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Webhook wird nach Klick auf "Jetzt kostenpflichtig bestellen" für Geschäftskunden aufgerufen</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Webhook URL Privatkunden (B2C)</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[backend_connection][webhook_url_private]"
|
||||
value="<?php echo esc_attr($settings['backend_connection']['webhook_url_private'] ?? ''); ?>"
|
||||
placeholder="https://api.example.com/webhooks/order-private"
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Webhook wird nach erfolgreicher PayPal-Zahlung für Privatkunden aufgerufen</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Redirect URL Geschäftskunden</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[backend_connection][redirect_url_business]"
|
||||
value="<?php echo esc_attr($settings['backend_connection']['redirect_url_business'] ?? ''); ?>"
|
||||
placeholder="https://example.com/danke-business"
|
||||
style="width: 100%; margin-top: 8px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Weiterleitung nach Bestellung für Geschäftskunden (nach Klick auf "Jetzt kostenpflichtig bestellen")</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Redirect URL Privatkunden</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[backend_connection][redirect_url_private]"
|
||||
value="<?php echo esc_attr($settings['backend_connection']['redirect_url_private'] ?? ''); ?>"
|
||||
placeholder="https://example.com/danke-privat"
|
||||
style="width: 100%; margin-top: 8px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Weiterleitung nach erfolgreicher PayPal-Zahlung für Privatkunden</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- REST API Security -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>🔐 REST API Sicherheit</h2>
|
||||
<p>Konfigurieren Sie einen API-Key für die REST-API-Endpunkte. Dieser Key muss im Header <code>X-Skrift-API-Key</code> mitgesendet werden.</p>
|
||||
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item" style="grid-column: 1 / -1;">
|
||||
<label>
|
||||
<strong>API Key</strong>
|
||||
</label>
|
||||
<div style="display: flex; gap: 10px; margin-top: 8px;">
|
||||
<input type="text" id="sk-api-key-input"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[api_security][api_key]"
|
||||
value="<?php echo esc_attr($settings['api_security']['api_key'] ?? ''); ?>"
|
||||
placeholder="sk_api_..."
|
||||
style="flex: 1; font-family: monospace;">
|
||||
<button type="button" class="button" onclick="document.getElementById('sk-api-key-input').value = 'sk_api_' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);">
|
||||
Generieren
|
||||
</button>
|
||||
</div>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Leer lassen um API-Key-Prüfung zu deaktivieren (nicht empfohlen für Produktion)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Schriftmuster Fallback -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>✍️ Schriftmuster (Vorschau-Fallback)</h2>
|
||||
<p>Wenn die Vorschau-Generierung fehlschlägt oder nicht verfügbar ist, wird ein "Schriftmuster ansehen"-Link angezeigt. Der Link öffnet sich in einem neuen Tab.</p>
|
||||
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item" style="grid-column: 1 / -1;">
|
||||
<label>
|
||||
<strong>Schriftmuster-URL</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[font_sample][url]"
|
||||
value="<?php echo esc_attr($settings['font_sample']['url'] ?? ''); ?>"
|
||||
placeholder="https://example.com/schriftmuster"
|
||||
style="width: 100%; margin-top: 8px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">URL zur Schriftmuster-Seite (wird in neuem Tab geöffnet)</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item" style="grid-column: 1 / -1;">
|
||||
<label>
|
||||
<strong>Platzhalter-Hilfe URL</strong>
|
||||
</label>
|
||||
<input type="url"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[font_sample][placeholder_help_url]"
|
||||
value="<?php echo esc_attr($settings['font_sample']['placeholder_help_url'] ?? ''); ?>"
|
||||
placeholder="https://example.com/platzhalter-hilfe"
|
||||
style="width: 100%; margin-top: 8px;">
|
||||
<small style="display: block; margin-top: 5px; color: #666;">URL zur Platzhalter-Hilfeseite (wird bei Platzhalter-Infotexten als Link angezeigt)</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PayPal-Verbindung -->
|
||||
<div class="sk-admin-section">
|
||||
<h2>💳 PayPal-Verbindung (nur Privatkunden)</h2>
|
||||
<p>Konfigurieren Sie die PayPal-Zahlungsintegration. PayPal ist nur für Privatkunden aktiviert.</p>
|
||||
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item" style="grid-column: 1 / -1;">
|
||||
<label style="display: flex; align-items: center; gap: 10px;">
|
||||
<input type="checkbox"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[paypal][enabled]"
|
||||
value="1"
|
||||
<?php checked($settings['paypal']['enabled'] ?? false); ?>>
|
||||
<strong>PayPal-Zahlung aktivieren</strong>
|
||||
</label>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Aktiviert PayPal als Zahlungsoption für Privatkunden</small>
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item" style="grid-column: 1 / -1;">
|
||||
<label>
|
||||
<strong>Modus</strong>
|
||||
</label>
|
||||
<select
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[paypal][mode]"
|
||||
style="width: 200px; margin-top: 8px;">
|
||||
<option value="sandbox" <?php selected(($settings['paypal']['mode'] ?? 'sandbox'), 'sandbox'); ?>>Sandbox (Test)</option>
|
||||
<option value="live" <?php selected(($settings['paypal']['mode'] ?? 'sandbox'), 'live'); ?>>Live (Produktion)</option>
|
||||
</select>
|
||||
<small style="display: block; margin-top: 5px; color: #666;">Sandbox für Tests, Live für echte Zahlungen</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd;">Sandbox-Zugangsdaten (Test)</h3>
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Client ID (Sandbox)</strong>
|
||||
</label>
|
||||
<input type="text"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[paypal][client_id_sandbox]"
|
||||
value="<?php echo esc_attr($settings['paypal']['client_id_sandbox'] ?? ''); ?>"
|
||||
placeholder="AZn4..."
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Client Secret (Sandbox)</strong>
|
||||
</label>
|
||||
<input type="password"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[paypal][client_secret_sandbox]"
|
||||
value="<?php echo esc_attr($settings['paypal']['client_secret_sandbox'] ?? ''); ?>"
|
||||
placeholder="EL3..."
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #ddd;">Live-Zugangsdaten (Produktion)</h3>
|
||||
<div class="sk-price-grid">
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Client ID (Live)</strong>
|
||||
</label>
|
||||
<input type="text"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[paypal][client_id_live]"
|
||||
value="<?php echo esc_attr($settings['paypal']['client_id_live'] ?? ''); ?>"
|
||||
placeholder="AZn4..."
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
</div>
|
||||
|
||||
<div class="sk-price-item">
|
||||
<label>
|
||||
<strong>Client Secret (Live)</strong>
|
||||
</label>
|
||||
<input type="password"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[paypal][client_secret_live]"
|
||||
value="<?php echo esc_attr($settings['paypal']['client_secret_live'] ?? ''); ?>"
|
||||
placeholder="EL3..."
|
||||
style="width: 100%; margin-top: 8px; font-family: monospace;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px; padding: 15px; background: #e7f3ff; border-left: 4px solid #2196f3;">
|
||||
<strong>Hinweis:</strong> Um PayPal zu aktivieren, benötigen Sie ein PayPal Business-Konto.
|
||||
Sie erhalten die API-Zugangsdaten im <a href="https://developer.paypal.com/dashboard/applications/" target="_blank">PayPal Developer Dashboard</a>.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php submit_button('Einstellungen speichern'); ?>
|
||||
</form>
|
||||
|
||||
<!-- URL Parameter Dokumentation -->
|
||||
<div class="sk-section" style="margin-top: 40px; padding: 20px; background: #f9f9f9; border: 1px solid #ddd; border-radius: 8px;">
|
||||
<h2 style="margin-top: 0;">URL-Parameter</h2>
|
||||
<p>Der Konfigurator unterstützt folgende URL-Parameter:</p>
|
||||
|
||||
<table class="widefat" style="margin-top: 15px;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 200px;">Parameter</th>
|
||||
<th style="width: 200px;">Werte</th>
|
||||
<th>Beschreibung</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>?businessbriefe</code><br>
|
||||
<code>?business-postkarten</code><br>
|
||||
<code>?follow-ups</code><br>
|
||||
<code>?einladungen</code><br>
|
||||
<code>?private-briefe</code></td>
|
||||
<td>–</td>
|
||||
<td>Produkt direkt vorauswählen. Der Produktauswahlschritt wird übersprungen.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>quantity</code></td>
|
||||
<td>Zahl (z.B. <code>100</code>)</td>
|
||||
<td>Menge vorausfüllen.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>format</code></td>
|
||||
<td><code>a4</code>, <code>a6h</code>, <code>a6q</code></td>
|
||||
<td>Format vorauswählen. <code>a6h</code> = A6 Hochformat, <code>a6q</code> = A6 Querformat.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>noPrice</code></td>
|
||||
<td>–</td>
|
||||
<td>Preise im Konfigurator ausblenden.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>noLimits</code></td>
|
||||
<td>–</td>
|
||||
<td>Keine Mindestmengen. Erlaubt Bestellungen ab 1 Stück.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h3 style="margin-top: 25px;">Beispiele</h3>
|
||||
<ul style="margin-left: 20px;">
|
||||
<li><code>/konfigurator/?businessbriefe</code> – Direkt zu Business Briefe</li>
|
||||
<li><code>/konfigurator/?einladungen&quantity=25&format=a6h</code> – Einladungen mit 25 Stück im A6 Hochformat</li>
|
||||
<li><code>/konfigurator/?businessbriefe&noPrice</code> – Business Briefe ohne Preisanzeige</li>
|
||||
<li><code>/konfigurator/?private-briefe&noLimits</code> – Private Briefe ohne Mindestmenge</li>
|
||||
<li><code>/konfigurator/?business-postkarten&noLimits&noPrice</code> – Postkarten ohne Mindestmenge und ohne Preise</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function render_product_card(string $key, string $default_label, array $settings): void {
|
||||
$label = $settings['products'][$key]['label'] ?? $default_label;
|
||||
$description = $settings['products'][$key]['description'] ?? 'Professionelle handgeschriebene Korrespondenz';
|
||||
$base_price = $settings['products'][$key]['base_price'] ?? '2.50';
|
||||
?>
|
||||
<div class="sk-product-card">
|
||||
<h3><?php echo esc_html($default_label); ?></h3>
|
||||
|
||||
<div class="sk-field-row">
|
||||
<label>Produktname</label>
|
||||
<input type="text"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[products][<?php echo esc_attr($key); ?>][label]"
|
||||
value="<?php echo esc_attr($label); ?>"
|
||||
placeholder="<?php echo esc_attr($default_label); ?>">
|
||||
</div>
|
||||
|
||||
<div class="sk-field-row">
|
||||
<label>Beschreibung</label>
|
||||
<textarea
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[products][<?php echo esc_attr($key); ?>][description]"
|
||||
rows="3"
|
||||
placeholder="Professionelle handgeschriebene Korrespondenz"><?php echo esc_textarea($description); ?></textarea>
|
||||
</div>
|
||||
|
||||
<div class="sk-field-row">
|
||||
<label>Startpreis (ab)</label>
|
||||
<div>
|
||||
<input type="number" step="0.01" min="0"
|
||||
name="<?php echo esc_attr(self::OPTION_KEY); ?>[products][<?php echo esc_attr($key); ?>][base_price]"
|
||||
value="<?php echo esc_attr($base_price); ?>"> €
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public static function get_settings(): array {
|
||||
$defaults = [
|
||||
'products' => [
|
||||
'businessbriefe' => [
|
||||
'label' => 'Businessbriefe',
|
||||
'description' => 'Professionelle handgeschriebene Korrespondenz',
|
||||
'base_price' => 2.50,
|
||||
],
|
||||
'business-postkarten' => [
|
||||
'label' => 'Business Postkarten',
|
||||
'description' => 'Professionelle handgeschriebene Korrespondenz',
|
||||
'base_price' => 1.80,
|
||||
],
|
||||
'follow-ups' => [
|
||||
'label' => 'Follow-ups',
|
||||
'description' => 'Professionelle handgeschriebene Korrespondenz',
|
||||
'base_price' => 2.50,
|
||||
],
|
||||
'einladungen' => [
|
||||
'label' => 'Einladungen',
|
||||
'description' => 'Professionelle handgeschriebene Korrespondenz',
|
||||
'base_price' => 1.80,
|
||||
],
|
||||
'private-briefe' => [
|
||||
'label' => 'Private Briefe',
|
||||
'description' => 'Professionelle handgeschriebene Korrespondenz',
|
||||
'base_price' => 2.50,
|
||||
],
|
||||
],
|
||||
'prices' => [
|
||||
// Versand & Umschlag
|
||||
'shipping_domestic' => 0.95, // Porto Inland
|
||||
'shipping_international' => 1.25, // Porto Ausland
|
||||
'shipping_service' => 0.95, // Serviceaufschlag Versand
|
||||
'shipping_bulk' => 4.95, // Bulkversand einmalig
|
||||
'envelope_base' => 0.50, // Kuvert Grundpreis
|
||||
'envelope_labeling' => 0.50, // Aufschlag Beschriftung
|
||||
// Legacy fields for backwards compatibility
|
||||
'shipping_direct' => 2.40,
|
||||
'envelope_recipient_address' => 0.50,
|
||||
'envelope_custom_text' => 0.30,
|
||||
|
||||
// Format Aufpreise
|
||||
'a4_upgrade_surcharge' => 0.50,
|
||||
|
||||
// Zusatzleistungen
|
||||
'motif_upload' => 0.30,
|
||||
'motif_printed' => 0.00,
|
||||
'motif_design' => 0.00,
|
||||
'textservice' => 0.00,
|
||||
'api_connection' => 250.00,
|
||||
|
||||
// Follow-ups Multiplikatoren
|
||||
'followup_mult_5_49' => 2.0,
|
||||
'followup_mult_50_199' => 1.7,
|
||||
'followup_mult_200_499' => 1.4,
|
||||
'followup_mult_500_999' => 1.2,
|
||||
'followup_mult_1000_plus' => 1.0,
|
||||
|
||||
// Steuern
|
||||
'tax_rate' => 19,
|
||||
'shipping_tax_rate' => 0,
|
||||
],
|
||||
'dynamic_pricing' => [
|
||||
'business_formula' => "(%qty% >= %norm_b%) ? 1 : (2 - Math.sqrt(%qty% / %norm_b%))",
|
||||
'private_formula' => "(%qty% >= %norm_p%) ? 1 : (2 - Math.sqrt(%qty% / %norm_p%))",
|
||||
'business_min_quantity' => 50,
|
||||
'private_min_quantity' => 10,
|
||||
'business_normal_quantity' => 200,
|
||||
'private_normal_quantity' => 50,
|
||||
],
|
||||
'backend_connection' => [
|
||||
'api_url' => '',
|
||||
'api_token' => '',
|
||||
'webhook_url_business' => '',
|
||||
'webhook_url_private' => '',
|
||||
'redirect_url_business' => '',
|
||||
'redirect_url_private' => '',
|
||||
],
|
||||
'paypal' => [
|
||||
'enabled' => false,
|
||||
'mode' => 'sandbox',
|
||||
'client_id_sandbox' => '',
|
||||
'client_secret_sandbox' => '',
|
||||
'client_id_live' => '',
|
||||
'client_secret_live' => '',
|
||||
],
|
||||
'api_security' => [
|
||||
'api_key' => '',
|
||||
],
|
||||
'font_sample' => [
|
||||
'url' => '',
|
||||
'placeholder_help_url' => '',
|
||||
],
|
||||
];
|
||||
|
||||
$saved = get_option(self::OPTION_KEY, []);
|
||||
|
||||
// Merge nested arrays properly
|
||||
$merged = $defaults;
|
||||
foreach (['products', 'prices', 'dynamic_pricing', 'backend_connection', 'paypal', 'api_security', 'font_sample'] as $section) {
|
||||
if (isset($saved[$section]) && is_array($saved[$section])) {
|
||||
$merged[$section] = array_merge($defaults[$section], $saved[$section]);
|
||||
}
|
||||
}
|
||||
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prüft ob ein API-Key gültig ist
|
||||
*/
|
||||
public static function validate_api_key($provided_key): bool {
|
||||
$settings = self::get_settings();
|
||||
$stored_key = $settings['api_security']['api_key'] ?? '';
|
||||
|
||||
// Wenn kein Key konfiguriert ist, ist alles erlaubt (für Entwicklung)
|
||||
if (empty($stored_key)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Key vergleichen (timing-safe)
|
||||
return hash_equals($stored_key, $provided_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Permission Callback für REST API mit API-Key
|
||||
*/
|
||||
public static function rest_api_key_permission($request): bool {
|
||||
$api_key = $request->get_header('X-Skrift-API-Key');
|
||||
return self::validate_api_key($api_key ?? '');
|
||||
}
|
||||
}
|
||||
|
||||
new Skrift_Konfigurator_Admin_Settings();
|
||||
Reference in New Issue
Block a user