type = $type;
if ( empty( $this->type ) ) {
add_action( 'admin_post_welcart_csv_upload', array( $this, 'handle_error' ) );
add_action( 'admin_post_welcart_csv_mapping', array( $this, 'handle_error' ) );
} else {
add_action( 'admin_post_welcart_csv_upload', array( $this, 'handle_csv_upload' ) );
add_action( 'admin_post_welcart_csv_mapping', array( $this, 'handle_csv_mapping' ) );
add_action( 'admin_post_download_csv_error_log', array( $this, 'download_error_log' ) );
add_action( 'wp_ajax_process_csv_chunk', array( $this, 'process_csv_chunk' ) );
$this->register_csv_import_handling_page();
}
}
/**
* Get instance
*
* @param string $type Import type.
* @return Welcart_CSV_Importer
*/
public static function get_instance( $type ) {
if ( null === self::$instance ) {
self::$instance = new Welcart_CSV_Importer( $type );
}
return self::$instance;
}
/**
* Set condition data
*
* @param array $condition Condition data.
*/
public function set_condition( $condition ) {
$this->page_title = isset( $condition['page_title'] ) ? $condition['page_title'] : __( 'Data Import', 'usces' );
$this->table_columns = isset( $condition['columns'] ) ? $condition['columns'] : array();
$this->meta_fields = isset( $condition['meta_fields'] ) ? $condition['meta_fields'] : array();
}
/**
* Add handling page
*/
public function register_csv_import_handling_page() {
add_submenu_page(
'wel-hidden-page', // Specify a fake parent page to hide from the menu.
__( 'Welcart CSV Import', 'usces' ),
__( 'Welcart CSV Import', 'usces' ),
'manage_options',
'welcart-csv-importer',
array( $this, 'handle_import_page_action' )
);
}
/**
* Switch page
*/
public function handle_import_page_action() {
if ( ! current_user_can( 'manage_options' ) ) {
$this->go_to_error_page( __( 'Permission error.', 'usces' ) . ' (#073)' );
}
check_admin_referer( 'welcart_csv_import', 'wc_nonce' );
$type = isset( $_GET['type'] ) ? sanitize_text_field( wp_unslash( $_GET['type'] ) ) : '';
if ( $this->type !== $type ) {
$this->render_error_page( __( 'Type does not match.', 'usces' ) . ' (#001)' );
}
$step = isset( $_GET['step'] ) ? sanitize_text_field( wp_unslash( $_GET['step'] ) ) : 'upload';
$import_id = isset( $_GET['import_id'] ) ? sanitize_text_field( wp_unslash( $_GET['import_id'] ) ) : '';
if ( ! $import_id && 'upload' !== $step ) {
$this->render_error_page( __( 'Invalid access.', 'usces' ) . ' (#050)' );
}
switch ( $step ) {
case 'upload':
$this->render_upload_form( $type );
break;
case 'preview':
$encoding = isset( $_GET['encoding'] ) ? sanitize_text_field( wp_unslash( $_GET['encoding'] ) ) : 'UTF-8';
$this->render_preview_and_mapping( $type, $import_id, $encoding );
break;
case 'import':
$this->render_import_progress( $type, $import_id );
break;
case 'result':
$this->render_result_page( $type, $import_id );
break;
case 'error':
$this->render_error_page();
break;
default:
$this->render_error_page( __( 'Invalid step. (#002)', 'usces' ) );
}
}
/**
* Upload form
*
* @param string $type Import type.
*/
private function render_upload_form( $type ) {
if ( $this->type !== $type ) {
$this->render_error_page( __( 'Type does not match.', 'usces' ) . ' (#005)' );
}
?>
go_to_error_page( __( 'Permission error.', 'usces' ) . ' (#072)' );
}
check_admin_referer( 'welcart_csv_import', 'wc_nonce' );
$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
if ( $this->type !== $type ) {
$this->go_to_error_page( __( 'Type does not match.', 'usces' ) . ' (#007)' );
}
if ( false !== $this->file_upload_error() ) {
$message = $this->file_upload_error();
$this->go_to_error_page( $message . __( ' (#008)', 'usces' ) );
}
$file_name_org = isset( $_FILES['csv_file']['name'] ) ? sanitize_text_field( wp_unslash( $_FILES['csv_file']['name'] ) ) : '';
if ( empty( $file_name_org ) ) {
$this->go_to_error_page( __( 'Failed to get file name.', 'usces' ) . ' (#009)' );
}
$file_name_org = sanitize_file_name( basename( urldecode( $file_name_org ) ) );
$temp_file_name = wp_unique_filename( WEL_IMPORT_UPLOADS_DIR, $file_name_org );
$uploaded_file = WEL_IMPORT_UPLOADS_DIR . '/' . $temp_file_name;
$allowed_types = array( 'text/csv', 'application/zip' );
$file_type = wp_check_filetype_and_ext( $uploaded_file, $file_name_org );
if ( ! in_array( $file_type['type'], $allowed_types, true ) ) {
$this->go_to_error_page( __( 'Please specify a CSV or ZIP file.', 'usces' ) . ' (#009)' );
}
// Delete all CSV files.
$files = glob( WEL_IMPORT_UPLOADS_DIR . '/*.csv' );
if ( is_array( $files ) ) {
foreach ( $files as $file ) {
if ( is_file( $file ) ) {
wp_delete_file( $file );
}
}
}
$tmp_name_org = isset( $_FILES['csv_file']['tmp_name'] ) ? sanitize_text_field( wp_unslash( $_FILES['csv_file']['tmp_name'] ) ) : '';
if ( empty( $tmp_name_org ) || ! move_uploaded_file( $tmp_name_org, $uploaded_file ) ) {
$this->go_to_error_page( __( 'Failed to save file.', 'usces' ) . ' (#009)' );
}
$ext = strtolower( pathinfo( $file_name_org, PATHINFO_EXTENSION ) );
if ( 'zip' === $ext ) {
// Extract CSV from ZIP.
$zip = new ZipArchive();
if ( true === $zip->open( $uploaded_file ) ) {
if ( $zip->numFiles > 2 ) {
$this->go_to_error_page( __( 'Too many files in ZIP.', 'usces' ) . ' (#030)' );
}
$csv_found = false;
for ( $i = 0; $i < $zip->numFiles; $i++ ) {
$entry = $zip->getNameIndex( $i );
if ( 'csv' === strtolower( pathinfo( $entry, PATHINFO_EXTENSION ) ) ) {
$csv_file_name = basename( $entry );
$temp_file_name = wp_unique_filename( WEL_IMPORT_UPLOADS_DIR, $csv_file_name );
$temp_file = WEL_IMPORT_UPLOADS_DIR . '/' . $temp_file_name;
if ( ! copy( "zip://{$uploaded_file}#{$entry}", $temp_file ) ) {
$this->go_to_error_page( __( 'Failed to extract CSV file from ZIP.', 'usces' ) . ' (#015)' );
}
$csv_found = true;
break;
} else {
$this->go_to_error_page( __( 'CSV file not found in ZIP.', 'usces' ) . ' (#031)' );
}
}
$zip->close();
wp_delete_file( $uploaded_file );
if ( ! $csv_found ) {
$this->go_to_error_page( __( 'CSV file not found in ZIP.', 'usces' ) . ' (#012)' );
}
$csv_name = $csv_file_name;
} else {
$this->go_to_error_page( __( 'Unable to open ZIP file.', 'usces' ) . ' (#013)' );
}
} else {
$temp_file = $uploaded_file;
$csv_name = $file_name_org;
}
$import_id = uniqid();
$data = array(
'temp_file' => $temp_file_name,
'csv_name' => $csv_name,
);
set_transient( $this->import_transient_prefix . $import_id, $data, 30 * MINUTE_IN_SECONDS );
$redirect_url = add_query_arg(
array(
'page' => 'welcart-csv-importer',
'step' => 'preview',
'type' => $this->type,
'import_id' => $import_id,
'wc_nonce' => wp_create_nonce( 'welcart_csv_import' ),
),
admin_url( 'admin.php' )
);
wp_safe_redirect( $redirect_url );
exit;
}
/**
* Preview & Mapping page
*
* @param string $type Import type.
* @param string $import_id Import ID.
* @param string $encoding Character encoding.
*/
private function render_preview_and_mapping( $type, $import_id, $encoding ) {
$data = get_transient( $this->import_transient_prefix . $import_id );
if ( ! $data ) {
$this->render_error_page( __( 'Import session not found.', 'usces' ) . ' (#051)' );
}
$temp_file_name = sanitize_file_name( basename( sanitize_text_field( wp_unslash( $data['temp_file'] ) ) ) );
$temp_file = WEL_IMPORT_UPLOADS_DIR . '/' . $temp_file_name;
$csv_name = sanitize_text_field( wp_unslash( $data['csv_name'] ) );
if ( ! file_exists( $temp_file ) ) {
$this->render_error_page( __( 'Temporary file not found.', 'usces' ) . ' ' . __( 'Please start over from the beginning.', 'usces' ) . ' (#017)' );
}
// To handle large files with low memory, do not use WP_Filesystem.
$handle = fopen( $temp_file, 'r' );
if ( false === $handle ) {
$this->render_error_page( __( 'Failed to read file.', 'usces' ) . ' ' . __( 'Please start over from the beginning.', 'usces' ) . ' (#018)' );
}
$sample = fread( $handle, 1000 );
$enc_type = mb_detect_encoding( $sample, array( 'SJIS-win', 'SJIS', 'UTF-8', 'EUC-JP' ), true );
rewind( $handle );
if ( 'SJIS' === $encoding && 'UTF-8' !== $enc_type ) {
stream_filter_append( $handle, 'convert.iconv.sjis-win/utf-8' );
}
$rows = array();
$max_rows = 6; // Retrieve maximum 6 rows for preview.
$i = 0;
while ( $i < $max_rows ) {
$data = fgetcsv( $handle );
if ( false === $data ) {
// End of file reached.
break;
}
// Exclude empty rows (allowing '0').
if ( ! empty( array_filter( $data, 'strlen' ) ) ) {
// Remove BOM from first field in first row.
if ( 0 === $i && isset( $data[0] ) && 0 === strncmp( $data[0], "\xEF\xBB\xBF", 3 ) ) {
$data[0] = substr( $data[0], 3 );
}
$rows[] = $data;
++$i;
}
}
fclose( $handle );
if ( 'SJIS' === $encoding && 'UTF-8' === $enc_type ) {
$rows = array();
}
$num_columns = ! empty( $rows ) ? count( $rows[0] ) : 0;
$num_all_rows = $this->count_csv_lines( $temp_file, $encoding );
?>