/home/vianto5/ceibaresidencial.mx/wp-content/plugins/wpforms/src/Pro/Admin/Entries/Import
NameSizeModeActions
FieldPreparer/-0755rm
Source/-0755rm
Ajax.php154170644editdlrm
EntryImporter.php440360644editdlrm
FailedEntriesCsv.php45160644editdlrm
Import.php61360644editdlrm
ImportSession.php45350644editdlrm
Edit: /home/vianto5/ceibaresidencial.mx/wp-content/plugins/wpforms/src/Pro/Admin/Entries/Import/Ajax.php (15417B)
failed_entries_csv = new FailedEntriesCsv(); } /** * Initialize hooks if conditions are met for the current user. * * @since 1.10.1 */ public function init(): void { if ( ! wpforms_is_admin_ajax() ) { return; } $this->hooks(); } /** * Register AJAX hooks. * * @since 1.10.1 */ private function hooks(): void { add_action( 'wp_ajax_wpforms_entries_import_get_plugin_forms', [ $this, 'ajax_get_plugin_forms' ] ); add_action( 'wp_ajax_wpforms_import_load_plugin_import', [ $this, 'ajax_load_plugin_import' ] ); add_action( 'wp_ajax_wpforms_import_load_file_import', [ $this, 'ajax_load_file_import' ] ); add_action( 'wp_ajax_wpforms_import_chunk', [ $this, 'ajax_import_chunk' ] ); add_action( 'wp_ajax_wpforms_import_cancel', [ $this, 'ajax_import_cancel' ] ); } /** * AJAX handler for getting forms from a plugin. * * @since 1.10.1 */ public function ajax_get_plugin_forms(): void { $this->validate_permission(); // phpcs:ignore WordPress.Security.NonceVerification.Missing $plugin = isset( $_POST['plugin'] ) ? sanitize_key( $_POST['plugin'] ) : ''; if ( empty( $plugin ) ) { wp_send_json_error( [ 'message' => esc_html__( 'No plugin specified.', 'wpforms' ) ] ); } $source = Plugins::get_by_slug( $plugin ); if ( ! $source ) { wp_send_json_error( [ 'message' => esc_html__( 'Invalid plugin.', 'wpforms' ) ] ); } wp_send_json_success( [ 'forms' => $source->get_forms() ] ); } /** * AJAX handler for validating plugin import. * * Returns source fields, destination fields, and entry count for mapping. * * @since 1.10.1 */ public function ajax_load_plugin_import(): void { $this->validate_permission(); $this->set_form_id(); // phpcs:disable WordPress.Security.NonceVerification.Missing $plugin = isset( $_POST['plugin'] ) ? sanitize_key( $_POST['plugin'] ) : ''; $source_form_id = isset( $_POST['source_form_id'] ) ? absint( $_POST['source_form_id'] ) : 0; // phpcs:enable WordPress.Security.NonceVerification.Missing if ( empty( $plugin ) || empty( $source_form_id ) ) { wp_send_json_error( esc_html__( 'Missing required parameters.', 'wpforms' ) ); } if ( $plugin === 'wpforms' && $source_form_id === $this->destination_form_id ) { wp_send_json_error( esc_html__( 'Source and destination forms cannot be the same.', 'wpforms' ) ); } try { $source = EntryImporter::get_source( $plugin, [ $source_form_id ] ); $this->send_import_init_response( $source, $plugin ); } catch ( Exception $e ) { wp_send_json_error( $e->getMessage() ); } } /** * Handle the validate file request. * * @since 1.10.1 */ public function ajax_load_file_import(): void { $this->validate_permission(); $this->set_form_id(); // phpcs:disable WordPress.Security.NonceVerification.Missing $file_path = isset( $_FILES['file']['tmp_name'] ) ? sanitize_text_field( wp_unslash( $_FILES['file']['tmp_name'] ) ) : ''; $extension = isset( $_FILES['file']['name'] ) ? pathinfo( sanitize_file_name( wp_unslash( $_FILES['file']['name'] ) ), PATHINFO_EXTENSION ) : ''; // phpcs:enable WordPress.Security.NonceVerification.Missing $real_path = realpath( $file_path ); if ( $real_path === false ) { wp_send_json_error( esc_html__( 'No file found.', 'wpforms' ) ); } try { $source = EntryImporter::get_source( $extension, [ $real_path ] ); $this->send_import_init_response( $source, $extension ); } catch ( Exception $e ) { wpforms_log( 'Entry import init failed', $e->getMessage(), [ 'type' => [ 'entry', 'error' ] ] ); wp_send_json_error( [ 'message' => $e->getMessage(), 'error_type' => 'file_validation', ] ); } } /** * Handle a chunk request: process 25 entries, advance session cursor. * * Expected POST params: request_id, nonce. * * @since 1.10.1 */ public function ajax_import_chunk(): void { $this->validate_permission(); $session = $this->get_import_session(); // phpcs:disable WordPress.Security.NonceVerification.Missing if ( empty( $_POST['map'] ) || ! is_array( $_POST['map'] ) ) { wp_send_json_error( esc_html__( 'No mapped fields.', 'wpforms' ) ); } $map = []; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput foreach ( $_POST['map'] as $destination_field_id => $source_field_id ) { $map[ wpforms_sanitize_key( $destination_field_id ) ] = wpforms_sanitize_key( $source_field_id ); } // phpcs:enable WordPress.Security.NonceVerification.Missing if ( $session->get_data( 'status' ) === 'failed' ) { wp_send_json_error( esc_html__( 'Import session has already failed.', 'wpforms' ) ); } try { $source_identifier = $session->get_data( 'source_identifier' ) ?? $session->get_data( 'source_type' ); $source_args = $session->get_data( 'source_args', [] ); $source = EntryImporter::get_source( $source_identifier, $source_args ); $chunk_size = $this->get_chunk_size(); $result = $source->process_chunk( $session->get_data( 'cursor', 0 ), $chunk_size ); $importing = count( $result['entries'] ); $errors = $result['errors']; if ( $importing === 0 ) { $session->advance( $result['next_cursor'], 0, $errors ); $this->maybe_complete_import( $session ); $session->fail(); wp_send_json_error( [ 'message' => esc_html__( 'Import stopped. No entries for import.', 'wpforms' ), 'errors' => $errors, ] ); } $form_handler = wpforms()->obj( 'form' ); $form = $form_handler ? $form_handler->get( $this->destination_form_id ) : null; // Catch the case where the form was trashed or deleted after the mapping step. if ( ! $form instanceof WP_Post || $form->post_status !== 'publish' ) { $session->fail(); wp_send_json_error( [ 'message' => esc_html__( 'Import stopped. The selected form is no longer available.', 'wpforms' ), 'errors' => $errors, ] ); } $form_data = wpforms_decode( $form->post_content ); if ( empty( $form_data ) ) { $session->fail(); wp_send_json_error( [ 'message' => esc_html__( "Import stopped. WPForms form wasn't found.", 'wpforms' ), 'errors' => $errors, ] ); } $importer = new EntryImporter( $this->destination_form_id, $source_identifier, $this->failed_entries_csv ); $imported = $importer->import_entries( $result, $form_data, $map ); $errors = $result['errors']; $this->failed_entries_csv->save( $session ); $session->advance( $result['next_cursor'], $imported, $errors ); $this->maybe_complete_import( $session ); wp_send_json_success( [ 'total' => $session->get_data( 'total' ), 'imported' => $session->get_data( 'imported' ), 'is_complete' => false, ] ); } catch ( Exception $e ) { wpforms_log( 'Entry import chunk failed', $e->getMessage(), [ 'type' => [ 'entry', 'error' ] ] ); wp_send_json_error( $e->getMessage() ); } } /** * Handle a cancel request: delete the session transient. * * Expected POST params: request_id, nonce. * * @since 1.10.1 */ public function ajax_import_cancel(): void { $this->validate_permission(); $session = $this->get_import_session(); $session->delete(); wp_send_json_success(); } /** * Validate the form ID and user permissions. * * @since 1.10.1 */ private function set_form_id(): void { // phpcs:disable WordPress.Security.NonceVerification.Missing if ( empty( $_POST['form_id'] ) ) { wp_send_json_error( esc_html__( 'Form ID is required.', 'wpforms' ) ); } $this->destination_form_id = absint( $_POST['form_id'] ); // phpcs:enable WordPress.Security.NonceVerification.Missing $this->validate_destination_form_permission(); $this->validate_destination_form_exists(); } /** * Ensure the selected destination form still exists. * * Catches the case where the form was deleted in another tab between * the user picking it and clicking Continue. * * @since 1.10.1 */ private function validate_destination_form_exists(): void { $form_handler = wpforms()->obj( 'form' ); $form = $form_handler ? $form_handler->get( $this->destination_form_id ) : null; if ( ! $form instanceof WP_Post || $form->post_status !== 'publish' ) { wp_send_json_error( esc_html__( 'Import stopped. The selected form is no longer available.', 'wpforms' ) ); } } /** * Validate user permissions for the destination form during entry import. * * @since 1.10.1 */ private function validate_destination_form_permission(): void { if ( wpforms_current_user_can( 'edit_entries_form_single', $this->destination_form_id ) === false ) { wp_send_json_error( esc_html__( 'You do not have permission to import entries for current form.', 'wpforms' ) ); } } /** * Validate user has permission to import entries for the current form. * * @since 1.10.1 */ private function validate_permission(): void { if ( ! check_ajax_referer( self::NONCE_ACTION, 'nonce', false ) ) { wp_send_json_error( esc_html__( 'Security check failed.', 'wpforms' ) ); } $permission_message = __( 'You do not have permission to import entries.', 'wpforms' ); if ( ! wpforms_current_user_can( [ 'edit_forms', 'view_entries' ] ) ) { wp_send_json_error( esc_html( $permission_message ) ); } } /** * Retrieve and validate the import session with a permission check. * * @since 1.10.1 * * @return ImportSession */ private function get_import_session(): ImportSession { // phpcs:disable WordPress.Security.NonceVerification.Missing if ( empty( $_POST['request_id'] ) ) { wp_send_json_error( esc_html__( 'Request ID is required.', 'wpforms' ) ); } $request_id = sanitize_text_field( wp_unslash( $_POST['request_id'] ) ); // phpcs:enable WordPress.Security.NonceVerification.Missing $session = new ImportSession( $request_id ); if ( ! $session->load() ) { wp_send_json_error( esc_html__( 'Import session not found or expired.', 'wpforms' ) ); } $this->destination_form_id = $session->get_data( 'form_id' ); $this->validate_destination_form_permission(); return $session; } /** * Create an import session and send an initialization response. * * @since 1.10.1 * * @param AbstractSource $source The import source. * @param string $source_identifier Source identifier (plugin slug or file extension). */ private function send_import_init_response( AbstractSource $source, string $source_identifier ): void { // Stop early when the source has no entries — there is nothing to map. if ( $source->get_total() < 1 ) { wp_send_json_error( esc_html__( 'Import stopped. No entries for import.', 'wpforms' ) ); } $session = ImportSession::create( $source, $this->destination_form_id, $source_identifier ); $importer = new EntryImporter( $this->destination_form_id, $source_identifier, $this->failed_entries_csv ); $tasks = wpforms()->obj( 'tasks' ); $destination_fields = $importer->get_destination_fields(); if ( $source instanceof AbstractFileSource ) { $destination_fields[] = [ 'key' => 'entry_date', 'label' => esc_html__( 'Entry Date', 'wpforms' ), 'type' => 'meta', 'default' => [ 'value' => 'current', 'label' => esc_html__( 'Date/Time of Import', 'wpforms' ), ], ]; } if ( $tasks && ! $tasks->is_scheduled( ImportCleanupTask::ACTION ) ) { $tasks ->create( ImportCleanupTask::ACTION ) ->recurring( time() + ImportCleanupTask::INTERVAL, ImportCleanupTask::INTERVAL ) ->params() ->register(); } wp_send_json_success( [ 'request_id' => $session->get_request_id(), 'source_fields' => $source->get_fields(), 'destination_fields' => $destination_fields, 'total' => $source->get_total(), ] ); } /** * Check if the import session is complete and send a success response. * * @since 1.10.1 * * @param ImportSession $session Instance of the import session being checked. */ private function maybe_complete_import( ImportSession $session ): void { if ( ! $session->is_complete() ) { return; } $errors = $this->sort_errors( (array) $session->get_data( 'errors' ) ); wp_send_json_success( [ 'total' => $session->get_data( 'total' ), 'imported' => $session->get_data( 'imported' ), 'skipped' => $session->get_data( 'total' ) - $session->get_data( 'imported' ), 'with_issue' => $this->count_entries_with_issue( $errors ), 'download_failed_entries_csv_url' => $this->failed_entries_csv->get_download_url( $session ), 'errors' => $errors, 'is_complete' => true, ] ); } /** * Count unique entries that have at least one error. * * A single entry can produce multiple errors (e.g., several invalid fields), * so we deduplicate by entry ID. * * @since 1.10.1 * * @param array $errors List of error items. * * @return int */ private function count_entries_with_issue( array $errors ): int { return count( array_unique( array_column( $errors, 'entry_id' ) ) ); } /** * Sort import errors so destination errors come first, preserving original order within each group. * * @since 1.10.1 * * @param array $errors List of error items, each with a `type` of `destination` or `source`. * * @return array */ private function sort_errors( array $errors ): array { if ( empty( $errors ) ) { return $errors; } $destination = []; $source = []; foreach ( $errors as $error ) { if ( ( $error['type'] ?? '' ) === 'destination' ) { $destination[] = $error; continue; } $source[] = $error; } return array_merge( $destination, $source ); } /** * Retrieve the chunk size for processing data. * * @since 1.10.1 * * @return int */ private function get_chunk_size(): int { /** * Allow changing the chunk size for entry import. * * @since 1.10.1 * * @param int $chunk_size The number of entries to process in each chunk. Default: 25. */ return (int) apply_filters( 'wpforms_pro_admin_entries_import_ajax_get_chunk_size', self::CHUNK_SIZE ); } }