activity_log = $activity_log;
$this->query_args = $query_args;
// Set GMT offset.
$timezone = $this->activity_log->settings->get_timezone();
if ( 'utc' === $timezone ) {
$this->gmt_offset_sec = date( 'Z' );
} else {
$this->gmt_offset_sec = get_option( 'gmt_offset' ) * HOUR_IN_SECONDS;
}
// Get MainWP child sites.
$this->mwp_child_sites = $this->activity_log->settings->get_mwp_child_sites();
parent::__construct(
array(
'singular' => 'activity-log',
'plural' => 'activity-logs',
'ajax' => true,
'screen' => 'interval-list',
)
);
}
/**
* Empty View.
*/
public function no_items() {
esc_html_e( 'No events so far.', 'mwp-al-ext' );
}
/**
* Generate the table navigation above or below the table
*
* @param string $which – Nav position.
*/
protected function display_tablenav( $which ) {
if ( 'top' === $which ) {
wp_nonce_field( 'bulk-' . $this->_args['plural'] );
}
?>
extra_tablenav( $which );
$this->pagination( $which );
?>
activity_log->settings->is_infinite_scroll() ) :
// Items-per-page widget.
$per_page = $this->activity_log->settings->get_view_per_page();
$items = array( 5, 10, 15, 30, 50 );
if ( ! in_array( $per_page, $items, true ) ) {
$items[] = $per_page;
}
?>
activity_log->settings->is_infinite_scroll() ) :
?>
activity_log->settings->get_wsal_child_sites();
if ( count( $wsal_child_sites ) > 0 ) :
$current_site = $this->activity_log->settings->get_view_site_id();
?>
id . '" name="' . esc_attr( $this->_args['singular'] ) . '[]" />';
}
/**
* Method: Get default column values.
*
* @param object $item - Column item.
* @param string $column_name - Name of the column.
*/
public function column_default( $item, $column_name ) {
$datetime_format = $this->activity_log->settings->get_date_time_format(); // Get date time format.
$type_username = $this->activity_log->settings->get_type_username(); // Get username type to display.
$mwp_child_sites = $this->mwp_child_sites; // Get MainWP child sites.
if ( ! isset( $this->item_meta[ $item->getId() ] ) ) {
$this->item_meta[ $item->getId() ] = $item->GetMetaArray();
}
switch ( $column_name ) {
case 'site':
$site_id = (string) $item->site_id;
$site_index = array_search( $site_id, array_column( $mwp_child_sites, 'id' ), true );
$html = '';
if ( false !== $site_index && isset( $mwp_child_sites[ $site_index ] ) ) {
$html = '';
$html .= esc_html( $mwp_child_sites[ $site_index ]['name'] );
$html .= '';
} else {
$html = __( 'MainWP Dashboard', 'mwp-al-ext' );
}
return $html;
case 'type':
$code = $this->activity_log->alerts->GetAlert( $item->alert_id );
return '' . str_pad( $item->alert_id, 4, '0', STR_PAD_LEFT ) . ' ';
case 'code':
$code = $this->activity_log->alerts->GetAlert( $item->alert_id );
$code = $code ? $code->code : 0;
$const = (object) array(
'name' => 'E_UNKNOWN',
'value' => 0,
'description' => __( 'Unknown error code.', 'mwp-al-ext' ),
);
$const = $this->activity_log->constants->GetConstantBy( 'value', $code, $const );
if ( 'E_CRITICAL' === $const->name ) {
$const->name = __( 'Critical', 'mwp-al-ext' );
} elseif ( 'E_WARNING' === $const->name ) {
$const->name = __( 'Warning', 'mwp-al-ext' );
} elseif ( 'E_NOTICE' === $const->name ) {
$const->name = __( 'Notification', 'mwp-al-ext' );
}
return '';
case 'crtd':
return $item->created_on ? (
str_replace(
'$$$',
substr( number_format( fmod( $item->created_on + $this->gmt_offset_sec, 1 ), 3 ), 2 ),
date( $datetime_format, $item->created_on + $this->gmt_offset_sec )
)
) : '' . __( 'Unknown', 'mwp-al-ext' ) . '';
case 'user':
$username = $item->GetUsername( $this->item_meta[ $item->getId() ] ); // Get username.
$user_data = $item->get_user_data( $this->item_meta[ $item->getId() ] ); // Get user data.
if ( empty( $user_data ) ) {
$user_data = get_user_by( 'login', $username );
}
// Check if the usernames exists & matches pre-defined cases.
if ( 'Plugin' === $username ) {
$image = '
';
$uhtml = '' . __( 'Plugin', 'mwp-al-ext' ) . '';
$roles = '';
} elseif ( 'Plugins' === $username ) {
$image = '';
$uhtml = '' . __( 'Plugins', 'mwp-al-ext' ) . '';
$roles = '';
} elseif ( 'Website Visitor' === $username ) {
$image = '';
$uhtml = '' . __( 'Website Visitor', 'mwp-al-ext' ) . '';
$roles = '';
} elseif ( 'System' === $username ) {
$image = '';
$uhtml = '' . __( 'System', 'mwp-al-ext' ) . '';
$roles = '';
} elseif ( $username && $user_data ) {
$image = get_avatar( $user_data->user_email, 32 ); // Avatar.
// Checks for display name.
if ( 'display_name' === $type_username && ! empty( $user_data->display_name ) ) {
$display_name = $user_data->display_name;
} elseif (
'first_last_name' === $type_username
&& ( ! empty( $user_data->first_name ) || ! empty( $user_data->last_name ) )
) {
$display_name = $user_data->first_name . ' ' . $user_data->last_name;
} else {
$display_name = $user_data->username;
}
$site_id = (string) $item->site_id;
$site_index = array_search( $site_id, array_column( $mwp_child_sites, 'id' ), true );
$site_url = '#';
if ( false !== $site_index && isset( $mwp_child_sites[ $site_index ] ) ) {
$site_url = $mwp_child_sites[ $site_index ]['url'];
$user_url = add_query_arg( 'user_id', $user_data->user_id, trailingslashit( $site_url ) . 'wp-admin/user-edit.php' );
} else {
$user_url = add_query_arg( 'user_id', $user_data->ID, admin_url( 'user-edit.php' ) );
}
// User html.
$uhtml = '' . esc_html( $display_name ) . '';
$roles = $item->GetUserRoles( $this->item_meta[ $item->getId() ] );
if ( is_array( $roles ) && count( $roles ) ) {
$roles = esc_html( ucwords( implode( ', ', $roles ) ) );
} elseif ( is_string( $roles ) && '' != $roles ) {
$roles = esc_html( ucwords( str_replace( array( '"', '[', ']' ), ' ', $roles ) ) );
} else {
$roles = '' . __( 'Unknown', 'mwp-al-ext' ) . '';
}
} else {
$image = '';
$uhtml = '' . __( 'System', 'mwp-al-ext' ) . '';
$roles = '';
}
return $image . $uhtml . '
' . $roles;
case 'scip':
$scip = $item->GetSourceIP( $this->item_meta[ $item->getId() ] );
if ( is_string( $scip ) ) {
$scip = str_replace( array( '"', '[', ']' ), '', $scip );
}
$oips = array(); // $item->GetOtherIPs();
// If there's no IP...
if ( is_null( $scip ) || '' == $scip ) {
return 'unknown';
}
// If there's only one IP...
$link = 'https://whatismyipaddress.com/ip/' . $scip . '?utm_source=plugin&utm_medium=referral&utm_campaign=WPSAL';
if ( class_exists( 'WSAL_SearchExtension' ) ) {
$tooltip = esc_attr__( 'Show me all activity originating from this IP Address', 'mwp-al-ext' );
if ( count( $oips ) < 2 ) {
return "" . esc_html( $scip ) . '';
}
} else {
if ( count( $oips ) < 2 ) {
return "" . esc_html( $scip ) . '';
}
}
// If there are many IPs...
if ( class_exists( 'WSAL_SearchExtension' ) ) {
$tooltip = esc_attr__( 'Show me all activity originating from this IP Address', 'mwp-al-ext' );
$html = "" . esc_html( $scip ) . ' (more…)';
foreach ( $oips as $ip ) {
if ( $scip != $ip ) {
$html .= '
' . $ip . '
';
}
}
$html .= '
';
return $html;
} else {
$html = "" . esc_html( $scip ) . ' (more…)';
foreach ( $oips as $ip ) {
if ( $scip != $ip ) {
$html .= '
' . $ip . '
';
}
}
$html .= '
';
return $html;
}
case 'mesg':
return '' . $item->GetMessage( array( $this, 'meta_formatter' ), $this->item_meta[ $item->getId() ] ) . '
';
case 'data':
$url_args = array(
'action' => 'metadata_inspector',
'occurrence_id' => $item->id,
'mwp_meta_nonc' => wp_create_nonce( 'mwp-meta-display-' . $item->id ),
'TB_iframe' => 'true',
'width' => '600',
'height' => '550',
);
$url = add_query_arg( $url_args, admin_url( 'admin-ajax.php' ) );
$tooltip = esc_attr__( 'View all details of this change', 'mwp-al-ext' );
return '…';
default:
/* translators: Column Name */
return isset( $item->$column_name ) ? esc_html( $item->$column_name ) : sprintf( esc_html__( 'Column "%s" not found', 'mwp-al-ext' ), $column_name );
}
}
/**
* Method: Get View Columns.
*
* @return array
*/
public function get_columns() {
// Audit log columns.
$cols = array(
'site' => __( 'Site', 'mwp-al-ext' ),
'type' => __( 'Event ID', 'mwp-al-ext' ),
'code' => __( 'Severity', 'mwp-al-ext' ),
'crtd' => __( 'Date', 'mwp-al-ext' ),
'user' => __( 'User', 'mwp-al-ext' ),
'scip' => __( 'Source IP', 'mwp-al-ext' ),
'mesg' => __( 'Message', 'mwp-al-ext' ),
'data' => '',
);
// Get selected columns.
$selected = $this->activity_log->settings->get_columns_selected();
// If selected columns are not empty, then unset default columns.
if ( ! empty( $selected ) ) {
unset( $cols );
$selected = (array) json_decode( $selected );
foreach ( $selected as $key => $value ) {
switch ( $key ) {
case 'site':
$cols['site'] = __( 'Site', 'mwp-al-ext' );
break;
case 'alert_code':
$cols['type'] = __( 'Event ID', 'mwp-al-ext' );
break;
case 'type':
$cols['code'] = __( 'Severity', 'mwp-al-ext' );
break;
case 'date':
$cols['crtd'] = __( 'Date', 'mwp-al-ext' );
break;
case 'username':
$cols['user'] = __( 'User', 'mwp-al-ext' );
break;
case 'source_ip':
$cols['scip'] = __( 'Source IP', 'mwp-al-ext' );
break;
case 'message':
$cols['mesg'] = __( 'Message', 'mwp-al-ext' );
break;
}
}
$cols['data'] = '';
}
return $cols;
}
/**
* Method: Get Sortable Columns.
*
* @return array
*/
public function get_sortable_columns() {
return array(
'read' => array( 'is_read', false ),
'type' => array( 'alert_id', false ),
'crtd' => array( 'created_on', true ),
'user' => array( 'user', true ),
'scip' => array( 'scip', false ),
);
}
/**
* Method: Prepare items.
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$query_events = $this->query_events();
$this->items = isset( $query_events['items'] ) ? $query_events['items'] : false;
$total_items = isset( $query_events['total_items'] ) ? $query_events['total_items'] : false;
$per_page = isset( $query_events['per_page'] ) ? $query_events['per_page'] : false;
if ( ! $this->activity_log->settings->is_infinite_scroll() ) {
$this->set_pagination_args(
array(
'total_items' => $total_items,
'per_page' => $per_page,
'total_pages' => ceil( $total_items / $per_page ),
)
);
}
}
/**
* Query Events from WSAL DB.
*
* @since 1.1
*
* @param integer $paged - Page number.
* @return array
*/
public function query_events( $paged = 0 ) {
// Query for events.
$events_query = new \WSAL\MainWPExtension\Models\OccurrenceQuery();
// Get site id for specific site events.
$bid = $this->query_args->site_id;
if ( $bid && 'dashboard' !== $bid ) {
$events_query->addCondition( 'site_id = %s ', $bid );
} elseif ( 'dashboard' === $bid ) {
$events_query->addCondition( 'site_id = %s ', '0' );
}
/**
* Filter: `mwpal_auditlog_query`
*
* This filter can be used to modify the query for events.
* It is helpful while performing search operations on the
* audit log events.
*
* @param \WSAL\MainWPExtension\Models\OccurrenceQuery $events_query – Occurrrence query instance.
*/
$events_query = apply_filters( 'mwpal_auditlog_query', $events_query );
if ( ! $this->activity_log->settings->is_infinite_scroll() ) {
$total_items = $events_query->getAdapter()->Count( $events_query );
$per_page = $this->activity_log->settings->get_view_per_page();
$offset = ( $this->get_pagenum() - 1 ) * $per_page;
} else {
$total_items = false;
$per_page = 25; // Manually set per page events for infinite scroll.
$offset = ( max( 1, $paged ) - 1 ) * $per_page;
}
// Set query order arguments.
$order_by = isset( $this->query_args->order_by ) ? $this->query_args->order_by : false;
$order = isset( $this->query_args->order ) ? $this->query_args->order : false;
if ( ! $order_by ) {
$events_query->addOrderBy( 'created_on', true );
} else {
$is_descending = true;
if ( ! empty( $order ) && 'asc' === $order ) {
$is_descending = false;
}
// TO DO: Allow order by meta values.
if ( 'scip' === $order_by ) {
$events_query->addMetaJoin(); // Since LEFT JOIN clause causes the result values to duplicate.
$events_query->addCondition( 'meta.name = %s', 'ClientIP' ); // A where condition is added to make sure that we're only requesting the relevant meta data rows from metadata table.
$events_query->addOrderBy( 'CASE WHEN meta.name = "ClientIP" THEN meta.value END', $is_descending );
} elseif ( 'user' === $order_by ) {
$events_query->addMetaJoin(); // Since LEFT JOIN clause causes the result values to duplicate.
$events_query->addCondition( 'meta.name = %s', 'CurrentUserID' ); // A where condition is added to make sure that we're only requesting the relevant meta data rows from metadata table.
$events_query->addOrderBy( 'CASE WHEN meta.name = "CurrentUserID" THEN meta.value END', $is_descending );
} else {
$tmp = new \WSAL\MainWPExtension\Models\Occurrence();
// Making sure the field exists to order by.
if ( isset( $tmp->{$order_by} ) ) {
// TODO: We used to use a custom comparator ... is it safe to let MySQL do the ordering now?.
$events_query->addOrderBy( $order_by, $is_descending );
} else {
$events_query->addOrderBy( 'created_on', true );
}
}
}
$events_query->setOffset( $offset ); // Set query offset.
$events_query->setLimit( $per_page ); // Set number of events per page.
return array(
'total_items' => $total_items,
'per_page' => $per_page,
'items' => $events_query->getAdapter()->Execute( $events_query ),
);
}
/**
* Method: Meta data formater.
*
* @param string $name - Name of the data.
* @param mix $value - Value of the data.
* @return string
*/
public function meta_formatter( $name, $value ) {
switch ( true ) {
case '%Message%' == $name:
return esc_html( $value );
case '%PromoMessage%' == $name:
return '' . $value . '
';
case '%PromoLink%' == $name:
case '%CommentLink%' == $name:
case '%CommentMsg%' == $name:
return $value;
case '%MetaLink%' == $name:
if ( ! empty( $value ) ) {
return " Exclude Custom Field from the Monitoring";
} else {
return '';
}
case '%RevisionLink%' === $name:
$check_value = (string) $value;
if ( 'NULL' !== $check_value ) {
return ' Click here to see the content changes.';
} else {
return false;
}
case '%EditorLinkPost%' == $name:
return ' View the post';
case '%EditorLinkPage%' == $name:
return ' View the page';
case '%CategoryLink%' == $name:
return ' View the category';
case '%TagLink%' == $name:
return ' View the tag';
case '%EditorLinkForum%' == $name:
return ' View the forum';
case '%EditorLinkTopic%' == $name:
return ' View the topic';
case in_array( $name, array( '%MetaValue%', '%MetaValueOld%', '%MetaValueNew%' ) ):
return '' . (
strlen( $value ) > 50 ? ( esc_html( substr( $value, 0, 50 ) ) . '…' ) : esc_html( $value )
) . '';
case '%ClientIP%' == $name:
if ( is_string( $value ) ) {
return '' . str_replace( array( '"', '[', ']' ), '', $value ) . '';
} else {
return 'unknown';
}
case '%LinkFile%' === $name:
if ( 'NULL' != $value ) {
$site_id = $this->activity_log->settings->get_view_site_id(); // Site id for multisite.
return '' . esc_html__( 'Download the log file', 'mwp-al-ext' ) . '';
} else {
return 'Click here to log such requests to file';
}
case '%URL%' === $name:
return ' or exclude this URL from being reported.';
case '%LogFileLink%' === $name: // Failed login file link.
return '';
case '%Attempts%' === $name: // Failed login attempts.
$check_value = (int) $value;
if ( 0 === $check_value ) {
return '';
} else {
return $value;
}
case '%LogFileText%' === $name: // Failed login file text.
return '' . esc_html__( 'Download the log file.', 'mwp-al-ext' ) . '';
case strncmp( $value, 'http://', 7 ) === 0:
case strncmp( $value, 'https://', 7 ) === 0:
return '' . esc_html( $value ) . '';
case '%PostStatus%' === $name:
if ( ! empty( $value ) && 'publish' === $value ) {
return '' . esc_html__( 'published', 'mwp-al-ext' ) . '';
} else {
return '' . esc_html( $value ) . '';
}
case '%multisite_text%' === $name:
if ( $this->is_multisite() && $value ) {
$site_info = get_blog_details( $value, true );
if ( $site_info ) {
return ' on site ' . esc_html( $site_info->blogname ) . '';
}
return;
}
return;
case '%ReportText%' === $name:
return;
case '%ChangeText%' === $name:
$url = admin_url( 'admin-ajax.php' ) . '?action=AjaxInspector&occurrence=' . $this->current_alert_id;
return ' View the changes in data inspector.';
case '%ScanError%' === $name:
if ( 'NULL' === $value ) {
return false;
}
/* translators: Mailto link for support. */
return ' with errors. ' . sprintf( __( 'Contact us on %s for assistance', 'mwp-al-ext' ), 'support@wpsecurityauditlog.com' );
case '%TableNames%' === $name:
$value = str_replace( ',', ', ', $value );
return '' . esc_html( $value ) . '';
case '%FileSettings%' === $name:
$file_settings_args = array(
'page' => 'wsal-settings',
'tab' => 'file-changes',
);
$file_settings = add_query_arg( $file_settings_args, admin_url( 'admin.php' ) );
return '' . esc_html__( 'plugin settings', 'mwp-al-ext' ) . '';
case '%ContactSupport%' === $name:
return '' . esc_html__( 'contact our support', 'mwp-al-ext' ) . '';
default:
return '' . esc_html( $value ) . '';
}
}
}