PluginProbe
404 Solution / trunk
404 Solution vtrunk
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 / view / View_SettingsSections.php

View_SettingsSections.php in 404 Solution trunk, at includes/view/View_SettingsSections.php

314 lines 18.3 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 * Presents advanced and general settings section templates.
9 */
10 class ABJ_404_Solution_View_SettingsSections extends ABJ_404_Solution_ViewComponent {
11
12 /** @param array<string,string> $vars */
13 private function fillSettingsTemplate(string $templateName, array $vars): string {
14 $html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . '/html/' . $templateName);
15 foreach ($vars as $key => $value) {
16 $html = $this->f->str_replace('{' . $key . '}', $value, $html);
17 }
18 return (string)$html;
19 }
20
21 /** @param array<string, mixed> $options */
22 function getAdminOptionsPageAutoRedirects(array $options): string {
23 $options = $this->optionsPresenter->normalizeOptionsForView($options);
24
25 $spaces = esc_html("&nbsp;&nbsp;&nbsp;");
26 $content = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/adminOptionsDefault404Destination.html");
27 $content = $this->f->str_replace(
28 array('{default_404_destination_label}', '{behavior_tiles_html}'),
29 array(esc_html__('Default 404 destination', '404-solution'), $this->optionsPresenter->getBehaviorTilesHTML($options)),
30 $content
31 );
32
33 $selectedAutoRedirects = $this->optionsPresenter->getCheckedAttr($options, 'auto_redirects');
34 $selectedAutoSlugs = $this->optionsPresenter->getCheckedAttr($options, 'auto_slugs');
35 $selectedAutoCats = $this->optionsPresenter->getCheckedAttr($options, 'auto_cats');
36 $selectedAutoTags = $this->optionsPresenter->getCheckedAttr($options, 'auto_tags');
37 $selectedAutoTrashRedirect = $this->optionsPresenter->getCheckedAttr($options, 'auto_trash_redirect');
38
39 $html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/adminOptionsAutoRedirects.html");
40 $html = $this->f->str_replace('{selectedAutoRedirects}', $selectedAutoRedirects, $html);
41 $html = $this->f->str_replace('{selectedAutoSlugs}', $selectedAutoSlugs, $html);
42 $html = $this->f->str_replace('{selectedAutoCats}', $selectedAutoCats, $html);
43 $html = $this->f->str_replace('{selectedAutoTags}', $selectedAutoTags, $html);
44 $html = $this->f->str_replace('{selectedAutoTrashRedirect}', $selectedAutoTrashRedirect, $html);
45 $html = $this->f->str_replace('{auto_deletion}', esc_attr($this->optionsPresenter->optStr($options, 'auto_deletion')), $html);
46 $html = $this->f->str_replace('{auto_302_expiration_days}', esc_attr($this->optionsPresenter->optStr($options, 'auto_302_expiration_days')), $html);
47 $html = $this->f->str_replace('{spaces}', $spaces, $html);
48 $html = $this->f->doNormalReplacements($html);
49 $content .= $html;
50
51 return $content;
52 }
53
54 /** @param array<string, mixed> $options */
55 function getAdminOptionsPageAdvancedContent(array $options): string {
56 $options = $this->optionsPresenter->normalizeOptionsForView($options);
57 $allPostTypesTemp = $this->viewReadService->getAllPostTypes();
58 $allPostTypes = esc_html(implode(', ', $allPostTypesTemp));
59
60 $html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/settingsAdvancedContent.html");
61
62 $html = $this->f->str_replace('{recognized_post_types}',
63 str_replace('\\n', "\n", wp_kses_post($this->optionsPresenter->optStr($options, 'recognized_post_types'))), $html);
64 $html = $this->f->str_replace('{all_post_types}', $allPostTypes, $html);
65 $html = $this->f->str_replace('{recognized_categories}',
66 str_replace('\\n', "\n", wp_kses_post($this->optionsPresenter->optStr($options, 'recognized_categories'))), $html);
67 $html = $this->f->str_replace('{folders_files_ignore}',
68 str_replace('\\n', "\n", wp_kses_post($this->optionsPresenter->optStr($options, 'folders_files_ignore'))), $html);
69 $html = $this->f->str_replace('{suggest_regex_exclusions}',
70 str_replace('\\n', "\n", esc_textarea($this->optionsPresenter->optStr($options, 'suggest_regex_exclusions'))), $html);
71
72 $html = $this->f->str_replace('{add-exclude-page-data-url}',
73 "admin-ajax.php?action=echoRedirectToPages&includeDefault404Page=false&includeSpecial=false&nonce=" . wp_create_nonce('abj404_ajax'), $html);
74 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_EMPTY}',
75 __('(Type a page name)', '404-solution'), $html);
76 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_PAGE}',
77 __('(A page has been selected.)', '404-solution'), $html);
78 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_CUSTOM_STRING}',
79 __('(A custom string has been entered.)', '404-solution'), $html);
80 $html = $this->f->str_replace('{TOOLTIP_POPUP_EXPLANATION_URL}',
81 __('(An external URL will be used.)', '404-solution'), $html);
82 $html = $this->f->str_replace('{loaded-excluded-pages}',
83 urlencode($this->optionsPresenter->optStr($options, 'excludePages[]')), $html);
84 $html = $this->f->doNormalReplacements($html);
85
86 return $html;
87 }
88
89 /** @param array<string, mixed> $options */
90 function getAdminOptionsPageAdvancedLogging(array $options): string {
91 $options = $this->optionsPresenter->normalizeOptionsForView($options);
92 $selectedLogRawIPs = $this->optionsPresenter->getCheckedAttr($options, 'log_raw_ips');
93 $selectedDebugLogging = $this->optionsPresenter->getCheckedAttr($options, 'debug_mode');
94
95 $debugExplanation = __('<a>View</a> the debug file.', '404-solution');
96 $debugLogLink = '?page=' . ABJ404_PP . '&subpage=abj404_debugfile';
97 $debugExplanation = $this->f->str_replace('<a>', '<a href="' . $debugLogLink . '" target="_blank" >', $debugExplanation);
98
99 $kbFileSize = $this->logger->getDebugFileSize() / 1024;
100 $kbFileSizePretty = number_format($kbFileSize, 2, ".", ",");
101 $mbFileSize = $this->logger->getDebugFileSize() / 1024 / 1000;
102 $mbFileSizePretty = number_format($mbFileSize, 2, ".", ",");
103 $debugFileSize = sprintf(__('Debug file size: %1$s KB (%2$s MB).', '404-solution'),
104 $kbFileSizePretty, $mbFileSizePretty);
105
106 $html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/settingsAdvancedLogging.html");
107 $html = $this->f->str_replace('checked="log_raw_ips"', $selectedLogRawIPs, $html);
108 $html = $this->f->str_replace('checked="debug_mode"', $selectedDebugLogging, $html);
109 $html = $this->f->str_replace('{<a>View</a> the debug file.}', $debugExplanation, $html);
110 $html = $this->f->str_replace('{Debug file size: %s KB.}', $debugFileSize, $html);
111 $html = $this->f->str_replace('{ignore_dontprocess}',
112 str_replace('\\n', "\n", wp_kses_post($this->optionsPresenter->optStr($options, 'ignore_dontprocess'))), $html);
113 $html = $this->f->str_replace('{ignore_doprocess}',
114 str_replace('\\n', "\n", wp_kses_post($this->optionsPresenter->optStr($options, 'ignore_doprocess'))), $html);
115 $html = $this->f->doNormalReplacements($html);
116
117 return $html;
118 }
119
120 /** @param array<string, mixed> $options */
121 function getAdminOptionsPageAdvancedSystem(array $options): string {
122 $options = $this->optionsPresenter->normalizeOptionsForView($options);
123 $selectedRedirectAllRequests = $this->optionsPresenter->getCheckedAttr($options, 'redirect_all_requests');
124
125 $hideRedirectAllRequests = "false";
126 if (array_key_exists('disallow-redirect-all-requests', $options)
127 && $options['disallow-redirect-all-requests'] == '1') {
128 $hideRedirectAllRequests = "true";
129 }
130
131 $html = ABJ_404_Solution_FileSystemService::readFileContents(dirname(__DIR__) . "/html/settingsAdvancedSystem.html");
132 $html = $this->f->str_replace('{DATABASE_VERSION}', esc_html($this->optionsPresenter->optStr($options, 'DB_VERSION')), $html);
133 $html = $this->f->str_replace('checked="redirect_all_requests"', $selectedRedirectAllRequests, $html);
134 $html = $this->f->str_replace('{disallow-redirect-all-requests}', $hideRedirectAllRequests, $html);
135 $html = $this->f->str_replace('{OPTION_MIN_AUTO_SCORE}', esc_attr($this->optionsPresenter->optStr($options, 'auto_score')), $html);
136 $html = $this->f->str_replace('{OPTION_AUTO_SCORE_TITLE}', esc_attr($this->optionsPresenter->optStr($options, 'auto_score_title')), $html);
137 $html = $this->f->str_replace('{OPTION_AUTO_SCORE_CATEGORY_TAG}', esc_attr($this->optionsPresenter->optStr($options, 'auto_score_category_tag')), $html);
138 $html = $this->f->str_replace('{OPTION_AUTO_SCORE_CONTENT}', esc_attr($this->optionsPresenter->optStr($options, 'auto_score_content')), $html);
139 $html = $this->f->str_replace('{OPTION_TEMPLATE_REDIRECT_PRIORITY}', esc_attr($this->optionsPresenter->optStr($options, 'template_redirect_priority')), $html);
140 $html = $this->f->str_replace('{days_wait_before_major_update}', esc_attr($this->optionsPresenter->optStr($options, 'days_wait_before_major_update')), $html);
141
142 $pluginAdminUsersRaw2 = $options['plugin_admin_users'];
143 if (is_array($pluginAdminUsersRaw2)) {
144 $pluginAdminUsers = implode("\n", $pluginAdminUsersRaw2);
145 } else {
146 $pluginAdminUsers = is_string($pluginAdminUsersRaw2) ? $pluginAdminUsersRaw2 : '';
147 }
148 $pluginAdminUsers = str_replace('\\n', "\n", wp_kses_post($pluginAdminUsers));
149 $html = $this->f->str_replace('{plugin_admin_users}', wp_kses_post($pluginAdminUsers), $html);
150 $html = $this->f->doNormalReplacements($html);
151
152 return $html;
153 }
154
155 /** @param array<string, mixed> $options */
156 function getAdminOptionsPageGeneralSettings(array $options): string {
157 $options = $this->optionsPresenter->normalizeOptionsForView($options);
158
159 $viewData = array_merge(
160 $this->generalSettingsFieldState($options),
161 $this->generalSettingsRuntimeDisplayData(),
162 array(
163 'admin_notification' => esc_attr($this->optionsPresenter->optStr($options, 'admin_notification')),
164 'capture_deletion' => esc_attr($this->optionsPresenter->optStr($options, 'capture_deletion')),
165 'manual_deletion' => esc_attr($this->optionsPresenter->optStr($options, 'manual_deletion')),
166 'maximum_log_disk_usage' => esc_attr($this->optionsPresenter->optStr($options, 'maximum_log_disk_usage')),
167 'admin_notification_email' => esc_attr($this->optionsPresenter->optStr($options, 'admin_notification_email')),
168 'PHP_VERSION' => PHP_VERSION,
169 )
170 );
171
172 $html = $this->fillSettingsTemplate('adminOptionsGeneral.html', $viewData);
173 $html = $this->f->doNormalReplacements($html);
174
175 return $html;
176 }
177
178 /**
179 * Build selected and checked attributes for the general settings template.
180 *
181 * @param array<string, mixed> $options
182 * @return array<string, string>
183 */
184 private function generalSettingsFieldState(array $options): array {
185 $viewData = array(
186 'selectedDefaultRedirect301' => ($options['default_redirect'] == '301') ? ' selected' : '',
187 'selectedDefaultRedirect302' => ($options['default_redirect'] == '302') ? ' selected' : '',
188 'selectedDefaultRedirect307' => ($options['default_redirect'] == '307') ? ' selected' : '',
189 'selectedDefaultRedirect308' => ($options['default_redirect'] == '308') ? ' selected' : '',
190 'selectedCapture404' => $this->optionsPresenter->getCheckedAttr($options, 'capture_404'),
191 'selectedSendErrorLogs' => $this->optionsPresenter->getCheckedAttr($options, 'send_error_logs'),
192 'selectedRemoveMatches' => $this->optionsPresenter->getCheckedAttr($options, 'remove_matches'),
193 'selectedAutoTrashJunk' => $this->optionsPresenter->getCheckedAttr($options, 'auto_trash_junk_urls'),
194 'selectedUnderSettings' => ($options['menuLocation'] == 'settingsLevel') ? '' : ' selected',
195 'selecteSsettingsLevel' => ($options['menuLocation'] == 'settingsLevel') ? ' selected' : '',
196 'theme_default' => __('Default', '404-solution'),
197 'disableAutoDarkModeChecked' => isset($options['disable_auto_dark_mode']) && $options['disable_auto_dark_mode'] == '1'
198 ? ' checked'
199 : '',
200 );
201
202 $adminTheme = isset($options['admin_theme']) ? $options['admin_theme'] : 'default';
203 foreach (array(
204 'selectedThemeDefault' => 'default',
205 'selectedThemeCalm' => 'calm',
206 'selectedThemeMono' => 'mono',
207 'selectedThemeNeon' => 'neon',
208 'selectedThemeObsidian' => 'obsidian',
209 ) as $placeholder => $theme) {
210 $viewData[$placeholder] = ($adminTheme == $theme) ? ' selected' : '';
211 }
212
213 $pluginLanguage = isset($options['plugin_language_override']) ? $options['plugin_language_override'] : '';
214 foreach (array(
215 'selectedLanguageDefault' => '',
216 'selectedLanguageEnUS' => 'en_US',
217 'selectedLanguageDeDE' => 'de_DE',
218 'selectedLanguageEsES' => 'es_ES',
219 'selectedLanguageFrFR' => 'fr_FR',
220 'selectedLanguageItIT' => 'it_IT',
221 'selectedLanguagePtBR' => 'pt_BR',
222 'selectedLanguageNlNL' => 'nl_NL',
223 'selectedLanguageRuRU' => 'ru_RU',
224 'selectedLanguageJa' => 'ja',
225 'selectedLanguageZhCN' => 'zh_CN',
226 'selectedLanguageIdID' => 'id_ID',
227 'selectedLanguageSvSE' => 'sv_SE',
228 ) as $placeholder => $language) {
229 $viewData[$placeholder] = ($pluginLanguage == $language) ? ' selected' : '';
230 }
231
232 $notifyFrequencyRaw = $options['admin_notification_frequency'] ?? 'instant';
233 $notifyFrequency = is_scalar($notifyFrequencyRaw) ? (string)$notifyFrequencyRaw : 'instant';
234 foreach (array(
235 'selectedNotifyInstant' => 'instant',
236 'selectedNotifyDaily' => 'daily',
237 'selectedNotifyWeekly' => 'weekly',
238 'selectedNotifyNever' => 'never',
239 ) as $placeholder => $frequency) {
240 $viewData[$placeholder] = ($notifyFrequency === $frequency) ? ' selected' : '';
241 }
242
243 return $viewData;
244 }
245
246 /** @return array<string, string> */
247 private function generalSettingsRuntimeDisplayData(): array {
248 $timeToDisplay = $this->statsRepository->getEarliestLogTimestamp();
249 $earliestLogDate = $timeToDisplay >= 0
250 ? date('Y/m/d', $timeToDisplay) . ' ' . date('h:i:s', $timeToDisplay) . '&nbsp;' . date('A', $timeToDisplay)
251 : 'N/A';
252 $adminEmail = get_option('admin_email');
253
254 return array(
255 'logCurrentSizeDiskUsage' => (string)round($this->viewReadService->getLogDiskUsage() / (1024 * 1000), 2),
256 'logCurrentRowCount' => (string)$this->viewReadService->getLogsCount(0),
257 'earliestLogDate' => $earliestLogDate,
258 'default_wordpress_admin_email' => is_string($adminEmail) ? $adminEmail : '',
259 );
260 }
261
262 /** @param array<string, mixed> $options */
263 function getAdminOptionsPageDiagnosticData(array $options): string {
264 if (!class_exists('ABJ_404_Solution_FeedbackSiteTokenStore')) {
265 require_once dirname(__DIR__) . '/feedback/FeedbackSiteTokenStore.php';
266 }
267 if (!class_exists('ABJ_404_Solution_Ajax_PrivacyExport')) {
268 require_once dirname(__DIR__) . '/ajax/Ajax_PrivacyExport.php';
269 }
270 if (!class_exists('ABJ_404_Solution_Ajax_PrivacyDelete')) {
271 require_once dirname(__DIR__) . '/ajax/Ajax_PrivacyDelete.php';
272 }
273
274 $rawToken = get_option(ABJ_404_Solution_FeedbackSiteTokenStore::TOKEN_OPTION, '');
275 $hasToken = is_string($rawToken) && $rawToken !== '';
276 $exportNonce = wp_create_nonce(ABJ_404_Solution_Ajax_PrivacyExport::NONCE_ACTION);
277 $deleteNonce = wp_create_nonce(ABJ_404_Solution_Ajax_PrivacyDelete::NONCE_ACTION);
278
279 if (!$hasToken) {
280 $body = $this->fillSettingsTemplate('viewSettingsDiagnosticDataNoToken.html', array(
281 'emptyDescription' => esc_html__('Diagnostic reporting has never been enabled for this site, so there is nothing stored on the developer\'s server for you to download or delete.', '404-solution'),
282 ));
283 } else {
284 $sendErrorLogs = $options['send_error_logs'] ?? '0';
285 $enabled = $sendErrorLogs === '1' || $sendErrorLogs === 1 || $sendErrorLogs === true;
286 $state = $enabled ? esc_html__('enabled', '404-solution') : esc_html__('disabled', '404-solution');
287 $description = sprintf(
288 esc_html__('This site has diagnostic reporting %s. You can download everything stored on the developer\'s server for this site, or permanently delete it.', '404-solution'),
289 $state
290 );
291 $body = $this->fillSettingsTemplate('viewSettingsDiagnosticDataActions.html', array(
292 'description' => $description,
293 'exportNonce' => esc_attr($exportNonce),
294 'deleteNonce' => esc_attr($deleteNonce),
295 'downloadLabel' => esc_html__('Download my data', '404-solution'),
296 'deleteLabel' => esc_html__('Delete my data', '404-solution'),
297 'emptyAfterDelete' => esc_html__('Nothing currently stored.', '404-solution'),
298 'modalTitle' => esc_html__('Delete your diagnostic data?', '404-solution'),
299 'modalBody' => esc_html__('This permanently deletes every diagnostic report this site has ever sent. This cannot be undone. Your redirects and settings are not affected -- only diagnostic/telemetry history is removed.', '404-solution'),
300 'cancelLabel' => esc_html__('Cancel', '404-solution'),
301 'confirmLabel' => esc_html__('Yes, delete permanently', '404-solution'),
302 ));
303 }
304
305 return $this->fillSettingsTemplate('viewSettingsDiagnosticDataSection.html', array(
306 'downloadDate' => esc_attr(gmdate('Y-m-d', abj_clock()->now())),
307 'exportNonce' => esc_attr($exportNonce),
308 'deleteNonce' => esc_attr($deleteNonce),
309 'hasToken' => $hasToken ? '1' : '0',
310 'body' => $body,
311 ));
312 }
313 }
314