diff --git a/src/ApplicationFactory.php b/src/ApplicationFactory.php index 4ef346a..5201817 100644 --- a/src/ApplicationFactory.php +++ b/src/ApplicationFactory.php @@ -1,11 +1,14 @@ createCommand($kernel, $commandName, $commandDescription); @@ -43,7 +46,7 @@ public function createApplication($kernel, $commandName = null, $commandDescript /** * {@inheritdoc} */ - public function createCommand($kernel, $commandName = null, $commandDescription = null) + public function createCommand($kernel, string $commandName = null, string $commandDescription = null): Command { $kernelObject = $this->getKernelObject($kernel); @@ -60,7 +63,7 @@ public function createCommand($kernel, $commandName = null, $commandDescription * * @return KernelInterface The kernel as an object implementing the KernelInterface */ - private function getKernelObject($kernel) + private function getKernelObject($kernel): KernelInterface { if ($kernel instanceof KernelInterface) { return $kernel; diff --git a/src/ApplicationFactoryInterface.php b/src/ApplicationFactoryInterface.php index 3cb5933..f25c54e 100644 --- a/src/ApplicationFactoryInterface.php +++ b/src/ApplicationFactoryInterface.php @@ -1,5 +1,7 @@ options[$option])) { throw new \InvalidArgumentException('Unknown option: '.$option); diff --git a/src/DaemonOptionsInterface.php b/src/DaemonOptionsInterface.php index 7c6dedb..e0cb075 100644 --- a/src/DaemonOptionsInterface.php +++ b/src/DaemonOptionsInterface.php @@ -1,5 +1,7 @@ isShutdown = true; $this->shutdownMessage = (null === $message ? 'Daemon flagged for shutdown' : $message); @@ -51,9 +53,9 @@ public function flagShutdown($message = null) * Loads to configuration from the daemon options and installs signal * handlers. * - * @param DaemonOptions $daemonOptions + * @param DaemonOptionsInterface $daemonOptions */ - private function setupDaemon(DaemonOptions $daemonOptions) + private function setupDaemon(DaemonOptionsInterface $daemonOptions): void { $this->requestCount = 0; $this->requestLimit = $daemonOptions->getOption(DaemonOptions::REQUEST_LIMIT); @@ -74,7 +76,7 @@ private function setupDaemon(DaemonOptions $daemonOptions) * * @param int[] $statusCodes The status codes of sent responses */ - private function considerStatusCodes($statusCodes) + private function considerStatusCodes(array $statusCodes): void { $this->requestCount += count($statusCodes); @@ -94,7 +96,7 @@ private function considerStatusCodes($statusCodes) * * @throws ShutdownException On receiving a SIGINT or SIGALRM */ - private function installSignalHandlers() + private function installSignalHandlers(): void { declare (ticks = 1); @@ -114,7 +116,7 @@ private function installSignalHandlers() * * @throws ShutdownException When limits in the daemon options are exceeded */ - private function checkDaemonLimits() + private function checkDaemonLimits(): void { if ($this->isShutdown) { throw new ShutdownException($this->shutdownMessage); diff --git a/src/Driver/DriverContainer.php b/src/Driver/DriverContainer.php index a7dfb82..4f06e77 100644 --- a/src/Driver/DriverContainer.php +++ b/src/Driver/DriverContainer.php @@ -1,7 +1,11 @@ drivers[$driver])) { throw new \InvalidArgumentException('Unknown driver: '.$driver); diff --git a/src/Driver/DriverContainerInterface.php b/src/Driver/DriverContainerInterface.php index a3168d1..1c216ad 100644 --- a/src/Driver/DriverContainerInterface.php +++ b/src/Driver/DriverContainerInterface.php @@ -1,5 +1,7 @@ close(); @@ -49,7 +51,7 @@ protected function createExceptionFromLastError($function) /** * {@inheritdoc} */ - public function read($length) + public function read(int $length): string { if ($this->isClosed()) { throw new ConnectionException('Connection has been closed'); @@ -71,7 +73,7 @@ public function read($length) /** * {@inheritdoc} */ - public function write($buffer) + public function write(string $buffer): void { if ($this->isClosed()) { throw new ConnectionException('Connection has been closed'); @@ -85,7 +87,7 @@ public function write($buffer) /** * {@inheritdoc} */ - public function isClosed() + public function isClosed(): bool { return $this->closed; } @@ -93,7 +95,7 @@ public function isClosed() /** * {@inheritdoc} */ - public function close() + public function close(): void { if (!$this->isClosed()) { fclose($this->socket); diff --git a/src/Driver/Userland/Connection/StreamSocketConnectionPool.php b/src/Driver/Userland/Connection/StreamSocketConnectionPool.php index 61d4ff9..a872bff 100644 --- a/src/Driver/Userland/Connection/StreamSocketConnectionPool.php +++ b/src/Driver/Userland/Connection/StreamSocketConnectionPool.php @@ -1,5 +1,7 @@ serverSocket = $socket; $this->clientSockets = []; @@ -47,7 +49,7 @@ public function __construct($socket) /** * {@inheritdoc} */ - public function getReadableConnections($timeout) + public function getReadableConnections(int $timeout): array { $this->removeClosedConnections(); @@ -76,7 +78,7 @@ public function getReadableConnections($timeout) /** * {@inheritdoc} */ - public function count() + public function count(): int { $this->removeClosedConnections(); @@ -86,7 +88,7 @@ public function count() /** * {@inheritdoc} */ - public function shutdown() + public function shutdown(): void { $this->shutdown = true; } @@ -94,7 +96,7 @@ public function shutdown() /** * {@inheritdoc} */ - public function close() + public function close(): void { $this->removeClosedConnections(); @@ -115,7 +117,7 @@ public function close() * @param resource[] $readSockets The sockets to test for readability (output parameter) * @param int $timeout The stream select call timeout */ - private function selectConnections(&$readSockets, $timeout) + private function selectConnections(&$readSockets, int $timeout): void { // stream_select will not always preserve array keys // call it with a (deep) copy so the original is preserved @@ -145,12 +147,12 @@ private function selectConnections(&$readSockets, $timeout) /** * Accept incoming connections from the server stream socket. */ - private function acceptConnection() + private function acceptConnection(): void { $clientSocket = @stream_socket_accept($this->serverSocket); if (false !== $clientSocket) { - stream_set_blocking($clientSocket, 0); + stream_set_blocking($clientSocket, false); $connection = new StreamSocketConnection($clientSocket); @@ -161,10 +163,7 @@ private function acceptConnection() } } - /** - * Remove connections. - */ - private function removeClosedConnections() + private function removeClosedConnections(): void { foreach ($this->connections as $id => $connection) { if ($connection->isClosed()) { diff --git a/src/Driver/Userland/ConnectionHandler/ConnectionHandler.php b/src/Driver/Userland/ConnectionHandler/ConnectionHandler.php index 50b637d..4c4368a 100644 --- a/src/Driver/Userland/ConnectionHandler/ConnectionHandler.php +++ b/src/Driver/Userland/ConnectionHandler/ConnectionHandler.php @@ -1,5 +1,7 @@ connection->read(self::READ_LENGTH); @@ -85,10 +87,10 @@ public function ready() $statusCodes = []; - while (null !== ($record = $this->readRecord())) { + while (!empty($record = $this->readRecord())) { $statusCode = $this->processRecord($record); - if (null != $statusCode) { + if (null !== $statusCode) { $statusCodes[] = $statusCode; } } @@ -104,7 +106,7 @@ public function ready() /** * {@inheritdoc} */ - public function shutdown() + public function shutdown(): void { $this->shutdown = true; } @@ -112,7 +114,7 @@ public function shutdown() /** * {@inheritdoc} */ - public function close() + public function close(): void { $this->buffer = null; $this->bufferLength = 0; @@ -131,7 +133,7 @@ public function close() /** * {@inheritdoc} */ - public function isClosed() + public function isClosed(): bool { return $this->closed; } @@ -142,13 +144,13 @@ public function isClosed() /** * Read a record from the connection. * - * @return array|null The record that has been read + * @return array The record that has been read */ - private function readRecord() + private function readRecord(): array { // Not enough data to read header if ($this->bufferLength < 8) { - return; + return []; } $headerData = substr($this->buffer, 0, 8); @@ -159,7 +161,7 @@ private function readRecord() // Not enough data to read rest of record if ($this->bufferLength - 8 < $record['contentLength'] + $record['paddingLength']) { - return; + return []; } $record['contentData'] = substr($this->buffer, 8, $record['contentLength']); @@ -178,11 +180,11 @@ private function readRecord() * * @param array $record The record that has been read * - * @return int Number of dispatched requests + * @return null|int Number of dispatched requests * * @throws ProtocolException If the client sends an unexpected record. */ - private function processRecord(array $record) + private function processRecord(array $record): ?int { $requestId = $record['requestId']; @@ -193,7 +195,7 @@ private function processRecord(array $record) } elseif (!isset($this->requests[$requestId])) { throw new ProtocolException('Invalid request id for record of type: '.$record['type']); } elseif (DaemonInterface::FCGI_PARAMS === $record['type']) { - while (strlen($content) > 0) { + while (null !== $content && strlen($content) > 0) { $this->readNameValuePair($requestId, $content); } } elseif (DaemonInterface::FCGI_STDIN === $record['type']) { @@ -216,11 +218,11 @@ private function processRecord(array $record) * Process a FCGI_BEGIN_REQUEST record. * * @param int $requestId The request id sending the record - * @param string $contentData The content of the record + * @param null|string $contentData The content of the record * * @throws ProtocolException If the FCGI_BEGIN_REQUEST record is unexpected */ - private function processBeginRequestRecord($requestId, $contentData) + private function processBeginRequestRecord(int $requestId, ?string $contentData): void { if (isset($this->requests[$requestId])) { throw new ProtocolException('Unexpected FCGI_BEGIN_REQUEST record'); @@ -255,9 +257,9 @@ private function processBeginRequestRecord($requestId, $contentData) * Read a FastCGI name-value pair from a buffer and add it to the request params. * * @param int $requestId The request id that sent the name-value pair - * @param string $buffer The buffer to read the pair from (pass by reference) + * @param null|string $buffer The buffer to read the pair from (pass by reference) */ - private function readNameValuePair($requestId, &$buffer) + private function readNameValuePair(int $requestId, ?string &$buffer): void { $nameLength = $this->readFieldLength($buffer); $valueLength = $this->readFieldLength($buffer); @@ -280,7 +282,7 @@ private function readNameValuePair($requestId, &$buffer) * * @return int The length of the field */ - private function readFieldLength(&$buffer) + private function readFieldLength(string &$buffer): int { $block = unpack('C4', $buffer); @@ -306,7 +308,7 @@ private function readFieldLength(&$buffer) * @param int $appStatus The application status to declare * @param int $protocolStatus The protocol status to declare */ - private function endRequest($requestId, $appStatus = 0, $protocolStatus = DaemonInterface::FCGI_REQUEST_COMPLETE) + private function endRequest(int $requestId, int $appStatus = 0, int $protocolStatus = DaemonInterface::FCGI_REQUEST_COMPLETE): void { $content = pack('NCx3', $appStatus, $protocolStatus); $this->writeRecord($requestId, DaemonInterface::FCGI_END_REQUEST, $content); @@ -329,7 +331,7 @@ private function endRequest($requestId, $appStatus = 0, $protocolStatus = Daemon * @param int $type The type of record * @param string $content The content of the record */ - private function writeRecord($requestId, $type, $content = null) + private function writeRecord(int $requestId, int $type, string $content = null): void { $contentLength = null === $content ? 0 : strlen($content); @@ -349,7 +351,7 @@ private function writeRecord($requestId, $type, $content = null) * @param string $headerData The header -data to write (including terminating CRLFCRLF) * @param resource $stream The stream to write */ - private function writeResponse($requestId, $headerData, $stream) + private function writeResponse(int $requestId, string $headerData, $stream): void { $data = $headerData; $eof = false; @@ -380,9 +382,11 @@ private function writeResponse($requestId, $headerData, $stream) * * @param int $requestId The request id that is ready to dispatch * + * @return int status code from the response. + * * @throws \LogicException If the kernel doesn't return a valid response */ - private function dispatchRequest($requestId) + private function dispatchRequest(int $requestId): int { $request = new Request( $this->requests[$requestId]['params'], @@ -415,7 +419,7 @@ private function dispatchRequest($requestId) * @param int $requestId The request id to respond to * @param ResponseInterface $response The PSR-7 HTTP response message */ - private function sendResponse($requestId, ResponseInterface $response) + private function sendResponse(int $requestId, ResponseInterface $response): void { $statusCode = $response->getStatusCode(); $reasonPhrase = $response->getReasonPhrase(); @@ -437,7 +441,7 @@ private function sendResponse($requestId, ResponseInterface $response) * @param int $requestId The request id to respond to * @param HttpFoundationResponse $response The HTTP foundation response message */ - private function sendHttpFoundationResponse($requestId, HttpFoundationResponse $response) + private function sendHttpFoundationResponse(int $requestId, HttpFoundationResponse $response): void { $statusCode = $response->getStatusCode(); diff --git a/src/Driver/Userland/ConnectionHandler/ConnectionHandlerFactory.php b/src/Driver/Userland/ConnectionHandler/ConnectionHandlerFactory.php index c88e7bf..81dfca2 100644 --- a/src/Driver/Userland/ConnectionHandler/ConnectionHandlerFactory.php +++ b/src/Driver/Userland/ConnectionHandler/ConnectionHandlerFactory.php @@ -1,5 +1,7 @@ setupDaemon($this->daemonOptions); $this->daemonOptions->getOption(DaemonOptions::LOGGER)->notice('Daemon is running and ready to accept connections'); @@ -93,8 +96,10 @@ public function run() * Wait for connections in the pool to become readable. Create connection * handlers for new connections and trigger the ready method when there is * data for the handlers to receive. Clean up closed connections. + * + * @throws \Exception */ - private function processConnectionPool() + private function processConnectionPool(): void { $readableConnections = $this->connectionPool->getReadableConnections(5); @@ -118,8 +123,10 @@ private function processConnectionPool() /** * Gracefully shutdown the daemon. + * + * @throws \Exception */ - private function shutdown() + private function shutdown(): void { $this->connectionPool->shutdown(); diff --git a/src/Driver/Userland/UserlandDaemonFactory.php b/src/Driver/Userland/UserlandDaemonFactory.php index 964b482..7393424 100644 --- a/src/Driver/Userland/UserlandDaemonFactory.php +++ b/src/Driver/Userland/UserlandDaemonFactory.php @@ -1,5 +1,7 @@ params; } @@ -108,7 +111,7 @@ public static function getUploadDir(): string /** * {@inheritdoc} */ - public function getQuery() + public function getQuery(): array { $query = null; @@ -122,7 +125,7 @@ public function getQuery() /** * {@inheritdoc} */ - public function getPost() + public function getPost(): array { $post = null; @@ -150,7 +153,7 @@ public function getPost() return $post ?: []; } - private function parseMultipartFormData($stream, $boundary) { + private function parseMultipartFormData($stream, string $boundary): array { $post = ""; $files = []; $fieldType = $fieldName = $filename = $mimeType = null; @@ -208,7 +211,7 @@ private function parseMultipartFormData($stream, $boundary) { /** * {@inheritdoc} */ - public function getCookies() + public function getCookies(): array { $cookies = []; @@ -235,7 +238,7 @@ public function getStdin() /** * {@inheritdoc} */ - public function getServerRequest() + public function getServerRequest(): ServerRequestInterface { if (null === self::$serverRequestCreator) { throw new \RuntimeException('You need to add an object of \Nyholm\Psr7Server\ServerRequestCreatorInterface to \PHPFastCGI\FastCGIDaemon\Http\Request::setServerRequestCreator to use PSR-7 requests. Please install and read more at https://github.com/nyholm/psr7-server'); @@ -262,7 +265,7 @@ public function getServerRequest() /** * {@inheritdoc} */ - public function getHttpFoundationRequest() + public function getHttpFoundationRequest(): HttpFoundationRequest { if (!class_exists(HttpFoundationRequest::class)) { throw new \RuntimeException('You need to install symfony/http-foundation:^4.0 to use HttpFoundation requests.'); diff --git a/src/Http/RequestInterface.php b/src/Http/RequestInterface.php index e03c75f..4bfa020 100644 --- a/src/Http/RequestInterface.php +++ b/src/Http/RequestInterface.php @@ -1,5 +1,7 @@ expectException(\InvalidArgumentException::class); + $this->expectException(\TypeError::class); new CallbackKernel('not a callable function'); } diff --git a/test/Helper/Mocker/Driver/Connection/MockConnection.php b/test/Helper/Mocker/Driver/Connection/MockConnection.php index 58b8baf..98d45f6 100644 --- a/test/Helper/Mocker/Driver/Connection/MockConnection.php +++ b/test/Helper/Mocker/Driver/Connection/MockConnection.php @@ -9,23 +9,23 @@ class MockConnection implements ConnectionInterface { use MockerTrait; - public function read($length) + public function read(int $length): string { - return $this->delegateCall('read', func_get_args()); + $this->delegateCall('read', func_get_args()); } - public function write($buffer) + public function write(string $buffer): void { - return $this->delegateCall('write', func_get_args()); + $this->delegateCall('write', func_get_args()); } - public function isClosed() + public function isClosed(): bool { return $this->delegateCall('isClosed', func_get_args()); } - public function close() + public function close(): void { - return $this->delegateCall('close', func_get_args()); + $this->delegateCall('close', func_get_args()); } } diff --git a/test/Helper/Mocker/Driver/Connection/MockConnectionPool.php b/test/Helper/Mocker/Driver/Connection/MockConnectionPool.php index 12cb53e..a8a835d 100644 --- a/test/Helper/Mocker/Driver/Connection/MockConnectionPool.php +++ b/test/Helper/Mocker/Driver/Connection/MockConnectionPool.php @@ -9,23 +9,23 @@ class MockConnectionPool implements ConnectionPoolInterface { use MockerTrait; - public function getReadableConnections($timeout) + public function getReadableConnections(int $timeout): array { return $this->delegateCall('getReadableConnections', func_get_args()); } - public function count() + public function count(): int { return $this->delegateCall('count', func_get_args()); } - public function shutdown() + public function shutdown(): void { - return $this->delegateCall('shutdown', func_get_args()); + $this->delegateCall('shutdown', func_get_args()); } - public function close() + public function close(): void { - return $this->delegateCall('close', func_get_args()); + $this->delegateCall('close', func_get_args()); } } diff --git a/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandler.php b/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandler.php index d224d28..3c6e792 100644 --- a/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandler.php +++ b/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandler.php @@ -9,22 +9,22 @@ class MockConnectionHandler implements ConnectionHandlerInterface { use MockerTrait; - public function ready() + public function ready(): array { return $this->delegateCall('ready', func_get_args()); } - public function shutdown() + public function shutdown(): void { - return $this->delegateCall('shutdown', func_get_args()); + $this->delegateCall('shutdown', func_get_args()); } - public function close() + public function close(): void { - return $this->delegateCall('close', func_get_args()); + $this->delegateCall('close', func_get_args()); } - public function isClosed() + public function isClosed(): bool { return $this->delegateCall('isClosed', func_get_args()); } diff --git a/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandlerFactory.php b/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandlerFactory.php index 1bb4f84..51e094a 100644 --- a/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandlerFactory.php +++ b/test/Helper/Mocker/Driver/ConnectionHandler/MockConnectionHandlerFactory.php @@ -2,6 +2,7 @@ namespace PHPFastCGI\Test\FastCGIDaemon\Helper\Mocker\Driver\ConnectionHandler; +use PHPFastCGI\FastCGIDaemon\Driver\Userland\ConnectionHandler\ConnectionHandlerInterface; use PHPFastCGI\FastCGIDaemon\KernelInterface; use PHPFastCGI\FastCGIDaemon\Driver\Userland\Connection\ConnectionInterface; use PHPFastCGI\FastCGIDaemon\Driver\Userland\ConnectionHandler\ConnectionHandlerFactoryInterface; @@ -11,7 +12,7 @@ class MockConnectionHandlerFactory implements ConnectionHandlerFactoryInterface { use MockerTrait; - public function createConnectionHandler(KernelInterface $kernel, ConnectionInterface $connection) + public function createConnectionHandler(KernelInterface $kernel, ConnectionInterface $connection): ConnectionHandlerInterface { return $this->delegateCall('createConnectionHandler', func_get_args()); } diff --git a/test/Helper/Mocker/Driver/MockDriverContainer.php b/test/Helper/Mocker/Driver/MockDriverContainer.php index 7536022..c431a24 100644 --- a/test/Helper/Mocker/Driver/MockDriverContainer.php +++ b/test/Helper/Mocker/Driver/MockDriverContainer.php @@ -2,6 +2,7 @@ namespace PHPFastCGI\Test\FastCGIDaemon\Helper\Mocker\Driver; +use PHPFastCGI\FastCGIDaemon\DaemonFactoryInterface; use PHPFastCGI\FastCGIDaemon\Driver\DriverContainerInterface; use PHPFastCGI\Test\FastCGIDaemon\Helper\Mocker\MockerTrait; @@ -9,7 +10,7 @@ class MockDriverContainer implements DriverContainerInterface { use MockerTrait; - public function getFactory($driver) + public function getFactory(string $driver): DaemonFactoryInterface { return $this->delegateCall('getFactory', func_get_args()); } diff --git a/test/Helper/Mocker/MockDaemon.php b/test/Helper/Mocker/MockDaemon.php index 8f3ca73..07c0a6c 100644 --- a/test/Helper/Mocker/MockDaemon.php +++ b/test/Helper/Mocker/MockDaemon.php @@ -8,13 +8,13 @@ class MockDaemon implements DaemonInterface { use MockerTrait; - public function run() + public function run(): void { - return $this->delegateCall('run', func_get_args()); + $this->delegateCall('run', func_get_args()); } - public function flagShutdown($message = null) + public function flagShutdown(string $message = null): void { - return $this->delegateCall('flagShutdown', func_get_args()); + $this->delegateCall('flagShutdown', func_get_args()); } } diff --git a/test/Helper/Mocker/MockDaemonFactory.php b/test/Helper/Mocker/MockDaemonFactory.php index 578164c..3343087 100644 --- a/test/Helper/Mocker/MockDaemonFactory.php +++ b/test/Helper/Mocker/MockDaemonFactory.php @@ -11,12 +11,12 @@ class MockDaemonFactory implements DaemonFactoryInterface { use MockerTrait; - public function createDaemon(KernelInterface $kernel, DaemonOptions $options, $fd = DaemonInterface::FCGI_LISTENSOCK_FILENO) + public function createDaemon(KernelInterface $kernel, DaemonOptions $options, int $fd = DaemonInterface::FCGI_LISTENSOCK_FILENO): DaemonInterface { return $this->delegateCall('createDaemon', func_get_args()); } - public function createTcpDaemon(KernelInterface $kernel, DaemonOptions $options, $port, $host = 'localhost') + public function createTcpDaemon(KernelInterface $kernel, DaemonOptions $options, string $host = 'localhost', int $port): DaemonInterface { return $this->delegateCall('createTcpDaemon', func_get_args()); } diff --git a/test/Helper/Mocker/MockerTrait.php b/test/Helper/Mocker/MockerTrait.php index 8f0957b..30a4d0b 100644 --- a/test/Helper/Mocker/MockerTrait.php +++ b/test/Helper/Mocker/MockerTrait.php @@ -41,7 +41,7 @@ public function __construct(array $callbacks = null) * * @throws \InvalidArgumentException When no callback is set for the method */ - protected function delegateCall($method, $arguments) + protected function delegateCall(string $method, array $arguments) { if (!isset($this->callbacks[$method])) { throw new \InvalidArgumentException('Method not configured: '.$method); @@ -61,7 +61,7 @@ protected function delegateCall($method, $arguments) * * @return array The delegated call list */ - public function getDelegatedCalls() + public function getDelegatedCalls(): array { return $this->delegatedCalls; }