Passed
Push — master ( 831177...1585b1 )
by Jeroen
01:32
created

IrcConnection::isConnected()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
1
<?php
2
3
namespace Jerodev\PhpIrcClient;
4
5
use Exception;
6
use Jerodev\PhpIrcClient\Helpers\EventHandlerCollection;
7
use Jerodev\PhpIrcClient\Messages\IrcMessage;
8
use React\EventLoop\LoopInterface;
9
use React\Socket\ConnectionInterface;
10
11
class IrcConnection
12
{
13
    /** @var bool */
14
    private $connected;
15
    
16
    /** @var ConnectionInterface|null */
17
    private $connection;
18
    
19
    /** @var EventHandlerCollection */
20
    private $eventHandlerCollection;
21
    
22
    /** @var LoopInterface */
23
    private $loop;
24
    
25
    /** @var IrcMessageParser */
26
    private $messageParser;
27
    
28
    /** @var string */
29
    private $server;
30
    
31
    public function __construct(string $server)
32
    {
33
        $this->connected = false;
34
        $this->eventHandlerCollection = new EventHandlerCollection();
35
        $this->messageParser = new IrcMessageParser();
36
        $this->server = $server;
37
    }
38
    
39
    /** 
40
     *  Open a connection to the irc server.
41
     */
42
    public function open()
43
    {
44
        $this->loop = \React\EventLoop\Factory::create();
45
        $tcpConnector = new \React\Socket\TcpConnector($this->loop);
46
        $dnsResolverFactory = new \React\Dns\Resolver\Factory();
47
        $dns = $dnsResolverFactory->createCached('1.1.1.1', $this->loop);
48
        $dnsConnector = new \React\Socket\DnsConnector($tcpConnector, $dns);
49
50
        $dnsConnector->connect($this->server)->then(function (ConnectionInterface $connection) {
51
            $this->connection = $connection;
52
            $this->connected = true;
53
54
            $this->connection->on('data', function ($data) {
55
                foreach ($this->messageParser->parse($data) as $msg) {
56
                    $this->handleMessage($msg);
57
                }
58
            });
59
            
60
            $this->connection->on('close', function () {
61
                $this->connected = false;
62
            });
63
            $this->connection->on('end', function () {
64
                $this->connected = false;
65
            });
66
        });
67
68
        $this->loop->run();
69
    }
70
    
71
    /**
72
     *  Close the current irc server connection.
73
     */
74
    public function close(): void
75
    {
76
        if ($this->isConnected()) {
77
            $this->connection->close();
78
            $this->loop->stop();
79
        }
80
    }
81
    
82
    /**
83
     *  Test if there is an open connection to the irc server.
84
     */
85
    public function isConnected(): bool
86
    {
87
        return $this->connection && $this->connected;
88
    }
89
    
90
    /** 
91
     *  Set a callback for received irc data
92
     *  An IrcMessage object will be passed to the callback
93
     *
94
     *  @param callable $function The function to be called.  
95
     */
96
    public function onData(callable $function): void
97
    {
98
        $this->eventHandlerCollection->addHandler('data', $function);
99
    }
100
    
101
    /**
102
     * Send a command to the irc server.
103
     *
104
     *  @param string $command The raw irc command.
105
     *
106
     *  @throws Exception if no open connection is available.
107
     */
108
    public function write(string $command): void
109
    {
110
        if (!$this->isConnected()) {
111
            throw new Exception('No open connection was found to write commands to.');
112
        }
113
        
114
        // Make sure the command ends in a newline character
115
        if (substr($command, -1) !== "\n") {
116
            $command .= "\n";
117
        }
118
        
119
        $this->connection->write($command);
120
    }
121
    
122
    /**
123
     *  Handle a single parsed IrcMessage.
124
     *
125
     *  @param IrcMessage $message The message received from the server.
126
     */
127
    private function handleMessage(IrcMessage $message): void
128
    {
129
        $this->eventHandlerCollection->invoke('data', [$message]);
130
    }
131
}