BuddyAd/sendy-laravel

View on GitHub
src/Sendy.php

Summary

Maintainability
A
45 mins
Test Coverage
<?php

namespace BuddyAd\Sendy;

use BuddyAd\Sendy\Exceptions\SendyException;

/**
 * Class Sendy
 *
 * @package BuddyAd\Sendy
 */
class Sendy extends SendyStatus
{
    protected $config;
    protected $installationUrl;
    protected $apiKey;
    protected $listId;

    /**
     * Sendy constructor.
     *
     * @param array $config
     *
     * @throws \Exception
     */
    public function __construct(array $config)
    {
        $this->setListId($config['listId']);
        $this->setInstallationUrl($config['installationUrl']);
        $this->setApiKey($config['apiKey']);
        $this->checkProperties();
    }

    /**
     * @param mixed $installationUrl
     */
    public function setInstallationUrl($installationUrl)
    {
        $this->installationUrl = $installationUrl;
    }

    /**
     * @param mixed $apiKey
     */
    public function setApiKey($apiKey)
    {
        $this->apiKey = $apiKey;
    }

    /**
     * @param $listId
     *
     * @return $this
     */
    public function setListId($listId)
    {
        $this->listId = $listId;

        return $this;
    }

    /**
     * Method to add a new subscriber to a list
     *
     * @param array $values
     *
     * @return array
     */
    public function subscribe(array $values): array
    {
        $response = $this->buildAndSend('subscribe', $values);
        $notice = $this->buildResponse($response);

        if ($notice['message'] === '1') {
            $notice['message'] = 'Subscribed.';
        }

        return $notice;
    }

    /**
     * Updating a subscriber using the email like a reference/key
     * If the email doesn't exists in the current list, this will create a new subscriber
     *
     * @param $email
     * @param array $values
     *
     * @return array
     */
    public function update($email, array $values): array
    {
        $values = array_merge([
            'email' => $email
        ], $values);
        $notice = $this->subscribe($values);
        $notice['status'] = !$notice['status'];

        return $notice;
    }

    /**
     * Method to unsubscribe a user from a list
     *
     * @param $email
     *
     * @return array
     */
    public function unsubscribe($email): array
    {
        $response = $this->buildAndSend('unsubscribe', [
            'email' => $email,
        ]);
        $notice = $this->buildResponse($response);

        if ($notice['message'] === '1') {
            $notice['message'] = 'Unsubscribed';
        }

        return $notice;
    }

    /**
     * Method to get the current status of a subscriber.
     * Success: Subscribed, Unsubscribed, Unconfirmed, Bounced, Soft bounced, Complained
     * Error: No data passed, Email does not exist in list, etc.
     *
     * @param string $email
     *
     * @return array
     */
    public function subscriptionStatus(string $email): array
    {
        $url = 'api/subscribers/subscription-status.php';
        $response = $this->buildAndSend($url, [
            'email' => $email,
        ]);

        return $this->buildResponse($response);
    }

    /**
     * Gets the total active subscriber count
     *
     * @return array
     */
    public function count(): array
    {
        $url = 'api/subscribers/active-subscriber-count.php';
        $response = $this->buildAndSend($url, []);

        return $this->buildResponse($response);
    }

    /**
     * Create a campaign based on the input params. See API (https://sendy.co/api#4) for parameters.
     * Bug: The API doesn't save the listIds passed to Sendy.
     *
     * @param $options
     * @param $content
     * @param bool $send : Set this to true to send the campaign
     *
     * @return array
     *
     * @throws \Exception
     */
    public function createCampaign($options, $content, $send = false): array
    {
        $url = '/api/campaigns/create.php';

        if (empty($options['from_name'])) {
            throw new SendyException('From Name is not set');
        }

        if (empty($options['from_email'])) {
            throw new SendyException('From Email is not set');
        }

        if (empty($options['reply_to'])) {
            throw new SendyException('Reply To address is not set');
        }

        if (empty($options['subject'])) {
            throw new SendyException('Subject is not set');
        }

        // 'plain_text' field can be included, but optional
        if (empty($content['html_text'])) {
            throw new SendyException('Campaign Content (HTML) is not set');
        }

        if ($send && empty($options['brand_id'])) {
            throw new SendyException('Brand ID should be set for Draft campaigns');
        }

        // list IDs can be single or comma separated values
        if (empty($options['list_ids'])) {
            $options['list_ids'] = $this->listId;
        }

        // should we send the campaign (1) or save as Draft (0)
        $options['send_campaign'] = $send ? 1 : 0;

        $response = $this->buildAndSend($url, array_merge($options, $content));

        return $this->buildResponse($response);
    }

    /**
     * @param $url
     * @param array $values
     *
     * @return string
     */
    private function buildAndSend($url, array $values): string
    {
        /**
         * Merge the passed in values with the options for return
         * Passing listId too, because old API calls use list, new ones use listId
         */
        $content = array_merge($values, [
            'list' => $this->listId,
            'list_id' => $this->listId, # ¯\_(ツ)_/¯
            'api_key' => $this->apiKey,
            'boolean' => 'true',
        ]);

        /**
         * Build a query using the $content
         */
        $post_data = http_build_query($content);
        $ch = curl_init($this->installationUrl . '/' . $url);

        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

        $result = curl_exec($ch);
        curl_close($ch);

        return $result;
    }

    /**
     * Checks the properties
     *
     * @throws \Exception
     */
    private function checkProperties()
    {
        if (null === $this->listId) {
            throw new SendyException('[listId] is not set');
        }

        if (null === $this->installationUrl) {
            throw new SendyException('[installationUrl] is not set');
        }

        if (null === $this->apiKey) {
            throw new SendyException('[apiKey] is not set');
        }
    }

    /**
     * @param $response
     *
     * @return bool
     */
    private function isError($response): bool
    {
        return !isset(self::ST_ERROR[$response]);
    }

    /**
     * @param $response
     *
     * @return array
     */
    private function buildResponse($response): array
    {
        $notice = [
            'status' => $this->isError($response),
            'message' => $response,
            'code' => $this->buildCode($response),
        ];

        return $notice;
    }

    /**
     * @param $response
     *
     * @return int
     */
    private function buildCode($response): int
    {
        if (array_key_exists($response, self::ST_ERROR)) {
            return self::ST_ERROR[$response];
        }

        if (array_key_exists($response, self::ST_SUCCESS)) {
            return self::ST_SUCCESS[$response];
        }

        return 1;
    }
}