Completed
Push — master ( e6ae53...3ea501 )
by Sam
10:01 queued 45s
created

Email::sendPlain()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Control\Email;
4
5
use SilverStripe\Control\Director;
6
use SilverStripe\Control\HTTP;
7
use SilverStripe\Core\Convert;
8
use SilverStripe\Core\Injector\Injector;
9
use SilverStripe\ORM\FieldType\DBDatetime;
10
use SilverStripe\View\Requirements;
11
use SilverStripe\View\ViewableData;
12
use Swift_Message;
13
use Swift_MimePart;
14
15
/**
16
 * Class to support sending emails.
17
 */
18
class Email extends ViewableData
19
{
20
21
    /**
22
     * @var array
23
     * @config
24
     */
25
    private static $send_all_emails_to = array();
26
27
    /**
28
     * @var array
29
     * @config
30
     */
31
    private static $cc_all_emails_to = array();
32
33
    /**
34
     * @var array
35
     * @config
36
     */
37
    private static $bcc_all_emails_to = array();
38
39
    /**
40
     * @var array
41
     * @config
42
     */
43
    private static $send_all_emails_from = array();
44
45
    /**
46
     * This will be set in the config on a site-by-site basis
47
     *
48
     * @config
49
     * @var string The default administrator email address.
50
     */
51
    private static $admin_email = null;
52
53
    /**
54
     * @var Swift_Message
55
     */
56
    private $swiftMessage;
57
58
    /**
59
     * @var string The name of the HTML template to render the email with (without *.ss extension)
60
     */
61
    private $HTMLTemplate = self::class;
62
63
    /**
64
     * @var string The name of the plain text template to render the plain part of the email with
65
     */
66
    private $plainTemplate = '';
67
68
    /**
69
     * @var Swift_MimePart
70
     */
71
    private $plainPart;
72
73
    /**
74
     * @var array|ViewableData Additional data available in a template.
75
     * Used in the same way than {@link ViewableData->customize()}.
76
     */
77
    private $data = array();
78
79
    /**
80
     * @var array
81
     */
82
    private $failedRecipients = array();
83
84
    /**
85
     * Checks for RFC822-valid email format.
86
     *
87
     * @param string $address
88
     * @return boolean
89
     *
90
     * @copyright Cal Henderson <[email protected]>
91
     *    This code is licensed under a Creative Commons Attribution-ShareAlike 2.5 License
92
     *    http://creativecommons.org/licenses/by-sa/2.5/
93
     */
94
    public static function is_valid_address($address)
95
    {
96
        return \Swift_Validate::email($address);
97
    }
98
99
    /**
100
     * Encode an email-address to protect it from spambots.
101
     * At the moment only simple string substitutions,
102
     * which are not 100% safe from email harvesting.
103
     *
104
     * @param string $email Email-address
105
     * @param string $method Method for obfuscating/encoding the address
106
     *    - 'direction': Reverse the text and then use CSS to put the text direction back to normal
107
     *    - 'visible': Simple string substitution ('@' to '[at]', '.' to '[dot], '-' to [dash])
108
     *    - 'hex': Hexadecimal URL-Encoding - useful for mailto: links
109
     * @return string
110
     */
111
    public static function obfuscate($email, $method = 'visible')
112
    {
113
        switch ($method) {
114
            case 'direction' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
115
                Requirements::customCSS('span.codedirection { unicode-bidi: bidi-override; direction: rtl; }', 'codedirectionCSS');
116
117
                return '<span class="codedirection">' . strrev($email) . '</span>';
118
            case 'visible' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
119
                $obfuscated = array('@' => ' [at] ', '.' => ' [dot] ', '-' => ' [dash] ');
120
121
                return strtr($email, $obfuscated);
122
            case 'hex' :
0 ignored issues
show
Coding Style introduced by
There must be no space before the colon in a CASE statement

As per the PSR-2 coding standard, there must not be a space in front of the colon in case statements.

switch ($selector) {
    case "A": //right
        doSomething();
        break;
    case "B" : //wrong
        doSomethingElse();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
123
                $encoded = '';
124
                for ($x = 0; $x < strlen($email); $x++) {
125
                    $encoded .= '&#x' . bin2hex($email{$x}) . ';';
126
                }
127
128
                return $encoded;
129
            default:
130
                user_error('Email::obfuscate(): Unknown obfuscation method', E_USER_NOTICE);
131
132
                return $email;
133
        }
134
    }
135
136
    /**
137
     * Email constructor.
138
     * @param string|array|null $from
139
     * @param string|array|null $to
140
     * @param string|null $subject
141
     * @param string|null $body
142
     * @param string|array|null $cc
143
     * @param string|array|null $bcc
144
     * @param string|null $returnPath
145
     */
146
    public function __construct(
147
        $from = null,
148
        $to = null,
149
        $subject = null,
150
        $body = null,
151
        $cc = null,
152
        $bcc = null,
153
        $returnPath = null
154
    ) {
155
        if ($from) {
156
            $this->setFrom($from);
157
        }
158
        if ($to) {
159
            $this->setTo($to);
160
        }
161
        if ($subject) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $subject of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
162
            $this->setSubject($subject);
163
        }
164
        if ($body) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $body of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
165
            $this->setBody($body);
166
        }
167
        if ($cc) {
168
            $this->setCC($cc);
169
        }
170
        if ($bcc) {
171
            $this->setBCC($bcc);
172
        }
173
        if ($returnPath) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $returnPath of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
174
            $this->setReturnPath($returnPath);
175
        }
176
177
        parent::__construct();
178
    }
179
180
    /**
181
     * @return Swift_Message
182
     */
183
    public function getSwiftMessage()
184
    {
185
        if (!$this->swiftMessage) {
186
            $this->setSwiftMessage(new Swift_Message(null, null, 'text/html', 'utf-8'));
187
        }
188
189
        return $this->swiftMessage;
190
    }
191
192
    /**
193
     * @param Swift_Message $swiftMessage
194
     *
195
     * @return $this
196
     */
197
    public function setSwiftMessage($swiftMessage)
198
    {
199
        $swiftMessage->setDate(DBDatetime::now()->Format('U'));
200
        if (!$swiftMessage->getFrom() && ($defaultFrom = $this->config()->admin_email)) {
0 ignored issues
show
Documentation introduced by
The property admin_email does not exist on object<SilverStripe\Core\Config\Config_ForClass>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
201
            $swiftMessage->setFrom($defaultFrom);
202
        }
203
        $this->swiftMessage = $swiftMessage;
204
205
        return $this;
206
    }
207
208
    /**
209
     * @return string[]
210
     */
211
    public function getFrom()
212
    {
213
        return $this->getSwiftMessage()->getFrom();
214
    }
215
216
    /**
217
     * @param string|array $address
218
     * @param string|null $name
219
     * @return $this
220
     */
221
    public function setFrom($address, $name = null)
222
    {
223
        $this->getSwiftMessage()->setFrom($address, $name);
224
225
        return $this;
226
    }
227
228
    /**
229
     * @param string|array $address
230
     * @param string|null $name
231
     * @return $this
232
     */
233
    public function addFrom($address, $name = null)
234
    {
235
        $this->getSwiftMessage()->addFrom($address, $name);
0 ignored issues
show
Bug introduced by
It seems like $address defined by parameter $address on line 233 can also be of type array; however, Swift_Mime_SimpleMessage::addFrom() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
236
237
        return $this;
238
    }
239
240
    /**
241
     * @return array
242
     */
243
    public function getSender()
244
    {
245
        return $this->getSwiftMessage()->getSender();
246
    }
247
248
    /**
249
     * @param string $address
250
     * @param string|null $name
251
     * @return $this
252
     */
253
    public function setSender($address, $name = null)
254
    {
255
        $this->getSwiftMessage()->setSender($address, $name);
256
257
        return $this;
258
    }
259
260
    /**
261
     * @return string
262
     */
263
    public function getReturnPath()
264
    {
265
        return $this->getSwiftMessage()->getReturnPath();
266
    }
267
268
    /**
269
     * The bounce handler address
270
     *
271
     * @param string $address Email address where bounce notifications should be sent
272
     * @return $this
273
     */
274
    public function setReturnPath($address)
275
    {
276
        $this->getSwiftMessage()->setReturnPath($address);
277
        return $this;
278
    }
279
280
    /**
281
     * @return array
282
     */
283
    public function getTo()
284
    {
285
        return $this->getSwiftMessage()->getTo();
286
    }
287
288
    /**
289
     * Set recipient(s) of the email
290
     *
291
     * To send to many, pass an array:
292
     * array('[email protected]' => 'My Name', '[email protected]');
293
     *
294
     * @param string|array $address The message recipient(s) - if sending to multiple, use an array of address => name
295
     * @param string|null $name The name of the recipient (if one)
296
     * @return $this
297
     */
298
    public function setTo($address, $name = null)
