Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<?php
/**
* "Conditional Email" ACFE Form Action Class.
*
* Handles the "Conditional Email" ACFE Form Action.
*
* @package Conditional_Form_Actions_For_ACFE
* @since 0.1
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* CiviCRM Profile Sync "Conditional Email" ACFE Form Action Class.
*
* A class that handles the "Conditional Email" ACFE Form Action.
*
* @since 0.1
*/
class CFAFA_Form_Action_Email extends CFAFA_Form_Action_Base {
/**
* Plugin object.
*
* @since 0.1
* @access public
* @var object $plugin The plugin object.
*/
public $plugin;
/**
* Parent (calling) object.
*
* @since 0.1
* @access public
* @var object $acf The parent object.
*/
public $acfe;
/**
* Form Action Name.
*
* @since 0.1
* @access public
* @var string $action_name The unique name of the Form Action.
*/
public $action_name = 'email_cfafa';
/**
* Field Key Prefix.
*
* @since 0.1
* @access public
* @var string $field_key The prefix for the Field Key.
*/
public $field_key = 'field_cfafa_email_';
/**
* Field Name Prefix.
*
* @since 0.1
* @access public
* @var string $field_name The prefix for the Field Name.
*/
public $field_name = 'cfafa_email_';
/**
* Constructor.
*
* @since 0.1
*
* @param object $parent The parent object reference.
*/
public function __construct( $parent ) {
// Store references to objects.
$this->plugin = $parent->plugin;
$this->acfe = $parent;
// Label this Form Action.
$this->action_label = __( 'Conditional Email action', 'conditional-form-actions-for-acfe' );
// Alias Placeholder for this Form Action.
$this->alias_placeholder = __( 'Conditional Email', 'conditional-form-actions-for-acfe' );
// Init parent.
parent::__construct();
}
/**
* Configure this object.
*
* @since 0.1
*/
public function configure() {
// Declare the mapped Email Fields with translatable titles.
$this->mapped_email_fields = [
'from_name' => __( 'From Name', 'conditional-form-actions-for-acfe' ),
'from_email' => __( 'From Email', 'conditional-form-actions-for-acfe' ),
'reply_to_name' => __( 'Reply To Name', 'conditional-form-actions-for-acfe' ),
'reply_to_email' => __( 'Reply To Email', 'conditional-form-actions-for-acfe' ),
'to_name' => __( 'To Name', 'conditional-form-actions-for-acfe' ),
'to_email' => __( 'To Email', 'conditional-form-actions-for-acfe' ),
'cc' => __( 'Cc', 'conditional-form-actions-for-acfe' ),
'bcc' => __( 'Bcc', 'conditional-form-actions-for-acfe' ),
'subject' => __( 'Subject', 'conditional-form-actions-for-acfe' ),
];
// Populate mapping Fields.
foreach ( $this->mapped_email_fields as $name => $title ) {
$this->mapping_field_filters_add( $name );
}
// Email Conditional Field.
$this->mapping_field_filters_add( 'email_conditional' );
// Map "File" Field.
$this->mapping_field_filter_deep( $this->field_name . 'file' );
}
/**
* Performs validation when the Form the Action is attached to is submitted.
*
* @since 0.1
*
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the action.
*/
public function validation( $form, $current_post_id, $action ) {
/*
// Get some Form details.
$form_name = acf_maybe_get( $form, 'name' );
$form_id = acf_maybe_get( $form, 'ID' );
//acfe_add_validation_error( $selector, $message );
*/
}
/**
* Performs the action when the Form the Action is attached to is submitted.
*
* @since 0.1
*
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the action.
*/
public function make( $form, $current_post_id, $action ) {
// Bail if a filter has overridden the action.
if ( false === $this->make_skip( $form, $current_post_id, $action ) ) {
return;
}
// Get some Form details.
$form_name = acf_maybe_get( $form, 'name' );
$form_id = acf_maybe_get( $form, 'ID' );
// Populate Email data array.
$email = $this->form_email_data( $form, $current_post_id, $action );
// Populate Attachments data array.
$attachments = $this->form_attachments_data( $form, $current_post_id, $action );
// Check Conditional.
if ( $this->form_conditional_check( $email ) ) {
// Build the arguments.
$args = $this->form_build_args( $email, $attachments, $form, $current_post_id, $action );
// Skip when the args have been overridden.
if ( ! empty( $args ) ) {
// Send the Email with the built arguments.
$email = $this->form_email_send( $args, $email );
// Maybe remove Dynamic Attachments.
$this->form_attachments_delete( $attachments );
}
}
// Save the results of this Action for later use.
$this->make_action_save( $action, $email );
}
/**
* Defines additional Fields for the "Action" Tab.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
public function tab_action_append() {
// Init Fields.
// Add Conditional Field.
$code = 'email_conditional';
$label = __( 'Conditional On', 'conditional-form-actions-for-acfe' );
$conditional = $this->mapping_field_get( $code, $label );
$conditional['placeholder'] = __( 'Always send', 'conditional-form-actions-for-acfe' );
$conditional['wrapper']['data-instruction-placement'] = 'field';
$conditional['instructions'] = __( 'To send the Email only when a Form Field is populated (e.g. "First Name") link this to the Form Field. To send the Email only when more complex conditions are met, link this to a Hidden Field with value "1" where the conditional logic of that Field shows it when the conditions are met.', 'conditional-form-actions-for-acfe' );
$fields[] = $conditional;
// --<
return $fields;
}
/**
* Defines the "Mapping" Tab.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
public function tab_mapping_add() {
// Get Tab Header.
$label = __( 'Email', 'conditional-form-actions-for-acfe' );
$mapping_tab_header = $this->tab_mapping_header( $label );
// Build Email Details Accordion.
$mapping_email_accordion = $this->tab_mapping_accordion_email_add();
// Combine Sub-Fields.
$fields = array_merge(
$mapping_tab_header,
$mapping_email_accordion
);
// --<
return $fields;
}
/**
* Defines the Fields in the "Email Fields" Accordion.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
public function tab_mapping_accordion_email_add() {
// Add "Mapping" Fields.
foreach ( $this->mapped_email_fields as $name => $title ) {
$fields[] = $this->mapping_field_get( $name, $title );
'key' => $this->field_key . 'content',
'label' => __( 'Content', 'conditional-form-actions-for-acfe' ),
'name' => $this->field_name . 'content',
'type' => 'wysiwyg',
'instructions' => sprintf(
__( 'Fields values may be included using %1$s{field:field_key}%2$s %1$s{field:title}%2$s. All fields may be included using %1$s{fields}%2$s.%3$sSee "Cheatsheet" tab for advanced usage.', 'conditional-form-actions-for-acfe' ),
'<code>',
'</code>',
'<br />'
),
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
'data-instruction-placement' => 'field',
'default_value' => '',
'tabs' => 'all',
'toolbar' => 'full',
'media_upload' => 1,
'delay' => 0,
'endpoint' => 1,
];
// --<
return $fields;
}
/**
* Defines the "Attachments" Tab.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
public function tab_attachments_add() {
// Init tab array.
$attachments_tab = [];
// Add "Dynamic Files" Repeater.
$attachments_tab[] = [
'key' => $this->field_key . 'files',
'label' => __( 'Dynamic Files', 'conditional-form-actions-for-acfe' ),
'name' => $this->field_name . 'files',
'type' => 'repeater',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
],
'acfe_permissions' => '',
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
'acfe_repeater_stylised_button' => 0,
'collapsed' => '',
'min' => 0,
'max' => 0,
'layout' => 'table',
'button_label' => __( 'Add File', 'conditional-form-actions-for-acfe' ),
'sub_fields' => [
[
'key' => $this->field_key . 'file',
'label' => __( 'File', 'conditional-form-actions-for-acfe' ),
'name' => $this->field_name . 'file',
'type' => 'select',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
],
'acfe_permissions' => '',
'choices' => [],
'default_value' => [],
'allow_null' => 0,
'multiple' => 0,
'ui' => 1,
'return_format' => 'value',
'ajax' => 0,
'placeholder' => '',
'search_placeholder' => __( 'Enter a custom value or template tag. (See "Cheatsheet" tab)', 'conditional-form-actions-for-acfe' ),
'allow_custom' => 1,
],
[
'key' => $this->field_key . 'file_delete',
'label' => __( 'Delete File', 'conditional-form-actions-for-acfe' ),
'name' => $this->field_name . 'file_delete',
'type' => 'true_false',
'instructions' => '',
'required' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
],
'acfe_permissions' => '',
'message' => __( 'Delete once submitted', 'conditional-form-actions-for-acfe' ),
'default_value' => 0,
'ui' => 1,
'ui_on_text' => '',
'ui_off_text' => '',
],
],
// Add "Static Files" Repeater.
$attachments_tab[] = [
'key' => $this->field_key . 'files_static',
'label' => __( 'Static Files', 'conditional-form-actions-for-acfe' ),
'name' => $this->field_name . 'files_static',
'type' => 'repeater',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
],
'acfe_permissions' => '',
'acfe_repeater_stylised_button' => 0,
'collapsed' => '',
'min' => 0,
'max' => 0,
'layout' => 'table',
'button_label' => __( 'Add File', 'conditional-form-actions-for-acfe' ),
'sub_fields' => [
[
'key' => $this->field_key . 'file_static',
'label' => __( 'File', 'conditional-form-actions-for-acfe' ),
'name' => $this->field_name . 'file_static',
'type' => 'file',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
],
'acfe_permissions' => '',
'return_format' => 'id',
],
],
// Get Tab Header.
$attachments_tab_header = $this->tab_attachments_header();
// Combine Sub-Fields.
$fields = array_merge(
$attachments_tab_header,
$attachments_tab
);
// --<
return $fields;
}
/**
* Builds Email data array from mapped Fields.
*
* @since 0.1
*
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the action.
* @return array $data The array of Email data.
*/
public function form_email_data( $form, $current_post_id, $action ) {
// Build Fields array.
$fields = [];
foreach ( $this->mapped_email_fields as $name => $title ) {
$fields[ $name ] = get_sub_field( $this->field_key . 'map_' . $name );
}
// Populate data array with values of mapped Fields.
$data = acfe_form_map_vs_fields( $fields, $fields, $current_post_id, $form );
// Add Email Content.
$content = get_sub_field( $this->field_key . 'content' );
$data['content'] = acfe_form_map_field_value( $content, $current_post_id, $form );
// Get Email Conditional Reference.
$data['email_conditional_ref'] = get_sub_field( $this->field_key . 'map_email_conditional' );
$conditionals = [ $data['email_conditional_ref'] ];
// Populate array with mapped Conditional Field values.
$conditionals = acfe_form_map_vs_fields( $conditionals, $conditionals, $current_post_id, $form );
// Save Email Conditional.
$data['email_conditional'] = array_pop( $conditionals );
// --<
return $data;
}
/**
* Builds Attachment data array from mapped Fields.
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the action.
* @return array $data The array of Attachment data.
public function form_attachments_data( $form, $current_post_id, $action ) {
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
// Init return array.
$data = [
'attachments' => [],
'delete' => [],
];
// Process Dynamic Attachments.
if ( have_rows( $this->field_name . 'files' ) ) {
while ( have_rows( $this->field_name . 'files' ) ) {
the_row();
// Find the ID of the File.
$file_field_key = get_sub_field( $this->field_name . 'file' );
$file_id = acfe_form_map_field_value( $file_field_key, $current_post_id, $form );
// Configure the File Field to return an array.
$field = acf_get_field( $file_field_key );
$field['return_format'] = 'array';
// Build an array of data for the Dynamic Attachments.
$files = acf_format_value( $file_id, 0, $field );
$files = acf_get_array( $files );
if ( acf_maybe_get( $files, 'ID' ) ) {
$files = [ $files ];
}
$file_delete = get_sub_field( $this->field_name . 'file_delete' );
foreach ( $files as $file ) {
// Skip if there's no File ID to process.
if ( ! acf_maybe_get( $file, 'ID' ) ) {
continue;
}
// Add to Attachments array.
$data['attachments'][] = get_attached_file( $file['ID'] );
// Maybe add to delete array.
if ( $file_delete ) {
$data['delete'][] = $file['ID'];
}
}
// Process Static Attachments.
if ( have_rows( $this->field_name . 'files_static' ) ) {
while ( have_rows( $this->field_name . 'files_static' ) ) {
the_row();
// The File reference is the Sub-field content.
$file = get_sub_field( $this->field_name . 'file_static' );
// Just add to Attachments array.
$data['attachments'][] = get_attached_file( $file );
}
// --<
return $data;
}
/**
* Builds the arguments array.
*
* @since 0.1
*
* @param array $email_data The array of Email data.
* @param array $attachments_data The array of Attachments data.
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the action.
* @return array|bool $args The arguments array, or false on failure.
*/
public function form_build_args( $email_data, $attachments_data, $form, $current_post_id, $action ) {
// Build "From" and "Reply To" params.
$from = $this->form_email_item_build( $email_data['from_name'], $email_data['from_email'] );
$reply_to = $this->form_email_item_build( $email_data['reply_to_name'], $email_data['reply_to_email'] );
// Maybe use "From" when "Reply To" is empty.
if ( empty( $reply_to ) ) {
$reply_to = $from;
// Build "To" param.
$to = $this->form_email_item_build( $email_data['to_name'], $email_data['to_email'] );
if ( empty( $from ) || empty( $to ) ) {
return false;
// Build Email headers.
$headers[] = 'From: ' . $from;
if ( ! empty( $reply_to ) ) {
$headers[] = 'Reply-To: ' . $reply_to;
}
if ( ! empty( $email_data['cc'] ) ) {
$headers[] = 'Cc: ' . $email_data['cc'];
}
if ( ! empty( $email_data['bcc'] ) ) {
$headers[] = 'Bcc: ' . $email_data['bcc'];
}
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
$headers[] = 'Content-Type: text/html';
$headers[] = 'charset=UTF-8';
// Finally, build args array.
$args = [
'from' => $from,
'to' => $to,
'reply_to' => $reply_to,
'cc' => $email_data['cc'],
'bcc' => $email_data['bcc'],
'subject' => $email_data['subject'],
'content' => $email_data['content'],
'headers' => $headers,
'attachments' => $attachments_data['attachments'],
];
// Get the Form name.
$form_name = acf_maybe_get( $form, 'name' );
/**
* Allow others to filter the Email arguments.
*
* Returning false for any of these filters will skip sending the Email.
*
* @since 0.1
*
* @param bool $args The array of arguments.
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the Form Action.
*/
$filter = 'acfe/form/submit/' . $this->action_name . '/email_args';
$args = apply_filters( $filter, $args, $form, $current_post_id, $action );
$args = apply_filters( $filter . '/form=' . $form_name, $args, $form, $current_post_id, $action );
if ( ! empty( $action ) ) {
$args = apply_filters( $filter . '/action=' . $action, $args, $form, $current_post_id, $action );
* Checks the Conditional Email Field given data from mapped Fields.
* @param array $email_data The array of Email data.
* @return bool $continue True if the Action should continue or false to skip.
public function form_conditional_check( $email_data ) {
// Approve by default.
$continue = true;
// Skip if the Email Conditional Reference Field has a value.
if ( ! empty( $email_data['email_conditional_ref'] ) ) {
// And the Email Conditional Field has no value.
if ( empty( $email_data['email_conditional'] ) ) {
return false;
}
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
// --<
return $continue;
}
/**
* Sends the Email given a set of arguments.
*
* @since 0.1
*
* @param array $args The array of Email arguments.
* @param array $email_data The array of Email data.
* @return array|bool $args The array of Email arguments, or false on failure.
*/
public function form_email_send( $args, $email_data ) {
// Define rules for checking Email headers.
$rules = [
[
'args_key' => 'from',
'value_old' => $this->form_email_item_build( $email_data['from_name'], $email_data['from_email'] ),
'header_key' => 'From:',
],
[
'args_key' => 'reply_to',
'value_old' => $this->form_email_item_build( $email_data['reply_to_name'], $email_data['reply_to_email'] ),
'header_key' => 'Reply-To:',
],
[
'args_key' => 'cc',
'value_old' => $email_data['cc'],
'header_key' => 'Cc:',
],
[
'args_key' => 'bcc',
'value_old' => $email_data['bcc'],
'header_key' => 'Bcc:',
],
];
// Check if the Email headers have been changed.
foreach ( $rules as $rule ) {
$check = acf_maybe_get( $args, $rule['args_key'] );
if ( ! empty( $check ) && $check !== $rule['value_old'] ) {
foreach ( $args['headers'] as &$header ) {
if ( stripos( $header, $rule['header_key'] ) !== 0 ) {
continue;
}
// Repair Email header.
$header = $rule['header_key'] . ' ' . $check;
break;
}
}
// Send the Email.
$result = wp_mail( $args['to'], $args['subject'], $args['content'], $args['headers'], $args['attachments'] );
// Bail on failure.
if ( $result === false ) {
return false;
}
* Builds an Email item according to the specification.
*
* For example "First Last <foo@bar.com>".
* @param str $name The name.
* @param str $email The email.
* @return str $item The built item.
public function form_email_item_build( $name, $email ) {
// Parse item from params.
if ( ! empty( $name ) && ! empty( $email ) ) {
$item = sprintf( '%1$s <%2$s>', $name, $email );
} elseif ( ! empty( $email ) ) {
$item = $email;
/**
* Deletes the Dynamic Attachments.
*
* @since 0.1
*
* @param array $attachments_data The array of Attachments data.
*/
public function form_attachments_delete( $attachments_data ) {
// Bail if there are none.
if ( ! empty( $attachments_data['delete'] ) ) {
return;
}
// Delete all the Dynamic Attachments.
foreach ( $attachments_data['delete'] as $file_id ) {
wp_delete_attachment( $file_id, true );
}