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.3 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 All 156 releases
← All changes | modules/logs/classes/class-log-events-list-table.php +1437 -667 5.0 → 6.2.2 View file →
@@ -7,773 +7,1543 @@
7 7 */
8 8
9 9 namespace MainWP\Dashboard\Module\Log;
10 10
11 -use MainWP\Dashboard\MainWP_DB;
12 11 use MainWP\Dashboard\MainWP_Utility;
12 +use MainWP\Dashboard\MainWP_UI;
13 +use MainWP\Dashboard\MainWP_Connect;
14 +use MainWP\Dashboard\MainWP_Manage_Sites;
15 +use MainWP\Dashboard\MainWP_Updates_Helper;
16 +use MainWP\Dashboard\MainWP_Site_Open;
17 +
18 +// Exit if accessed directly.
19 +if ( ! defined( 'ABSPATH' ) ) {
20 + exit;
21 +}
22 +
13 23 /**
14 24 * Class Log_Events_List_Table
15 25 *
16 26 * @package MainWP\Dashboard
17 27 */
18 -class Log_Events_List_Table {
28 +class Log_Events_List_Table { //phpcs:ignore -- NOSONAR - complex.
19 29
20 - /**
21 - * Holds instance of manager object
22 - *
23 - * @var Log_Manager
24 - */
25 - public $manager;
30 + /**
31 + * Holds instance of manager object
32 + *
33 + * @var Log_Manager
34 + */
35 + public $manager;
26 36
27 37
28 - /**
29 - * Public variable to hold Items information.
30 - *
31 - * @var array
32 - */
33 - public $items;
38 + /**
39 + * Public variable to hold Items information.
40 + *
41 + * @var array
42 + */
43 + public $items;
34 44
35 - /**
36 - * Public variable to hold Previous Items information.
37 - *
38 - * @var array
39 - */
40 - public $items_prev;
41 45
46 + /**
47 + * Public variable to hold Items information.
48 + *
49 + * @var array
50 + */
51 + public $sites_opts = array();
42 52
43 - /**
44 - * Public variable to hold total items number.
45 - *
46 - * @var integer
47 - */
48 - public $total_items;
53 + /**
54 + * Public variable to hold Previous Items information.
55 + *
56 + * @var array
57 + */
58 + public $items_prev;
49 59
50 - /**
51 - * Protected variable to hold columns headers
52 - *
53 - * @var array
54 - */
55 - protected $column_headers;
56 60
57 - /**
58 - * Class constructor.
59 - *
60 - * Run each time the class is called.
61 - *
62 - * @param Log_Manager $manager Instance of manager object.
63 - */
64 - public function __construct( $manager ) {
65 - $this->manager = $manager;
66 - }
61 + /**
62 + * Public variable to hold type value.
63 + *
64 + * @var array
65 + */
66 + public $table_id_prefix = null;
67 67
68 - /**
69 - * Get the default primary column name.
70 - *
71 - * @return string Child Site name.
72 - */
73 - protected function get_default_primary_column_name() {
74 - return 'name';
75 - }
76 68
69 + /**
70 + * Public variable to hold total items number.
71 + *
72 + * @var integer
73 + */
74 + public $total_items;
77 75
78 - /**
79 - * Get sortable columns.
80 - *
81 - * @return array $sortable_columns Array of sortable column names.
82 - */
83 - public function get_sortable_columns() {
84 - $sortable_columns = array(
85 - 'created' => array( 'created', false ),
86 - 'name' => array( 'name', false ),
87 - 'user_id' => array( 'user_id', false ),
88 - );
89 - return $sortable_columns;
90 - }
76 + /**
77 + * Public variable to hold extra data.
78 + *
79 + * @var integer
80 + */
81 + public $items_extra_data;
91 82
92 - /**
93 - * Get default columns.
94 - *
95 - * @return array Array of default column names.
96 - */
97 - public function get_default_columns() {
98 - return array(
99 - 'created' => esc_html__( 'Event', 'mainwp' ),
100 - 'name' => esc_html__( 'Website', 'mainwp' ),
101 - 'user_id' => esc_html__( 'User', 'mainwp' ),
102 - );
103 - }
83 + /**
84 + * Protected variable to hold columns headers
85 + *
86 + * @var array
87 + */
88 + protected $column_headers;
104 89
105 - /**
106 - * Method get_columns()
107 - *
108 - * Combine all columns.
109 - *
110 - * @return array $columns Array of column names.
111 - */
112 - public function get_columns() {
113 90
114 - $columns = $this->get_default_columns();
91 + /**
92 + * Private static variable to hold the optimize value.
93 + *
94 + * @var mixed Default null
95 + */
96 + private $optimize_table = false;
115 97
116 - return $columns;
117 - }
118 98
119 - /**
120 - * Instantiate Columns.
121 - *
122 - * @return array $init_cols
123 - */
124 - public function get_columns_init() {
125 - $cols = $this->get_columns();
126 - $init_cols = array();
127 - foreach ( $cols as $key => $val ) {
128 - $init_cols[] = array( 'data' => esc_html( $key ) );
129 - }
130 - return $init_cols;
131 - }
99 + /**
100 + * Private static variable to hold the forced modified events title value.
101 + *
102 + * @var mixed Default null
103 + */
104 + private $forced_modified_events = null;
132 105
133 - /**
134 - * Get column defines.
135 - *
136 - * @return array $defines
137 - */
138 - public function get_columns_defines() {
139 - $defines = array();
140 - $defines[] = array(
141 - 'targets' => 'no-sort',
142 - 'orderable' => false,
143 - );
144 - $defines[] = array(
145 - 'targets' => 'manage-created-column',
146 - 'className' => 'mainwp-created-cell',
147 - );
148 - $defines[] = array(
149 - 'targets' => 'manage-site-column',
150 - 'className' => 'column-site-bulk mainwp-site-cell',
151 - );
152 - $defines[] = array(
153 - 'targets' => 'manage-user-column',
154 - 'className' => 'mainwp-user-cell',
155 - );
156 - $defines[] = array(
157 - 'targets' => array( 'extra-column' ),
158 - 'className' => 'collapsing',
159 - );
160 - return $defines;
161 - }
106 + /**
107 + * Class constructor.
108 + *
109 + * Run each time the class is called.
110 + *
111 + * @param Log_Manager $manager Instance of manager object.
112 + * @param Strings $type Events table type: manage_events|widget_overview|widget_insight.
113 + * @param bool $optimize Whether optimize table.
114 + */
115 + public function __construct( $manager, $type = '', $optimize = false ) {
116 + $this->manager = $manager;
117 + $this->table_id_prefix = $type;
118 + $this->optimize_table = $optimize;
119 + }
162 120
121 + /**
122 + * Get the default primary column name.
123 + *
124 + * @return string Child Site name.
125 + */
126 + protected function get_default_primary_column_name() {
127 + return 'name';
128 + }
163 129
164 - /**
165 - * Returns the column content for the provided item and column.
166 - *
167 - * @param array $item Record data.
168 - * @param string $column_name Column name.
169 - * @return string $out Output.
170 - */
171 - public function column_default( $item, $column_name ) {
172 - $out = '';
130 + // @NO_SONAR_START@ - duplicated issue.
131 + /**
132 + * Get sortable columns.
133 + *
134 + * @return array $sortable_columns Array of sortable column names.
135 + */
136 + public function get_sortable_columns() {
137 + return array(
138 + 'event' => array( 'event', false ),
139 + 'action' => array( 'action', false ),
140 + 'log_object' => array( 'log_object', false ),
141 + 'created' => array( 'created', false ),
142 + 'name' => array( 'name', false ),
143 + 'user_id' => array( 'user_id', false ),
144 + 'source' => array( 'source', false ),
145 + );
146 + }
173 147
174 - $record = new Log_Record( $item );
148 + /**
149 + * Get default columns.
150 + *
151 + * @return array Array of default column names.
152 + */
153 + public function get_default_columns() {
154 + if ( 'widget-overview' === $this->table_id_prefix ) {
155 + $columns = array(
156 + 'created' => esc_html__( 'Time', 'mainwp' ),
157 + 'log_object' => esc_html__( 'Object', 'mainwp' ),
158 + 'event' => esc_html__( 'Event', 'mainwp' ),
159 + 'name' => esc_html__( 'Site', 'mainwp' ),
160 + );
161 + } else {
162 + $columns = array(
163 + 'cb' => '<input type="checkbox" />',
164 + 'created' => esc_html__( 'Date', 'mainwp' ),
165 + 'user_id' => esc_html__( 'User', 'mainwp' ),
166 + 'action' => esc_html__( 'Action', 'mainwp' ),
167 + 'log_object' => esc_html__( 'Object', 'mainwp' ),
168 + 'icon' => '',
169 + 'name' => esc_html__( 'Website', 'mainwp' ),
170 + 'event' => esc_html__( 'Event', 'mainwp' ),
171 + 'source' => esc_html__( 'Source', 'mainwp' ),
172 + 'col_action' => '',
173 + );
174 + }
175 175
176 - $escaped = false;
177 - switch ( $column_name ) {
178 - case 'created':
179 - $event_title = $this->parse_event_title( $record );
180 - $act_label = $this->get_action_title( $record->action, 'action', true );
181 - $date_string = sprintf(
182 - '%s<br>%s<br><time datetime="%s" class="relative-time record-created">%s</time>',
183 - $event_title,
184 - $act_label,
185 - mainwp_module_log_get_iso_8601_extended_date( $record->created ),
186 - MainWP_Utility::format_timestamp( $record->created )
187 - );
188 - $out = $date_string;
189 - $escaped = true;
190 - break;
191 - case 'name':
192 - $out = ! empty( $record->log_site_name ) ? '<a href="admin.php?page=managesites&dashboard=' . intval( $record->site_id ) . '">' . esc_html( $record->log_site_name ) . '</a>' : 'N/A';
193 - $escaped = true;
194 - break;
195 - case 'user_id':
196 - $user = new Log_Author( (int) $record->user_id, (array) $record->user_meta );
197 - $out = $user->get_display_name() . sprintf( '<br /><small>%s</small>', $user->get_agent_label( $user->get_agent() ) );
198 - $escaped = true;
199 - break;
200 - default:
201 - }
176 + if ( 'manage-events' !== $this->table_id_prefix ) {
177 + unset( $columns['source'] );
178 + }
202 179
203 - if ( empty( $out ) ) {
204 - return '';
205 - }
180 + if ( 'widget-overview' === $this->table_id_prefix ) {
181 + unset( $columns['log_site_name'] );
182 + unset( $columns['icon'] );
183 + unset( $columns['user_id'] );
184 + unset( $columns['action'] );
185 + unset( $columns['source'] );
186 + unset( $columns['col_action'] );
187 + unset( $columns['cb'] );
188 + }
206 189
207 - if ( ! $escaped ) {
208 - $allowed_tags = wp_kses_allowed_html( 'post' );
209 - $allowed_tags['time'] = array(
210 - 'datetime' => true,
211 - 'class' => true,
212 - );
190 + return $columns;
191 + }
213 192
214 - $allowed_tags['img']['srcset'] = true;
193 + /**
194 + * Method get_columns()
195 + *
196 + * Combine all columns.
197 + *
198 + * @return array $columns Array of column names.
199 + */
200 + public function get_columns() {
201 + return $this->get_default_columns();
202 + }
215 203
216 - return wp_kses( $out, $allowed_tags );
217 - } else {
218 - return $out; //phpcs:ignore -- escaped.
219 - }
220 - }
204 + /**
205 + * Instantiate Columns.
206 + *
207 + * @return array $init_cols
208 + */
209 + public function get_columns_init() {
210 + $cols = $this->get_columns();
211 + $init_cols = array();
212 + foreach ( $cols as $key => $val ) {
213 + $init_cols[] = array( 'data' => esc_html( $key ) );
214 + }
215 + return $init_cols;
216 + }
221 217
218 + /**
219 + * Get column defines.
220 + *
221 + * @return array $defines
222 + */
223 + public function get_columns_defines() {
224 + $defines = array();
225 + $defines[] = array(
226 + 'targets' => 'no-sort',
227 + 'orderable' => false,
228 + );
229 + $defines[] = array(
230 + 'targets' => 'manage-cb-column',
231 + 'className' => 'check-column',
232 + );
233 + $defines[] = array(
234 + 'targets' => 'manage-created-column',
235 + 'className' => 'mainwp-created-cell',
236 + );
237 + $defines[] = array(
238 + 'targets' => 'manage-icon-column',
239 + 'className' => 'manage-icon-cell center aligned collapsing',
240 + );
241 + $defines[] = array(
242 + 'targets' => 'manage-site-column',
243 + 'className' => 'column-site-bulk mainwp-site-cell',
244 + );
245 + $defines[] = array(
246 + 'targets' => 'manage-user-column',
247 + 'className' => 'mainwp-user-cell',
248 + );
249 + $defines[] = array(
250 + 'targets' => array( 'manage-col_action-column' ),
251 + 'className' => 'collapsing',
252 + );
253 + $defines[] = array(
254 + 'targets' => array( 'manage-log_object-column' ),
255 + 'className' => 'mainwp-sites-changes-object-cell',
256 + );
222 257
223 - /**
224 - * Returns the label for a status.
225 - *
226 - * @param object $record record item.
227 - *
228 - * @return string
229 - */
230 - public function get_state_title( $record ) {
258 + return $defines;
259 + }
260 + // @NO_SONAR_END@ .
231 261
232 - $state = esc_html__( 'Undefined', 'mainwp' );
233 - if ( is_null( $record->state ) ) {
234 - $state = 'N/A';
235 - } elseif ( '0' === $record->state ) {
236 - $state = esc_html__( 'Failed', 'mainwp' );
237 - } elseif ( '1' === $record->state ) {
238 - $state = esc_html__( 'Success', 'mainwp' );
239 - }
240 - return $state;
241 - }
262 + /**
263 + * Returns the column content for the provided item and column.
264 + *
265 + * @param object $item Record data.
266 + * @param string $column_name Column name.
267 + * @param array $site_opts Site options.
268 + *
269 + * @return string $out Output.
270 + */
271 + public function column_default( $item, $column_name ) { //phpcs:ignore -- NOSONAR -complex.
272 + $out = '';
242 273
243 - /**
244 - * Returns the label for a connector term.
245 - *
246 - * @param string $act Action type.
247 - * @param string $type Connector term.
248 - * @param bool $coloring Coloring term.
249 - * @return string
250 - */
251 - public function get_action_title( $act, $type, $coloring = false ) {
274 + $record = new Log_Record( $item );
252 275
253 - if ( ! isset( $this->manager->connectors->term_labels[ 'logs_' . $type ][ $act ] ) ) {
254 - $title = $act;
255 - } else {
256 - $title = $this->manager->connectors->term_labels[ 'logs_' . $type ][ $act ];
257 - }
276 + $escaped = false;
277 + switch ( $column_name ) {
278 + case 'cb':
279 + $out = '<div class="ui checkbox">
280 + <input type="checkbox" value="' . (int) $record->log_id . '" name="" aria-label="' . esc_attr__( 'Select the change.', 'mainwp' ) . '"/>
281 + </div>';
282 + $escaped = true;
283 + break;
284 + case 'event':
285 + $out = $this->get_event_title( $record, 'action', true );
286 + $escaped = true;
287 + break;
288 + case 'action':
289 + $out = $this->get_action_title( $record );
290 + $escaped = true;
291 + break;
292 + case 'log_object':
293 + $out = $this->get_object_title( $record );
294 + $escaped = true;
295 + break;
296 + case 'created':
297 + $site_info = is_array( $this->sites_opts ) && isset( $this->sites_opts[ $record->site_id ] ) && isset( $this->sites_opts[ $record->site_id ]['site_info'] ) ? $this->sites_opts[ $item->site_id ]['site_info'] : array();
298 + $site_dtf = is_array( $site_info ) && isset( $site_info['format_datetime'] ) ? $site_info['format_datetime'] : false;
258 299
259 - $title = is_string( $title ) ? ucfirst( $title ) : $title;
260 - if ( $coloring ) {
261 - $format_title = '<span class="ui medium text">%s</span>';
262 - if ( 'deactivate' === $act || 'deleted' === $act || 'delete' === $act ) {
263 - $format_title = '<span class="ui medium red text">%s</span>';
264 - } elseif ( 'activate' === $act || 'updated' === $act || 'update' === $act ) {
265 - $format_title = '<span class="ui medium blue text">%s</span>';
266 - } elseif ( 'install' === $act || 'created' === $act || 'added' === $act || 'sync' === $act ) {
267 - $format_title = '<span class="ui medium green text">%s</span>';
268 - }
269 - $title = sprintf( $format_title, esc_html( $title ) );
270 - }
271 - return $title;
272 - }
300 + $child_time = MainWP_Utility::format_timezone( (int) $record->created, false, $site_dtf );
301 + if ( ! empty( $child_time ) ) {
302 + /* translators: %s: Child site time */
303 + $tooltip_text = esc_attr__( 'Child Site time: %s', 'mainwp' );
304 + $date_string = sprintf(
305 + '<span data-tooltip="' . $tooltip_text . ' " created-time="' . esc_attr( $record->created ) . '" data-inverted="" data-position="right center"><time datetime="%s" class="relative-time record-created">%s</time></span>',
306 + $child_time,
307 + mainwp_module_log_get_iso_8601_extended_date( $record->created ),
308 + MainWP_Utility::format_timezone( $record->created )
309 + );
310 + } else {
311 + $date_string = sprintf(
312 + '<time datetime="%s" created-time="' . esc_attr( $record->created ) . '" class="relative-time record-created">%s</time>',
313 + mainwp_module_log_get_iso_8601_extended_date( $record->created ),
314 + MainWP_Utility::format_timezone( $record->created )
315 + );
316 + }
317 + $out = $date_string;
318 + $escaped = true;
319 + break;
320 + case 'icon':
321 + $out = 'N/A';
322 + if ( ! empty( $record->log_site_name ) ) {
323 + $site_opts = is_array( $this->sites_opts ) && isset( $this->sites_opts[ $record->site_id ] ) ? $this->sites_opts[ $record->site_id ] : array();
324 + $siteObj = (object) array(
325 + 'id' => $record->site_id,
326 + 'url' => $record->url,
327 + 'name' => $record->log_site_name,
328 + 'favi_icon' => is_array( $site_opts ) && isset( $site_opts['favi_icon'] ) ? $site_opts['favi_icon'] : '',
329 + );
330 + $favi_url = MainWP_Connect::get_favico_url( $siteObj );
331 + $site_icon = MainWP_Manage_Sites::get_instance()->get_site_icon_display( is_array( $site_opts ) && isset( $site_opts['cust_site_icon_info'] ) ? $site_opts['cust_site_icon_info'] : '', $favi_url );
273 332
274 - /**
275 - * Parse event title.
276 - *
277 - * @param object $record Log record object.
278 - * @return string
279 - */
280 - public function parse_event_title( $record ) {
281 - $extra_meta = ! empty( $record->extra_meta ) ? json_decode( $record->extra_meta, true ) : array();
282 - if ( ! is_array( $extra_meta ) ) {
283 - $extra_meta = array();
284 - }
285 - $title = '';
286 - if ( 'posts' === $record->connector || 'users' === $record->connector || 'client' === $record->connector || 'installer' === $record->connector ) {
287 - $title = $record->item;
288 - } elseif ( 'site' === $record->connector ) {
289 - $title = esc_html__( 'Website', 'mainwp' );
290 - } elseif ( isset( $extra_meta['name'] ) ) {
291 - $title = $extra_meta['name'];
292 - }
293 - $title = esc_html( $title ) . $this->get_context_title( $record->context, $record->connector );
294 - return $title;
295 - }
333 + ob_start();
334 + echo $site_icon; // phpcs:ignore WordPress.Security.EscapeOutput
335 + $out = ob_get_clean();
336 + }
337 + $escaped = true;
338 + break;
339 + case 'name':
340 + $out = 'N/A';
296 341
297 - /**
298 - * Returns the label for a context.
299 - *
300 - * @param string $context Log context.
301 - * @param string $connector Log connector.
302 - * @return string
303 - */
304 - public function get_context_title( $context, $connector ) {
305 - $title = '';
342 + if ( ! empty( $record->log_site_name ) ) {
343 + ob_start();
344 + if ( \mainwp_current_user_can( 'dashboard', 'access_wpadmin_on_child_sites' ) ) : ?>
345 + <a href="<?php MainWP_Site_Open::get_open_site_url( $record->site_id ); ?>" class="open_newwindow_wpadmin" target="_blank"><i class="sign in icon"></i></a>
346 + <?php endif; ?>
347 + <a href="<?php echo 'admin.php?page=managesites&dashboard=' . intval( $record->site_id ); ?>">
348 + <?php echo esc_attr( stripslashes( $record->log_site_name ) ); ?>
349 + </a>
350 + <div>
351 + <span class="ui small text">
352 + <a href="<?php echo esc_url( $record->url ); ?>" class="mainwp-may-hide-referrer open_site_url ui grey text" target="_blank">
353 + <?php echo esc_html( MainWP_Utility::get_nice_url( $record->url ) ); ?>
354 + </a>
355 + </span>
356 + </div>
357 + <?php
358 + $out = ob_get_clean();
359 + }
360 + $escaped = true;
361 + break;
362 + case 'user_id':
363 + $user_meta = ! empty( $record->user_meta ) ? $record->user_meta : array();
306 364
307 - if ( 'plugin' === $context ) {
308 - $title = esc_html__( 'Plugin', 'mainwp' );
309 - } elseif ( 'theme' === $context ) {
310 - $title = esc_html__( 'Theme', 'mainwp' );
311 - } elseif ( 'translation' === $context ) {
312 - $title = esc_html__( 'Translation', 'mainwp' );
313 - } elseif ( 'core' === $context ) {
314 - $title = esc_html__( 'WP Core WordPress', 'mainwp' );
315 - } elseif ( 'posts' === $connector ) {
316 - if ( 'post' === $context ) {
317 - $title = esc_html__( 'Post', 'mainwp' );
318 - } elseif ( 'page' === $context ) {
319 - $title = esc_html__( 'Page', 'mainwp' );
320 - } else {
321 - $title = esc_html__( 'Custom Post', 'mainwp' );
322 - }
323 - } elseif ( 'clients' === $context ) {
324 - $title = esc_html__( 'Client', 'mainwp' );
325 - } elseif ( 'users' === $context ) {
326 - $title = esc_html__( 'User', 'mainwp' );
327 - }
365 + if ( empty( $user_meta['full_name'] ) && isset( $record->meta['first_name'] ) && isset( $record->meta['last_name'] ) ) {
366 + $user_meta['wp_user_id'] = $record->user_id;
367 + $user_meta['full_name'] = $record->meta['first_name'] . ' ' . $record->meta['last_name'];
368 + $user_meta['ip'] = ! empty( $record->meta['client_ip'] ) ? $record->meta['client_ip'] : '';
369 + }
328 370
329 - if ( ! empty( $title ) ) {
330 - $title = ' ' . $title;
331 - }
371 + $user = new Log_Author( $record->user_id, $user_meta );
332 372
333 - return $title;
334 - }
373 + if ( empty( $out ) ) {
374 + if ( ! empty( $record->log_type_id ) || 'non-mainwp-changes' === $record->connector ) {
375 + $out = $user->get_full_name();
376 + } else {
377 + $out = $user->get_display_name();
378 + }
379 + }
335 380
336 - /**
337 - * Html output if no Child Sites are connected.
338 - *
339 - * @uses \MainWP\Dashboard\MainWP_DB::instance()::get_websites_count()
340 - */
341 - public function no_items() {
342 - ?>
343 - <div class="ui center aligned segment">
344 - <i class="globe massive icon"></i>
345 - <div class="ui header">
346 - <?php esc_html_e( 'No records found.', 'mainwp' ); ?>
347 - </div>
348 - </div>
349 - <?php
350 - }
381 + if ( empty( $out ) ) {
382 + $out = $user->get_agent_label( $user->get_agent() );
383 + }
384 + $escaped = true;
385 + break;
386 + case 'source':
387 + if ( ! empty( $record->source ) ) {
388 + $out = $record->source; // sub query field.
389 + } else {
390 + $out = ( 'non-mainwp-changes' === $record->connector ) ? 'WP Admin' : 'Dashboard';
391 + }
392 + break;
393 + case 'col_action':
394 + ob_start();
395 + ?>
396 + <div action-id="<?php echo intval( $record->log_id ); ?>">
397 + <a class="ui mini green button insights-actions-row-dismiss" href="javascript:void(0)" data-tooltip="<?php esc_attr_e( 'Dismiss the change.', 'mainwp' ); ?>" data-position="left center" data-inverted=""><?php esc_html_e( 'Dismiss', 'mainwp' ); ?></a>
398 + </div>
399 + <?php
400 + $out = ob_get_clean();
401 + break;
402 + default:
403 + }
351 404
352 - /**
353 - * Method has_items().
354 - *
355 - * Verify if items exist.
356 - */
357 - public function has_items() {
358 - return ! empty( $this->items );
359 - }
405 + if ( empty( $out ) ) {
406 + return '';
407 + }
360 408
361 - /**
362 - * Get last query found rows
363 - *
364 - * @return integer
365 - */
366 - public function get_total_found_rows() {
367 - return $this->total_items;
368 - }
409 + if ( ! $escaped ) {
410 + $allowed_tags = wp_kses_allowed_html( 'post' );
411 + $allowed_tags['time'] = array(
412 + 'datetime' => true,
413 + 'class' => true,
414 + );
369 415
370 - /**
371 - * Prepare the items to be listed.
372 - *
373 - * @param bool $with_prev_data To get previous data.
374 - * @param array $insights_filters Insights filters.
375 - */
376 - public function prepare_items( $with_prev_data = false, $insights_filters = array() ) { //phpcs:ignore -- complex method.
416 + $allowed_tags['img']['srcset'] = true;
377 417
378 - $req_orderby = '';
379 - $req_order = null;
418 + return wp_kses( $out, $allowed_tags );
419 + } else {
420 + return $out; //phpcs:ignore -- escaped.
421 + }
422 + }
380 423
381 - // phpcs:disable WordPress.Security.NonceVerification
382 - if ( isset( $_REQUEST['order'] ) ) {
383 - $columns = isset( $_REQUEST['columns'] ) ? wp_unslash( $_REQUEST['columns'] ) : array(); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
384 - $ord_col = isset( $_REQUEST['order'][0]['column'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['order'][0]['column'] ) ) : '';
385 - if ( isset( $columns[ $ord_col ] ) ) {
386 - $req_orderby = isset( $columns[ $ord_col ]['data'] ) ? sanitize_text_field( wp_unslash( $columns[ $ord_col ]['data'] ) ) : '';
387 - $req_order = isset( $_REQUEST['order'][0]['dir'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['order'][0]['dir'] ) ) : '';
388 - }
389 - }
390 424
391 - $search = isset( $_REQUEST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search']['value'] ) ) : '';
425 + /**
426 + * Returns the label for a status.
427 + *
428 + * @param object $record record item.
429 + *
430 + * @return string
431 + */
432 + public function get_state_title( $record ) {
392 433
393 - $filter_dtsstart = '';
394 - $filter_dtsstop = '';
395 - $array_clients_ids = array();
396 - $array_groups_ids = array();
397 - $array_users_ids = array();
434 + $state = esc_html__( 'Undefined', 'mainwp' );
435 + if ( is_null( $record->state ) ) {
436 + $state = 'N/A';
437 + } elseif ( '0' === $record->state ) {
438 + $state = esc_html__( 'Failed', 'mainwp' );
439 + } elseif ( '1' === $record->state ) {
440 + $state = esc_html__( 'Success', 'mainwp' );
441 + }
442 + return $state;
443 + }
398 444
399 - extract( $insights_filters ); //phpcs:ignore -- ok.
445 + /**
446 + * Returns the label for a connector term.
447 + *
448 + * @param object $record Event data.
449 + * @return string
450 + */
451 + public function get_action_title( $record ) {
452 + if ( ! empty( $record->log_type_id ) ) {
453 + $action = $this->parse_changes_action_title( $record );
454 + } else {
455 + $act = $record->action;
456 + $type = 'action';
400 457
401 - if ( ! empty( $filter_dtsstart ) && ! empty( $filter_dtsstop ) && ! is_numeric( $filter_dtsstart ) && ! is_numeric( $filter_dtsstop ) ) { // after extract.
402 - // to fix string of date.
403 - $filter_dtsstart = gmdate( 'Y-m-d', strtotime( $filter_dtsstart ) );
404 - $filter_dtsstop = gmdate( 'Y-m-d', strtotime( $filter_dtsstop ) );
405 - }
458 + if ( ! isset( $this->manager->connectors->term_labels[ 'logs_' . $type ][ $act ] ) ) {
459 + $title = $act;
460 + } else {
461 + $title = $this->manager->connectors->term_labels[ 'logs_' . $type ][ $act ];
462 + }
463 + $title = is_string( $title ) ? ucfirst( $title ) : $title;
464 + $action = $title;
465 + }
466 + return $action;
467 + }
406 468
407 - // phpcs:enable
469 + /**
470 + * Returns the forced modified event title.
471 + *
472 + * @return array Logs type ids.
473 + */
474 + public function get_forced_modified_event_title() {
475 + if ( null === $this->forced_modified_events ) {
476 + $defaults = array( 1460, 1330, 1335, 1495, 1720, 1721, 1725, 1726 );
477 + $this->forced_modified_events = apply_filters( 'mainwp_module_logs_forced_modified_event_title', $defaults );
478 + }
479 + if ( ! is_array( $this->forced_modified_events ) ) {
480 + $this->forced_modified_events = array();
481 + }
482 + return $this->forced_modified_events;
483 + }
408 484
409 - // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
410 - $perPage = isset( $_REQUEST['length'] ) ? intval( $_REQUEST['length'] ) : false;
411 - if ( -1 === (int) $perPage || empty( $perPage ) ) {
412 - $perPage = 99999;
413 - }
414 - $start = isset( $_REQUEST['start'] ) ? intval( $_REQUEST['start'] ) : 0;
415 485
416 - $search = isset( $_REQUEST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search']['value'] ) ) : '';
486 + /**
487 + * Returns the label for a connector term.
488 + *
489 + * @param string $record Log data.
490 + * @param string $type Connector term.
491 + * @param bool $coloring Coloring term.
492 + * @return string
493 + */
494 + public function get_event_title( $record, $type, $coloring = false ) { //phpcs:ignore -- NOSONAR - complex.
417 495
418 - $recent_number = isset( $_REQUEST['recent_number'] ) ? intval( $_REQUEST['recent_number'] ) : 0;
496 + $act = $record->action;
419 497
420 - // phpcs:enable
498 + if ( ! empty( $record->log_type_id ) ) {
499 + $title = $act;
500 + if ( in_array( (int) $record->log_type_id, $this->get_forced_modified_event_title() ) ) {
501 + $title = esc_html__( 'Modified', 'mainwp' );
502 + } else {
503 + $title = ucfirst( $title );
504 + }
505 + } else {
506 + if ( ! isset( $this->manager->connectors->term_labels[ 'logs_' . $type ][ $act ] ) ) {
507 + $title = $act;
508 + } else {
509 + $title = $this->manager->connectors->term_labels[ 'logs_' . $type ][ $act ];
510 + }
511 + $title = is_string( $title ) ? ucfirst( $title ) : $title;
512 + }
421 513
422 - $args = array(
423 - 'order' => ( 'asc' === $req_order ) ? 'asc' : 'desc',
424 - 'orderby' => $req_orderby,
425 - 'start' => $start,
426 - 'recent_number' => $recent_number,
427 - 'search' => $search,
428 - 'groups_ids' => $array_groups_ids,
429 - 'client_ids' => $array_clients_ids,
430 - 'user_ids' => $array_users_ids,
431 - 'timestart' => strtotime( $filter_dtsstart . ' 00:00:00' ),
432 - 'timestop' => strtotime( $filter_dtsstop . ' 23:59:59' ),
433 - );
514 + if ( $coloring ) {
434 515
435 - $args['records_per_page'] = $perPage;
516 + $color = '';
436 517
437 - $this->items = $this->manager->db->get_records( $args );
518 + if ( in_array( $act, array( 'deleted', 'removed', 'revoked', 'deactivated', 'disabled', 'suspended', 'trashed' ), true ) ) {
519 + $color = 'red';
520 + } elseif ( in_array( $act, array( 'updated', 'modified', 'unapproved', 'spammed' ), true ) ) {
521 + $color = 'orange';
522 + } elseif ( in_array( $act, array( 'added', 'activated', 'created', 'published', 'enabled', 'approved' ), true ) ) {
523 + $color = 'green';
524 + } elseif ( in_array( $act, array( 'synced', 'installed', 'uploaded' ), true ) ) {
525 + $color = 'teal';
526 + } elseif ( in_array( $act, array( 'opened', 'logged-in', 'logged-out', 'unspammed' ), true ) ) {
527 + $color = 'blue';
528 + } else {
529 + $color = 'grey'; // fallback / unknown event
530 + }
438 531
439 - if ( isset( $_REQUEST['recent_number'] ) ) { //phpcs:ignore -- ok.
440 - $this->total_items = $this->manager->db->get_found_records_count(); // get this value for recent events request only.
441 - }
532 + /* Compatibility aliases */
533 + if ( 'delete' === $act ) {
534 + $color = 'red';
535 + } elseif ( 'deactivate' === $act ) {
536 + $color = 'red';
537 + } elseif ( 'update' === $act ) {
538 + $color = 'orange';
539 + } elseif ( in_array( $act, array( 'install', 'activate' ), true ) ) {
540 + $color = 'teal';
541 + }
442 542
443 - $this->items_prev = array();
444 - if ( $with_prev_data && ! empty( $args['timestart'] ) && ! empty( $args['timestop'] ) && $args['timestart'] < $args['timestop'] ) {
445 - $timestart_prev = $args['timestart'] - ( $args['timestop'] - $args['timestart'] );
446 - $timestop_prev = $args['timestart'];
447 - $args['timestart'] = $timestart_prev;
448 - $args['timestop'] = $timestop_prev;
449 - $this->items_prev = $this->manager->db->get_records( $args );
450 - }
451 - }
543 + $title = sprintf( '<span class="ui mini basic %s label">%s</span>', $color, esc_html( $title ) );
544 + }
452 545
546 + return $title;
547 + }
453 548
454 - /**
455 - * Display the table.
456 - */
457 - public function display() {
549 + /**
550 + * Returns the icons for object.
551 + *
552 + * @param string $record Log data.
553 + * @return string
554 + */
555 + public function get_object_icon( $record ) {
556 + $context = $record->context;
557 + $icon = '';
558 + switch ( $context ) {
559 + case 'post':
560 + $icon = 'file text';
561 + break;
562 + case 'file':
563 + $icon = 'file';
564 + break;
565 + case 'system-setting':
566 + $icon = 'cogs';
567 + break;
568 + case 'category':
569 + $icon = 'layer group';
570 + break;
571 + case 'tag':
572 + $icon = 'tag';
573 + break;
574 + case 'widget':
575 + $icon = 'puzzle piece';
576 + break;
577 + case 'plugin':
578 + $icon = 'plug';
579 + break;
580 + case 'theme':
581 + $icon = 'tint icon';
582 + break;
583 + case 'menu':
584 + $icon = 'bars';
585 + break;
586 + case 'comment':
587 + $icon = 'comment';
588 + break;
589 + case 'user':
590 + $icon = 'user';
591 + break;
592 + case 'database':
593 + $icon = 'database';
594 + break;
595 + case 'cron':
596 + $icon = 'clock';
597 + break;
598 + case 'sites':
599 + $icon = 'globe';
600 + break;
601 + // To compatible.
602 + case 'translation':
603 + $icon = 'language';
604 + break;
605 + case 'core':
606 + $icon = 'wordpress icon';
607 + break;
608 + case 'posts':
609 + $icon = 'file text';
610 + break;
611 + case 'clients':
612 + $icon = 'address card';
613 + break;
614 + case 'users':
615 + $icon = 'users';
616 + break;
617 + default:
618 + break;
619 + }
620 + return ! empty( $icon ) ? sprintf( '<i class="%s icon"></i>', $icon ) : '';
621 + }
458 622
459 - $sites_per_page = get_option( 'mainwp_default_sites_per_page', 25 );
623 + /**
624 + * Parse event title.
625 + *
626 + * @param object $record Log record object.
627 + * @param bool $with_icon Return with icon.
628 + * @param bool $with_context_suffix Return name object with context suffix.
629 + *
630 + * @return string
631 + */
632 + public function get_object_title( $record, $with_icon = true, $with_context_suffix = true ) { //phpcs:ignore -- NOSONAR - complex.
633 + $extra_meta = ! empty( $record->extra_meta ) ? json_decode( $record->extra_meta, true ) : array();
634 + if ( ! is_array( $extra_meta ) ) {
635 + $extra_meta = array();
636 + }
637 + $title = '';
638 + $roll_msg = '';
639 + if ( 'posts' === $record->connector || 'users' === $record->connector || 'client' === $record->connector || 'installer' === $record->connector ) {
640 + $title = $record->item;
641 + if ( 'installer' === $record->connector && ! empty( $extra_meta['rollback_info'] ) ) {
642 + $roll_msg = MainWP_Updates_Helper::get_roll_msg( $extra_meta['rollback_info'], true ) . ' ';
643 + }
644 + } elseif ( 'site' === $record->connector ) {
645 + $title = esc_html__( 'Website', 'mainwp' );
646 + } elseif ( 'non-mainwp-changes' === $record->connector ) {
647 + $title = esc_html( $record->item );
648 + if ( ! empty( $record->log_type_id ) ) {
649 + $title = $this->get_changes_object_title( $record );
650 + }
651 + } elseif ( isset( $extra_meta['name'] ) ) {
652 + $title = $extra_meta['name'];
653 + if ( 'installer' === $record->connector && ! empty( $extra_meta['rollback_info'] ) ) {
654 + $roll_msg = MainWP_Updates_Helper::get_roll_msg( $extra_meta['rollback_info'], true ) . ' ';
655 + }
656 + }
460 657
461 - $sites_per_page = intval( $sites_per_page );
658 + if ( empty( $record->log_type_id && $with_context_suffix ) ) {
659 + $title = $roll_msg . $this->get_context_title( $title, $record->context, $record->connector );
660 + }
462 661
463 - $pages_length = array(
464 - 25 => '25',
465 - 10 => '10',
466 - 50 => '50',
467 - 100 => '100',
468 - 300 => '300',
469 - );
662 + if ( ! $with_context_suffix ) {
663 + $title = trim( $title );
664 + $title = preg_replace( '/( ?(plugin|theme))$/i', '', $title );
665 + }
470 666
471 - $pages_length = $pages_length + array( $sites_per_page => $sites_per_page );
472 - ksort( $pages_length );
667 + if ( ! empty( $record->log_type_id ) ) {
668 + $title = Log_Changes_Logs_Helper::get_changes_logs_object_title( $record, $title );
669 + }
473 670
474 - if ( isset( $pages_length[-1] ) ) {
475 - unset( $pages_length[-1] );
476 - }
671 + if ( $with_icon ) {
672 + $obj_icon = $this->get_object_icon( $record );
673 + return $obj_icon . $title;
674 + }
477 675
478 - $pagelength_val = implode( ',', array_keys( $pages_length ) );
479 - $pagelength_title = implode( ',', array_values( $pages_length ) );
676 + return $title;
677 + }
480 678
481 - ?>
482 - <table id="mainwp-module-log-records-table" style="width:100%" class="ui single line selectable unstackable table mainwp-with-preview-table">
483 - <thead>
484 - <tr><?php $this->print_column_headers( true ); ?></tr>
485 - </thead>
486 - <tfoot>
487 - <tr><?php $this->print_column_headers( false ); ?></tr>
488 - </tfoot>
489 - </table>
490 - <?php
491 - $count = $this->get_total_found_rows();
492 - if ( empty( $count ) ) {
493 - ?>
494 - <div id="sites-table-count-empty" style="display: none;">
495 - <?php $this->no_items(); ?>
496 - </div>
497 - <?php
498 - }
499 - ?>
500 - <div id="mainwp-loading-sites" style="display: none;">
501 - <div class="ui active inverted dimmer">
502 - <div class="ui indeterminate large text loader"><?php esc_html_e( 'Loading ...', 'mainwp' ); ?></div>
503 - </div>
504 - </div>
505 - <?php
506 - $table_features = array(
507 - 'searching' => 'true',
508 - 'paging' => 'true',
509 - 'pagingType' => 'full_numbers',
510 - 'info' => 'true',
511 - 'colReorder' => '{ fixedColumnsLeft: 1, fixedColumnsRight: 1 }',
512 - 'stateSave' => 'true',
513 - 'stateDuration' => '0',
514 - 'order' => '[]',
515 - 'scrollX' => 'true',
516 - 'responsive' => 'true',
517 - 'fixedColumns' => '',
518 - );
519 - ?>
679 + /**
680 + * Method get_log_author_name().
681 + *
682 + * @param object $record Logs record.
683 + *
684 + * @return string Author name.
685 + */
686 + public function get_log_author_name( $record ) { //phpcs:ignore -- NOSONAR - long function.
687 + $name = '';
688 + $user_meta = ! empty( $record->user_meta ) ? $record->user_meta : array();
520 689
521 - <script type="text/javascript">
522 - var responsive = <?php echo esc_js( $table_features['responsive'] ); ?>;
523 - if( jQuery( window ).width() > 1140 ) {
524 - responsive = false;
525 - }
526 - jQuery( document ).ready( function( $ ) {
527 - var $module_log_table = null;
528 - try {
529 - jQuery( '#mainwp-sites-table-loader' ).hide();
530 - $module_log_table = jQuery( '#mainwp-module-log-records-table' ).on( 'processing.dt', function ( e, settings, processing ) {
531 - jQuery( '#mainwp-loading-sites' ).css( 'display', processing ? 'block' : 'none' );
532 - if (!processing) {
533 - var tb = jQuery( '#mainwp-module-log-records-table' );
534 - tb.find( 'th[cell-cls]' ).each( function(){
535 - var ceIdx = this.cellIndex;
536 - var cls = jQuery( this ).attr( 'cell-cls' );
537 - jQuery( '#mainwp-module-log-records-table tr' ).each(function(){
538 - jQuery(this).find( 'td:eq(' + ceIdx + ')' ).addClass(cls);
539 - } );
540 - } );
541 - $( '#mainwp-module-log-records-table .ui.dropdown' ).dropdown();
542 - $( '#mainwp-module-log-records-table .ui.checkbox' ).checkbox();
543 - }
544 - } ).on( 'column-reorder.dt', function ( e, settings, details ) {
545 - $( '#mainwp-module-log-records-table .ui.dropdown' ).dropdown();
546 - $( '#mainwp-module-log-records-table .ui.checkbox' ).checkbox();
547 - } ).DataTable( {
548 - "ajax": {
549 - "url": ajaxurl,
550 - "type": "POST",
551 - "data": function ( d ) {
552 - var data = mainwp_secure_data( {
553 - action: 'mainwp_module_log_events_display_rows',
554 - range: $( '#mainwp-module-log-filter-ranges').dropdown('get value'),
555 - group: $( '#mainwp-module-log-filter-groups').dropdown('get value'),
556 - client: $( '#mainwp-module-log-filter-clients').dropdown('get value'),
557 - user: $( '#mainwp-module-log-filter-users').dropdown('get value'),
558 - dtsstart: $('#mainwp-module-log-filter-dtsstart input[type=text]').val(),
559 - dtsstop: $('#mainwp-module-log-filter-dtsstop input[type=text]').val(),
560 - recent_number: 100,
561 - } );
562 - return $.extend( {}, d, data );
563 - },
564 - "dataSrc": function ( json ) {
565 - for ( var i=0, ien=json.data.length ; i < ien ; i++ ) {
566 - json.data[i].rowClass = json.rowsInfo[i].rowClass;
567 - json.data[i].log_id = json.rowsInfo[i].log_id;
568 - json.data[i].created_sort = json.rowsInfo[i].created;
569 - json.data[i].state_sort = json.rowsInfo[i].state;
570 - }
571 - return json.data;
572 - }
573 - },
574 - "responsive": responsive,
575 - "searching" : <?php echo esc_js( $table_features['searching'] ); ?>,
576 - "paging" : <?php echo esc_js( $table_features['paging'] ); ?>,
577 - "pagingType" : "<?php echo esc_js( $table_features['pagingType'] ); ?>",
578 - "info" : <?php echo esc_js( $table_features['info'] ); ?>,
579 - "colReorder" : <?php echo esc_js( $table_features['colReorder'] ); ?>,
580 - "scrollX" : <?php echo esc_js( $table_features['scrollX'] ); ?>,
581 - "stateSave" : <?php echo esc_js( $table_features['stateSave'] ); ?>,
582 - "stateDuration" : <?php echo esc_js( $table_features['stateDuration'] ); ?>,
583 - "order" : <?php echo $table_features['order']; // phpcs:ignore -- specical chars. ?>,
584 - "fixedColumns" : <?php echo ! empty( $table_features['fixedColumns'] ) ? esc_js( $table_features['fixedColumns'] ) : '""'; ?>,
585 - "lengthMenu" : [ [<?php echo esc_js( $pagelength_val ); ?>, -1 ], [<?php echo esc_js( $pagelength_title ); ?>, "All"] ],
586 - "serverSide": true,
587 - "pageLength": <?php echo intval( $sites_per_page ); ?>,
588 - "columnDefs": <?php echo wp_json_encode( $this->get_columns_defines() ); ?>,
589 - "columns": <?php echo wp_json_encode( $this->get_columns_init() ); ?>,
590 - "language": {
591 - "emptyTable": "<?php esc_html_e( 'No events found.', 'mainwp' ); ?>"
592 - },
593 - "drawCallback": function( settings ) {
594 - this.api().tables().body().to$().attr( 'id', 'mainwp-module-log-records-body-table' );
595 - mainwp_datatable_fix_menu_overflow();
596 - if ( typeof mainwp_preview_init_event !== "undefined" ) {
597 - mainwp_preview_init_event();
598 - }
599 - jQuery( '#mainwp-sites-table-loader' ).hide();
600 - if ( jQuery('#mainwp-module-log-records-body-table td.dataTables_empty').length > 0 && jQuery('#sites-table-count-empty').length ){
601 - jQuery('#mainwp-module-log-records-body-table td.dataTables_empty').html(jQuery('#sites-table-count-empty').html());
602 - }
603 - },
604 - "initComplete": function( settings, json ) {
605 - },
606 - rowCallback: function (row, data) {
607 - jQuery( row ).addClass(data.rowClass);
608 - jQuery( row ).attr( 'id', "log-row-" + data.log_id );
609 - jQuery( row ).find('.mainwp-date-cell').attr('data-sort', data.created_sort );
610 - jQuery( row ).find('.mainwp-state-cell').attr('data-sort', data.state_sort );
611 - }
612 - } );
613 - } catch(err) {
614 - // to fix js error.
615 - console.log(err);
616 - }
617 -
618 - mainwp_module_log_events_filter = function() {
619 - try {
620 - $module_log_table.ajax.reload();
621 - } catch(err) {
622 - // to fix js error.
623 - console.log(err);
624 - }
625 - };
626 - mainwp_module_log_overview_content_filter = function() {
627 - var range = jQuery( '#mainwp-module-log-filter-ranges').dropdown('get value');
628 - var group = jQuery( '#mainwp-module-log-filter-groups').dropdown('get value');
629 - var client = jQuery( '#mainwp-module-log-filter-clients').dropdown('get value');
630 - var user = jQuery( '#mainwp-module-log-filter-users').dropdown('get value');
631 - var dtsstart = jQuery('#mainwp-module-log-filter-dtsstart input[type=text]').val();
632 - var dtsstop = jQuery('#mainwp-module-log-filter-dtsstop input[type=text]').val();
633 - var params = '';
634 - params += '&range=' + encodeURIComponent( range );
635 - params += '&group=' + encodeURIComponent( group );
636 - params += '&client=' + encodeURIComponent( client );
637 - params += '&user=' + encodeURIComponent( user );
638 - params += '&dtsstart=' + encodeURIComponent( dtsstart );
639 - params += '&dtsstop=' + encodeURIComponent( dtsstop );
640 - params += '&_insights_opennonce=' + mainwpParams._wpnonce;
641 - window.location = 'admin.php?page=InsightsOverview' + params;
642 - return false;
643 - };
690 + if ( empty( $user_meta['full_name'] ) && isset( $record->meta['first_name'] ) && isset( $record->meta['last_name'] ) ) {
691 + $user_meta['wp_user_id'] = $record->user_id;
692 + $user_meta['full_name'] = $record->meta['first_name'] . ' ' . $record->meta['last_name'];
693 + $user_meta['ip'] = ! empty( $record->meta['client_ip'] ) ? $record->meta['client_ip'] : '';
694 + }
644 695
645 - } );
646 -
647 - </script>
648 - <?php
649 - }
696 + $user = new Log_Author( $record->user_id, $user_meta );
650 697
651 - /**
652 - * Get the column count.
653 - *
654 - * @return int Column Count.
655 - */
656 - public function get_column_count() {
657 - list( $columns ) = $this->get_column_info();
658 - return count( $columns );
659 - }
698 + if ( ! empty( $record->log_type_id ) || 'non-mainwp-changes' === $record->connector ) {
699 + $name = $user->get_full_name();
700 + } else {
701 + $name = $user->get_display_name();
702 + }
660 703
661 - /**
662 - * Echo the column headers.
663 - */
664 - public function print_column_headers() {
665 - list( $columns, $sortable, $primary ) = $this->get_column_info();
704 + return ! empty( $name ) ? $name : 'N/A';
705 + }
666 706
667 - $def_columns = $this->get_default_columns();
668 - $def_columns['site_actions'] = '';
707 + /**
708 + * Parse event changes logs title.
709 + *
710 + * @param object $record Log record object.
711 + * @return string
712 + */
713 + public function parse_changes_action_title( $record ) {
714 + $data = array( 'action' => ucfirst( $record->action ) );
715 + $meta = ! empty( $record->meta ) && is_array( $record->meta ) ? $record->meta : array();
716 + $na = 'N/A';
717 + switch ( (int) $record->log_type_id ) {
718 + case 1455:
719 + $name = ! empty( $meta['name'] ) ? $meta['name'] : '';
720 + if ( empty( $name ) ) {
721 + $name = ! empty( $meta['plugin'] ) ? $meta['plugin'] : $na;
722 + }
723 + $data['plugin'] = $name;
724 + break;
725 + case 1465:
726 + $data['theme'] = ! empty( $meta['theme'] ) ? basename( $meta['theme'] ) : $na;
727 + break;
728 + case 1460:
729 + case 1470:
730 + $data['name'] = ! empty( $meta['name'] ) ? $meta['name'] : $na;
731 + break;
732 + default:
733 + break;
734 + }
735 + $parse_title = Log_Changes_Logs_Helper::get_changes_log_title( $record->log_type_id, $data, 'action' );
736 + return ! empty( $parse_title ) ? $parse_title : ucfirst( $record->action );
737 + }
669 738
670 - foreach ( $columns as $column_key => $column_display_name ) {
739 + /**
740 + * Parse object changes logs title.
741 + *
742 + * @param string $title Object title.
743 + * @param object $record Log record object.
744 + * @return string
745 + */
746 + public function get_changes_formatted_object_title( $title, $record ) {
747 + $meta = ! empty( $record->meta ) && is_array( $record->meta ) ? $record->meta : array();
748 + $na = 'N/A';
749 + $data = array();
750 + switch ( (int) $record->log_type_id ) { // NOSONAR - switch is ok.
751 + case 1461:
752 + case 1965:
753 + $name = ! empty( $meta['name'] ) ? $meta['name'] : '';
754 + if ( empty( $name ) ) {
755 + $name = ! empty( $meta['plugin'] ) ? $meta['plugin'] : $na;
756 + }
757 + $data['plugin'] = $name;
758 + break;
759 + default:
760 + break;
761 + }
762 + if ( ! empty( $data ) ) {
763 + $formatted_title = Log_Changes_Logs_Helper::get_changes_log_title( $record->log_type_id, $data, 'object' );
764 + if ( ! empty( $formatted_title ) ) {
765 + return $formatted_title;
766 + }
767 + }
768 + return $title;
769 + }
671 770
672 - $class = array( 'manage-' . $column_key . '-column' );
673 - $attr = '';
674 - if ( ! isset( $def_columns[ $column_key ] ) ) {
675 - $class[] = 'extra-column';
676 - $attr = 'cell-cls="' . esc_html( "collapsing $column_key column-$column_key" ) . '"';
677 - }
771 + /**
772 + * Returns the label for a context.
773 + *
774 + * @param string $title Current title.
775 + * @param string $context Log context.
776 + * @param string $connector Log connector.
777 + * @return string
778 + */
779 + public function get_context_title( $title, $context, $connector ) {
780 + $context_title = '';
678 781
679 - if ( ! isset( $sortable[ $column_key ] ) ) {
680 - $class[] = 'no-sort';
681 - }
782 + if ( in_array( $context, array( 'plugin', 'theme' ) ) ) {
783 + $title = preg_replace( '/( ?(plugin|theme|translation))$/i', '', $title );
784 + $title = trim( $title );
785 + }
682 786
683 - $tag = 'th';
684 - $id = "id='$column_key'";
787 + if ( 'plugin' === $context ) {
788 + $context_title = esc_html__( 'Plugin', 'mainwp' );
789 + } elseif ( 'theme' === $context ) {
790 + $context_title = esc_html__( 'Theme', 'mainwp' );
791 + } elseif ( 'translation' === $context ) {
792 + $context_title = esc_html__( 'Translation', 'mainwp' );
793 + } elseif ( 'core' === $context ) {
794 + $context_title = esc_html__( 'WordPress', 'mainwp' );
795 + } elseif ( 'posts' === $connector ) {
796 + if ( 'post' === $context ) {
797 + $context_title = esc_html__( 'Post', 'mainwp' );
798 + } elseif ( 'page' === $context ) {
799 + $context_title = esc_html__( 'Page', 'mainwp' );
800 + } else {
801 + $context_title = esc_html__( 'Custom Post', 'mainwp' );
802 + }
803 + } elseif ( 'clients' === $context ) {
804 + $context_title = esc_html__( 'Client', 'mainwp' );
805 + } elseif ( 'users' === $context ) {
806 + $context_title = esc_html__( 'User', 'mainwp' );
807 + }
685 808
686 - if ( ! empty( $class ) ) {
687 - $class = "class='" . join( ' ', $class ) . "'";
688 - }
809 + if ( ! empty( $context_title ) ) {
810 + $title .= ' ' . $context_title;
811 + }
689 812
690 - echo "<$tag $id $class $attr>$column_display_name</$tag>"; // phpcs:ignore WordPress.Security.EscapeOutput
691 - }
692 - }
813 + return $title;
814 + }
693 815
694 - /**
695 - * Get column info.
696 - */
697 - protected function get_column_info() {
816 + /**
817 + * Parse changes logs object title.
818 + *
819 + * @param object $record Log record object.
820 + * @return string
821 + */
822 + public function get_changes_object_title( $record ) {
823 + $title = esc_html( ucwords( str_replace( '-', ' ', $record->context ) ) );
824 + $title = $this->get_changes_formatted_object_title( $title, $record );
825 + return $title;
826 + }
698 827
699 - if ( isset( $this->column_headers ) && is_array( $this->column_headers ) ) {
700 - $column_headers = array( array(), array(), array(), $this->get_default_primary_column_name() );
701 - foreach ( $this->column_headers as $key => $value ) {
702 - $column_headers[ $key ] = $value;
703 - }
828 + /**
829 + * Html output if no Child Sites are connected.
830 + */
831 + public function no_items() {
832 + MainWP_UI::render_empty_element_placeholder( __( 'No Activity Logged Yet', 'mainwp' ), __( 'Site actions and updates will appear here once activity is detected.', 'mainwp' ), '<em data-emoji=":calendar_spiral:" class="medium"></em>' );
833 + }
704 834
705 - return $column_headers;
706 - }
835 + /**
836 + * Method has_items().
837 + *
838 + * Verify if items exist.
839 + */
840 + public function has_items() {
841 + return ! empty( $this->items );
842 + }
707 843
708 - $columns = $this->get_columns();
844 + /**
845 + * Get last query found rows
846 + *
847 + * @return integer
848 + */
849 + public function get_total_found_rows() {
850 + return $this->total_items;
851 + }
709 852
710 - $sortable_columns = $this->get_sortable_columns();
853 + /**
854 + * Prepare the items to be listed.
855 + *
856 + * @param bool $with_prev_data To get previous data.
857 + * @param array $insights_filters Required: Insights filters.
858 + */
859 + public function prepare_items( $with_prev_data, $insights_filters ) { //phpcs:ignore -- NOSONAR - complex method.
711 860
712 - $_sortable = $sortable_columns;
861 + $req_orderby = '';
862 + $req_order = null;
713 863
714 - $sortable = array();
715 - foreach ( $_sortable as $id => $data ) {
716 - if ( empty( $data ) ) {
717 - continue;
718 - }
864 + // phpcs:disable WordPress.Security.NonceVerification
865 + if ( isset( $_REQUEST['order'] ) ) {
866 + $order_values = MainWP_Utility::instance()->get_table_orders( $_REQUEST );
867 + $req_orderby = $order_values['orderby'];
868 + $req_order = $order_values['order'];
869 + }
719 870
720 - $data = (array) $data;
721 - if ( ! isset( $data[1] ) ) {
722 - $data[1] = false;
723 - }
871 + $filter_dtsstart = '';
872 + $filter_dtsstop = '';
873 + $array_clients_ids = array();
874 + $array_groups_ids = array();
875 + $array_usersfilter_sites_ids = array();
724 876
725 - $sortable[ $id ] = $data;
726 - }
877 + $sources_conds = '';
878 + $array_sites_ids = array();
879 + $array_events_list = array();
727 880
728 - $primary = $this->get_default_primary_column_name();
729 - $this->column_headers = array( $columns, $sortable, $primary );
881 + extract( $insights_filters ); //phpcs:ignore -- ok.
730 882
731 - return $this->column_headers;
732 - }
883 + if ( ! empty( $filter_dtsstart ) && ! empty( $filter_dtsstop ) && ! is_numeric( $filter_dtsstart ) && ! is_numeric( $filter_dtsstop ) ) { // after extract.
884 + // to fix string of date.
885 + $filter_dtsstart = gmdate( 'Y-m-d', strtotime( $filter_dtsstart ) );
886 + $filter_dtsstop = gmdate( 'Y-m-d', strtotime( $filter_dtsstop ) );
887 + }
888 + // phpcs:enable WordPress.Security.NonceVerification
733 889
890 + // phpcs:disable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
891 + $perPage = isset( $_REQUEST['length'] ) ? intval( $_REQUEST['length'] ) : false;
734 892
735 - /**
736 - * Get table rows.
737 - *
738 - * Optimize for shared hosting or big networks.
739 - *
740 - * @return array Rows html.
741 - */
742 - public function ajax_get_datatable_rows() {
893 + if ( 'widget-overview' === $this->table_id_prefix && ( false === $perPage || -1 === (int) $perPage ) ) {
894 + $perPage = 25;
895 + }
743 896
744 - $all_rows = array();
745 - $info_rows = array();
897 + if ( -1 === (int) $perPage || empty( $perPage ) ) {
898 + $perPage = 9999999;
899 + }
900 + $start = isset( $_REQUEST['start'] ) ? intval( $_REQUEST['start'] ) : 0;
746 901
747 - if ( $this->items ) {
748 - foreach ( $this->items as $log ) {
749 - $rw_classes = 'log-item mainwp-log-item-' . intval( $log->log_id );
902 + $search = isset( $_REQUEST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search']['value'] ) ) : '';
750 903
751 - $info_item = array(
752 - 'rowClass' => esc_html( $rw_classes ),
753 - 'log_id' => $log->log_id,
754 - 'site_id' => ! empty( $log->site_id ) ? $log->site_id : 0,
755 - 'created' => $log->created,
756 - 'state' => is_null( $log->state ) ? - 1 : $log->state,
757 - );
904 + $recent_number = isset( $_REQUEST['recent_number'] ) ? intval( $_REQUEST['recent_number'] ) : 0;
758 905
759 - $columns = $this->get_columns();
906 + $now = time();
760 907
761 - $cols_data = array();
908 + // Get last 24 hours items.
909 + if ( 'widget-overview' === $this->table_id_prefix ) {
910 + if ( empty( $filter_dtsstart ) && empty( $filter_dtsstop ) ) {
911 + $filter_dtsstart = $now - DAY_IN_SECONDS;
912 + $filter_dtsstop = $now;
913 + }
914 + } else {
915 + $filter_dtsstart = ! empty( $filter_dtsstart ) ? strtotime( $filter_dtsstart . ' 00:00:00' ) : '';
916 + $filter_dtsstop = ! empty( $filter_dtsstop ) ? strtotime( $filter_dtsstop . ' 23:59:59' ) : '';
917 + }
762 918
763 - foreach ( $columns as $column_name => $column_display_name ) {
764 - ob_start();
765 - echo $this->column_default( $log, $column_name ); // phpcs:ignore WordPress.Security.EscapeOutput
766 - $cols_data[ $column_name ] = ob_get_clean();
767 - }
768 - $all_rows[] = $cols_data;
769 - $info_rows[] = $info_item;
770 - }
771 - }
772 - return array(
773 - 'data' => $all_rows,
774 - 'recordsTotal' => $this->total_items,
775 - 'recordsFiltered' => $this->total_items,
776 - 'rowsInfo' => $info_rows,
777 - );
778 - }
919 + // phpcs:enable WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
920 +
921 + $args = array(
922 + 'order' => ( 'asc' === $req_order ) ? 'asc' : 'desc',
923 + 'orderby' => $req_orderby,
924 + 'start' => $start,
925 + 'recent_number' => $recent_number,
926 + 'search' => $search,
927 + 'groups_ids' => $array_groups_ids,
928 + 'client_ids' => $array_clients_ids,
929 + 'usersfilter_sites_ids' => $array_usersfilter_sites_ids, // format: userid-siteid, siteid = 0 => dashboard user.
930 + 'timestart' => $filter_dtsstart,
931 + 'timestop' => $filter_dtsstop,
932 + 'dismiss' => 0,
933 + 'view' => 'events_list',
934 + 'wpid' => ! empty( $insights_filters['wpid'] ) ? $insights_filters['wpid'] : 0, // int or array of site ids.
935 + 'sources_conds' => $sources_conds,
936 + 'sites_ids' => $array_sites_ids,
937 + 'events' => $array_events_list,
938 + );
939 +
940 + if ( isset( $_REQUEST['optimize_table'] ) && 1 === intval( $_REQUEST['optimize_table'] ) ) { //phpcs:ignore --ok.
941 + $args['optimize'] = 1;
942 + $args['optimize_with_meta'] = 1;
943 + }
944 +
945 + $args['records_per_page'] = $perPage;
946 + $args['dev_log_query'] = 0; // 1 for dev logs.
947 +
948 + if ( 'widget-overview' === $this->table_id_prefix ) {
949 + $args['optimize'] = 1;
950 + $args['optimize_with_meta'] = 1;
951 + $args['not_count'] = true;
952 + $args['optimize_has_more'] = true;
953 + } else {
954 + $args['with_all_logs_meta'] = 1; // so it will enable optimize_with_meta too.
955 + }
956 +
957 + $this->items = $this->manager->db->get_records( $args );
958 + $this->total_items = $this->manager->db->get_found_records_count(); // get this value for recent events request only.
959 + $this->sites_opts = $this->manager->db->get_logs_sites_opts();
960 + $this->items_extra_data = $this->manager->db->get_logs_extra_data();
961 +
962 + $this->items_prev = array();
963 + if ( $with_prev_data && ! empty( $args['timestart'] ) && ! empty( $args['timestop'] ) && $args['timestart'] < $args['timestop'] ) {
964 + $timestart_prev = $args['timestart'] - ( $args['timestop'] - $args['timestart'] );
965 + $timestop_prev = $args['timestart'];
966 + $args['timestart'] = $timestart_prev;
967 + $args['timestop'] = $timestop_prev;
968 + $this->items_prev = $this->manager->db->get_records( $args );
969 + }
970 + }
971 +
972 +
973 + /**
974 + * Display the table.
975 + */
976 + public function display() {
977 +
978 + $sites_per_page = get_option( 'mainwp_default_manage_insights_events_per_page', 25 );
979 +
980 + $sites_per_page = intval( $sites_per_page );
981 +
982 + $pages_length = array(
983 + 25 => '25',
984 + 10 => '10',
985 + 50 => '50',
986 + 100 => '100',
987 + 300 => '300',
988 + );
989 +
990 + if ( ! isset( $pages_length[ $sites_per_page ] ) ) {
991 + $pages_length = $pages_length + array( $sites_per_page => $sites_per_page );
992 + }
993 +
994 + ksort( $pages_length );
995 +
996 + if ( isset( $pages_length[-1] ) ) {
997 + unset( $pages_length[-1] );
998 + }
999 +
1000 + // @since version 5.5.
1001 + $pages_length = apply_filters( 'mainwp_site_changes_table_pages_length', $pages_length, $this->table_id_prefix );
1002 +
1003 + if ( 'widget-overview' === $this->table_id_prefix ) {
1004 + $pages_length = array(
1005 + 25 => '25',
1006 + );
1007 + $sites_per_page = 25;
1008 + }
1009 +
1010 + $pagelength_val = implode( ',', array_keys( $pages_length ) );
1011 + $pagelength_title = implode( ',', array_values( $pages_length ) );
1012 +
1013 + $ajaxaction = 'mainwp_module_log_manage_events_display_rows';
1014 + if ( 'widget-insight' === $this->table_id_prefix ) {
1015 + $ajaxaction = 'mainwp_module_log_widget_insights_display_rows';
1016 + } elseif ( 'widget-overview' === $this->table_id_prefix ) {
1017 + $ajaxaction = 'mainwp_module_log_widget_events_overview_display_rows';
1018 + }
1019 +
1020 + $events_tbl_id = 'mainwp-module-log-records-table';
1021 + if ( ! empty( $this->table_id_prefix ) ) {
1022 + $events_tbl_id .= '-' . esc_attr( $this->table_id_prefix );
1023 + }
1024 +
1025 + if ( 'manage-events' === $this->table_id_prefix ) {
1026 + ?>
1027 + <div class="ui padded segment">
1028 + <?php
1029 + }
1030 + ?>
1031 + <div id="mainwp-module-log-records-table-container" style="opacity:0;">
1032 + <table id="<?php echo esc_attr( $events_tbl_id ); ?>" style="width:100%" class="ui single line <?php echo 'manage-events' === $this->table_id_prefix ? 'selectable' : ''; ?> unstackable table mainwp-with-preview-table">
1033 + <thead>
1034 + <tr><?php $this->print_column_headers( true ); ?></tr>
1035 + </thead>
1036 + </table>
1037 + </div>
1038 + <?php
1039 + if ( 'manage-events' === $this->table_id_prefix ) {
1040 + ?>
1041 + </div>
1042 + <?php
1043 + }
1044 + if ( 'widget-overview' !== $this->table_id_prefix ) {
1045 + ?>
1046 + <div id="mainwp-loading-sites">
1047 + <div class="ui active page dimmer">
1048 + <div class="ui double text loader"><?php esc_html_e( 'Loading...', 'mainwp' ); ?></div>
1049 + </div>
1050 + </div>
1051 + <?php
1052 + }
1053 + $table_features = array(
1054 + 'searching' => 'true',
1055 + 'paging' => 'true',
1056 + 'pagingType' => 'full_numbers',
1057 + 'info' => 'true',
1058 + 'colReorder' => '{columns:":not(.check-column):not(:last-child)"}',
1059 + 'stateSave' => 'true',
1060 + 'stateDuration' => '60 * 60 * 24 * 30',
1061 + 'order' => '[]',
1062 + 'scrollX' => 'true',
1063 + 'responsive' => 'true',
1064 + 'fixedColumns' => '',
1065 + 'searchDelay' => 350,
1066 + 'numbers' => 7,
1067 + );
1068 +
1069 + // Fix for widget state save overview table.
1070 + if ( 'widget-overview' === $this->table_id_prefix ) {
1071 + $table_features['stateSave'] = 'false';
1072 + $table_features['searching'] = 'false';
1073 + $table_features['paging'] = 'true';
1074 + $table_features['info'] = 'false';
1075 + $table_features['numbers'] = 3;
1076 + }
1077 +
1078 + ?>
1079 +
1080 + <script type="text/javascript">
1081 + var responsive = <?php echo esc_js( $table_features['responsive'] ); ?>;
1082 + if( jQuery( window ).width() > 1140 ) {
1083 + responsive = false;
1084 + }
1085 + var $module_log_table = null;
1086 + jQuery( document ).ready( function( $ ) {
1087 + const manage_tbl_id = '#<?php echo esc_js( $events_tbl_id ); ?>';
1088 + const ajax_action = '<?php echo esc_js( $ajaxaction ); ?>';
1089 +
1090 + let widgetViewSource = '';
1091 +
1092 + if( jQuery('#widget-sites-changes-dropdown-selector').length ){
1093 + widgetViewSource = mainwp_ui_state_load('sites-changes-widget');
1094 + widgetViewSource = ['wp-admin', 'dashboard', '' ].includes(widgetViewSource) ? widgetViewSource : 'wp-admin';
1095 + }
1096 +
1097 + try {
1098 +
1099 + const nextButton = document.createElement('a');
1100 + nextButton.href = '#';
1101 + nextButton.className = 'ui tiny basic button';
1102 + nextButton.innerHTML = '<?php echo esc_js( __( 'More', 'mainwp' ) ); ?>';
1103 +
1104 + //jQuery( '#mainwp-sites-table-loader' ).hide();
1105 + $module_log_table = jQuery( manage_tbl_id ).on( 'processing.dt', function ( e, settings, processing ) {
1106 + if(jQuery( '#mainwp-loading-sites' ).length){
1107 + jQuery( '#mainwp-loading-sites' ).css( 'display', processing ? 'block' : 'none' );
1108 + }
1109 + if (!processing) {
1110 + let tb = jQuery( manage_tbl_id );
1111 + tb.find( 'th[cell-cls]' ).each( function(){
1112 + let ceIdx = this.cellIndex;
1113 + let cls = jQuery( this ).attr( 'cell-cls' );
1114 + jQuery( manage_tbl_id + ' tr' ).each(function(){
1115 + jQuery(this).find( 'td:eq(' + ceIdx + ')' ).addClass(cls);
1116 + } );
1117 + } );
1118 + $( manage_tbl_id + ' .ui.dropdown' ).dropdown();
1119 + $( manage_tbl_id + ' .ui.checkbox' ).checkbox();
1120 + }
1121 + } ).DataTable( {
1122 + "ajax": {
1123 + "url": ajaxurl,
1124 + "type": "POST",
1125 + "data": function ( d ) {
1126 + let data = mainwp_secure_data( {
1127 + action: ajax_action,
1128 + range: $( '#mainwp-module-log-filter-ranges').length ? $( '#mainwp-module-log-filter-ranges').dropdown('get value') : '',
1129 + group: $( '#mainwp-module-log-filter-groups').length ? $( '#mainwp-module-log-filter-groups').dropdown('get value') : '',
1130 + client: $( '#mainwp-module-log-filter-clients').length ? $( '#mainwp-module-log-filter-clients').dropdown('get value') : 0,
1131 + user: $( '#mainwp-module-log-filter-users').length ? $( '#mainwp-module-log-filter-users').dropdown('get value') : 0,
1132 + dtsstart: $('#mainwp-module-log-filter-dtsstart input[type=text]').length ? $('#mainwp-module-log-filter-dtsstart input[type=text]').val() : '',
1133 + dtsstop: $('#mainwp-module-log-filter-dtsstop input[type=text]').length ? $('#mainwp-module-log-filter-dtsstop input[type=text]').val() : '',
1134 + current_client_id: $( '#mainwp-widget-filter-current-client-id').length ? $( '#mainwp-widget-filter-current-client-id').val() : 0,
1135 + current_site_id: $( '#mainwp-widget-filter-current-site-id').length ? $( '#mainwp-widget-filter-current-site-id').val() : 0,
1136 + } );
1137 +
1138 + <?php if ( $this->optimize_table ) { ?>
1139 + data.optimize_table = 1;
1140 + <?php } ?>
1141 +
1142 + if('mainwp_module_log_manage_events_display_rows' === ajax_action ){
1143 + data.source = $( '#mainwp-module-log-filter-source').length ? $( '#mainwp-module-log-filter-source').dropdown('get value') : '';
1144 + data.sites = $( '#mainwp-module-log-filter-sites').length ? $( '#mainwp-module-log-filter-sites').dropdown('get value') : '';
1145 + data.events = $( '#mainwp-module-log-filter-events').length ? $( '#mainwp-module-log-filter-events').dropdown('get value') : '';
1146 + } else {
1147 + if( 'mainwp_module_log_widget_events_overview_display_rows' === ajax_action ){
1148 + data.source = widgetViewSource;
1149 + } else if( 'mainwp_module_log_widget_insights_display_rows' === ajax_action ) {
1150 + // set recent number for none-manage-events table.
1151 + data.recent_number = $( '#mainwp-widget-filter-events-limit').length ? $( '#mainwp-widget-filter-events-limit').val() : 100;
1152 + }
1153 + }
1154 +
1155 + if('mainwp_module_log_manage_events_display_rows' === ajax_action ){
1156 + if( ( data.source == '' || data.source == 'allsource' ) &&
1157 + ( data.events == '' || data.events == 'allevents' ) &&
1158 + ( data.sites == '' || data.sites == 'allsites' ) &&
1159 + ( data.group == '' || data.group == 'alltags' ) &&
1160 + ( data.client == '' || data.client == 'allclients' ) &&
1161 + ( data.user == '' || data.user == 'allusers' ) &&
1162 + data.range == 'thismonth' &&
1163 + data.current_client_id == '' &&
1164 + data.current_site_id == ''
1165 + ){
1166 + jQuery('#mainwp-module-log-filters-row').fadeOut(300);
1167 + } else{
1168 + jQuery('#mainwp-module-log-filters-row').fadeIn(300);
1169 + }
1170 + }
1171 +
1172 + return $.extend( {}, d, data );
1173 + },
1174 + "dataSrc": function ( json ) {
1175 + for ( let i=0, ien=json.data.length ; i < ien ; i++ ) {
1176 + json.data[i].rowClass = json.rowsInfo[i].rowClass;
1177 + json.data[i].log_id = json.rowsInfo[i].log_id;
1178 + json.data[i].created_sort = json.rowsInfo[i].created;
1179 + json.data[i].state_sort = json.rowsInfo[i].state;
1180 + }
1181 +
1182 + <?php if ( 'widget-overview' === $this->table_id_prefix ) { ?>
1183 + if (json?.has_more) {
1184 + nextButton.classList.remove('disabled');
1185 + nextButton.removeAttribute('aria-disabled');
1186 + nextButton.removeAttribute('tabindex');
1187 + nextButton.setAttribute('href', '#');
1188 + } else {
1189 + nextButton.classList.add('disabled');
1190 + nextButton.setAttribute('aria-disabled', 'true');
1191 + nextButton.setAttribute('tabindex', '-1');
1192 + nextButton.removeAttribute('href');
1193 + }
1194 + <?php } ?>
1195 + return json.data;
1196 + }
1197 + },
1198 + "layout": {
1199 + <?php
1200 + if ( 'widget-overview' === $this->table_id_prefix ) {
1201 + ?>
1202 + "topStart": null,
1203 + "bottomEnd": nextButton
1204 + <?php
1205 + } else {
1206 + ?>
1207 + "bottomEnd": {
1208 + "paging": {
1209 + "numbers": <?php echo intval( $table_features['numbers'] ); ?>
1210 + }
1211 + }
1212 + <?php
1213 + }
1214 + ?>
1215 + },
1216 + 'responsive': responsive,
1217 + 'searching' : <?php echo esc_js( $table_features['searching'] ); ?>,
1218 + "paging" : <?php echo esc_js( $table_features['paging'] ); ?>,
1219 + "pagingType" : "<?php echo esc_js( $table_features['pagingType'] ); ?>",
1220 + "info" : <?php echo esc_js( $table_features['info'] ); ?>,
1221 + "colReorder" : <?php echo $table_features['colReorder']; // phpcs:ignore -- specical chars. ?>,
1222 + "scrollX" : <?php echo esc_js( $table_features['scrollX'] ); ?>,
1223 + "stateSave" : <?php echo esc_js( $table_features['stateSave'] ); ?>,
1224 + "stateDuration" : <?php echo esc_js( $table_features['stateDuration'] ); ?>,
1225 + "order" : <?php echo $table_features['order']; // phpcs:ignore -- specical chars. ?>,
1226 + "fixedColumns" : <?php echo ! empty( $table_features['fixedColumns'] ) ? esc_js( $table_features['fixedColumns'] ) : '""'; ?>,
1227 + "lengthMenu" : [ [<?php echo esc_js( $pagelength_val ); ?>], [<?php echo esc_js( $pagelength_title ); ?>] ],
1228 + "serverSide": true,
1229 + "pageLength": <?php echo intval( $sites_per_page ); ?>,
1230 + "columnDefs": <?php echo wp_json_encode( $this->get_columns_defines() ); ?>,
1231 + "columns": <?php echo wp_json_encode( $this->get_columns_init() ); ?>,
1232 + "language": {
1233 + "emptyTable": "<?php echo 'widget-overview' === $this->table_id_prefix ? esc_html__( 'No matching activity was found in the last 24 hours.', 'mainwp' ) : esc_html__( 'No events found.', 'mainwp' ); ?>"
1234 + },
1235 + "drawCallback": function( settings ) {
1236 + this.api().tables().body().to$().attr( 'id', 'mainwp-module-log-records-body-table' );
1237 + jQuery( '#mainwp-module-log-records-table-container' ).css( 'opacity', '1' );
1238 + mainwp_datatable_fix_menu_overflow(manage_tbl_id);
1239 + if ( typeof mainwp_preview_init_event !== "undefined" ) {
1240 + mainwp_preview_init_event();
1241 + }
1242 + //jQuery( '#mainwp-sites-table-loader' ).hide();
1243 + if ( jQuery('#mainwp-module-log-records-body-table td.dt-empty').length > 0 && jQuery('#sites-table-count-empty').length ){
1244 + jQuery('#mainwp-module-log-records-body-table td.dt-empty').html(jQuery('#sites-table-count-empty').html());
1245 + }
1246 + if( 'manage-events' === '<?php echo esc_js( $this->table_id_prefix ); ?>' ){
1247 + setTimeout(() => {
1248 + jQuery(manage_tbl_id + ' .ui.checkbox').checkbox();
1249 + mainwp_datatable_fix_menu_overflow(manage_tbl_id);
1250 + mainwp_table_check_columns_init(manage_tbl_id);
1251 + if (typeof mainwp_sites_changes_update_dismiss_button_state !== 'undefined') {
1252 + mainwp_sites_changes_update_dismiss_button_state();
1253 + }
1254 + }, 1000);
1255 + }
1256 + },
1257 + "initComplete": function( settings, json ) {
1258 + if( 'widget-overview' === '<?php echo esc_js( $this->table_id_prefix ); ?>' ){
1259 + setTimeout(() => {
1260 + jQuery('#mainwp-module-log-records-table-container div.dt-search #dt-search-1').val('');// to fix issue autofill for chrome.
1261 + }, 100);
1262 + }
1263 + },
1264 + rowCallback: function (row, data) {
1265 + jQuery( row ).addClass(data.rowClass);
1266 + jQuery( row ).attr( 'id', "log-row-" + data.log_id );
1267 + jQuery( row ).attr( 'log-id', data.log_id );
1268 + jQuery( row ).find('.mainwp-date-cell').attr('data-sort', data.created_sort );
1269 + jQuery( row ).find('.mainwp-state-cell').attr('data-sort', data.state_sort );
1270 + },
1271 + stateSaveParams: function (settings, data) {
1272 + data._mwpv = mainwpParams.mainwpVersion || 'dev';
1273 + },
1274 + stateLoadParams: function (settings, data) {
1275 + if ((mainwpParams.mainwpVersion || 'dev') !== data._mwpv) return false;
1276 + },
1277 + search: { regex: false, smart: false },
1278 + orderMulti: false,
1279 + searchDelay: <?php echo intval( $table_features['searchDelay'] ); ?>
1280 + <?php
1281 + if ( 'manage-events' === $this->table_id_prefix ) {
1282 + echo ",select: {
1283 + items: 'row',
1284 + style: 'multi+shift',
1285 + selector: 'tr>td.check-column'
1286 + }"; // phpcs:ignore -- NOSONAR -- ok.
1287 + }
1288 + ?>
1289 + })
1290 +
1291 + if( 'manage-events' === '<?php echo esc_js( $this->table_id_prefix ); ?>' ){
1292 + $module_log_table.on('select', function (e, dt, type, indexes) {
1293 + if( 'row' == type ){
1294 + dt.rows(indexes)
1295 + .nodes()
1296 + .to$().find('td.check-column .ui.checkbox' ).checkbox('set checked');
1297 + }
1298 + }).on('deselect', function (e, dt, type, indexes) {
1299 + if( 'row' == type ){
1300 + dt.rows(indexes)
1301 + .nodes()
1302 + .to$().find('td.check-column .ui.checkbox' ).checkbox('set unchecked');
1303 + }
1304 + });
1305 + }
1306 +
1307 +
1308 + nextButton.addEventListener('click', function (e) {
1309 + e.preventDefault();
1310 +
1311 + if (nextButton.classList.contains('disabled')) {
1312 + return;
1313 + }
1314 + $module_log_table.page('next').draw('page');
1315 + });
1316 +
1317 + } catch(err) {
1318 + // to fix js error.
1319 + console.log(err);
1320 + }
1321 +
1322 + // Delay dropdown initialization to prevent it from being overwritten.
1323 + setTimeout(() => {
1324 + jQuery( '#widget-sites-changes-dropdown-selector' ).dropdown( {
1325 + onChange: function( value ) {
1326 + mainwp_ui_state_save('sites-changes-widget', value);
1327 + if(widgetViewSource !== value ){
1328 + widgetViewSource = value;
1329 + $module_log_table.ajax.reload();
1330 + }
1331 + }
1332 + } ).dropdown("set selected", widgetViewSource);
1333 + }, 1000);
1334 +
1335 +
1336 + mainwp_module_log_overview_content_filter = function() {
1337 + if(jQuery( '#mainwp-common-filter-segments-model-name').length && 'manage-events' === jQuery( '#mainwp-common-filter-segments-model-name').val() ){
1338 + mainwp_module_log_manage_events_filter();
1339 + return;
1340 + }
1341 + let range = jQuery( '#mainwp-module-log-filter-ranges').dropdown('get value');
1342 + let group = jQuery( '#mainwp-module-log-filter-groups').dropdown('get value');
1343 + let client = jQuery( '#mainwp-module-log-filter-clients').dropdown('get value');
1344 + let user = jQuery( '#mainwp-module-log-filter-users').dropdown('get value');
1345 + let dtsstart = jQuery('#mainwp-module-log-filter-dtsstart input[type=text]').val();
1346 + let dtsstop = jQuery('#mainwp-module-log-filter-dtsstop input[type=text]').val();
1347 + let params = '';
1348 + params += '&range=' + encodeURIComponent( range );
1349 + params += '&group=' + encodeURIComponent( group );
1350 + params += '&client=' + encodeURIComponent( client );
1351 + params += '&user=' + encodeURIComponent( user );
1352 + params += '&dtsstart=' + encodeURIComponent( dtsstart );
1353 + params += '&dtsstop=' + encodeURIComponent( dtsstop );
1354 + params += '&_insights_opennonce=' + mainwpParams._wpnonce;
1355 + window.location = 'admin.php?page=InsightsOverview' + params;
1356 + return false;
1357 + };
1358 + mainwp_module_log_overview_content_reset_filters = function(resetObj) {
1359 + try {
1360 + jQuery( '#mainwp-module-log-filter-ranges').dropdown('set selected', 'thismonth');
1361 + jQuery( '#mainwp-module-log-filter-groups').dropdown('clear');
1362 + jQuery( '#mainwp-module-log-filter-clients').dropdown('clear');
1363 + jQuery( '#mainwp-module-log-filter-users').dropdown('clear');
1364 + jQuery('#mainwp-module-log-filter-dtsstart input[type=text]').val('');
1365 + jQuery('#mainwp-module-log-filter-dtsstop input[type=text]').val('');
1366 + jQuery(resetObj).attr('disabled', 'disabled');
1367 + mainwp_module_log_overview_content_filter();
1368 + } catch(err) {
1369 + // to fix js error.
1370 + console.log(err);
1371 + }
1372 + };
1373 + _init_manage_events_screen();
1374 + } );
1375 +
1376 + _init_manage_events_screen = function() {
1377 + jQuery( '#mainwp-manage-events-screen-options-modal input[type=checkbox][id^="mainwp_show_column_"]' ).each( function() {
1378 + let check_id = jQuery( this ).attr( 'id' );
1379 + col_id = check_id.replace( "mainwp_show_column_", "" );
1380 + try {
1381 + $module_log_table.column( '#' + col_id ).visible( jQuery(this).is( ':checked' ) );
1382 + } catch(err) {
1383 + // to fix js error.
1384 + }
1385 + } );
1386 + };
1387 +
1388 + mainwp_manage_events_screen_options = function () {
1389 + jQuery( '#mainwp-manage-events-screen-options-modal' ).modal( {
1390 + allowMultiple: true,
1391 + onHide: function () {
1392 + //ok.
1393 + }
1394 + } ).modal( 'show' );
1395 +
1396 + jQuery( '#manage-events-screen-options-form' ).submit( function() {
1397 + if ( jQuery('input[name=reset_manage_events_columns_order]').attr('value') == 1 ) {
1398 + $module_log_table.colReorder.reset();
1399 + }
1400 + jQuery( '#mainwp-manage-events-screen-options-modal' ).modal( 'hide' );
1401 + } );
1402 + return false;
1403 + };
1404 +
1405 + </script>
1406 + <?php
1407 + }
1408 +
1409 + /**
1410 + * Get the column count.
1411 + *
1412 + * @return int Column Count.
1413 + */
1414 + public function get_column_count() {
1415 + list( $columns ) = $this->get_column_info();
1416 + return count( $columns );
1417 + }
1418 +
1419 + /**
1420 + * Echo the column headers.
1421 + *
1422 + * @param bool $top Top header.
1423 + * @return void
1424 + */
1425 + public function print_column_headers( $top ) {
1426 + list( $columns, $sortable ) = $this->get_column_info();
1427 +
1428 + $def_columns = $this->get_default_columns();
1429 + $def_columns['site_actions'] = '';
1430 +
1431 + if ( ! empty( $columns['cb'] ) ) {
1432 + $columns['cb'] = '<div class="ui checkbox"><input id="' . ( $top ? 'cb-select-all-top' : 'cb-select-all-bottom' ) . '" type="checkbox" aria-label="Select all clients." /></div>';
1433 + }
1434 +
1435 + foreach ( $columns as $column_event_key => $column_display_name ) {
1436 +
1437 + $class = array( 'manage-' . $column_event_key . '-column' );
1438 + $attr = '';
1439 + if ( ! isset( $def_columns[ $column_event_key ] ) ) {
1440 + $class[] = 'extra-column';
1441 + $attr = 'cell-cls="' . esc_html( "collapsing $column_event_key column-$column_event_key" ) . '"';
1442 + }
1443 +
1444 + if ( ! isset( $sortable[ $column_event_key ] ) ) {
1445 + $class[] = 'no-sort';
1446 + }
1447 +
1448 + if ( 'cb' === $column_event_key ) {
1449 + $class[] = 'check-column';
1450 + $class[] = 'collapsing';
1451 + }
1452 +
1453 + $tag = 'th';
1454 + $id = "id='$column_event_key'";
1455 +
1456 + if ( ! empty( $class ) ) {
1457 + $class = "class='" . join( ' ', $class ) . "'";
1458 + }
1459 +
1460 + echo "<$tag $id $class $attr>$column_display_name</$tag>"; // phpcs:ignore WordPress.Security.EscapeOutput
1461 + }
1462 + }
1463 +
1464 + /**
1465 + * Get column info.
1466 + */
1467 + protected function get_column_info() {
1468 +
1469 + if ( isset( $this->column_headers ) && is_array( $this->column_headers ) ) {
1470 + $column_headers = array( array(), array(), array(), $this->get_default_primary_column_name() );
1471 + foreach ( $this->column_headers as $key => $value ) {
1472 + $column_headers[ $key ] = $value;
1473 + }
1474 +
1475 + return $column_headers;
1476 + }
1477 +
1478 + $columns = $this->get_columns();
1479 +
1480 + $sortable_columns = $this->get_sortable_columns();
1481 +
1482 + $_sortable = $sortable_columns;
1483 +
1484 + $sortable = array();
1485 + foreach ( $_sortable as $id => $data ) {
1486 + if ( empty( $data ) ) {
1487 + continue;
1488 + }
1489 +
1490 + $data = (array) $data;
1491 + if ( ! isset( $data[1] ) ) {
1492 + $data[1] = false;
1493 + }
1494 +
1495 + $sortable[ $id ] = $data;
1496 + }
1497 +
1498 + $primary = $this->get_default_primary_column_name();
1499 + $this->column_headers = array( $columns, $sortable, $primary );
1500 +
1501 + return $this->column_headers;
1502 + }
1503 +
1504 +
1505 + /**
1506 + * Get table rows.
1507 + *
1508 + * Optimize for shared hosting or big networks.
1509 + *
1510 + * @return array Rows html.
1511 + */
1512 + public function ajax_get_datatable_rows() {
1513 +
1514 + $all_rows = array();
1515 + $info_rows = array();
1516 +
1517 + $columns = $this->get_columns();
1518 +
1519 + if ( $this->items ) {
1520 + foreach ( $this->items as $log ) {
1521 + $created_time = intval( $log->created / 1000000 ); // Seconds.
1522 + $rw_classes = 'log-item mainwp-log-item-' . intval( $log->log_id );
1523 +
1524 + $info_item = array(
1525 + 'rowClass' => esc_html( $rw_classes ),
1526 + 'log_id' => $log->log_id,
1527 + 'site_id' => ! empty( $log->site_id ) ? $log->site_id : 0,
1528 + 'created' => $created_time,
1529 + 'state' => is_null( $log->state ) ? - 1 : $log->state,
1530 + );
1531 + $cols_data = array();
1532 + foreach ( $columns as $column_name => $column_display_name ) {
1533 + ob_start();
1534 + echo $this->column_default( $log, $column_name ); // phpcs:ignore WordPress.Security.EscapeOutput
1535 + $cols_data[ $column_name ] = ob_get_clean();
1536 + }
1537 + $all_rows[] = $cols_data;
1538 + $info_rows[] = $info_item;
1539 + }
1540 + }
1541 + return array(
1542 + 'data' => $all_rows,
1543 + 'recordsTotal' => $this->total_items,
1544 + 'recordsFiltered' => $this->total_items,
1545 + 'rowsInfo' => $info_rows,
1546 + 'has_more' => is_array( $this->items_extra_data ) && ! empty( $this->items_extra_data['has_more'] ) ? true : false,
1547 + );
1548 + }
779 1549 }