PluginProbe
DecaLog / 4.4.0
DecaLog v4.4.0
3.0.2 3.1.0 3.10.0 3.2.0 3.3.0 3.4.0 3.4.1 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.6.3 3.7.0 3.7.1 3.8.0 3.9.0 3.9.1 4.0.0 4.1.0 4.2.0 4.3.0 4.3.1 4.4.0 4.5.0 All 75 releases
decalog / admin / class-decalog-admin.php

class-decalog-admin.php in DecaLog 4.4.0, at admin/class-decalog-admin.php

1,643 lines 73.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * The admin-specific functionality of the plugin.
4 *
5 * @package Plugin
6 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
7 * @since 1.0.0
8 */
9
10 namespace Decalog\Plugin;
11
12 use Decalog\Plugin\Feature\Autolog;
13 use Decalog\Plugin\Feature\BootstrapManager;
14 use Decalog\System\APCu;
15 use Decalog\System\Blog;
16 use Decalog\System\SharedMemory;
17 use Decalog\Plugin\Feature\Log;
18 use Decalog\Plugin\Feature\EventViewer;
19 use Decalog\Plugin\Feature\HandlerTypes;
20 use Decalog\Plugin\Feature\ProcessorTypes;
21 use Decalog\Plugin\Feature\LoggerFactory;
22 use Decalog\Plugin\Feature\Events;
23 use Decalog\Plugin\Feature\Traces;
24 use Decalog\Plugin\Feature\InlineHelp;
25 use Decalog\Listener\ListenerFactory;
26 use Decalog\System\Assets;
27 use Decalog\System\UUID;
28 use Decalog\System\Option;
29 use Decalog\System\Form;
30 use Decalog\System\Role;
31 use Decalog\System\GeoIP;
32 use Decalog\System\Environment;
33 use DLMonolog\Logger;
34 use PerfOpsOne\Menus;
35 use PerfOpsOne\AdminBar;
36 use Decalog\Plugin\Feature\DLogger;
37 use Decalog\Plugin\Feature\TraceViewer;
38 use Decalog\System\Cache;
39
40 /**
41 * The admin-specific functionality of the plugin.
42 *
43 * @package Plugin
44 * @author Pierre Lannoy <https://pierre.lannoy.fr/>.
45 * @since 1.0.0
46 */
47 class Decalog_Admin {
48
49 /**
50 * The assets manager that's responsible for handling all assets of the plugin.
51 *
52 * @since 1.0.0
53 * @var Assets $assets The plugin assets manager.
54 */
55 protected $assets;
56
57 /**
58 * The internal logger.
59 *
60 * @since 1.0.0
61 * @var DLogger $logger The plugin admin logger.
62 */
63 protected $logger;
64
65 /**
66 * The current logger.
67 *
68 * @since 1.0.0
69 * @var array $current_logger The current logger.
70 */
71 protected $current_logger;
72
73 /**
74 * The current handler.
75 *
76 * @since 1.0.0
77 * @var array $current_handler The current handler.
78 */
79 protected $current_handler;
80
81 /**
82 * The current view.
83 *
84 * @since 1.0.0
85 * @var object $current_view The current view.
86 */
87 protected $current_view = null;
88
89 /**
90 * The logger will be created.
91 *
92 * @since 3.0.0
93 * @var boolean $creation_mode The form mode (creation / editing).
94 */
95 protected $creation_mode = false;
96
97 /**
98 * Initialize the class and set its properties.
99 *
100 * @since 1.0.0
101 */
102 public function __construct() {
103 $this->assets = new Assets();
104 $this->logger = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
105 }
106
107 /**
108 * Register the stylesheets for the admin area.
109 *
110 * @since 1.0.0
111 */
112 public function register_styles() {
113 $this->assets->register_style( DECALOG_ASSETS_ID, DECALOG_ADMIN_URL, 'css/decalog.min.css' );
114 $this->assets->register_style( DECALOG_LIVELOG_ID, DECALOG_ADMIN_URL, 'css/livelog.min.css' );
115 }
116
117 /**
118 * Register the JavaScript for the admin area.
119 *
120 * @since 1.0.0
121 */
122 public function register_scripts() {
123 $this->assets->register_script( DECALOG_ASSETS_ID, DECALOG_ADMIN_URL, 'js/decalog.min.js', [ 'jquery' ] );
124 $this->assets->register_script( DECALOG_LIVELOG_ID, DECALOG_ADMIN_URL, 'js/livelog.min.js', [ 'jquery' ] );
125 }
126
127 /**
128 * The reference to the class that orchestrates the hooks with the plugin.
129 *
130 * @since 2.0.0
131 */
132 public function disable_wp_emojis() {
133 if ( 'decalog-console' === filter_input( INPUT_GET, 'page' ) ) {
134 remove_action( 'wp_head', 'print_emoji_detection_script', 7 );
135 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
136 remove_action( 'wp_print_styles', 'print_emoji_styles' );
137 remove_action( 'admin_print_styles', 'print_emoji_styles' );
138 remove_filter( 'the_content_feed', 'wp_staticize_emoji' );
139 remove_filter( 'comment_text_rss', 'wp_staticize_emoji' );
140 remove_filter( 'wp_mail', 'wp_staticize_emoji_for_email' );
141 }
142 }
143
144 /**
145 * Sets the help action for the settings page.
146 *
147 * @param string $hook_suffix The hook suffix.
148 * @since 1.0.0
149 */
150 public function set_settings_help( $hook_suffix ) {
151 add_action( 'load-' . $hook_suffix, [ new InlineHelp(), 'set_contextual_settings' ] );
152 }
153
154 /**
155 * Sets the help action (and boxes settings) for the viewer.
156 *
157 * @param string $hook_suffix The hook suffix.
158 * @since 1.0.0
159 */
160 public function set_viewer_help( $hook_suffix ) {
161 $this->current_view = null;
162 add_action( 'load-' . $hook_suffix, [ new InlineHelp(), 'set_contextual_viewer' ] );
163 $logid = filter_input( INPUT_GET, 'logid', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
164 $eventid = filter_input( INPUT_GET, 'eventid', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
165 $traceid = filter_input( INPUT_GET, 'traceid', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
166 if ( 'decalog-viewer' === filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) {
167 if ( isset( $logid ) && isset( $eventid ) && 0 !== $eventid ) {
168 $this->current_view = new EventViewer( $logid, $eventid, $this->logger );
169 add_action( 'load-' . $hook_suffix, [ $this->current_view, 'add_metaboxes_options' ] );
170 add_action( 'admin_footer-' . $hook_suffix, [ $this->current_view, 'add_footer' ] );
171 add_filter( 'screen_settings', [ $this->current_view, 'display_screen_settings' ], 10, 2 );
172 }
173 }
174 if ( 'decalog-tviewer' === filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) {
175 if ( isset( $logid ) && isset( $traceid ) && 0 !== $traceid ) {
176 $this->current_view = new TraceViewer( $logid, $traceid, $this->logger );
177 add_action( 'load-' . $hook_suffix, [ $this->current_view, 'add_metaboxes_options' ] );
178 add_action( 'admin_footer-' . $hook_suffix, [ $this->current_view, 'add_footer' ] );
179 add_filter( 'screen_settings', [ $this->current_view, 'display_screen_settings' ], 10, 2 );
180 }
181 }
182 }
183
184 /**
185 * Init PerfOps admin menus.
186 *
187 * @param array $perfops The already declared menus.
188 * @return array The completed menus array.
189 * @since 1.0.0
190 */
191 public function init_perfopsone_admin_menus( $perfops ) {
192 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
193 $perfops['settings'][] = [
194 'name' => DECALOG_PRODUCT_NAME,
195 'description' => '',
196 'icon_callback' => [ \Decalog\Plugin\Core::class, 'get_base64_logo' ],
197 'slug' => 'decalog-settings',
198 /* translators: as in the sentence "DecaLog Settings" or "WordPress Settings" */
199 'page_title' => sprintf( decalog_esc_html__( '%s Settings', 'decalog' ), DECALOG_PRODUCT_NAME ),
200 'menu_title' => DECALOG_PRODUCT_NAME,
201 'capability' => 'manage_options',
202 'callback' => [ $this, 'get_settings_page' ],
203 'plugin' => DECALOG_SLUG,
204 'version' => DECALOG_VERSION,
205 'activated' => true,
206 'remedy' => '',
207 'statistics' => [ '\Decalog\System\Statistics', 'sc_get_raw' ],
208 'post_callback' => [ $this, 'set_settings_help' ],
209 ];
210 }
211 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() || Role::LOCAL_ADMIN === Role::admin_type() || Role::override_privileges() ) {
212 if ( Events::loggers_count() > 0 ) {
213 $perfops['records'][] = [
214 'name' => decalog_esc_html__( 'Events Log', 'decalog' ),
215 /* translators: as in the sentence "Check the events that occurred on your network." or "Check the events that occurred on your website." */
216 'description' => sprintf( decalog_esc_html__( 'Check the events that occurred on your %s.', 'decalog' ), Environment::is_wordpress_multisite() ? decalog_esc_html__( 'network', 'decalog' ) : decalog_esc_html__( 'website', 'decalog' ) ),
217 'icon_callback' => [ \Decalog\Plugin\Core::class, 'get_base64_logo' ],
218 'slug' => 'decalog-viewer',
219 /* translators: as in the sentence "DecaLog Events Viewer" */
220 'page_title' => sprintf( decalog_esc_html__( '%s Events Viewer', 'decalog' ), DECALOG_PRODUCT_NAME ),
221 'menu_title' => decalog_esc_html__( 'Events Log', 'decalog' ),
222 'capability' => 'read_private_pages',
223 'callback' => [ $this, 'get_events_page' ],
224 'plugin' => DECALOG_SLUG,
225 'activated' => true,
226 'remedy' => '',
227 'post_callback' => [ $this, 'set_viewer_help' ],
228 ];
229 }
230 if ( Traces::loggers_count() > 0 ) {
231 $perfops['records'][] = [
232 'name' => decalog_esc_html__( 'Traces', 'decalog' ),
233 /* translators: as in the sentence "Check the traces that are recorded on your network." or "Check the traces that are recorded on your website." */
234 'description' => sprintf( decalog_esc_html__( 'Check the traces that are recorded on your %s.', 'decalog' ), Environment::is_wordpress_multisite() ? decalog_esc_html__( 'network', 'decalog' ) : decalog_esc_html__( 'website', 'decalog' ) ),
235 'icon_callback' => [ \Decalog\Plugin\Core::class, 'get_base64_logo' ],
236 'slug' => 'decalog-tviewer',
237 /* translators: as in the sentence "DecaLog Traces Viewer" */
238 'page_title' => sprintf( decalog_esc_html__( '%s Traces Viewer', 'decalog' ), DECALOG_PRODUCT_NAME ),
239 'menu_title' => decalog_esc_html__( 'Traces', 'decalog' ),
240 'capability' => 'read_private_pages',
241 'callback' => [ $this, 'get_traces_page' ],
242 'plugin' => DECALOG_SLUG,
243 'activated' => true,
244 'remedy' => '',
245 'post_callback' => [ $this, 'set_viewer_help' ],
246 ];
247 }
248 }
249 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() || Role::override_privileges() ) {
250 $perfops['consoles'][] = [
251 'name' => decalog_esc_html__( 'Live Events', 'decalog' ),
252 /* translators: as in the sentence "Check the events that occurred on your network." or "Check the events that occurred on your website." */
253 'description' => sprintf( decalog_esc_html__( 'Displays events as soon as they occur on your %s.', 'decalog' ), Environment::is_wordpress_multisite() ? decalog_esc_html__( 'network', 'decalog' ) : decalog_esc_html__( 'website', 'decalog' ) ),
254 'icon_callback' => [ \Decalog\Plugin\Core::class, 'get_base64_logo' ],
255 'slug' => 'decalog-console',
256 /* translators: as in the sentence "DecaLog Viewer" */
257 'page_title' => sprintf( decalog_esc_html__( '%s Live Events', 'decalog' ), DECALOG_PRODUCT_NAME ),
258 'menu_title' => decalog_esc_html__( 'Live Events', 'decalog' ),
259 'capability' => 'read_private_pages',
260 'callback' => [ $this, 'get_console_page' ],
261 'plugin' => DECALOG_SLUG,
262 'activated' => SharedMemory::$available,
263 'remedy' => esc_url( admin_url( 'admin.php?page=decalog-settings&tab=misc' ) ),
264 ];
265 }
266 return $perfops;
267 }
268
269 /**
270 * Init PerfOps admin bar.
271 *
272 * @param array $perfops The already declared items.
273 * @return array The completed items array.
274 * @since 3.2.0
275 */
276 public function init_perfopsone_admin_bar( $perfops ) {
277 if ( ! ( $action = filter_input( INPUT_GET, 'action' ) ) ) {
278 $action = filter_input( INPUT_POST, 'action' );
279 }
280 if ( ! ( $tab = filter_input( INPUT_GET, 'tab' ) ) ) {
281 $tab = filter_input( INPUT_POST, 'tab' );
282 }
283 $early_signal = ( 'misc' === $tab && 'do-save' === $action ) && ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() );
284 $early_signal &= ( ! empty( $_POST ) && array_key_exists( 'submit', $_POST ) );
285 $early_signal &= ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-plugin-options' ) );
286 if ( $early_signal ) {
287 Option::network_set( 'adminbar', array_key_exists( 'decalog_plugin_options_adminbar', $_POST ) );
288 }
289 if ( Option::network_get( 'adminbar' ) && ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() || Role::LOCAL_ADMIN === Role::admin_type() || Role::override_privileges() ) ) {
290 if ( Events::loggers_count() > 0 ) {
291 $perfops[] = [
292 'id' => 'decalog-events-viewer',
293 'title' => '<strong>' .decalog__( 'Logs', 'decalog' ) . '</strong>&nbsp;&nbsp;➜&nbsp;&nbsp;' .decalog__( 'View Events', 'decalog' ),
294 'href' => esc_url( admin_url( 'admin.php?page=decalog-viewer' . ( Environment::is_wordpress_multisite() ? '&site_id=' . Blog::get_current_blog_id() : '' ) ) ),
295 'meta' => false,
296 ];
297 }
298 if ( Traces::loggers_count() > 0 ) {
299 $perfops[] = [
300 'id' => 'decalog-traces-viewer',
301 'title' => '<strong>' .decalog__( 'Logs', 'decalog' ) . '</strong>&nbsp;&nbsp;➜&nbsp;&nbsp;' .decalog__( 'View Traces', 'decalog' ),
302 'href' => esc_url( admin_url( 'admin.php?page=decalog-tviewer' . ( Environment::is_wordpress_multisite() ? '&site_id=' . Blog::get_current_blog_id() : '' ) ) ),
303 'meta' => false,
304 ];
305 }
306 }
307 return $perfops;
308 }
309
310 /**
311 * Dispatch the items in the settings menu.
312 *
313 * @since 2.0.0
314 */
315 public function finalize_admin_menus() {
316 Menus::finalize();
317 }
318
319 /**
320 * Removes unneeded items from the settings menu.
321 *
322 * @since 2.0.0
323 */
324 public function normalize_admin_menus() {
325 Menus::normalize();
326 }
327
328 /**
329 * Set the items in the settings menu.
330 *
331 * @since 1.0.0
332 */
333 public function init_admin_menus() {
334 if ( 'decalog-settings' === filter_input( INPUT_GET, 'page', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) ) {
335 remove_action( 'admin_print_scripts', 'print_emoji_detection_script' );
336 remove_action( 'admin_print_styles', 'print_emoji_styles' );
337 }
338 add_filter( 'init_perfopsone_admin_menus', [ $this, 'init_perfopsone_admin_menus' ] );
339 add_filter( 'init_perfopsone_admin_bar', [ $this, 'init_perfopsone_admin_bar' ] );
340 Menus::initialize();
341 AdminBar::initialize();
342 }
343
344 /**
345 * Get actions links for myblogs_blog_actions hook.
346 *
347 * @param string $actions The HTML site link markup.
348 * @param object $user_blog An object containing the site data.
349 * @return string The action string.
350 * @since 1.2.0
351 */
352 public function blog_action( $actions, $user_blog ) {
353 if ( Role::override_privileges() || Role::SUPER_ADMIN === Role::admin_type() || Role::LOCAL_ADMIN === Role::admin_type() ) {
354 if ( Events::loggers_count() > 0 ) {
355 $actions .= " | <a href='" . esc_url( admin_url( 'admin.php?page=decalog-viewer&site_id=' . $user_blog->userblog_id ) ) . "'>" .decalog__( 'Events', 'decalog' ) . '</a>';
356 }
357 if ( Traces::loggers_count() > 0 ) {
358 $actions .= " | <a href='" . esc_url( admin_url( 'admin.php?page=decalog-tviewer&site_id=' . $user_blog->userblog_id ) ) . "'>" .decalog__( 'Traces', 'decalog' ) . '</a>';
359 }
360 }
361 return $actions;
362 }
363
364 /**
365 * Get actions for manage_sites_action_links hook.
366 *
367 * @param string[] $actions An array of action links to be displayed.
368 * @param int $blog_id The site ID.
369 * @param string $blogname Site path, formatted depending on whether it is a sub-domain
370 * or subdirectory multisite installation.
371 * @return array The actions.
372 * @since 1.2.0
373 */
374 public function site_action( $actions, $blog_id, $blogname ) {
375 if ( Role::override_privileges() || Role::SUPER_ADMIN === Role::admin_type() || Role::LOCAL_ADMIN === Role::admin_type() ) {
376 if ( Events::loggers_count() > 0 ) {
377 $actions['events_log'] = "<a href='" . esc_url( admin_url( 'admin.php?page=decalog-viewer&site_id=' . $blog_id ) ) . "' rel='bookmark'>" .decalog__( 'Events', 'decalog' ) . '</a>';
378 }
379 if ( Traces::loggers_count() > 0 ) {
380 $actions['traces_log'] = "<a href='" . esc_url( admin_url( 'admin.php?page=decalog-tviewer&site_id=' . $blog_id ) ) . "' rel='bookmark'>" .decalog__( 'traces', 'decalog' ) . '</a>';
381 }
382 }
383 return $actions;
384 }
385
386 /**
387 * Initializes settings sections.
388 *
389 * @since 1.0.0
390 */
391 public function init_settings_sections() {
392 add_settings_section( 'decalog_loggers_options_section', decalog_esc_html__( 'Loggers options', 'decalog' ), [ $this, 'loggers_options_section_callback' ], 'decalog_loggers_options_section' );
393 add_settings_section( 'decalog_plugin_features_section', decalog_esc_html__( 'Plugin features', 'decalog' ), [ $this, 'plugin_features_section_callback' ], 'decalog_plugin_features_section' );
394 add_settings_section( 'decalog_plugin_options_section', decalog_esc_html__( 'Plugin options', 'decalog' ), [ $this, 'plugin_options_section_callback' ], 'decalog_plugin_options_section' );
395 add_settings_section( 'decalog_listeners_options_section', null, [ $this, 'listeners_options_section_callback' ], 'decalog_listeners_options_section' );
396 add_settings_section( 'decalog_listeners_settings_section', null, [ $this, 'listeners_settings_section_callback' ], 'decalog_listeners_settings_section' );
397 add_settings_section( 'decalog_logger_misc_section', null, [ $this, 'logger_misc_section_callback' ], 'decalog_logger_misc_section' );
398 add_settings_section( 'decalog_logger_delete_section', null, [ $this, 'logger_delete_section_callback' ], 'decalog_logger_delete_section' );
399 add_settings_section( 'decalog_logger_specific_section', null, [ $this, 'logger_specific_section_callback' ], 'decalog_logger_specific_section' );
400 add_settings_section( 'decalog_logger_privacy_section', decalog_esc_html__( 'Privacy options', 'decalog' ), [ $this, 'logger_privacy_section_callback' ], 'decalog_logger_privacy_section' );
401 add_settings_section( 'decalog_logger_details_section', decalog_esc_html__( 'Reported details', 'decalog' ), [ $this, 'logger_details_section_callback' ], 'decalog_logger_details_section' );
402 if ( apply_filters( 'perfopsone_show_advanced', false ) ) {
403 add_settings_section( 'decalog_plugin_advanced_section', decalog_esc_html__( 'Plugin advanced options', 'decalog' ), [ $this, 'plugin_advanced_section_callback' ], 'decalog_plugin_advanced_section' );
404 }
405 }
406
407 /**
408 * Add links in the "Actions" column on the plugins view page.
409 *
410 * @param string[] $actions An array of plugin action links. By default this can include 'activate',
411 * 'deactivate', and 'delete'.
412 * @param string $plugin_file Path to the plugin file relative to the plugins directory.
413 * @param array $plugin_data An array of plugin data. See `get_plugin_data()`.
414 * @param string $context The plugin context. By default this can include 'all', 'active', 'inactive',
415 * 'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
416 * @return array Extended list of links to print in the "Actions" column on the Plugins page.
417 * @since 1.0.0
418 */
419 public function add_actions_links( $actions, $plugin_file, $plugin_data, $context ) {
420 $actions[] = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=decalog-settings' ), decalog_esc_html__( 'Settings', 'decalog' ) );
421 if ( Events::loggers_count() > 0 ) {
422 $actions[] = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=decalog-viewer' ), decalog_esc_html__( 'Events', 'decalog' ) );
423 }
424 if ( Traces::loggers_count() > 0 ) {
425 $actions[] = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=decalog-tviewer' ), decalog_esc_html__( 'Traces', 'decalog' ) );
426 }
427 return $actions;
428 }
429
430 /**
431 * Add links in the "Description" column on the Plugins page.
432 *
433 * @param array $links List of links to print in the "Description" column on the Plugins page.
434 * @param string $file Path to the plugin file relative to the plugins directory.
435 * @return array Extended list of links to print in the "Description" column on the Plugins page.
436 * @since 1.3.0
437 */
438 public function add_row_meta( $links, $file ) {
439 if ( 0 === strpos( $file, DECALOG_SLUG . '/' ) ) {
440 $links[] = '<a href="https://wordpress.org/support/plugin/' . DECALOG_SLUG . '/">' .decalog__( 'Support', 'decalog' ) . '</a>';
441 }
442 return $links;
443 }
444
445 /**
446 * Get the content of the events page.
447 *
448 * @since 1.0.0
449 */
450 public function get_events_page() {
451 if ( isset( $this->current_view ) ) {
452 $this->current_view->get();
453 } else {
454 include DECALOG_ADMIN_DIR . 'partials/decalog-admin-view-events.php';
455 }
456 }
457
458 /**
459 * Get the content of the traces page.
460 *
461 * @since 1.0.0
462 */
463 public function get_traces_page() {
464 if ( isset( $this->current_view ) ) {
465 wp_enqueue_style( DECALOG_ASSETS_ID );
466 $this->current_view->get();
467 } else {
468 include DECALOG_ADMIN_DIR . 'partials/decalog-admin-view-traces.php';
469 }
470 }
471
472 /**
473 * Get the content of the console page.
474 *
475 * @since 1.0.0
476 */
477 public function get_console_page() {
478 if ( isset( $this->current_view ) ) {
479 $this->current_view->get();
480 } else {
481 include DECALOG_ADMIN_DIR . 'partials/decalog-admin-view-console.php';
482 }
483 }
484
485 /**
486 * Get the content of the settings page.
487 *
488 * @since 1.0.0
489 */
490 public function get_settings_page() {
491 $this->current_handler = null;
492 $this->current_logger = null;
493 if ( ! ( $action = filter_input( INPUT_GET, 'action' ) ) ) {
494 $action = filter_input( INPUT_POST, 'action' );
495 }
496 if ( ! ( $tab = filter_input( INPUT_GET, 'tab' ) ) ) {
497 $tab = filter_input( INPUT_POST, 'tab' );
498 }
499 if ( ! ( $handler = filter_input( INPUT_GET, 'handler' ) ) ) {
500 $handler = filter_input( INPUT_POST, 'handler' );
501 }
502 if ( ! ( $uuid = filter_input( INPUT_GET, 'uuid' ) ) ) {
503 $uuid = filter_input( INPUT_POST, 'uuid' );
504 }
505 $nonce = filter_input( INPUT_GET, 'nonce' );
506 if ( $uuid ) {
507 $loggers = Option::network_get( 'loggers' );
508 if ( array_key_exists( $uuid, $loggers ) ) {
509 $this->current_logger = $loggers[ $uuid ];
510 $this->current_logger['uuid'] = $uuid;
511 }
512 }
513 if ( $handler ) {
514 $handlers = new HandlerTypes();
515 $this->current_handler = $handlers->get( $handler );
516 } elseif ( $this->current_logger ) {
517 $handlers = new HandlerTypes();
518 $this->current_handler = $handlers->get( $this->current_logger['handler'] );
519 }
520 if ( $this->current_handler && ! $this->current_logger ) {
521 $this->creation_mode = true;
522 $this->current_logger = [
523 'uuid' => $uuid = UUID::generate_v4(),
524 'name' => decalog_esc_html__( 'New logger', 'decalog' ),
525 'handler' => $this->current_handler['id'],
526 'running' => Option::network_get( 'logger_autostart' ),
527 'level' => Logger::INFO,
528 ];
529 }
530 if ( $this->current_logger ) {
531 $factory = new LoggerFactory();
532 $this->current_logger = $factory->check( $this->current_logger );
533 }
534 $view = 'decalog-admin-settings-main';
535 if ( $action && $tab ) {
536 switch ( $tab ) {
537 case 'loggers':
538 switch ( $action ) {
539 case 'form-edit':
540 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
541 $current_logger = $this->current_logger;
542 $current_handler = $this->current_handler;
543 $args = compact( 'current_logger', 'current_handler' );
544 $view = 'decalog-admin-settings-logger-edit';
545 }
546 if ( 'system' === $current_handler['class'] ) {
547 $view = 'decalog-admin-settings-main';
548 $message = decalog_esc_html__( 'You can not modify or remove a system logger.', 'decalog' );
549 $code = 403;
550 $this->logger->error( $message, $code );
551 add_settings_error( 'decalog_error', $code, $message, 'error' );
552 }
553 break;
554 case 'form-delete':
555 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
556 $current_logger = $this->current_logger;
557 $current_handler = $this->current_handler;
558 $args = compact( 'current_logger', 'current_handler' );
559 $view = 'decalog-admin-settings-logger-delete';
560 }
561 if ( 'system' === $current_handler['class'] ) {
562 $view = 'decalog-admin-settings-main';
563 $message = decalog_esc_html__( 'You can not modify or remove a system logger.', 'decalog' );
564 $code = 403;
565 $this->logger->error( $message, $code );
566 add_settings_error( 'decalog_error', $code, $message, 'error' );
567 }
568 break;
569 case 'do-edit':
570 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
571 $this->save_current();
572 }
573 break;
574 case 'do-delete':
575 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
576 $this->delete_current();
577 }
578 break;
579 case 'start':
580 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
581 if ( $nonce && $uuid && wp_verify_nonce( $nonce, 'decalog-logger-start-' . $uuid ) ) {
582 $loggers = Option::network_get( 'loggers' );
583 if ( array_key_exists( $uuid, $loggers ) && 'system' !== $this->current_handler['class'] ) {
584 $loggers[ $uuid ]['running'] = true;
585 Option::network_set( 'loggers', $loggers );
586 $this->logger = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
587 $message = sprintf( decalog_esc_html__( 'Logger %s has started.', 'decalog' ), '<em>' . $loggers[ $uuid ]['name'] . '</em>' );
588 $code = 0;
589 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
590 $this->logger->info( sprintf( 'Logger "%s" has started.', $loggers[ $uuid ]['name'] ), $code );
591 } else {
592 $message = decalog_esc_html__( 'You can not start or pause a system logger.', 'decalog' );
593 $code = 403;
594 $this->logger->error( $message, $code );
595 add_settings_error( 'decalog_error', $code, $message, 'error' );
596 }
597 }
598 }
599 break;
600 case 'pause':
601 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
602 if ( $nonce && $uuid && wp_verify_nonce( $nonce, 'decalog-logger-pause-' . $uuid ) ) {
603 $loggers = Option::network_get( 'loggers' );
604 if ( array_key_exists( $uuid, $loggers ) && 'system' !== $this->current_handler['class'] ) {
605 $message = sprintf( decalog_esc_html__( 'Logger %s has been paused.', 'decalog' ), '<em>' . $loggers[ $uuid ]['name'] . '</em>' );
606 $code = 0;
607 $this->logger->notice( sprintf( 'Logger "%s" has been paused.', $loggers[ $uuid ]['name'] ), $code );
608 $loggers[ $uuid ]['running'] = false;
609 Option::network_set( 'loggers', $loggers );
610 $this->logger = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
611 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
612 }
613 else {
614 $message = decalog_esc_html__( 'You can not start or pause a system logger.', 'decalog' );
615 $code = 403;
616 $this->logger->error( $message, $code );
617 add_settings_error( 'decalog_error', $code, $message, 'error' );
618 }
619 }
620 }
621 case 'test':
622 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
623 if ( $nonce && $uuid && wp_verify_nonce( $nonce, 'decalog-logger-test-' . $uuid ) ) {
624 $loggers = Option::network_get( 'loggers' );
625 if ( array_key_exists( $uuid, $loggers ) ) {
626 $test = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION, $uuid );
627 $done = true;
628 foreach ( [ 'DEBUG', 'INFO', 'NOTICE', 'WARNING', 'ERROR', 'CRITICAL', 'ALERT', 'EMERGENCY' ] as $level ) {
629 $done &= $test->log( $level, ucfirst( strtolower( $level ) ) . ' test message.', 210871 );
630 }
631 if ( $done ) {
632 $message = sprintf( decalog_esc_html__( 'Test messages have been sent to logger %s.', 'decalog' ), '<em>' . $loggers[ $uuid ]['name'] . '</em>' );
633 $code = 0;
634 $this->logger->info( sprintf( 'Logger "%s" has been tested.', $loggers[ $uuid ]['name'] ), $code );
635 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
636 } else {
637 $message = sprintf( decalog_esc_html__( 'Test messages have not been sent to logger %s. Please check the logger\'s settings.', 'decalog' ), '<em>' . $loggers[ $uuid ]['name'] . '</em>' );
638 $code = 1;
639 $this->logger->warning( sprintf( 'Logger "%s" has been unsuccessfully tested.', $loggers[ $uuid ]['name'] ), $code );
640 add_settings_error( 'decalog_error', $code, $message, 'error' );
641 }
642 }
643 }
644 }
645 }
646 break;
647 case 'misc':
648 switch ( $action ) {
649 case 'do-save':
650 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
651 if ( ! empty( $_POST ) && array_key_exists( 'submit', $_POST ) ) {
652 $this->save_options();
653 } elseif ( ! empty( $_POST ) && array_key_exists( 'reset-to-defaults', $_POST ) ) {
654 $this->reset_options();
655 }
656 }
657 break;
658 case 'install-podd':
659 if ( class_exists( 'PerfOpsOne\Installer' ) && $nonce && wp_verify_nonce( $nonce, $action ) ) {
660 $result = \PerfOpsOne\Installer::do( 'device-detector', true );
661 if ( '' === $result ) {
662 add_settings_error( 'decalog_no_error', '', decalog_esc_html__( 'Plugin successfully installed and activated with default settings.', 'decalog' ), 'info' );
663 } else {
664 add_settings_error( 'decalog_install_error', '', sprintf( decalog_esc_html__( 'Unable to install or activate the plugin. Error message: %s.', 'decalog' ), $result ), 'error' );
665 }
666 }
667 break;
668 case 'install-iplocator':
669 if ( class_exists( 'PerfOpsOne\Installer' ) && $nonce && wp_verify_nonce( $nonce, $action ) ) {
670 $result = \PerfOpsOne\Installer::do( 'ip-locator', true );
671 if ( '' === $result ) {
672 add_settings_error( 'decalog_no_error', '', decalog_esc_html__( 'Plugin successfully installed and activated with default settings.', 'decalog' ), 'info' );
673 } else {
674 add_settings_error( 'decalog_install_error', '', sprintf( decalog_esc_html__( 'Unable to install or activate the plugin. Error message: %s.', 'decalog' ), $result ), 'error' );
675 }
676 }
677 break;
678 }
679 break;
680 case 'listeners':
681 switch ( $action ) {
682 case 'do-save':
683 if ( Role::SUPER_ADMIN === Role::admin_type() || Role::SINGLE_ADMIN === Role::admin_type() ) {
684 if ( ! empty( $_POST ) && array_key_exists( 'submit', $_POST ) ) {
685 $this->save_listeners();
686 } elseif ( ! empty( $_POST ) && array_key_exists( 'reset-to-defaults', $_POST ) ) {
687 $this->reset_listeners();
688 }
689 }
690 break;
691 }
692 break;
693 }
694 }
695 include DECALOG_ADMIN_DIR . 'partials/' . $view . '.php';
696 }
697
698 /**
699 * Save the listeners options.
700 *
701 * @since 1.0.0
702 */
703 private function save_listeners() {
704 if ( ! empty( $_POST ) ) {
705 if ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-listeners-options' ) ) {
706 Option::network_set( 'autolisteners', 'auto' === filter_input( INPUT_POST, 'decalog_listeners_options_auto',FILTER_SANITIZE_FULL_SPECIAL_CHARS ) );
707 $list = [];
708 $listeners = ListenerFactory::$infos;
709 foreach ( $listeners as $listener ) {
710 if ( array_key_exists( 'decalog_listeners_settings_' . $listener['id'], $_POST ) ) {
711 $list[] = $listener['id'];
712 }
713 }
714 Option::network_set( 'listeners', $list );
715 $message = decalog_esc_html__( 'Listeners settings have been saved.', 'decalog' );
716 $code = 0;
717 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
718 $this->logger->info( 'Listeners settings updated.', $code );
719 } else {
720 $message = decalog_esc_html__( 'Listeners settings have not been saved. Please try again.', 'decalog' );
721 $code = 2;
722 add_settings_error( 'decalog_nonce_error', $code, $message, 'error' );
723 $this->logger->warning( 'Listeners settings not updated.', $code );
724 }
725 }
726 }
727
728 /**
729 * Reset the listeners options.
730 *
731 * @since 1.0.0
732 */
733 private function reset_listeners() {
734 if ( ! empty( $_POST ) ) {
735 if ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-listeners-options' ) ) {
736 Option::network_set( 'autolisteners', true );
737 $message = decalog_esc_html__( 'Listeners settings have been reset to defaults.', 'decalog' );
738 $code = 0;
739 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
740 $this->logger->info( 'Listeners settings reset to defaults.', $code );
741 } else {
742 $message = decalog_esc_html__( 'Listeners settings have not been reset to defaults. Please try again.', 'decalog' );
743 $code = 2;
744 add_settings_error( 'decalog_nonce_error', $code, $message, 'error' );
745 $this->logger->warning( 'Listeners settings not reset to defaults.', $code );
746 }
747 }
748 }
749
750 /**
751 * Save the plugin options.
752 *
753 * @since 1.0.0
754 */
755 private function save_options() {
756 if ( ! empty( $_POST ) ) {
757 if ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-plugin-options' ) ) {
758 Option::network_set( 'use_cdn', array_key_exists( 'decalog_plugin_options_usecdn', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_options_usecdn' ) : false );
759 Option::network_set( 'display_nag', array_key_exists( 'decalog_plugin_options_nag', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_options_nag' ) : false );
760 Option::network_set( 'adminbar', array_key_exists( 'decalog_plugin_options_adminbar', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_options_adminbar' ) : false );
761 Option::network_set( 'download_favicons', array_key_exists( 'decalog_plugin_options_favicons', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_options_favicons' ) : false );
762 Option::network_set( 'earlyloading', array_key_exists( 'decalog_plugin_features_earlyloading', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_features_earlyloading' ) : false );
763 Option::network_set( 'logger_autostart', array_key_exists( 'decalog_loggers_options_autostart', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_loggers_options_autostart' ) : false );
764 Option::network_set( 'pseudonymization', array_key_exists( 'decalog_loggers_options_pseudonymization', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_loggers_options_pseudonymization' ) : false );
765 Option::network_set( 'respect_wp_debug', array_key_exists( 'decalog_loggers_options_wpdebug', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_loggers_options_wpdebug' ) : false );
766 Option::network_set( 'env_substitution', array_key_exists( 'decalog_loggers_options_env_substitution', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_loggers_options_env_substitution' ) : false );
767 Option::network_set( 'privileges', array_key_exists( 'decalog_plugin_options_privileges', $_POST ) ? (string) filter_input( INPUT_POST, 'decalog_plugin_options_privileges', FILTER_SANITIZE_NUMBER_INT ) : Option::network_get( 'privileges' ) );
768 Option::network_set( 'metrics_authent', array_key_exists( 'decalog_plugin_features_metrics_authent', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_features_metrics_authent' ) : false );
769 Option::network_set( 'slow_query_warn', array_key_exists( 'decalog_plugin_features_slowqueries', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_features_slowqueries' ) : false );
770 Option::network_set( 'unknown_metrics_warn', array_key_exists( 'decalog_plugin_features_unknownmetrics', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_features_unknownmetrics' ) : false );
771 Option::network_set( 'trace_query', array_key_exists( 'decalog_plugin_features_tracequeries', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_features_tracequeries' ) : false );
772
773 Option::network_set( 'unbuffered_cli', array_key_exists( 'decalog_plugin_advanced_unbuffered_cli', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_advanced_unbuffered_cli' ) : false );
774 Option::network_set( 'buffer_size', array_key_exists( 'decalog_plugin_advanced_buffer_size', $_POST ) ? (string) filter_input( INPUT_POST, 'decalog_plugin_advanced_buffer_size', FILTER_SANITIZE_NUMBER_INT ) : Option::network_get( 'buffer_size' ) );
775
776 $autolog = array_key_exists( 'decalog_plugin_features_livelog', $_POST ) ? (bool) filter_input( INPUT_POST, 'decalog_plugin_features_livelog' ) : false;
777 if ( $autolog ) {
778 Autolog::activate();
779 } else {
780 Autolog::deactivate();
781 }
782 $message = decalog_esc_html__( 'Plugin settings have been saved.', 'decalog' );
783 $code = 0;
784 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
785 $this->logger->info( 'Plugin settings updated.', $code );
786 } else {
787 $message = decalog_esc_html__( 'Plugin settings have not been saved. Please try again.', 'decalog' );
788 $code = 2;
789 add_settings_error( 'decalog_nonce_error', $code, $message, 'error' );
790 $this->logger->warning( 'Plugin settings not updated.', $code );
791 }
792 }
793 }
794
795 /**
796 * Reset the plugin options.
797 *
798 * @since 1.0.0
799 */
800 private function reset_options() {
801 if ( ! empty( $_POST ) ) {
802 if ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-plugin-options' ) ) {
803 Option::reset_to_defaults();
804 $message = decalog_esc_html__( 'Plugin settings have been reset to defaults.', 'decalog' );
805 $code = 0;
806 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
807 $this->logger->info( 'Plugin settings reset to defaults.', $code );
808 } else {
809 $message = decalog_esc_html__( 'Plugin settings have not been reset to defaults. Please try again.', 'decalog' );
810 $code = 2;
811 add_settings_error( 'decalog_nonce_error', $code, $message, 'error' );
812 $this->logger->warning( 'Plugin settings not reset to defaults.', $code );
813 }
814 }
815 }
816
817 /**
818 * Save the current logger as new or modified logger.
819 *
820 * @since 1.0.0
821 */
822 private function save_current() {
823 if ( ! empty( $_POST ) ) {
824 if ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-logger-edit' ) ) {
825 if ( array_key_exists( 'submit', $_POST ) ) {
826 $this->current_logger['name'] = ( array_key_exists( 'decalog_logger_misc_name', $_POST ) ? filter_input( INPUT_POST, 'decalog_logger_misc_name', FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : $this->current_logger['name'] );
827 $this->current_logger['level'] = ( array_key_exists( 'decalog_logger_misc_level', $_POST ) ? filter_input( INPUT_POST, 'decalog_logger_misc_level', FILTER_SANITIZE_NUMBER_INT ) : $this->current_logger['level'] );
828 $this->current_logger['privacy']['obfuscation'] = ( array_key_exists( 'decalog_logger_privacy_ip', $_POST ) ? true : false );
829 $this->current_logger['privacy']['pseudonymization'] = ( array_key_exists( 'decalog_logger_privacy_name', $_POST ) ? true : false );
830 $this->current_logger['processors'] = [];
831 $proc = new ProcessorTypes();
832 foreach ( array_reverse( $proc->get_all() ) as $processor ) {
833 if ( array_key_exists( 'decalog_logger_details_' . strtolower( $processor['id'] ), $_POST ) ) {
834 $this->current_logger['processors'][] = $processor['id'];
835 }
836 }
837 foreach ( $this->current_handler['configuration'] as $key => $configuration ) {
838 $id = 'decalog_logger_details_' . strtolower( $key );
839 if ( 'boolean' === $configuration['control']['cast'] ) {
840 $this->current_logger['configuration'][ $key ] = ( array_key_exists( $id, $_POST ) ? true : false );
841 }
842 if ( 'integer' === $configuration['control']['cast'] ) {
843 $this->current_logger['configuration'][ $key ] = ( array_key_exists( $id, $_POST ) ? filter_input( INPUT_POST, $id, FILTER_SANITIZE_NUMBER_INT ) : $this->current_logger['configuration'][ $key ] );
844 }
845 if ( 'string' === $configuration['control']['cast'] ) {
846 $this->current_logger['configuration'][ $key ] = ( array_key_exists( $id, $_POST ) ? filter_input( INPUT_POST, $id, FILTER_SANITIZE_FULL_SPECIAL_CHARS ) : $this->current_logger['configuration'][ $key ] );
847 }
848 if ( 'password' === $configuration['control']['cast'] ) {
849 $this->current_logger['configuration'][ $key ] = ( array_key_exists( $id, $_POST ) ? filter_input( INPUT_POST, $id, FILTER_UNSAFE_RAW ) : $this->current_logger['configuration'][ $key ] );
850 }
851 }
852 $uuid = $this->current_logger['uuid'];
853 $loggers = Option::network_get( 'loggers' );
854 $factory = new LoggerFactory();
855 $loggers[ $uuid ] = $factory->check( $this->current_logger, true );
856 if ( array_key_exists( 'uuid', $loggers[ $uuid ] ) ) {
857 unset( $loggers[ $uuid ]['uuid'] );
858 }
859 Option::network_set( 'loggers', $loggers );
860 $this->logger = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
861 $message = sprintf( decalog_esc_html__( 'Logger %s has been saved.', 'decalog' ), '<em>' . $this->current_logger['name'] . '</em>' );
862 $code = 0;
863 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
864 $this->logger->info( sprintf( 'Logger "%s" has been saved.', $this->current_logger['name'] ), $code );
865 }
866 } else {
867 $message = sprintf( decalog_esc_html__( 'Logger %s has not been saved. Please try again.', 'decalog' ), '<em>' . $this->current_logger['name'] . '</em>' );
868 $code = 2;
869 add_settings_error( 'decalog_nonce_error', $code, $message, 'error' );
870 $this->logger->warning( sprintf( 'Logger "%s" has not been saved.', $this->current_logger['name'] ), $code );
871 }
872 }
873 }
874
875 /**
876 * Delete the current logger.
877 *
878 * @since 1.0.0
879 */
880 private function delete_current() {
881 if ( ! empty( $_POST ) ) {
882 if ( array_key_exists( '_wpnonce', $_POST ) && wp_verify_nonce( $_POST['_wpnonce'], 'decalog-logger-delete' ) ) {
883 if ( array_key_exists( 'submit', $_POST ) ) {
884 $uuid = $this->current_logger['uuid'];
885 $loggers = Option::network_get( 'loggers' );
886 $factory = new LoggerFactory();
887 $factory->destroy( $this->current_logger );
888 unset( $loggers[ $uuid ] );
889 Option::network_set( 'loggers', $loggers );
890 $this->logger = Log::bootstrap( 'plugin', DECALOG_PRODUCT_SHORTNAME, DECALOG_VERSION );
891 $message = sprintf( decalog_esc_html__( 'Logger %s has been removed.', 'decalog' ), '<em>' . $this->current_logger['name'] . '</em>' );
892 $code = 0;
893 add_settings_error( 'decalog_no_error', $code, $message, 'updated' );
894 $this->logger->notice( sprintf( 'Logger "%s" has been removed.', $this->current_logger['name'] ), $code );
895 }
896 } else {
897 $message = sprintf( decalog_esc_html__( 'Logger %s has not been removed. Please try again.', 'decalog' ), '<em>' . $this->current_logger['name'] . '</em>' );
898 $code = 2;
899 add_settings_error( 'decalog_nonce_error', $code, $message, 'error' );
900 $this->logger->warning( sprintf( 'Logger "%s" has not been removed.', $this->current_logger['name'] ), $code );
901 }
902 }
903 }
904
905 /**
906 * Callback for listeners options section.
907 *
908 * @since 1.0.0
909 */
910 public function listeners_options_section_callback() {
911 $form = new Form();
912 add_settings_field(
913 'decalog_listeners_options_auto',
914 __( 'Activate', 'decalog' ),
915 [ $form, 'echo_field_select' ],
916 'decalog_listeners_options_section',
917 'decalog_listeners_options_section',
918 [
919 'list' => [
920 0 => [ 'manual', decalog_esc_html__( 'Selected listeners', 'decalog' ) ],
921 1 => [ 'auto', decalog_esc_html__( 'All available listeners (recommended)', 'decalog' ) ],
922 ],
923 'id' => 'decalog_listeners_options_auto',
924 'value' => Option::network_get( 'autolisteners' ) ? 'auto' : 'manual',
925 'description' => decalog_esc_html__( 'Automatically or selectively choose which sources to listen.', 'decalog' ),
926 'full_width' => false,
927 'enabled' => true,
928 ]
929 );
930 register_setting( 'decalog_listeners_options_section', 'decalog_listeners_options_autostart' );
931 }
932
933 /**
934 * Callback for listeners settings section.
935 *
936 * @since 1.0.0
937 */
938 public function listeners_settings_section_callback() {
939 $standard = [];
940 $plugin = [];
941 $theme = [];
942 $library = [];
943 $listeners = ListenerFactory::$infos;
944 usort(
945 $listeners,
946 function( $a, $b ) {
947 return strcmp( strtolower( $a['name'] ), strtolower( $b['name'] ) );
948 }
949 );
950 foreach ( $listeners as $listener ) {
951 if ( 'plugin' === $listener['class'] && $listener['available'] ) {
952 $plugin[] = $listener;
953 } elseif ( 'theme' === $listener['class'] && $listener['available'] ) {
954 $theme[] = $listener;
955 } elseif ( 'library' === $listener['class'] && $listener['available'] ) {
956 $library[] = $listener;
957 } elseif ( $listener['available'] ) {
958 $standard[] = $listener;
959 }
960 }
961 $main = [
962 decalog_esc_html__( 'Standard listeners', 'decalog' ) => $standard,
963 decalog_esc_html__( 'Plugin listeners', 'decalog' ) => $plugin,
964 decalog_esc_html__( 'Library listeners', 'decalog' ) => $library,
965 decalog_esc_html__( 'Theme listeners', 'decalog' ) => $theme,
966 ];
967 $form = new Form();
968 foreach ( $main as $name => $items ) {
969 $title = true;
970 foreach ( $items as $item ) {
971 add_settings_field(
972 'decalog_listeners_settings_' . $item['id'],
973 $title ? $name : null,
974 [ $form, 'echo_field_checkbox' ],
975 'decalog_listeners_settings_section',
976 'decalog_listeners_settings_section',
977 [
978 'text' => sprintf( '%s (%s %s)', $item['name'], $item['product'], $item['version'] ),
979 'id' => 'decalog_listeners_settings_' . $item['id'],
980 'checked' => in_array( $item['id'], Option::network_get( 'listeners' ), true ),
981 'description' => null,
982 'full_width' => false,
983 'enabled' => true,
984 ]
985 );
986 register_setting( 'decalog_listeners_settings_section', 'decalog_listeners_settings_' . $item['id'] );
987 $title = false;
988 }
989 }
990 }
991
992 /**
993 * Callback for loggers options section.
994 *
995 * @since 1.0.0
996 */
997 public function loggers_options_section_callback() {
998 $form = new Form();
999 add_settings_field(
1000 'decalog_loggers_options_autostart',
1001 __( 'New logger', 'decalog' ),
1002 [ $form, 'echo_field_checkbox' ],
1003 'decalog_loggers_options_section',
1004 'decalog_loggers_options_section',
1005 [
1006 'text' => decalog_esc_html__( 'Auto-start', 'decalog' ),
1007 'id' => 'decalog_loggers_options_autostart',
1008 'checked' => Option::network_get( 'logger_autostart' ),
1009 'description' => decalog_esc_html__( 'If checked, when a new logger is added it automatically starts.', 'decalog' ),
1010 'full_width' => false,
1011 'enabled' => true,
1012 ]
1013 );
1014 register_setting( 'decalog_loggers_options_section', 'decalog_loggers_options_autostart' );
1015 add_settings_field(
1016 'decalog_loggers_options_pseudonymization',
1017 __( 'Events messages', 'decalog' ),
1018 [ $form, 'echo_field_checkbox' ],
1019 'decalog_loggers_options_section',
1020 'decalog_loggers_options_section',
1021 [
1022 'text' => decalog_esc_html__( 'Respect privacy', 'decalog' ),
1023 'id' => 'decalog_loggers_options_pseudonymization',
1024 'checked' => Option::network_get( 'pseudonymization' ),
1025 'description' => decalog_esc_html__( 'If checked, DecaLog will try to obfuscate personal information in events messages.', 'decalog' ),
1026 'full_width' => false,
1027 'enabled' => true,
1028 ]
1029 );
1030 register_setting( 'decalog_loggers_options_section', 'decalog_loggers_options_pseudonymization' );
1031 add_settings_field(
1032 'decalog_loggers_options_wpdebug',
1033 __( 'Rules', 'decalog' ),
1034 [ $form, 'echo_field_checkbox' ],
1035 'decalog_loggers_options_section',
1036 'decalog_loggers_options_section',
1037 [
1038 'text' => decalog_esc_html__( 'Respect WP_DEBUG', 'decalog' ),
1039 'id' => 'decalog_loggers_options_wpdebug',
1040 'checked' => Option::network_get( 'respect_wp_debug' ),
1041 'description' => decalog_esc_html__( 'If checked, the value of WP_DEBUG will override each logger\'s settings for minimal level of logging.', 'decalog' ),
1042 'full_width' => false,
1043 'enabled' => true,
1044 ]
1045 );
1046 register_setting( 'decalog_loggers_options_section', 'decalog_loggers_options_wpdebug' );
1047 add_settings_field(
1048 'decalog_loggers_options_env_substitution',
1049 __( 'Parameters', 'decalog' ),
1050 [ $form, 'echo_field_checkbox' ],
1051 'decalog_loggers_options_section',
1052 'decalog_loggers_options_section',
1053 [
1054 'text' => decalog_esc_html__( 'Variables substitution', 'decalog' ),
1055 'id' => 'decalog_loggers_options_env_substitution',
1056 'checked' => Option::network_get( 'env_substitution' ),
1057 'description' => decalog_esc_html__( 'If checked, DecaLog will replace strings between curly braces by the corresponding environment variables or PHP-defined constants.', 'decalog' ),
1058 'full_width' => false,
1059 'enabled' => true,
1060 ]
1061 );
1062 register_setting( 'decalog_loggers_options_section', 'decalog_loggers_options_env_substitution' );
1063 }
1064
1065 /**
1066 * Get the available privileges overriding.
1067 *
1068 * @return array An array containing the privileges overriding.
1069 * @since 2.4.0
1070 */
1071 protected function get_privileges_array() {
1072 $result = [];
1073 $result[] = [ 0, decalog_esc_html__( 'Never override privileges', 'decalog' ) ];
1074 $result[] = [ 1, decalog_esc_html__( 'Override privileges for development environments', 'decalog' ) ];
1075 $result[] = [ 2, decalog_esc_html__( 'Override privileges for staging environments', 'decalog' ) ];
1076 $result[] = [ 3, decalog_esc_html__( 'Override privileges for staging and development environments', 'decalog' ) ];
1077 return $result;
1078 }
1079
1080 /**
1081 * Callback for plugin options section.
1082 *
1083 * @since 1.0.0
1084 */
1085 public function plugin_options_section_callback() {
1086 $form = new Form();
1087 if ( function_exists( 'wp_get_environment_type' ) ) {
1088 add_settings_field(
1089 'decalog_plugin_options_privileges',
1090 decalog_esc_html__( 'Logs accesses', 'decalog' ),
1091 [ $form, 'echo_field_select' ],
1092 'decalog_plugin_options_section',
1093 'decalog_plugin_options_section',
1094 [
1095 'list' => $this->get_privileges_array(),
1096 'id' => 'decalog_plugin_options_privileges',
1097 'value' => Option::network_get( 'privileges' ),
1098 'description' => decalog_esc_html__( 'Allows other users than administrators to access live console and local events logs depending of environments.', 'decalog' ) . '<br/>' . decalog_esc_html__( 'Note: choosing something other than "Never override privileges" grants access to all users having "read_private_pages" capability and may have privacy and security implications.', 'decalog' ),
1099 'full_width' => false,
1100 'enabled' => true,
1101 ]
1102 );
1103 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_privileges' );
1104 }
1105 add_settings_field(
1106 'decalog_plugin_options_adminbar',
1107 __( 'Quick actions', 'decalog' ),
1108 [ $form, 'echo_field_checkbox' ],
1109 'decalog_plugin_options_section',
1110 'decalog_plugin_options_section',
1111 [
1112 'text' => decalog_esc_html__( 'Display in admin bar', 'decalog' ),
1113 'id' => 'decalog_plugin_options_adminbar',
1114 'checked' => Option::network_get( 'adminbar' ),
1115 'description' => decalog_esc_html__( 'If checked, DecaLog will display in admin bar the most important actions, if any.', 'decalog' ),
1116 'full_width' => false,
1117 'enabled' => true,
1118 ]
1119 );
1120 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_adminbar' );
1121 add_settings_field(
1122 'decalog_plugin_options_favicons',
1123 __( 'Favicons', 'decalog' ),
1124 [ $form, 'echo_field_checkbox' ],
1125 'decalog_plugin_options_section',
1126 'decalog_plugin_options_section',
1127 [
1128 'text' => decalog_esc_html__( 'Download and display', 'decalog' ),
1129 'id' => 'decalog_plugin_options_favicons',
1130 'checked' => Option::network_get( 'download_favicons' ),
1131 'description' => decalog_esc_html__( 'If checked, DecaLog will download favicons of websites to display them in reports.', 'decalog' ) . '<br/>' . decalog_esc_html__( 'Note: This feature uses the (free) Google Favicon Service.', 'decalog' ),
1132 'full_width' => false,
1133 'enabled' => true,
1134 ]
1135 );
1136 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_favicons' );
1137 if ( class_exists( 'PODeviceDetector\API\Device' ) ) {
1138 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'thumbs-up', 'none', '#00C800' ) . '" />&nbsp;';
1139 $help .= sprintf( decalog_esc_html__('Your site is currently using %s.', 'decalog' ), '<em>Device Detector v' . PODD_VERSION .'</em>' );
1140 } else {
1141 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'alert-triangle', 'none', '#FF8C00' ) . '" />&nbsp;';
1142 $help .= sprintf( decalog_esc_html__('Your site does not use any device detection mechanism. To handle user-agents and callers reporting in DecaLog, I recommend you to install the excellent (and free) %s. But it is not mandatory.', 'decalog' ), '<a href="https://wordpress.org/plugins/device-detector/">Device Detector</a>' );
1143 if ( class_exists( 'PerfOpsOne\Installer' ) && ! Environment::is_wordpress_multisite() ) {
1144 $help .= '<br/><a href="' . wp_nonce_url( admin_url( 'admin.php?page=decalog-settings&tab=misc&action=install-podd' ), 'install-podd', 'nonce' ) . '" class="poo-button-install"><img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'download-cloud', 'none', '#FFFFFF', 3 ) . '" />&nbsp;&nbsp;' . decalog_esc_html__('Install It Now', 'decalog' ) . '</a>';
1145 }
1146 }
1147 add_settings_field(
1148 'decalog_plugin_options_podd',
1149 __( 'Device Detection', 'decalog' ),
1150 [ $form, 'echo_field_simple_text' ],
1151 'decalog_plugin_options_section',
1152 'decalog_plugin_options_section',
1153 [
1154 'text' => $help
1155 ]
1156 );
1157 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_podd' );
1158 $geo_ip = new GeoIP();
1159 if ( $geo_ip->is_installed() ) {
1160 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'thumbs-up', 'none', '#00C800' ) . '" />&nbsp;';
1161 $help .= sprintf( decalog_esc_html__('Your site is currently using %s.', 'decalog' ), '<em>' . $geo_ip->get_full_name() .'</em>' );
1162 } else {
1163 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'alert-triangle', 'none', '#FF8C00' ) . '" />&nbsp;';
1164 $help .= sprintf( decalog_esc_html__('Your site does not use any IP geographic information plugin. To display callers geographical details in DecaLog, I recommend you to install the excellent (and free) %s. But it is not mandatory.', 'decalog' ), '<a href="https://wordpress.org/plugins/ip-locator/">IP Locator</a>' );
1165 if ( class_exists( 'PerfOpsOne\Installer' ) && ! Environment::is_wordpress_multisite() ) {
1166 $help .= '<br/><a href="' . wp_nonce_url( admin_url( 'admin.php?page=decalog-settings&tab=misc&action=install-iplocator' ), 'install-iplocator', 'nonce' ) . '" class="poo-button-install"><img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'download-cloud', 'none', '#FFFFFF', 3 ) . '" />&nbsp;&nbsp;' . decalog_esc_html__('Install It Now', 'decalog' ) . '</a>';
1167 }
1168 }
1169 add_settings_field(
1170 'decalog_plugin_options_geoip',
1171 __( 'IP information', 'decalog' ),
1172 [ $form, 'echo_field_simple_text' ],
1173 'decalog_plugin_options_section',
1174 'decalog_plugin_options_section',
1175 [
1176 'text' => $help
1177 ]
1178 );
1179 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_geoip' );
1180 if ( SharedMemory::$available ) {
1181 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'thumbs-up', 'none', '#00C800' ) . '" />&nbsp;';
1182 $help .= decalog_esc_html__('Shared memory is available on your server: you can use live console.', 'decalog' );
1183 } else {
1184 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'alert-triangle', 'none', '#FF8C00' ) . '" />&nbsp;';
1185 $help .= sprintf( decalog_esc_html__('Shared memory is not available on your server. To use live console you must activate %s PHP module.', 'decalog' ), '<code>shmop</code>' );
1186 }
1187 add_settings_field(
1188 'decalog_plugin_options_shmop',
1189 __( 'Shared memory', 'decalog' ),
1190 [ $form, 'echo_field_simple_text' ],
1191 'decalog_plugin_options_section',
1192 'decalog_plugin_options_section',
1193 [
1194 'text' => $help
1195 ]
1196 );
1197 if ( Cache::$apcu_available) {
1198 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'thumbs-up', 'none', '#00C800' ) . '" />&nbsp;';
1199 $help .= decalog_esc_html__('APCu is available on your server: you can use high peformance storage mechanism.', 'decalog' );
1200 } else {
1201 $help = '<img style="width:16px;vertical-align:text-bottom;" src="' . \Feather\Icons::get_base64( 'alert-triangle', 'none', '#FF8C00' ) . '" />&nbsp;';
1202 $help .= sprintf( decalog_esc_html__('APCu is not available on your server. To use high peformance storage mechanism you must activate %s PHP module.', 'decalog' ), '<code>apcu</code>' );
1203 }
1204 add_settings_field(
1205 'decalog_plugin_options_apcu',
1206 __( 'APCu storage', 'decalog' ),
1207 [ $form, 'echo_field_simple_text' ],
1208 'decalog_plugin_options_section',
1209 'decalog_plugin_options_section',
1210 [
1211 'text' => $help
1212 ]
1213 );
1214 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_shmop' );
1215 add_settings_field(
1216 'decalog_plugin_options_usecdn',
1217 __( 'Resources', 'decalog' ),
1218 [ $form, 'echo_field_checkbox' ],
1219 'decalog_plugin_options_section',
1220 'decalog_plugin_options_section',
1221 [
1222 'text' => decalog_esc_html__( 'Use public CDN', 'decalog' ),
1223 'id' => 'decalog_plugin_options_usecdn',
1224 'checked' => Option::network_get( 'use_cdn' ),
1225 'description' => decalog_esc_html__( 'Use CDN (jsDelivr) to serve DecaLog scripts and stylesheets.', 'decalog' ),
1226 'full_width' => false,
1227 'enabled' => true,
1228 ]
1229 );
1230 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_usecdn' );
1231 add_settings_field(
1232 'decalog_plugin_options_nag',
1233 __( 'Admin notices', 'decalog' ),
1234 [ $form, 'echo_field_checkbox' ],
1235 'decalog_plugin_options_section',
1236 'decalog_plugin_options_section',
1237 [
1238 'text' => decalog_esc_html__( 'Display', 'decalog' ),
1239 'id' => 'decalog_plugin_options_nag',
1240 'checked' => Option::network_get( 'display_nag' ),
1241 'description' => decalog_esc_html__( 'Allows DecaLog to display admin notices throughout the admin dashboard.', 'decalog' ) . '<br/>' . decalog_esc_html__( 'Note: DecaLog respects DISABLE_NAG_NOTICES flag.', 'decalog' ),
1242 'full_width' => false,
1243 'enabled' => true,
1244 ]
1245 );
1246 register_setting( 'decalog_plugin_options_section', 'decalog_plugin_options_nag' );
1247 }
1248
1249 /**
1250 * Callback for plugin features section.
1251 *
1252 * @since 1.0.0
1253 */
1254 public function plugin_features_section_callback() {
1255 $form = new Form();
1256 add_settings_field(
1257 'decalog_plugin_features_earlyloading',
1258 __( 'Initialization', 'decalog' ),
1259 [ $form, 'echo_field_checkbox' ],
1260 'decalog_plugin_features_section',
1261 'decalog_plugin_features_section',
1262 [
1263 'text' => decalog_esc_html__( 'Activate early loading', 'decalog' ),
1264 'id' => 'decalog_plugin_features_earlyloading',
1265 'checked' => ( 3 === \decalog_get_psr_log_version() ) ? Option::network_get( 'earlyloading' ) : false,
1266 'description' => ( 3 === \decalog_get_psr_log_version() ) ? decalog_esc_html__( 'If checked, DecaLog will be loaded before all other plugins (recommended).', 'decalog' ) : decalog_esc_html__( 'Option not available.', 'decalog' ) . ' ' . sprintf( decalog_esc_html__( '%s is running in PSR-3 v1 compatibility mode due to an obsolete or outdated third-party plugin or theme.', 'decalog' ), DECALOG_PRODUCT_NAME ) . '<br/>' . sprintf(decalog__( 'Please, do not hesitate to <a href="%s">take part in discussion</a>.', 'decalog' ), 'https://github.com/Pierre-Lannoy/wp-decalog/discussions/63' ),
1267 'full_width' => false,
1268 'enabled' => ( 3 === \decalog_get_psr_log_version() ),
1269 ]
1270 );
1271 register_setting( 'decalog_plugin_features_section', 'decalog_plugin_features_earlyloading' );
1272 if ( SharedMemory::$available ) {
1273 add_settings_field(
1274 'decalog_plugin_features_livelog',
1275 __( 'Live console', 'decalog' ),
1276 [ $form, 'echo_field_checkbox' ],
1277 'decalog_plugin_features_section',
1278 'decalog_plugin_features_section',
1279 [
1280 'text' => decalog_esc_html__( 'Activate auto-logging', 'decalog' ),
1281 'id' => 'decalog_plugin_features_livelog',
1282 'checked' => Autolog::is_enabled(),
1283 'description' => decalog_esc_html__( 'If checked, DecaLog will silently start the features needed by live console.', 'decalog' ),
1284 'full_width' => false,
1285 'enabled' => true,
1286 ]
1287 );
1288 register_setting( 'decalog_plugin_features_section', 'decalog_plugin_features_livelog' );
1289 }
1290 add_settings_field(
1291 'decalog_plugin_features_slowqueries',
1292 __( 'Database', 'decalog' ),
1293 [ $form, 'echo_field_checkbox' ],
1294 'decalog_plugin_features_section',
1295 'decalog_plugin_features_section',
1296 [
1297 'text' => decalog_esc_html__( 'Warn about slow queries', 'decalog' ),
1298 'id' => 'decalog_plugin_features_slowqueries',
1299 'checked' => Option::network_get( 'slow_query_warn' ),
1300 'description' => sprintf( decalog_esc_html__( 'If checked, a warning will be triggered for each SQL query that takes %.1F ms or more to execute.', 'decalog' ), Option::network_get( 'slow_query_ms', 50 ) ),
1301 'full_width' => false,
1302 'enabled' => true,
1303 ]
1304 );
1305 register_setting( 'decalog_plugin_features_section', 'decalog_plugin_features_slowqueries' );
1306 add_settings_field(
1307 'decalog_plugin_features_tracequeries',
1308 '',
1309 [ $form, 'echo_field_checkbox' ],
1310 'decalog_plugin_features_section',
1311 'decalog_plugin_features_section',
1312 [
1313 'text' => decalog_esc_html__( 'Trace queries', 'decalog' ),
1314 'id' => 'decalog_plugin_features_tracequeries',
1315 'checked' => Option::network_get( 'trace_query' ),
1316 'description' => decalog_esc_html__( 'If checked, all SQL queries will be traced and pushed to running trace loggers.', 'decalog' ),
1317 'full_width' => false,
1318 'enabled' => true,
1319 ]
1320 );
1321 register_setting( 'decalog_plugin_features_section', 'decalog_plugin_features_tracequeries' );
1322 add_settings_field(
1323 'decalog_plugin_features_unknownmetrics',
1324 __( 'Metrics', 'decalog' ),
1325 [ $form, 'echo_field_checkbox' ],
1326 'decalog_plugin_features_section',
1327 'decalog_plugin_features_section',
1328 [
1329 'text' => decalog_esc_html__( 'Warn about non-existent metrics', 'decalog' ),
1330 'id' => 'decalog_plugin_features_unknownmetrics',
1331 'checked' => Option::network_get( 'unknown_metrics_warn' ),
1332 'description' => decalog_esc_html__( 'If checked, an error will be triggered when a process try to set a value for a metric which is not defined.', 'decalog' ),
1333 'full_width' => false,
1334 'enabled' => true,
1335 ]
1336 );
1337 register_setting( 'decalog_plugin_features_section', 'decalog_plugin_features_unknownmetrics' );
1338 add_settings_field(
1339 'decalog_plugin_features_metrics_authent',
1340 '',
1341 [ $form, 'echo_field_checkbox' ],
1342 'decalog_plugin_features_section',
1343 'decalog_plugin_features_section',
1344 [
1345 'text' => decalog_esc_html__( 'Authenticated endpoint', 'decalog' ),
1346 'id' => 'decalog_plugin_features_metrics_authent',
1347 'checked' => Option::network_get( 'metrics_authent' ),
1348 'description' => sprintf( decalog_esc_html__( 'If checked, DecaLog will require authentication to serve %s calls.', 'decalog' ), '<code>' . htmlentities( '/wp-json/' . DECALOG_REST_NAMESPACE . '/metrics' ) . '</code>' ) . '<br/>' . sprintf( decalog_esc_html__( 'Note: if you activate authentication, you must generate an application password for a user having %s capability.', 'decalog' ), '<code>read_private_pages</code>' ),
1349 'full_width' => false,
1350 'enabled' => true,
1351 ]
1352 );
1353 register_setting( 'decalog_plugin_features_section', 'decalog_plugin_features_metrics_authent' );
1354 }
1355
1356 /**
1357 * Callback for plugin advanced section.
1358 *
1359 * @since 4.3.0
1360 */
1361 public function plugin_advanced_section_callback() {
1362 $form = new Form();
1363 add_settings_field(
1364 'decalog_plugin_advanced_unbuffered_cli',
1365 'Force unbuffering',
1366 [ $form, 'echo_field_checkbox' ],
1367 'decalog_plugin_advanced_section',
1368 'decalog_plugin_advanced_section',
1369 [
1370 'text' => 'WP CLI events',
1371 'id' => 'decalog_plugin_advanced_unbuffered_cli',
1372 'checked' => Option::network_get( 'unbuffered_cli' ),
1373 'description' => 'If checked, events triggered via WP CLI will not be buffered.',
1374 'full_width' => false,
1375 'enabled' => true,
1376 ]
1377 );
1378 register_setting( 'decalog_plugin_advanced_section', 'decalog_plugin_advanced_unbuffered_cli' );
1379 add_settings_field(
1380 'decalog_plugin_advanced_buffer_size',
1381 'Events buffer size',
1382 [ $form, 'echo_field_input_integer' ],
1383 'decalog_plugin_advanced_section',
1384 'decalog_plugin_advanced_section',
1385 [
1386 'id' => 'decalog_plugin_advanced_buffer_size',
1387 'value' => Option::network_get( 'buffer_size' ),
1388 'min' => 10,
1389 'max' => 2000,
1390 'step' => 10,
1391 'description' => 'Buffer size, in number of events.',
1392 'full_width' => false,
1393 'enabled' => true,
1394 ]
1395 );
1396 register_setting( 'decalog_plugin_advanced_section', 'decalog_plugin_advanced_buffer_size' );
1397 }
1398
1399
1400 /**
1401 * Callback for logger misc section.
1402 *
1403 * @since 1.0.0
1404 */
1405 public function logger_misc_section_callback() {
1406 $icon = '<img style="vertical-align:middle;width:34px;margin-top: -2px;padding-right:6px;" src="' . $this->current_handler['icon'] . '" />';
1407 $title = $this->current_handler['name'];
1408 echo '<h2>' . $icon . '&nbsp;' . $title . '</h2>';
1409 echo '<p style="margin-top: -10px;margin-left: 6px;">' . $this->current_handler['help'] . '</p>';
1410 $form = new Form();
1411 add_settings_field(
1412 'decalog_logger_misc_name',
1413 __( 'Name', 'decalog' ),
1414 [ $form, 'echo_field_input_text' ],
1415 'decalog_logger_misc_section',
1416 'decalog_logger_misc_section',
1417 [
1418 'id' => 'decalog_logger_misc_name',
1419 'value' => $this->current_logger['name'],
1420 'description' => decalog_esc_html__( 'Used only in admin dashboard.', 'decalog' ),
1421 'full_width' => false,
1422 'placeholder' => '',
1423 'enabled' => true,
1424 ]
1425 );
1426 register_setting( 'decalog_logger_misc_section', 'decalog_logger_misc_name' );
1427 if ( in_array( $this->current_handler['class'], [ 'alerting', 'logging', 'debugging', 'analytics' ], true ) ) {
1428 add_settings_field(
1429 'decalog_logger_misc_level',
1430 __( 'Minimal level', 'decalog' ),
1431 [ $form, 'echo_field_select' ],
1432 'decalog_logger_misc_section',
1433 'decalog_logger_misc_section',
1434 [
1435 'list' => Log::get_levels( $this->current_handler['minimal'], true ),
1436 'id' => 'decalog_logger_misc_level',
1437 'value' => $this->current_logger['level'],
1438 'description' => decalog_esc_html__( 'Minimal reported level. May be overridden by the "respect WP_DEBUG directive" option.', 'decalog' ),
1439 'full_width' => false,
1440 'enabled' => true,
1441 ]
1442 );
1443 register_setting( 'decalog_logger_misc_section', 'decalog_logger_misc_level' );
1444 }
1445 }
1446
1447 /**
1448 * Callback for logger delete section.
1449 *
1450 * @since 1.0.0
1451 */
1452 public function logger_delete_section_callback() {
1453 $icon = '<img style="vertical-align:middle;width:34px;margin-top: -2px;padding-right:6px;" src="' . $this->current_handler['icon'] . '" />';
1454 $title = $this->current_handler['name'];
1455 echo '<h2>' . $icon . '&nbsp;' . $title . '</h2>';
1456 echo '<p style="margin-top: -10px;margin-left: 6px;">' . $this->current_handler['help'] . '</p>';
1457 $form = new Form();
1458 add_settings_field(
1459 'decalog_logger_delete_name',
1460 __( 'Name', 'decalog' ),
1461 [ $form, 'echo_field_input_text' ],
1462 'decalog_logger_delete_section',
1463 'decalog_logger_delete_section',
1464 [
1465 'id' => 'decalog_logger_delete_name',
1466 'value' => $this->current_logger['name'],
1467 'description' => null,
1468 'full_width' => false,
1469 'placeholder' => '',
1470 'enabled' => false,
1471 ]
1472 );
1473 register_setting( 'decalog_logger_delete_section', 'decalog_logger_delete_name' );
1474 if ( in_array( $this->current_handler['class'], [ 'alerting', 'logging', 'debugging', 'analytics' ], true ) ) {
1475 add_settings_field(
1476 'decalog_logger_delete_level',
1477 __( 'Minimal level', 'decalog' ),
1478 [ $form, 'echo_field_select' ],
1479 'decalog_logger_delete_section',
1480 'decalog_logger_delete_section',
1481 [
1482 'list' => Log::get_levels( $this->current_handler['minimal'] ),
1483 'id' => 'decalog_logger_delete_level',
1484 'value' => $this->current_logger['level'],
1485 'description' => null,
1486 'full_width' => false,
1487 'enabled' => false,
1488 ]
1489 );
1490 register_setting( 'decalog_logger_delete_section', 'decalog_logger_delete_level' );
1491 }
1492 }
1493
1494 /**
1495 * Callback for logger specific section.
1496 *
1497 * @since 1.0.0
1498 */
1499 public function logger_specific_section_callback() {
1500 $form = new Form();
1501 if ( 'ErrorLogHandler' === $this->current_logger['handler'] ) {
1502 add_settings_field(
1503 'decalog_logger_specific_dummy',
1504 __( 'Log file', 'decalog' ),
1505 [ $form, 'echo_field_input_text' ],
1506 'decalog_logger_specific_section',
1507 'decalog_logger_specific_section',
1508 [
1509 'id' => 'decalog_logger_specific_dummy',
1510 'value' => ini_get( 'error_log' ),
1511 'description' => decalog_esc_html__( 'Value set in php.ini file.', 'decalog' ),
1512 'full_width' => false,
1513 'placeholder' => '',
1514 'enabled' => false,
1515 ]
1516 );
1517 register_setting( 'decalog_logger_specific_section', 'decalog_logger_specific_dummy' );
1518 }
1519 foreach ( $this->current_handler['configuration'] as $key => $configuration ) {
1520 if ( ! $configuration['show'] ) {
1521 continue;
1522 }
1523 $id = 'decalog_logger_details_' . strtolower( $key );
1524 $args = [
1525 'id' => $id,
1526 'text' => decalog_esc_html__( 'Enabled', 'decalog' ),
1527 'checked' => (bool) $this->current_logger['configuration'][ $key ],
1528 'value' => $this->current_logger['configuration'][ $key ],
1529 'description' => $configuration['help'],
1530 'full_width' => false,
1531 'enabled' => $configuration['control']['enabled'],
1532 'placeholder' => $configuration['default'],
1533 'list' => ( array_key_exists( 'list', $configuration['control'] ) ? $configuration['control']['list'] : [] ),
1534 ];
1535 foreach ( $configuration['control'] as $index => $control ) {
1536 if ( 'type' !== $index && 'cast' !== $index ) {
1537 if ( 0 === strpos( $key, 'constant-' ) && ! $this->creation_mode && 'enabled' === $index ) {
1538 $control = false;
1539 }
1540 $args[ $index ] = $control;
1541 }
1542 }
1543 add_settings_field(
1544 $id,
1545 $configuration['name'],
1546 [ $form, 'echo_' . $configuration['control']['type'] ],
1547 'decalog_logger_specific_section',
1548 'decalog_logger_specific_section',
1549 $args
1550 );
1551 register_setting( 'decalog_logger_specific_section', $id );
1552 }
1553 }
1554
1555 /**
1556 * Callback for logger privacy section.
1557 *
1558 * @since 1.0.0
1559 */
1560 public function logger_privacy_section_callback() {
1561 $form = new Form();
1562 add_settings_field(
1563 'decalog_logger_privacy_ip',
1564 __( 'Remote IPs', 'decalog' ),
1565 [ $form, 'echo_field_checkbox' ],
1566 'decalog_logger_privacy_section',
1567 'decalog_logger_privacy_section',
1568 [
1569 'text' => decalog_esc_html__( 'Obfuscation', 'decalog' ),
1570 'id' => 'decalog_logger_privacy_ip',
1571 'checked' => $this->current_logger['privacy']['obfuscation'],
1572 'description' => decalog_esc_html__( 'If checked, logged details will contain hashes instead of real IPs.', 'decalog' ) . '<br/>' . decalog_esc_html__( 'Note: it concerns everything except events messages.', 'decalog' ),
1573 'full_width' => false,
1574 'enabled' => true,
1575 ]
1576 );
1577 register_setting( 'decalog_logger_privacy_section', 'decalog_logger_privacy_ip' );
1578 add_settings_field(
1579 'decalog_logger_privacy_name',
1580 __( 'Users', 'decalog' ),
1581 [ $form, 'echo_field_checkbox' ],
1582 'decalog_logger_privacy_section',
1583 'decalog_logger_privacy_section',
1584 [
1585 'text' => decalog_esc_html__( 'Pseudonymisation', 'decalog' ),
1586 'id' => 'decalog_logger_privacy_name',
1587 'checked' => $this->current_logger['privacy']['pseudonymization'],
1588 'description' => decalog_esc_html__( 'If checked, logged details will contain hashes instead of user IDs & names.', 'decalog' ) . '<br/>' . decalog_esc_html__( 'Note: it concerns everything except events messages.', 'decalog' ),
1589 'full_width' => false,
1590 'enabled' => true,
1591 ]
1592 );
1593 register_setting( 'decalog_logger_privacy_section', 'decalog_logger_privacy_name' );
1594 }
1595
1596 /**
1597 * Callback for logger privacy section.
1598 *
1599 * @since 1.0.0
1600 */
1601 public function logger_details_section_callback() {
1602 $form = new Form();
1603 $id = 'decalog_logger_details_dummy';
1604 add_settings_field(
1605 $id,
1606 __( 'Standard', 'decalog' ),
1607 [ $form, 'echo_field_checkbox' ],
1608 'decalog_logger_details_section',
1609 'decalog_logger_details_section',
1610 [
1611 'text' => decalog_esc_html__( 'Included', 'decalog' ),
1612 'id' => $id,
1613 'checked' => true,
1614 'description' => decalog_esc_html__( 'Allows to log standard DecaLog information.', 'decalog' ),
1615 'full_width' => false,
1616 'enabled' => false,
1617 ]
1618 );
1619 register_setting( 'decalog_logger_details_section', $id );
1620 $proc = new ProcessorTypes( 'tracing' === $this->current_handler['class'] );
1621 foreach ( array_reverse( $proc->get_all() ) as $processor ) {
1622 $id = 'decalog_logger_details_' . strtolower( $processor['id'] );
1623 add_settings_field(
1624 $id,
1625 $processor['name'],
1626 [ $form, 'echo_field_checkbox' ],
1627 'decalog_logger_details_section',
1628 'decalog_logger_details_section',
1629 [
1630 'text' => decalog_esc_html__( 'Included', 'decalog' ),
1631 'id' => $id,
1632 'checked' => in_array( $processor['id'], $this->current_logger['processors'], true ),
1633 'description' => $processor['help'],
1634 'full_width' => false,
1635 'enabled' => ! in_array( $processor['id'], array_merge( $this->current_handler['processors']['excluded'] ?? [], $this->current_handler['processors']['included'] ?? [] ), true ),
1636 ]
1637 );
1638 register_setting( 'decalog_logger_details_section', $id );
1639 }
1640 }
1641
1642 }
1643