From ac939448c939c455ff4125c20580ebd1f228dd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=BCck?= Date: Sat, 1 Jun 2024 16:06:25 +0200 Subject: [PATCH] Improve PHP 8.4+ support by avoiding implicitly nullable types --- composer.json | 6 +++--- src/Factory.php | 9 ++++++++- src/Socket.php | 11 ++++++++++- tests/FactoryTest.php | 12 ++++++++++++ tests/SocketTest.php | 9 +++++++++ 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index 9db659b..a1d12d7 100644 --- a/composer.json +++ b/composer.json @@ -29,13 +29,13 @@ "require": { "php": ">=5.3", "evenement/evenement": "^3.0 || ^2.0 || ^1.0", - "react/dns": "^1.7", + "react/dns": "^1.13", "react/event-loop": "^1.2", - "react/promise": "^3 || ^2.1 || ^1.2" + "react/promise": "^3.2 || ^2.1 || ^1.2" }, "require-dev": { "phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36", - "react/async": "^4 || ^3 || ^2" + "react/async": "^4.3 || ^3 || ^2" }, "autoload": { "psr-4": { diff --git a/src/Factory.php b/src/Factory.php index 89586a6..d7836d7 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -29,8 +29,15 @@ class Factory * try to load the system default DNS config or fall back to using * Google's public DNS 8.8.8.8 */ - public function __construct(LoopInterface $loop = null, ResolverInterface $resolver = null) + public function __construct($loop = null, $resolver = null) { + if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + } + if ($resolver !== null && !$resolver instanceof ResolverInterface) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #2 ($resolver) expected null|React\Dns\Resolver\ResolverInterface'); + } + $loop = $loop ?: Loop::get(); if ($resolver === null) { // try to load nameservers from system config or default to Google's public DNS diff --git a/src/Socket.php b/src/Socket.php index e06723c..465154c 100644 --- a/src/Socket.php +++ b/src/Socket.php @@ -15,8 +15,17 @@ class Socket extends EventEmitter implements SocketInterface public $bufferSize = 65536; - public function __construct(LoopInterface $loop, $socket, Buffer $buffer = null) + /** + * @param LoopInterface $loop + * @param resource $socket + * @param ?Buffer $buffer + */ + public function __construct(LoopInterface $loop, $socket, $buffer = null) { + if ($buffer !== null && !$buffer instanceof Buffer) { // manual type check to support legacy PHP < 7.1 + throw new \InvalidArgumentException('Argument #3 ($buffer) expected null|React\Datagram\Buffer'); + } + $this->loop = $loop; $this->socket = $socket; diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 228ab6d..e8df249 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -33,6 +33,18 @@ public function testConstructWithoutLoopAssignsLoopAutomatically() $this->assertInstanceOf('React\EventLoop\LoopInterface', $loop); } + public function testCtorThrowsForInvalidLoop() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #1 ($loop) expected null|React\EventLoop\LoopInterface'); + new Factory('loop'); + } + + public function testCtorThrowsForInvalidResolver() + { + $this->setExpectedException('InvalidArgumentException', 'Argument #2 ($resolver) expected null|React\Dns\Resolver\ResolverInterface'); + new Factory(null, 'resolver'); + } + public function testCreateClient() { $this->resolver->expects($this->never())->method('resolve'); diff --git a/tests/SocketTest.php b/tests/SocketTest.php index bdc82f5..f728670 100644 --- a/tests/SocketTest.php +++ b/tests/SocketTest.php @@ -18,6 +18,15 @@ public function setUpFactory() $this->factory = new \React\Datagram\Factory($this->loop, $this->createResolverMock()); } + public function testCtorThrowsForInvalidBuffer() + { + $socket = stream_socket_server('udp://127.0.0.1:0', $errno, $errstr, STREAM_SERVER_BIND); + assert(is_resource($socket)); + + $this->setExpectedException('InvalidArgumentException', 'Argument #3 ($buffer) expected null|React\Datagram\Buffer'); + new Socket($this->loop, $socket, 'buffer'); + } + /** * @doesNotPerformAssertions */