Passed
Push — master ( f617b1...a2b844 )
by Alain
03:39
created

AbstractMail::instantiateSections()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 18
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 18
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 9
nc 3
nop 2
crap 3
1
<?php
2
/**
3
 * BrightNucleus Chainmail Component.
4
 *
5
 * @package   BrightNucleus/Chainmail
6
 * @author    Alain Schlesser <[email protected]>
7
 * @license   MIT
8
 * @link      http://www.brightnucleus.com/
9
 * @copyright 2016 Alain Schlesser, Bright Nucleus
10
 */
11
12
namespace BrightNucleus\ChainMail\Mail;
13
14
use BrightNucleus\Chainmail\Exception\InvalidTemplateException;
15
use BrightNucleus\ChainMail\MailInterface;
16
use BrightNucleus\ChainMail\Support\Factory;
17
use BrightNucleus\ChainMail\TemplateInterface;
18
use BrightNucleus\Config\ConfigInterface;
19
use BrightNucleus\Config\Exception\FailedToProcessConfigException;
20
use BrightNucleus\View;
21
use BrightNucleus\View\Location\FilesystemLocation;
22
use BrightNucleus\View\ViewBuilder;
23
use Exception;
24
use RuntimeException;
25
26
/**
27
 * Abstract Class AbstractMail.
28
 *
29
 * @since   1.0.0
30
 *
31
 * @package BrightNucleus\ChainMail
32
 * @author  Alain Schlesser <[email protected]>
33
 */
