Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c873406
written the test for neo4jOGM test using ogm class
p123-stack Dec 11, 2024
9d7bca0
test code for OGM test cases
p123-stack Dec 12, 2024
450102a
test code for OGM test cases
p123-stack Dec 12, 2024
2de50a1
added the test code for float and 3D point datatype
p123-stack Dec 12, 2024
32866cc
OGM test code for all point datatypes
p123-stack Dec 13, 2024
6d0fbd3
OGM test code for all datatypes
p123-stack Dec 13, 2024
939d106
Changed the code for point test cases
p123-stack Dec 13, 2024
c2a583b
OGM test code for points
p123-stack Dec 13, 2024
8ed53ba
test code
p123-stack Dec 16, 2024
ede39eb
test code
p123-stack Dec 16, 2024
683f37c
updated test code for ci
p123-stack Dec 16, 2024
1667917
add result cache to gitignore
p123-stack Dec 16, 2024
5f53d22
Merge branch 'main' into pratiksha
p123-stack Dec 16, 2024
42de66a
enable ci for every pull_request
p123-stack Dec 16, 2024
cc44e63
Merge branch 'pratiksha' of https://github.com/nagels-tech/Neo4j-Clie…
p123-stack Dec 16, 2024
945e9f8
test code with parameters
p123-stack Dec 17, 2024
97b5c6c
added the neo4j exception implementation
p123-stack Dec 18, 2024
7226193
Exception testing code
p123-stack Dec 19, 2024
5a77694
Merge remote-tracking branch 'origin/main' into pratiksha
p123-stack Dec 19, 2024
21ec7b1
updated test
p123-stack Dec 20, 2024
0ca519a
added extra material for pratiksha to understand the query api use ca…
transistive Dec 27, 2024
b471ee2
transaction code
p123-stack Dec 27, 2024
e05524e
Transaction test case code
p123-stack Dec 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ on:
branches:
- main
pull_request:
branches:
- main

concurrency:
group: ${{ github.ref }}
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.idea/
vendor
phpunit.xml
test
test
.phpunit.result.cache
1 change: 0 additions & 1 deletion .phpunit.result.cache

This file was deleted.

