From 08d6bf2099bb3ec67c00070d50d4e51e72ab6d23 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Thu, 3 Nov 2022 16:18:00 +0100 Subject: [PATCH 01/13] install phpstan --- composer.json | 3 ++- composer.lock | 63 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 1a363d0..35f4f6e 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "php": "^7.3|^8.0" }, "require-dev": { - "phpunit/phpunit": "^7.0|^9.0" + "phpunit/phpunit": "^7.0|^9.0", + "phpstan/phpstan": "^1.9" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 433ba8e..c7c50a1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "65d3bddfa41df1edbdedfcf7a8ba5028", + "content-hash": "df403c6432b8e7aabec45e7967153537", "packages": [], "packages-dev": [ { @@ -283,6 +283,65 @@ "description": "Library for handling version information and constraints", "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.9.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e08de53a5eec983de78a787a88e72518cf8fe43a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e08de53a5eec983de78a787a88e72518cf8fe43a", + "reference": "e08de53a5eec983de78a787a88e72518cf8fe43a", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.9.0" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-11-03T07:26:48+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.18", @@ -1635,5 +1694,5 @@ "php": "^7.3|^8.0" }, "platform-dev": [], - "plugin-api-version": "1.1.0" + "plugin-api-version": "2.3.0" } From ce3ed9f77ae699a1d21223c4a0bca2ef17183489 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 13 Nov 2022 13:56:43 +0100 Subject: [PATCH 02/13] excluse .vscode --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0f0b5c2..64ea464 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ vendor/* .idea/* .phpunit.result.cache coverage.xml -.DS_Store \ No newline at end of file +.DS_Store +.vscode/* From 752511132da08cb8a463a07f59f215fb08815447 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 13 Nov 2022 14:42:56 +0100 Subject: [PATCH 03/13] exclude /var --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 64ea464..b775214 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ vendor/* coverage.xml .DS_Store .vscode/* +var/* From 1a74c927bab52aea034cf1cf5a9a7931e0436f20 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 13 Nov 2022 14:44:13 +0100 Subject: [PATCH 04/13] check the read result before constructing the response --- src/Client.php | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Client.php b/src/Client.php index 5b5b235..f7b446a 100644 --- a/src/Client.php +++ b/src/Client.php @@ -53,7 +53,22 @@ public function send(CommandInterface $command): ResponseInterface */ public function read(): ResponseInterface { - $message = explode("\r\n", fgets($this->resource))[0]; + if (!$this->resource) { + throw new ConnectionException(); + } + + $string = fgets($this->resource); + + if($string === false) { + throw new \RuntimeException("Unable to read from stream"); + } + + if(empty($string)) { + throw new \RuntimeException("Read empty string from stream"); + } + + $message = explode("\r\n", $string)[0]; + return new SonicResponse($message); } @@ -61,7 +76,7 @@ public function read(): ResponseInterface * @throws ConnectionException * connects to the socket */ - public function connect() + public function connect():void { if (!$this->resource = stream_socket_client("tcp://{$this->host}:{$this->port}", $this->errorNo, $this->errorMessage, $this->maxTimeout)) { throw new ConnectionException(); From ed164e6ebcab3fe79db18b7696066fd855fbc41a Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 13 Nov 2022 16:47:56 +0100 Subject: [PATCH 05/13] type hints and close the resource after socket shutdown --- src/Client.php | 37 ++++++++++++++++++++++++------------- tests/Unit/ClientTest.php | 5 ++++- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/Client.php b/src/Client.php index f7b446a..3d2ff8b 100644 --- a/src/Client.php +++ b/src/Client.php @@ -6,15 +6,22 @@ use Psonic\Contracts\Client as ClientInterface; use Psonic\Contracts\Command as CommandInterface; use Psonic\Contracts\Response as ResponseInterface; +use TypeError; class Client implements ClientInterface { + /** @var resource $resource */ private $resource; + /** @var string */ private $host; + /** @var int */ private $port; + /** @var int|null */ private $errorNo; + /** @var string */ private $errorMessage; + /** @var int */ private $maxTimeout; /** @@ -39,11 +46,12 @@ public function __construct($host = 'localhost', $port = 1491, $timeout = 30) */ public function send(CommandInterface $command): ResponseInterface { - if (!$this->resource) { - throw new ConnectionException(); + try { + fwrite($this->resource, $command); + }catch (TypeError $e) { + throw new ConnectionException("Not connected to sonic. " . $e->getMessage()); } - fwrite($this->resource, $command); return $this->read(); } @@ -53,10 +61,6 @@ public function send(CommandInterface $command): ResponseInterface */ public function read(): ResponseInterface { - if (!$this->resource) { - throw new ConnectionException(); - } - $string = fgets($this->resource); if($string === false) { @@ -76,20 +80,27 @@ public function read(): ResponseInterface * @throws ConnectionException * connects to the socket */ - public function connect():void + public function connect(): void { - if (!$this->resource = stream_socket_client("tcp://{$this->host}:{$this->port}", $this->errorNo, $this->errorMessage, $this->maxTimeout)) { - throw new ConnectionException(); + $resource = stream_socket_client("tcp://{$this->host}:{$this->port}", $this->errorNo, $this->errorMessage, $this->maxTimeout); + if (!$resource) { + throw new ConnectionException("Unable to connect to sonic search engine with given host: $this->host and port: $this->port}. Error code $this->errorNo with $this->errorMessage was produced"); } + $this->resource = $resource; } /** * Disconnects from a socket */ - public function disconnect() + public function disconnect(): void { - stream_socket_shutdown($this->resource, STREAM_SHUT_WR); - $this->resource = null; + $result = stream_socket_shutdown($this->resource, STREAM_SHUT_WR); + + if(!$result) { + throw new \RuntimeException("Unable to shut down stream socket connection"); + } + + fclose($this->resource); } /** diff --git a/tests/Unit/ClientTest.php b/tests/Unit/ClientTest.php index 9662252..77cd2d7 100644 --- a/tests/Unit/ClientTest.php +++ b/tests/Unit/ClientTest.php @@ -7,9 +7,11 @@ use Psonic\Client; use Psonic\Commands\Misc\PingCommand; +use Psonic\Commands\Search\QueryCommand; use Psonic\Contracts\Command; use Psonic\Contracts\Response; use Psonic\Exceptions\ConnectionException; +use Psonic\Search; use Tests\TestCase; class ClientTest extends TestCase @@ -38,6 +40,7 @@ public function the_client_can_disconnect_from_socket_and_throws_exception_if_co $this->client->connect(); $this->client->disconnect(); $this->expectException(ConnectionException::class); + $this->expectExceptionMessage("Not connected to sonic. fwrite(): supplied resource is not a valid stream resource"); $this->client->send(new PingCommand); } @@ -76,4 +79,4 @@ public function the_client_can_send_a_command_to_sonic_and_returns_a_response_ob $this->assertInstanceOf(Response::class, $this->client->send(new PingCommand)); } -} \ No newline at end of file +} From 14dd00a9f856edf81afd401d46550b6d58b13c98 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 13 Nov 2022 16:57:56 +0100 Subject: [PATCH 06/13] types --- src/Contracts/Client.php | 6 +++--- src/Contracts/Response.php | 5 ++--- src/SonicResponse.php | 6 ++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/Contracts/Client.php b/src/Contracts/Client.php index 322e5ab..b9421a1 100644 --- a/src/Contracts/Client.php +++ b/src/Contracts/Client.php @@ -1,4 +1,4 @@ -pieces[$key])){ return $this->pieces[$key]; @@ -94,4 +93,3 @@ public function getCount():int return $this->get('count') ?? 0; } } - \ No newline at end of file From bacddf7072c44dca13d8856f1a445913c9623c94 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 13 Nov 2022 23:57:48 +0100 Subject: [PATCH 07/13] support php7.4 --- src/Client.php | 16 +++++++++++----- tests/Unit/ClientTest.php | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Client.php b/src/Client.php index 3d2ff8b..52222ac 100644 --- a/src/Client.php +++ b/src/Client.php @@ -6,7 +6,8 @@ use Psonic\Contracts\Client as ClientInterface; use Psonic\Contracts\Command as CommandInterface; use Psonic\Contracts\Response as ResponseInterface; -use TypeError; +use RuntimeException; + class Client implements ClientInterface { @@ -46,10 +47,15 @@ public function __construct($host = 'localhost', $port = 1491, $timeout = 30) */ public function send(CommandInterface $command): ResponseInterface { - try { - fwrite($this->resource, $command); - }catch (TypeError $e) { - throw new ConnectionException("Not connected to sonic. " . $e->getMessage()); + if(!is_resource($this->resource)) { + //Fixme: In php8+ a try catch on fwrite throws a TypeError and catches the case of an empty $this->>resource variable + throw new ConnectionException("Not connected to sonic. Empty stream given ". var_export($this->resource, true)); + } + + $result = fwrite($this->resource, $command); + + if($result === false) { + throw new RuntimeException("Unable to write to stream"); } return $this->read(); diff --git a/tests/Unit/ClientTest.php b/tests/Unit/ClientTest.php index 77cd2d7..19f334a 100644 --- a/tests/Unit/ClientTest.php +++ b/tests/Unit/ClientTest.php @@ -40,7 +40,7 @@ public function the_client_can_disconnect_from_socket_and_throws_exception_if_co $this->client->connect(); $this->client->disconnect(); $this->expectException(ConnectionException::class); - $this->expectExceptionMessage("Not connected to sonic. fwrite(): supplied resource is not a valid stream resource"); + $this->expectExceptionMessage("Not connected to sonic. Empty stream given NULL"); $this->client->send(new PingCommand); } From 9a0871f76b000f1bdf7e50be68b53901afd7b8db Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 11 Dec 2022 17:13:40 +0100 Subject: [PATCH 08/13] run phpstan during test --- .github/workflows/tests.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index da107c5..34b2a0b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,7 +1,7 @@ on: [push, pull_request] jobs: - run: + run: runs-on: ${{ matrix.operating-system }} strategy: matrix: @@ -31,3 +31,5 @@ jobs: with: files: ./coverage.xml verbose: true + - name: Run phpstan + run: ./vendor/bin/phpstan --level=max analyse src From 8d50eac70c2bc0d6111bb596f895723ac4637579 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 11 Dec 2022 17:14:03 +0100 Subject: [PATCH 09/13] support php 8 and typehints on abstract command --- .github/workflows/tests.yml | 2 +- composer.json | 2 +- src/Commands/Command.php | 15 +++++++++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 34b2a0b..4ed432e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -6,7 +6,7 @@ jobs: strategy: matrix: operating-system: [ubuntu-latest] - php-versions: ['7.3', '7.4', '8.0'] + php-versions: ['8.0', '8.1', '8.2'] name: PHP ${{ matrix.php-versions }} Test on ${{ matrix.operating-system }} steps: - name: Checkout diff --git a/composer.json b/composer.json index 35f4f6e..7ffb8a2 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "search engine" ], "require": { - "php": "^7.3|^8.0" + "php": "^8.0" }, "require-dev": { "phpunit/phpunit": "^7.0|^9.0", diff --git a/src/Commands/Command.php b/src/Commands/Command.php index e3a32fa..b8f3991 100644 --- a/src/Commands/Command.php +++ b/src/Commands/Command.php @@ -6,10 +6,16 @@ abstract class Command implements CommandInterface { - private $command; - private $parameters; + private string $command; + /** + * @var array + */ + private array $parameters; - public function __construct($command, $parameters = []) + /** + * @param array $parameters + */ + public function __construct(string $command, array $parameters = []) { $this->command = $command; $this->parameters = $parameters; @@ -18,8 +24,9 @@ public function __construct($command, $parameters = []) /** * Wrap the string in quotes, and normalize whitespace. Also remove double quotes. */ - protected function wrapInQuotes($string) + protected function wrapInQuotes(string $string):string { + /** @var string $string */ $string = preg_replace('/[\r\n\t"]/', ' ', $string); $string = '"' . str_replace('"', '\"', $string) . '"'; return $string; From 7f019bcf55f2d48e56c951adb66bc1f938182dff Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 11 Dec 2022 17:17:22 +0100 Subject: [PATCH 10/13] enable xdebug --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 4ed432e..a3fa330 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -32,4 +32,4 @@ jobs: files: ./coverage.xml verbose: true - name: Run phpstan - run: ./vendor/bin/phpstan --level=max analyse src + run: ./vendor/bin/phpstan --level=max --xdebug analyse src From b8887d3fda452026fffefee4e9de8406c4a499b8 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 11 Dec 2022 23:21:27 +0100 Subject: [PATCH 11/13] typehints for commands --- src/Commands/Control/InfoCommand.php | 7 ++++--- .../Control/StartControlChannelCommand.php | 7 ++++--- src/Commands/Control/TriggerCommand.php | 7 ++++--- src/Commands/Ingest/CountCommand.php | 7 ++++--- src/Commands/Ingest/FlushBucketCommand.php | 7 ++++--- src/Commands/Ingest/FlushCollectionCommand.php | 7 ++++--- src/Commands/Ingest/FlushObjectCommand.php | 7 ++++--- src/Commands/Ingest/PopCommand.php | 7 ++++--- src/Commands/Ingest/PushCommand.php | 7 ++++--- .../Ingest/StartIngestChannelCommand.php | 7 ++++--- src/Commands/Misc/PingCommand.php | 7 ++++--- src/Commands/Misc/QuitChannelCommand.php | 7 ++++--- src/Commands/Search/QueryCommand.php | 16 ++++------------ .../Search/StartSearchChannelCommand.php | 13 +++++-------- src/Commands/Search/SuggestCommand.php | 13 +++++-------- 15 files changed, 62 insertions(+), 64 deletions(-) diff --git a/src/Commands/Control/InfoCommand.php b/src/Commands/Control/InfoCommand.php index 81b24bc..56cd4ff 100644 --- a/src/Commands/Control/InfoCommand.php +++ b/src/Commands/Control/InfoCommand.php @@ -6,8 +6,9 @@ final class InfoCommand extends Command { - private $command = 'INFO'; - private $parameters = []; + private string $command = 'INFO'; + /** @var array $parameters */ + private array $parameters = []; /** * Info Command constructor. @@ -16,4 +17,4 @@ public function __construct() { parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Control/StartControlChannelCommand.php b/src/Commands/Control/StartControlChannelCommand.php index a6302e1..1489a67 100644 --- a/src/Commands/Control/StartControlChannelCommand.php +++ b/src/Commands/Control/StartControlChannelCommand.php @@ -6,8 +6,9 @@ final class StartControlChannelCommand extends Command { - private $command = 'START'; - private $parameters = []; + private string $command = 'START'; + /** @var array $parameters */ + private array $parameters = []; /** * StartControlChannelCommand constructor. @@ -22,4 +23,4 @@ public function __construct($password) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Control/TriggerCommand.php b/src/Commands/Control/TriggerCommand.php index 9013e08..93c7813 100644 --- a/src/Commands/Control/TriggerCommand.php +++ b/src/Commands/Control/TriggerCommand.php @@ -6,8 +6,9 @@ final class TriggerCommand extends Command { - private $command = 'TRIGGER'; - private $parameters = []; + private string $command = 'TRIGGER'; + /** @var array $parameters */ + private array $parameters = []; /** * TriggerCommand constructor. @@ -21,4 +22,4 @@ public function __construct(string $action) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/CountCommand.php b/src/Commands/Ingest/CountCommand.php index ea39b50..e23d1ce 100644 --- a/src/Commands/Ingest/CountCommand.php +++ b/src/Commands/Ingest/CountCommand.php @@ -6,8 +6,9 @@ final class CountCommand extends Command { - private $command = 'COUNT'; - private $parameters = []; + private string $command = 'COUNT'; + /** @var array $parameters */ + private array $parameters = []; /** * Counts the number of objects @@ -26,4 +27,4 @@ public function __construct(string $collection, string $bucket = null, string $o parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/FlushBucketCommand.php b/src/Commands/Ingest/FlushBucketCommand.php index 7216c82..e0f4f4a 100644 --- a/src/Commands/Ingest/FlushBucketCommand.php +++ b/src/Commands/Ingest/FlushBucketCommand.php @@ -6,8 +6,9 @@ final class FlushBucketCommand extends Command { - private $command = 'FLUSHB'; - private $parameters = []; + private string $command = 'FLUSHB'; + /** @var array $parameters */ + private array $parameters = []; /** * Flushes a given bucket in a collection @@ -24,4 +25,4 @@ public function __construct(string $collection, string $bucket) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/FlushCollectionCommand.php b/src/Commands/Ingest/FlushCollectionCommand.php index 40bda14..e89bc2e 100644 --- a/src/Commands/Ingest/FlushCollectionCommand.php +++ b/src/Commands/Ingest/FlushCollectionCommand.php @@ -6,8 +6,9 @@ final class FlushCollectionCommand extends Command { - private $command = 'FLUSHC'; - private $parameters = []; + private string $command = 'FLUSHC'; + /** @var array $parameters */ + private array $parameters = []; /** * Flushes a given collection @@ -22,4 +23,4 @@ public function __construct(string $collection) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/FlushObjectCommand.php b/src/Commands/Ingest/FlushObjectCommand.php index fdef4a4..0c424fb 100644 --- a/src/Commands/Ingest/FlushObjectCommand.php +++ b/src/Commands/Ingest/FlushObjectCommand.php @@ -6,8 +6,9 @@ final class FlushObjectCommand extends Command { - private $command = 'FLUSHO'; - private $parameters = []; + private string $command = 'FLUSHO'; + /** @var array $parameters */ + private array $parameters = []; /** * Flushes the text from an object @@ -26,4 +27,4 @@ public function __construct(string $collection, string $bucket, string $object) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/PopCommand.php b/src/Commands/Ingest/PopCommand.php index 0eeacb5..a75ce94 100644 --- a/src/Commands/Ingest/PopCommand.php +++ b/src/Commands/Ingest/PopCommand.php @@ -6,8 +6,9 @@ final class PopCommand extends Command { - private $command = 'POP'; - private $parameters = []; + private string $command = 'POP'; + /** @var array $parameters */ + private array $parameters = []; /** * pops a text from a given object @@ -28,4 +29,4 @@ public function __construct(string $collection, string $bucket, string $object, parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/PushCommand.php b/src/Commands/Ingest/PushCommand.php index c03d44f..e68a7df 100644 --- a/src/Commands/Ingest/PushCommand.php +++ b/src/Commands/Ingest/PushCommand.php @@ -6,8 +6,9 @@ final class PushCommand extends Command { - private $command = 'PUSH'; - private $parameters = []; + private string $command = 'PUSH'; + /** @var array $parameters */ + private array $parameters = []; /** * Push a text/object into an object/bucket respectively @@ -30,4 +31,4 @@ public function __construct(string $collection, string $bucket, string $object, parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Ingest/StartIngestChannelCommand.php b/src/Commands/Ingest/StartIngestChannelCommand.php index 6d64baa..f77cfc6 100644 --- a/src/Commands/Ingest/StartIngestChannelCommand.php +++ b/src/Commands/Ingest/StartIngestChannelCommand.php @@ -6,8 +6,9 @@ final class StartIngestChannelCommand extends Command { - private $command = 'START'; - private $parameters = []; + private string $command = 'START'; + /** @var array $parameters */ + private array $parameters = []; /** * StartIngestChannelCommand constructor. @@ -22,4 +23,4 @@ public function __construct($password) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Misc/PingCommand.php b/src/Commands/Misc/PingCommand.php index 7178f10..f5b7ff2 100644 --- a/src/Commands/Misc/PingCommand.php +++ b/src/Commands/Misc/PingCommand.php @@ -8,8 +8,9 @@ final class PingCommand extends Command { - private $command = 'PING'; - private $parameters = []; + private string $command = 'PING'; + /** @var array $parameters */ + private array $parameters = []; /** * PingCommand constructor. @@ -18,4 +19,4 @@ public function __construct() { parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Misc/QuitChannelCommand.php b/src/Commands/Misc/QuitChannelCommand.php index aed537c..1ded233 100644 --- a/src/Commands/Misc/QuitChannelCommand.php +++ b/src/Commands/Misc/QuitChannelCommand.php @@ -8,8 +8,9 @@ final class QuitChannelCommand extends Command { - private $command = 'QUIT'; - private $parameters = []; + private string $command = 'QUIT'; + /** @var array $parameters */ + private array $parameters = []; /** * QuitChannelCommand constructor. @@ -18,4 +19,4 @@ public function __construct() { parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Search/QueryCommand.php b/src/Commands/Search/QueryCommand.php index bad4c1f..27ede65 100644 --- a/src/Commands/Search/QueryCommand.php +++ b/src/Commands/Search/QueryCommand.php @@ -6,19 +6,11 @@ final class QueryCommand extends Command { - private $command = 'QUERY'; - private $parameters = []; + private string $command = 'QUERY'; + /** @var array $parameters */ + private array $parameters = []; - /** - * QueryCommand constructor. - * @param string $collection - * @param string $bucket - * @param string $terms - * @param null $limit - * @param null $offset - * @param null $locale - */ - public function __construct(string $collection, string $bucket, string $terms, $limit = null, $offset = null, $locale = null) + public function __construct(string $collection, string $bucket, string $terms, int $limit = null, int $offset = null,string $locale = null) { $this->parameters = [ 'collection' => $collection, diff --git a/src/Commands/Search/StartSearchChannelCommand.php b/src/Commands/Search/StartSearchChannelCommand.php index 54ffe41..f8065e9 100644 --- a/src/Commands/Search/StartSearchChannelCommand.php +++ b/src/Commands/Search/StartSearchChannelCommand.php @@ -6,14 +6,11 @@ final class StartSearchChannelCommand extends Command { - private $command = 'START'; - private $parameters = []; + private string $command = 'START'; + /** @var array $parameters */ + private array $parameters = []; - /** - * StartSearchChannelCommand constructor. - * @param string $password - */ - public function __construct($password) + public function __construct(string $password) { $this->parameters = [ 'mode' => 'search', @@ -22,4 +19,4 @@ public function __construct($password) parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} diff --git a/src/Commands/Search/SuggestCommand.php b/src/Commands/Search/SuggestCommand.php index 26f451c..21986c3 100644 --- a/src/Commands/Search/SuggestCommand.php +++ b/src/Commands/Search/SuggestCommand.php @@ -6,17 +6,14 @@ final class SuggestCommand extends Command { - private $command = 'SUGGEST'; - private $parameters = []; + private string $command = 'SUGGEST'; + /** @var array $parameters */ + private array $parameters = []; /** * SuggestCommand constructor. - * @param string $collection - * @param string $bucket - * @param string $terms - * @param null $limit */ - public function __construct(string $collection, string $bucket, string $terms, $limit = null) + public function __construct(string $collection, string $bucket, string $terms,int $limit = null) { $this->parameters = [ 'collection' => $collection, @@ -27,4 +24,4 @@ public function __construct(string $collection, string $bucket, string $terms, $ parent::__construct($this->command, $this->parameters); } -} \ No newline at end of file +} From cc740ed3a3f20f60d3958753e60972e18e52fd89 Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Sun, 11 Dec 2022 23:54:55 +0100 Subject: [PATCH 12/13] more typehints --- src/Commands/Control/TriggerCommand.php | 1 - src/Contracts/Response.php | 1 + src/Control.php | 24 +++------ src/Ingest.php | 69 +++++++++++-------------- src/Search.php | 32 +++++------- src/SonicResponse.php | 42 +++++++-------- 6 files changed, 71 insertions(+), 98 deletions(-) diff --git a/src/Commands/Control/TriggerCommand.php b/src/Commands/Control/TriggerCommand.php index 93c7813..cbfe7bb 100644 --- a/src/Commands/Control/TriggerCommand.php +++ b/src/Commands/Control/TriggerCommand.php @@ -12,7 +12,6 @@ final class TriggerCommand extends Command /** * TriggerCommand constructor. - * @param string $action */ public function __construct(string $action) { diff --git a/src/Contracts/Response.php b/src/Contracts/Response.php index 53bc838..795e874 100644 --- a/src/Contracts/Response.php +++ b/src/Contracts/Response.php @@ -14,4 +14,5 @@ public function get(string $key); * @return string */ public function getStatus(): string; + } diff --git a/src/Control.php b/src/Control.php index b6acf57..0ba48a0 100644 --- a/src/Control.php +++ b/src/Control.php @@ -8,6 +8,7 @@ use Psonic\Commands\Control\InfoCommand; use Psonic\Commands\Control\TriggerCommand; use Psonic\Commands\Control\StartControlChannelCommand; +use Psonic\Contracts\Response; class Control extends Channel { @@ -20,41 +21,32 @@ public function __construct(Client $client) parent::__construct($client); } - /** - * @return mixed|Contracts\Response|void - * @throws Exceptions\ConnectionException - */ - public function connect($password = 'SecretPassword') + public function connect(string $password = 'SecretPassword'): Response { parent::connect(); $response = $this->send(new StartControlChannelCommand($password)); - if ($bufferSize = $response->get('bufferSize')) { + /** @var string $bufferSize */ + $bufferSize = $response->get('bufferSize'); + if ($bufferSize) { $this->bufferSize = (int)$bufferSize; } return $response; } - /** - * @param $action - * @return Contracts\Response - */ - public function trigger($action) + public function trigger(string $action): Response { return $this->send(new TriggerCommand($action)); } - /** - * @return Contracts\Response - */ - public function consolidate() + public function consolidate(): Response { return $this->trigger('consolidate'); } - public function info() + public function info(): Response { return $this->send(new InfoCommand); } diff --git a/src/Ingest.php b/src/Ingest.php index d4512b9..0a88ffe 100644 --- a/src/Ingest.php +++ b/src/Ingest.php @@ -12,6 +12,7 @@ use Psonic\Commands\Ingest\FlushBucketCommand; use Psonic\Commands\Ingest\FlushCollectionCommand; use Psonic\Commands\Ingest\StartIngestChannelCommand; +use Psonic\Contracts\Response; class Ingest extends Channel { @@ -24,17 +25,15 @@ public function __construct(Client $client) parent::__construct($client); } - /** - * @return mixed|Contracts\Response|void - * @throws Exceptions\ConnectionException - */ - public function connect($password = 'SecretPassword') + public function connect(string $password = 'SecretPassword'): Response { parent::connect(); $response = $this->send(new StartIngestChannelCommand($password)); - if ($bufferSize = $response->get('bufferSize')) { + /** @var string $bufferSize */ + $bufferSize = $response->get('bufferSize'); + if ($bufferSize) { $this->bufferSize = (int)$bufferSize; } @@ -88,61 +87,53 @@ public function pop(string $collection, string $bucket, string $object, string $ return $count; } - /** - * @param $collection - * @param null $bucket - * @param null $object - * @return mixed - */ - public function count($collection, $bucket = null, $object = null) + public function count(string $collection,string $bucket = null, string $object = null): int { + /** @var SonicResponse $message */ $message = $this->send(new CountCommand($collection, $bucket, $object)); - return $message->get('count'); + /** @var string $count */ + $count = $message->get('count'); + return (int)$count; } - /** - * @param $collection - * @return mixed - */ - public function flushc($collection) + + public function flushc(string $collection): int { - $message = $this->send(new FlushCollectionCommand($collection)); + /** @var SonicResponse $message */ + $message = $this->send(new FlushCollectionCommand( $collection)); + return $message->getCount(); } - /** - * @param $collection - * @param $bucket - * @return integer - */ - public function flushb($collection, $bucket) + + public function flushb(string $collection, string $bucket): int { + /** @var SonicResponse $message */ $message = $this->send(new FlushBucketCommand($collection, $bucket)); return $message->getCount(); } - /** - * @param $collection - * @param $bucket - * @param $object - * @return mixed - */ - public function flusho($collection, $bucket, $object) + public function flusho(string $collection,string $bucket,string $object): int { + /** @var SonicResponse $message */ $message = $this->send(new FlushObjectCommand($collection, $bucket, $object)); return $message->getCount(); } /** - * @param string $collection - * @param string $bucket - * @param string $key - * @param string $text - * @return array + * @return array */ private function splitString(string $collection, string $bucket, string $key, string $text): array { - return str_split($text, ($this->bufferSize - (strlen($key . $collection . $bucket) + 20))); + $extraBytesRequired = strlen($key . $collection . $bucket) + 20; + $splitLength = $this->bufferSize - $extraBytesRequired; + if($splitLength<=0) { + //@TODO: test this exception + throw new \RuntimeException("Insufficient buffer size for splitting the message string Given " + . $splitLength + . "Buffersize should be more than {$extraBytesRequired} to accomodate the collection, bucket and key name(s) length in the message"); + } + return str_split($text, $splitLength); } } diff --git a/src/Search.php b/src/Search.php index ed97068..42b0571 100644 --- a/src/Search.php +++ b/src/Search.php @@ -25,30 +25,28 @@ public function __construct(Client $client) * @return mixed|Contracts\Response|void * @throws Exceptions\ConnectionException */ - public function connect($password = 'SecretPassword') + public function connect(string $password = 'SecretPassword') { parent::connect(); $response = $this->send(new StartSearchChannelCommand($password)); - if ($bufferSize = $response->get('bufferSize')) { + + /** @var string $bufferSize */ + $bufferSize = $response->get('bufferSize'); + + if ($bufferSize) { $this->bufferSize = (int)$bufferSize; } return $response; } + /** - * @param $collection - * @param $bucket - * @param $terms - * @param $limit - * @param $offset - * @param $locale - * @return array - * @throws CommandFailedException + *@return array */ - public function query($collection, $bucket, $terms, $limit = null, $offset = null, $locale = null): array + public function query(string $collection,string $bucket,string $terms,int $limit = null,int $offset = null,string $locale = null): array { $response = $this->send(new QueryCommand($collection, $bucket, $terms, $limit, $offset, $locale)); @@ -56,6 +54,7 @@ public function query($collection, $bucket, $terms, $limit = null, $offset = nul throw new CommandFailedException; } + /** @var SonicResponse $results */ $results = $this->read(); if (!$results->getStatus() == 'EVENT') { @@ -65,15 +64,11 @@ public function query($collection, $bucket, $terms, $limit = null, $offset = nul return $results->getResults(); } + /** - * @param $collection - * @param $bucket - * @param $terms - * @param $limit - * @return array - * @throws CommandFailedException + *@return array */ - public function suggest($collection, $bucket, $terms, $limit = null): array + public function suggest(string $collection,string $bucket,string $terms, int $limit = null): array { $response = $this->send(new SuggestCommand($collection, $bucket, $terms, $limit)); @@ -81,6 +76,7 @@ public function suggest($collection, $bucket, $terms, $limit = null): array throw new CommandFailedException; } + /** @var SonicResponse $results */ $results = $this->read(); if (!$results->getStatus() == 'EVENT') { diff --git a/src/SonicResponse.php b/src/SonicResponse.php index b83e22b..d4680ba 100644 --- a/src/SonicResponse.php +++ b/src/SonicResponse.php @@ -7,17 +7,15 @@ class SonicResponse implements ResponseInterface { - private $message; - private $pieces; - private $results; + private string $message; + /** @var array */ + private array $pieces; + /** @var array */ + private array $results; - /** - * SonicResponse constructor. - * @param $message - */ - public function __construct($message) + public function __construct(string $message) { - $this->message = (string) $message; + $this->message = $message; $this->parse(); } @@ -25,7 +23,7 @@ public function __construct($message) * parses the read buffer into a readable object * @throws CommandFailedException */ - private function parse() + private function parse(): void { $this->pieces = explode(" ", $this->message); @@ -52,17 +50,14 @@ private function parse() } /** - * @return mixed + * @return array */ - public function getResults() + public function getResults(): array { return $this->results; } - /** - * @return string - */ - public function __toString() + public function __toString():string { return implode(" ", $this->pieces); } @@ -77,19 +72,18 @@ public function get(string $key) } } - /** - * @return mixed - */ public function getStatus(): string { - return $this->get('status'); + /** @var string $status */ + $status = $this->get('status'); + + return $status; } - /** - * @return int - */ public function getCount():int { - return $this->get('count') ?? 0; + /** @var string $count */ + $count = $this->get('count'); + return $count ? (int)$count : 0; } } From a25d588bef41fa0010cf8b41e36e3df8224dfecd Mon Sep 17 00:00:00 2001 From: ppshobi <8536607+ppshobi@users.noreply.github.com> Date: Wed, 4 Jan 2023 14:36:08 +0100 Subject: [PATCH 13/13] test buffersize exception --- src/Ingest.php | 3 +-- tests/Unit/IngestChannelTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Ingest.php b/src/Ingest.php index 0a88ffe..9359e5e 100644 --- a/src/Ingest.php +++ b/src/Ingest.php @@ -129,10 +129,9 @@ private function splitString(string $collection, string $bucket, string $key, st $extraBytesRequired = strlen($key . $collection . $bucket) + 20; $splitLength = $this->bufferSize - $extraBytesRequired; if($splitLength<=0) { - //@TODO: test this exception throw new \RuntimeException("Insufficient buffer size for splitting the message string Given " . $splitLength - . "Buffersize should be more than {$extraBytesRequired} to accomodate the collection, bucket and key name(s) length in the message"); + . ". Buffersize should be more than {$extraBytesRequired} to accomodate the collection, bucket and key name(s) length in the message"); } return str_split($text, $splitLength); } diff --git a/tests/Unit/IngestChannelTest.php b/tests/Unit/IngestChannelTest.php index ad81d0c..97c2507 100644 --- a/tests/Unit/IngestChannelTest.php +++ b/tests/Unit/IngestChannelTest.php @@ -124,6 +124,20 @@ public function it_can_flush_an_object() $this->assertEquals(1, $this->ingest->flusho($this->collection, $this->bucket, "1234")); } + /** + * @test + **/ + public function it_throws_exception_when_buffer_is_not_enough() + { + $response = $this->ingest->connect($this->password); + $bufferSize = $response->get('bufferSize'); + + $longBucketName = str_repeat('i', $bufferSize); + $this->ingest->flushc($this->collection); + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage("Insufficient buffer size for splitting the message string Given -38. Buffersize should be more than ". $bufferSize+38 ." to accomodate the collection, bucket and key name(s) length in the message"); // 38 is the length of collectionName, bucketname and object key + $this->assertEquals("OK", $this->ingest->push($this->collection, $longBucketName, "1234", "hi Shobi how are you?")->getStatus()); + } // @todo /** * Implement tests for locale based ingestion