<?php
/**
 * Import Functions
 *
 * These are functions are used for import data into Easy Digital Downloads.
 *
 * @package     EDD\Admin\Import
 * @copyright   Copyright (c) 2018, Sandhills Development, LLC
 * @license     https://opensource.org/licenses/gpl-2.0.php GNU Public License
 */

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit; // @codeCoverageIgnore

use EDD\Utils\FileSystem;
use EDD\Utils\Validators\FileType\CSV;

/**
 * Upload an import file with ajax
 *
 * @since 2.6
 * @return void
 */
function edd_do_ajax_import_file_upload() {

	if ( ! wp_verify_nonce( $_REQUEST['edd_ajax_import'], 'edd_ajax_import' ) ) {
		wp_send_json_error( array( 'error' => __( 'Nonce verification failed.', 'easy-digital-downloads' ) ) );
	}

	if ( empty( $_POST['edd-import-class'] ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'Missing import parameters. Import class must be specified.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	if ( ! function_exists( 'wp_handle_upload' ) ) {
		require_once ABSPATH . 'wp-admin/includes/file.php';
	}

	require_once EDD_PLUGIN_DIR . 'includes/admin/import/class-batch-import.php';

	$importer_class   = sanitize_text_field( $_POST['edd-import-class'] );
	$is_class_allowed = edd_importer_is_class_allowed( $importer_class );
	if ( false === $is_class_allowed ) {
		wp_send_json_error( array( 'error' => __( 'Invalid importer class supplied', 'easy-digital-downloads' ) ) );
	}

	do_action( 'edd_batch_import_class_include', $importer_class );

	$import = new $importer_class();

	// The import class checks for the user's capability.
	if ( ! $import->can_import() ) {
		wp_send_json_error( array( 'error' => __( 'You do not have permission to import data', 'easy-digital-downloads' ) ) );
	}

	if ( empty( $_FILES['edd-import-file'] ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'Missing import file. Please provide an import file.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	if ( ! FileSystem::file_exists( $_FILES['edd-import-file']['tmp_name'] ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'Something went wrong during the upload process, please try again.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	// Validate the uploaded import file.
	$csv = new CSV();
	if ( ! $csv->is_valid( $_FILES['edd-import-file']['tmp_name'], $_FILES['edd-import-file']['name'] ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'The file you uploaded does not appear to be a CSV file.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	// Upload to the protected exports directory under a single validated
	// extension, so a crafted name like "shell.php.csv" cannot persist as-is.
	$file_name   = $csv->sanitize_filename( $_FILES['edd-import-file']['name'] );
	$exports_dir = edd_get_exports_dir();
	$file_path   = trailingslashit( $exports_dir ) . wp_unique_filename( $exports_dir, $file_name );

	// Move the uploaded file to the protected directory.
	if ( move_uploaded_file( $_FILES['edd-import-file']['tmp_name'], $file_path ) ) {
		$import_file = array(
			'file' => $file_path,
			'url'  => '',
			'type' => 'text/csv',
		);
	} else {
		wp_send_json_error(
			array(
				'error' => __( 'Failed to move uploaded file to protected directory.', 'easy-digital-downloads' ),
			)
		);
	}

	if ( $import_file && empty( $import_file['error'] ) ) {

		$import->set_up_csv( $import_file['file'] );
		wp_send_json_success(
			array(
				'form'      => $_POST,
				'class'     => $importer_class,
				'upload'    => $import_file,
				'first_row' => $import->get_first_row(),
				'columns'   => $import->get_columns(),
				'nonce'     => wp_create_nonce( 'edd_ajax_import' ),
			)
		);

	} else {

		/**
		 * Error generated by file upload.
		 */

		wp_send_json_error( array( 'error' => $import_file['error'] ) );
	}

	exit;
}
add_action( 'edd_upload_import_file', 'edd_do_ajax_import_file_upload' );

/**
 * Process batch imports via ajax
 *
 * @since 2.6
 * @return void
 */
function edd_do_ajax_import() {

	require_once EDD_PLUGIN_DIR . 'includes/admin/import/class-batch-import.php';

	if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'edd_ajax_import' ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'Nonce verification failed.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	if ( empty( $_REQUEST['class'] ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'Missing import parameters. Import class must be specified.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	$file = sanitize_text_field( wp_unslash( $_REQUEST['upload']['file'] ) );

	$exports_dir = trailingslashit( edd_get_exports_dir() );
	if ( false !== strpos( $file, '..' ) || 0 !== strpos( $file, $exports_dir ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'The import file path is invalid.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	if ( ! FileSystem::file_exists( $file ) ) {
		wp_send_json_error(
			array(
				'error'   => __( 'Something went wrong during the upload process, please try again.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	$mime_type_allowed = false;
	if ( is_callable( 'mime_content_type' ) ) {
		if ( in_array( mime_content_type( $file ), edd_importer_accepted_mime_types(), true ) ) {
			$mime_type_allowed = true;
		}
	} else {
		if ( wp_check_filetype( $file, edd_importer_accepted_mime_types() ) ) {
			$mime_type_allowed = true;
		}
	}

	if ( false === $mime_type_allowed ) {
		wp_send_json_error(
			array(
				'error'   => __( 'The file you uploaded does not appear to be a CSV file.', 'easy-digital-downloads' ),
				'request' => $_REQUEST,
			)
		);
	}

	$importer_class   = sanitize_text_field( $_REQUEST['class'] );
	$is_class_allowed = edd_importer_is_class_allowed( $importer_class );

	if ( ! $is_class_allowed ) {
		wp_send_json_error( array( 'error' => __( 'Invalid importer class supplied', 'easy-digital-downloads' ) ) );
	}

	do_action( 'edd_batch_import_class_include', $importer_class );

	$step         = absint( $_REQUEST['step'] );
	$import_class = $importer_class;
	$import       = new $import_class( '', $step );

	if ( ! $import->can_import() ) {
		wp_send_json_error( array( 'error' => __( 'You do not have permission to import data', 'easy-digital-downloads' ) ) );
	}
	$import->set_up_csv( $file );

	parse_str( $_REQUEST['mapping'], $map );

	$import->map_fields( $map['edd-import-field'] );

	$ret = $import->process_step( $step );

	$percentage = $import->get_percentage_complete();

	if ( $ret ) {

		$step += 1;
		wp_send_json_success(
			array(
				'step'       => $step,
				'percentage' => $percentage,
				'columns'    => $import->get_columns(),
				'mapping'    => $import->field_mapping,
				'total'      => $import->total,
			)
		);

	} elseif ( true === $import->is_empty ) {

		wp_send_json_error(
			array(
				'error' => __( 'No data found for import parameters', 'easy-digital-downloads' ),
			)
		);

	} else {

		// Import is complete - clean up the file.
		if ( FileSystem::file_exists( $file ) ) {
			FileSystem::get_fs()->delete( $file );
		}

		wp_send_json_success(
			array(
				'step'    => 'done',
				'message' => sprintf(
				/* translators: 1: URL to view imported items, 2: Import type label */
					__( 'Import complete! <a href="%1$s">View imported %2$s</a>.', 'easy-digital-downloads' ),
					esc_url( $import->get_list_table_url() ),
					esc_html( $import->get_import_type_label() )
				),
			)
		);

	}
}
add_action( 'wp_ajax_edd_do_ajax_import', 'edd_do_ajax_import' );

/**
 * Returns the array of accepted mime types for the importer.
 *
 * @since 3.0
 * @return array
 */
function edd_importer_accepted_mime_types() {
	return CSV::MIME_TYPES;
}

/**
 * Given an importer class name, is it allowed to process as an importer.
 *
 * @since 3.0.2
 *
 * @param string $import_class The class name to check.
 *
 * @return bool If the class is allowed to be used as an importer.
 */
function edd_importer_is_class_allowed( $import_class = '' ) {
	$allowed_importer_classes = edd_get_importer_accepted_classes();

	return in_array( $import_class, $allowed_importer_classes, true );
}

/**
 * Returns a list of allowed importer classes.
 *
 * @since 3.0.2
 *
 * @return array An array of class names to allow during imports.
 */
function edd_get_importer_accepted_classes() {
	return apply_filters(
		'edd_accepted_importer_classes',
		array(
			'EDD_Batch_Downloads_Import',
			'EDD_Batch_Payments_Import',
		)
	);
}
