Completed
Pull Request — master (#3)
by Chris
06:24 queued 04:30
created

SparkPostTemplates::getInlineContent()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 13
ccs 8
cts 8
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 4
nop 1
crap 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 14
    public function __construct(SparkPost $sparkPost, LoggerInterface $logger = null)
38
    {
39 14
        $this->sparkPost = $sparkPost;
40 14
        $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 6
    public function convertTemplatedEmail(Email $email): Email
53
    {
54 6
        $template    = $this->getTemplate($email);
55 5
        $inlineEmail = clone $email;
56
57
        $inlineEmail
58 5
            ->setSubject($template[SparkPostCourier::SUBJECT])
59 5
            ->setContent($this->getInlineContent($template));
60
61
        // If the from contains a templated from, it should be actively replaced now to avoid validation errors.
62 5
        if (strpos($template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_EMAIL], '{{') !== false) {
63 3
            $inlineEmail->setFrom($email->getFrom());
64
        } else {
65 2
            $inlineEmail->setFrom(
66 2
                new Address(
67 2
                    $template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_EMAIL],
68 2
                    $template[SparkPostCourier::FROM][SparkPostCourier::CONTACT_NAME]
69
                )
70
            );
71
        }
72
73
        // If the form contains a templated replyTo, it should be actively replaced now to avoid validation errors.
74 5
        if (array_key_exists(SparkPostCourier::REPLY_TO, $template)) {
75 5
            if (strpos($template[SparkPostCourier::REPLY_TO], '{{') !== false) {
76 3
                if (empty($email->getReplyTos())) {
77 1
                    throw new ValidationException('Reply to is templated but no value was given');
78
                }
79
80 2
                $inlineEmail->setReplyTos($email->getReplyTos()[0]);
81
            } else {
82 2
                $inlineEmail->setReplyTos(Address::fromString($template[SparkPostCourier::REPLY_TO]));
83
            }
84
        }
85
86
        // Include headers defined on the template
87 4
        if (array_key_exists(SparkPostCourier::HEADERS, $template)) {
88 3
            foreach ($template[SparkPostCourier::HEADERS] as $key => $value) {
89 3
                $inlineEmail->addHeaders(new Header($key, $value));
90
            }
91
        }
92
93 4
        if ($email->getHeaders()) {
94 1
            $inlineEmail->addHeaders(...$email->getHeaders());
95
        }
96
97 4
        return $inlineEmail;
98
    }
99
100
    /**
101
     * Create the SimpleContent based on the SparkPost template data.
102
     *
103
     * @param array $template
104
     *
105
     * @return Content\SimpleContent
106
     */
107 5
    protected function getInlineContent(array $template): Content\SimpleContent
108
    {
109 5
        $htmlContent = null;
110 5
        if (array_key_exists(SparkPostCourier::HTML, $template)) {
111 5
            $htmlContent = new Content\SimpleContent\Message($template[SparkPostCourier::HTML]);
112
        }
113
114 5
        $textContent = null;
115 5
        if (array_key_exists(SparkPostCourier::TEXT, $template)) {
116 1
            $textContent = new Content\SimpleContent\Message($template[SparkPostCourier::TEXT]);
117
        }
118
119 5
        return new Content\SimpleContent($htmlContent, $textContent);
120
    }
121
122
    /**
123
     * Get the template content from SparkPost.
124
     *
125
     * @param Email $email
126
     *
127
     * @throws TransmissionException
128
     *
129
     * @return array
130
     */
131 6
    private function getTemplate(Email $email): array
132
    {
133
        try {
134 6
            $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

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