SocketClient   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 80.38%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 16
lcom 1
cbo 2
dl 0
loc 186
ccs 41
cts 51
cp 0.8038
rs 10
c 2
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
B connect() 0 30 3
A reconnect() 0 10 2
A close() 0 4 1
A setBlocking() 0 5 1
A read() 0 4 1
A write() 0 8 2
A crypto() 0 13 3
A getResource() 0 4 1
A getAddress() 0 4 1
1
<?php
2
3
/**
4
 * Copyright 2014 Fabian Grutschus. All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without modification,
7
 * are permitted provided that the following conditions are met:
8
 *
9
 * 1. Redistributions of source code must retain the above copyright notice, this
10
 *   list of conditions and the following disclaimer.
11
 *
12
 * 2. Redistributions in binary form must reproduce the above copyright notice,
13
 *   this list of conditions and the following disclaimer in the documentation
14
 *   and/or other materials provided with the distribution.
15
 *
16
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
20
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
 *
27
 * The views and conclusions contained in the software and documentation are those
28
 * of the authors and should not be interpreted as representing official policies,
29
 * either expressed or implied, of the copyright holders.
30
 *
31
 * @author    Fabian Grutschus <[email protected]>
32
 * @copyright 2014 Fabian Grutschus. All rights reserved.
33
 * @license   BSD
34
 * @link      http://github.com/fabiang/xmpp
35
 */
36
37
namespace Fabiang\Xmpp\Stream;
38
39
use Fabiang\Xmpp\Exception\InvalidArgumentException;
40
use Fabiang\Xmpp\Util\ErrorHandler;
41
42
/**
43
 * Stream functions wrapper class.
44
 *
45
 * @package Xmpp\Stream
46
 */
47
class SocketClient
48
{
49
50
    const BUFFER_LENGTH = 4096;
51
52
    /**
53
     * Resource.
54
     *
55
     * @var resource
56
     */
57
    protected $resource;
58
59
    /**
60
     * Address.
61
     *
62
     * @var string
63
     */
64
    protected $address;
65
66
67
    /**
68
     * Options used to create a stream context
69
     * @see http://php.net/manual/en/function.stream-context-create.php
70
     *
71 6
     * @var array
72
     */
73 6
    protected $options;
74 6
75
    /**
76
     * Constructor takes address as argument.
77
     *
78
     * @param string $address
79
     */
80
    public function __construct($address, $options = null)
81
    {
82
        $this->address = $address;
83 6
        $this->options = $options;
84
    }
85 6
86 3
    /**
87 3
     * Connect.
88 3
     *
89
     * @param integer $timeout Timeout for connection
90
     * @param boolean $persistent Persitent connection
91
     * @return void
92 6
     */
93 6
    public function connect($timeout = 30, $persistent = false)
94 6
    {
95 6
        $flags = STREAM_CLIENT_CONNECT;
96 6
97 6
        if (true === $persistent) {
98
            $flags |= STREAM_CLIENT_PERSISTENT;
99 6
        }
100 6
101
        // call stream_socket_client with custom error handler enabled
102 6
        $handler = new ErrorHandler(
103 6
            function ($address, $timeout, $flags, array $options = null) {
104 6
                $errno  = null;
105
                $errstr = null;
106
107
                if (!empty($options)) {
108
                    $context = stream_context_create($options);
109
                    return stream_socket_client($address, $errno, $errstr, $timeout, $flags, $context);
110
                }
111
                return stream_socket_client($address, $errno, $errstr, $timeout, $flags);
112
            },
113 3
            $this->address,
114
            $timeout,
115 3
            $flags,
116
            $this->options
117 3
        );
118 3
        $resource = $handler->execute(__FILE__, __LINE__);
119 3
120
        stream_set_timeout($resource, $timeout);
121 3
        $this->resource = $resource;
122 3
    }
123
124
    /**
125
     * Reconnect and optionally use different address.
126
     *
127
     * @param string $address
128
     * @param integer $timeout
129 3
     * @param bool $persistent
130
     */
131 3
    public function reconnect($address = null, $timeout = 30, $persistent = false)
132 3
    {
133
        $this->close();
134
135
        if (null !== $this->address) {
136
            $this->address = $address;
137
        }
138
139
        $this->connect($timeout, $persistent);
140
    }
141
142
    /**
143
     * Close stream.
144
     *
145
     * @return void
146
     */
147
    public function close()
148
    {
149
        fclose($this->resource);
150
    }
151
152 3
    /**
153
     * Set stream blocking mode.
154 3
     *
155
     * @param boolean $flag Flag
156
     * @return $this
157
     */
158
    public function setBlocking($flag = true)
159
    {
160
        stream_set_blocking($this->resource, (int)$flag);
161
        return $this;
162
    }
163
164 3
    /**
165
     * Read from stream.
166 3
     *
167 3
     * @param integer $length Bytes to read
168 3
     * @return string
169 3
     */
170
    public function read($length = self::BUFFER_LENGTH)
171 3
    {
172
        return fread($this->resource, $length);
173
    }
174
175
    /**
176
     * Write to stream.
177
     *
178
     * @param string $string String
179
     * @param integer $length Limit
180
     * @return void
181
     */
182
    public function write($string, $length = null)
183
    {
184
        if (null !== $length) {
185
            fwrite($this->resource, $string, $length);
186
        } else {
187
            fwrite($this->resource, $string);
188
        }
189
    }
190
191
    /**
192
     * Enable/disable cryptography on stream.
193
     *
194
     * @param boolean $enable Flag
195
     * @param integer $cryptoType One of the STREAM_CRYPTO_METHOD_* constants.
196
     * @return void
197
     * @throws InvalidArgumentException
198
     */
199
    public function crypto($enable, $cryptoType = null)
200 6
    {
201
        if (false === $enable) {
202 6
            $handler = new ErrorHandler('stream_socket_enable_crypto', $this->resource, false);
203
            return $handler->execute(__FILE__, __LINE__);
204
        }
205
206
        if (null === $cryptoType) {
207
            throw new InvalidArgumentException('Second argument is require when enabling crypto an stream');
208
        }
209
210 3
        return stream_socket_enable_crypto($this->resource, $enable, $cryptoType);
211
    }
212 3
213
    /**
214
     * Get socket stream.
215
     *
216
     * @return resource
217
     */
218
    public function getResource()
219
    {
220
        return $this->resource;
221
    }
222
223
    /**
224
     * Return address.
225
     *
226
     * @return string
227
     */
228
    public function getAddress()
229
    {
230
        return $this->address;
231
    }
232
}
233