Auto-attach Uploaded Files from Child to Parent Notifications

Auto-attach Uploaded Files from Child to Parent Notifications

Code

Filename: gpnf-auto-attach-child-files.php

<?php
/**
 * Gravity Perks // Nested Forms // Auto-attach Uploaded Files from Child to Parent Notifications
 * https://gravitywiz.com/documentation/gravity-forms-nested-forms/
 *
 * This snippet automatically attaches files uploaded onto the child form to the parent form notifications.
 * If parent form has any File Upload fields, this snippet will rely on the "Attachments" setting for each parent notification.
 * Otherwise, you must specify a list of notifications by ID to which child uploads should be attached.
 *
 * Plugin Name:  GP Nested Forms - Auto-attach Uploaded Files from Child to Parent Notifications
 * Plugin URI:   https://gravitywiz.com/documentation/gravity-forms-nested-forms/
 * Description:  Auto-attach Uploaded Files from Child to Parent Notifications
 * Author:       Gravity Wiz
 * Version:      0.3
 * Author URI:   https://gravitywiz.com/
 */
class GPNF_Auto_Attach_Child_Files {
	/**
	 * The ID of the parent form to apply this to (optional).
	 */
	private $parent_form_id = null;

	/**
	 * The IDs of the child form field to apply this to (optional).
	 */
	private $child_form_field_ids = null;

	/**
	 * The IDs of the parent form notifications to which child uploads should be attached (optional).
	 */
	private $notification_ids = array();

	/**
	 * The IDs of child form fields whose files should be attached to notifications (optional).
	 */
	private $child_form_upload_field_ids = array();

	function __construct( $config = array() ) {
		$this->set_config_data( $config );
		$this->init_hooks();
	}

	function init_hooks() {
		add_filter( 'gform_notification', array( $this, 'handle_notification_attachments' ), 10, 3 );
	}

	function set_config_data( $config ) {
		if ( ! empty( $config['parent_form_id'] ) ) {
			$this->parent_form_id = $config['parent_form_id'];
		}

		if ( ! empty( $config['child_form_field_ids'] ) ) {
			$this->child_form_field_ids = $config['child_form_field_ids'];
		}

		if ( ! empty( $config['notification_ids'] ) ) {
			$this->notification_ids = $config['notification_ids'];
		}

		if ( ! empty( $config['child_form_upload_field_ids'] ) ) {
			$this->child_form_upload_field_ids = $config['child_form_upload_field_ids'];
		}
	}

	function handle_notification_attachments( $notification, $form, $entry ) {
		if ( ! class_exists( 'GPNF_Entry' ) ) {
			return $notification;
		}

		if ( $this->parent_form_id && $form['id'] != $this->parent_form_id ) {
			return $notification;
		}

		$upload_fields = GFCommon::get_fields_by_type( $form, array( 'fileupload', 'image_hopper', 'image_hopper_post' ) );

		if ( ! $this->is_applicable_notification( $notification ) ) {
			return $notification;
		}

		// If parent form has upload fields, rely on the notification's Attachments setting.
		if ( ! empty( $upload_fields ) && ! rgar( $notification, 'enableAttachments', false ) ) {
			return $notification;
		}

		$attachments  =& $notification['attachments'];
		$parent_entry = new GPNF_Entry( $entry );

		foreach ( $form['fields'] as $field ) {
			if ( $field->get_input_type() !== 'form' ) {
				continue;
			}

			if ( $this->child_form_field_ids && ! in_array( $field['id'], $this->child_form_field_ids ) ) {
				continue;
			}

			$child_form    = GFAPI::get_form( $field->gpnfForm );
			$upload_fields = GFCommon::get_fields_by_type( $child_form, array( 'fileupload', 'image_hopper', 'image_hopper_post' ) );
			$child_entries = $parent_entry->get_child_entries( $field->id );
			$upload_root   = GFFormsModel::get_upload_root();

			foreach ( $child_entries as $child_entry ) {
				foreach ( $upload_fields as $upload_field ) {
					if ( ! $this->is_applicable_upload_field( $upload_field ) ) {
						continue;
					}

					/*
					 * Handle GP Media Library as handle_attachments won't work as expected for the parent form since
					 * these file upload fields do not exist in the parent form, and it will fail to find the IDs.
					 */
					if ( function_exists( 'gp_media_library' ) ) {
						$gpml_file_ids = gp_media_library()->get_file_ids_by_entry( $child_entry, $child_form );

						/*
						 * gp_media_library()->get_file_ids_by_entry() returns a structure with array<fieldId, array<fileId>>
						 * so this is a cheap way to flatten it and avoid PHP errors at the same time.
						 */
						$gpml_ids = ( count( $gpml_file_ids ) > 0 ) ? call_user_func_array( 'array_merge', $gpml_file_ids ) : array();

						foreach ( $gpml_ids as $gpml_id ) {
							$attachments[] = get_attached_file( $gpml_id );
						}
					}

					$attachment_urls = rgar( $child_entry, $upload_field->id );
					if ( empty( $attachment_urls ) ) {
						continue;
					}

					$attachment_urls = $upload_field->multipleFiles ? json_decode( $attachment_urls, true ) : array( $attachment_urls );

					foreach ( $attachment_urls as $attachment_url ) {
						$attachment_url = preg_replace( '|^(.*?)/gravity_forms/|', $upload_root, $attachment_url );
						$attachments[]  = $attachment_url;
					}
				}
			}
		}

		return $notification;
	}

