Completed
Pull Request — master (#33)
by
unknown
08:05 queued 05:13
created

Composer::compose()   F

Complexity

Conditions 19
Paths 288

Size

Total Lines 124
Code Lines 85

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 53
CRAP Score 53.9552

Importance

Changes 0
Metric Value
dl 0
loc 124
ccs 53
cts 98
cp 0.5407
rs 3.6524
c 0
b 0
f 0
cc 19
eloc 85
nc 288
nop 3
crap 53.9552

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * MtMail - e-mail module for Zend Framework 2
4
 *
5
 * @link      http://github.com/mtymek/MtMail
6
 * @copyright Copyright (c) 2013-2014 Mateusz Tymek
7
 * @license   BSD 2-Clause
8
 */
9
10
namespace MtMail\Service;
11
12
use MtMail\Event\ComposerEvent;
13
use MtMail\Exception\InvalidArgumentException;
14
use MtMail\Renderer\RendererInterface;
15
use MtMail\Template\HtmlTemplateInterface;
16
use MtMail\Template\TemplateInterface;
17
use MtMail\Template\TextTemplateInterface;
18
use Zend\EventManager\EventManager;
19
use Zend\EventManager\EventManagerAwareInterface;
20
use Zend\EventManager\EventManagerInterface;
21
use Zend\Mail\Message;
22
use Zend\View\Model\ModelInterface;
23
use Zend\Mime\Message as MimeMessage;
24
use Zend\Mime\Part as MimePart;
25
use Zend\View\Model\ViewModel;
26
27
class Composer implements EventManagerAwareInterface
28
{
29
    /**
30
     * @var RendererInterface
31
     */
32
    protected $renderer;
33
34
    /**
35
     * @var EventManagerInterface
36
     */
37
    protected $eventManager;
38
39
    /**
40
     * Class constructor
41
     *
42
     * @param RendererInterface $renderer
43
     */
44 10
    public function __construct(RendererInterface $renderer)
45
    {
46 10
        $this->renderer = $renderer;
47 10
    }
48
49
    /**
50
     * Inject an EventManager instance
51
     *
52
     * @param  EventManagerInterface $eventManager
53
     * @return self
54
     */
55 3
    public function setEventManager(EventManagerInterface $eventManager)
56
    {
57 3
        $this->eventManager = $eventManager;
58
59 3
        return $this;
60
    }
61
62
    /**
63
     * Retrieve the event manager
64
     *
65
     * Lazy-loads an EventManager instance if none registered.
66
     *
67
     * @return EventManagerInterface
68
     */
69 8
    public function getEventManager()
70
    {
71 8
        if (null === $this->eventManager) {
72 6
            $this->eventManager = new EventManager();
73 6
        }
74
75 8
        return $this->eventManager;
76
    }
77
78
    /**
79
     * @param  \MtMail\Renderer\RendererInterface $renderer
80
     * @return self
81
     */
82 1
    public function setRenderer($renderer)
83
    {
84 1
        $this->renderer = $renderer;
85
86 1
        return $this;
87
    }
88
89
    /**
90
     * @return \MtMail\Renderer\RendererInterface
91
     */
92 3
    public function getRenderer()
93
    {
94 3
        return $this->renderer;
95
    }
96
97
    /**
98
     * Create and return event used by compose and send methods
99
     *
100
     * @return ComposerEvent
101
     */
102 5
    protected function getEvent()
103
    {
104 5
        $event = new ComposerEvent();
105 5
        $event->setTarget($this);
106
107 5
        return $event;
108
    }
109
110
    /**
111
     * Build e-mail message
112
     *
113
     * @param  TemplateInterface        $template
114
     * @param  array                    $headers
115
     * @param  ModelInterface           $viewModel
116
     * @throws InvalidArgumentException if template is not string nor TemplateInterface
117
     * @return Message
118
     */
119 5
    public function compose(array $headers, TemplateInterface $template, ModelInterface $viewModel = null)
120
    {
121 5
        if (null == $viewModel) {
122
            $viewModel = new ViewModel();
123
        }
124
125 5
        $event = $this->getEvent();
126 5
        $event->setTemplate($template);
127 5
        $em = $this->getEventManager();
128
129
        // 1. Trigger pre event
130 5
        $event->setName(ComposerEvent::EVENT_COMPOSE_PRE);
131 5
        $em->triggerEvent($event);
132
133
        // 2. inject headers
134 5
        $event->setName(ComposerEvent::EVENT_HEADERS_PRE);
135 5
        $em->triggerEvent($event);
136 5
        foreach ($headers as $name => $value) {
137
            switch ($name) {
138 1
                case "to":
139
                    $value = explode(",", $value);
140
                    if (!is_array($value)) {
141
                        $tmp = $value;
142
                        $value = [];
143
                        $value[] = $tmp;
144
                    }
145
                    foreach ($value as $item) {
146
                        $event->getMessage()->addTo($item);
147
                    }
148
                    break;
149 1
                case "from":
150
                    $value = explode(",", $value);
151
                    if (!is_array($value)) {
152
                        $tmp = $value;
153
                        $value = [];
154
                        $value[] = $tmp;
155
                    }
156
                    foreach ($value as $item) {
157
                        $event->getMessage()->addFrom($item);
158
                    }
159
                    break;
160 1
                case "bcc":
161
                    $value = explode(",", $value);
162
                    if (!is_array($value)) {
163
                        $tmp = $value;
164
                        $value = [];
165
                        $value[] = $tmp;
166
                    }
167
                    foreach ($value as $item) {
168
                        $event->getMessage()->addBcc($item);
169
                    }
170
                    break;
171 1
                case "cc":
172
                    $value = explode(",", $value);
173
                    if (!is_array($value)) {
174
                        $tmp = $value;
175
                        $value = [];
176
                        $value[] = $tmp;
177
                    }
178
                    foreach ($value as $item) {
179
                        $event->getMessage()->addCc($item);
180
                    }
181
                    break;
182 1
                default:
183 1
                    $event->getMessage()->getHeaders()->addHeaderLine($name, $value);
184 1
            }
185 5
        }
186 5
        $event->setName(ComposerEvent::EVENT_HEADERS_POST);
187 5
        $em->triggerEvent($event);
188
189
        // prepare placeholder for message body
190 5
        $body = new MimeMessage();
191
192
        // 3. Render plain text template
193 5
        if ($template instanceof TextTemplateInterface) {
194 2
            $textViewModel = clone $viewModel;
195 2
            $textViewModel->setTemplate($template->getTextTemplateName());
196 2
            $event->setViewModel($textViewModel);
197
198 2
            $event->setName(ComposerEvent::EVENT_TEXT_BODY_PRE);
199 2
            $em->triggerEvent($event);
200
201 2
            $text = new MimePart($this->renderer->render($event->getViewModel()));
202 2
            $text->type = 'text/plain';
203 2
            $text->charset = $event->getMessage()->getHeaders()->getEncoding();
204 2
            $body->addPart($text);
205
206 2
            $event->setName(ComposerEvent::EVENT_TEXT_BODY_POST);
207 2
            $em->triggerEvent($event);
208 2
        }
209
210
        // 4. Render HTML template
211 5
        if ($template instanceof HtmlTemplateInterface) {
212 3
            $htmlViewModel = clone $viewModel;
213 3
            $htmlViewModel->setTemplate($template->getHtmlTemplateName());
214 3
            $event->setViewModel($htmlViewModel);
215
216 3
            $event->setName(ComposerEvent::EVENT_HTML_BODY_PRE);
217 3
            $em->triggerEvent($event);
218
219 3
            $html = new MimePart($this->renderer->render($event->getViewModel()));
220 3
            $html->type = 'text/html';
221 3
            $html->charset = $event->getMessage()->getHeaders()->getEncoding();
222 3
            $body->addPart($html);
223
224 3
            $event->setName(ComposerEvent::EVENT_HTML_BODY_POST);
225 3
            $em->triggerEvent($event);
226 3
        }
227
228
        // 5. inject body into message
229 5
        $event->setBody($body);
230 5
        $event->getMessage()->setBody($body);
231
232
        // 6. set multipart/alternative when both versions are available
233 5
        if ($template instanceof TextTemplateInterface && $template instanceof HtmlTemplateInterface) {
234
            $event->getMessage()->getHeaders()->get('content-type')->setType('multipart/alternative')
235
                ->addParameter('boundary', $body->getMime()->boundary());
236
        }
237
238 5
        $event->setName(ComposerEvent::EVENT_COMPOSE_POST);
239 5
        $em->triggerEvent($event);
240
241 5
        return $event->getMessage();
242
    }
243
244
    public function attachments(Message $message, array $attachments)
245
    {
246
        if (sizeof($attachments) > 0) {
247
            $type = $message->getHeaders()->get('content-type')->getType();
248
            if ($type != 'multipart/related') {
249
                $parts = $message->getBody()->getParts();
250
                $htmlPart = null;
251
                $textPart = null;
252
253
                // locate HTML body
254
                foreach ($parts as $part) {
255
                    foreach ($part->getHeadersArray() as $header) {
256
                        if ($header[0] == 'Content-Type' && strpos($header[1], 'text/html') === 0) {
257
                            $htmlPart = $part;
258
                        } elseif ($header[0] == 'Content-Type' && strpos($header[1], 'text/plain') === 0) {
259
                            $textPart = $part;
260
                        }
261
                    }
262
                }
263
264
                if (!empty($textPart) && !empty($htmlPart)) {
265
                    $content = new MimeMessage();
266
                    $content->addPart($textPart);
267
                    $content->addPart($htmlPart);
268
                    $contentPart = new MimePart($content->generateMessage());
269
                    $contentPart->type = "multipart/alternative;\n boundary=\"" .
270
                        $content->getMime()->boundary() . '"';
271
                    $message->getBody()->setParts([$contentPart]);
272
                } else {
273
                    if (empty($textPart)) {
274
                        $message->getBody()->setParts([$htmlPart]);
275
                    } else {
276
                        $message->getBody()->setParts([$textPart]);
277
                    }
278
                }
279
            }
280
281
            foreach ($attachments as $attachment) {
282
                if (is_readable($attachment)) {
283
                    $pathParts          = pathinfo($attachment);
284
                    $at = new MimePart(file_get_contents($attachment));
285
                    $at->type           = $this->getType($pathParts['extension']);
286
                    $at->filename       = $pathParts['filename'];
287
                    $at->disposition    = Mime::DISPOSITION_ATTACHMENT;
288
289
                    $message->getBody()->addPart($at);
290
                }
291
            }
292
293
            // force multipart/alternative content type
294
            if ($type != 'multipart/related') {
295
                $message->getHeaders()->get('content-type')->setType('multipart/related')
296
                    ->addParameter('boundary', $event->getBody()->getMime()->boundary());
0 ignored issues
show
Bug introduced by
The variable $event does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
297
            }
298
        }
299
        return $message;
300
    }
301
302
    private function getType($ext)
303
    {
304
        switch (strtolower($ext)) {
305
            case "pdf":
306
                $type = 'application/pdf';
307
                break;
308
            case "doc":
309
                $type = "application/msword";
310
                break;
311
            case "docx":
312
                $type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
313
                break;
314
            case "odt":
315
                $type =  "application/vnd.oasis.opendocument.text";
316
                break;
317
            case "gzip":
318
                $type =  'application/gzip';
319
                break;
320
            case "txt":
321
                $type= 'application/text';
322
                break;
323
            case "zip":
324
                $type = 'application/zip';
325
                break;
326
            default:
327
                $type = Mime::TYPE_OCTETSTREAM;
328
        }
329
        return $type;
330
    }
331
}
332