403 ) ); } check_admin_referer( self::ACTION ); $form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; $form = FormRepository::find( $form_id ); if ( ! $form ) { wp_die( esc_html__( 'Form not found.', 'fillaro' ), '', array( 'response' => 404 ) ); } $status = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : 'all'; $ids = isset( $_GET['ids'] ) ? array_filter( array_map( 'absint', explode( ',', sanitize_text_field( wp_unslash( $_GET['ids'] ) ) ) ) ) : array(); // Export what the Entries screen shows: same search, dates and field filters. $search = isset( $_GET['search'] ) ? sanitize_text_field( wp_unslash( $_GET['search'] ) ) : ''; $dates = array(); foreach ( array( 'after', 'before' ) as $key ) { $dates[ $key ] = isset( $_GET[ $key ] ) && preg_match( '/^\d{4}-\d{2}-\d{2}$/', sanitize_text_field( wp_unslash( $_GET[ $key ] ) ) ) ? sanitize_text_field( wp_unslash( $_GET[ $key ] ) ) : ''; } $filters = EntriesController::filters( isset( $_GET['filters'] ) ? sanitize_text_field( wp_unslash( $_GET['filters'] ) ) : '', $form ); $columns = array(); foreach ( $form['fields'] as $field ) { $type = Plugin::instance()->fields->get( $field['type'] ); if ( $type && $type->has_value() ) { $columns[] = array( $field, $type ); } } $filename = sanitize_file_name( sanitize_title( $form['title'] ) . '-entries-' . gmdate( 'Y-m-d' ) . '.csv' ); nocache_headers(); header( 'Content-Type: text/csv; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="' . $filename . '"' ); $out = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- Streaming to output. fwrite( $out, "\xEF\xBB\xBF" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite -- UTF-8 BOM for Excel. $header = array( __( 'Entry ID', 'fillaro' ), __( 'Submitted (UTC)', 'fillaro' ) ); foreach ( $columns as $col ) { $header[] = '' !== $col[0]['label'] ? $col[0]['label'] : $col[0]['key']; } $header[] = __( 'Page URL', 'fillaro' ); fputcsv( $out, array_map( array( $this, 'cell' ), $header ) ); $page = 1; do { $batch = EntryRepository::query( $form_id, array( 'page' => $page, 'per_page' => 200, 'status' => $status, 'ids' => $ids, 'search' => $search, 'after' => $dates['after'], 'before' => $dates['before'], 'filters' => $filters, 'order' => 'asc', ) ); foreach ( $batch['items'] as $entry ) { $row = array( $entry['id'], $entry['created_at'] ); foreach ( $columns as $col ) { $key = $col[0]['key']; $row[] = isset( $entry['values'][ $key ] ) ? $col[1]->to_text( $entry['values'][ $key ], $col[0] ) : ''; } $row[] = $entry['source_url']; fputcsv( $out, array_map( array( $this, 'cell' ), $row ) ); } ++$page; $fetched = count( $batch['items'] ); } while ( 200 === $fetched ); fclose( $out ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Streaming to output. exit; } /** * Neutralize spreadsheet formulas (CSV injection). * * @param mixed $value Cell. * @return string */ public function cell( $value ) { $value = (string) $value; if ( '' !== $value && in_array( $value[0], array( '=', '+', '-', '@', "\t", "\r" ), true ) ) { $value = "'" . $value; } return $value; } }