Covivo/mobicoop

View on GitHub
api/src/MassCommunication/CampaignProvider/SendinBlueProvider.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

/**
 * Copyright (c) 2020, MOBICOOP. All rights reserved.
 * This project is dual licensed under AGPL and proprietary licence.
 ***************************
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as
 *    published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <gnu.org/licenses>.
 ***************************
 *    Licence MOBICOOP described in the file
 *    LICENSE
 **************************/

namespace App\MassCommunication\CampaignProvider;

use App\MassCommunication\Entity\Sender;
use App\MassCommunication\Exception\CampaignException;
use App\MassCommunication\Interfaces\CampaignProviderInterface;
use SendinBlue\Client as SendinBlueClient;
use GuzzleHttp\Client;
use DateTime;
use Exception;

/**
 * SendinBlue mass email sender service.
 *
 * @author Sylvain Briat <sylvain.briat@mobicoop.org>
 * @author Remi Wortemann <remi.wortemann@mobicoop.org>
 *
 */
class SendinBlueProvider implements CampaignProviderInterface
{
    private $folderId;
    private $senderName;
    private $senderEmail;
    private $replyTo;
    private $templateId;
    private $contactsApi;
    private $emailCampaignApi;

    const CAMPAIGN_NAME="Campaign";
    const CONTACT_EMAIL="EMAIL";
    const CONTACT_FAMILYNAME="NOM";
    const CONTACT_GIVENNAME="PRENOM";
    const SIZE_LIMIT_CONTACT_IMPORT=8388608;

    /**
     * Constructor
     *
     * @param string $key           The api key
     * @param int $folderId         The ID for the SendinBlue folder
     * @param string $senderName    The sender name
     * @param string $senderEmail   The sender email
     * @param string $replyTo       The replyTo email
     * @param string $templateId    The ID for the SendinBlue template
     */
    public function __construct(string $key, int $folderId, string $senderName, string $senderEmail, string $replyTo, string $templateId)
    {
        $this->folderId = $folderId;
        $this->replyTo = $replyTo;
        $this->senderEmail = $senderEmail;
        $this->senderName = $senderName;
        $this->templateId = $templateId;
        // implement sendinBlue php library
        $config = SendinBlueClient\Configuration::getDefaultConfiguration()->setApiKey('api-key', $key);
        $this->contactsApi = new SendinBlueClient\Api\ContactsApi(
            new Client(),
            $config
        );
        $this->emailCampaignApi = new SendinBlueClient\Api\EmailCampaignsApi(
            new Client(),
            $config
        );
    }

    /**
     * Create a SendinBlue mailing campaign
     *
     * @param string $name              The name of the campaign
     * @param Sender $sender            The sender
     * @param string $subject           The subject
     * @param string $body              The body
     * @param Recipient[] $recipients   The list of recipients (as Recipient objects)
     * @return void
     */
    public function createCampaign(string $name, Sender $sender, string $subject, string $body, array $recipients)
    {
        // we create the list
        $createList = new SendinBlueClient\Model\CreateList();
        $createList['name'] = self::CAMPAIGN_NAME.date_format(new DateTime(), 'YmdHis');
        $createList['folderId'] = $this->folderId;
        try {
            $list = $this->contactsApi->createList($createList);
        } catch (Exception $e) {
            throw new CampaignException('Exception when calling SendinBlue ContactsApi->createList: ' . $e->getMessage());
        }

        // we import contacts
        $contactsList[0] = [self::CONTACT_EMAIL,self::CONTACT_FAMILYNAME,self::CONTACT_GIVENNAME];
        // we add the sender infos because the sender needs to be in the list to receive the test email
        $contactsList[1] = [$sender->getUser()->getEmail(), $sender->getUser()->getFamilyName(), $sender->getUser()->getGivenName()];
        $i = 2;
        // We add recipients to the contacts list
        foreach ($recipients as $recipient) {
            $contactsList[$i++] = [$recipient->getEmail(), $recipient->getFamilyName(), $recipient->getGivenName()];
        }
        //  We format the contacts list
        $contacts=[];
        foreach ($contactsList as $line) {
            $contact = implode(";", $line);
            $contacts[]=$contact;
        }
        $formatedContacts = implode("\n", $contacts);

        // we check if the contact list doesn't exceed size limit
        if (strlen($formatedContacts) > self::SIZE_LIMIT_CONTACT_IMPORT) {
            throw new CampaignException("Your contact list exceeds the size limit of " . self::SIZE_LIMIT_CONTACT_IMPORT);
        }
        
        // we import contacts
        $requestContactImport = new SendinBlueClient\Model\RequestContactImport();
        $requestContactImport['fileBody'] = $formatedContacts;
        $requestContactImport['listIds'] = [$list['id']];
        $requestContactImport['emailBlacklist'] = false;
        $requestContactImport['smsBlacklist'] = false;
        $requestContactImport['updateExistingContacts'] = true;
        $requestContactImport['emptyContactsAttributes'] = false;

        try {
            $this->contactsApi->importContacts($requestContactImport);
        } catch (Exception $e) {
            throw new CampaignException('Exception when calling SendinBlue ContactsApi->importContacts: ' . $e->getMessage());
        }

        // We create the campaign
        $emailCampaigns = new SendinBlueClient\Model\CreateEmailCampaign();
        $emailCampaigns['sender'] = ['name' => $this->senderName, 'email' => $this->senderEmail];
        $emailCampaigns['name'] = $createList['name'];
        $emailCampaigns['htmlContent'] = $body;
        if ($this->templateId != '') {
            $emailCampaigns['templateId'] = $this->templateId;
        }
        $emailCampaigns['subject'] = $subject;
        $emailCampaigns['replyTo'] = $this->replyTo;
        $emailCampaigns['recipients'] =  ['listIds' => [$list['id']]];
        $emailCampaigns['type'] = 'classic';

        try {
            return $this->emailCampaignApi->createEmailCampaign($emailCampaigns);
        } catch (Exception $e) {
            throw new CampaignException('Exception when calling SendinBlue EmailCampaignsApi->createEmailCampaign: ' . $e->getMessage());
        }
    }

    /**
     * Method to send the campaign now
     *
     * @param string $name          The name of the campaign (not useful for SendinBlue)
     * @param integer $campaignId   The campaign ID
     * @return void
     */
    public function sendCampaign(string $name, int $campaignId)
    {
        try {
            return $this->emailCampaignApi->sendEmailCampaignNow($campaignId);
        } catch (Exception $e) {
            throw new CampaignException('Exception when calling SendinBlue EmailCampaignsApi->sendEmailCampaignNow: ' . $e->getMessage());
        }
    }

    /**
     * Method to send a test email
     *
     * @param string $name (not usefull for SendinBlue)
     * @param integer $campaignId
     * @param array $emails
     * @return void
     */
    public function sendCampaignTest(string $name, int $campaignId, array $emails)
    {
        $emailTo = new SendinBlueClient\Model\SendTestEmail();
        $emailTo['emailTo'] = $emails;

        try {
            return $this->emailCampaignApi->sendTestEmail($campaignId, $emailTo);
        } catch (Exception $e) {
            throw new CampaignException('Exception when calling SendinBlue EmailCampaignsApi->sendTestEmail: ' . $e->getMessage());
        }
    }
}