Skip to content

Gravity Flow Form Connector: Map PDF to Upload Field #1603

@jakejackson1

Description

@jakejackson1

TODO

  • If updating an entry, grab the existing Multi File Upload entry data so the newly-generated PDF can be added to the existing list of files.
  • Add support for the Update Fields step. This acts in reverse to the other steps, in that the data is pulled from another entry and saved to fields in the current one (rather than pushing to another entry)
  • Test a Remote server
<?php

/* Register PDFs in Gravity Flow Generic Map */
add_filter( 'gravityflow_step_settings_fields', function ( $settings, $step_id ) {
	$gflow = \Gravity_Flow::get_instance();

	if ( $step_id ) {
		$step      = $gflow->get_step( $step_id );
		$step_type = $step !== false ? $step->get_type() : '';
	} else {
		$step_type = $gflow->get_setting( 'step_type' );
	}

	/* skip unsupported steps */
	if ( ! in_array( $step_type, [ 'new_entry', 'update_entry' ], true ) ) {
		return $settings;
	}

	/* skip forms without PDFs configured */
	$form_id = absint( rgget( 'id' ) );
	$pdfs    = \GPDFAPI::get_form_pdfs( $form_id );
	if ( is_wp_error( $pdfs ) || empty( $pdfs ) ) {
		return $settings;
	}

	$mapping_key = 'value_field';

	foreach ( $settings as $i => $setting_group ) {
		if (
			empty( $setting_group['class'] ) ||
			empty( $setting_group['fields'] ) ||
			$setting_group['class'] !== 'gravityflow-step-settings'
		) {
			continue;
		}

		foreach ( $setting_group['fields'] as $j => $field ) {
			// only target the generic map field
			if ( empty( $field['name'] ) || $field['name'] !== 'mappings' ) {
				continue;
			}

			// verify expected data structure
			if ( ! isset( $field[ $mapping_key ]['choices'] ) || ! is_array( $field[ $mapping_key ]['choices'] ) ) {
				continue;
			}

			// add PDFs to list
			foreach ( $pdfs as $pdf ) {
				/* Ignore inactive pdf template. */
				if ( ( $pdf['active'] ?? false ) === false ) {
					continue;
				}

				$field[ $mapping_key ]['choices'][] = [
					'label' => __( 'PDF: ' ) . $pdf['name'] ?? '',
					'value' => sprintf(
						'gpdf:%s',
						$pdf['id'] ?? '',
					),
				];
			}

			$settings[ $i ]['fields'][ $j ] = $field;

			break;
		}

	}

	return $settings;
}, 10, 2 );

/**
 * Generates a PDF and saves it in a File Upload field
 *
 * @param array              $target_entry
 * @param array              $target_form
 * @param array              $entry
 * @param array              $form
 *
 * @param \Gravity_Flow_Step $step
 *
 * @return array
 */
$gravityflow_form_connector_save_pdf_to_fileupload = function ( $target_entry, $target_form, $entry, $form, $mappings, $server_type ) {
	foreach ( $mappings as $mapping ) {
		if ( strpos( $mapping['value'], 'gpdf:' ) !== 0 ) {
			continue;
		}

		/* Get the target info */
		$target_field_id = trim( $mapping['key'] ) === 'gf_custom' ? trim( $mapping['custom_key'] ) : trim( $mapping['key'] );
		$target_field    = \GFAPI::get_field( $target_form, $target_field_id );

		/* Verify target is a file upload field */
		if ( $target_field === false || $target_field->get_input_type() !== 'fileupload' ) {
			gravity_flow()->log_error( __METHOD__ . '(): target is not a File Upload field for: ' . $mapping['value'] );

			continue;
		}

		/* Generate the PDF */
		$pdf_id   = explode( ':', $mapping['value'] )[1] ?? '';
		$pdf_path = \GPDFAPI::create_pdf( $entry['id'] ?? 0, $pdf_id );
		if ( is_wp_error( $pdf_path ) ) {
			gravity_flow()->log_error( sprintf( __METHOD__ . '(): could not generate PDF for entry ID%d and PDF ID %s.', $entry['id'] ?? 0, $mapping['value'] ) );

			continue;
		}

		/*
		 * Move the PDF to the upload directory
		 * If the target is the local site then we'll save to the target upload folder
		 * If the target is remove then we'll save to the source upload folder
		  */
		$upload_root_info = \GF_Field_FileUpload::get_upload_root_info( $server_type === 'remote' ? $form['id'] : $target_form['id'] );

		/* Create the directory if it doesn't exist */
		wp_mkdir_p( $upload_root_info['path'] );

		$file_name = wp_basename( $pdf_path, '.pdf' );
		$extension = '.pdf';

		/* Get unique target info */
		$counter         = 1;
		$target_filename = $file_name . $extension;
		$target_path     = $upload_root_info['path'] . $target_filename;
		while ( is_file( $target_path ) ) {
			$target_filename = $file_name . $counter . $extension;
			$target_path     = $upload_root_info['path'] . $target_filename;
			$counter++;
		}

		/* Verify there's been no path traversal */
		$path_to_test = realpath( dirname( $target_path ) );
		if ( $path_to_test === false || strpos( $path_to_test, realpath( $upload_root_info['path'] ) ) !== 0 ) {
			gravity_flow()->log_error( __METHOD__ . '(): Path traversal detected in target path: ' . $target_path );

			continue;
		}

		/* Move PDF to target form upload directory */
		if ( copy( $pdf_path, $target_path ) ) {
			\GFFormsModel::set_permissions( $target_path );

			/* prepare info for DB storage */
			$target_url = $upload_root_info['url'] . $target_filename;

			if ( ! $target_field->multipleFiles ) {
				$target_entry[ $target_field_id ] = $target_url;
			} else {
				$value                            = ! empty( $target_entry[ $target_field_id ] ) ? json_decode( $target_entry[ $target_field_id ], true ) : [];
				$value[]                          = $target_url;
				$target_entry[ $target_field_id ] = json_encode( $value );
			}
		}
	}

	return $target_entry;
};

add_filter( 'gravityflowformconnector_new_entry', function ( $new_entry, $entry, $form, $target_form, $step ) use ( $gravityflow_form_connector_save_pdf_to_fileupload ) {
	return $gravityflow_form_connector_save_pdf_to_fileupload(
		$new_entry,
		$target_form,
		$entry,
		$form,
		$step->mappings,
		$step->server_type
	);
}, 10, 5 );

add_filter( 'gravityflowformconnector_update_entry', function ( $new_entry, $entry, $form, $target_form, $step ) use ( $gravityflow_form_connector_save_pdf_to_fileupload ) {
	return $gravityflow_form_connector_save_pdf_to_fileupload(
		$new_entry,
		$target_form,
		$entry,
		$form,
		$step->mappings,
		$step->server_type
	);
}, 10, 5 );

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions