Completed
Pull Request — master (#489)
by Richard
10:39
created

XoopsMailer::send()   F

Complexity

Conditions 25
Paths 3124

Size

Total Lines 103
Code Lines 58

Duplication

Lines 22
Ratio 21.36 %

Code Coverage

Tests 0
CRAP Score 650
Metric Value
dl 22
loc 103
ccs 0
cts 55
cp 0
rs 2
cc 25
eloc 58
nc 3124
nop 1
crap 650

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
 You may not change or alter any portion of this comment or credits
4
 of supporting developers from this source code or any supporting source code
5
 which is considered copyrighted (c) material of the original comment or credit authors.
6
7
 This program is distributed in the hope that it will be useful,
8
 but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10
*/
11
12
use Xoops\Core\Kernel\Handlers\XoopsGroup;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, XoopsGroup.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use Xoops\Core\Kernel\Handlers\XoopsUser;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, XoopsUser.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
14
15
/**
16
 * XOOPS mailer
17
 *
18
 * @copyright       XOOPS Project (http://xoops.org)
19
 * @license         GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
20
 * @package         class
21
 * @since           2.0.0
22
 * @author          Kazumi Ono (AKA onokazu) http://www.myweb.ne.jp/, http://jp.xoops.org/
23
 * @version         $Id$
24
 * @deprecated      use {@link XoopsMultiMailer} instead.
25
 */
26
27
/**
28
 * Class for sending mail.
29
 *
30
 * Changed to use the facilities of  {@link XoopsMultiMailer}
31
 *
32
 * @package class
33
 * @subpackage mail
34
 * @author Kazumi Ono <[email protected]>
35
 */
36
class XoopsMailer
37
{
38
    /**
39
     * reference to a {@link XoopsMultiMailer}
40
     *
41
     * @var XoopsMultiMailer
42
     * @access protected
43
     * @since 21.02.2003 14:14:13
44
     */
45
    protected $multimailer;
46
47
    /**
48
     * sender email address
49
     *
50
     * @var string
51
     */
52
    private $fromEmail;
53
54
    /**
55
     * sender name
56
     *
57
     * @var string
58
     */
59
    private $fromName;
60
61
    /**
62
     * sender UID
63
     *
64
     * @var XoopsUser
65
     */
66
    private $fromUser;
67
68
    /**
69
     * array of user class objects
70
     *
71
     * @var array
72
     */
73
    private $toUsers;
74
75
    /**
76
     * array of email addresses
77
     *
78
     * @var array
79
     */
80
    private $toEmails;
81
82
    // private
83
    /**
84
     * custom headers
85
     *
86
     * @var array
87
     */
88
    private $headers;
89
90
    /**
91
     * subjet of mail
92
     *
93
     * @var string
94
     */
95
    private $subject;
96
97
    /**
98
     * body of mail
99
     *
100
     * @var string
101
     */
102
    private $body;
103
104
    /**
105
     * error messages
106
     *
107
     * @var array
108
     */
109
    private $errors;
110
111
    /**
112
     * messages upon success
113
     *
114
     * @var array
115
     */
116
    private $success;
117
118
    /**
119
     * @var bool
120
     */
121
    private $isMail;
122
123
    /**
124
     * @var bool
125
     */
126
    private $isPM;
127
128
    /**
129
     * @var array
130
     */
131
    private $assignedTags;
132
133
    /**
134
     * @var string
135
     */
136
    private $template;
137
138
    /**
139
     * @var string
140
     */
141
    private $templatedir;
142
143
    /**
144
     * @var string
145
     */
146
    protected $charSet = 'iso-8859-1';
147
148
    /**
149
     * @var string
150
     */
151
    protected $encoding = '8bit';
152
153
    /**
154
     * @var string
155
     */
156
    private $priority;
157
158
    /**
159
     * @var string
160
     */
161
    private $LE;
162
163
    /**
164
     * Constructor
165
     *
166
     * @return XoopsMailer
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
167
     */
168 27
    public function __construct()
169
    {
170 27
        $this->multimailer = new XoopsMultiMailer();
171 27
        $this->reset();
172 27
    }
173
174
    /**
175
     * reset all properties to default
176
     *
177
     * @param bool $value
178
     * @return void
179
     */
180 1
    public function setHTML($value = true)
181
    {
182 1
        $this->multimailer->isHTML($value);
183 1
    }
184
185
    /**
186
     * reset all properties to default
187
     *
188
     * @return void
189
     */
190 27
    public function reset()
191
    {
192 27
        $this->fromEmail = "";
193 27
        $this->fromName = "";
194 27
        $this->fromUser = null; // RMV-NOTIFY
195 27
        $this->priority = '';
196 27
        $this->toUsers = array();
197 27
        $this->toEmails = array();
198 27
        $this->headers = array();
199 27
        $this->subject = "";
200 27
        $this->body = "";
201 27
        $this->errors = array();
202 27
        $this->success = array();
203 27
        $this->isMail = false;
204 27
        $this->isPM = false;
205 27
        $this->assignedTags = array();
206 27
        $this->template = "";
207 27
        $this->templatedir = "";
208
        // Change below to \r\n if you have problem sending mail
209 27
        $this->LE = "\n";
210 27
    }
211
212
    /**
213
     * @param string $value
214
     * @return void
215
     */
216 1
    public function setTemplateDir($value = null)
217
    {
218 1
        $xoops = Xoops::getInstance();
219 1
        if ($value === null && $xoops->isModule()) {
220
            $value = $xoops->module->getVar('dirname', 'n');
221
        } else {
222 1
            $value = str_replace(DIRECTORY_SEPARATOR, "/", $value);
223
        }
224 1
        $this->templatedir = $value;
225 1
    }
226
227
    /**
228
     * @return bool|string
229
     */
230
    private function getTemplatePath()
231
    {
232
        $xoops = Xoops::getInstance();
233
        if (!$path = $this->templatedir) {
234
            $path = \XoopsBaseConfig::get('root-path') . "/locale/";
235
        } elseif (false === strpos($path, '/')) {
236
            $path = \XoopsBaseConfig::get('root-path') . "/modules/" . $path . "/locale/";
237
        } elseif (substr($path, -1, 1) !== "/") {
238
            $path .= "/";
239
        }
240
        if (XoopsLoad::fileExists($path . $xoops->getConfig('locale') . "/templates/" . $this->template)) {
241
            return $path . $xoops->getConfig('locale') . "/templates/" . $this->template;
242
        } elseif (XoopsLoad::fileExists($path . "en_US/templates/" . $this->template)) {
243
            return $path . "en_US/templates/" . $this->template;
244
        } elseif (XoopsLoad::fileExists($path . $this->template)) {
245
            return $path . $this->template;
246
        } else {
247
            return false;
248
        }
249
    }
250
251
    /**
252
     * @param string $value
253
     * @return void
254
     */
255 1
    public function setTemplate($value)
256
    {
257 1
        $this->template = $value;
258 1
    }
259
260
    /**
261
     * @param string $value
262
     * @return void
263
     */
264 1
    public function setFromEmail($value)
265
    {
266 1
        $this->fromEmail = trim($value);
267 1
    }
268
269
    /**
270
     * @param string $value
271
     * @return void
272
     */
273 1
    public function setFromName($value)
274
    {
275 1
        $this->fromName = trim($value);
276 1
    }
277
278
    /**
279
     * @param XoopsUser $user
280
     * @return void
281
     */
282 1
    public function setFromUser(XoopsUser $user)
283
    {
284 1
        $this->fromUser = $user;
285 1
    }
286
287
    /**
288
     * @param string $value
289
     * @return void
290
     */
291 1
    public function setPriority($value)
292
    {
293 1
        $this->priority = trim($value);
294 1
    }
295
296
    /**
297
     * @param string $value
298
     * @return void
299
     */
300 1
    public function setSubject($value)
301
    {
302 1
        $this->subject = trim($value);
303 1
    }
304
305
    /**
306
     * @param string $value
307
     * @return void
308
     */
309 1
    public function setBody($value)
310
    {
311 1
        $this->body = trim($value);
312 1
    }
313
314
    /**
315
     * @return void
316
     */
317 1
    public function useMail()
318
    {
319 1
        $this->isMail = true;
320 1
    }
321
322
    /**
323
     * @return void
324
     */
325 1
    public function usePM()
326
    {
327 1
        $this->isPM = true;
328 1
    }
329
330
    /**
331
     * @param bool $debug
332
     * @return bool
333
     */
334
    public function send($debug = false)
335
    {
336
        $xoops = Xoops::getInstance();
337
        if ($this->body == "" && $this->template == "") {
338
            if ($debug) {
339
                $this->errors[] = XoopsLocale::E_MESSAGE_BODY_NOT_SET;
340
            }
341
            return false;
342
        } elseif ($this->template != "") {
343
            $path = $this->getTemplatePath();
344
            if (!($fd = @fopen($path, 'r'))) {
345
                if ($debug) {
346
                    $this->errors[] = XoopsLocale::E_TEMPLATE_FILE_NOT_OPENED;
347
                }
348
                return false;
349
            }
350
            $this->setBody(fread($fd, filesize($path)));
351
        }
352
        $headers = '';
353
        // for sending mail only
354
        if ($this->isMail || !empty($this->toEmails)) {
355
            if (!empty($this->priority)) {
356
                $this->headers[] = "X-Priority: " . $this->priority;
357
            }
358
            // $this->headers[] = "X-Mailer: PHP/".phpversion();
359
            // $this->headers[] = "Return-Path: ".$this->fromEmail;
360
            $headers = join($this->LE, $this->headers);
361
        }
362
        // TODO: we should have an option of no-reply for private messages and emails
363
        // to which we do not accept replies.  e.g. the site admin doesn't want a
364
        // a lot of message from people trying to unsubscribe.  Just make sure to
365
        // give good instructions in the message.
366
        // add some standard tags (user-dependent tags are included later)
367
368
        $this->assign('X_ADMINMAIL', $xoops->getConfig('adminmail'));
369
        $this->assign('X_SITENAME', $xoops->getConfig('sitename'));
370
        $this->assign('X_SITEURL', \XoopsBaseConfig::get('url') . "/");
371
        // TODO: also X_ADMINNAME??
372
        // TODO: X_SIGNATURE, X_DISCLAIMER ?? - these are probably best
373
        // done as includes if mail templates ever get this sophisticated
374
        // replace tags with actual values
375
        foreach ($this->assignedTags as $k => $v) {
376
            $this->body = str_replace("{" . $k . "}", $v, $this->body);
377
            $this->subject = str_replace("{" . $k . "}", $v, $this->subject);
378
        }
379
        $this->body = str_replace("\r\n", "\n", $this->body);
380
        $this->body = str_replace("\r", "\n", $this->body);
381
        $this->body = str_replace("\n", $this->LE, $this->body);
382
        // send mail to specified mail addresses, if any
383
        foreach ($this->toEmails as $mailaddr) {
384
            if (!$this->sendMail($mailaddr, $this->subject, $this->body, $headers)) {
385
                if ($debug) {
386
                    $this->errors[] = sprintf(XoopsLocale::EF_EMAIL_NOT_SENT_TO, $mailaddr);
387
                }
388
            } else {
389
                if ($debug) {
390
                    $this->success[] = sprintf(XoopsLocale::SF_EMAIL_SENT_TO, $mailaddr);
391
                }
392
            }
393
        }
394
        // send message to specified users, if any
395
        // NOTE: we don't send to LIST of recipients, because the tags
396
        // below are dependent on the user identity; i.e. each user
397
        // receives (potentially) a different message
398
        foreach ($this->toUsers as $user) {
399
            /* @var $user XoopsUser */
400
            // set some user specific variables
401
            $subject = str_replace("{X_UNAME}", $user->getVar("uname"), $this->subject);
402
            $text = str_replace("{X_UID}", $user->getVar("uid"), $this->body);
403
            $text = str_replace("{X_UEMAIL}", $user->getVar("email"), $text);
404
            $text = str_replace("{X_UNAME}", $user->getVar("uname"), $text);
405
            $text = str_replace("{X_UACTLINK}", \XoopsBaseConfig::get('url') . "/register.php?op=actv&id=" . $user->getVar("uid") . "&actkey=" . $user->getVar('actkey'), $text);
406
            // send mail
407 View Code Duplication
            if ($this->isMail) {
408
                if (!$this->sendMail($user->getVar("email"), $subject, $text, $headers)) {
409
                    if ($debug) {
410
                        $this->errors[] = sprintf(XoopsLocale::EF_EMAIL_NOT_SENT_TO, $user->getVar("uname"));
411
                    }
412
                } else {
413
                    if ($debug) {
414
                        $this->success[] = sprintf(XoopsLocale::SF_EMAIL_SENT_TO, $user->getVar("uname"));
415
                    }
416
                }
417
            }
418
            // send private message
419 View Code Duplication
            if ($this->isPM) {
420
                if (!$this->sendPM($user->getVar("uid"), $subject, $text)) {
421
                    if ($debug) {
422
                        $this->errors[] = sprintf(XoopsLocale::EF_PRIVATE_MESSAGE_NOT_SENT_TO, $user->getVar("uname"));
423
                    }
424
                } else {
425
                    if ($debug) {
426
                        $this->success[] = sprintf(XoopsLocale::SF_PRIVATE_MESSAGE_SENT_TO, $user->getVar("uname"));
427
                    }
428
                }
429
            }
430
            flush();
431
        }
432
        if (count($this->errors) > 0) {
433
            return false;
434
        }
435
        return true;
436
    }
437
438
    /**
439
     * @param int $uid
440
     * @param string $subject
441
     * @param string $body
442
     * @return bool
443
     */
444
    private function sendPM($uid, $subject, $body)
445
    {
446
        $xoops = Xoops::getInstance();
447
        $pm_handler = $xoops->getHandlerPrivateMessage();
448
        $pm = $pm_handler->create();
449
        $pm->setVar("subject", $subject);
450
        // RMV-NOTIFY
451
        $pm->setVar('from_userid', !empty($this->fromUser) ? $this->fromUser->getVar('uid') : (!$xoops->isUser() ? 1
452
                : $xoops->user->getVar('uid')));
453
        $pm->setVar("msg_text", $body);
454
        $pm->setVar("to_userid", $uid);
455
        $pm->setVar('msg_time', time());
456
        if (!$pm_handler->insert($pm)) {
457
            return false;
458
        }
459
        return true;
460
    }
461
462
    /**
463
     * Send email
464
     *
465
     * Uses the new XoopsMultiMailer
466
     *
467
     * @param string $email
468
     * @param string $subject
469
     * @param string $body
470
     * @param array $headers
471
     * @return bool
472
     */
473
    private function sendMail($email, $subject, $body, $headers)
0 ignored issues
show
Unused Code introduced by
The parameter $headers is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
474
    {
475
        $subject = $this->encodeSubject($subject);
476
        $this->encodeBody($body);
477
        $this->multimailer->ClearAllRecipients();
478
        $this->multimailer->AddAddress($email);
479
        $this->multimailer->Subject = $subject;
480
        $this->multimailer->Body = $body;
481
        $this->multimailer->CharSet = $this->charSet;
482
        $this->multimailer->Encoding = $this->encoding;
483
        if (!empty($this->fromName)) {
484
            $this->multimailer->FromName = $this->encodeFromName($this->fromName);
485
        }
486
        if (!empty($this->fromEmail)) {
487
            $this->multimailer->Sender = $this->multimailer->From = $this->fromEmail;
488
        }
489
490
        $this->multimailer->ClearCustomHeaders();
491
        foreach ($this->headers as $header) {
492
            $this->multimailer->AddCustomHeader($header);
493
        }
494
        if (!$this->multimailer->Send()) {
495
            $this->errors[] = $this->multimailer->ErrorInfo;
496
            return false;
497
        }
498
        return true;
499
    }
500
501
    /**
502
     * @param bool $ashtml
503
     * @return string
504
     */
505 1
    public function getErrors($ashtml = true)
506
    {
507 1
        if (!$ashtml) {
508 1
            return $this->errors;
509 View Code Duplication
        } else {
510 1
            $ret = "";
511 1
            if (!empty($this->errors)) {
512 1
                $ret = "<h4>" . XoopsLocale::ERRORS . "</h4>";
513 1
                foreach ($this->errors as $error) {
514 1
                    $ret .= $error . "<br />";
515
                }
516
            }
517 1
            return $ret;
518
        }
519
    }
520
521
    // public
522 1
    function getSuccess($ashtml = true)
523
    {
524 1
        if (!$ashtml) {
525 1
            return $this->success;
526
        } else {
527 1
            $ret = "";
528 1
            if (!empty($this->success)) {
529 1
                foreach ($this->success as $suc) {
530 1
                    $ret .= $suc . "<br />";
531
                }
532
            }
533 1
            return $ret;
534
        }
535
    }
536
537
    /**
538
     * @param string|array $tag
539
     * @param null $value
540
     * @return void
541
     */
542 1
    public function assign($tag, $value = null)
543
    {
544 1
        if (is_array($tag)) {
545 1
            foreach ($tag as $k => $v) {
546 1
                $this->assign($k, $v);
547
            }
548
        } else {
549 1
            if (!empty($tag) && isset($value)) {
550 1
                $tag = strtoupper(trim($tag));
551
                // RMV-NOTIFY
552
                // TEMPORARY FIXME: until the X_tags are all in here
553
                // if ( substr($tag, 0, 2) != "X_" ) {
554 1
                $this->assignedTags[$tag] = $value;
555
                // }
556
            }
557
        }
558 1
    }
559
560
    /**
561
     * @param string $value
562
     * @return void
563
     */
564 1
    public function addHeaders($value)
565
    {
566 1
        $this->headers[] = trim($value) . $this->LE;
567 1
    }
568
569
    /**
570
     * @param $email
571
     * @return void
572
     */
573 1
    public function setToEmails($email)
574
    {
575 1
        if (!is_array($email)) {
576 1
            $xoops = Xoops::getInstance();
577 1
            if ($xoops->checkEmail($email)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $xoops->checkEmail($email) of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false 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...
578 1
                array_push($this->toEmails, $email);
579
            }
580
        } else {
581 1
            foreach ($email as $e) {
582 1
                $this->setToEmails($e);
583
            }
584
        }
585 1
    }
586
587
    /**
588
     * @param XoopsUser|array $user
0 ignored issues
show
Bug introduced by
There is no parameter named $user. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
589
     * @return void
590
     */
591 2
    public function setToUsers($users)
592
    {
593 2
        if ($users instanceof XoopsUser) {
594 2
            array_push($this->toUsers, $users);
595
        } elseif (is_array($users)) {
596 2
            foreach ($users as $u) {
597 2
                $this->setToUsers($u);
598
            }
599
        }
600 2
    }
601
602
    /**
603
     * @param XoopsGroup $group
0 ignored issues
show
Documentation introduced by
There is no parameter named $group. Did you maybe mean $groups?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
604
     * @return void
605
     */
606 1
    public function setToGroups($groups)
607
    {
608 1
        if ($groups instanceof XoopsGroup) {
609 1
            $this->setToUsers(Xoops::getInstance()
610 1
                    ->getHandlerMember()
611 1
                    ->getUsersByGroup($groups->getVar('groupid'), true));
612
613
        } elseif (is_array($groups)) {
614 1
            foreach ($groups as $g) {
615 1
                $this->setToGroups($g);
616
            }
617
        }
618 1
    }
619
620
    /**
621
     * abstract, to be overridden by lang specific mail class, if needed
622
     *
623
     * @param $text
624
     * @return
625
     */
626 1
    public function encodeFromName($text)
627
    {
628 1
        return $text;
629
    }
630
631
    /**
632
     * abstract, to be overridden by lang specific mail class, if needed
633
     *
634
     * @param string $text
635
     * @return string
636
     */
637 1
    public function encodeSubject($text)
638
    {
639 1
        return $text;
640
    }
641
642
    /**
643
     * abstract, to be overridden by lang specific mail class, if needed
644
     *
645
     * @param string $text
646
     * @return void
647
     */
648 1
    public function encodeBody(&$text)
0 ignored issues
show
Unused Code introduced by
The parameter $text is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
649
    {
650 1
    }
651
}
652