299
    {
300
        $this->getSwiftMessage()->setTo($address, $name);
301
302
        return $this;
303
    }
304
305
    /**
306
     * @param string|array $address
307
     * @param string|null $name
308
     * @return $this
309
     */
310
    public function addTo($address, $name = null)
311
    {
312
        $this->getSwiftMessage()->addTo($address, $name);
0 ignored issues
show
Bug introduced by
It seems like $address defined by parameter $address on line 310 can also be of type array; however, Swift_Mime_SimpleMessage::addTo() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
313
314
        return $this;
315
    }
316
317
    /**
318
     * @return array
319
     */
320
    public function getCC()
321
    {
322
        return $this->getSwiftMessage()->getCc();
323
    }
324
325
    /**
326
     * @param string|array $address
327
     * @param string|null $name
328
     * @return $this
329
     */
330
    public function setCC($address, $name = null)
331
    {
332
        $this->getSwiftMessage()->setCc($address, $name);
333
334
        return $this;
335
    }
336
337
    /**
338
     * @param string|array $address
339
     * @param string|null $name
340
     * @return $this
341
     */
342
    public function addCC($address, $name = null)
343
    {
344
        $this->getSwiftMessage()->addCc($address, $name);
0 ignored issues
show
Bug introduced by
It seems like $address defined by parameter $address on line 342 can also be of type array; however, Swift_Mime_SimpleMessage::addCc() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
345
346
        return $this;
347
    }
348
349
    /**
350
     * @return array
351
     */
352
    public function getBCC()
353
    {
354
        return $this->getSwiftMessage()->getBcc();
355
    }
356
357
    /**
358
     * @param string|array $address
359
     * @param string|null $name
360
     * @return $this
361
     */
362
    public function setBCC($address, $name = null)
363
    {
364
        $this->getSwiftMessage()->setBcc($address, $name);
365
366
        return $this;
367
    }
368
369
    /**
370
     * @param string|array $address
371
     * @param string|null $name
372
     * @return $this
373
     */
374
    public function addBCC($address, $name = null)
375
    {
376
        $this->getSwiftMessage()->addBcc($address, $name);
0 ignored issues
show
Bug introduced by
It seems like $address defined by parameter $address on line 374 can also be of type array; however, Swift_Mime_SimpleMessage::addBcc() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
377
378
        return $this;
379
    }
380
381
    public function getReplyTo()
382
    {
383
        return $this->getSwiftMessage()->getReplyTo();
384
    }
385
386
    /**
387
     * @param string|array $address
388
     * @param string|null $name
389
     * @return $this
390
     */
391
    public function setReplyTo($address, $name = null)
392
    {
393
        $this->getSwiftMessage()->setReplyTo($address, $name);
394
395
        return $this;
396
    }
397
398
    /**
399
     * @param string|array $address
400
     * @param string|null $name
401
     * @return $this
402
     */
403
    public function addReplyTo($address, $name = null)
404
    {
405
        $this->getSwiftMessage()->addReplyTo($address, $name);
0 ignored issues
show
Bug introduced by
It seems like $address defined by parameter $address on line 403 can also be of type array; however, Swift_Mime_SimpleMessage::addReplyTo() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
406
407
        return $this;
408
    }
409
410
    /**
411
     * @return string
412
     */
413
    public function getSubject()
414
    {
415
        return $this->getSwiftMessage()->getSubject();
416
    }
417
418
    /**
419
     * @param string $subject The Subject line for the email
420
     * @return $this
421
     */
422
    public function setSubject($subject)
423
    {
424
        $this->getSwiftMessage()->setSubject($subject);
425
426
        return $this;
427
    }
428
429
    /**
430
     * @return int
431
     */
432
    public function getPriority()
433
    {
434
        return $this->getSwiftMessage()->getPriority();
435
    }
436
437
    /**
438
     * @param int $priority
439
     * @return $this
440
     */
441
    public function setPriority($priority)
442
    {
443
        $this->getSwiftMessage()->setPriority($priority);
444
445
        return $this;
446
    }
447
448
    /**
449
     * @param string $path Path to file
450
     * @param string $alias An override for the name of the file
451
     * @param string $mime The mime type for the attachment
452
     * @return $this
453
     */
454
    public function addAttachment($path, $alias = null, $mime = null)
455
    {
456
        $attachment = \Swift_Attachment::fromPath($path);
457
        if ($alias) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $alias of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
458
            $attachment->setFilename($alias);
459
        }
460
        if ($mime) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $mime of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
461
            $attachment->setContentType($mime);
462
        }
