added additional plugins
This commit is contained in:
parent
c85895d306
commit
00e60ec1b7
132 changed files with 27514 additions and 0 deletions
|
|
@ -0,0 +1,302 @@
|
|||
<?php
|
||||
/**
|
||||
* Handle WPForms submissions and trigger Mailjet actions.
|
||||
*
|
||||
* @package WPFMJ
|
||||
* @subpackage WPFMJ/includes
|
||||
*/
|
||||
|
||||
class WPFMJ_Form_Handler {
|
||||
|
||||
/**
|
||||
* Maximum retry attempts (configurable via filter).
|
||||
*/
|
||||
private $max_retries;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
// Allow filtering of max retry attempts (default 3, min 1, max 5)
|
||||
$this->max_retries = apply_filters('wpfmj_max_retry_attempts', 3);
|
||||
$this->max_retries = max(1, min(5, absint($this->max_retries)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle form submission.
|
||||
*/
|
||||
public function handle_submission($fields, $entry, $form_data, $entry_id) {
|
||||
$form_id = $form_data['id'];
|
||||
|
||||
// Find all active automations for this form
|
||||
$automations = $this->get_active_automations($form_id);
|
||||
|
||||
if (empty($automations)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($automations as $automation) {
|
||||
$this->process_automation($automation, $fields, $entry_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active automations for a form.
|
||||
*/
|
||||
private function get_active_automations($form_id) {
|
||||
$args = array(
|
||||
'post_type' => 'wpfmj_automation',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => -1,
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => '_wpfmj_form_id',
|
||||
'value' => $form_id,
|
||||
'compare' => '='
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return get_posts($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a single automation.
|
||||
*/
|
||||
private function process_automation($automation, $fields, $entry_id) {
|
||||
$automation_id = $automation->ID;
|
||||
|
||||
// Get automation settings
|
||||
$config = get_post_meta($automation_id, '_wpfmj_config', true);
|
||||
|
||||
if (empty($config)) {
|
||||
$this->log_error($automation_id, $entry_id, 'missing_config', 'Automation configuration is empty');
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate config structure for data integrity
|
||||
$required_keys = array('field_mapping', 'trigger_field_id', 'api_key', 'api_secret', 'list_mappings');
|
||||
foreach ($required_keys as $key) {
|
||||
if (!isset($config[$key])) {
|
||||
$this->log_error($automation_id, $entry_id, 'invalid_config', "Missing required config key: {$key}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($config['field_mapping']['email'])) {
|
||||
$this->log_error($automation_id, $entry_id, 'invalid_config', 'Email field mapping is missing');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($config['list_mappings']) || empty($config['list_mappings'])) {
|
||||
$this->log_error($automation_id, $entry_id, 'invalid_config', 'List mappings are empty or invalid');
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract form data
|
||||
$email = $this->get_field_value($fields, $config['field_mapping']['email']);
|
||||
$firstname = $this->get_field_value($fields, $config['field_mapping']['firstname']);
|
||||
$lastname = $this->get_field_value($fields, $config['field_mapping']['lastname']);
|
||||
$trigger_value = $this->get_field_value($fields, $config['trigger_field_id']);
|
||||
|
||||
// Validate email address
|
||||
if (empty($email)) {
|
||||
$this->log_error($automation_id, $entry_id, 'missing_email', 'Email field is empty');
|
||||
return;
|
||||
}
|
||||
|
||||
// Sanitize and validate email format
|
||||
$email = sanitize_email($email);
|
||||
if (!is_email($email)) {
|
||||
$this->log_error($automation_id, $entry_id, 'invalid_email', 'Email address is not valid: ' . sanitize_text_field($email));
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine which lists to add the contact to based on trigger value
|
||||
$lists_to_add = $this->get_lists_for_trigger_value($trigger_value, $config['list_mappings']);
|
||||
|
||||
if (empty($lists_to_add)) {
|
||||
// No matching lists, this is normal behavior
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare contact properties
|
||||
$properties = array();
|
||||
if (!empty($firstname)) {
|
||||
$properties['firstname'] = $firstname;
|
||||
}
|
||||
if (!empty($lastname)) {
|
||||
$properties['lastname'] = $lastname;
|
||||
}
|
||||
|
||||
// Add to Mailjet with retry logic
|
||||
$this->add_to_mailjet_with_retry($automation_id, $entry_id, $email, $lists_to_add, $properties, $config['api_key'], $config['api_secret']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get field value from fields array.
|
||||
*/
|
||||
private function get_field_value($fields, $field_id) {
|
||||
if (!isset($fields[$field_id])) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = $fields[$field_id]['value'];
|
||||
|
||||
// Handle arrays (checkboxes, multi-select)
|
||||
if (is_array($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return sanitize_text_field($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get lists for trigger value.
|
||||
*/
|
||||
private function get_lists_for_trigger_value($trigger_value, $mappings) {
|
||||
$lists = array();
|
||||
|
||||
// Handle array values (checkboxes, multi-select)
|
||||
if (is_array($trigger_value)) {
|
||||
foreach ($trigger_value as $value) {
|
||||
if (isset($mappings[$value])) {
|
||||
$lists[] = $mappings[$value];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Single value (radio, dropdown)
|
||||
if (isset($mappings[$trigger_value])) {
|
||||
$lists[] = $mappings[$trigger_value];
|
||||
}
|
||||
}
|
||||
|
||||
return array_unique(array_filter($lists));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add to Mailjet with retry logic.
|
||||
*/
|
||||
private function add_to_mailjet_with_retry($automation_id, $entry_id, $email, $lists, $properties, $api_key, $api_secret) {
|
||||
$decrypted_key = WPFMJ_Encryption::decrypt($api_key);
|
||||
$decrypted_secret = WPFMJ_Encryption::decrypt($api_secret);
|
||||
|
||||
// Check for decryption failures (can happen if encryption key changed)
|
||||
if ($decrypted_key === false || $decrypted_secret === false || empty($decrypted_key) || empty($decrypted_secret)) {
|
||||
$this->log_error(
|
||||
$automation_id,
|
||||
$entry_id,
|
||||
'decryption_failed',
|
||||
'Failed to decrypt API credentials. The encryption key may have changed. Please re-save this automation with valid API credentials.'
|
||||
);
|
||||
$this->notify_admin_of_failure($automation_id, $entry_id, 'API credential decryption failed');
|
||||
return;
|
||||
}
|
||||
|
||||
$api = new WPFMJ_Mailjet_API($decrypted_key, $decrypted_secret);
|
||||
|
||||
$attempt = 0;
|
||||
$success = false;
|
||||
|
||||
while ($attempt < $this->max_retries && !$success) {
|
||||
$result = $api->add_contact_to_lists($email, $lists, $properties);
|
||||
|
||||
if (!is_wp_error($result)) {
|
||||
$success = true;
|
||||
|
||||
// Log success
|
||||
do_action('wpfmj_automation_success', $automation_id, $entry_id, $email, $lists);
|
||||
} else {
|
||||
$attempt++;
|
||||
|
||||
if ($attempt < $this->max_retries) {
|
||||
// Exponential backoff: 1s, 2s, 4s
|
||||
sleep(pow(2, $attempt - 1));
|
||||
} else {
|
||||
// Max retries reached, log error
|
||||
$this->log_error(
|
||||
$automation_id,
|
||||
$entry_id,
|
||||
'mailjet_api_error',
|
||||
$result->get_error_message(),
|
||||
$attempt
|
||||
);
|
||||
|
||||
// Notify admin
|
||||
$this->notify_admin_of_failure($automation_id, $entry_id, $result->get_error_message());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log error.
|
||||
*/
|
||||
private function log_error($automation_id, $entry_id, $error_type, $error_message, $retry_count = 0) {
|
||||
$logger = new WPFMJ_Error_Logger();
|
||||
$logger->log($automation_id, $entry_id, $error_type, $error_message, $retry_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify admin of failure.
|
||||
*/
|
||||
private function notify_admin_of_failure($automation_id, $entry_id, $error_message) {
|
||||
// Check if notifications are disabled
|
||||
if (apply_filters('wpfmj_disable_failure_notifications', false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get notification recipients (filterable)
|
||||
$default_email = get_option('admin_email');
|
||||
$recipients = apply_filters('wpfmj_failure_notification_emails', array($default_email));
|
||||
|
||||
// Ensure recipients is an array
|
||||
if (!is_array($recipients)) {
|
||||
$recipients = array($default_email);
|
||||
}
|
||||
|
||||
// Remove invalid emails
|
||||
$recipients = array_filter($recipients, function($email) {
|
||||
return is_email($email);
|
||||
});
|
||||
|
||||
if (empty($recipients)) {
|
||||
error_log('WPFMJ: No valid email recipients for failure notification');
|
||||
return;
|
||||
}
|
||||
|
||||
$automation_title = get_the_title($automation_id);
|
||||
$site_name = get_bloginfo('name');
|
||||
|
||||
// Sanitize all data for email
|
||||
$automation_title = sanitize_text_field($automation_title);
|
||||
$site_name = sanitize_text_field($site_name);
|
||||
$error_message = sanitize_textarea_field($error_message);
|
||||
$entry_id = intval($entry_id);
|
||||
|
||||
$subject = sprintf(
|
||||
'[%s] Mailjet Automation Failed',
|
||||
$site_name
|
||||
);
|
||||
|
||||
$message = sprintf(
|
||||
"A Mailjet automation has failed after %d retry attempts.\n\nAutomation: %s\nEntry ID: %d\nError: %s\n\nPlease check the error logs in your WordPress admin.",
|
||||
$this->max_retries,
|
||||
$automation_title,
|
||||
$entry_id,
|
||||
$error_message
|
||||
);
|
||||
|
||||
// Use wp_mail with proper headers
|
||||
$headers = array('Content-Type: text/plain; charset=UTF-8');
|
||||
|
||||
// Send to all recipients
|
||||
foreach ($recipients as $recipient) {
|
||||
$sent = wp_mail($recipient, $subject, $message, $headers);
|
||||
|
||||
if (!$sent) {
|
||||
error_log("WPFMJ: Failed to send notification email to {$recipient}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue