Passed
Push — master ( 7c0504...2690fb )
by Xu
06:27
created

BaseBroadcast::generateMessageFileName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link http://www.tintsoft.com/
4
 * @copyright Copyright (c) 2012 TintSoft Technology Co. Ltd.
5
 * @license http://www.tintsoft.com/license/
6
 */
7
8
namespace yuncms\broadcast;
9
10
use Yii;
11
use yii\base\Component;
12
13
/**
14
 * 广播组件
15
 *
16
 * @author Tongle Xu <[email protected]>
17
 * @since 3.0
18
 */
19
abstract class BaseBroadcast extends Component implements BroadcastInterface
20
{
21
    /**
22
     * @event BroadcastEvent an event raised right before send.
23
     * You may set [[BroadcastEvent::isValid]] to be false to cancel the send.
24
     */
25
    const EVENT_BEFORE_SEND = 'beforeSend';
26
27
    /**
28
     * @event BroadcastEvent an event raised right after send.
29
     */
30
    const EVENT_AFTER_SEND = 'afterSend';
31
32
    /**
33
     * @var string the default class name of the new message instances created by [[createMessage()]]
34
     */
35
    public $messageClass = 'yuncms\broadcast\BaseMessage';
36
37
    /**
38
     * @var bool whether to save broadcast messages as files under [[fileTransportPath]] instead of sending them
39
     * to the actual recipients. This is usually used during development for debugging purpose.
40
     * @see fileTransportPath
41
     */
42
    public $useFileTransport = false;
43
44
    /**
45
     * @var string the directory where the broadcast messages are saved when [[useFileTransport]] is true.
46
     */
47
    public $fileTransportPath = '@runtime/broadcast';
48
49
    /**
50
     * @var callable a PHP callback that will be called by [[send()]] when [[useFileTransport]] is true.
51
     * The callback should return a file name which will be used to save the broadcast message.
52
     * If not set, the file name will be generated based on the current timestamp.
53
     *
54
     * The signature of the callback is:
55
     *
56
     * ```php
57
     * function ($broadcast, $message)
58
     * ```
59
     */
60
    public $fileTransportCallback;
61
62
    /**
63
     * Creates a new message instance and optionally composes its body content via view rendering.
64
     *
65
     * @param array $message message payload.
66
     * @return MessageInterface|object message instance.
67
     * @throws \yii\base\InvalidConfigException
68
     */
69
    public function createMessage($message): MessageInterface
70
    {
71
        $config = [
72
            'class' => $this->messageClass,
73
            'broadcast' => $this,
74
            'body' => $message,
75
        ];
76
        return Yii::createObject($config);
77
    }
78
79
    /**
80
     * Sends the given broadcast message.
81
     * This method will log a message about the broadcast being sent.
82
     * If [[useFileTransport]] is true, it will save the broadcast as a file under [[fileTransportPath]].
83
     * Otherwise, it will call [[sendMessage()]] to send the broadcast to its recipient(s).
84
     * Child classes should implement [[sendMessage()]] with the actual broadcast sending logic.
85
     * @param MessageInterface $message broadcast message instance to be sent
86
     * @return bool whether the message has been sent successfully
87
     */
88
    public function send($message)
89
    {
90
        if (!$this->beforeSend($message)) {
91
            return false;
92
        }
93
        Yii::info('Sending broadcast :' . $message->toString(), __METHOD__);
94
95
        if ($this->useFileTransport) {
96
            $isSuccessful = $this->saveMessage($message);
97
        } else {
98
            $isSuccessful = $this->sendMessage($message);
99
        }
100
        $this->afterSend($message, $isSuccessful);
101
102
        return $isSuccessful;
103
    }
104
105
    /**
106
     * Sends multiple messages at once.
107
     *
108
     * The default implementation simply calls [[send()]] multiple times.
109
     * Child classes may override this method to implement more efficient way of
110
     * sending multiple messages.
111
     *
112
     * @param array $messages list of broadcast messages, which should be sent.
113
     * @return int number of messages that are successfully sent.
114
     */
115
    public function sendMultiple(array $messages)
116
    {
117
        $successCount = 0;
118
        foreach ($messages as $message) {
119
            if ($this->send($message)) {
120
                $successCount++;
121
            }
122
        }
123
124
        return $successCount;
125
    }
126
127
    /**
128
     * Sends the specified message.
129
     * This method should be implemented by child classes with the actual broadcast sending logic.
130
     * @param MessageInterface $message the message to be sent
131
     * @return bool whether the message is sent successfully
132
     */
133
    abstract protected function sendMessage($message);
134
135
    /**
136
     * Saves the message as a file under [[fileTransportPath]].
137
     * @param MessageInterface $message
138
     * @return bool whether the message is saved successfully
139
     */
140
    protected function saveMessage($message)
141
    {
142
        $path = Yii::getAlias($this->fileTransportPath);
143
        if (!is_dir($path)) {
144
            mkdir($path, 0777, true);
145
        }
146
        if ($this->fileTransportCallback !== null) {
147
            $file = $path . '/' . call_user_func($this->fileTransportCallback, $this, $message);
148
        } else {
149
            $file = $path . '/' . $this->generateMessageFileName();
150
        }
151
        file_put_contents($file, $message->toString());
152
        return true;
153
    }
154
155
    /**
156
     * @return string the file name for saving the message when [[useFileTransport]] is true.
157
     */
158
    public function generateMessageFileName()
159
    {
160
        $time = microtime(true);
161
        return date('Ymd-His-', $time) . sprintf('%04d', (int)(($time - (int)$time) * 10000)) . '-' . sprintf('%04d', mt_rand(0, 10000)) . '.eml';
162
    }
163
164
    /**
165
     * This method is invoked right before mail send.
166
     * You may override this method to do last-minute preparation for the message.
167
     * If you override this method, please make sure you call the parent implementation first.
168
     * @param MessageInterface $message
169
     * @return bool whether to continue sending an broadcast.
170
     */
171
    public function beforeSend($message)
172
    {
173
        $event = new BroadcastEvent(['message' => $message]);
174
        $this->trigger(self::EVENT_BEFORE_SEND, $event);
175
        return $event->isValid;
176
    }
177
178
    /**
179
     * This method is invoked right after mail was send.
180
     * You may override this method to do some postprocessing or logging based on mail send status.
181
     * If you override this method, please make sure you call the parent implementation first.
182
     * @param MessageInterface $message
183
     * @param bool $isSuccessful
184
     */
185
    public function afterSend($message, $isSuccessful)
186
    {
187
        $event = new BroadcastEvent(['message' => $message, 'isSuccessful' => $isSuccessful]);
188
        $this->trigger(self::EVENT_AFTER_SEND, $event);
189
    }
190
}