<commit_before><?php

/*
 * SendPulse REST API Client
 *
 * Documentation
 * https://login.sendpulse.com/manual/rest-api/
 * https://sendpulse.com/api
 *
 */

namespace Sendpulse\RestApi;

use Exception;
use Sendpulse\RestApi\Storage\FileStorage;
use Sendpulse\RestApi\Storage\TokenStorageInterface;
use stdClass;

class ApiClient implements ApiInterface
{

    private $apiUrl = 'https://api.sendpulse.com';

    private $userId;
    private $secret;
    private $token;

    private $refreshToken = 0;

    /**
     * @var null|TokenStorageInterface
     */
    private $tokenStorage;


    /**
     * Sendpulse API constructor
     *
     * @param                       $userId
     * @param                       $secret
     * @param TokenStorageInterface $tokenStorage
     *
     * @throws Exception
     */
    public function __construct($userId, $secret, TokenStorageInterface $tokenStorage = null)
    {
        if ($tokenStorage === null) {
            $tokenStorage = new FileStorage();
        }
        if (empty($userId) || empty($secret)) {
            throw new Exception('Empty ID or SECRET');
        }

        $this->userId = $userId;
        $this->secret = $secret;
        $this->tokenStorage = $tokenStorage;
        $hashName = md5($userId . '::' . $secret);

        /** load token from storage */
        $this->token = $this->tokenStorage->get($hashName);

        if (empty($this->token) && !$this->getToken()) {
            throw new Exception('Could not connect to api, check your ID and SECRET');
        }
    }

    /**
     * Get token and store it
     *
     * @return bool
     */
    private function getToken()
    {
        $data = array(
            'grant_type' => 'client_credentials',
            'client_id' => $this->userId,
            'client_secret' => $this->secret,
        );

        $requestResult = $this->sendRequest('oauth/access_token', 'POST', $data, false);

        if ($requestResult->http_code !== 200) {
            return false;
        }

        $this->refreshToken = 0;
        $this->token = $requestResult->data->access_token;

        $hashName = md5($this->userId . '::' . $this->secret);
        /** Save token to storage */
        $this->tokenStorage->set($hashName, $this->token);

        return true;
    }

