PluginProbe
404 Solution / 4.2.0
404 Solution v4.2.0
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / ViewTrait_Settings.php

ViewTrait_Settings.php in 404 Solution 4.2.0, at includes/ViewTrait_Settings.php

517 lines 27.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * ViewTrait_Settings methods.
9 */
10 trait ViewTrait_Settings {
11
12
13 /** @return void */
14 function echoAdminOptionsPage() {
15 global $abj404view;
16 global $abj404viewSuggestions;
17
18 // If globals are not set, use sensible defaults
19 if ($abj404view === null) {
20 $abj404view = $this;
21 }
22
23 $options = $this->getOptionsWithDefaults();
24
25 // Get the current user's settings mode preference
26 $settingsMode = $this->logic->getSettingsMode();
27
28 // if the current URL does not match the chosen menuLocation then redirect to the correct URL
29 $helperFunctions = abj_service('functions');
30 $urlParts = parse_url($helperFunctions->normalizeUrlString($_SERVER['REQUEST_URI'] ?? ''));
31 $currentURL = (is_array($urlParts) && isset($urlParts['path'])) ? $urlParts['path'] : '';
32 if (is_array($options) && isset($options['menuLocation']) &&
33 $options['menuLocation'] == 'settingsLevel') {
34 if ($this->f->strpos($currentURL, 'options-general.php') !== false) {
35 // the option changed and we're at the wrong URL now, so we redirect to the correct one.
36 $this->logic->forceRedirect(admin_url() . "admin.php?page=" .
37 ABJ404_PP . '&subpage=abj404_options');
38 }
39 } else if ($this->f->strpos($currentURL, 'admin.php') !== false) {
40 // if the current URL has admin.php then the URLs don't match and we need to reload.
41 $this->logic->forceRedirect(admin_url() . "options-general.php?page=" .
42 ABJ404_PP . '&subpage=abj404_options');
43 }
44
45 // Toast notification container
46 $abj404view->echoToastNotification();
47
48 // Options page header with mode toggle and expand button
49 echo "\n<div class=\"abj404-header-row\">";
50 echo "<h2>" . esc_html__('Options', '404-solution') . "</h2>";
51 echo "<div class=\"abj404-header-controls\">";
52 $this->echoInlineModeToggle();
53 // Expand/Collapse All button for both Simple and Advanced modes
54 echo '<button type="button" id="abj404-expand-collapse-all" class="button">';
55 echo esc_html__('Expand All', '404-solution');
56 echo '</button>';
57 echo "</div>";
58 echo "</div>";
59
60 // Main container
61 echo "<div class=\"abj404-container\">";
62 echo "<div class=\"abj404-settings-content\">";
63
64 $formBeginning = '<form method="POST" id="admin-options-page" ' .
65 'name="admin-options-page" action="#" data-url="{data-url}">' . "\n";
66 $formBeginning .= '<input type="hidden" name="action" id="action" value="updateOptions">' . "\n";
67 $formBeginning .= '<input type="hidden" name="nonce" id="nonce" value="' .
68 wp_create_nonce('abj404UpdateOptions') . '">' . "\n";
69 $formBeginning = $this->f->str_replace('{data-url}',
70 "admin-ajax.php?action=updateOptions", $formBeginning);
71 echo $formBeginning;
72
73 // Add loading overlay for save operations
74 echo '<div id="abj404-save-overlay" class="abj404-save-overlay" style="display: none;">';
75 echo '<div class="abj404-save-overlay-content">';
76 echo '<div class="abj404-spinner"></div>';
77 echo '<p class="abj404-save-message">' . esc_html__('Saving settings...', '404-solution') . '</p>';
78 echo '</div>';
79 echo '</div>';
80
81 if ($settingsMode === 'simple') {
82 // Simple Mode: Show streamlined options with card layout
83 $abj404view->echoSimpleModeOptions($options);
84 } else {
85 // Advanced Mode: Show all card sections with icons
86
87 // Render each section with card structure and icons
88 $contentAutomaticRedirects = $abj404view->getAdminOptionsPageAutoRedirects($options);
89 $abj404view->echoOptionsSection(
90 "abj404-autooptions",
91 "abj404-autooptions",
92 __('Automatic Redirects', '404-solution'),
93 $contentAutomaticRedirects,
94 true,
95 $abj404view->getCardIcon('lightning')
96 );
97
98 $contentGeneralSettings = $abj404view->getAdminOptionsPageGeneralSettings($options);
99 $abj404view->echoOptionsSection(
100 "abj404-generaloptions",
101 "abj404-generaloptions",
102 __('General Settings', '404-solution'),
103 $contentGeneralSettings,
104 true,
105 $abj404view->getCardIcon('gear')
106 );
107
108 $contentAdvancedContent = $abj404view->getAdminOptionsPageAdvancedContent($options);
109 $abj404view->echoOptionsSection(
110 "abj404-advanced-content",
111 "abj404-advanced-content",
112 __('Content & URL Filtering', '404-solution'),
113 $contentAdvancedContent,
114 true,
115 $abj404view->getCardIcon('filter')
116 );
117
118 $contentAdvancedLogging = $abj404view->getAdminOptionsPageAdvancedLogging($options);
119 $abj404view->echoOptionsSection(
120 "abj404-advanced-logging",
121 "abj404-advanced-logging",
122 __('Logging & Privacy', '404-solution'),
123 $contentAdvancedLogging,
124 true,
125 $abj404view->getCardIcon('document')
126 );
127
128 // "Need help?" support-request section. Anchored at
129 // #abj404-support-request so the plugins-page row action
130 // (which appends that fragment) lands the admin right here
131 // and the JS component auto-opens the modal on arrival.
132 // Lives on the plugin's own Settings page so it does not
133 // violate CLAUDE.md Self-Healing §4 (no support buttons
134 // on screens outside abj404_solution).
135 $supportButton = class_exists('ABJ_404_Solution_SupportRequestButton')
136 ? ABJ_404_Solution_SupportRequestButton::render('settings_debug')
137 : '';
138 $supportSectionHtml = '<div id="abj404-support-request">'
139 . '<p>'
140 . esc_html__('Having trouble? Send your debug log to the developer. This sends a one-time diagnostic report (URLs, PHP/WP/DB versions, a debug log excerpt, active plugins, site URL) so we can diagnose the issue without asking you to copy-paste anything.', '404-solution')
141 . '</p>'
142 . $supportButton
143 . '</div>';
144 $abj404view->echoOptionsSection(
145 "abj404-support-request-section",
146 "abj404-support-request-section",
147 __('Need help? Contact the developer', '404-solution'),
148 $supportSectionHtml,
149 true,
150 $abj404view->getCardIcon('lightbulb')
151 );
152
153 $contentAdvancedSystem = $abj404view->getAdminOptionsPageAdvancedSystem($options);
154 $abj404view->echoOptionsSection(
155 "abj404-advanced-system",
156 "abj404-advanced-system",
157 __('Advanced Configuration', '404-solution'),
158 $contentAdvancedSystem,
159 true,
160 $abj404view->getCardIcon('sliders')
161 );
162
163 // Only render suggestions section if the suggestions view is available
164 if ($abj404viewSuggestions !== null && is_object($abj404viewSuggestions) && method_exists($abj404viewSuggestions, 'getAdminOptionsPage404Suggestions')) {
165 /** @var ABJ_404_Solution_View_Suggestions $abj404viewSuggestions */
166 $content404PageSuggestions = $abj404viewSuggestions->getAdminOptionsPage404Suggestions($options);
167 $abj404view->echoOptionsSection(
168 "abj404-suggestoptions",
169 "abj404-suggestoptions",
170 __('404 Page Suggestions', '404-solution'),
171 $content404PageSuggestions,
172 true,
173 $abj404view->getCardIcon('lightbulb')
174 );
175 }
176 }
177
178 echo "</form><!-- end in admin-options-page -->";
179
180 // Engine Profiles and GSC are advanced features — hidden in simple mode
181 if ($settingsMode === 'advanced') {
182 // Engine Profiles — outside the main form (uses its own AJAX save)
183 $epHtml = ABJ_404_Solution_Functions::readFileContents(__DIR__ . '/html/engineProfilesSection.html');
184 $epHtml = $this->f->doNormalReplacements($epHtml);
185 $abj404view->echoOptionsSection('settings-engine-profiles', 'abj404-engineProfiles', __('Engine Profiles', '404-solution'), $epHtml, false, $abj404view->getCardIcon('filter'));
186
187 // Google Search Console — deferred via AJAX so the options page shell
188 // renders immediately and is not blocked by logs/GSC data fetches.
189 $gscPlaceholder = '<div id="abj404-gsc-deferred-content"'
190 . ' data-deferred-load="1"'
191 . ' data-ajax-action="abj404_load_gsc_section"'
192 . ' data-ajax-nonce="' . esc_attr(wp_create_nonce('abj404_gsc_deferred')) . '">'
193 . '<p class="abj404-form-help">' . esc_html__('Loading Google Search Console section…', '404-solution') . '</p>'
194 . '</div>';
195 $abj404view->echoOptionsSection(
196 'settings-gsc',
197 'abj404-gsc-section',
198 __('Google Search Console', '404-solution'),
199 $gscPlaceholder,
200 true,
201 $abj404view->getCardIcon('chart')
202 );
203 }
204
205 // Sticky save bar — outside the form but linked via form="admin-options-page" on the submit button
206 $abj404view->echoStickySaveBar();
207
208 echo "</div>"; // end abj404-settings-content
209 echo "</div>"; // end abj404-container
210 }
211
212 /**
213 * @return void
214 */
215
216
217 /**
218 * @param array<string, mixed> $options
219 * @return string
220 */
221 function getAdminOptionsPageAutoRedirects($options) {
222 $options = $this->normalizeOptionsForView($options);
223
224 $spaces = esc_html("&nbsp;&nbsp;&nbsp;");
225 $content = "";
226
227 // Behavior tiles (replaces the old page-search dropdown)
228 $content .= '<div class="abj404-form-group">';
229 $content .= '<label class="abj404-form-label">' . __('Default 404 destination', '404-solution') . '</label>';
230 $content .= $this->getBehaviorTilesHTML($options);
231 $content .= '</div>';
232
233 // -----------------------------------------------
234 // Load auto redirects options template
235 $selectedAutoRedirects = $this->getCheckedAttr($options, 'auto_redirects');
236 $selectedAutoSlugs = $this->getCheckedAttr($options, 'auto_slugs');
237 $selectedAutoCats = $this->getCheckedAttr($options, 'auto_cats');
238 $selectedAutoTags = $this->getCheckedAttr($options, 'auto_tags');
239 $selectedAutoTrashRedirect = $this->getCheckedAttr($options, 'auto_trash_redirect');
240
241 $html = ABJ_404_Solution_Functions::readFileContents(__DIR__ . "/html/adminOptionsAutoRedirects.html");
242 $html = $this->f->str_replace('{selectedAutoRedirects}', $selectedAutoRedirects, $html);
243 $html = $this->f->str_replace('{selectedAutoSlugs}', $selectedAutoSlugs, $html);
244 $html = $this->f->str_replace('{selectedAutoCats}', $selectedAutoCats, $html);
245 $html = $this->f->str_replace('{selectedAutoTags}', $selectedAutoTags, $html);
246 $html = $this->f->str_replace('{selectedAutoTrashRedirect}', $selectedAutoTrashRedirect, $html);
247 $html = $this->f->str_replace('{auto_deletion}', esc_attr($this->optStr($options, 'auto_deletion')), $html);
248 $html = $this->f->str_replace('{auto_302_expiration_days}', esc_attr($this->optStr($options, 'auto_302_expiration_days')), $html);
249 $html = $this->f->str_replace('{spaces}', $spaces, $html);
250 $html = $this->f->doNormalReplacements($html);
251 $content .= $html;
252
253 return $content;
254 }
255
256 /**
257 * @param array<string, mixed> $options
258 * @return string
259 */
260 /**
261 * Get the HTML content for the Content & URL Filtering section
262 * @param array<string, mixed> $options
263 * @return string
264 */
265 function getAdminOptionsPageAdvancedContent($options) {
266 $options = $this->normalizeOptionsForView($options);
267 $allPostTypesTemp = $this->viewReadService->getAllPostTypes();
268 $allPostTypes = esc_html(implode(', ', $allPostTypesTemp));
269
270 // Read the html content
271 $html = ABJ_404_Solution_Functions::readFileContents(__DIR__ . "/html/settingsAdvancedContent.html");
272
273 $html = $this->f->str_replace('{recognized_post_types}',
274 str_replace('\\n', "\n", wp_kses_post($this->optStr($options, 'recognized_post_types'))), $html);
275 $html = $this->f->str_replace('{all_post_types}', $allPostTypes, $html);
276
277 $html = $this->f->str_replace('{recognized_categories}',
278 str_replace('\\n', "\n", wp_kses_post($this->optStr($options, 'recognized_categories'))), $html);
279 $html = $this->f->str_replace('{folders_files_ignore}',
280 str_replace('\\n', "\n", wp_kses_post($this->optStr($options, 'folders_files_ignore'))), $html);
281 $html = $this->f->str_replace('{suggest_regex_exclusions}',
282 str_replace('\\n', "\n", esc_textarea($this->optStr($options, 'suggest_regex_exclusions'))), $html);
283
284 $html = $this->f->str_replace('{add-exclude-page-data-url}',
285 "admin-ajax.php?action=echoRedirectToPages&includeDefault404Page=false&includeSpecial=false&nonce=" . wp_create_nonce('abj404_ajax'), $html);
286 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_EMPTY}',
287 __('(Type a page name)', '404-solution'), $html);
288 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_PAGE}',
289 __('(A page has been selected.)', '404-solution'), $html);
290 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_CUSTOM_STRING}',
291 __('(A custom string has been entered.)', '404-solution'), $html);
292 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_URL}',
293 __('(An external URL will be used.)', '404-solution'), $html);
294 $html = $this->f->str_replace('{loaded-excluded-pages}',
295 urlencode($this->optStr($options, 'excludePages[]')), $html);
296
297 // Constants and translations
298 $html = $this->f->doNormalReplacements($html);
299
300 return $html;
301 }
302
303 /**
304 * Get the HTML content for the Logging & Privacy section
305 * @param array<string, mixed> $options
306 * @return string
307 */
308 function getAdminOptionsPageAdvancedLogging($options) {
309 $options = $this->normalizeOptionsForView($options);
310 $selectedLogRawIPs = $this->getCheckedAttr($options, 'log_raw_ips');
311 $selectedDebugLogging = $this->getCheckedAttr($options, 'debug_mode');
312
313 $debugExplanation = __('<a>View</a> the debug file.', '404-solution');
314 $debugLogLink = $this->logic->getDebugLogFileLink();
315 $debugExplanation = $this->f->str_replace('<a>', '<a href="' . $debugLogLink . '" target="_blank" >', $debugExplanation);
316
317 $kbFileSize = $this->logger->getDebugFileSize() / 1024;
318 $kbFileSizePretty = number_format($kbFileSize, 2, ".", ",");
319 $mbFileSize = $this->logger->getDebugFileSize() / 1024 / 1000;
320 $mbFileSizePretty = number_format($mbFileSize, 2, ".", ",");
321 /* Translators: 1: The file size in KB. 2: The file size in MB. */
322 $debugFileSize = sprintf(__('Debug file size: %1$s KB (%2$s MB).', '404-solution'),
323 $kbFileSizePretty, $mbFileSizePretty);
324
325 // Read the html content
326 $html = ABJ_404_Solution_Functions::readFileContents(__DIR__ . "/html/settingsAdvancedLogging.html");
327
328 $html = $this->f->str_replace('checked="log_raw_ips"', $selectedLogRawIPs, $html);
329 $html = $this->f->str_replace('checked="debug_mode"', $selectedDebugLogging, $html);
330 $html = $this->f->str_replace('{<a>View</a> the debug file.}', $debugExplanation, $html);
331 $html = $this->f->str_replace('{Debug file size: %s KB.}', $debugFileSize, $html);
332
333 $html = $this->f->str_replace('{ignore_dontprocess}',
334 str_replace('\\n', "\n", wp_kses_post($this->optStr($options, 'ignore_dontprocess'))), $html);
335 $html = $this->f->str_replace('{ignore_doprocess}',
336 str_replace('\\n', "\n", wp_kses_post($this->optStr($options, 'ignore_doprocess'))), $html);
337
338 // Constants and translations
339 $html = $this->f->doNormalReplacements($html);
340
341 return $html;
342 }
343
344 /**
345 * Get the HTML content for the Advanced Configuration section
346 * @param array<string, mixed> $options
347 * @return string
348 */
349 function getAdminOptionsPageAdvancedSystem($options) {
350 $options = $this->normalizeOptionsForView($options);
351 $selectedRedirectAllRequests = $this->getCheckedAttr($options, 'redirect_all_requests');
352
353 $hideRedirectAllRequests = "false";
354 if (array_key_exists('disallow-redirect-all-requests', $options)
355 && $options['disallow-redirect-all-requests'] == '1') {
356 $hideRedirectAllRequests = "true";
357 }
358
359 // Read the html content
360 $html = ABJ_404_Solution_Functions::readFileContents(__DIR__ . "/html/settingsAdvancedSystem.html");
361
362 $html = $this->f->str_replace('{DATABASE_VERSION}', esc_html($this->optStr($options, 'DB_VERSION')), $html);
363 $html = $this->f->str_replace('checked="redirect_all_requests"', $selectedRedirectAllRequests, $html);
364 $html = $this->f->str_replace('{disallow-redirect-all-requests}', $hideRedirectAllRequests, $html);
365
366 $html = $this->f->str_replace('{OPTION_MIN_AUTO_SCORE}', esc_attr($this->optStr($options, 'auto_score')), $html);
367 $html = $this->f->str_replace('{OPTION_AUTO_SCORE_TITLE}', esc_attr($this->optStr($options, 'auto_score_title')), $html);
368 $html = $this->f->str_replace('{OPTION_AUTO_SCORE_CATEGORY_TAG}', esc_attr($this->optStr($options, 'auto_score_category_tag')), $html);
369 $html = $this->f->str_replace('{OPTION_AUTO_SCORE_CONTENT}', esc_attr($this->optStr($options, 'auto_score_content')), $html);
370 $html = $this->f->str_replace('{OPTION_TEMPLATE_REDIRECT_PRIORITY}', esc_attr($this->optStr($options, 'template_redirect_priority')), $html);
371 $html = $this->f->str_replace('{days_wait_before_major_update}', esc_attr($this->optStr($options, 'days_wait_before_major_update')), $html);
372
373 // Handle plugin_admin_users - convert array to string first before sanitization
374 $pluginAdminUsersRaw2 = $options['plugin_admin_users'];
375 if (is_array($pluginAdminUsersRaw2)) {
376 $pluginAdminUsers = implode("\n", $pluginAdminUsersRaw2);
377 } else {
378 $pluginAdminUsers = is_string($pluginAdminUsersRaw2) ? $pluginAdminUsersRaw2 : '';
379 }
380 $pluginAdminUsers = str_replace('\\n', "\n", wp_kses_post($pluginAdminUsers));
381 $html = $this->f->str_replace('{plugin_admin_users}', wp_kses_post($pluginAdminUsers), $html);
382
383 // Constants and translations
384 $html = $this->f->doNormalReplacements($html);
385
386 return $html;
387 }
388
389 /**
390 * @param array<string, mixed> $options
391 * @return string
392 */
393 function getAdminOptionsPageGeneralSettings($options) {
394 $options = $this->normalizeOptionsForView($options);
395
396 $selectedDefaultRedirect301 = ($options['default_redirect'] == '301') ? ' selected' : '';
397 $selectedDefaultRedirect302 = ($options['default_redirect'] == '302') ? ' selected' : '';
398 $selectedDefaultRedirect307 = ($options['default_redirect'] == '307') ? ' selected' : '';
399 $selectedDefaultRedirect308 = ($options['default_redirect'] == '308') ? ' selected' : '';
400
401 $selectedCapture404 = $this->getCheckedAttr($options, 'capture_404');
402 $selectedSendErrorLogs = $this->getCheckedAttr($options, 'send_error_logs');
403
404 $selectedUnderSettings = "";
405 $selecteSsettingsLevel = "";
406 if ($options['menuLocation'] == 'settingsLevel') {
407 $selecteSsettingsLevel = " selected";
408 } else {
409 $selectedUnderSettings = " selected";
410 }
411
412 // Theme selection
413 $adminTheme = isset($options['admin_theme']) ? $options['admin_theme'] : 'default';
414 $selectedThemeDefault = ($adminTheme == 'default') ? " selected" : "";
415 $selectedThemeCalm = ($adminTheme == 'calm') ? " selected" : "";
416 $selectedThemeMono = ($adminTheme == 'mono') ? " selected" : "";
417 $selectedThemeNeon = ($adminTheme == 'neon') ? " selected" : "";
418 $selectedThemeObsidian = ($adminTheme == 'obsidian') ? " selected" : "";
419
420 // Theme name translations
421 $themeDefault = __('Default', '404-solution');
422
423 // Language override selection
424 $pluginLanguage = isset($options['plugin_language_override']) ? $options['plugin_language_override'] : '';
425 $selectedLanguageDefault = ($pluginLanguage == '') ? " selected" : "";
426 $selectedLanguageEnUS = ($pluginLanguage == 'en_US') ? " selected" : "";
427 $selectedLanguageDeDE = ($pluginLanguage == 'de_DE') ? " selected" : "";
428 $selectedLanguageEsES = ($pluginLanguage == 'es_ES') ? " selected" : "";
429 $selectedLanguageFrFR = ($pluginLanguage == 'fr_FR') ? " selected" : "";
430 $selectedLanguageItIT = ($pluginLanguage == 'it_IT') ? " selected" : "";
431 $selectedLanguagePtBR = ($pluginLanguage == 'pt_BR') ? " selected" : "";
432 $selectedLanguageNlNL = ($pluginLanguage == 'nl_NL') ? " selected" : "";
433 $selectedLanguageRuRU = ($pluginLanguage == 'ru_RU') ? " selected" : "";
434 $selectedLanguageJa = ($pluginLanguage == 'ja') ? " selected" : "";
435 $selectedLanguageZhCN = ($pluginLanguage == 'zh_CN') ? " selected" : "";
436 $selectedLanguageIdID = ($pluginLanguage == 'id_ID') ? " selected" : "";
437 $selectedLanguageSvSE = ($pluginLanguage == 'sv_SE') ? " selected" : "";
438
439 // Auto dark mode detection checkbox
440 $disableAutoDarkMode = isset($options['disable_auto_dark_mode']) && $options['disable_auto_dark_mode'] == '1';
441 $disableAutoDarkModeChecked = $disableAutoDarkMode ? " checked" : "";
442
443 $logSizeBytes = $this->viewReadService->getLogDiskUsage();
444 $logSizeMB = round($logSizeBytes / (1024 * 1000), 2);
445 $totalLogLines = $this->viewReadService->getLogsCount(0);
446
447 $timeToDisplay = $this->statsRepository->getEarliestLogTimestamp();
448 $earliestLogDate = 'N/A';
449 if ($timeToDisplay >= 0) {
450 $earliestLogDate = date('Y/m/d', $timeToDisplay) . ' ' . date('h:i:s', $timeToDisplay) . '&nbsp;' .
451 date('A', $timeToDisplay);
452 }
453
454
455 $selectedRemoveMatches = $this->getCheckedAttr($options, 'remove_matches');
456
457 // Notification frequency selection
458 $notifyFrequency = isset($options['admin_notification_frequency']) ? (string)(is_scalar($options['admin_notification_frequency']) ? $options['admin_notification_frequency'] : 'instant') : 'instant';
459 $selectedNotifyInstant = ($notifyFrequency === 'instant') ? ' selected' : '';
460 $selectedNotifyDaily = ($notifyFrequency === 'daily') ? ' selected' : '';
461 $selectedNotifyWeekly = ($notifyFrequency === 'weekly') ? ' selected' : '';
462
463 $html = ABJ_404_Solution_Functions::readFileContents(__DIR__ . "/html/adminOptionsGeneral.html");
464 $html = $this->f->str_replace('{selectedSendErrorLogs}', $selectedSendErrorLogs, $html);
465 $html = $this->f->str_replace('{selectedDefaultRedirect301}', $selectedDefaultRedirect301, $html);
466 $html = $this->f->str_replace('{selectedDefaultRedirect302}', $selectedDefaultRedirect302, $html);
467 $html = $this->f->str_replace('{selectedDefaultRedirect307}', $selectedDefaultRedirect307, $html);
468 $html = $this->f->str_replace('{selectedDefaultRedirect308}', $selectedDefaultRedirect308, $html);
469 $html = $this->f->str_replace('{selectedCapture404}', $selectedCapture404, $html);
470 $html = $this->f->str_replace('{admin_notification}', esc_attr($this->optStr($options, 'admin_notification')), $html);
471 $html = $this->f->str_replace('{capture_deletion}', esc_attr($this->optStr($options, 'capture_deletion')), $html);
472 $html = $this->f->str_replace('{manual_deletion}', esc_attr($this->optStr($options, 'manual_deletion')), $html);
473 $html = $this->f->str_replace('{maximum_log_disk_usage}', esc_attr($this->optStr($options, 'maximum_log_disk_usage')), $html);
474 $html = $this->f->str_replace('{logCurrentSizeDiskUsage}', (string)$logSizeMB, $html);
475 $html = $this->f->str_replace('{logCurrentRowCount}', (string)$totalLogLines, $html);
476 $html = $this->f->str_replace('{earliestLogDate}', $earliestLogDate, $html);
477 $html = $this->f->str_replace('{selectedRemoveMatches}', $selectedRemoveMatches, $html);
478 $html = $this->f->str_replace('{selectedUnderSettings}', $selectedUnderSettings, $html);
479 $html = $this->f->str_replace('{selecteSsettingsLevel}', $selecteSsettingsLevel, $html);
480 $html = $this->f->str_replace('{selectedThemeDefault}', $selectedThemeDefault, $html);
481 $html = $this->f->str_replace('{selectedThemeCalm}', $selectedThemeCalm, $html);
482 $html = $this->f->str_replace('{selectedThemeMono}', $selectedThemeMono, $html);
483 $html = $this->f->str_replace('{selectedThemeNeon}', $selectedThemeNeon, $html);
484 $html = $this->f->str_replace('{selectedThemeObsidian}', $selectedThemeObsidian, $html);
485 $html = $this->f->str_replace('{theme_default}', $themeDefault, $html);
486 $html = $this->f->str_replace('{selectedLanguageDefault}', $selectedLanguageDefault, $html);
487 $html = $this->f->str_replace('{selectedLanguageEnUS}', $selectedLanguageEnUS, $html);
488 $html = $this->f->str_replace('{selectedLanguageDeDE}', $selectedLanguageDeDE, $html);
489 $html = $this->f->str_replace('{selectedLanguageEsES}', $selectedLanguageEsES, $html);
490 $html = $this->f->str_replace('{selectedLanguageFrFR}', $selectedLanguageFrFR, $html);
491 $html = $this->f->str_replace('{selectedLanguageItIT}', $selectedLanguageItIT, $html);
492 $html = $this->f->str_replace('{selectedLanguagePtBR}', $selectedLanguagePtBR, $html);
493 $html = $this->f->str_replace('{selectedLanguageNlNL}', $selectedLanguageNlNL, $html);
494 $html = $this->f->str_replace('{selectedLanguageRuRU}', $selectedLanguageRuRU, $html);
495 $html = $this->f->str_replace('{selectedLanguageJa}', $selectedLanguageJa, $html);
496 $html = $this->f->str_replace('{selectedLanguageZhCN}', $selectedLanguageZhCN, $html);
497 $html = $this->f->str_replace('{selectedLanguageIdID}', $selectedLanguageIdID, $html);
498 $html = $this->f->str_replace('{selectedLanguageSvSE}', $selectedLanguageSvSE, $html);
499 $html = $this->f->str_replace('{disableAutoDarkModeChecked}', $disableAutoDarkModeChecked, $html);
500 $html = $this->f->str_replace('{admin_notification_email}', esc_attr($this->optStr($options, 'admin_notification_email')), $html);
501 $adminEmail = get_option('admin_email');
502 $html = $this->f->str_replace('{default_wordpress_admin_email}', is_string($adminEmail) ? $adminEmail : '', $html);
503 $html = $this->f->str_replace('{PHP_VERSION}', PHP_VERSION, $html);
504 $html = $this->f->str_replace('{selectedNotifyInstant}', $selectedNotifyInstant, $html);
505 $html = $this->f->str_replace('{selectedNotifyDaily}', $selectedNotifyDaily, $html);
506 $html = $this->f->str_replace('{selectedNotifyWeekly}', $selectedNotifyWeekly, $html);
507 $selectedAutoTrashJunk = $this->getCheckedAttr($options, 'auto_trash_junk_urls');
508 $html = $this->f->str_replace('{selectedAutoTrashJunk}', $selectedAutoTrashJunk, $html);
509 // constants and translations.
510 $html = $this->f->doNormalReplacements($html);
511
512 return $html;
513 }
514
515
516 }
517