' . esc_html($msg) . '
';
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- class-mom-admin.php::admin_notices: ausschließlich Anzeige/Filter/fester Navigationspfad; kein Speichern oder Erteilen einer Berechtigung. Mutierende Handler besitzen eigene Prüfung.
$mom_saved = isset($_GET['mom_saved']) && $_GET['mom_saved'] === '1';
if ($mom_saved) {
echo '' . esc_html__('Das Extras-Modul ist nicht verfügbar.', 'restocommerce') . '
';
return;
}
// Get the instance - GastroComplete_Extras_Plugin is instantiated at the bottom of the file
global $restocommerce_extras_plugin_instance;
$instance = null;
if (isset($restocommerce_extras_plugin_instance) && method_exists($restocommerce_extras_plugin_instance, 'admin_page')) {
$instance = $restocommerce_extras_plugin_instance;
} else {
// Fallback: create a temporary instance just to render the page
$instance = new GastroComplete_Extras_Plugin();
}
if ($instance && method_exists($instance, 'admin_page')) {
// Capture the output
ob_start();
$instance->admin_page();
$output = ob_get_clean();
// Remove the outer wrap div and h1 (we're already inside a wrap)
$output = preg_replace('/\s*/i', '', $output, 1);
$output = preg_replace('/
Extras & Zutaten<\/h1>\s*/i', 'Extras & Zutaten ', $output, 1);
// Remove the closing wrap div at the end (but keep other content)
$output = preg_replace('/<\/div>\s*$/', '', $output);
echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Captured admin_page renderer escapes fields; removing wrappers must preserve forms, nonces and inline UI script.
} else {
echo ' ' . esc_html__('Die Extras-Seite konnte nicht geladen werden.', 'restocommerce') . '
';
}
}
private function render_tab_inventory(array $settings): void {
$s = $settings['inventory'] ?? [];
$enabled = !empty($s['enabled']);
$show_in_shop = array_key_exists('show_in_shop', $s) ? !empty($s['show_in_shop']) : true;
$rows = class_exists('MoM_GastroComplete_Inventory')
? MoM_GastroComplete_Inventory::get_categories_snapshot()
: [];
?>
'rot', 'label' => '', 'last_test' => '', 'last_error' => '', 'hint' => ''];
$conflicts = class_exists('GC_Mail_Settings') ? GC_Mail_Settings::conflicting_smtp_plugins() : [];
$err = class_exists('GC_Mail_Log') ? GC_Mail_Log::last_error() : [];
?>
—
·
jQuery(function ($) {
$('#gc-admin-mail-test-btn').on('click', function () {
var $b = $(this);
$b.prop('disabled', true);
$.post(ajaxurl, {
action: 'gc_mail_test',
nonce: '',
to: $('#gc-admin-mail-test-to').val()
}).done(function (res) {
$('#gc-admin-mail-test-result').text(res && res.success ? (res.data && res.data.message) : ((res && res.data && res.data.message) || ));
}).always(function () { $b.prop('disabled', false); });
});
});
reset, null->'', always string.
*/
private static function mom_safe_scalar($v) {
if (is_array($v)) {
$v = reset($v);
}
return $v === null ? '' : (string)$v;
}
private static function sanitize_preorder_flag($raw, int $fallback): int {
if ($raw === null) {
return $fallback ? 1 : 0;
}
if (is_array($raw)) {
$raw = end($raw);
}
return !empty($raw) ? 1 : 0;
}
public function sanitize_settings($input): array {
$current = MoM_GastroComplete_Core::get_settings();
if (!is_array($input)) {
return $current;
}
/* MoM speichert NICHT über options.php – nur admin-post/REST. Kein option_page-Check. */
$output = $current;
// Sanitize each section - preserve existing values if not in input
if (isset($input['online_orders']) && is_array($input['online_orders'])) {
$output['online_orders'] = array_merge($output['online_orders'] ?? [], [
'hours_format' => in_array($input['online_orders']['hours_format'] ?? '', ['12', '24'], true) ? $input['online_orders']['hours_format'] : ($output['online_orders']['hours_format'] ?? ''),
'allergens_url' => isset($input['online_orders']['allergens_url']) ? esc_url_raw($input['online_orders']['allergens_url']) : ($output['online_orders']['allergens_url'] ?? ''),
'checkout_labeling_enabled' => isset($input['online_orders']['checkout_labeling_enabled'])
? (!empty($input['online_orders']['checkout_labeling_enabled']) ? 1 : 0)
: (int) ($output['online_orders']['checkout_labeling_enabled'] ?? 1),
'pickup_enabled' => isset($input['online_orders']['pickup_enabled']) ? (!empty($input['online_orders']['pickup_enabled']) ? 1 : 0) : ($output['online_orders']['pickup_enabled'] ?? 0),
'slot_minutes' => isset($input['online_orders']['slot_minutes']) ? max(5, min(120, (int)($input['online_orders']['slot_minutes'] ?? 15))) : ($output['online_orders']['slot_minutes'] ?? 15),
'category_limits' => isset($input['online_orders']['category_limits']) && is_array($input['online_orders']['category_limits'])
? array_map('intval', $input['online_orders']['category_limits'])
: ($output['online_orders']['category_limits'] ?? []),
'closed_dates' => isset($input['online_orders']['closed_dates']) ? sanitize_textarea_field($input['online_orders']['closed_dates']) : ($output['online_orders']['closed_dates'] ?? ''),
'special_dates' => isset($input['online_orders']['special_dates']) ? sanitize_textarea_field($input['online_orders']['special_dates']) : ($output['online_orders']['special_dates'] ?? ''),
'preorder_enabled' => self::sanitize_preorder_flag(
$input['online_orders']['preorder_enabled'] ?? null,
(int)($output['online_orders']['preorder_enabled'] ?? 0)
),
'preorder_min_days' => isset($input['online_orders']['preorder_min_days'])
? max(1, min(14, (int)$input['online_orders']['preorder_min_days']))
: max(1, min(14, (int)($output['online_orders']['preorder_min_days'] ?? 1))),
]);
// Hours
if (isset($input['online_orders']['hours']) && is_array($input['online_orders']['hours'])) {
foreach (['mon','tue','wed','thu','fri','sat','sun'] as $day) {
if (isset($input['online_orders']['hours'][$day])) {
$output['online_orders']['hours'][$day] = [
'open' => !empty($input['online_orders']['hours'][$day]['open']) ? 1 : 0,
'l_from' => sanitize_text_field($input['online_orders']['hours'][$day]['l_from'] ?? ''),
'l_to' => sanitize_text_field($input['online_orders']['hours'][$day]['l_to'] ?? ''),
'e_from' => sanitize_text_field($input['online_orders']['hours'][$day]['e_from'] ?? ''),
'e_to' => sanitize_text_field($input['online_orders']['hours'][$day]['e_to'] ?? ''),
];
}
}
}
}
if (isset($input['website']) && is_array($input['website'])) {
if (class_exists('GC_Frontend')) {
$output['website'] = GC_Frontend::sanitize_website($input['website']);
GC_Frontend::apply_website($output['website']);
// receipt logo sync to TSE removed in Basic (Pro/Kasse only)
} else {
$output['website'] = array_merge($output['website'] ?? [], $input['website']);
}
}
if (class_exists('GC_Frontend') && (isset($input['seo']) || isset($input['seo_json']))) {
GC_Frontend::save_seo([
'seo' => is_array($input['seo'] ?? null) ? $input['seo'] : [],
'seo_json' => is_string($input['seo_json'] ?? null) ? $input['seo_json'] : '',
]);
$fresh = MoM_GastroComplete_Core::get_settings();
if (isset($fresh['website']) && is_array($fresh['website'])) {
$output['website'] = $fresh['website'];
}
}
if (isset($input['timeslots']) && is_array($input['timeslots'])) {
$time_mode = isset($input['timeslots']['time_mode'])
? (class_exists('MoM_GastroComplete_Time_Confirmation') ? MoM_GastroComplete_Time_Confirmation::normalize_mode($input['timeslots']['time_mode']) : sanitize_text_field((string)$input['timeslots']['time_mode']))
: ($output['timeslots']['time_mode'] ?? 'slots');
$output['timeslots'] = array_merge($output['timeslots'] ?? [], [
'category_limits_enabled' => isset($input['timeslots']['category_limits_enabled']) ? (!empty($input['timeslots']['category_limits_enabled']) ? 1 : 0) : ($output['timeslots']['category_limits_enabled'] ?? 1),
'slot_minutes' => isset($input['timeslots']['slot_minutes']) ? max(5, min(120, (int)($input['timeslots']['slot_minutes'] ?? 15))) : ($output['timeslots']['slot_minutes'] ?? 15),
'time_mode' => $time_mode,
]);
// Also handle category_limits if moved to timeslots
if (isset($input['timeslots']['category_limits']) && is_array($input['timeslots']['category_limits'])) {
$output['timeslots']['category_limits'] = array_map('intval', $input['timeslots']['category_limits']);
} elseif (isset($output['online_orders']['category_limits'])) {
// Preserve from online_orders if exists
$output['timeslots']['category_limits'] = $output['online_orders']['category_limits'];
}
}
if (isset($input['reservations']) && is_array($input['reservations'])) {
$output['reservations']['enabled'] = !empty($input['reservations']['enabled']) ? 1 : 0;
}
if (isset($input['delivery']) && is_array($input['delivery'])) {
$excluded_products = [];
if (isset($input['delivery']['min_order_excluded_products']) && is_array($input['delivery']['min_order_excluded_products'])) {
$excluded_products = array_map('intval', array_filter($input['delivery']['min_order_excluded_products']));
}
$d = $input['delivery'];
$default_service = sanitize_key((string) self::mom_safe_scalar($d['default_service'] ?? ($output['delivery']['default_service'] ?? 'pickup')));
if (!in_array($default_service, ['pickup', 'delivery'], true)) {
$default_service = 'pickup';
}
$output['delivery'] = array_merge($output['delivery'], [
'enabled' => !empty($d['enabled']) ? 1 : 0,
'default_service' => $default_service,
'checkout_page_id' => max(0, (int)(self::mom_safe_scalar($d['checkout_page_id'] ?? 0))),
'min_order_amount' => !empty($d['min_order_amount']) ? (float)self::mom_safe_scalar($d['min_order_amount']) : '',
'min_order_excluded_products' => $excluded_products,
'google_places_api_key' => sanitize_text_field(self::mom_safe_scalar($d['google_places_api_key'] ?? '')),
'google_places_enabled' => !empty($d['google_places_enabled']) ? 1 : 0,
'fee_mode' => in_array(($d['fee_mode'] ?? 'none'), ['none', 'free', 'flat', 'zones'], true) ? $d['fee_mode'] : 'none',
'fee_amount' => sanitize_text_field(self::mom_safe_scalar($d['fee_amount'] ?? '')),
'free_above' => sanitize_text_field(self::mom_safe_scalar($d['free_above'] ?? '')),
'fee_configured' => 1,
'postcode_whitelist' => sanitize_textarea_field(self::mom_safe_scalar($d['postcode_whitelist'] ?? '')),
'postcode_ranges' => sanitize_textarea_field(self::mom_safe_scalar($d['postcode_ranges'] ?? '')),
'postcode_prefixes' => sanitize_textarea_field(self::mom_safe_scalar($d['postcode_prefixes'] ?? '')),
'checkout_info_text' => wp_kses_post(self::mom_safe_scalar($d['checkout_info_text'] ?? '')),
]);
}
if(isset($input['delivery'])) {
$zones=GC_Delivery_Fees::validate_zones($input['delivery']['fee_zones']??($output['delivery']['fee_zones']??[]));
if(is_wp_error($zones)||(($output['delivery']['fee_mode']??'')==='zones'&&!$zones)) {
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped -- Fehler beim Speichern wird abgefangen; Redirect-Parameter wird beim Anzeigen mit sanitize_text_field und esc_html behandelt.
throw new InvalidArgumentException(is_wp_error($zones)?$zones->get_error_message():__('Bitte mindestens ein Liefergebiet anlegen.', 'restocommerce'));
} else $output['delivery']['fee_zones']=$zones;
}
if (isset($input['mail']) && is_array($input['mail']) && class_exists('GC_Mail_Settings')) {
$output['mail'] = GC_Mail_Settings::sanitize($input['mail'], $output['mail'] ?? []);
}
if (isset($input['inventory']) && is_array($input['inventory'])) {
$inv_in = $input['inventory'];
$output['inventory'] = class_exists('MoM_GastroComplete_Inventory')
? MoM_GastroComplete_Inventory::sanitize_settings($inv_in)
: [
'enabled' => !empty($inv_in['enabled']) ? 1 : 0,
'show_in_shop' => !empty($inv_in['show_in_shop']) ? 1 : 0,
];
if (class_exists('MoM_GastroComplete_Inventory')) {
MoM_GastroComplete_Inventory::apply_category_input($inv_in);
$sync = MoM_GastroComplete_Inventory::current_master_map();
$output['online_orders']['category_master_products'] = $sync['masters'];
}
}
if (isset($input['debug']) && is_array($input['debug'])) {
$output['debug']['enabled'] = !empty($input['debug']['enabled']) ? 1 : 0;
}
// Update settings version
$output['settings_version'] = MOM_GASTROKOMPLETE_VERSION;
// Sync back to legacy options for backward compatibility
$this->sync_to_legacy_options($output);
return $output;
}
/**
* Sync settings back to legacy options for backward compatibility
*/
private function sync_to_legacy_options(array $settings): void {
// Sync to fimui_settings (for backward compatibility)
if (isset($settings['online_orders'])) {
// Get slot_minutes from timeslots or fallback to online_orders
$slot_minutes = $settings['timeslots']['slot_minutes'] ?? $settings['online_orders']['slot_minutes'] ?? 15;
update_option('fimui_settings', [
'allergens_url' => $settings['online_orders']['allergens_url'] ?? '',
'checkout_labeling_enabled' => array_key_exists('checkout_labeling_enabled', $settings['online_orders'])
? (!empty($settings['online_orders']['checkout_labeling_enabled']) ? 1 : 0)
: 1,
'pickup_enabled' => $settings['online_orders']['pickup_enabled'] ?? 0,
'slot_minutes' => $slot_minutes,
'category_limits' => $settings['online_orders']['category_limits'] ?? [],
'category_master_products' => $settings['online_orders']['category_master_products'] ?? [],
'hours' => $settings['online_orders']['hours'] ?? [],
'closed_dates' => $settings['online_orders']['closed_dates'] ?? '',
'special_dates' => $settings['online_orders']['special_dates'] ?? '',
'preorder_enabled' => array_key_exists('preorder_enabled', $settings['online_orders'])
? (!empty($settings['online_orders']['preorder_enabled']) ? 1 : 0)
: 0,
'preorder_min_days' => max(1, min(14, (int)($settings['online_orders']['preorder_min_days'] ?? 1))),
]);
}
}
/**
* Render Zahlungsarten page
*/
public function render_payment_methods_page(): void {
if (!current_user_can('manage_woocommerce')) {
wp_die('Unauthorized');
}
?>
RestoCommerce Pro'
),
['a' => ['href' => true]]
);
?>