diff --git a/README.md b/README.md index db7952d..d32abbb 100644 --- a/README.md +++ b/README.md @@ -20,11 +20,11 @@ composer require neo4j-php/query-api ## Client Installation -If you plan on using the HTTP drivers, make sure you have psr-7, psr-17, and psr-18 implementations included in your project. -If you don't have any, you can install them via Composer: +This client uses the HTTP protocol, make sure you have psr-7, psr-17, and psr-18 implementations included in your project. +If you don't have any, you can install one of the many options via Composer: ```sh -composer require psr/http-message psr/http-factory psr/http-client +composer require guzzlehttp/guzzle ``` > **_NOTE:_** PSR-17 and PSR-18 are essential for HTTP client communication. Other compatible clients like Guzzle can also be used. @@ -121,19 +121,18 @@ Cypher values and types map to these php types and classes: | Authentication | Yes | | Transaction | Yes | | HTTP | Yes | -| Cluster | Partly* | +| Cluster | Partly * | | Aura | Yes | | Bookmarks | Yes | | Bolt | No | -> **_NOTE:_** It supports neo4j databases versions > 5.25 or Neo4j Aura (which has QueryAPI enabled.) > \* Client side routing is only supported in the Neo4j driver - + **_NOTE:_** *_It supports neo4j databases versions > 5.25 or Neo4j Aura (which has QueryAPI enabled.)_* ## Contributing -Please see CONTRIBUTING for details. +Please see [CONTRIBUTING.md](./Contributing.md) for details. ## Security @@ -142,8 +141,10 @@ If you discover any security-related issues, please email *security@nagels.tech* ## Credits - Created with ❤️ by Nagels -- [Ghlen Nagels](https://www.linkedin.com/in/ghlen/), [Kiran Chandani](https://www.linkedin.com/in/kiran-chandani-5628a1213/), [Pratiksha Zalte]() +- [Kiran Chandani](https://www.linkedin.com/in/kiran-chandani-5628a1213/), +- [Pratiksha Zalte](https://github.com/p123-stack), +- [Ghlen Nagels](https://www.linkedin.com/in/ghlen/) ## License -The MIT License (MIT). Please see License File for more information. \ No newline at end of file +The MIT License (MIT). Please see [License File](LICENSE) for more information. \ No newline at end of file diff --git a/phpunit.dist.xml b/phpunit.dist.xml index 158b08f..a3ab58d 100644 --- a/phpunit.dist.xml +++ b/phpunit.dist.xml @@ -1,5 +1,8 @@ - + diff --git a/src/Neo4jRequestFactory.php b/src/Neo4jRequestFactory.php index bd78fbf..600427d 100644 --- a/src/Neo4jRequestFactory.php +++ b/src/Neo4jRequestFactory.php @@ -8,7 +8,7 @@ use Psr\Http\Message\RequestInterface; use Psr\Http\Message\StreamFactoryInterface; -class Neo4jRequestFactory +final class Neo4jRequestFactory { public function __construct( private RequestFactoryInterface $psr17Factory, diff --git a/src/OGM.php b/src/OGM.php index 72b6c40..5c3c064 100644 --- a/src/OGM.php +++ b/src/OGM.php @@ -8,7 +8,7 @@ use Neo4j\QueryAPI\Objects\Path; use InvalidArgumentException; -class OGM +final class OGM { /** * @param array $data diff --git a/src/Objects/Authentication.php b/src/Objects/Authentication.php index 9dd0f1d..df15367 100644 --- a/src/Objects/Authentication.php +++ b/src/Objects/Authentication.php @@ -7,7 +7,7 @@ use Neo4j\QueryAPI\Authentication\BearerAuthentication; use Neo4j\QueryAPI\Authentication\NoAuth; -class Authentication +final class Authentication { public static function basic(string $username, string $password): AuthenticateInterface { diff --git a/src/Objects/Path.php b/src/Objects/Path.php index bdfb28c..b96666c 100644 --- a/src/Objects/Path.php +++ b/src/Objects/Path.php @@ -6,7 +6,7 @@ * Represents a path in a Neo4j graph, consisting of nodes and relationships. */ -class Path +final class Path { /** * @var Node[] Array of nodes in the path. diff --git a/src/Objects/Person.php b/src/Objects/Person.php index cc937c8..a6156b0 100644 --- a/src/Objects/Person.php +++ b/src/Objects/Person.php @@ -6,7 +6,7 @@ * @psalm-suppress UnusedClass * Represents a Person node in the Neo4j graph. */ -class Person extends Node +final class Person extends Node { /** * Person constructor. diff --git a/src/Objects/Point.php b/src/Objects/Point.php index 4a79ec5..9bbda88 100644 --- a/src/Objects/Point.php +++ b/src/Objects/Point.php @@ -5,7 +5,7 @@ /** * Represents a point with x, y, z coordinates, and SRID (Spatial Reference System Identifier). */ -class Point +final class Point { /** * @param float $x The x coordinate of the point. diff --git a/src/Objects/ProfiledQueryPlanArguments.php b/src/Objects/ProfiledQueryPlanArguments.php index 74e4c48..a56cfd2 100644 --- a/src/Objects/ProfiledQueryPlanArguments.php +++ b/src/Objects/ProfiledQueryPlanArguments.php @@ -2,7 +2,7 @@ namespace Neo4j\QueryAPI\Objects; -class ProfiledQueryPlanArguments +final class ProfiledQueryPlanArguments { public function __construct( public readonly ?int $globalMemory = null, diff --git a/src/Objects/Relationship.php b/src/Objects/Relationship.php index 9d441f3..9b96902 100644 --- a/src/Objects/Relationship.php +++ b/src/Objects/Relationship.php @@ -6,7 +6,7 @@ * Represents a relationship in a Neo4j graph, with a type and associated properties. */ -class Relationship +final class Relationship { /** * @var string The type of the relationship (e.g., "FRIENDS_WITH", "WORKS_FOR"). diff --git a/src/Objects/ResultCounters.php b/src/Objects/ResultCounters.php index 08669b9..ebeb1af 100644 --- a/src/Objects/ResultCounters.php +++ b/src/Objects/ResultCounters.php @@ -2,7 +2,7 @@ namespace Neo4j\QueryAPI\Objects; -class ResultCounters +final class ResultCounters { public function __construct( private readonly bool $containsUpdates = false, diff --git a/src/Results/ResultSet.php b/src/Results/ResultSet.php index 5660aec..6708720 100644 --- a/src/Results/ResultSet.php +++ b/src/Results/ResultSet.php @@ -15,7 +15,7 @@ * @template TValue * @implements IteratorAggregate */ -class ResultSet implements IteratorAggregate, Countable +final class ResultSet implements IteratorAggregate, Countable { /** * @param list $rows diff --git a/tests/CreatesQueryAPI.php b/tests/CreatesQueryAPI.php index c4b4465..9820606 100644 --- a/tests/CreatesQueryAPI.php +++ b/tests/CreatesQueryAPI.php @@ -6,12 +6,13 @@ use Neo4j\QueryAPI\Enums\AccessMode; use Neo4j\QueryAPI\Neo4jQueryAPI; use Neo4j\QueryAPI\Objects\Authentication; +use Neo4j\QueryAPI\Objects\Bookmarks; trait CreatesQueryAPI { protected Neo4jQueryAPI $api; - protected function createQueryAPI(AccessMode $accessMode = AccessMode::WRITE): void + protected function createQueryAPI(AccessMode $accessMode = AccessMode::WRITE, ?Bookmarks $bookmarks = null): void { $neo4jAddress = getenv('NEO4J_ADDRESS'); if (!is_string($neo4jAddress) || trim($neo4jAddress) === '') { @@ -19,7 +20,7 @@ protected function createQueryAPI(AccessMode $accessMode = AccessMode::WRITE): v } $this->api = Neo4jQueryAPI::create( - new Configuration(baseUri: $neo4jAddress, accessMode: $accessMode), + new Configuration(baseUri: $neo4jAddress, bookmarks: $bookmarks ?? new Bookmarks([]), accessMode: $accessMode), Authentication::fromEnvironment() ); } diff --git a/tests/Integration/BookmarksIntegrationTest.php b/tests/Integration/BookmarksIntegrationTest.php index d63b444..58c6d4b 100644 --- a/tests/Integration/BookmarksIntegrationTest.php +++ b/tests/Integration/BookmarksIntegrationTest.php @@ -2,6 +2,9 @@ namespace Neo4j\QueryAPI\Tests\Integration; +use Neo4j\QueryAPI\Configuration; +use Neo4j\QueryAPI\Exception\Neo4jException; +use Neo4j\QueryAPI\Neo4jQueryAPI; use Neo4j\QueryAPI\Tests\CreatesQueryAPI; use PHPUnit\Framework\TestCase; use Neo4j\QueryAPI\Objects\Bookmarks; @@ -34,4 +37,26 @@ public function testCreateBookmarks(): void $this->assertCount(1, $result); } + + public function testInvalidBookmarkThrowsException(): void + { + $exceptionCaught = false; + + $invalidBookmark = new Bookmarks(['invalid:bookmark']); + $this->createQueryAPI(bookmarks: $invalidBookmark); + + try { + $this->api->run('MATCH (n) RETURN n'); + } catch (Neo4jException $e) { + $exceptionCaught = true; + $this->assertEquals('Parsing of supplied bookmarks failed with message: Illegal base64 character 3a', $e->getMessage()); + $this->assertEquals('InvalidBookmark', $e->getName()); + $this->assertEquals('Transaction', $e->getSubType()); + $this->assertEquals('ClientError', $e->getType()); + } + + $this->assertTrue($exceptionCaught); + } + + } diff --git a/tests/Integration/Neo4jOGMTest.php b/tests/Integration/Neo4jOGMTest.php index 60d50cc..635fd74 100644 --- a/tests/Integration/Neo4jOGMTest.php +++ b/tests/Integration/Neo4jOGMTest.php @@ -2,15 +2,12 @@ namespace Neo4j\QueryAPI\Tests\Integration; +use Neo4j\QueryAPI\Objects\Path; use Neo4j\QueryAPI\OGM; use PHPUnit\Framework\TestCase; -/** - * @api - */ -class Neo4jOGMTest extends TestCase +final class Neo4jOGMTest extends TestCase { - /** @psalm-suppress PropertyNotSetInConstructor */ private OGM $ogm; #[\Override] @@ -84,11 +81,11 @@ public function testWithPath(): void ]; $path = $this->ogm->map($pathData); + $this->assertInstanceOf(Path::class, $path); $this->assertCount(2, $path->nodes); $this->assertCount(1, $path->relationships); $this->assertEquals('A', $path->nodes[0]->getProperties()['name']['_value']); $this->assertEquals('B', $path->nodes[1]->getProperties()['name']['_value']); } - }