| @@ -8,11 +8,10 @@ | ||
| 8 | 8 | namespace WP_Defender\Controller; |
| 9 | 9 | |
| 10 | 10 | use DateTime; |
| 11 | 11 | use Exception; |
| 12 | -use DateInterval; | |
| 12 | +use Generator; | |
| 13 | 13 | use WP_Defender\Event; |
| 14 | -use Calotes\Helper\HTTP; | |
| 15 | 14 | use WP_Defender\Traits\User; |
| 16 | 15 | use Calotes\Component\Request; |
| 17 | 16 | use Calotes\Component\Response; |
| 18 | 17 | use Calotes\Helper\Array_Cache; |
| @@ -21,8 +20,9 @@ | ||
| 21 | 20 | use WP_Defender\Model\Audit_Log; |
| 22 | 21 | use WP_Defender\Behavior\WPMUDEV; |
| 23 | 22 | use WP_Defender\Component\Network_Cron_Manager; |
| 24 | 23 | use WP_Defender\Model\Notification\Audit_Report; |
| 24 | +use WP_Defender\Component\Export\Csv; | |
| 25 | 25 | use WP_Defender\Component\Config\Config_Hub_Helper; |
| 26 | 26 | use WP_Defender\Model\Setting\Audit_Logging as Model_Audit_Logging; |
| 27 | 27 | |
| 28 | 28 | /** |
| @@ -199,9 +199,11 @@ | ||
| 199 | 199 | * @throws Exception If there is an error during export. |
| 200 | 200 | * @defender_route |
| 201 | 201 | */ |
| 202 | 202 | public function export_as_csv(): void { |
| 203 | - $result = $this->fetch_logs( defender_get_data_from_request( null, 'g' ), false ); | |
| 203 | + $params = defender_get_data_from_request( null, 'g' ); | |
| 204 | + $user_id = ''; | |
| 205 | + $result = $this->fetch_logs( $params, 1, $user_id, 1000 ); | |
| 204 | 206 | |
| 205 | 207 | if ( is_wp_error( $result ) ) { |
| 206 | 208 | wp_send_json_error( |
| 207 | 209 | array( |
| @@ -209,10 +211,8 @@ | ||
| 209 | 211 | ) |
| 210 | 212 | ); |
| 211 | 213 | } |
| 212 | 214 | |
| 213 | - // WP_Filesystem class doesn't directly provide a function for opening a stream to php://memory with the 'w' mode. | |
| 214 | - $fp = fopen( 'php://memory', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen | |
| 215 | 215 | $headers = array( |
| 216 | 216 | esc_html__( 'Summary', 'defender-security' ), |
| 217 | 217 | esc_html__( 'Date / Time', 'defender-security' ), |
| 218 | 218 | esc_html__( 'Context', 'defender-security' ), |
| @@ -219,32 +219,56 @@ | ||
| 219 | 219 | esc_html__( 'Type', 'defender-security' ), |
| 220 | 220 | esc_html__( 'IP address', 'defender-security' ), |
| 221 | 221 | esc_html__( 'User', 'defender-security' ), |
| 222 | 222 | ); |
| 223 | - fputcsv( $fp, $headers, ',', '"', '\\' ); | |
| 224 | - foreach ( $this->format_log_rows( $result ) as $row ) { | |
| 225 | - $vars = array( | |
| 226 | - $row['msg'], | |
| 227 | - is_array( $row['timestamp'] ) | |
| 228 | - ? $this->format_date_time( $row['timestamp'][0] ) | |
| 229 | - : $this->format_date_time( $row['timestamp'] ), | |
| 230 | - $row['context'], | |
| 231 | - $row['action_type'], | |
| 232 | - $row['ip'], | |
| 233 | - $row['user'], | |
| 234 | - ); | |
| 235 | - fputcsv( $fp, $vars, ',', '"', '\\' ); | |
| 223 | + try { | |
| 224 | + Csv::to_browser( 'audit-logs', $this->get_export_rows( $params, $result ), $headers ); | |
| 225 | + } catch ( \RuntimeException $e ) { | |
| 226 | + $this->log( $e->getMessage(), 'audit-logging' ); | |
| 236 | 227 | } |
| 237 | - $filename = 'wdf-audit-logs-export-' . wp_date( 'ymdHis' ) . '.csv'; | |
| 238 | - fseek( $fp, 0 ); | |
| 239 | - header( 'Content-Type: text/csv' ); | |
| 240 | - header( 'Content-Disposition: attachment; filename="' . $filename . '";' ); | |
| 241 | - // Make php send the generated csv lines to the browser. | |
| 242 | - fpassthru( $fp ); | |
| 243 | - exit(); | |
| 244 | 228 | } |
| 245 | 229 | |
| 246 | 230 | /** |
| 231 | + * Generates audit log export rows in database-backed pages. | |
| 232 | + * | |
| 233 | + * @param array $params Request filters. | |
| 234 | + * @param array $logs First page of audit logs. | |
| 235 | + * | |
| 236 | + * @return Generator | |
| 237 | + * @throws Exception If there is an error while fetching logs. | |
| 238 | + */ | |
| 239 | + private function get_export_rows( array $params, array $logs ): Generator { | |
| 240 | + $page = 1; | |
| 241 | + $per_page = 1000; | |
| 242 | + $user_id = ''; | |
| 243 | + | |
| 244 | + do { | |
| 245 | + if ( 1 < $page ) { | |
| 246 | + $logs = $this->fetch_logs( $params, $page, $user_id, $per_page ); | |
| 247 | + if ( is_wp_error( $logs ) ) { | |
| 248 | + throw new Exception( esc_html( $logs->get_error_message() ) ); | |
| 249 | + } | |
| 250 | + } | |
| 251 | + | |
| 252 | + foreach ( $this->format_log_rows( $logs ) as $row ) { | |
| 253 | + yield array( | |
| 254 | + $row['msg'], | |
| 255 | + is_array( $row['timestamp'] ) | |
| 256 | + ? $this->format_date_time( $row['timestamp'][0] ) | |
| 257 | + : $this->format_date_time( $row['timestamp'] ), | |
| 258 | + $row['context'], | |
| 259 | + $row['action_type'], | |
| 260 | + $row['ip'], | |
| 261 | + $row['user'], | |
| 262 | + ); | |
| 263 | + } | |
| 264 | + | |
| 265 | + $has_more = count( $logs ) === $per_page; | |
| 266 | + ++$page; | |
| 267 | + } while ( $has_more ); | |
| 268 | + } | |
| 269 | + | |
| 270 | + /** | |
| 247 | 271 | * We'll pass all the event logs into the db handler, so it writes down to db. |
| 248 | 272 | * Do it in shutdown runtime, so no delay time. |
| 249 | 273 | * |
| 250 | 274 | * @return void |
| @@ -394,9 +418,9 @@ | ||
| 394 | 418 | ); |
| 395 | 419 | |
| 396 | 420 | wp_enqueue_style( |
| 397 | 421 | $handle, |
| 398 | - WP_DEFENDER_BASE_URL . 'assets/css/showcase.css', | |
| 422 | + WP_DEFENDER_BASE_URL . 'assets/css/core-ui.css', | |
| 399 | 423 | array(), |
| 400 | 424 | DEFENDER_VERSION |
| 401 | 425 | ); |
| 402 | 426 | |