Passed
Push — master ( eb1258...b22374 )
by Chris
03:04
created

SparkPostTemplates::convertTemplatedEmail()   B

Complexity

Conditions 8
Paths 26

Size

Total Lines 46
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 8

Importance

Changes 0
Metric Value
cc 8
eloc 25
nc 26
nop 1
dl 0
loc 46
ccs 23
cts 23
cp 1
crap 8
rs 8.4444
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Courier\SparkPost;
6
7
use Courier\Exceptions\TransmissionException;
8
use Courier\Exceptions\ValidationException;
9
use PhpEmail\Address;
10
use PhpEmail\Content;
11
use PhpEmail\Email;
12
use PhpEmail\Header;
13
use Psr\Log\LoggerInterface;
14
use Psr\Log\NullLogger;
15
use SparkPost\SparkPost;
16
use SparkPost\SparkPostException;
17
18
/**
19
 * A class to retrieve SparkPost templates and convert them into SimpleContent Email classes.
20
 *
21
 * SparkPost does not currently support sending attachments with templated emails. For this reason,
22
 * this class will instead get the template from SparkPost and create a new SimpleContent Email object with enough
23
 * properties set to allow the courier to build the email content.
24
 */
25
class SparkPostTemplates
26
{
27
    /**
28
     * @var SparkPost
29
     */
30
    private $sparkPost;
31
32
    /**
33
     * @var LoggerInterface
34
     */
35
    private $logger;
36
37 15
    public function __construct(SparkPost $sparkPost, LoggerInterface $logger = null)
38
    {
39 15
        $this->sparkPost = $sparkPost;
40 15
        $this->logger    = $logger ?: new NullLogger();
41
    }
42
43
    /**
44
     * Convert a templated email into simple content email using the content of the template stored on SparkPost.
45
     *
46
     * @param Email $email
47
     *
48
     * @return Email
49
     */
50 6
    public function convertTemplatedEmail(Email $email): Email
51
    {
52 6
        $template    = $this->getTemplate($email);
53 5
        $inlineEmail = clone $email;
54
55
        $inlineEmail
56 5
            ->setSubject($template[SparkPostCourier::SUBJECT])
57 5
            ->setContent($this->getInlineContent($template));
58
59
        // If the from contains a templated from, it should be actively replaced now to avoid validation errors.
60 5
        if (strpos($template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_EMAIL], '{{') !== false) {
61 3
            $inlineEmail->setFrom($email->getFrom());
62
        } else {
63 2
            $inlineEmail->setFrom(
64 2
                new Address(
65 2
                    $template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_EMAIL],
66 2
                    $template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_NAME]
67
                )
68
            );
69
        }
70
71
        // If the form contains a templated replyTo, it should be actively replaced now to avoid validation errors.
72 5
        if (array_key_exists(SparkPostCourier::REPLY_TO, $template)) {
73 5
            if (strpos($template[SparkPostCourier::REPLY_TO], '{{') !== false) {
74 3
                if (empty($email->getReplyTos())) {
75 1
                    throw new ValidationException('Reply to is templated but no value was given');
76
                }
77
78 2
                $inlineEmail->setReplyTos($email->getReplyTos()[0]);
79
            } else {
80 2
                $inlineEmail->setReplyTos(Address::fromString($template[SparkPostCourier::REPLY_TO]));
81
            }
82
        }
83
84
        // Include headers defined on the template
85 4
        if (array_key_exists(SparkPostCourier::HEADERS, $template)) {
86 4
            foreach ($template[SparkPostCourier::HEADERS] as $key => $value) {
87 4
                $inlineEmail->addHeaders(new Header($key, $value));
88
            }
89
        }
90
91 4
        if ($email->getHeaders()) {
92 1
            $inlineEmail->addHeaders(...$email->getHeaders());
93
        }
94
95 4
        return $inlineEmail;
96
    }
97
98
    /**
99
     * Create the SimpleContent based on the SparkPost template data.
100
     *
101
     * @param array $template
102
     *
103
     * @return Content\SimpleContent
104
     */
105 5
    protected function getInlineContent(array $template): Content\SimpleContent
106
    {
107 5
        $htmlContent = null;
108 5
        if (array_key_exists(SparkPostCourier::HTML, $template)) {
109 5
            $htmlContent = new Content\SimpleContent\Message($template[SparkPostCourier::HTML]);
110
        }
111
112 5
        $textContent = null;
113 5
        if (array_key_exists(SparkPostCourier::TEXT, $template)) {
114 1
            $textContent = new Content\SimpleContent\Message($template[SparkPostCourier::TEXT]);
115
        }
116
117 5
        return new Content\SimpleContent($htmlContent, $textContent);
118
    }
119
120
    /**
121
     * Get the template content from SparkPost.
122
     *
123
     * @param Email $email
124
     *
125
     * @throws TransmissionException
126
     *
127
     * @return array
128
     */
129 6
    protected function getTemplate(Email $email): array
130
    {
131
        try {
132 6
            $response = $this->sparkPost->syncRequest('GET', "templates/{$email->getContent()->getTemplateId()}");
133
134 5
            return $response->getBody()['results'][SparkPostCourier::CONTENT];
135 1
        } catch (SparkPostException $e) {
136 1
            $this->logger->error(
137 1
                'Received status {code} from SparkPost while retrieving template with body: {body}',
138
                [
139 1
                    'code' => $e->getCode(),
140 1
                    'body' => $e->getBody(),
141
                ]
142
            );
143
144 1
            throw new TransmissionException($e->getCode(), $e);
145
        }
146
    }
147
}
148