monorepo/native/wordpress/wpforms-mailjet-automations/includes/class-wpfmj-mailjet-api.php

218 lines
6.2 KiB
PHP

<?php
/**
* Mailjet API wrapper.
*
* @package WPFMJ
* @subpackage WPFMJ/includes
*/
class WPFMJ_Mailjet_API {
/**
* API base URL.
*/
private $api_url = 'https://api.mailjet.com/v3';
/**
* API key.
*/
private $api_key;
/**
* API secret.
*/
private $api_secret;
/**
* Constructor.
*/
public function __construct($api_key = '', $api_secret = '') {
$this->api_key = $api_key;
$this->api_secret = $api_secret;
}
/**
* Test API connection.
*/
public function test_connection() {
$response = $this->request('GET', '/contact');
return !is_wp_error($response);
}
/**
* Get all contact lists.
*/
public function get_lists() {
$response = $this->request('GET', '/contactslist?Limit=1000');
if (is_wp_error($response)) {
return $response;
}
return isset($response['Data']) ? $response['Data'] : array();
}
/**
* Add contact to list(s).
*/
public function add_contact_to_lists($email, $lists, $properties = array()) {
// Validate inputs
if (empty($email) || !is_email($email)) {
return new WP_Error('invalid_email', 'Invalid email address provided');
}
if (!is_array($lists) || empty($lists)) {
return new WP_Error('invalid_lists', 'Lists must be a non-empty array');
}
// First, ensure contact exists
$contact = $this->get_or_create_contact($email, $properties);
if (is_wp_error($contact)) {
return $contact;
}
// Validate contact response structure
if (!isset($contact['ID'])) {
return new WP_Error('invalid_contact_response', 'Contact response missing ID field');
}
$contact_id = $contact['ID'];
$results = array();
// Add contact to each list
foreach ($lists as $list_id) {
// Validate list ID
$list_id = absint($list_id);
if ($list_id === 0) {
$results['invalid'] = new WP_Error('invalid_list_id', 'Invalid list ID');
continue;
}
$result = $this->add_contact_to_list($contact_id, $list_id);
$results[$list_id] = $result;
}
return $results;
}
/**
* Get or create a contact.
*/
private function get_or_create_contact($email, $properties = array()) {
// Try to get existing contact
$response = $this->request('GET', '/contact/' . rawurlencode($email));
if (!is_wp_error($response) && isset($response['Data'][0])) {
// Contact exists, update properties if provided
if (!empty($properties)) {
$this->update_contact($email, $properties);
}
return $response['Data'][0];
}
// Create new contact
$data = array('Email' => $email);
if (!empty($properties)) {
$data['Properties'] = $properties;
}
$response = $this->request('POST', '/contact', $data);
if (is_wp_error($response)) {
return $response;
}
return isset($response['Data'][0]) ? $response['Data'][0] : new WP_Error('contact_creation_failed', 'Failed to create contact');
}
/**
* Update contact properties.
*/
private function update_contact($email, $properties) {
$data = array('Data' => $properties);
return $this->request('PUT', '/contactdata/' . rawurlencode($email), $data);
}
/**
* Add contact to a specific list.
*/
private function add_contact_to_list($contact_id, $list_id) {
$data = array(
'ContactID' => $contact_id,
'ListID' => $list_id,
'IsActive' => true
);
return $this->request('POST', '/contactslist/' . $list_id . '/managecontact', $data);
}
/**
* Make API request with rate limiting.
*/
private function request($method, $endpoint, $data = array()) {
// Rate limiting: configurable via filter, default 60 requests per minute
$rate_limit = apply_filters('wpfmj_api_rate_limit', 60);
$rate_limit = max(10, min(300, absint($rate_limit))); // Clamp between 10-300
$rate_limit_key = 'wpfmj_api_rate_' . md5($this->api_key);
$requests = get_transient($rate_limit_key);
if ($requests === false) {
$requests = 0;
}
if ($requests >= $rate_limit) {
return new WP_Error('rate_limit_exceeded', sprintf(
'API rate limit exceeded (%d requests per minute). Please wait a moment and try again.',
$rate_limit
));
}
// Increment request count
set_transient($rate_limit_key, $requests + 1, 60);
$url = $this->api_url . $endpoint;
$args = array(
'method' => $method,
'headers' => array(
'Content-Type' => 'application/json',
'Authorization' => 'Basic ' . base64_encode($this->api_key . ':' . $this->api_secret)
),
'timeout' => 30,
'sslverify' => true
);
if ($method === 'POST' || $method === 'PUT') {
$args['body'] = wp_json_encode($data);
}
$response = wp_remote_request($url, $args);
if (is_wp_error($response)) {
return $response;
}
$code = wp_remote_retrieve_response_code($response);
$body = wp_remote_retrieve_body($response);
// Validate JSON response
$json = json_decode($body, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return new WP_Error(
'mailjet_json_error',
sprintf('Invalid JSON response from Mailjet API: %s', json_last_error_msg()),
array('status' => $code, 'body' => substr($body, 0, 200))
);
}
if ($code >= 400) {
$message = isset($json['ErrorMessage']) ? sanitize_text_field($json['ErrorMessage']) : 'API request failed';
return new WP_Error('mailjet_api_error', $message, array('status' => $code));
}
return $json;
}
}