    /**
     * Form and send request to API service
     *
     * @param        $path
     * @param string $method
     * @param array $data
     * @param bool $useToken
     *
     * @return stdClass
     */
    private function sendRequest($path, $method = 'GET', $data = array(), $useToken = true)
    {
        $url = $this->apiUrl . '/' . $path;
        $method = strtoupper($method);
        $curl = curl_init();

        if ($useToken && !empty($this->token)) {
            $headers = array('Authorization: Bearer ' . $this->token);
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }

        switch ($method) {
            case 'POST':
                curl_setopt($curl, CURLOPT_POST, count($data));
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            case 'PUT':
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            case 'DELETE':
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            default:
                if (!empty($data)) {
                    $url .= '?' . http_build_query($data);
                }
        }

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HEADER, true);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15);
        curl_setopt($curl, CURLOPT_TIMEOUT, 15);

        $response = curl_exec($curl);
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $headerCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $responseBody = substr($response, $header_size);

        curl_close($curl);

        if ($headerCode === 401 && $this->refreshToken === 0) {
            ++$this->refreshToken;
            $this->getToken();
            $retval = $this->sendRequest($path, $method, $data);
        } else {
            $retval = new stdClass();
            $retval->data = json_decode($responseBody);
            $retval->http_code = $headerCode;
        }

        return $retval;
    }

    /**
     * Process results
     *
     * @param $data
     *
     * @return stdClass
     */
    private function handleResult($data)
    {
        if (empty($data->data)) {
            $data->data = new stdClass();
        }
        if ($data->http_code !== 200) {
            $data->data->is_error = true;
            $data->data->http_code = $data->http_code;
        }

        return $data->data;
    }

    /**
     * Process errors
     *
     * @param null $customMessage
     *
     * @return stdClass
     */
    private function handleError($customMessage = null)
    {
        $message = new stdClass();
        $message->is_error = true;
        if (null !== $customMessage) {
            $message->message = $customMessage;
        }

        return $message;
    }


    /*
     * API interface implementation
     */


    /**
     * Create address book
     *
     * @param $bookName
     *
     * @return stdClass
     */
    public function createAddressBook($bookName)
    {
        if (empty($bookName)) {
            return $this->handleError('Empty book name');
        }

        $data = array('bookName' => $bookName);
        $requestResult = $this->sendRequest('addressbooks', 'POST', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Edit address book name
     *
     * @param $id
     * @param $newName
     *
     * @return stdClass
     */
    public function editAddressBook($id, $newName)
    {
        if (empty($newName) || empty($id)) {
            return $this->handleError('Empty new name or book id');
        }

        $data = array('name' => $newName);
        $requestResult = $this->sendRequest('addressbooks/' . $id, 'PUT', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Remove address book
     *
     * @param $id
     *
     * @return stdClass
     */
    public function removeAddressBook($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id, 'DELETE');

        return $this->handleResult($requestResult);
    }

    /**
     * Get list of address books
     *
     * @param null $limit
     * @param null $offset
     *
     * @return mixed
     */
    public function listAddressBooks($limit = null, $offset = null)
    {
        $data = array();
        if (null !== $limit) {
            $data['limit'] = $limit;
        }
        if (null !== $offset) {
            $data['offset'] = $offset;
        }

        $requestResult = $this->sendRequest('addressbooks', 'GET', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Get information about book
     *
     * @param $id
     *
     * @return stdClass
     */
    public function getBookInfo($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id);

        return $this->handleResult($requestResult);
    }

    /**
     * Get variables from book
     *
     * @param $id
     *   Address book id.
     *
     * @return stdClass
     */
    public function getBookVariables($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id . '/variables');

        return $this->handleResult($requestResult);
    }

    /**
     * List email addresses from book
     *
     * @param $id
     * @param $limit
     * @param $offset
     *
     * @return stdClass
     */
    public function getEmailsFromBook($id, $limit = null, $offset = null)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $data = array();
        if (null !== $limit) {
            $data['limit'] = $limit;
        }
        if (null !== $offset) {
            $data['offset'] = $offset;
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id . '/emails', 'GET', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Add new emails to address book
     *
     * @param $bookID
     * @param $emails
     *
     * @return stdClass
     */
    public function addEmails($bookID, $emails)
    {
        if (empty($bookID) || empty($emails)) {
            return $this->handleError('Empty book id or emails');
        }

        $data = array(
            'emails' => serialize($emails),
        );

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/emails', 'POST', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Remove email addresses from book
     *
     * @param $bookID
     * @param $emails
     *
     * @return stdClass
     */
    public function removeEmails($bookID, $emails)
    {
        if (empty($bookID) || empty($emails)) {
            return $this->handleError('Empty book id or emails');
        }

        $data = array(
            'emails' => serialize($emails),
        );

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/emails', 'DELETE', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Get information about email address from book
     *
     * @param $bookID
     * @param $email
     *
     * @return stdClass
     */
    public function getEmailInfo($bookID, $email)
    {
        if (empty($bookID) || empty($email)) {
            return $this->handleError('Empty book id or email');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/emails/' . $email);

        return $this->handleResult($requestResult);
    }

    /**
     * Get cost of campaign based on address book
     *
     * @param $bookID
     *
     * @return stdClass
     */
    public function campaignCost($bookID)
    {
        if (empty($bookID)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/cost');

        return $this->handleResult($requestResult);
    }

    /**
     * Get list of campaigns
     *
     * @param null $limit
     * @param null $offset
     *
     * @return mixed
     */
    public function listCampaigns($limit = null, $offset = null)
    {
        $data = array();
        if (!empty($limit)) {
            $data['limit'] = $limit;
        }
        if (!empty($offset)) {
            $data['offset'] = $offset;
        }
        $requestResult = $this->sendRequest('campaigns', 'GET', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Get information about campaign
     *
     * @param $id
     *
     * @return stdClass
     */
    public function getCampaignInfo($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id);

        return $this->handleResult($requestResult);
    }

    /**
     * Get campaign statistic by countries
     *
     * @param $id
     *
     * @return stdClass
     */
    public function campaignStatByCountries($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id . '/countries');

        return $this->handleResult($requestResult);
    }

    /**
     * Get campaign statistic by referrals
     *
     * @param $id
     *
     * @return stdClass
     */
    public function campaignStatByReferrals($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id . '/referrals');

        return $this->handleResult($requestResult);
    }

    /**
     * Create new campaign
     *
     * @param        $senderName
     * @param        $senderEmail
     * @param        $subject
     * @param        $body
     * @param        $bookId
     * @param string $name
     * @param string $attachments
     * @param string $type
     *
     * @return mixed
     */
    public function createCampaign(
        $senderName,
        $senderEmail,
        $subject,
        $body,
        $bookId,
        $name = '',
        $attachments = '',
        $type = ''
    ) {
        if (empty($senderName) || empty($senderEmail) || empty($subject) || empty($body) || empty($bookId)) {
            return $this->handleError('Not all data.');
        }

        if (!empty($attachments)) {
            $attachments = serialize($attachments);
        }
        $data = array(
            'sender_name' => $senderName,
            'sender_email' => $senderEmail,
            'subject' => $subject,
            'body' => base64_encode($body),
            'list_id' => $bookId,
            'name' => $name,
            'attachments' => $attachments,
            'type' => $type,
        );

        $requestResult = $this->sendRequest('campaigns', 'POST', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Cancel campaign
     *
     * @param $id
     *
     * @return stdClass
     */
    public function cancelCampaign($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id, 'DELETE');<commit_msg>added the ability to create a campaign with a template<commit_after><?php

/*
 * SendPulse REST API Client
 *
 * Documentation
 * https://login.sendpulse.com/manual/rest-api/
 * https://sendpulse.com/api
 *
 */

namespace Sendpulse\RestApi;

use Exception;
use Sendpulse\RestApi\Storage\FileStorage;
use Sendpulse\RestApi\Storage\TokenStorageInterface;
use stdClass;

class ApiClient implements ApiInterface
{

    private $apiUrl = 'https://api.sendpulse.com';

    private $userId;
    private $secret;
    private $token;

    private $refreshToken = 0;

    /**
     * @var null|TokenStorageInterface
     */
    private $tokenStorage;


    /**
     * Sendpulse API constructor
     *
     * @param                       $userId
     * @param                       $secret
     * @param TokenStorageInterface $tokenStorage
     *
     * @throws Exception
     */
    public function __construct($userId, $secret, TokenStorageInterface $tokenStorage = null)
    {
        if ($tokenStorage === null) {
            $tokenStorage = new FileStorage();
        }
        if (empty($userId) || empty($secret)) {
            throw new Exception('Empty ID or SECRET');
        }

        $this->userId = $userId;
        $this->secret = $secret;
        $this->tokenStorage = $tokenStorage;
        $hashName = md5($userId . '::' . $secret);

        /** load token from storage */
        $this->token = $this->tokenStorage->get($hashName);

        if (empty($this->token) && !$this->getToken()) {
            throw new Exception('Could not connect to api, check your ID and SECRET');
        }
    }

    /**
     * Get token and store it
     *
     * @return bool
     */
    private function getToken()
    {
        $data = array(
            'grant_type' => 'client_credentials',
            'client_id' => $this->userId,
            'client_secret' => $this->secret,
        );

        $requestResult = $this->sendRequest('oauth/access_token', 'POST', $data, false);

        if ($requestResult->http_code !== 200) {
            return false;
        }

        $this->refreshToken = 0;
        $this->token = $requestResult->data->access_token;

        $hashName = md5($this->userId . '::' . $this->secret);
        /** Save token to storage */
        $this->tokenStorage->set($hashName, $this->token);

        return true;
    }

    /**
     * Form and send request to API service
     *
     * @param        $path
     * @param string $method
     * @param array $data
     * @param bool $useToken
     *
     * @return stdClass
     */
    private function sendRequest($path, $method = 'GET', $data = array(), $useToken = true)
    {
        $url = $this->apiUrl . '/' . $path;
        $method = strtoupper($method);
        $curl = curl_init();

        if ($useToken && !empty($this->token)) {
            $headers = array('Authorization: Bearer ' . $this->token);
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }

        switch ($method) {
            case 'POST':
                curl_setopt($curl, CURLOPT_POST, count($data));
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            case 'PUT':
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT');
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            case 'DELETE':
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
                break;
            default:
                if (!empty($data)) {
                    $url .= '?' . http_build_query($data);
                }
        }

        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HEADER, true);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 15);
        curl_setopt($curl, CURLOPT_TIMEOUT, 15);

        $response = curl_exec($curl);
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
        $headerCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        $responseBody = substr($response, $header_size);

        curl_close($curl);

        if ($headerCode === 401 && $this->refreshToken === 0) {
            ++$this->refreshToken;
            $this->getToken();
            $retval = $this->sendRequest($path, $method, $data);
        } else {
            $retval = new stdClass();
            $retval->data = json_decode($responseBody);
            $retval->http_code = $headerCode;
        }

        return $retval;
    }

    /**
     * Process results
     *
     * @param $data
     *
     * @return stdClass
     */
    private function handleResult($data)
    {
        if (empty($data->data)) {
            $data->data = new stdClass();
        }
        if ($data->http_code !== 200) {
            $data->data->is_error = true;
            $data->data->http_code = $data->http_code;
        }

        return $data->data;
    }

    /**
     * Process errors
     *
     * @param null $customMessage
     *
     * @return stdClass
     */
    private function handleError($customMessage = null)
    {
        $message = new stdClass();
        $message->is_error = true;
        if (null !== $customMessage) {
            $message->message = $customMessage;
        }

        return $message;
    }


    /*
     * API interface implementation
     */


    /**
     * Create address book
     *
     * @param $bookName
     *
     * @return stdClass
     */
    public function createAddressBook($bookName)
    {
        if (empty($bookName)) {
            return $this->handleError('Empty book name');
        }

        $data = array('bookName' => $bookName);
        $requestResult = $this->sendRequest('addressbooks', 'POST', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Edit address book name
     *
     * @param $id
     * @param $newName
     *
     * @return stdClass
     */
    public function editAddressBook($id, $newName)
    {
        if (empty($newName) || empty($id)) {
            return $this->handleError('Empty new name or book id');
        }

        $data = array('name' => $newName);
        $requestResult = $this->sendRequest('addressbooks/' . $id, 'PUT', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Remove address book
     *
     * @param $id
     *
     * @return stdClass
     */
    public function removeAddressBook($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id, 'DELETE');

        return $this->handleResult($requestResult);
    }

    /**
     * Get list of address books
     *
     * @param null $limit
     * @param null $offset
     *
     * @return mixed
     */
    public function listAddressBooks($limit = null, $offset = null)
    {
        $data = array();
        if (null !== $limit) {
            $data['limit'] = $limit;
        }
        if (null !== $offset) {
            $data['offset'] = $offset;
        }

        $requestResult = $this->sendRequest('addressbooks', 'GET', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Get information about book
     *
     * @param $id
     *
     * @return stdClass
     */
    public function getBookInfo($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id);

        return $this->handleResult($requestResult);
    }

    /**
     * Get variables from book
     *
     * @param $id
     *   Address book id.
     *
     * @return stdClass
     */
    public function getBookVariables($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id . '/variables');

        return $this->handleResult($requestResult);
    }

    /**
     * List email addresses from book
     *
     * @param $id
     * @param $limit
     * @param $offset
     *
     * @return stdClass
     */
    public function getEmailsFromBook($id, $limit = null, $offset = null)
    {
        if (empty($id)) {
            return $this->handleError('Empty book id');
        }

        $data = array();
        if (null !== $limit) {
            $data['limit'] = $limit;
        }
        if (null !== $offset) {
            $data['offset'] = $offset;
        }

        $requestResult = $this->sendRequest('addressbooks/' . $id . '/emails', 'GET', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Add new emails to address book
     *
     * @param $bookID
     * @param $emails
     *
     * @return stdClass
     */
    public function addEmails($bookID, $emails)
    {
        if (empty($bookID) || empty($emails)) {
            return $this->handleError('Empty book id or emails');
        }

        $data = array(
            'emails' => serialize($emails),
        );

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/emails', 'POST', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Remove email addresses from book
     *
     * @param $bookID
     * @param $emails
     *
     * @return stdClass
     */
    public function removeEmails($bookID, $emails)
    {
        if (empty($bookID) || empty($emails)) {
            return $this->handleError('Empty book id or emails');
        }

        $data = array(
            'emails' => serialize($emails),
        );

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/emails', 'DELETE', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Get information about email address from book
     *
     * @param $bookID
     * @param $email
     *
     * @return stdClass
     */
    public function getEmailInfo($bookID, $email)
    {
        if (empty($bookID) || empty($email)) {
            return $this->handleError('Empty book id or email');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/emails/' . $email);

        return $this->handleResult($requestResult);
    }

    /**
     * Get cost of campaign based on address book
     *
     * @param $bookID
     *
     * @return stdClass
     */
    public function campaignCost($bookID)
    {
        if (empty($bookID)) {
            return $this->handleError('Empty book id');
        }

        $requestResult = $this->sendRequest('addressbooks/' . $bookID . '/cost');

        return $this->handleResult($requestResult);
    }

    /**
     * Get list of campaigns
     *
     * @param null $limit
     * @param null $offset
     *
     * @return mixed
     */
    public function listCampaigns($limit = null, $offset = null)
    {
        $data = array();
        if (!empty($limit)) {
            $data['limit'] = $limit;
        }
        if (!empty($offset)) {
            $data['offset'] = $offset;
        }
        $requestResult = $this->sendRequest('campaigns', 'GET', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Get information about campaign
     *
     * @param $id
     *
     * @return stdClass
     */
    public function getCampaignInfo($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id);

        return $this->handleResult($requestResult);
    }

    /**
     * Get campaign statistic by countries
     *
     * @param $id
     *
     * @return stdClass
     */
    public function campaignStatByCountries($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id . '/countries');

        return $this->handleResult($requestResult);
    }

    /**
     * Get campaign statistic by referrals
     *
     * @param $id
     *
     * @return stdClass
     */
    public function campaignStatByReferrals($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id . '/referrals');

        return $this->handleResult($requestResult);
    }

    /**
     * Create new campaign
     *
     * @param        $senderName
     * @param        $senderEmail
     * @param        $subject
     * @param        $bodyOrTemplateId
     * @param        $bookId
     * @param string $name
     * @param string $attachments
     * @param string $type
     * @param bool   $useTemplateId
     *
     * @return mixed
     */
    public function createCampaign(
        $senderName,
        $senderEmail,
        $subject,
        $bodyOrTemplateId,
        $bookId,
        $name = '',
        $attachments = '',
        $type = '',
        $useTemplateId = false
    ) {
        if (empty($senderName) || empty($senderEmail) || empty($subject) || empty($bodyOrTemplateId) || empty($bookId)) {
            return $this->handleError('Not all data.');
        }

        if (!empty($attachments)) {
            $attachments = serialize($attachments);
        }

        if($useTemplateId) {
            $paramName = 'template_id';
            $paramValue = $bodyOrTemplateId;
        } else {
            $paramName = 'body';
            $paramValue = base64_encode($bodyOrTemplateId);
        }

        $data = array(
            'sender_name' => $senderName,
            'sender_email' => $senderEmail,
            'subject' => $subject,
            $paramName => $paramValue,
            'list_id' => $bookId,
            'name' => $name,
            'attachments' => $attachments,
            'type' => $type,
        );

        $requestResult = $this->sendRequest('campaigns', 'POST', $data);

        return $this->handleResult($requestResult);
    }

    /**
     * Cancel campaign
     *
     * @param $id
     *
     * @return stdClass
     */
    public function cancelCampaign($id)
    {
        if (empty($id)) {
            return $this->handleError('Empty campaign id');
        }

        $requestResult = $this->sendRequest('campaigns/' . $id, 'DELETE');
{'fraction_non_alphanumeric': 0.14429389579550217, 'fraction_numerical': 0.0013968431345159939, 'mean_word_length': 1.8505872984272347, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 211, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3051977', 'n_tokens_mistral': 8550, 'n_tokens_neox': 8213, 'n_words': 1761}