get_option( 'activity-extension-activated', $default ); } /** * Updates extension activated option. * * @param string $value - Value of the option. * @return boolean */ public function set_extension_activated( $value ) { return $this->update_option( 'activity-extension-activated', $value ); } /** * Determines datetime format to be displayed in any UI in the plugin (logs in administration, emails, reports, * notifications etc.). * * Note: Format returned by this function is not compatible with JavaScript date and time picker widgets. Use * functions get_time_format and get_date_format for those. * * @param boolean $line_break - True if line break otherwise false. * * @return string */ public function get_date_time_format( $line_break = true, $use_nb_space_for_am_pm = true ) { $result = $this->get_date_format(); $result .= $line_break ? '<\b\r>' : ' '; $time_format = $this->get_time_format(); $has_am_pm = false; $am_pm_fraction = false; $am_pm_pattern = '/(?i)(\s+A)/'; if ( preg_match( $am_pm_pattern, $time_format, $am_pm_matches ) ) { $has_am_pm = true; $am_pm_fraction = $am_pm_matches[0]; $time_format = preg_replace( $am_pm_pattern, '', $time_format ); } // Check if the time format does not have seconds. if ( stripos( $time_format, 's' ) === false ) { $time_format .= ':s'; // Add seconds to time format. } $time_format .= '.$$$'; // Add milliseconds to time format. if ( $has_am_pm ) { $time_format .= preg_replace( '/\s/', $use_nb_space_for_am_pm ? '&\n\b\s\p;' : ' ', $am_pm_fraction ); } $result .= $time_format; return $result; } /** * Date format based on WordPress date settings. It can be optionally sanitized to get format compatible with * JavaScript date and time picker widgets. * * Note: This function must not be used to display actual date and time values anywhere. For that use function get_date_time_format. * * @param bool $sanitized If true, the format is sanitized for use with JavaScript date and time picker widgets. * * @return string */ public function get_date_format( $sanitized = false ) { if ( $sanitized ) { return 'Y-m-d'; } return get_option( 'date_format' ); } /** * Time format based on WordPress date settings. It can be optionally sanitized to get format compatible with * JavaScript date and time picker widgets. * * Note: This function must not be used to display actual date and time values anywhere. For that use function get_date_time_format. * * @param bool $sanitize If true, the format is sanitized for use with JavaScript date and time picker widgets. * * @return string */ public function get_time_format( $sanitize = false ) { $result = get_option( 'time_format' ); if ( $sanitize ) { $search = array( 'a', 'A', 'T', ' ' ); $replace = array( '', '', '', '' ); $result = str_replace( $search, $replace, $result ); } return $result; } /** * Get MainWP Child Sites. * * @return array */ public function get_mwp_child_sites() { $activity_log = \WSAL\MainWPExtension\mwpal_extension(); return apply_filters( 'mainwp_getsites', $activity_log->get_child_file(), $activity_log->get_child_key(), null ); } /** * Get MainWP child site by site ID. * * @param int $site_id Site ID. * * @return array|null */ public function get_mwp_child_site_by_id( $site_id ) { // Get MainWP child sites. $mwp_sites = $this->get_mwp_child_sites(); // Search for the site data. $key = array_search( $site_id, array_column( $mwp_sites, 'id' ), false ); if ( false !== $key && isset( $mwp_sites[ $key ] ) ) { return $mwp_sites[ $key ]; } return null; } /** * Set Alert Views Per Page. * * @param int $newvalue – New value. */ public function set_view_per_page( $newvalue ) { $perpage = max( $newvalue, 1 ); $this->update_option( 'items-per-page', $perpage ); } /** * Get Alert Views Per Page. * * @return int */ public function get_view_per_page() { return (int) $this->get_option( 'items-per-page', 10 ); } /** * Return Site ID. * * @return integer */ public function get_view_site_id() { // @codingStandardsIgnoreStart $site_id = isset( $_REQUEST['mwpal-site-id'] ) ? sanitize_text_field( $_REQUEST['mwpal-site-id'] ) : 0; // Site ID. // @codingStandardsIgnoreEnd if ( 'dashboard' !== $site_id ) { return (int) $site_id; } return $site_id; } /** * Method: Get number of hours since last logged alert. * * @return mixed – False if $created_on is empty | Number of hours otherwise. * * @param float $created_on – Timestamp of last logged alert. */ public function get_hours_since_last_alert( $created_on ) { // If $created_on is empty, then return. if ( empty( $created_on ) ) { return false; } // Last alert date. $created_date = new \DateTime( date( 'Y-m-d H:i:s', (int) $created_on ) ); // Current date. $current_date = new \DateTime( 'NOW' ); // Calculate time difference. $time_diff = $current_date->diff( $created_date ); $diff_days = $time_diff->d; // Difference in number of days. $diff_hrs = $time_diff->h; // Difference in number of hours. $total_hrs = ( $diff_days * 24 ) + $diff_hrs; // Total number of hours. // Return difference in hours. return $total_hrs; } /** * Return audit log columns. * * @return array */ public function get_columns() { $columns = array( 'site' => '1', 'alert_code' => '1', 'type' => '1', 'info' => '1', 'date' => '1', 'username' => '1', 'event_type' => '1', 'object' => '1', 'source_ip' => '1', 'message' => '1', ); // Get selected columns. $selected = $this->get_columns_selected(); if ( ! empty( $selected ) ) { $columns = array( 'site' => '0', 'alert_code' => '0', 'type' => '0', 'info' => '0', 'date' => '0', 'username' => '0', 'event_type' => '0', 'object' => '0', 'source_ip' => '0', 'message' => '0', ); $selected = (array) json_decode( $selected ); $columns = array_merge( $columns, $selected ); } return $columns; } /** * Get Selected Columns. * * @return string */ public function get_columns_selected() { return $this->get_option( 'columns' ); } /** * Set Columns. * * @param array $columns – Columns. */ public function set_columns( $columns ) { $this->update_option( 'columns', wp_json_encode( $columns ) ); } /** * Get WSAL Child Sites. * * @return array */ public function get_wsal_child_sites() { // Check if the WSAL child sites option exists. $child_sites = $this->get_option( 'wsal-child-sites' ); // Get MainWP Child sites. $mwp_sites = $this->get_mwp_child_sites(); $activity_log = \WSAL\MainWPExtension\mwpal_extension(); if ( empty( $child_sites ) && ! empty( $mwp_sites ) ) { foreach ( $mwp_sites as $site ) { // Call to child sites to check if WSAL is installed on them or not. $results[ $site['id'] ] = $activity_log->make_api_call( $site['id'], 'check_wsal' ); } if ( ! empty( $results ) && is_array( $results ) ) { $child_sites = array(); foreach ( $results as $site_id => $site_array ) { if ( empty( $site_array ) || ! is_array( $site_array ) ) { continue; } elseif ( is_array( $site_array ) && isset( $site_array['wsal_installed'] ) && true === $site_array['wsal_installed'] ) { $child_sites[ $site_id ] = $site_array; } } $this->update_option( 'wsal-child-sites', $child_sites ); } } return $child_sites; } /** * Set WSAL Child Sites. * * @param array $site_ids – Array of Site ids. * @return void */ public function set_wsal_child_sites( $site_ids ) { $wsal_sites = $this->get_wsal_child_sites(); // Get WSAL child sites. $disabled_sites = $this->get_option( 'disabled-wsal-sites', array() ); // Get already disabled sites. $new_sites = array(); // Set new WSAL sites. if ( ! empty( $site_ids ) && is_array( $site_ids ) ) { foreach ( $site_ids as $id ) { if ( isset( $wsal_sites[ $id ] ) ) { $new_sites[ $id ] = $wsal_sites[ $id ]; unset( $wsal_sites[ $id ] ); } elseif ( isset( $disabled_sites[ $id ] ) ) { $new_sites[ $id ] = $disabled_sites[ $id ]; unset( $disabled_sites[ $id ] ); } else { $new_sites[ $id ] = new \stdClass(); } } } // Remove events of removed sites from the DB. if ( ! empty( $wsal_sites ) && is_array( $wsal_sites ) ) { foreach ( $wsal_sites as $site_id => $site ) { // Delete events by site id. $delete_query = new \WSAL\MainWPExtension\Models\OccurrenceQuery(); $delete_query->addCondition( 'site_id = %s ', $site_id ); $delete_query->getAdapter()->Delete( $delete_query ); $disabled_sites[ $site_id ] = $site; } } $this->update_option( 'wsal-child-sites', $new_sites ); $this->update_option( 'disabled-wsal-sites', $disabled_sites ); } /** * Get Timezone. * * @return string */ public function get_timezone() { return $this->get_option( 'timezone', 'wp' ); } /** * Set Timezone. * * @param string $newvalue – New value. */ public function set_timezone( $newvalue ) { $this->update_option( 'timezone', $newvalue ); } /** * Get Username Type. * * @return string */ public function get_type_username() { return $this->get_option( 'type_username', 'display_name' ); } /** * Set Username Type. * * @param string $newvalue – New value. */ public function set_type_username( $newvalue ) { $this->update_option( 'type_username', $newvalue ); } /** * Get number of child site events. * * @return integer */ public function get_child_site_events() { return $this->get_option( 'child_site_events', 100 ); } /** * Set number of child site events. * * @param integer $newvalue – New value. */ public function set_child_site_events( $newvalue ) { $this->update_option( 'child_site_events', $newvalue ); } /** * Get Events Frequency. * * @return integer */ public function get_events_frequency() { return $this->get_option( 'events_frequency', 3 ); } /** * Set Events Frequency. * * @param integer $newvalue – New value. */ public function set_events_frequency( $newvalue ) { $this->update_option( 'events_frequency', $newvalue ); } /** * Get Current User Roles. * * @param array $base_roles – Base roles. * @return array */ public function get_current_user_roles( $base_roles = null ) { if ( null === $base_roles ) { $base_roles = wp_get_current_user()->roles; } if ( function_exists( 'is_super_admin' ) && is_super_admin() ) { $base_roles[] = 'superadmin'; } return $base_roles; } /** * Check if the user is super admin. * * @param string $username – Username. * @return boolean */ public function is_login_super_admin( $username ) { $user_id = username_exists( $username ); return function_exists( 'is_super_admin' ) && is_super_admin( $user_id ); } /** * Get Server IP. * * @return string */ public function get_server_ip() { $result = null; if ( isset( $_SERVER['SERVER_ADDR'] ) ) { $result = $this->normalize_ip( sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) ); if ( ! $this->validate_ip( $result ) ) { $result = 'Error ' . self::ERROR_CODE_INVALID_IP . ': Invalid IP Address'; } } return $result; } /** * Get Client IP. * * @return string */ public function get_main_client_ip() { $result = null; if ( isset( $_SERVER['REMOTE_ADDR'] ) ) { $result = $this->normalize_ip( sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) ); if ( ! $this->validate_ip( $result ) ) { $result = 'Error ' . self::ERROR_CODE_INVALID_IP . ': Invalid IP Address'; } } return $result; } /** * Normalize IP Address. * * @param string $ip – IP Address. * @return string */ protected function normalize_ip( $ip ) { $ip = trim( $ip ); if ( strpos( $ip, ':' ) !== false && substr_count( $ip, '.' ) == 3 && strpos( $ip, '[' ) === false ) { // IPv4 with a port (eg: 11.22.33.44:80). $ip = explode( ':', $ip ); $ip = $ip[0]; } else { // IPv6 with a port (eg: [::1]:80). $ip = explode( ']', $ip ); $ip = ltrim( $ip[0], '[' ); } return $ip; } /** * Validate IP Address. * * @param string $ip – IP Address. * @return string */ protected function validate_ip( $ip ) { $opts = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6; $filtered_ip = filter_var( $ip, FILTER_VALIDATE_IP, $opts ); if ( ! $filtered_ip || empty( $filtered_ip ) ) { if ( // Regex IPV4. preg_match( '/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', $ip ) // Regex IPV6. || preg_match( '/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/', $ip ) ) { return $ip; } return false; } else { return $filtered_ip; } } /** * Search & Return MainWP site. * * @param string $value – Column value. * @param string $column – Column name. * * @return mixed */ public function get_mwp_site_by( $value, $column = 'id' ) { // Get MainWP sites. $mwp_sites = $this->get_mwp_child_sites(); // Search by column name. $key = array_search( $value, array_column( $mwp_sites, $column ), true ); if ( false !== $key ) { return $mwp_sites[ $key ]; } return false; } /** * Get last checked timestamp by site id. * * @since 1.0.1 * * @param integer $site_id - Site id. * @return mixed */ public function get_last_checked_by_siteid( $site_id = 0 ) { if ( $site_id ) { return $this->get_option( 'mwpal_last_checked_site_' . $site_id ); } return false; } /** * Set last checked timestamp by site id. * * @param string $last_checked - Last checked timestamp. * @param integer $site_id - Site id. * * @since 1.0.1 * */ public function set_last_checked_by_siteid( $last_checked, $site_id = 0 ) { if ( $site_id ) { $this->update_option( 'mwpal_last_checked_site_' . $site_id, $last_checked ); } } /** * Return Events Navigation Type. * * @since 1.1 * * @return string */ public function get_events_type_nav() { return $this->get_option( 'events-nav-type', 'infinite-scroll' ); } /** * Sets Events Navigation Type. * * @since 1.1 * * @param string $nav_type - Navigation type. */ public function set_events_type_nav( $nav_type ) { $this->update_option( 'events-nav-type', $nav_type ); } /** * Returns true if infinite scroll, otherwise false. * * @since 1.1 * * @return boolean */ public function is_infinite_scroll() { return 'infinite-scroll' === $this->get_events_type_nav(); } /** * Sets Events Global Sync Option. * * @since 1.1 * * @param bool $enabled - True if enabled, false otherwise. */ public function set_events_global_sync( $enabled ) { $this->update_option( 'events-global-sync', $enabled ); } /** * Returns true if events global sync is set, otherwise false. * * @since 1.1 * * @return boolean */ public function is_events_global_sync() { return $this->get_option( 'events-global-sync' ); } /** * Checks if current admin page is extension's page or not. * * @since 1.1 * * @return boolean */ public function is_current_extension_page() { global $pagenow; $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : false; // phpcs:ignore if ( 'admin.php' === $pagenow && MWPAL_EXTENSION_NAME === $page ) { return true; } return false; } /** * Meta data formater. * * @param string $name - Name of the data. * @param mixed $value - Value of the data. * @param integer $occ_id - Event occurrence id. * @return string */ public function meta_formatter( $name, $value, $occ_id ) { 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->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: if ( $occ_id ) { $url_args = array( 'action' => 'AjaxInspector', 'occurrence' => $occ_id, 'TB_iframe' => 'true', 'width' => 600, 'height' => 550, ); $url = add_query_arg( $url_args, admin_url( 'admin-ajax.php' ) ); return ' View the changes in data inspector.'; } else { return; } 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@melapress.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 ) . ''; } } /** * Set disabled events. * * @param array $types - IDs events to disable. */ public function set_disabled_events( $types ) { $disabled = array_unique( array_map( 'intval', $types ) ); $this->update_option( 'disabled-events', implode( ',', $disabled ) ); } /** * Return IDs of disabled events. * * @return array */ public function get_disabled_events() { $disabled = $this->get_option( 'disabled-events', false ); $disabled = ! $disabled ? array() : explode( ',', $disabled ); $disabled = array_map( 'intval', $disabled ); return $disabled; } /** * Set events pruning. * * @param string $state - Enabled or disabled state. */ public function set_events_pruning( $state ) { $this->update_option( 'events-pruning', $state ); } /** * Checks if events pruning is enabled or disabled. * * @return boolean */ public function is_events_pruning() { $pruning = $this->get_option( 'events-pruning', 'disabled' ); return 'enabled' === $pruning ? true : false; } /** * Set events pruning date. * * @param string $date - Date. * @param string $unit - Time unit. */ public function set_pruning_date( $date, $unit ) { $date_obj = new \stdClass(); $date_obj->date = $date; $date_obj->unit = $unit; $this->update_option( 'pruning-date', $date_obj ); } /** * Get events pruning date. * * @return stdClass|bool */ public function get_pruning_date() { $default = new \stdClass(); $default->date = false; $default->unit = false; return $this->get_option( 'pruning-date', $default ); } public function get_enforce_settings_on_subsites() { return $this->get_option( 'enforce_settings_on_subsites', 'none' ); } public function set_enforce_settings_on_subsites( $value ) { return $this->update_option( 'enforce_settings_on_subsites', $value ); } public function get_sites_with_enforced_settings() { $result = []; $sites = $this->get_option( 'subsites_with_enforced_settings' ); if ( ! empty( $sites ) ) { if ( is_string( $sites ) ) { $result = array_map( 'intval', explode( ',', $sites ) ); } } return $result; } public function set_sites_with_enforced_settings( $site_ids ) { if ( empty($site_ids) ) { return $this->delete_option( 'subsites_with_enforced_settings' ); } return $this->update_option( 'subsites_with_enforced_settings', implode( ',', $site_ids ) ); } public function get_enforced_child_sites_settings() { return $this->get_option( 'enforced_settings_data', [] ); } public function set_enforced_child_sites_settings( $value ) { return $this->update_option( 'enforced_settings_data', $value ); } /** * Sets the setting driving the automatic addition of new sites to the list of sites that have WSAL. * * @param bool $enabled - True if enabled, false otherwise. * * @since 2.0.0 */ public function set_automatically_add_new_sites( $enabled ) { $this->update_option( 'auto-add-new-sites', $enabled ); } /** * Returns true if new sites are automatically added to the list of sites that have WSAL. False otherwise. * * @since 2.0.0 * * @return boolean */ public function can_automatically_add_new_sites() { return $this->get_option( 'auto-add-new-sites', true ); } }