8000 Merge pull request #318 from clue-labs/nullable-v1 · reactphp/socket@038f639 · GitHub
[go: up one dir, main page]

Skip to content

Commit 038f639

Browse files
authored
Merge pull request #318 from clue-labs/nullable-v1
[1.x] Improve PHP 8.4+ support by avoiding implicitly nullable types
2 parents 216d3ae + dbf58dc commit 038f639

23 files changed

+161
-23
lines changed

composer.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@
2828
"require": {
2929
"php": ">=5.3.0",
3030
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
31-
"react/dns": "^1.11",
31+
"react/dns": "^1.13",
3232
"react/event-loop": "^1.2",
33-
"react/promise": "^3 || ^2.6 || ^1.2.1",
34-
"react/stream": "^1.2"
33+
"react/promise": "^3.2 || ^2.6 || ^1.2.1",
34+
"react/stream": "^1.4"
3535
},
3636
"require-dev": {
3737
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36",
38-
"react/async": "^4 || ^3 || ^2",
38+
"react/async": "^4.3 || ^3.3 || ^2",
3939
"react/promise-stream": "^1.4",
40-
"react/promise-timer": "^1.10"
40+
"react/promise-timer": "^1.11"
4141
},
4242
"autoload": {
4343
"psr-4": {

src/FdServer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ final class FdServer extends EventEmitter implements ServerInterface
7575
* @throws \InvalidArgumentException if the listening address is invalid
7676
* @throws \RuntimeException if listening on this address fails (already in use etc.)
7777
*/
78-
public function __construct($fd, LoopInterface $loop = null)
78+
public function __construct($fd, $loop = null)
7979
{
8080
if (\preg_match('#^php://fd/(\d+)$#', $fd, $m)) {
8181
$fd = (int) $m[1];
@@ -87,6 +87,10 @@ public function __construct($fd, LoopInterface $loop = null)
8787
);
8888
}
8989

90+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
91+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
92+
}
93+
9094
$this->loop = $loop ?: Loop::get();
9195

9296
$errno = 0;

src/HappyEyeBallsConnector.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,26 @@ final class HappyEyeBallsConnector implements ConnectorInterface
1313
private $connector;
1414
private $resolver;
1515

16-
public function __construct(LoopInterface $loop = null, ConnectorInterface $connector = null, ResolverInterface $resolver = null)
16+
/**
17+
* @param ?LoopInterface $loop
18+
* @param ConnectorInterface $connector
19+
* @param ResolverInterface $resolver
20+
*/
21+
public function __construct($loop = null, $connector = null, $resolver = null)
1722
{
1823
// $connector and $resolver arguments are actually required, marked
1924
// optional for technical reasons only. Nullable $loop without default
2025
// requires PHP 7.1, null default is also supported in legacy PHP
2126
// versions, but required parameters are not allowed after arguments
2227
// with null default. Mark all parameters optional and check accordingly.
23-
if ($connector === null || $resolver === null) {
24-
throw new \InvalidArgumentException('Missing required $connector or $resolver argument');
28+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
29+
throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
30+
}
31+
if (!$connector instanceof ConnectorInterface) { // manual type check to support legacy PHP < 7.1
32+
throw new \InvalidArgumentException('Argument #2 ($connector) expected React\Socket\ConnectorInterface');
33+
}
34+
if (!$resolver instanceof ResolverInterface) { // manual type check to support legacy PHP < 7.1
35+
throw new \InvalidArgumentException('Argument #3 ($resolver) expected React\Dns\Resolver\ResolverInterface');
2536
}
2637

2738
$this->loop = $loop ?: Loop::get();

src/SecureConnector.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,17 @@ final class SecureConnector implements ConnectorInterface
1515
private $streamEncryption;
1616
private $context;
1717

18-
public function __construct(ConnectorInterface $connector, LoopInterface $loop = null, array $context = array())
18+
/**
19+
* @param ConnectorInterface $connector
20+
* @param ?LoopInterface $loop
21+
* @param array $context
22+
*/
23+
public function __construct(ConnectorInterface $connector, $loop = null, array $context = array())
1924
{
25+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
26+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
27+
}
28+
2029
$this->connector = $connector;
2130
$this->streamEncryption = new StreamEncryption($loop ?: Loop::get(), false);
2231
$this->context = $context;

src/SecureServer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,12 @@ final class SecureServer extends EventEmitter implements ServerInterface
122122
* @see TcpServer
123123
* @link https://www.php.net/manual/en/context.ssl.php for TLS context options
124124
*/
125-
public function __construct(ServerInterface $tcp, LoopInterface $loop = null, array $context = array())
125+
public function __construct(ServerInterface $tcp, $loop = null, array $context = array())
126126
{
127+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
128+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
129+
}
130+
127131
if (!\function_exists('stream_socket_enable_crypto')) {
128132
throw new \BadMethodCallException('Encryption not supported on your platform (HHVM < 3.8?)'); // @codeCoverageIgnore
129133
}

src/Server.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,18 @@ final class Server extends EventEmitter implements ServerInterface
4343
* For BC reasons, you can also pass the TCP socket context options as a simple
4444
* array without wrapping this in another array under the `tcp` key.
4545
*
46-
* @param string|int $uri
47-
* @param LoopInterface $loop
48-
* @param array $context
46+
* @param string|int $uri
47+
* @param ?LoopInterface $loop
48+
* @param array $context
4949
* @deprecated 1.9.0 See `SocketServer` instead
5050
* @see SocketServer
5151
*/
52-
public function __construct($uri, LoopInterface $loop = null, array $context = array())
52+
public function __construct($uri, $loop = null, array $context = array())
5353
{
54+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
55+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
56+
}
57+
5458
$loop = $loop ?: Loop::get();
5559

5660
// sanitize TCP context options if not properly wrapped

src/SocketServer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ final class SocketServer extends EventEmitter implements ServerInterface
3131
* @throws \InvalidArgumentException if the listening address is invalid
3232
* @throws \RuntimeException if listening on this address fails (already in use etc.)
3333
*/
34-
public function __construct($uri, array $context = array(), LoopInterface $loop = null)
34+
public function __construct($uri, array $context = array(), $loop = null)
3535
{
36+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
37+
throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
38+
}
39+
3640
// apply default options if not explicitly given
3741
$context += array(
3842
'tcp' => array(),

src/TcpConnector.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,16 @@ final class TcpConnector implements ConnectorInterface
1313
private $loop;
1414
private $context;
1515

16-
public function __construct(LoopInterface $loop = null, array $context = array())
16+
/**
17+
* @param ?LoopInterface $loop
18+
* @param array $context
19+
*/
20+
public function __construct($loop = null, array $context = array())
1721
{
22+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
23+
throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
24+
}
25+
1826
$this->loop = $loop ?: Loop::get();
1927
$this->context = $context;
2028
}

src/TcpServer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,12 @@ final class TcpServer extends EventEmitter implements ServerInterface
128128
* @throws InvalidArgumentException if the listening address is invalid
129129
* @throws RuntimeException if listening on this address fails (already in use etc.)
130130
*/
131-
public function __construct($uri, LoopInterface $loop = null, array $context = array())
131+
public function __construct($uri, $loop = null, array $context = array())
132132
{
133+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
134+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
135+
}
136+
133137
$this->loop = $loop ?: Loop::get();
134138

135139
// a single port has been given => assume localhost

src/TimeoutConnector.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,17 @@ final class TimeoutConnector implements ConnectorInterface
1212
private $timeout;
1313
private $loop;
1414

15-
public function __construct(ConnectorInterface $connector, $timeout, LoopInterface $loop = null)
15+
/**
16+
* @param ConnectorInterface $connector
17+
* @param float $timeout
18+
* @param ?LoopInterface $loop
19+
*/
20+
public function __construct(ConnectorInterface $connector, $timeout, $loop = null)
1621
{
22+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
23+
throw new \InvalidArgumentException('Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
24+
}
25+
1726
$this->connector = $connector;
1827
$this->timeout = $timeout;
1928
$this->loop = $loop ?: Loop::get();

src/UnixConnector.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,15 @@ final class UnixConnector implements ConnectorInterface
1818
{
1919
private $loop;
2020

21-
public function __construct(LoopInterface $loop = null)
21+
/**
22+
* @param ?LoopInterface $loop
23+
*/
24+
public function __construct($loop = null)
2225
{
26+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
27+
throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
28+
}
29+
2330
$this->loop = $loop ?: Loop::get();
2431
}
2532

src/UnixServer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,12 @@ final class UnixServer extends EventEmitter implements ServerInterface
5050
* @throws InvalidArgumentException if the listening address is invalid
5151
* @throws RuntimeException if listening on this address fails (already in use etc.)
5252
*/
53-
public function __construct($path, LoopInterface $loop = null, array $context = array())
53+
public function __construct($path, $loop = null, array $context = array())
5454
{
55+
if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
56+
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
57+
}
58+
5559
$this->loop = $loop ?: Loop::get();
5660

5761
if (\strpos($path, '://') === false) {

tests/FdServerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ public function testCtorThrowsForInvalidUrl()
5050
new FdServer('tcp://127.0.0.1:8080', $loop);
5151
}
5252

53+
public function testCtorThrowsForInvalidLoop()
54+
{
55+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
56+
new FdServer(0, 'loop');
57+
}
58+
5359
public function testCtorThrowsForUnknownFdWithoutCallingCustomErrorHandler()
5460
{
5561
if (!is_dir('/dev/fd') || defined('HHVM_VERSION')) {

tests/HappyEyeBallsConnectorTest.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,21 @@ public function testConstructWithoutLoopAssignsLoopAutomatically()
4040
$this->assertInstanceOf('React\EventLoop\LoopInterface', $loop);
4141
}
4242

43+
public function testConstructWithInvalidLoopThrows()
44+
{
45+
$this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
46+
new HappyEyeBallsConnector('loop', $this->tcp, $this->resolver);
47+
}
48+
4349
public function testConstructWithoutRequiredConnectorThrows()
4450
{
45-
$this->setExpectedException('InvalidArgumentException');
51+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($connector) expected React\Socket\ConnectorInterface');
4652
new HappyEyeBallsConnector(null, null, $this->resolver);
4753
}
4854

4955
public function testConstructWithoutRequiredResolverThrows()
5056
{
51-
$this->setExpectedException('InvalidArgumentException');
57+
$this->setExpectedException('InvalidArgumentException', 'Argument #3 ($resolver) expected React\Dns\Resolver\ResolverInterface');
5258
new HappyEyeBallsConnector(null, $this->tcp);
5359
}
5460

tests/SecureConnectorTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public function setUpConnector()
2626
$this->connector = new SecureConnector($this->tcp, $this->loop);
2727
}
2828

29+
public function testCtorThrowsForInvalidLoop()
30+
{
31+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
32+
new SecureConnector($this->tcp, 'loop');
33+
}
34+
2935
public function testConstructWithoutLoopAssignsLoopAutomatically()
3036
{
3137
$connector = new SecureConnector($this->tcp);

tests/SecureServerTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@ public function setUpSkipTest()
1818
}
1919
}
2020

21+
public function testCtorThrowsForInvalidLoop()
22+
{
23+
$tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();
24+
25+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
26+
new SecureServer($tcp, 'loop');
27+
}
28+
2129
public function testConstructWithoutLoopAssignsLoopAutomatically()
2230
{
2331
$tcp = $this->getMockBuilder('React\Socket\ServerInterface')->getMock();

tests/ServerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ public function testConstructorThrowsForInvalidUri()
4444
$server = new Server('invalid URI', $loop);
4545
}
4646

47+
public function testCtorThrowsForInvalidLoop()
48+
{
49+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
50+
new Server('127.0.0.1:0', 'loop');
51+
}
52+
4753
public function testConstructorCreatesExpectedTcpServer()
4854
{
4955
$server = new Server(0);

tests/SocketServerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ public function testConstructorWithInvalidUriWithSchemaAndPortOnlyThrows()
6565
new SocketServer('tcp://0');
6666
}
6767

68+
public function testCtorThrowsForInvalidLoop()
69+
{
70+
$this->setExpectedException('InvalidArgumentException', 'Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
71+
new SocketServer('127.0.0.1:0', array(), 'loop');
72+
}
73+
6874
public function testConstructorCreatesExpectedTcpServer()
6975
{
7076
$socket = new SocketServer('127.0.0.1:0', array());

tests/TcpConnectorTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ class TcpConnectorTest extends TestCase
1212
{
1313
const TIMEOUT = 5.0;
1414

15+
public function testCtorThrowsForInvalidLoop()
16+
{
17+
$this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
18+
new TcpConnector('loop');
19+
}
20+
1521
public function testConstructWithoutLoopAssignsLoopAutomatically()
1622
{
1723
$connector = new TcpConnector();

tests/TcpServerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ public function setUpServer()
2626
$this->port = parse_url($this->server->getAddress(), PHP_URL_PORT);
2727
}
2828

29+
public function testCtorThrowsForInvalidLoop()
30+
{
31+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
32+
new TcpServer(0, 'loop');
33+
}
34+
2935
public function testConstructWithoutLoopAssignsLoopAutomatically()
3036
{
3137
$server = new TcpServer(0);

tests/TimeoutConnectorTest.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99

1010
class TimeoutConnectorTest extends TestCase
1111
{
12+
public function testCtorThrowsForInvalidLoop()
13+
{
14+
$base = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();
15+
16+
$this->setExpectedException('InvalidArgumentException', 'Argument #3 ($loop) expected null|React\EventLoop\LoopInterface');
17+
new TimeoutConnector($base, 0.001, 'loop');
18+
}
19+
1220
public function testConstructWithoutLoopAssignsLoopAutomatically()
1321
{
1422
$base = $this->getMockBuilder('React\Socket\ConnectorInterface')->getMock();

tests/UnixConnectorTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ public function setUpConnector()
1919
$this->connector = new UnixConnector($this->loop);
2020
}
2121

22+
public function testCtorThrowsForInvalidLoop()
23+
{
24+
$this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface');
25+
new UnixConnector('loop');
26+
}
27+
2228
public function testConstructWithoutLoopAssignsLoopAutomatically()
2329
{
2430
$connector = new UnixConnector();

tests/UnixServerTest.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ public function setUpServer()
2929
$this->server = new UnixServer($this->uds);
3030
}
3131

32+
public function testCtorThrowsForInvalidLoop()
33+
{
34+
$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
35+
new UnixServer($this->getRandomSocketUri(), 'loop');
36+
}
37+
3238
public function testConstructWithoutLoopAssignsLoopAutomatically()
3339
{
3440
unlink(str_replace('unix://', '', $this->uds));

0 commit comments

Comments
 (0)
0