PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.0.12
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.0.12
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 5.2.2 5.3 All 153 releases
mainwp / modules / logs / classes / class-log-admin.php

class-log-admin.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.0.12, at modules/logs/classes/class-log-admin.php

417 lines 17.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Centralized manager for WordPress backend functionality.
4 *
5 * @package MainWP\Dashboard
6 * @version 4.5.1
7 */
8
9 namespace MainWP\Dashboard\Module\Log;
10
11 use MainWP\Dashboard\MainWP_Logger;
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;
16
17 defined( 'ABSPATH' ) || exit;
18
19 use DateTime;
20 use DateTimeZone;
21 use DateInterval;
22 use WP_CLI;
23
24 /**
25 * Class - Log_Admin
26 */
27 class Log_Admin {
28
29 /**
30 * Holds Instance of manager object
31 *
32 * @var Log_manager
33 */
34 public $manager;
35
36
37 /**
38 * Menu page screen id
39 *
40 * @var string
41 */
42 public $screen_id = array();
43
44 /**
45 * List table object
46 *
47 * @var List_Table
48 */
49 public $list_table = null;
50
51 /**
52 * Parent page of the records and settings pages
53 *
54 * @var string
55 */
56 public $admin_parent_page = 'admin.php';
57
58 /**
59 * Class constructor.
60 *
61 * @param Log_Manager $manager Instance of manager object.
62 */
63 public function __construct( $manager ) {
64 $this->manager = $manager;
65 add_action( 'init', array( &$this, 'init' ) );
66 // Load admin scripts and styles.
67 add_action(
68 'admin_enqueue_scripts',
69 array(
70 $this,
71 'admin_enqueue_scripts',
72 ),
73 9
74 );
75
76 // Auto purge setup.
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' ) );
87 }
88
89 /**
90 * Initiate Hooks
91 *
92 * Initiates hooks for the Dashboard insights module.
93 */
94 public function init() {
95 add_action( 'mainwp_help_sidebar_content', array( $this, 'mainwp_help_content' ) );
96 }
97
98 /**
99 * Handle admin_init action.
100 */
101 public function admin_init() {
102 Log_Events_Filter_Segment::get_instance()->admin_init();
103 $this->handle_post_archive_data();
104 }
105
106 /**
107 * Handle archive data action.
108 */
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 }
115 }
116
117 /**
118 * Enqueue scripts/styles for admin screen
119 *
120 * @action admin_enqueue_scripts
121 *
122 * @param string $hook Current hook.
123 *
124 * @return void
125 */
126 public function admin_enqueue_scripts( $hook ) {
127 $script_screens = array( 'mainwp_page_InsightsOverview', 'mainwp_page_SettingsDashboardInsights', 'mainwp_page_SettingsInsights', 'mainwp_page_InsightsManage' );
128 wp_enqueue_style( 'mainwp-module-log-admin', $this->manager->locations['url'] . 'ui/css/admin.css', array(), $this->manager->get_version() );
129
130 if ( in_array( $hook, $script_screens, true ) ) {
131 wp_enqueue_script(
132 'mainwp-module-log-admin',
133 $this->manager->locations['url'] . 'ui/js/admin.js',
134 array(
135 'jquery',
136 'mainwp',
137 ),
138 $this->manager->get_version(),
139 false
140 );
141
142 if ( in_array( $hook, array( 'mainwp_page_InsightsOverview' ), true ) ) {
143 add_filter(
144 'mainwp_admin_enqueue_scripts',
145 function ( $scripts ) {
146 if ( is_array( $scripts ) ) {
147 $scripts['apexcharts'] = true;
148 }
149 return $scripts;
150 }
151 );
152 }
153
154 wp_localize_script(
155 'mainwp-module-log-admin',
156 'mainwpModuleLog',
157 array(
158 'i18n' => array(),
159 'gmt_offset' => get_option( 'gmt_offset' ),
160 )
161 );
162 }
163 }
164
165 /**
166 * Method hook_schedules_cron_listing().
167 *
168 * @param array $cron_list Cron info.
169 * @return array Cron info.
170 */
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;
190 }
191
192 /**
193 * Handle ajax delete logs records.
194 */
195 public function ajax_delete_records() {
196 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_log_delete_records' );
197
198 $start_date = isset( $_POST['startdate'] ) ? sanitize_text_field( wp_unslash( $_POST['startdate'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
199 $end_date = isset( $_POST['enddate'] ) ? sanitize_text_field( wp_unslash( $_POST['enddate'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
200
201 $start_time = ! empty( $start_date ) ? strtotime( $start_date . ' 00:00:00' ) : '';
202 $end_time = ! empty( $end_date ) ? strtotime( $end_date . ' 23:59:59' ) : '';
203
204 if ( ! is_numeric( $start_time ) || ! is_numeric( $end_time ) || $start_time > $end_time ) {
205 die( wp_json_encode( array( 'error' => esc_html__( 'Invalid Start date or end date. Please try again.', 'mainwp' ) ) ) );
206 }
207
208 $this->manager->db->create_compact_and_erase_records( $start_time, $end_time );
209
210 wp_send_json( array( 'result' => 'SUCCESS' ) );
211 }
212
213
214 /**
215 * Handle ajax compact logs records.
216 */
217 public function ajax_compact_records() {
218 MainWP_Post_Handler::instance()->check_security( 'mainwp_module_log_compact_records' );
219
220 $year = isset( $_POST['year'] ) ? intval( $_POST['year'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
221
222 if ( $year < 2022 ) {
223 die( wp_json_encode( array( 'error' => esc_html__( 'Invalid selected year. Please try again.', 'mainwp' ) ) ) );
224 }
225
226 $aday = $year . '-12-15'; // a day in last month.
227
228 $start_time = strtotime( $year . '-1-1 00:00:00' );
229 $end_time = strtotime( gmdate( 'Y-m-t', strtotime( $aday ) ) . ' 23:59:59' );
230
231 $this->manager->db->create_compact_and_erase_records( $start_time, $end_time );
232
233 wp_send_json( array( 'result' => 'SUCCESS' ) );
234 }
235
236 /**
237 * Handle ajax clean up child logs.
238 */
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 );
271 }
272
273 /**
274 * Schedules a purge of records.
275 *
276 * @compatible
277 *
278 * @return void
279 */
280 public function hook_purge_scheduled_action() { //phpcs:ignore -- NOSONAR - complex.
281 $enable_schedule = is_array( $this->manager->settings->options ) && ! empty( $this->manager->settings->options['enabled'] ) && ! empty( $this->manager->settings->options['auto_purge'] ) ? true : false;
282 if ( $enable_schedule ) {
283 $last_purge = get_option( 'mainwp_module_log_last_time_auto_purge_logs' );
284 $next_purge = get_option( 'mainwp_module_log_next_time_auto_purge_logs' );
285 $days = 100;
286 if ( is_array( $this->manager->settings->options ) && isset( $this->manager->settings->options['records_ttl'] ) ) {
287 $days = intval( $this->manager->settings->options['records_ttl'] );
288 }
289
290 if ( defined( 'MAINWP_MODULE_LOG_KEEP_RECORDS_TTL' ) && is_numeric( MAINWP_MODULE_LOG_KEEP_RECORDS_TTL ) && MAINWP_MODULE_LOG_KEEP_RECORDS_TTL > 0 ) {
291 $days = MAINWP_MODULE_LOG_KEEP_RECORDS_TTL;
292 }
293
294 if ( $days ) {
295 $time = time();
296 $next_time_purge = false;
297 if ( false === $last_purge && false === $next_purge ) {
298 $next_time_purge = $time + $days * DAY_IN_SECONDS;
299 } elseif ( ! empty( $next_purge ) && $time > (int) $next_purge ) {
300 do_action( 'mainwp_log_action', 'module log :: purge logs schedule start.', MainWP_Logger::LOGS_AUTO_PURGE_LOG_PRIORITY );
301 $end_time = $time - $days * DAY_IN_SECONDS;
302 $start_time = ! empty( $last_purge ) ? $last_purge : $end_time - $days * DAY_IN_SECONDS;
303 $this->manager->db->create_compact_and_erase_records( $start_time, $end_time );
304 update_option( 'mainwp_module_log_last_time_auto_purge_logs', $time );
305 $next_time_purge = $time + $days * DAY_IN_SECONDS;
306 }
307 if ( $next_time_purge ) {
308 update_option( 'mainwp_module_log_next_time_auto_purge_logs', $next_time_purge );
309 }
310 }
311 }
312 }
313
314
315 /**
316 * Render logs db large size notice.
317 *
318 * @param int $limit DB size limit in MByte, default 300 MB.
319 */
320 public function render_logs_db_notice( $limit = 300 ) {
321 if ( empty( $limit ) ) {
322 $limit = 300; // MB.
323 }
324 if ( MainWP_Utility::show_mainwp_message( 'notice', 'logs-db-size-large' ) ) {
325 $size = Log_DB_Helper::instance()->get_db_size();
326 if ( $size >= $limit ) {
327 ?>
328 <div class="ui yellow message">
329 <i class="close icon mainwp-notice-dismiss" notice-id="logs-db-size-large"></i>
330 <?php
331 /* translators: 1: Database size in MB, 2: Opening anchor tag, 3: Closing anchor tag */
332 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=MainWPTools#mainwp-clear-archived-sites-changes-data">', '</a>' ); // NOSONAR - noopener - open safe.
333 ?>
334 </div>
335 <?php
336 }
337 }
338 }
339
340 /**
341 * Render logs db update notice.
342 */
343 public function render_update_db_notice() {
344 $status = '';
345 $dbver = Log_Install::instance()->get_current_logs_db_ver();
346 if ( version_compare( $dbver, '1.0.1.26', '=' ) && ! get_option( 'mainwp_module_logs_updates_dismissed_db_cancelled' ) ) { // NOSONAR - no ip,checks ver <= 22 only.
347 $status = get_option( 'mainwp_module_logs_updates_dismissed_db_process_status', '' );
348 }
349 ?>
350 <div class="ui green message" id="module-log-update-dissmised-logs-running" style="display:none;"></div>
351 <?php
352 if ( 'require_update' === $status && MainWP_Utility::show_mainwp_message( 'notice', 'logs-db-update-required' ) ) {
353 delete_option( 'mainwp_module_logs_updates_dismissed_db_cancelled' ); // To ensure it does not retrieve old saved values.
354 ?>
355 <div class="ui yellow message">
356 <i class="close icon mainwp-notice-dismiss" notice-id="logs-db-update-required"></i>
357 <?php
358 /* translators: 1: Opening anchor tag, 2: Closing anchor tag */
359 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>' );
360 ?>
361 </div>
362 <?php
363 } elseif ( 'running' === $status ) {
364 ?>
365 <script type="text/javascript">
366 jQuery(function ($) {
367 mainwp_module_logs_start_update_dismissed_db();
368 });
369 </script>
370 <?php
371 }
372 }
373
374 /**
375 * Get WP users.
376 *
377 * @return array Array of users.
378 */
379 public function get_all_users() {
380 $users_sites = Log_DB_Helper::instance()->get_logs_users();
381 return ! empty( $users_sites ) ? $users_sites : array();
382 }
383
384 /**
385 * Method mainwp_help_content()
386 *
387 * Creates the MainWP Help Documentation List for the help component in the sidebar.
388 */
389 public static function mainwp_help_content() {
390 $allow_pages = array( 'InsightsOverview' );
391 if ( isset( $_GET['page'] ) && in_array( $_GET['page'], $allow_pages, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
392 ?>
393 <p><?php esc_html_e( 'If you need help with the Dashboard Insights module, please review following help documents', 'mainwp' ); ?></p>
394 <div class="ui list">
395 <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. ?>
396 <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. ?>
397 <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. ?>
398 <?php
399 /**
400 * Action: mainwp_module_dashboard_insights_help_item
401 *
402 * Fires at the bottom of the help articles list in the Help sidebar on the Insights page.
403 *
404 * Suggested HTML markup:
405 *
406 * <div class="item"><a href="Your custom URL">Your custom text</a></div>
407 *
408 * @since 5.2
409 */
410 do_action( 'mainwp_module_dashboard_insights_help_item' );
411 ?>
412 </div>
413 <?php
414 }
415 }
416 }
417