Test Failed
Push — master ( fbea6a...5a4cf9 )
by Taosikai
13:28
created

MessageHandler::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the slince/smartqq package.
5
 *
6
 * (c) Slince <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Slince\SmartQQ;
13
14
use GuzzleHttp\Exception\ConnectException;
15
use Slince\EventDispatcher\DispatcherInterface;
16
use Slince\EventDispatcher\Event;
17
use Slince\SmartQQ\Exception\InvalidArgumentException;
18
use Slince\SmartQQ\Exception\ResponseException;
19
use Slince\SmartQQ\Exception\RuntimeException;
20
21
class MessageHandler
22
{
23
    /**
24
     * 事件名,当收到消息时触发.
25
     *
26
     * @var string
27
     */
28
    const EVENT_MESSAGE = 'message';
29
30
    /**
31
     * @var Client
32
     */
33
    protected $client;
34
35
    /**
36
     * @var DispatcherInterface
37
     */
38
    protected $eventDispatcher;
39
40
    /**
41
     * @var boolean
42
     */
43
    protected $stop = false;
44
45
    /**
46
     * 可以被忽略的状态码.
47
     *
48
     * @var array
49
     */
50
    protected static $ignoredCodes = [
51
        0, 100003, 100100, 100012
52
    ];
53
54
    public function __construct(Client $client)
55
    {
56
        $this->client = $client;
57
        $this->eventDispatcher = $client->getEventDispatcher();
58
    }
59
60
    /**
61
     * 绑定消息处理回调
62
     *
63
     * ```php
64
     * $handler->onMessage(function(Slince\SmartQQ\Message\Response\Message $message){
65
     *      //...
66
     * });
67
     * ```
68
     *
69
     * @param callable $handler
70
     */
71
    public function onMessage($handler)
72
    {
73
        if (!is_callable($handler)) {
74
            throw new InvalidArgumentException('Message handler should be callable.');
75
        }
76
        $this->eventDispatcher->addListener(static::EVENT_MESSAGE, function(Event $event) use ($handler){
77
            $handler($event->getArgument('message'));
78
        });
79
    }
80
81
    /**
82
     * 开始监听客户端消息
83
     */
84
    public function listen()
85
    {
86
        while (!$this->stop) {
87
            try {
88
                $messages = $this->client->pollMessages();
89
                foreach ($messages as $message) {
90
                    // 收到消息时触发事件
91
                    $event = new Event(static::EVENT_MESSAGE, null, [
92
                        'message' => $message
93
                    ]);
94
                    $this->eventDispatcher->dispatch($event);
95
                }
96
            } catch (ResponseException $exception) {
97
                if (in_array($exception->getCode(), static::$ignoredCodes)) {
98
                    $this->testLogin();
99
                    usleep(2000000);
100
                } else {
101
                    throw $exception; // 其它状态码接着抛出异常
102
                }
103
            } catch (ConnectException $exception) {
104
                // 超时请求忽略
105
                usleep(2000000);
106
            }
107
        }
108
    }
109
110
    /**
111
     * 终止下一次消息监听.
112
     *
113
     * ```php
114
     * $handler->onMessage(function($message) use ($handler){
115
     *     var_dump($message);
116
     *     $handler->stop();  //停止
117
     * });
118
     * ```
119
     */
120
    public function stop()
121
    {
122
        $this->stop = true;
123
    }
124
125
    /**
126
     * 测试登录
127
     */
128
    protected function testLogin()
129
    {
130
        try {
131
            $this->client->getFriendsOnlineStatus();
132
        } catch (\Exception $exception) {
133
            //登录凭证可能失效
134
            throw new RuntimeException('The credential may be expired, please login again.', $exception->getCode());
135
        }
136
    }
137
}