preset => [pages collected, pages analysed] */ private const SIZE_PRESETS = [ 'quick' => [100, 50], 'standard' => [300, 150], 'full' => [0, 0], ]; /** @var array pace => milliseconds between crawl batches */ private const PACE_PRESETS = [ 'gentle' => 1500, 'balanced' => 1000, 'fast' => 500, ]; public function render(): void { Capabilities::require_manage_options(); $request_method = isset($_SERVER['REQUEST_METHOD']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_METHOD'])) : ''; // Plugin Check / WPCS InputNotUnslashed: read $_POST through a single // unslashed copy; every field is sanitized individually below. $post = wp_unslash($_POST); if ($request_method === 'POST' && isset($post['aetos_seo_save_settings'])) { check_admin_referer('aetos_seo_save_settings'); $this->save($post); } $s = Settings::get(); $limits = isset($s['scan_limits']) && is_array($s['scan_limits']) ? $s['scan_limits'] : []; $crawl_max = (int) ($limits['crawl_max_urls'] ?? 200); $analysis_max = (int) ($limits['audit_analysis_max_pages'] ?? 50); $delay = (int) ($limits['crawl_delay_ms'] ?? 1500); $size = 'custom'; foreach (self::SIZE_PRESETS as $key => [$c, $a]) { if ($crawl_max === $c && $analysis_max === $a) { $size = $key; } } $pace = 'gentle'; foreach (self::PACE_PRESETS as $key => $ms) { if ($delay >= $ms) { $pace = $key; break; } } echo wp_kses(Brand::wrap_open(), Brand::admin_kses()); echo wp_kses(Brand::header(I18n::tr('Settings', 'الإعدادات')), Brand::admin_kses()); echo '
'; wp_nonce_field('aetos_seo_save_settings'); // ── What to check ─────────────────────────────────────────────────── echo '
'; echo '

' . esc_html(I18n::tr('How much of the site to check', 'حجم الفحص')) . '

'; echo '
'; $size_labels = [ 'quick' => [I18n::tr('Quick', 'سريع'), I18n::tr('Up to 100 pages. Good for a first look.', 'حتى 100 صفحة. مناسب لنظرة أولى.')], 'standard' => [I18n::tr('Standard', 'قياسي'), I18n::tr('Up to 300 pages. Fits most stores.', 'حتى 300 صفحة. يناسب أغلب المتاجر.')], 'full' => [I18n::tr('Whole site', 'كل الموقع'), I18n::tr('Every page found. Takes longer on large sites.', 'كل الصفحات التي يُعثر عليها. يستغرق وقتًا أطول في المواقع الكبيرة.')], 'custom' => [I18n::tr('Custom', 'مخصص'), I18n::tr('Set the numbers yourself.', 'حدد الأرقام بنفسك.')], ]; foreach ($size_labels as $key => [$label, $hint]) { $this->choice('size_preset', $key, $size === $key, $label, $hint); } echo '
'; echo '
'; echo ''; echo ''; echo '

' . esc_html(I18n::tr('0 means every page.', 'اكتب 0 لفحص كل الصفحات.')) . '

'; echo '
'; echo '
'; // ── Pace ──────────────────────────────────────────────────────────── echo '
'; echo '

' . esc_html(I18n::tr('Scan pace', 'سرعة الفحص')) . '

'; echo '

' . esc_html(I18n::tr('A gentler pace keeps shared hosting responsive while the scan runs.', 'السرعة الهادئة تحافظ على سرعة الموقع أثناء الفحص في الاستضافة المشتركة.')) . '

'; echo '
'; $pace_labels = [ 'gentle' => [I18n::tr('Gentle (recommended)', 'هادئة (موصى بها)'), I18n::tr('Best for shared hosting.', 'الأفضل للاستضافة المشتركة.')], 'balanced' => [I18n::tr('Balanced', 'متوسطة'), I18n::tr('For good hosting plans.', 'لخطط الاستضافة الجيدة.')], 'fast' => [I18n::tr('Fast', 'سريعة'), I18n::tr('For dedicated or cloud servers.', 'للخوادم الخاصة أو السحابية.')], ]; foreach ($pace_labels as $key => [$label, $hint]) { $this->choice('pace_preset', $key, $pace === $key, $label, $hint); } echo '
'; // ── Email summary ─────────────────────────────────────────────────── $email_on = !empty($s['notifications']['email_on_complete']); $email_to = (string) ($s['notifications']['email_recipient'] ?? ''); echo '
'; echo '

' . esc_html(I18n::tr('Email summary', 'ملخص بالبريد')) . '

'; echo ''; echo '
'; echo ''; echo '

' . esc_html(I18n::tr('Leave empty to use the site admin email.', 'اتركه فارغًا لاستخدام بريد مدير الموقع.')) . '

'; echo '
'; // ── Language ──────────────────────────────────────────────────────── $ui_settings = isset($s['ui']) && is_array($s['ui']) ? $s['ui'] : []; $admin_locale = isset($ui_settings['admin_locale']) ? (string) $ui_settings['admin_locale'] : 'auto'; echo '
'; echo '

' . esc_html(I18n::tr('Language of this plugin', 'لغة الإضافة')) . '

'; echo '

' . esc_html(I18n::tr('Changes the language of Aetos screens and results only. Your site language stays as it is.', 'تغيّر لغة شاشات Aetos ونتائجها فقط، وتبقى لغة موقعك كما هي.')) . '

'; echo '
'; echo '
'; echo ''; echo ''; echo '
'; echo '
'; // ── Reset ─────────────────────────────────────────────────────────── echo '
' . esc_html(I18n::tr('Reset data', 'مسح البيانات')) . ''; echo '
'; echo '
' . esc_html(I18n::tr('Clear audit results', 'مسح نتائج الفحص')) . '

' . esc_html(I18n::tr('Deletes past audits and their findings. Your settings stay.', 'يحذف الفحوصات السابقة ونتائجها، وتبقى إعداداتك.')) . '

'; echo '
'; echo '
' . esc_html(I18n::tr('Reset everything', 'إعادة كل شيء كما كان')) . '

' . esc_html(I18n::tr('Deletes results and settings and returns the plugin to its first state.', 'يحذف النتائج والإعدادات ويعيد الإضافة إلى حالتها الأولى.')) . '

'; echo '
'; echo ''; echo '
'; echo ''; } /** * @param array $post */ private function save(array $post): void { $current = Settings::get(); $new = $current; $new['scan_mode'] = 'full'; $size = sanitize_key((string) ($post['size_preset'] ?? 'custom')); if (isset(self::SIZE_PRESETS[$size])) { [$crawl_max, $analysis_max] = self::SIZE_PRESETS[$size]; } else { $crawl_max = isset($post['crawl_max_urls']) ? absint($post['crawl_max_urls']) : 200; $analysis_max = isset($post['audit_analysis_max_pages']) ? absint($post['audit_analysis_max_pages']) : 50; } $pace = sanitize_key((string) ($post['pace_preset'] ?? 'gentle')); $delay = self::PACE_PRESETS[$pace] ?? self::PACE_PRESETS['gentle']; $new['scan_limits'] = array_replace($current['scan_limits'], [ 'crawl_delay_ms' => $delay, 'crawl_max_urls' => $crawl_max, 'audit_analysis_max_pages' => $analysis_max, ]); $new['notifications'] = [ 'email_on_complete' => isset($post['email_on_complete']) ? 1 : 0, 'email_recipient' => sanitize_email((string) ($post['email_recipient'] ?? '')), ]; $locale = sanitize_key((string) ($post['ui_admin_locale'] ?? 'auto')); $new['ui'] = ['admin_locale' => in_array($locale, ['auto', 'ar', 'en'], true) ? $locale : 'auto']; $ok = Settings::update($new); // The language may have just changed; render the notice in the new one. I18n::reset_cache(); echo '

' . esc_html($ok ? I18n::tr('Settings saved.', 'تم حفظ الإعدادات.') : I18n::tr('The settings could not be saved.', 'تعذر حفظ الإعدادات.')) . '

'; } private function choice(string $name, string $value, bool $checked, string $label, string $hint): void { echo ''; } }