PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.2 6.2.1 6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 All 155 releases
← All changes | modules/logs/classes/class-log-admin.php +177 -107 5.1 → 6.2.2 View file →
@@ -9,10 +9,12 @@
9 9 namespace MainWP\Dashboard\Module\Log;
10 10
11 11 use MainWP\Dashboard\MainWP_Logger;
12 12 use MainWP\Dashboard\MainWP_Post_Handler;
13 +use MainWP\Dashboard\MainWP_Utility;
14 +use MainWP\Dashboard\MainWP_DB;
15 +use MainWP\Dashboard\MainWP_Connect;
13 16
14 -
15 17 defined( 'ABSPATH' ) || exit;
16 18
17 19 use DateTime;
18 20 use DateTimeZone;
@@ -59,9 +61,9 @@
59 61 * @param Log_Manager $manager Instance of manager object.
60 62 */
61 63 public function __construct( $manager ) {
62 64 $this->manager = $manager;
63 - add_filter( 'mainwp_getsubpages_settings', array( $this, 'add_subpage_menu_logs' ) );
65 + add_action( 'init', array( &$this, 'init' ) );
64 66 // Load admin scripts and styles.
65 67 add_action(
66 68 'admin_enqueue_scripts',
67 69 array(
@@ -71,65 +73,46 @@
71 73 9
72 74 );
73 75
74 76 // Auto purge setup.
75 - add_action( 'wp_loaded', array( $this, 'hook_purge_scheduled_action' ) );
76 77 add_action( 'admin_init', array( $this, 'admin_init' ) );
78 + $log_page = Log_Insights_Page::instance();
79 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_delete_records', array( $this, 'ajax_delete_records' ) );
80 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_compact_records', array( $this, 'ajax_compact_records' ) );
81 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_clean_up_child_logs', array( $this, 'ajax_clean_up_child_logs' ) );
82 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_manage_events_display_rows', array( Log_Manage_Insights_Events_Page::instance(), 'ajax_manage_events_display_rows' ) );
83 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_widget_insights_display_rows', array( $log_page, 'ajax_events_display_rows' ) );
84 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_widget_events_overview_display_rows', array( $log_page, 'ajax_events_overview_display_rows' ) );
85 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_update_dismissed_db', array( $log_page, 'ajax_archive_dismissed_db' ) );
86 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_cancel_update_dismissed_db', array( $log_page, 'ajax_cancel_update_dismissed_db' ) );
77 87 }
78 88
79 89 /**
80 - * Handle admin_init action.
90 + * Initiate Hooks
91 + *
92 + * Initiates hooks for the Dashboard insights module.
81 93 */
82 - public function admin_init() {
83 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_display_rows', array( $this, 'ajax_display_rows' ) );
84 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_delete_records', array( $this, 'ajax_delete_records' ) );
85 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_compact_records', array( $this, 'ajax_compact_records' ) );
86 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_events_display_rows', array( Log_Insights_Page::instance(), 'ajax_events_display_rows' ) );
87 - Log_Events_Filter_Segment::get_instance()->admin_init();
94 + public function init() {
95 + add_action( 'mainwp_help_sidebar_content', array( $this, 'mainwp_help_content' ) );
88 96 }
89 97
90 -
91 98 /**
92 - * Init sub menu logs.
93 - *
94 - * @param array $subpages sub pages.
95 - *
96 - * @action init
99 + * Handle admin_init action.
97 100 */
98 - public function add_subpage_menu_logs( $subpages = array() ) {
99 - $subpages[] = array(
100 - 'title' => esc_html__( 'Dashboard Insights', 'mainwp' ),
101 - 'slug' => 'DashboardInsights',
102 - 'callback' => array( $this, 'render_list_table' ),
103 - 'class' => 'mainwp-logs-menu',
104 - );
105 - return $subpages;
101 + public function admin_init() {
102 + Log_Events_Filter_Segment::get_instance()->admin_init();
103 + $this->handle_post_archive_data();
106 104 }
107 105
108 106 /**
109 - * Render main page
107 + * Handle archive data action.
110 108 */
111 - public function render_list_table() {
112 - $this->list_table = new Log_List_Table( $this->manager );
113 - /** This action is documented in ../pages/page-mainwp-manage-sites.php */
114 - do_action( 'mainwp_pageheader_settings', 'DashboardInsights' );
115 - ?>
116 - <div id="mainwp-manage-sites-content" class="ui segment">
117 - <div class="ui form">
118 - <h3 class="ui dividing header"><?php esc_html_e( 'Dashboard Insights', 'mainwp' ); ?></h3>
119 - <h4 class="ui header"><?php printf( esc_html__( 'Total logs size: %1$s (MB)', 'mainwp' ), esc_html( $this->get_db_size() ) ); ?></h4>
120 - <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
121 - <form method="post" class="mainwp-table-container">
122 - <?php
123 - wp_nonce_field( 'mainwp-admin-nonce' );
124 - $this->list_table->display();
125 - ?>
126 - </form>
127 - </div>
128 - </div>
129 - <?php
130 - /** This action is documented in ../pages/page-mainwp-manage-sites.php */
131 - do_action( 'mainwp_pagefooter_settings', 'DashboardInsights' );
109 + public function handle_post_archive_data() {
110 + if ( isset( $_GET['clearArchivedSitesChangesData'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'clear_archived_sites_changes' ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
111 + Log_DB_Archive::instance()->truncate_archive_tables();
112 + wp_safe_redirect( esc_url( admin_url( 'admin.php?page=MainWPTools' ) ) );
113 + die();
114 + }
132 115 }
133 116
134 117 /**
135 118 * Enqueue scripts/styles for admin screen
@@ -140,9 +123,9 @@
140 123 *
141 124 * @return void
142 125 */
143 126 public function admin_enqueue_scripts( $hook ) {
144 - $script_screens = array( 'mainwp_page_InsightsOverview', 'mainwp_page_SettingsDashboardInsights', 'mainwp_page_SettingsInsights' );
127 + $script_screens = array( 'mainwp_page_InsightsOverview', 'mainwp_page_SettingsDashboardInsights', 'mainwp_page_SettingsInsights', 'mainwp_page_InsightsManage' );
145 128 wp_enqueue_style( 'mainwp-module-log-admin', $this->manager->locations['url'] . 'ui/css/admin.css', array(), $this->manager->get_version() );
146 129
147 130 if ( in_array( $hook, $script_screens, true ) ) {
148 131 wp_enqueue_script(
@@ -178,21 +161,33 @@
178 161 );
179 162 }
180 163 }
181 164
182 -
183 165 /**
184 - * Method ajax_display_rows()
166 + * Method hook_schedules_cron_listing().
185 167 *
186 - * Display table rows, optimize for shared hosting or big networks.
168 + * @param array $cron_list Cron info.
169 + * @return array Cron info.
187 170 */
188 - public function ajax_display_rows() {
189 - MainWP_Post_Handler::instance()->check_security( 'mainwp_module_log_display_rows' );
190 - $this->load_list_table();
191 - $this->list_table->prepare_items();
192 - $output = $this->list_table->ajax_get_datatable_rows();
193 - MainWP_Logger::instance()->log_execution_time( 'ajax_display_rows()' );
194 - wp_send_json( $output );
171 + public function hook_schedules_cron_listing( $cron_list = array() ) {
172 +
173 + if ( ! $this->manager->is_enabled_auto_archive_logs() ) {
174 + return $cron_list;
175 + }
176 +
177 + if ( ! is_array( $cron_list ) ) {
178 + $cron_list = array();
179 + }
180 + $start_lasttime = get_option( 'mainwp_module_log_last_time_auto_archive_logs', 0 );
181 + $start_nexttime = wp_next_scheduled( 'mainwp_module_log_cron_job_auto_archive' );
182 + $cron_list['mainwp_module_log_cron_job_auto_archive'] = array(
183 + 'title' => __( 'Auto archive Network Activity logs', 'mainwp' ),
184 + 'action' => 'mainwp_module_log_cron_job_auto_archive',
185 + 'frequency' => __( 'Once daily', 'mainwp' ),
186 + 'last_run' => empty( $start_lasttime ) ? 'N/A' : MainWP_Utility::format_timestamp( $start_lasttime ),
187 + 'next_run' => empty( $start_nexttime ) ? 'N/A' : MainWP_Utility::format_timestamp( $start_nexttime ),
188 + );
189 + return $cron_list;
195 190 }
196 191
197 192 /**
198 193 * Handle ajax delete logs records.
@@ -206,9 +201,9 @@
206 201 $start_time = ! empty( $start_date ) ? strtotime( $start_date . ' 00:00:00' ) : '';
207 202 $end_time = ! empty( $end_date ) ? strtotime( $end_date . ' 23:59:59' ) : '';
208 203
209 204 if ( ! is_numeric( $start_time ) || ! is_numeric( $end_time ) || $start_time > $end_time ) {
210 - die( wp_json_encode( array( 'error' => esc_html__( 'Invalid Start date or end date. Please try again.' ) ) ) );
205 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid Start date or end date. Please try again.', 'mainwp' ) ) ) );
211 206 }
212 207
213 208 $this->manager->db->create_compact_and_erase_records( $start_time, $end_time );
214 209
@@ -224,9 +219,9 @@
224 219
225 220 $year = isset( $_POST['year'] ) ? intval( $_POST['year'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
226 221
227 222 if ( $year < 2022 ) {
228 - die( wp_json_encode( array( 'error' => esc_html__( 'Invalid selected year. Please try again.' ) ) ) );
223 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid selected year. Please try again.', 'mainwp' ) ) ) );
229 224 }
230 225
231 226 $aday = $year . '-12-15'; // a day in last month.
232 227
@@ -238,20 +233,49 @@
238 233 wp_send_json( array( 'result' => 'SUCCESS' ) );
239 234 }
240 235
241 236 /**
242 - * Method load_sites_table()
243 - *
244 - * Load sites table.
237 + * Handle ajax clean up child logs.
245 238 */
246 - public function load_list_table() {
247 - $this->list_table = new Log_List_Table( $this->manager );
239 + public function ajax_clean_up_child_logs() {
240 + MainWP_Post_Handler::instance()->check_security( 'mainwp_module_log_clean_up_child_logs' );
241 +
242 + $siteid = isset( $_POST['siteid'] ) ? intval( $_POST['siteid'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
243 + $website = false;
244 +
245 + if ( $siteid > 0 ) {
246 + $website = MainWP_DB::instance()->get_website_by_id( $siteid );
247 + }
248 +
249 + if ( empty( $siteid ) || empty( $website ) ) {
250 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid site id or website not found. Please try again.', 'mainwp' ) ) ) );
251 + }
252 +
253 + $information = MainWP_Connect::fetch_url_authed( $website, 'clean_up_child_logs' );
254 +
255 + if ( ! is_array( $information ) ) {
256 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid response from child site. Please try again.', 'mainwp' ) ) ) );
257 + }
258 +
259 + $rsult = array();
260 + if ( isset( $information['success'] ) && 1 === intval( $information['success'] ) ) {
261 + $rsult['success'] = 1;
262 +
263 + if ( isset( $information['dbsize_activitylogs'] ) ) {
264 + MainWP_DB::instance()->update_website_option( $website, 'dbsize_activitylogs', $information['dbsize_activitylogs'] );
265 + }
266 + } elseif ( isset( $information['error'] ) ) {
267 + $rsult['error'] = $information['error'];
268 + }
269 +
270 + wp_send_json( $rsult );
248 271 }
249 272
250 -
251 273 /**
252 274 * Schedules a purge of records.
253 275 *
276 + * @compatible
277 + *
254 278 * @return void
255 279 */
256 280 public function hook_purge_scheduled_action() { //phpcs:ignore -- NOSONAR - complex.
257 281 $enable_schedule = is_array( $this->manager->settings->options ) && ! empty( $this->manager->settings->options['enabled'] ) && ! empty( $this->manager->settings->options['auto_purge'] ) ? true : false;
@@ -257,13 +281,11 @@
257 281 $enable_schedule = is_array( $this->manager->settings->options ) && ! empty( $this->manager->settings->options['enabled'] ) && ! empty( $this->manager->settings->options['auto_purge'] ) ? true : false;
258 282 if ( $enable_schedule ) {
259 283 $last_purge = get_option( 'mainwp_module_log_last_time_auto_purge_logs' );
260 284 $next_purge = get_option( 'mainwp_module_log_next_time_auto_purge_logs' );
261 - $days = false;
285 + $days = 100;
262 286 if ( is_array( $this->manager->settings->options ) && isset( $this->manager->settings->options['records_ttl'] ) ) {
263 287 $days = intval( $this->manager->settings->options['records_ttl'] );
264 - } else {
265 - $days = 100;
266 288 }
267 289
268 290 if ( defined( 'MAINWP_MODULE_LOG_KEEP_RECORDS_TTL' ) && is_numeric( MAINWP_MODULE_LOG_KEEP_RECORDS_TTL ) && MAINWP_MODULE_LOG_KEEP_RECORDS_TTL > 0 ) {
269 291 $days = MAINWP_MODULE_LOG_KEEP_RECORDS_TTL;
@@ -290,37 +312,65 @@
290 312 }
291 313
292 314
293 315 /**
294 - * Get db size.
316 + * Render logs db large size notice.
295 317 *
296 - * @return string Return current db size.
318 + * @param int $limit DB size limit in MByte, default 300 MB.
319 + * @param string $which The page slug where the notice is displayed.
297 320 */
298 - public function get_db_size() {
299 - $size = get_transient( 'mainwp_module_log_transient_db_logs_size' );
300 - if ( false !== $size ) {
301 - return $size;
321 + public function render_logs_db_notice( $limit = 300, $which = '' ) {
322 + if ( empty( $limit ) ) {
323 + $limit = 300; // MB.
302 324 }
325 + if ( MainWP_Utility::show_mainwp_message( 'notice', 'logs-db-size-large' ) ) {
326 + $size = Log_DB_Helper::instance()->get_db_size();
327 + if ( $size >= $limit ) {
328 + ?>
329 + <div class="ui yellow message" <?php echo 'overview' === $which || 'client_overview' === $which ? 'style="margin: 1em;"' : ''; ?>>
330 + <i class="close icon mainwp-notice-dismiss" notice-id="logs-db-size-large"></i>
331 + <?php
332 + /* translators: 1: Database size in MB, 2: Opening anchor tag, 3: Closing anchor tag */
333 + printf( esc_html__( 'Your Network Activity logs are using a lot of database space (%1$s MB). Go to %2$sMainWP > Settings > Network Activity Settings%3$s and enable Automatically archive logs, then set a Data retention period to keep the table size under control.', 'mainwp' ), esc_html( $size ), '<a href="admin.php?page=SettingsInsights#field-log-enable-auto-archive">', '</a>' ); // NOSONAR - noopener - open safe.
334 + ?>
335 + </div>
336 + <?php
337 + }
338 + }
339 + }
303 340
304 - global $wpdb;
305 - $sql = $wpdb->prepare(
306 - 'SELECT
307 - ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2)
308 - FROM INFORMATION_SCHEMA.TABLES
309 - WHERE
310 - TABLE_SCHEMA = %s
311 - AND table_name = %s
312 - OR table_name = %s',
313 - $wpdb->dbname,
314 - $wpdb->mainwp_tbl_logs,
315 - $wpdb->mainwp_tbl_logs_meta
316 - );
317 -
318 - $dbsize_mb = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery -- prepared SQL.
319 -
320 - set_transient( 'mainwp_module_log_transient_db_logs_size', $dbsize_mb, 15 * MINUTE_IN_SECONDS );
321 -
322 - return $dbsize_mb;
341 + /**
342 + * Render logs db update notice.
343 + */
344 + public function render_update_db_notice() {
345 + $status = '';
346 + $dbver = Log_Install::instance()->get_current_logs_db_ver();
347 + if ( version_compare( $dbver, '1.0.1.26', '=' ) && ! get_option( 'mainwp_module_logs_updates_dismissed_db_cancelled' ) ) { // NOSONAR - no ip,checks ver <= 22 only.
348 + $status = get_option( 'mainwp_module_logs_updates_dismissed_db_process_status', '' );
349 + }
350 + ?>
351 + <div class="ui green message" id="module-log-update-dissmised-logs-running" style="display:none;"></div>
352 + <?php
353 + if ( 'require_update' === $status && MainWP_Utility::show_mainwp_message( 'notice', 'logs-db-update-required' ) ) {
354 + delete_option( 'mainwp_module_logs_updates_dismissed_db_cancelled' ); // To ensure it does not retrieve old saved values.
355 + ?>
356 + <div class="ui yellow message">
357 + <i class="close icon mainwp-notice-dismiss" notice-id="logs-db-update-required"></i>
358 + <?php
359 + /* translators: 1: Opening anchor tag, 2: Closing anchor tag */
360 + printf( esc_html__( 'Your \'Network Activity\' database needs to be updated. Click %1$shere%2$s to start the update.', 'mainwp' ), '<a href="javascript:void(0);" id="module-update-logs-db-requirement">', '</a>' );
361 + ?>
362 + </div>
363 + <?php
364 + } elseif ( 'running' === $status ) {
365 + ?>
366 + <script type="text/javascript">
367 + jQuery(function ($) {
368 + mainwp_module_logs_start_update_dismissed_db();
369 + });
370 + </script>
371 + <?php
372 + }
323 373 }
324 374
325 375 /**
326 376 * Get WP users.
@@ -327,21 +377,41 @@
327 377 *
328 378 * @return array Array of users.
329 379 */
330 380 public function get_all_users() {
331 - $list_users = array();
332 - $all_users = get_users();
333 - if ( is_array( $all_users ) ) {
334 - foreach ( $all_users as $user ) {
335 - if ( empty( $user->ID ) ) {
336 - continue;
337 - }
338 - $fields = array();
339 - $fields['id'] = $user->ID;
340 - $fields['login'] = $user->user_login;
341 - $fields['nicename'] = $user->user_nicename;
342 - $list_users[] = $fields;
343 - }
381 + $users_sites = Log_DB_Helper::instance()->get_logs_users();
382 + return ! empty( $users_sites ) ? $users_sites : array();
383 + }
384 +
385 + /**
386 + * Method mainwp_help_content()
387 + *
388 + * Creates the MainWP Help Documentation List for the help component in the sidebar.
389 + */
390 + public static function mainwp_help_content() {
391 + $allow_pages = array( 'InsightsOverview' );
392 + if ( isset( $_GET['page'] ) && in_array( $_GET['page'], $allow_pages, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
393 + ?>
394 + <p><?php esc_html_e( 'If you need help with the Dashboard Insights module, please review following help documents', 'mainwp' ); ?></p>
395 + <div class="ui list">
396 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/add-ons/security/dashboard-insights-extension#dashboard-insights" target="_blank">Dashboard Insights</a></div> <?php // NOSONAR -- compatible with help. ?>
397 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/add-ons/security/dashboard-insights-extension#comprehensive-filtering-options" target="_blank">Filtering Options</a></div> <?php // NOSONAR -- compatible with help. ?>
398 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/add-ons/security/dashboard-insights-extension#export-the-data-and-charts-from-an-individual-widget" target="_blank">Export Insights Data</a></div> <?php // NOSONAR -- compatible with help. ?>
399 + <?php
400 + /**
401 + * Action: mainwp_module_dashboard_insights_help_item
402 + *
403 + * Fires at the bottom of the help articles list in the Help sidebar on the Insights page.
404 + *
405 + * Suggested HTML markup:
406 + *
407 + * <div class="item"><a href="Your custom URL">Your custom text</a></div>
408 + *
409 + * @since 5.2
410 + */
411 + do_action( 'mainwp_module_dashboard_insights_help_item' );
412 + ?>
413 + </div>
414 + <?php
344 415 }
345 - return $list_users;
346 416 }
347 417 }