463
        $this->getSwiftMessage()->attach($attachment);
464
465
        return $this;
466
    }
467
468
    /**
469
     * @param string $data
470
     * @param string $name
471
     * @param string $mime
472
     * @return $this
473
     */
474
    public function addAttachmentFromData($data, $name, $mime = null)
475
    {
476
        $attachment = new \Swift_Attachment($data, $name);
477
        if ($mime) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $mime of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
478
            $attachment->setContentType($mime);
479
        }
480
        $this->getSwiftMessage()->attach($attachment);
481
482
        return $this;
483
    }
484
485
    /**
486
     * @return array|ViewableData The template data
487
     */
488
    public function getData()
489
    {
490
        return $this->data;
491
    }
492
493
    /**
494
     * @param array|ViewableData $data The template data to set
495
     * @return $this
496
     */
497
    public function setData($data)
498
    {
499
        $this->data = $data;
500
501
        return $this;
502
    }
503
504
    /**
505
     * @param string|array $name The data name to add or array to names => value
506
     * @param string|null $value The value of the data to add
507
     * @return $this
508
     */
509
    public function addData($name, $value = null)
510
    {
511
        if (is_array($name)) {
512
            $this->data = array_merge($this->data, $name);
513
        } elseif (is_array($this->data)) {
514
            $this->data[$name] = $value;
515
        } else {
516
            $this->data->$name = $value;
517
        }
518
519
        return $this;
520
    }
521
522
    /**
523
     * Remove a datum from the message
524
     *
525
     * @param string $name
526
     * @return $this
527
     */
528
    public function removeData($name)
529
    {
530
        if (is_array($this->data)) {
531
            unset($this->data[$name]);
532
        } else {
533
            $this->data->$name = null;
534
        }
535
536
        return $this;
537
    }
538
539
    /**
540
     * @return string
541
     */
542
    public function getBody()
543
    {
544
        return $this->getSwiftMessage()->getBody();
545
    }
546
547
    /**
548
     * @param string $body The email body
549
     * @return $this
550
     */
551
    public function setBody($body)
552
    {
553
        $body = HTTP::absoluteURLs($body);
554
        $this->getSwiftMessage()->setBody($body);
555
556
        return $this;
557
    }
558
559
    /**
560
     * @return string The base URL for the email
561
     */
562
    public function BaseURL()
563
    {
564
        return Director::absoluteBaseURL();
565
    }
566
567
    /**
568
     * Debugging help
569
     *
570
     * @return string Debug info
571
     */
572
    public function debug()
573
    {
574
        $this->render();
575
576
        return "<h2>Email template {$this->class}:</h2>\n" . '<pre>' . $this->getSwiftMessage()->toString() . '</pre>';
577
    }
578
579
    /**
580
     * @return string
581
     */
582
    public function getHTMLTemplate()
583
    {
584
        return $this->HTMLTemplate;
585
    }
586
587
    /**
588
     * Set the template to render the email with
589
     *
590
     * @param string $template
591
     * @return $this
592
     */
593
    public function setHTMLTemplate($template)
594
    {
595
        if (substr($template, -3) == '.ss') {
596
            $template = substr($template, 0, -3);
597
        }
598
        $this->HTMLTemplate = $template;
599
600
        return $this;
601
    }
602
603
    /**
604
     * Get the template to render the plain part with
605
     *
606
     * @return string
607
     */
608
    public function getPlainTemplate()
609
    {
610
        return $this->plainTemplate;
611
    }
612
613
    /**
614
     * Set the template to render the plain part with
615
     *
616
     * @param string $template
617
     * @return $this
618
     */
619
    public function setPlainTemplate($template)
620
    {
621
        if (substr($template, -3) == '.ss') {
622
            $template = substr($template, 0, -3);
623
        }
624
        $this->plainTemplate = $template;
625
626
        return $this;
627
    }
628
629
    /**
630
     * @param array $recipients
631
     * @return $this
632
     */
633
    public function setFailedRecipients($recipients)
634
    {
635
        $this->failedRecipients = $recipients;
636
637
        return $this;
638
    }
639
640
    /**
641
     * @return array
642
     */
643
    public function getFailedRecipients()
644
    {
645
        return $this->failedRecipients;
646
    }
647
648
    /**
649
     * Used by {@link SSViewer} templates to detect if we're rendering an email template rather than a page template
650
     *
651
     * @return bool
652
     */
653
    public function IsEmail()
654
    {
655
        return true;
656
    }
657
658
    /**
659
     * Send the message to the recipients
660
     *
661
     * @return bool true if successful or array of failed recipients
662
     */
