task(['connection'=>'local','batch_size'=>50,'processed_events_count'=>0]);
new Metadata_Migration_440( 'local' );
new Metadata_Migration_440( 'external' );
new Metadata_Migration_440( 'archive' );
$get_migration_connections = (array) WP_Helper::get_global_option( Metadata_Migration_440::OPTION_NAME_MIGRATION_INFO, array() );
foreach ( array_keys( $get_migration_connections ) as $connection_name ) {
if ( true === in_array( $connection_name, array( 'local', 'external', 'archive' ), true ) ) {
continue;
}
new Metadata_Migration_440( $connection_name );
}
\add_action( 'all_admin_notices', array( Metadata_Migration_440::class, 'maybe_display_progress_admin_notice' ) );
}
self::init_hooks();
\add_action( 'after_setup_theme', array( __CLASS__, 'load_wsal' ) );
}
/**
* Returns whether the plugin should load.
*
* @return bool Whether the plugin should load.
*
* @since 5.0.0
*/
private static function should_load() {
// Always load on the admin, except for the scenario when this plugin is being updated.
if ( \is_admin() ) {
$acceptable_slugs = array(
'wp-security-audit-log',
'wp-activity-log',
);
// Check if this plugin is being updated from the plugin list.
if ( isset( $_REQUEST['action'] ) && isset( $_REQUEST['slug'] ) && 'update-plugin' === trim( \sanitize_text_field( \wp_unslash( $_REQUEST['action'] ) ) )
&& in_array( trim( \sanitize_text_field( \wp_unslash( $_REQUEST['slug'] ) ) ), $acceptable_slugs ) ) {
return false;
}
// Check if this plugin is being updated using the file upload method.
if ( isset( $_REQUEST['action'] ) && 'upload-plugin' === trim( \sanitize_text_field( \wp_unslash( $_REQUEST['action'] ) ) )
&& isset( $_REQUEST['overwrite'] ) && 'update-plugin' === trim( \sanitize_text_field( \wp_unslash( $_REQUEST['overwrite'] ) ) )
&& isset( $_REQUEST['package'] ) ) {
/**
* Request doesn't contain the file name, but a numeric package ID.
*
* @see File_Upload_Upgrader::__construct()
*/
$post_id = (int) $_REQUEST['package'];
$attachment = \get_post( $post_id );
if ( ! empty( $attachment ) ) {
$filename = $attachment->post_title;
foreach ( $acceptable_slugs as $acceptable_slug ) {
if ( false !== strpos( $filename, $acceptable_slug ) ) {
return false;
}
}
}
}
// Check if this plugin is being updated from the WordPress updated screen (update-core.php).
if ( isset( $_REQUEST['action'] ) && 'do-plugin-upgrade' === trim( \sanitize_text_field( \wp_unslash( $_REQUEST['action'] ) ) ) ) {
if ( isset( $_REQUEST['checked'] ) ) {
$selected_plugins = $_REQUEST['checked']; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
if ( ! empty( $selected_plugins ) ) {
foreach ( $selected_plugins as $selected_plugin ) {
if ( 'wp-security-audit-log.php' === basename( trim( \sanitize_text_field( \wp_unslash( $selected_plugin ) ) ) ) ) {
return false;
}
}
}
}
}
return true;
}
// Check conditions for frontend.
if ( self::is_frontend() && ! \is_user_logged_in() && ! self::should_load_frontend() ) {
// User isn't logged in, and we aren't logging visitor events on front-end.
return false;
}
// Other contexts/scenarios.
if ( self::is_rest_api() ) {
return \is_user_logged_in();
}
return true;
}
/**
* Checks to see if WSAL should be loaded for register, login, and comment events.
*
* @return bool
*
* @since 5.0.0
*/
public static function should_load_frontend() {
$frontend_events = Settings_Helper::get_frontend_events();
$should_load = ! empty( $frontend_events['register'] ) || ! empty( $frontend_events['login'] ) || ! empty( $frontend_events['woocommerce'] || ! empty( $frontend_events['gravityforms'] ) );
// Allow extensions to manually allow a sensor to load.
return apply_filters( 'wsal_load_on_frontend', $should_load, $frontend_events );
}
/**
* Include Plugin Files.
* Initialize Plugin Hooks.
*
* @since 3.3
*/
private static function init_hooks() {
// Setup screen options. Needs to be here as admin_init hook it too late.
\add_filter( 'set-screen-option', array( List_Events::class, 'set_screen_option' ), 10, 3 );
\add_action( 'current_screen', array( Upgrade_Notice::class, 'init' ) );
// Listen for cleanup event.
\add_action( 'wsal_cleanup', array( __CLASS__, 'clean_up' ) );
\add_action( 'shutdown', array( __CLASS__, 'close_external_connection' ), 999 );
// Render wsal footer.
\add_action( 'admin_footer', array( __CLASS__, 'render_footer' ) );
// Handle admin Disable Custom Field.
\add_action( 'wp_ajax_AjaxDisableCustomField', array( __CLASS__, 'ajax_disable_custom_field' ) );
// Handle admin Disable Alerts.
\add_action( 'wp_ajax_AjaxDisableByCode', array( __CLASS__, 'ajax_disable_by_code' ) );
// Render Login Page Notification.
\add_filter( 'login_message', array( __CLASS__, 'render_login_page_message' ), 10, 1 );
\add_filter( 'mainwp_child_extra_execution', array( '\WSAL\MainWP\MainWP_API', 'retrieve_info_call_back' ), 10, 2 );
\add_action( 'wsal_freemius_loaded', array( __CLASS__, 'adjust_freemius_strings' ) );
add_filter( 'plugins_api_result', array( __CLASS__, 'filter_default_no_plugin_error' ), 10, 3 );
Cron_Jobs::init();
// Extensions which are only admin based.
if ( \is_admin() ) {
Plugin_Installer::init();
Feedback_Form::init();
}
Plugin_Extensions::init();
Notices::init_ajax_hooks();
// Dequeue conflicting scripts.
\add_action( 'wp_print_scripts', array( __CLASS__, 'dequeue_conflicting_scripts' ) );
}
/**
* Load Freemius SDK.
*
* @since 5.0.0
*/
public static function load_freemius() {
if ( file_exists( WSAL_BASE_DIR . '/sdk/wsal-freemius.php' ) ) {
require_once WSAL_BASE_DIR . '/sdk/wsal-freemius.php';
}
}
/**
* Check if MainWP plugin is active or not.
*
* @return boolean
*
* @since 5.0.0
*/
public static function is_mainwp_active() {
$active = WP_Helper::is_plugin_active( 'mainwp-child/mainwp-child.php' );
if ( WP_Helper::is_multisite() ) {
// Check if the plugin is active on the main site.
if ( ! defined( '\MAINWP_CHILD_URL' ) ) {
$active = false;
} else {
$active = true;
}
}
return $active;
}
/**
* Initializes Freemius and its hooks, conditionally.
*
* @return void
*
* @since 5.0.0
*/
private static function init_freemius() {
$is_admin_blocking_plugins_support_enabled = self::is_admin_blocking_plugins_support_enabled();
if ( self::is_frontend() && self::is_premium_freemius() && file_exists( WSAL_BASE_DIR . '/extensions/class-wsal-extension-manager.php' ) ) {
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
\WSAL_Extension_Manager::include_extension( 'reports' );
\WSAL_Extension_Manager::include_extension( 'usersessions' );
\WSAL_Extension_Manager::include_extension( 'external-db' );
} elseif ( self::should_load() ) {
\WSAL_Extension_Manager::include_extension( 'notifications' );
\WSAL_Extension_Manager::include_extension( 'external-db' );
}
if ( ! $is_admin_blocking_plugins_support_enabled ) {
// We only stop here if the support for admin blocking plugins is enabled.
return;
}
}
if ( $is_admin_blocking_plugins_support_enabled || is_admin() || WP_Helper::is_login_screen() || self::is_rest_api() || ( defined( 'DOING_CRON' ) && DOING_CRON ) || ( defined( 'WP_CLI' ) && \WP_CLI ) ) {
self::load_freemius();
if ( ! apply_filters( 'wsal_disable_freemius_sdk', false ) ) {
// Add filters to customize freemius welcome message.
wsal_freemius()->add_filter( 'connect_message', array( __CLASS__, 'wsal_freemius_connect_message' ), 10, 6 );
wsal_freemius()->add_filter( 'connect_message_on_update', array( __CLASS__, 'wsal_freemius_update_connect_message' ), 10, 6 );
wsal_freemius()->add_filter( 'show_admin_notice', array( __CLASS__, 'freemius_show_admin_notice' ), 10, 2 );
wsal_freemius()->add_filter( 'show_delegation_option', '__return_false' );
wsal_freemius()->add_filter( 'enable_per_site_activation', '__return_false' );
wsal_freemius()->add_filter( 'show_trial', '__return_false' );
wsal_freemius()->add_filter( 'opt_in_error_message', array( __CLASS__, 'limited_license_activation_error' ), 10, 1 );
wsal_freemius()->add_action( 'after_account_plan_sync', array( __CLASS__, 'sync_premium_freemius' ), 10, 1 );
wsal_freemius()->add_action( 'after_premium_version_activation', array( __CLASS__, 'sync_premium_freemius' ) );
wsal_freemius()->add_filter(
'plugin_icon',
function ( $plugin_icon ) {
return WSAL_BASE_DIR . 'img/wsal-logo@2x.png';
}
);
wsal_freemius()->add_action( 'is_submenu_visible', array( __CLASS__, 'hide_freemius_submenu_items' ), 10, 2 );
wsal_freemius()->add_filter(
'freemius_pricing_js_path',
function ( $default_pricing_js_path ) {
return WSAL_BASE_DIR . 'js/freemius-pricing/freemius-pricing.js';
}
);
wsal_freemius()->add_filter( 'default_to_anonymous_feedback', '__return_true' );
wsal_freemius()->add_filter( 'show_deactivation_feedback_form', '__return_false' );
wsal_freemius()->add_filter(
'pricing_url',
function ( $url ) {
return 'https://melapress.com/wordpress-activity-log/pricing/?&utm_source=plugin&utm_medium=link&utm_campaign=wsal';
}
);
}
}
}
/**
* Method: WSAL plugin redirect.
*
* @since 5.0.0
*/
public static function wsal_plugin_redirect() {
// Plugin redirect on activation.
if ( false === Settings_Helper::get_option_value( 'redirect_on_activate', false ) ) {
return;
}
$restrict_to = Settings_Helper::get_option_value( 'restrict-plugin-settings', 'only_admins' );
if ( ( 'only_admins' === $restrict_to && \current_user_can( 'manage_options' ) ) || ( 'only_me' === $restrict_to && (int) Settings_Helper::get_option_value( 'only-me-user-id' ) === (int) get_current_user_id() ) ) {
// WSAL State.
$wsal_state = Settings_Helper::get_option_value( 'freemius_state', 'anonymous' );
if (
in_array( $wsal_state, array( 'anonymous', 'skipped' ), true ) && Settings_Helper::get_option_value( 'redirect_on_activate', false ) // Redirect flag.
) {
// If the redirect option is true, then continue.
Settings_Helper::delete_option_value( 'wsal_redirect_on_activate' ); // Delete redirect option.
// Redirect URL.
$redirect = '';
// Otherwise, redirect to main audit log view.
$redirect = self::get_plugin_admin_url_page();
\wp_safe_redirect( $redirect );
exit();
}
}
}
/**
* Method: Include extensions for premium version.
*
* @since 2.7.0
*/
private static function include_extensions__premium_only() {
// Initiate the extensions' manager.
\WSAL_Extension_Manager::init();
}
/**
* Customize Freemius connect message for new users.
*
* @param string $message - Connect message.
* @param string $user_first_name - User first name.
* @param string $plugin_title - Plugin title.
* @param string $user_login - Username.
* @param string $site_link - Site link.
* @param string $_freemius_link - Freemius link.
*
* @return string
*
* @since 5.0.0
*/
public static function wsal_freemius_connect_message( $message, $user_first_name, $plugin_title, $user_login, $site_link, $_freemius_link ) {
$result = sprintf(
/* translators: User's first name */
esc_html__( 'Hey %s', 'wp-security-audit-log' ),
$user_first_name
);
$result .= ',
';
$result .= esc_html__( 'Never miss an important update! Opt-in to our security and feature updates notifications, and non-sensitive diagnostic tracking with freemius.com.', 'wp-security-audit-log' ) .
$result .= '
' . esc_html__( 'Note: ', 'wp-security-audit-log' ) . '';
$result .= esc_html__( 'NO ACTIVITY LOG ACTIVITY & DATA IS SENT BACK TO OUR SERVERS.', 'wp-security-audit-log' );
return $result;
}
/**
* Customize Freemius connect message on update.
*
* @param string $message - Connect message.
* @param string $user_first_name - User first name.
* @param string $plugin_title - Plugin title.
* @param string $user_login - Username.
* @param string $site_link - Site link.
* @param string $_freemius_link - Freemius link.
*
* @return string
*
* @since 4.3.4
*/
public static function wsal_freemius_update_connect_message( $message, $user_first_name, $plugin_title, $user_login, $site_link, $_freemius_link ) {
$result = sprintf(
/* tranxslators: User's first name */
esc_html__( 'Hey %s', 'wp-security-audit-log' ),
$user_first_name
);
$result .= ',
';
$result .= sprintf(
/* translators: 1: Plugin name. 2: Plugin name. 2: Freemius link. 4: Plugin name. */
esc_html__( 'Please help us improve %1$s! If you opt-in, some non-sensitive data about your usage of %2$s will be sent to %3$s, a diagnostic tracking service we use. If you skip this, that\'s okay! %2$s will still work just fine.', 'wp-security-audit-log' ) .
'' . $plugin_title . '',
'' . $plugin_title . '',
'freemius.com',
'' . $plugin_title . ''
);
$result .= '
' . esc_html__( 'Note: ', 'wp-security-audit-log' ) . '';
$result .= esc_html__( 'NO ACTIVITY LOG ACTIVITY & DATA IS SENT BACK TO OUR SERVERS.', 'wp-security-audit-log' );
return $result;
}
/**
* Freemius Admin Notice View Permission.
*
* Check to see if the user has permission to view Freemius admin notices or not.
*
* @param bool $show – If show then set to true, otherwise false.
* @param array $msg Message related data.
*
* @return bool
*
* @since 3.3
*/
public static function freemius_show_admin_notice( $show, $msg ) {
if ( Settings_Helper::current_user_can( 'edit' ) ) {
return $show;
}
return false;
}
/**
* Changes some of the strings that Freemius outputs with our own.
*
* @method adjust_freemius_strings
*
* @since 4.0.0
*/
public static function adjust_freemius_strings() {
// only update these messages if using premium plugin.
if ( ( ! wsal_freemius()->is_premium() ) || ( ! method_exists( wsal_freemius(), 'override_il8n' ) ) ) {
return;
}
wsal_freemius()->override_i18n(
array(
'few-plugin-tweaks' =>
// translators: The license key.
esc_html__(
'You need to activate the license key to use WP Activity Log Premium. %s',
'wp-security-audit-log'
),
'optin-x-now' => esc_html__( 'Activate the license key now', 'wp-security-audit-log' ),
)
);
}
/**
* Limited License Activation Error.
*
* @param string $error - Error Message.
*
* @return string
*
* @since 5.0.0
*/
public static function limited_license_activation_error( $error ) {
// We only process error if it's some sort of string message.
if ( ! is_string( $error ) ) {
return $error;
}
$site_count = null;
preg_match( '!\d+!', $error, $site_count );
// Check if this is an expired error.
if ( strpos( $error, 'expired' ) !== false ) {
/* Translators: Expired message and time */
$error = sprintf( esc_html__( '%s You need to renew your license to continue using premium features.', 'wp-security-audit-log' ), preg_replace( '/\([^)]+\)/', '', $error ) );
} elseif ( ! empty( $site_count[0] ) ) {
/* Translators: Number of sites */
$error = sprintf( esc_html__( 'The license is limited to %s sub-sites. You need to upgrade your license to cover all the sub-sites on this network.', 'wp-security-audit-log' ), $site_count[0] );
}
return $error;
}
/**
* Start to trigger the events after installation.
*
* @internal
*
* @since 5.0.0
*/
private static function init() {
if ( \is_admin() ) {
View_Manager::init();
Widget_Manager::init();
}
// Reports.
if ( \class_exists( Notifications::class ) ) {
Notifications::init();
}
if ( \is_admin() ) {
// Hide plugin.
if ( Settings_Helper::get_boolean_option_value( 'hide-plugin' ) ) {
\add_action( 'admin_head', array( __CLASS__, 'hide_plugin' ) );
\add_filter( 'all_plugins', array( __CLASS__, 'wsal_hide_plugin' ) );
}
}
global $wsal_class;
/**
* Action: `wsal_init`
*
* Action hook to mark that WSAL has initialized.
*
* @param WpSecurityAuditLog $this – Instance of main plugin class.
*/
\do_action( 'wsal_init', $wsal_class );
// \add_action( 'init', array( Migration::class, 'migrate' ), PHP_INT_MAX );
if ( defined( '\WP_CLI' ) && \WP_CLI ) {
\WP_CLI::add_command( 'wsal_cli_commands', '\WSAL\Controllers\WP_CLI\WP_CLI_Commands' );
}
}
/**
* Plugin Deactivation Actions.
*
* This function runs on plugin deactivation.
*
* @param bool $network_wide - Whether the plugin is being deactivated for the entire network.
*
* @return void
*
* @since 3.3.1
* @since 5.6.2 Unschedule all cron jobs on deactivation, including per-site on multisite.
*/
public static function deactivate_actions( $network_wide = false ) {
Cron_Jobs::unschedule_all_cron_jobs( $network_wide );
/**
* Allow short-circuiting of the deactivation email sending by using
* this filter to return true here instead of default false.
*
* @since 3.5.2
*
* @var bool
*/
if ( apply_filters( 'wsal_filter_prevent_deactivation_email_delivery', false ) ) {
return;
}
// Send deactivation email.
if ( \class_exists( '\WSAL\Helpers\Email_Helper', false ) ) {
// Get email template.
Email_Helper::send_deactivation_email();
}
}
/**
* Disable Custom Field through ajax.
*
* @internal
*
* @since 5.0.0
* @since 5.6.0 - Return JSON payload instead of HTML.
*/
public static function ajax_disable_custom_field() {
if ( ! Settings_Helper::current_user_can( 'edit' ) ) {
\wp_send_json_error(
array(
'message' => \esc_html__( 'Error: You do not have sufficient permissions to disable this custom field.', 'wp-security-audit-log' ),
),
403
);
}
$notice = \sanitize_text_field( \wp_unslash( $_POST['notice'] ?? '' ) );
$nonce_is_valid = \check_ajax_referer( 'disable-custom-nonce' . $notice, 'disable_nonce', false );
if ( false === $nonce_is_valid ) {
\wp_send_json_error(
array(
'message' => \esc_html__( 'Error: Invalid nonce.', 'wp-security-audit-log' ),
),
403
);
}
$notice = \str_replace( array( "'", '"', ',' ), '', $notice );
// Validate object type.
$object_type_post = \sanitize_text_field( \wp_unslash( $_POST['object_type'] ?? '' ) );
$object_type = ( 'user' === $object_type_post ) ? 'user' : 'post';
$excluded_meta = array();
// Get current excluded meta fields.
if ( 'post' === $object_type ) {
$excluded_meta = Settings_Helper::get_excluded_post_meta_fields();
} elseif ( 'user' === $object_type ) {
$excluded_meta = Settings_Helper::get_excluded_user_meta_fields();
}
// Add the new field to the array.
if ( ! \in_array( $notice, $excluded_meta, true ) ) {
$excluded_meta[] = $notice;
}
// Save updated excluded meta fields.
if ( 'post' === $object_type ) {
Settings_Helper::set_excluded_post_meta_fields( $excluded_meta );
} elseif ( 'user' === $object_type ) {
Settings_Helper::set_excluded_user_meta_fields( $excluded_meta );
}
/**
* Build response messages. These will end up inside
tags on the JS side. */ // Message 1: "Custom field [FIELD_NAME] is no longer being monitored.". /* translators: %s: Custom field name */ $message_1 = \esc_html__( 'Custom field %s is no longer being monitored.', 'wp-security-audit-log' ); $p1_parts = \explode( '%s', $message_1, 2 ); $p1_parts = ( 2 === count( $p1_parts ) ) ? $p1_parts : array( $message_1, '' ); // Message 2: "Enable monitoring again from the [TAB_NAME] tab in settings.". /* translators: %s: Settings tab name */ $message_2 = \esc_html__( 'Enable the monitoring of this custom field again from the %s tab in the plugin settings.', 'wp-security-audit-log' ); $p2_parts = \explode( '%s', $message_2, 2 ); $p2_parts = ( 2 === count( $p2_parts ) ) ? $p2_parts : array( $message_2, '' ); // Exclude object settings link. $exclude_objects_link = \add_query_arg( array( 'page' => 'wsal-settings', 'tab' => 'exclude-objects', ), \network_admin_url( 'admin.php' ) ); \wp_send_json_success( array( 'notice' => $notice, 'settings_url' => \esc_url_raw( $exclude_objects_link ), 'tab_label' => \esc_html__( 'Excluded Objects', 'wp-security-audit-log' ), 'p1_parts' => $p1_parts, 'p2_parts' => $p2_parts, ) ); } /** * Disable Alert through ajax. * * @internal * * @since 5.0.0 */ public static function ajax_disable_by_code() { // Die if user does not have permission to disable. if ( ! Settings_Helper::current_user_can( 'edit' ) ) { echo '
' . esc_html__( 'Error: You do not have sufficient permissions to disable this alert.', 'wp-security-audit-log' ) . '
'; die(); } $disable_nonce = ( isset( $_POST['disable_nonce'] ) ) ? \sanitize_text_field( \wp_unslash( $_POST['disable_nonce'] ) ) : null; $code = ( isset( $_POST['code'] ) ) ? \sanitize_text_field( \wp_unslash( $_POST['code'] ) ) : null; if ( ! isset( $disable_nonce ) || ! \wp_verify_nonce( $disable_nonce, 'disable-alert-nonce' . $code ) ) { die(); } $s_alerts = Settings_Helper::get_option_value( 'disabled-alerts' ); if ( is_string( $s_alerts ) ) { $s_alerts = \array_filter( \array_map( 'trim', \explode( ',', $s_alerts ) ) ); } if ( isset( $s_alerts ) && '' !== $s_alerts ) { $s_alerts[] = (int) esc_html( $code ); Settings_Helper::set_disabled_alerts( $s_alerts ); } echo wp_sprintf( // translators: Alert code which is no longer monitored. '' . esc_html__( 'Alert %1$s is no longer being monitored. %2$s', 'wp-security-audit-log' ) . '
', \esc_html( $code ), '