File "MailChimp.php"
Full Path: /home/warrior1/public_html/wp-content/plugins/mailpoet/lib/Subscribers/ImportExport/Import/MailChimp.php
File size: 5.39 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace MailPoet\Subscribers\ImportExport\Import;
if (!defined('ABSPATH')) exit;
use MailPoet\Util\Helpers;
class MailChimp {
private const API_BASE_URI = 'https://user:%s@%s.api.mailchimp.com/3.0/';
private const API_KEY_REGEX = '/[a-zA-Z0-9]{32}-[a-zA-Z0-9]{2,4}$/';
private const API_BATCH_SIZE = 100;
/** @var false|string */
public $apiKey;
/** @var int */
public $maxPostSize;
/** @var false|string */
public $dataCenter;
/** @var MailChimpDataMapper */
private $mapper;
public function __construct(
string $apiKey
) {
$this->apiKey = $this->getAPIKey($apiKey);
$this->maxPostSize = (int)Helpers::getMaxPostSize('bytes');
$this->dataCenter = $this->getDataCenter($this->apiKey);
$this->mapper = new MailChimpDataMapper();
}
public function getLists(): array {
if (!$this->apiKey || !$this->dataCenter) {
$this->throwException('API');
}
$lists = [];
$count = 0;
while (true) {
$data = $this->getApiData('lists', $count);
if ($data === null) {
$this->throwException('lists');
break;
}
$count += count($data['lists']);
foreach ($data['lists'] as $list) {
$lists[] = [
'id' => $list['id'],
'name' => $list['name'],
];
}
if ($data['total_items'] <= $count) {
break;
}
}
return $lists;
}
public function getSubscribers(array $lists = []): array {
if (!$this->apiKey || !$this->dataCenter) {
$this->throwException('API');
}
if (!$lists) {
$this->throwException('lists');
}
$subscribers = [];
$duplicate = [];
$disallowed = [];
foreach ($lists as $list) {
$count = 0;
while (true) {
$data = $this->getApiData("lists/{$list}/members", $count);
if ($data === null) {
$this->throwException('lists');
break;
}
$count += count($data['members']);
foreach ($data['members'] as $member) {
$emailAddress = $member['email_address'];
if (!$this->isSubscriberAllowed($member)) {
$disallowed[$emailAddress] = $this->mapper->mapMember($member);
} elseif (isset($subscribers[$emailAddress])) {
$duplicate[$emailAddress] = $this->mapper->mapMember($member);
} else {
$subscribers[$emailAddress] = $this->mapper->mapMember($member);
}
}
if ($data['total_items'] <= $count) {
break;
}
}
}
if (!count($subscribers)) {
$this->throwException('subscribers');
}
return [
'subscribers' => array_values($subscribers),
'invalid' => [],
'duplicate' => $duplicate,
'disallowed' => $disallowed,
'role' => [],
'header' => $this->mapper->getMembersHeader(),
'subscribersCount' => count($subscribers),
];
}
/**
* @param string|false $apiKey
* @return false|string
*/
public function getDataCenter($apiKey) {
if (!$apiKey) return false;
$apiKeyParts = explode('-', $apiKey);
return end($apiKeyParts);
}
/**
* @param string $apiKey
* @return false|string
*/
public function getAPIKey(string $apiKey) {
return (preg_match(self::API_KEY_REGEX, $apiKey)) ? $apiKey : false;
}
/**
* @param string $error
* @throws \Exception
*/
public function throwException(string $error): void {
$errorMessage = __('Unknown MailChimp error.', 'mailpoet');
switch ($error) {
case 'API':
$errorMessage = __('Invalid API Key.', 'mailpoet');
break;
case 'size':
$errorMessage = __('The information received from MailChimp is too large for processing. Please limit the number of lists!', 'mailpoet');
break;
case 'subscribers':
$errorMessage = __('Did not find any active subscribers.', 'mailpoet');
break;
case 'lists':
$errorMessage = __('Did not find any valid lists.', 'mailpoet');
break;
}
throw new \Exception($errorMessage);
}
public function isSubscriberAllowed(array $subscriber): bool {
if (in_array($subscriber['status'], ['unsubscribed', 'cleaned', 'pending'], true)) {
return false;
}
if ($subscriber['member_rating'] < 2) {
return false;
}
// Rate 1 is on MailChimp API equal to 100% and we don't want to import avg_open_rate lower than 5%
if ($subscriber['stats']['avg_open_rate'] < 0.05) {
return false;
}
// We don't want to import avg_click_rate lower than 0.5%
if ($subscriber['stats']['avg_click_rate'] < 0.005) {
return false;
}
return true;
}
private function getApiData(string $endpoint, int $offset): ?array {
$url = sprintf(self::API_BASE_URI, $this->apiKey, $this->dataCenter);
$url .= $endpoint . '?' . http_build_query([
'count' => self::API_BATCH_SIZE,
'offset' => $offset,
]);
$connection = @fopen($url, 'r');
if (!$connection) {
return null;
}
$bytesFetched = 0;
$response = '';
while (!feof($connection)) {
$buffer = fgets($connection, 4096);
if (!is_string($buffer)) {
return null;
}
if (trim($buffer) !== '') {
$response .= $buffer;
}
$bytesFetched += strlen((string)$buffer);
if ($bytesFetched > $this->maxPostSize) {
$this->throwException('size');
}
}
fclose($connection);
return json_decode($response, true);
}
}