	function is_applicable_notification( $notification ) {
		return empty( $this->notification_ids ) || in_array( $notification['id'], $this->notification_ids );
	}

	function is_applicable_upload_field( $upload_field ) {
		return empty( $this->child_form_upload_field_ids ) || in_array( $upload_field->id, $this->child_form_upload_field_ids );
	}
}

/**
 *  Notes:
 * - If notifications IDs are specified this snippet will only work for those specific forms.
 * - If child form upload field IDs are specified, only files from those fields will be attached.
 * - If the parent form has upload fields, they will be attached instead of the child form's fields.
 * - If none of these conditions are present, child form uploads will be attached by default.
 *
 * Configuration:
 *
 * 1) Ensure that the parent form's notification has the "Attach uploaded fields to notification" checked.
 * 2) [Optional] Modify one ore more of the following examples to limit the snippet to specific notification IDs or child form upload field IDs.
 *
 * 💡 Notification IDs can be retrieved from the nid parameter in the URL when editing a notification.
*/

# -------------------------------------------------
# Examples
# -------------------------------------------------

# Attach all child form uploads to all notifications.
// new GPNF_Auto_Attach_Child_Files();

# Attach all uploads from child forms to *only* the notification with id "63331f3fcf7f0".
// new GPNF_Auto_Attach_Child_Files( array(
// 	'notification_ids' => array( '63331f3fcf7f0' ),
// ) );

# Attach child form upload from field with ID 3 to all notifications.
// new GPNF_Auto_Attach_Child_Files( array(
// 	'child_form_upload_field_ids' => array( 3 ),
// ) );


# Attach child form upload from field with ID 3 to only notification with id "63331f3fcf7f0".
// new GPNF_Auto_Attach_Child_Files( array(
// 	'notification_ids'            => array( '63331f3fcf7f0' ),
// 	'child_form_upload_field_ids' => array( 3 ),
// ) );

# Attach all child form uploads only on the child form with field ID of 2 on the parent form with ID of 1
// new GPNF_Auto_Attach_Child_Files( array(
// 	'parent_form_id'              => 1,
// 	'child_form_field_ids'        => array( 2 ),
// ) );

Leave a Reply

Your email address will not be published. Required fields are marked *

  • Trouble installing this snippet? See our troubleshooting tips.
  • Need to include code? Create a gist and link to it in your comment.
  • Reporting a bug? Provide a URL where this issue can be recreated.

By commenting, I understand that I may receive emails related to Gravity Wiz and can unsubscribe at any time.