Skip to content

Commit

Permalink
Merge pull request #179 from clue-labs/nullable-v1
Browse files Browse the repository at this point in the history
[1.x] Improve PHP 8.4+ support by avoiding implicitly nullable types
  • Loading branch information
WyriHaximus committed May 19, 2024
2 parents 78a6ea5 + 37fa61d commit d258e40
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 3 deletions.
15 changes: 14 additions & 1 deletion src/DuplexResourceStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ final class DuplexResourceStream extends EventEmitter implements DuplexStreamInt
private $closing = false;
private $listening = false;

public function __construct($stream, LoopInterface $loop = null, $readChunkSize = null, WritableStreamInterface $buffer = null)
/**
* @param resource $stream
* @param ?LoopInterface $loop
* @param ?int $readChunkSize
* @param ?WritableStreamInterface $buffer
*/
public function __construct($stream, $loop = null, $readChunkSize = null, $buffer = null)
{
if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
throw new InvalidArgumentException('First parameter must be a valid stream resource');
Expand All @@ -56,6 +62,13 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize
throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
}

if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
}
if ($buffer !== null && !$buffer instanceof WritableStreamInterface) { // manual type check to support legacy PHP < 7.1
throw new \InvalidArgumentException('Argument #4 ($buffer) expected null|React\Stream\WritableStreamInterface');
}

// Use unbuffered read operations on the underlying stream resource.
// Reading chunks from the stream may otherwise leave unread bytes in
// PHP's stream buffers which some event loop implementations do not
Expand Down
11 changes: 10 additions & 1 deletion src/ReadableResourceStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ final class ReadableResourceStream extends EventEmitter implements ReadableStrea
private $closed = false;
private $listening = false;

public function __construct($stream, LoopInterface $loop = null, $readChunkSize = null)
/**
* @param resource $stream
* @param ?LoopInterface $loop
* @param ?int $readChunkSize
*/
public function __construct($stream, $loop = null, $readChunkSize = null)
{
if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
throw new InvalidArgumentException('First parameter must be a valid stream resource');
Expand All @@ -58,6 +63,10 @@ public function __construct($stream, LoopInterface $loop = null, $readChunkSize
throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
}

if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
}

// Use unbuffered read operations on the underlying stream resource.
// Reading chunks from the stream may otherwise leave unread bytes in
// PHP's stream buffers which some event loop implementations do not
Expand Down
12 changes: 11 additions & 1 deletion src/WritableResourceStream.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@ final class WritableResourceStream extends EventEmitter implements WritableStrea
private $closed = false;
private $data = '';

public function __construct($stream, LoopInterface $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null)
/**
* @param resource $stream
* @param ?LoopInterface $loop
* @param ?int $writeBufferSoftLimit
* @param ?int $writeChunkSize
*/
public function __construct($stream, $loop = null, $writeBufferSoftLimit = null, $writeChunkSize = null)
{
if (!\is_resource($stream) || \get_resource_type($stream) !== "stream") {
throw new \InvalidArgumentException('First parameter must be a valid stream resource');
Expand All @@ -46,6 +52,10 @@ public function __construct($stream, LoopInterface $loop = null, $writeBufferSof
throw new \RuntimeException('Unable to set stream resource to non-blocking mode');
}

if ($loop !== null && !$loop instanceof LoopInterface) { // manual type check to support legacy PHP < 7.1
throw new \InvalidArgumentException('Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
}

$this->stream = $stream;
$this->loop = $loop ?: Loop::get();
$this->softLimit = ($writeBufferSoftLimit === null) ? 65536 : (int)$writeBufferSoftLimit;
Expand Down
16 changes: 16 additions & 0 deletions tests/DuplexResourceStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking(
new DuplexResourceStream($stream, $loop);
}

public function testContructorThrowsExceptionForInvalidLoop()
{
$stream = fopen('php://temp', 'r+');

$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
new DuplexResourceStream($stream, 42);
}

public function testContructorThrowsExceptionForInvalidBuffer()
{
$stream = fopen('php://temp', 'r+');

$this->setExpectedException('InvalidArgumentException', 'Argument #4 ($buffer) expected null|React\Stream\WritableStreamInterface');
new DuplexResourceStream($stream, null, null, 42);
}

/**
* @covers React\Stream\DuplexResourceStream::__construct
* @doesNotPerformAssertions
Expand Down
7 changes: 7 additions & 0 deletions tests/ReadableResourceStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,13 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking(
new ReadableResourceStream($stream, $loop);
}

public function testContructorThrowsExceptionForInvalidLoop()
{
$stream = fopen('php://temp', 'r+');

$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
new ReadableResourceStream($stream, 42);
}

public function testCloseShouldEmitCloseEvent()
{
Expand Down
8 changes: 8 additions & 0 deletions tests/WritableResourceStreamTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ public function testConstructorThrowsExceptionIfStreamDoesNotSupportNonBlocking(
new WritableResourceStream($stream, $loop);
}

public function testContructorThrowsExceptionForInvalidLoop()
{
$stream = fopen('php://temp', 'r+');

$this->setExpectedException('InvalidArgumentException', 'Argument #2 ($loop) expected null|React\EventLoop\LoopInterface');
new WritableResourceStream($stream, 42);
}

/**
* @covers React\Stream\WritableResourceStream::write
* @covers React\Stream\WritableResourceStream::handleWrite
Expand Down

0 comments on commit d258e40

Please sign in to comment.