Description

The deleteuploadedfiles Class is designed to delete uploaded files subsequent to email notifications. This functionality is particularly useful when entry storage and saving to the Media Library are disabled.

WPForms strongly discourages modifying any parent theme files directly. Any alterations made directly to the parent theme are at risk of being overwritten during theme updates, resulting in the loss of customizations. It is advised to create and use a child theme for making any desired changes.

Methods

  1. Establish dependencies to support the Class by generating a file named class-delete-uploaded-files.php within the root directory of your theme.
  2. After creating this file, open your functions.php and insert the following snippet. Save the changes to your functions file.
    require __DIR__ . '/class-delete-uploaded-files.php';
    
    ( new \WPF\DeleteUploadedFiles() )->hooks();
    

Source

File: class-delete-uploaded-files.php

/**
 * Class deleteuploadedfiles to delete uploaded files from the server
 *
 * @link https://wpforms.com/developers/class-deleteuploadedfiles/
 */
<?php

namespace WPF;

class DeleteUploadedFiles {

	/**
	 * Should we delete files from the WordPress Media Library?
	 * Change the constant to true to delete files form the WordPress Media Library.
	 */
	const DELETE_MEDIA_FILES = false;

        /**
	* Add hooks.
	*/
	public function hooks() {
		add_action( 'wpforms_process_complete', [ $this, 'delete_attached_files' ], 10, 4 );
		add_filter( 'wpforms_html_field_value', [ $this, 'replace_html_field_value' ], 100, 4 );
		add_filter( 'wpforms_emails_notifications_plaintext_field_value', [ $this, 'replace_plaintext_field_value' ], 100, 3 );
		add_filter( 'wpforms_smarttags_process_field_id_value', [ $this, 'replace_field_id_smart_tags_value' ], 10, 5 );
		add_filter( 'wpforms_smarttags_process_field_value_id_value', [ $this, 'replace_field_value_id_smart_tags_value' ], 10, 5 );
	}

	/**
	 * Delete attached files after emails are sent if these files aren't stored in entries.
	 *
	 * @param array $fields    Fields data.
	 * @param array $entry     Form submission raw data ($_POST).
	 * @param array $form_data Form data and settings.
	 * @param int   $entry_id  Entry ID.
	 */
	public function delete_attached_files( $fields, $entry, $form_data, $entry_id ) {

		if ( ! $this->is_allowed_delete_files_after_sending_email( $form_data ) ) {
			return;
		}

		$delete_files_fields = $this->get_filtered_attached_files_fields( $form_data );

		if ( empty( $delete_files_fields ) ) {
			return;
		}

		foreach ( $delete_files_fields as $field_id ) {
			if ( empty( $fields[ $field_id ] ) ) {
				continue;
			}

			$field = $fields[ $field_id ];

			if ( self::DELETE_MEDIA_FILES ) {
				if ( ! empty( $field[ 'style' ] ) && $field[ 'style' ] === 'modern' ) {
					$is_media_field = false;

					foreach ( $field[ 'value_raw' ] as $file ) {
						if ( ! empty( $file[ 'attachment_id' ] ) ) {
							wp_delete_attachment( $file[ 'attachment_id' ], true );

							$is_media_field = true;
						}
					}

					if ( $is_media_field ) {
						continue;
					}
				}

				if ( ! empty( $field[ 'attachment_id' ] ) ) {
					wp_delete_attachment( $field[ 'attachment_id' ], true );

					continue;
				}
			}

			$files_paths = \WPForms_Field_File_Upload::get_entry_field_file_paths( $form_data[ 'id' ], $field );

			if ( empty( $files_paths ) ) {
				continue;
			}

			foreach ( $files_paths as $path ) {
				// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, WordPress.WP.AlternativeFunctions.unlink_unlink
				@unlink( $path );
			}
		}
	}

	/**
	 * Replace field value with (attached) text if file is attached
	 * to email and will be deleted after sending HTML email.
	 *
	 * @param string $field_val Field value.
	 * @param array  $field     The field.
	 * @param array  $form_data Form data and settings.
	 * @param string $context   Context usage.
	 *
	 * @return string
	 */
	public function replace_html_field_value( $field_val, $field, $form_data, $context ) {

		if ( $context !== 'email-html' ) {
			return $field_val;
		}

		if ( empty( $field[ 'type' ] ) || $field[ 'type' ] !== 'file-upload' ) {
			return $field_val;
		}

		if ( ! $this->is_allowed_delete_files_after_sending_email( $form_data ) ) {
			return $field_val;
		}

		$delete_files_fields = $this->get_filtered_attached_files_fields( $form_data );

		if ( empty( $field[ 'id' ] ) || ! in_array( $field[ 'id' ], $delete_files_fields, true ) ) {
			return $field_val;
		}

		if ( ! empty( $field[ 'style' ] ) && $field[ 'style' ] === 'modern' ) {
			$files = [];

			foreach ( $field['value_raw'] as $file ) {
				$file_name = $file['file'] ?? '';

				$files[] = sprintf( '%1$s (%2$s)', $file_name, __( 'attached', 'wpforms' ) );
			}

			return implode( "\n", $files );
		}

		$file_name = $field[ 'file' ] ?? '';

		return sprintf( '%1$s (%2$s)', $file_name, __( 'attached', 'wpforms' ) );
	}

	/**
	 * Replace field value with (attached) text if file is attached
	 * to email and will be deleted after sending text email.
	 *
	 * @param string $field_val Field value.
	 * @param array  $field     The field.
	 * @param array  $form_data Form data and settings.
	 *
	 * @return string
	 */
	public function replace_plaintext_field_value( $field_val, $field, $form_data ) {

		$replaced_value = $this->replace_html_field_value( $field_val, $field, $form_data, 'email-html' );

		if ( $replaced_value !== $field ) {
			return $replaced_value . "\r\n\r\n";
		}

		return $field_val;
	}

