log_file_path = $upload_dir['basedir'] . '/activitylog/activitylog.txt'; $this->create_log_directory(); add_action( 'wp_login', [ $this, 'alpl_handle_user_login' ], 10, 2 ); add_action( 'wp_logout', [ $this, 'alpl_handle_user_logout' ] ); add_action( 'transition_post_status', [ $this, 'alpl_handle_transition_post_status' ], 10, 3 ); add_action( 'before_delete_post', [ $this, 'alpl_handle_delete_post' ] ); add_action( 'activated_plugin', [ $this, 'alpl_handle_plugin_activated' ], 10, 2 ); add_action( 'deactivated_plugin', [ $this, 'alpl_handle_plugin_deactivated' ], 10, 2 ); add_action( 'deleted_plugin', [ $this, 'alpl_handle_plugin_deleted' ], 10, 1 ); add_action( 'admin_menu', [ $this, 'alpl_register_admin_menu' ] ); add_action( 'admin_init', [ $this, 'alpl_register_settings' ] ); } private function create_log_directory() { $upload_dir = wp_upload_dir(); $log_dir = $upload_dir['basedir'] . '/activitylog/'; if ( ! file_exists( $log_dir ) ) { wp_mkdir_p( $log_dir ); } } public function alpl_register_settings() { register_setting( 'alpl_activitylog_settings', self::OPTION_NAME, [ 'type' => 'integer', 'description' => __( 'How many days to keep the logs?', 'activitylog' ), 'sanitize_callback' => 'absint', 'default' => 7, ] ); add_settings_section( 'alpl_activitylog_main_section', __( 'Activity Log Settings', 'activitylog' ), null, 'alpl_activitylog_settings' ); add_settings_field( self::OPTION_NAME, __( 'Retention (days)', 'activitylog' ), [ $this, 'alpl_log_retention_days_field_render' ], 'alpl_activitylog_settings', 'alpl_activitylog_main_section' ); } public function alpl_log_retention_days_field_render() { $value = get_option( self::OPTION_NAME, 7 ); ?> alpl_write_log( $message, $user->ID ); } public function alpl_handle_user_logout() { $user_id = get_current_user_id(); $message = __( 'User logged out', 'activitylog' ); $this->alpl_write_log( $message, $user_id ); } public function alpl_handle_transition_post_status( $new_status, $old_status, $post ) { if ( 'revision' === $post->post_type ) { return; } if ( ! $post->ID ) { return; } $label = ( 'page' === $post->post_type ) ? __( 'Page', 'activitylog' ) : __( 'Post', 'activitylog' ); if ( 'auto-draft' === $old_status && 'auto-draft' !== $new_status ) { $message = sprintf( // translators: 1: post type label, 2: post title, 3: post ID. __( 'New %1$s "%2$s" (ID %3$d) created', 'activitylog' ), $label, $post->post_title, (int) $post->ID ); $this->alpl_write_log( $message ); return; } if ( 'trash' === $new_status && 'trash' !== $old_status ) { $message = sprintf( // translators: 1: post type label, 2: post title, 3: post ID. __( '%1$s "%2$s" (ID %3$d) moved to Trash', 'activitylog' ), $label, $post->post_title, (int) $post->ID ); $this->alpl_write_log( $message ); return; } if ( 'auto-draft' !== $new_status && 'trash' !== $new_status ) { $message = sprintf( // translators: 1: post type label, 2: post title, 3: post ID. __( '%1$s "%2$s" (ID %3$d) updated', 'activitylog' ), $label, $post->post_title, (int) $post->ID ); $this->alpl_write_log( $message ); } } public function alpl_handle_delete_post( $post_id ) { $post = get_post( $post_id ); if ( ! $post ) { return; } if ( 'revision' === $post->post_type ) { return; } $label = ( 'page' === $post->post_type ) ? __( 'Page', 'activitylog' ) : __( 'Post', 'activitylog' ); $message = sprintf( // translators: 1: post type label, 2: post title, 3: post ID. __( '%1$s "%2$s" (ID %3$d) permanently deleted', 'activitylog' ), $label, $post->post_title, (int) $post_id ); $this->alpl_write_log( $message ); } public function alpl_handle_plugin_activated( $plugin, $network_wide ) { $plugin_name = $this->alpl_get_plugin_name( $plugin ); // translators: %s: plugin name. $message = sprintf( __( 'Plugin "%s" was activated.', 'activitylog' ), $plugin_name ); $this->alpl_write_log( $message ); } public function alpl_handle_plugin_deactivated( $plugin, $network_wide ) { $plugin_name = $this->alpl_get_plugin_name( $plugin ); // translators: %s: plugin name. $message = sprintf( __( 'Plugin "%s" was deactivated.', 'activitylog' ), $plugin_name ); $this->alpl_write_log( $message ); } public function alpl_handle_plugin_deleted( $plugin ) { $plugin_name = $this->alpl_get_plugin_name( $plugin ); // translators: %s: plugin name. $message = sprintf( __( 'Plugin "%s" was deleted.', 'activitylog' ), $plugin_name ); $this->alpl_write_log( $message ); } private function alpl_get_plugin_name( $plugin_path ) { if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } $all_plugins = get_plugins(); return isset( $all_plugins[ $plugin_path ] ) ? $all_plugins[ $plugin_path ]['Name'] : $plugin_path; } private function alpl_write_log( $action, $user_id = 0 ) { if ( ! $user_id ) { $user_id = get_current_user_id(); } $user = get_user_by( 'ID', $user_id ); $user_login = $user ? $user->user_login : __( 'Unknown', 'activitylog' ); $date_time = current_time( 'mysql' ); $log_entry = sprintf( "%s | %s | %s\n", $date_time, $user_login, $action ); $this->alpl_append_to_log_file( $log_entry ); $this->alpl_cleanup_logs(); } private function alpl_cleanup_logs() { $retention_days = (int) get_option( self::OPTION_NAME, 7 ); if ( $retention_days <= 0 ) { return; } if ( ! $this->alpl_file_exists( $this->log_file_path ) ) { return; } $lines = $this->alpl_get_file_lines( $this->log_file_path ); $now = current_time( 'timestamp' ); $new_lines = []; foreach ( $lines as $line ) { $parts = explode( '|', $line, 3 ); if ( count( $parts ) < 3 ) { continue; } $date_time_str = trim( $parts[0] ); $log_timestamp = strtotime( $date_time_str ); if ( false === $log_timestamp ) { continue; } $diff_days = ( $now - $log_timestamp ) / DAY_IN_SECONDS; if ( $diff_days <= $retention_days ) { $new_lines[] = $line; } } $content = implode( "\n", $new_lines ) . "\n"; $this->alpl_write_file_contents( $this->log_file_path, $content ); } public function alpl_register_admin_menu() { add_menu_page( __( 'Activity Log', 'activitylog' ), __( 'Activity Log', 'activitylog' ), 'manage_options', 'activitylog', [ $this, 'alpl_render_admin_page' ], 'dashicons-admin-site', 80 ); add_submenu_page( 'activitylog', __( 'Activity Log Settings', 'activitylog' ), __( 'Settings', 'activitylog' ), 'manage_options', 'alpl_activitylog_settings', [ $this, 'alpl_render_settings_page' ] ); } public function alpl_render_admin_page() { if ( ! current_user_can( 'manage_options' ) ) { return; } $filter = isset( $_GET['filter'] ) ? sanitize_text_field( $_GET['filter'] ) : 'all'; ?>
' . esc_html__( 'No log file found.', 'activitylog' ) . '
'; echo '' . esc_html__( 'No log entries found.', 'activitylog' ) . '
'; echo ''; return; } $filtered_lines = []; foreach ( $all_lines as $line ) { $line = trim( $line ); if ( empty( $line ) ) { continue; } $parts = explode( '|', $line, 3 ); if ( count( $parts ) < 3 ) { continue; } $action = trim( $parts[2] ); if ( $filter === 'all' ) { $filtered_lines[] = $line; } elseif ( $filter === 'login' ) { if ( stripos( $action, 'logged in' ) !== false || stripos( $action, 'logged out' ) !== false ) { $filtered_lines[] = $line; } } elseif ( $filter === 'publication' ) { if ( stripos( $action, 'Post' ) !== false || stripos( $action, 'Page' ) !== false ) { $filtered_lines[] = $line; } } elseif ( $filter === 'plugin' ) { if ( stripos( $action, 'Plugin' ) !== false ) { $filtered_lines[] = $line; } } elseif ( $filter === 'user' ) { if ( stripos( $action, 'User' ) !== false && stripos( $action, 'logged in' ) === false && stripos( $action, 'logged out' ) === false ) { $filtered_lines[] = $line; } } } $all_lines = array_reverse( $filtered_lines ); $lines_per_page = 20; $total_lines = count( $all_lines ); $total_pages = ceil( $total_lines / $lines_per_page ); $paged = isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1; if ( $paged < 1 ) { $paged = 1; } if ( $paged > $total_pages ) { $paged = $total_pages; } $offset = ( $paged - 1 ) * $lines_per_page; $lines_for_page = array_slice( $all_lines, $offset, $lines_per_page ); ?>' . esc_html__( 'Logs cleared successfully.', 'activitylog' ) . '
' . esc_html__( 'Log file not found.', 'activitylog' ) . '