Test Failed
Pull Request — master (#24)
by Evgeniy
07:58
created

FileMailer   A

Complexity

Total Complexity 8

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 1 Features 0
Metric Value
eloc 17
c 2
b 1
f 0
dl 0
loc 80
ccs 15
cts 15
cp 1
rs 10
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A generateMessageFilename() 0 14 3
A sendMessage() 0 10 4
A __construct() 0 11 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mailer;
6
7
use Exception;
8
use Psr\EventDispatcher\EventDispatcherInterface;
9
use RuntimeException;
10
11
use function date;
12
use function file_put_contents;
13
use function gettype;
14
use function is_dir;
15
use function is_string;
16
use function microtime;
17
use function mkdir;
18
use function random_int;
19
use function sprintf;
20
21
/**
22
 * FileMailer is a mock mailer that save email messages in files instead of sending them.
23
 */
24
final class FileMailer extends Mailer
25
{
26
    /**
27
     * The path where message files located.
28
     *
29
     * @var string
30
     */
31
    private string $path;
32
33
    /**
34
     * @var callable|null A PHP callback that return a file name which will be used to save the email message.
35
     *
36
     * If not set, the file name will be generated based on the current
37
     * timestamp {@see FileMailer::generateMessageFilename()}.
38 2
     *
39
     * The signature of the callback is:
40 2
     *
41
     * ```php
42
     * function (MessageInterface $message): string;
43
     * ```
44
     */
45
    private $filenameCallback;
46
47
    /**
48 2
     * @param MessageFactoryInterface $messageFactory The message factory instance.
49
     * @param MessageBodyRenderer $messageBodyRenderer The message body renderer instance.
50 2
     * @param EventDispatcherInterface $eventDispatcher The event dispatcher instance.
51 2
     * @param string $path The path where message files located.
52
     * @param callable|null $filenameCallback A PHP callback that return
53
     * a file name which will be used to save the email message.
54
     */
55
    public function __construct
56
    (
57
        MessageFactoryInterface $messageFactory,
58
        MessageBodyRenderer $messageBodyRenderer,
59
        EventDispatcherInterface $eventDispatcher,
60 12
        string $path,
61
        callable $filenameCallback = null
62
    ) {
63
        parent::__construct($messageFactory, $messageBodyRenderer, $eventDispatcher);
64
        $this->path = $path;
65
        $this->filenameCallback = $filenameCallback;
66
    }
67 12
68 12
    protected function sendMessage(MessageInterface $message): void
69 12
    {
70
        $filename = $this->path . DIRECTORY_SEPARATOR . $this->generateMessageFilename($message);
71
        $filepath = dirname($filename);
72
73
        if (!is_dir($filepath) && !mkdir($filepath, 0777, true) && !is_dir($filepath)) {
74
            throw new RuntimeException(sprintf('Directory "%s" was not created.', $filepath));
75
        }
76
77
        file_put_contents($filename, $message->__toString());
78
    }
79
80
    /**
81
     * Generates a filename based on the current timestamp.
82
     *
83
     * @param MessageInterface $message The message instance.
84
     *
85
     * @throws Exception {@see https://www.php.net/manual/en/function.random-int.php}
86
     * @throws RuntimeException If {@see FileMailer::$filenameCallback} does not return a string.
87
     *
88
     * @return string The filename for saving the message.
89 1
     */
90
    private function generateMessageFilename(MessageInterface $message): string
91 1
    {
92 1
        if ($this->filenameCallback === null) {
93
            $time = (int) microtime(true);
94
            return date('Ymd-His-', $time) . sprintf('%04d', $time) . '-' . sprintf('%04d', random_int(0, 10000)) . '.eml';
95
        }
96
97
        $filename = ($this->filenameCallback)($message);
98
99 5
        if (!is_string($filename)) {
100
            throw new RuntimeException(sprintf('Filename must be a string. "%s" received.', gettype($filename)));
101 5
        }
102
103 5
        return $filename;
104
    }
105
}
106