3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"guzzlehttp/guzzle": "^7.9",
"psr/http-client": "^1.0",
"ext-json": "*",
"php": "^8.1"
"php": "^8.1",
"ext-curl": "*"
},
"require-dev": {
"phpunit/phpunit": "^11.0"
Expand Down
16 changes: 8 additions & 8 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: '3.8'

services:
neo4j:
image: neo4j:5
container_name: neo4j
environment:
# Change the password here as desired
NEO4J_AUTH: "neo4j/your_password"
ports:
- "7474:7474" # HTTP
- "7687:7687" # Bolt
37 changes: 37 additions & 0 deletions run.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Neo4j\QueryAPI;
require './vendor/autoload.php'; // Make sure Guzzle is installed (composer require guzzlehttp/guzzle)

use GuzzleHttp\Client;


$neo4j_url = 'https://6f72daa1.databases.neo4j.io/';
$username = 'neo4j';
//$password = 'your_password';
$password = '9lWmptqBgxBOz8NVcTJjgs3cHPyYmsy63ui6Spmw1d0';

$query = 'CREATE (n:Person {name: "Bobby"}) RETURN n';

$auth = base64_encode("$username:$password");

$payload = json_encode([
'statement' => $query,
]);

$headers = [
'Authorization' => 'Basic ' . $auth,
'Content-Type' => 'application/json',
'Accept' => 'application/json',
];


$client = new Client();

$response = $client->post('https://6f72daa1.databases.neo4j.io/db/neo4j/query/v2/tx', [
'headers' => $headers,
'body' => $payload,
]);
$responseData = json_decode($response->getBody(), true);

print_r($responseData);
68 changes: 68 additions & 0 deletions src/Exception/Neo4jException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

namespace Neo4j\QueryAPI\Exception;

use Exception;

class Neo4jException extends Exception
{
private readonly string $errorCode;
private readonly ?string $errorType;
private readonly ?string $errorSubType;
private readonly ?string $errorName;

public function __construct(
array $errorDetails = [],
int $statusCode = 0,
?\Throwable $previous = null
)
{
$this->errorCode = $errorDetails['code'] ?? 'Neo.UnknownError';
$errorParts = explode('.', $this->errorCode);
$this->errorType = $errorParts[1] ?? null;
$this->errorSubType = $errorParts[2] ?? null;
$this->errorName = $errorParts[3] ?? null;


$message = $errorDetails['message'] ?? 'An unknown error occurred.';
parent::__construct($message, $statusCode, $previous);
}

/**
* Get the Neo4j error code associated with this exception.
*/
public function getErrorCode(): string
{
return $this->errorCode;
}

public function getType(): ?string
{
return $this->errorType;
}

public function getSubType(): ?string
{
return $this->errorSubType;
}

public function getName(): ?string
{
return $this->errorName;
}

/**
* Create a Neo4jException instance from a Neo4j error response array.
*
* @param array $response The error response from Neo4j.
* @param \Throwable|null $exception Optional previous exception for chaining.
* @return self
*/
public static function fromNeo4jResponse(array $response, ?\Throwable $exception = null): self
{
$errorDetails = $response['errors'][0] ?? [];
$statusCode = $errorDetails['statusCode'] ?? 0;

return new self($errorDetails, (int)$statusCode, $exception);
}
}
67 changes: 53 additions & 14 deletions src/Neo4jQueryAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

namespace Neo4j\QueryAPI;

use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Exception\RequestException;
use Neo4j\QueryAPI\Results\ResultRow;
use Neo4j\QueryAPI\Results\ResultSet;
use Neo4j\QueryAPI\Exception\Neo4jException;
use Psr\Http\Client\RequestExceptionInterface;
use RuntimeException;
use stdClass;

Expand Down Expand Up @@ -35,27 +39,62 @@ public static function login(string $address, string $username, string $password
}

/**
* @throws GuzzleException
* @throws Neo4jException
* @throws RequestExceptionInterface
*/
public function run(string $cypher, array $parameters, string $database = 'neo4j'): ResultSet
{
$payload = [
'statement' => $cypher,
'parameters' => $parameters === [] ? new stdClass() : $parameters,
];

$response = $this->client->post('/db/' . $database . '/query/v2', [
'json' => $payload,
]);
try {
// Prepare the payload for the request
$payload = [
'statement' => $cypher,
'parameters' => empty($parameters) ? new stdClass() : $parameters,
];

// Execute the request to the Neo4j server
$response = $this->client->post('/db/' . $database . '/query/v2', [
'json' => $payload,
]);

// Decode the response body
$data = json_decode($response->getBody()->getContents(), true);
$ogm = new OGM();

$keys = $data['data']['fields'];
$values = $data['data']['values'];
$rows = array_map(function ($resultRow) use ($ogm, $keys) {
$data = [];
foreach ($keys as $index => $key) {
$fieldData = $resultRow[$index] ?? null;
$data[$key] = $ogm->map($fieldData);
}
return new ResultRow($data);
}, $values);

return new ResultSet($rows);
} catch (RequestExceptionInterface $e) {
$response = $e->getResponse();
if ($response !== null) {
$contents = $response->getBody()->getContents();
$errorResponse = json_decode($contents, true);

throw Neo4jException::fromNeo4jResponse($errorResponse, $e);
}

throw $e;
}
}

public function beginTransaction(string $database = 'neo4j'): Transaction
{
$response = $this->client->post("/db/neo4j/query/v2/tx");

$data = json_decode($response->getBody()->getContents(), true);
$clusterAffinity = $response->getHeaderLine('neo4j-cluster-affinity');
$responseData = json_decode($response->getBody(), true);
$transactionId = $responseData['transaction']['id'];


$ogm = new OGM();

return new ResultSet($data['data']['fields'], $data['data']['values'], $ogm);
return new Transaction($this->client, $clusterAffinity, $transactionId);
}


}
Loading
Loading