	/**
	 * Replace {field_id} smart tag value with (attached) text if file is attached
	 * to email and will be deleted after sending text email.
	 *
	 * @param scalar|null $value            Smart Tag value.
	 * @param array       $form_data        Form data.
	 * @param array       $fields           List of fields.
	 * @param int         $entry_id         Entry ID.
	 * @param SmartTag    $smart_tag_object The smart tag object or the Generic object for those cases when class unregistered.
	 *
	 * @return string
	 */
	public function replace_field_id_smart_tags_value( $value, $form_data, $fields, $entry_id, $smart_tag_object ) {

		$attributes = $smart_tag_object->get_attributes();

		if ( empty( $attributes[ 'field_id' ] ) ) {
			return $value;
		}

		if ( empty( $fields[ $attributes[ 'field_id' ] ] ) ) {
			return $value;
		}

		return $this->replace_html_field_value( $value, $fields[ $attributes[ 'field_id' ] ], $form_data, 'email-html' );
	}

	/**
	 * Replace {field_value_id} smart tag value with (attached) text if file is attached
	 * to email and will be deleted after sending text email.
	 *
	 * @param scalar|null $value            Smart Tag value.
	 * @param array       $form_data        Form data.
	 * @param array       $fields           List of fields.
	 * @param int         $entry_id         Entry ID.
	 * @param SmartTag    $smart_tag_object The smart tag object or the Generic object for those cases when class unregistered.
	 *
	 * @return string
	 */
	public function replace_field_value_id_smart_tags_value( $value, $form_data, $fields, $entry_id, $smart_tag_object ) {

		$attributes = $smart_tag_object->get_attributes();

		if ( empty( $attributes[ 'field_value_id' ] ) ) {
			return $value;
		}

		if ( empty( $fields[ $attributes[ 'field_value_id' ] ] ) ) {
			return $value;
		}

		return $this->replace_html_field_value( $value, $fields[ $attributes[ 'field_value_id' ] ], $form_data, 'email-html' );
	}

	/**
	 * Determine if the files should be deleted after sending email.
	 *
	 * @param array $form_data Form data and settings.
	 *
	 * @return bool
	 */
	private function is_allowed_delete_files_after_sending_email( $form_data ) {

		return ! empty( $form_data[ 'settings' ][ 'disable_entries' ] ) && ! empty( $form_data[ 'settings' ][ 'notifications' ] );
	}

	/**
	 * Get fields IDs that are attached to email and will be deleted after sending email.
	 *
	 * @param array $form_data Form data and settings.
	 *
	 * @return array
	 */
	private function get_filtered_attached_files_fields( $form_data ) {

		if ( empty( $form_data[ 'fields' ] ) || empty( $form_data[ 'settings' ][ 'notifications' ] ) ) {
			return [];
		}

		$fields = $this->get_all_attached_files_fields( $form_data );

		foreach ( $fields as $key => $field_id ) {
			if ( empty( $form_data[ 'fields' ][ $field_id ][ 'type' ] ) || $form_data['fields'][ $field_id ][ 'type' ] !== 'file-upload' ) {
				unset( $fields[ $key ] );
			}

			if ( ! self::DELETE_MEDIA_FILES && ! empty( $form_data[ 'fields' ][ $field_id ][ 'media_library' ] ) ) {
				unset( $fields[ $key ] );
			}
		}

		return $fields;
	}

	/**
	 * Get fields IDs that are attached to email.
	 *
	 * @param array $form_data Form data and settings.
	 *
	 * @return array
	 */
	private function get_all_attached_files_fields( $form_data ) {

		$is_first = true;
		$fields   = [];

		foreach ( $form_data[ 'settings' ][ 'notifications' ] as $notification ) {
			if ( empty( $notification[ 'file_upload_attachment_enable' ] ) || empty( $notification[ 'file_upload_attachment_fields' ] ) ) {
				return [];
			}

			if ( $is_first ) {
				$fields   = $notification[ 'file_upload_attachment_fields' ];
				$is_first = false;

				continue;
			}

			$fields = array_intersect( $fields, $notification[ 'file_upload_attachment_fields' ] );
		}

		return $fields;
	}
}

Usage

To utilize this Class, there are certain setup requirements.

Entries are disabled

To disable storing the entries, select Settings » General. Confirm the Disable storing entry information in WordPress is enabled.
disable storing the entries

Disable storing uploads to Media Library

Next, be sure the File Upload field has the Store file in WordPress Media Library disabled by clicking on the field and on the Advanced tab, be sure the setting is disabled.

disable storing the files in the Media Library

Attach file to email notifications

Finally, the last step is to be sure the file attachements are enabled to the email notification. To complete this step, navigate to Settings » Notifications and under the Advanced options, enable the Enable File Upload Attachments. From the File Upload Fields dropdown select your upload field.

Enable File Upload Attachments

Once these settings are completed, any file upload on your forms will attach the files uploaded but not store them on your server.

Additional (optional)

Moreover, this Class permits the removal of uploaded files from the WP Media Library. This feature is turned off by default since certain users might prefer to retain uploaded files in the WP Media, especially when utilizing Post Submissions addon and requiring file storage for thumbnails. Nevertheless, if users wish to delete both uploaded files and associated files from the WP Media Library, please must modify the DELETE_MEDIA_FILES constant in the class-delete-uploaded-files.php file to true.