Completed
Pull Request — master (#3)
by Chris
02:06
created

SparkPostTemplates   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 123
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 15
eloc 46
dl 0
loc 123
ccs 0
cts 43
cp 0
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getTemplate() 0 16 2
A __construct() 0 4 2
B convertTemplatedEmail() 0 47 8
A getInlineContent() 0 13 3
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
    public function __construct(SparkPost $sparkPost, LoggerInterface $logger = null)
38
    {
39
        $this->sparkPost = $sparkPost;
40
        $this->logger    = $logger ?: new NullLogger();
41
    }
42
43
    /**
44
     * SparkPost does not currently support sending attachments with templated emails. For this reason,
45
     * we will instead get the template from SparkPost and create a new inline template using the information
46
     * from it instead.
47
     *
48
     * @param Email $email
49
     *
50
     * @return Email
51
     */
52
    public function convertTemplatedEmail(Email $email): Email
53
    {
54
        $template    = $this->getTemplate($email);
55
        $inlineEmail = clone $email;
56
57
        $inlineEmail
58
            ->setSubject($template[SparkPostCourier::SUBJECT])
59
            ->setContent($this->getInlineContent($template));
60
61
62
        // If the from contains a templated from, it should be actively replaced now to avoid validation errors.
63
        if (strpos($template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_EMAIL], '{{') !== false) {
64
            $inlineEmail->setFrom($email->getFrom());
65
        } else {
66
            $inlineEmail->setFrom(
67
                new Address(
68
                    $template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_EMAIL],
69
                    $template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_NAME]
70
                )
71
            );
72
        }
73
74
        // If the form contains a templated replyTo, it should be actively replaced now to avoid validation errors.
75
        if (array_key_exists(SparkPostCourier::REPLY_TO, $template)) {
76
            if (strpos($template[SparkPostCourier::REPLY_TO], '{{') !== false) {
77
                if (empty($email->getReplyTos())) {
78
                    throw new ValidationException('Reply to is templated but no value was given');
79
                }
80
81
                $inlineEmail->setReplyTos($email->getReplyTos()[0]);
82
            } else {
83
                $inlineEmail->setReplyTos(Address::fromString($template[SparkPostCourier::REPLY_TO]));
84
            }
85
        }
86
87
        // Include headers defined on the template
88
        if (array_key_exists(SparkPostCourier::HEADERS, $template)) {
89
            foreach ($template[SparkPostCourier::HEADERS] as $key => $value) {
90
                $inlineEmail->addHeaders(new Header($key, $value));
91
            }
92
        }
93
94
        if ($email->getHeaders()) {
95
            $inlineEmail->addHeaders(...$email->getHeaders());
96
        }
97
98
        return $inlineEmail;
99
    }
100
101
    /**
102
     * Create the SimpleContent based on the SparkPost template data.
103
     *
104
     * @param array $template
105
     *
106
     * @return Content\SimpleContent
107
     */
108
    protected function getInlineContent(array $template): Content\SimpleContent
109
    {
110
        $htmlContent = null;
111
        if (array_key_exists(SparkPostCourier::HTML, $template)) {
112
            $htmlContent = new Content\SimpleContent\Message($template[SparkPostCourier::HTML]);
113
        }
114
115
        $textContent = null;
116
        if (array_key_exists(SparkPostCourier::TEXT, $template)) {
117
            $textContent = new Content\SimpleContent\Message($template[SparkPostCourier::TEXT]);
118
        }
119
120
        return new Content\SimpleContent($htmlContent, $textContent);
121
    }
122
123
    /**
124
     * Get the template content from SparkPost.
125
     *
126
     * @param Email $email
127
     *
128
     * @throws TransmissionException
129
     *
130
     * @return array
131
     */
132
    private function getTemplate(Email $email): array
133
    {
134
        try {
135
            $response = $this->sparkPost->syncRequest('GET', "templates/{$email->getContent()->getTemplateId()}");
1 ignored issue
show
Bug introduced by
The method getTemplateId() does not exist on PhpEmail\Content. It seems like you code against a sub-type of PhpEmail\Content such as PhpEmail\Content\Contracts\TemplatedContent. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
            $response = $this->sparkPost->syncRequest('GET', "templates/{$email->getContent()->/** @scrutinizer ignore-call */ getTemplateId()}");
Loading history...
136
137
            return $response->getBody()['results'][SparkPostCourier::CONTENT];
138
        } catch (SparkPostException $e) {
139
            $this->logger->error(
140
                'Received status {code} from SparkPost while retrieving template with body: {body}',
141
                [
142
                    'code' => $e->getCode(),
143
                    'body' => $e->getBody(),
144
                ]
145
            );
146
147
            throw new TransmissionException($e->getCode(), $e);
148
        }
149
    }
150
}
151