663
    public function send()
664
    {
665
        if (!$this->getBody()) {
666
            $this->render();
667
        }
668
        if (!$this->hasPlainPart()) {
669
            $this->generatePlainPartFromBody();
670
        }
671
        return Injector::inst()->get(Mailer::class)->send($this);
672
    }
673
674
    /**
675
     * @return array|bool
676
     */
677
    public function sendPlain()
678
    {
679
        if (!$this->hasPlainPart()) {
680
            $this->render(true);
681
        }
682
        return Injector::inst()->get(Mailer::class)->send($this);
683
    }
684
685
    /**
686
     * Render the email
687
     * @param bool $plainOnly Only render the message as plain text
688
     * @return $this
689
     */
690
    public function render($plainOnly = false)
691
    {
692
        if ($existingPlainPart = $this->findPlainPart()) {
693
            $this->getSwiftMessage()->detach($existingPlainPart);
694
        }
695
        unset($existingPlainPart);
696
        if (!$this->getHTMLTemplate() && !$this->getPlainTemplate()) {
697
            return $this;
698
        }
699
        $HTMLPart = '';
700
        $plainPart = '';
701
702
        if ($this->getHTMLTemplate()) {
703
            $HTMLPart = $this->renderWith($this->getHTMLTemplate(), $this->getData());
0 ignored issues
show
Bug introduced by
It seems like $this->getData() targeting SilverStripe\Control\Email\Email::getData() can also be of type object<SilverStripe\View\ViewableData>; however, SilverStripe\View\ViewableData::renderWith() does only seem to accept array|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
704
        }
705
706
        if ($this->getPlainTemplate()) {
707
            $plainPart =  $this->renderWith($this->getPlainTemplate(), $this->getData());
0 ignored issues
show
Bug introduced by
It seems like $this->getData() targeting SilverStripe\Control\Email\Email::getData() can also be of type object<SilverStripe\View\ViewableData>; however, SilverStripe\View\ViewableData::renderWith() does only seem to accept array|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
708
        } elseif ($HTMLPart) {
709
            $plainPart = Convert::xml2raw($HTMLPart);
710
        }
711
712
        if ($HTMLPart && !$plainOnly) {
713
            $this->setBody($HTMLPart);
0 ignored issues
show
Bug introduced by
It seems like $HTMLPart defined by $this->renderWith($this-...te(), $this->getData()) on line 703 can also be of type object<SilverStripe\ORM\FieldType\DBHTMLText>; however, SilverStripe\Control\Email\Email::setBody() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
714
            $this->getSwiftMessage()->setContentType('text/html');
715
            $this->getSwiftMessage()->setCharset('utf-8');
716
            if ($plainPart) {
717
                $this->getSwiftMessage()->addPart($plainPart, 'text/plain', 'utf-8');
718
            }
719
        } elseif ($plainPart || $plainOnly) {
720
            if ($plainPart) {
721
                $this->setBody($plainPart);
722
            }
723
            $this->getSwiftMessage()->setContentType('text/plain');
724
            $this->getSwiftMessage()->setCharset('utf-8');
725
        }
726
727
        return $this;
728
    }
729
730
    /**
731
     * @return Swift_MimePart|false
732
     */
733
    public function findPlainPart()
734
    {
735
        foreach ($this->getSwiftMessage()->getChildren() as $child) {
736
            if ($child instanceof Swift_MimePart && $child->getContentType() == 'text/plain') {
737
                return $child;
738
            }
739
        }
740
        return false;
741
    }
742
743
    /**
744
     * @return bool
745
     */
746
    public function hasPlainPart()
747
    {
748
        if ($this->getSwiftMessage()->getContentType() == 'text/plain') {
749
            return true;
750
        }
751
        return (bool) $this->findPlainPart();
752
    }
753
754
    /**
755
     * Automatically adds a plain part to the email generated from the current Body
756
     *
757
     * @return $this
758
     */
759
    public function generatePlainPartFromBody()
760
    {
761
        $this->getSwiftMessage()->addPart(
762
            Convert::xml2raw($this->getBody()),
0 ignored issues
show
Bug introduced by
It seems like \SilverStripe\Core\Conve...l2raw($this->getBody()) targeting SilverStripe\Core\Convert::xml2raw() can also be of type array; however, Swift_Message::addPart() does only seem to accept string|object<Swift_OutputByteStream>, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
763
            'text/plain',
764
            'utf-8'
765
        );
766
767
        return $this;
768
    }
769
}
770