34
abstract class AbstractMail implements MailInterface
35
{
36
37
    /**
38
     * Configuration Settings.
39
     *
40
     * @since 1.0.0
41
     *
42
     * @var ConfigInterface
43
     */
44
    protected $config;
45
46
    /**
47
     * Template that is used for the email.
48
     *
49
     * @since 1.0.0
50
     *
51
     * @var TemplateInterface
52
     */
53
    protected $template;
54
55
    /**
56
     * Content for the different sections.
57
     *
58
     * @since 1.0.0
59
     *
60
     * @var array
61
     */
62
    protected $sectionContent = [];
63
64
    /**
65
     * Format of the mail.
66
     *
67
     * @since 1.0.0
68
     *
69
     * @var string
70
     */
71
    protected $format;
72
73
    /**
74
     * ViewBuilder to create template and section views.
75
     *
76
     * @since 1.0.0
77
     *
78
     * @var ViewBuilder
79
     */
80
    protected $viewBuilder;
81
82
    /**
83
     * Instantiate an AbstractMail object.
84
     *
85
     * @since 1.0.0
86
     *
87
     * @param ConfigInterface $config The Config to use.
88
     *
89
     * @throws FailedToProcessConfigException If the Config could not be processed.
90
     */
91 16
    public function __construct(ConfigInterface $config)
92
    {
93 16
        $this->config = $config;
94 16
        $this->setFormat();
95
96 16
        $this->viewBuilder = new ViewBuilder($config
97 16
            ? $config->getSubConfig('ViewBuilder')
98 16
            : View::getDefaultConfig()
99
        );
100
101 16
        foreach ($this->config->getKey('view_root_locations') as $folder) {
102 16
            $this->viewBuilder->addLocation(
103 16
                new FilesystemLocation($folder)
104
            );
105
        }
106 16
    }
107
108
    /**
109
     * Get the template to use for the renderer.
110
     *
111
     * @since 1.0.0
112
     *
113
     * @return TemplateInterface Reference to the template that is used.
114
     * @throws RuntimeException
115
     */
116 16
    public function getTemplate()
117
    {
118
119 16
        if (! $this->template) {
120
            $this->setDefaultTemplate();
121
        }
122
123 16
        if (is_string($this->template)) {
124
            $this->template = $this->createTemplate($this->template);
125
        }
126
127 16
        return $this->template;
128
    }
129
130
    /**
131
     * Set the template to use for the renderer.
132
     *
133
     * @since 1.0.0
134
     *
135
     * @param string|TemplateInterface $template Template to use for the
136
     *                                           renderer.
137
     *
138
     * @throws InvalidTemplateException If the template class could not be instantiated.
139
     * @throws InvalidTemplateException If the template type is not recognized.
140
     */
141 16
    public function setTemplate($template)
142
    {
143
        try {
144 16
            if (is_string($template)) {
145 16
                $template = $this->createTemplate($template);
146
            }
147
        } catch (Exception $exception) {
148
            throw new InvalidTemplateException(
149
                'Could not instantiate the template class "%1$s". Reason: "%2$s".',
150
                $template,
151
                $exception->getMessage()
152
            );
153
        }
154
155 16
        if (! $template instanceof TemplateInterface) {
156
            throw new InvalidTemplateException(
157
                'Could not set the template, invalid type.',
158
                (array)$template
159
            );
160
        }
161 16
        $this->template = $template;
162 16
    }
163
164
    /**
165
     * Add a section to the Mail.
166
     *
167
     * @since 1.0.0
168
     *
169
     * @param string $type    Type of section to add.
170
     * @param string $content Content of the section.
171
     *
172
     * @throws RuntimeException
173
     */
174 8
    public function addSection($type, $content)
175
    {
176 8
        $this->sectionContent[$type] = $content;
177 8
    }
178
179
    /**
180
     * Render the Mail for a given context.
181
     *
182
     * @since 1.0.0
183
     *
184
     * @param array $context The context in which to render the email.
185
     *
186
     * @return string Rendered output of the email
187
     */
188 8
    public function render(array $context)
189
    {
190 8
        $template = $this->getTemplate();
191
192 8
        $context['template'] = $template;
193
194 8
        $this->instantiateSections($template->getUsedSections(), $context);
195
196 8
        $context['format'] = $this->getFormat();
197
198 8
        $context = $this->setContext($context);
199
200 8
        return $template->render($context);
201
    }
202
203
    /**
204
     * Instantiate the requested sections for a template.
205
     *
206
     * @since 1.0.0
207
     *
208
     * @param array $sections Sections to instantiate.
209
     * @param array $context  The context in which to instantiate the sections.
210
     */
211 8
    protected function instantiateSections(array $sections, array &$context)
212
    {
213 8
        $sectionFactory = new Factory($this->config, 'sections');
214
215 8
        foreach ($sections as $section) {
216
217 8
            $content = null;
218
219 8
            if (array_key_exists($section, $this->sectionContent)) {
220 8
                $content = $this->sectionContent[$section];
221
            }
222
223 8
            $context['sections'][$section] = $sectionFactory->create(
224
                $section,
225 8
                [$section, $content, $this->viewBuilder]
226
            );
227
        }
228 8
    }
229
230
    /**
231
     * Set the format of the mail.
232
     *
233
     * @since 1.0.0
234
     *
235
     * @return string Format of the Mail.
236
     */
237 8
    protected function getFormat()
238
    {
239 8
        return $this->format;
240
    }
241
242
    /**
243
     * Set the format of the mail.
244
     *
245
     * @since 1.0.0
246
     *
247
     * @return void
248
     */
249
    abstract protected function setFormat();
250
251
    /**
252
     * Set the template to the default template defined in the configuration.
253
     *
254
     * @since 1.0.0
255
     *
256
     * @throws RuntimeException
257
     */
258
    protected function setDefaultTemplate()
259
    {
260
        $defaultTemplate = $this->config->getKey('default_template');
261
        $this->setTemplate($defaultTemplate);
262
    }
263
264
    /**
265
     * Create an instance of a template.
266
     *
267
     * @since 1.0.0
268
     *
269
     * @param string $template Template to instantiate.
270
     *
271
     * @return TemplateInterface $template Newly created instance.
272
     * @throws RuntimeException
273
     */
274 16
    protected function createTemplate($template)
275
    {
276 16
        $templateFactory = new Factory($this->config, 'templates');
277
278 16
        return $templateFactory->create($template, [$template, $this->viewBuilder]);
279
    }
280
281
    /**
282
     * Set the context of the mail.
283
     *
284
     * @since 1.0.0
285
     *
286
     * @param array $context Context to set/modify.
287
     *
288
     * @return array Updated context.
289
     */
290
    abstract protected function setContext(array $context);
291
}
292