Skip to content

Commit 2e4c7eb

Browse files
committed
git branch (monday.com)
1 parent a4acd18 commit 2e4c7eb

File tree

4 files changed

+278
-183
lines changed

4 files changed

+278
-183
lines changed

src/Configuration.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Neo4j\QueryAPI;
4+
5+
class Configuration
6+
{
7+
private string $baseUrl;
8+
private string $authToken;
9+
private array $defaultHeaders;
10+
11+
public function __construct(
12+
string $baseUrl = 'https://localhost:7474',
13+
string $authToken = '',
14+
array $defaultHeaders = []
15+
) {
16+
$this->baseUrl = $baseUrl;
17+
$this->authToken = $authToken;
18+
$this->defaultHeaders = $defaultHeaders;
19+
}
20+
21+
/**
22+
* Set the base URL of the API.
23+
*
24+
* @param string $baseUrl
25+
* @return self
26+
*/
27+
public function setBaseUrl(string $baseUrl): self
28+
{
29+
$this->baseUrl = $baseUrl;
30+
return $this;
31+
}
32+
33+
/**
34+
* Set the authentication token.
35+
*
36+
* @param string $authToken
37+
* @return self
38+
*/
39+
public function setAuthToken(string $authToken): self
40+
{
41+
$this->authToken = $authToken;
42+
return $this;
43+
}
44+
45+
/**
46+
* Set default headers for API requests.
47+
*
48+
* @param array $headers
49+
* @return self
50+
*/
51+
public function setDefaultHeaders(array $headers): self
52+
{
53+
$this->defaultHeaders = $headers;
54+
return $this;
55+
}
56+
57+
/**
58+
* Get the base URL of the API.
59+
*
60+
* @return string
61+
*/
62+
public function getBaseUrl(): string
63+
{
64+
return $this->baseUrl;
65+
}
66+
67+
/**
68+
* Get the authentication token.
69+
*
70+
* @return string
71+
*/
72+
public function getAuthToken(): string
73+
{
74+
return $this->authToken;
75+
}
76+
77+
/**
78+
* Get the default headers for API requests.
79+
*
80+
* @return array
81+
*/
82+
public function getDefaultHeaders(): array
83+
{
84+
return array_merge($this->defaultHeaders, [
85+
'Authorization' => 'Bearer ' . $this->authToken,
86+
'Content-Type' => 'application/json',
87+
]);
88+
}
89+
}

src/Neo4jQueryAPI.php

Lines changed: 43 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -2,150 +2,83 @@
22

33
namespace Neo4j\QueryAPI;
44

5-
use Exception;
65
use GuzzleHttp\Client;
7-
use GuzzleHttp\Exception\GuzzleException;
86
use GuzzleHttp\Exception\RequestException;
9-
use InvalidArgumentException;
10-
use Neo4j\QueryAPI\Objects\ChildQueryPlan;
11-
use Neo4j\QueryAPI\Objects\QueryArguments;
12-
use Neo4j\QueryAPI\Objects\ResultCounters;
13-
use Neo4j\QueryAPI\Objects\ProfiledQueryPlan;
14-
use Neo4j\QueryAPI\Results\ResultRow;
7+
use Neo4j\QueryAPI\Enums\AccessMode;
8+
use Neo4j\QueryAPI\Objects\Bookmarks;
159
use Neo4j\QueryAPI\Results\ResultSet;
1610
use Neo4j\QueryAPI\Exception\Neo4jException;
1711
use Psr\Http\Client\RequestExceptionInterface;
18-
use RuntimeException;
19-
use stdClass;
20-
use Neo4j\QueryAPI\Objects\Bookmarks;
21-
use Neo4j\QueryAPI\Enums\AccessMode;
22-
12+
use Psr\Http\Message\ResponseInterface;
2313

2414
class Neo4jQueryAPI
2515
{
26-
2716
private Client $client;
17+
private Configuration $config;
18+
private ResponseParser $responseParser;
2819

29-
public function __construct(Client $client)
20+
public function __construct(Configuration $config, ResponseParser $responseParser)
3021
{
31-
$this->client = $client;
22+
$this->config = $config;
23+
$this->responseParser = $responseParser;
24+
25+
$this->client = new Client([
26+
'base_uri' => rtrim($this->config->getBaseUrl(), '/'),
27+
'timeout' => 10.0,
28+
'headers' => $this->config->getDefaultHeaders(),
29+
]);
3230
}
31+
3332
/**
34-
* @api
33+
* Static method to create an instance with login details.
3534
*/
3635
public static function login(string $address, string $username, string $password): self
3736
{
37+
$authToken = base64_encode("$username:$password");
38+
$config = (new Configuration())
39+
->setBaseUrl($address)
40+
->setAuthToken($authToken);
3841

39-
40-
$client = new Client([
41-
'base_uri' => rtrim($address, '/'),
42-
'timeout' => 10.0,
43-
'headers' => [
44-
'Authorization' => 'Basic ' . base64_encode("$username:$password"),
45-
'Content-Type' => 'application/vnd.neo4j.query',
46-
'Accept' => 'application/vnd.neo4j.query',
47-
],
48-
]);
49-
50-
return new self($client);
42+
return new self($config, new ResponseParser(new OGM()));
5143
}
5244

5345
/**
54-
* @throws Neo4jException
55-
* @throws RequestExceptionInterface
56-
* @api
46+
* Executes a Cypher query.
47+
*
48+
* @throws Neo4jException|RequestExceptionInterface
5749
*/
5850
public function run(string $cypher, array $parameters = [], string $database = 'neo4j', Bookmarks $bookmark = null, ?string $impersonatedUser = null, AccessMode $accessMode = AccessMode::WRITE): ResultSet
5951
{
6052
try {
6153
$payload = [
6254
'statement' => $cypher,
63-
'parameters' => empty($parameters) ? new stdClass() : $parameters,
55+
'parameters' => empty($parameters) ? new \stdClass() : $parameters,
6456
'includeCounters' => true,
6557
'accessMode' => $accessMode->value,
6658
];
6759

68-
6960
if ($bookmark !== null) {
7061
$payload['bookmarks'] = $bookmark->getBookmarks();
7162
}
63+
7264
if ($impersonatedUser !== null) {
7365
$payload['impersonatedUser'] = $impersonatedUser;
7466
}
7567

76-
$response = $this->client->post('/db/' . $database . '/query/v2', [
77-
'json' => $payload,
78-
]);
68+
$response = $this->client->post("/db/{$database}/query/v2", ['json' => $payload]);
7969

80-
$data = json_decode($response->getBody()->getContents(), true);
81-
82-
$ogm = new OGM();
83-
84-
$keys = $data['data']['fields'];
85-
$values = $data['data']['values'];
86-
87-
$rows = array_map(function ($resultRow) use ($ogm, $keys) {
88-
$data = [];
89-
foreach ($keys as $index => $key) {
90-
$fieldData = $resultRow[$index] ?? null;
91-
$data[$key] = $ogm->map($fieldData);
92-
}
93-
return new ResultRow($data);
94-
}, $values);
95-
96-
$profile = null;
97-
if (isset($data['profiledQueryPlan'])) {
98-
$profile = $this->createProfileData($data['profiledQueryPlan']);
99-
}
100-
101-
$resultCounters = new ResultCounters(
102-
containsUpdates: $data['counters']['containsUpdates'] ?? false,
103-
nodesCreated: $data['counters']['nodesCreated'] ?? 0,
104-
nodesDeleted: $data['counters']['nodesDeleted'] ?? 0,
105-
propertiesSet: $data['counters']['propertiesSet'] ?? 0,
106-
relationshipsCreated: $data['counters']['relationshipsCreated'] ?? 0,
107-
relationshipsDeleted: $data['counters']['relationshipsDeleted'] ?? 0,
108-
labelsAdded: $data['counters']['labelsAdded'] ?? 0,
109-
labelsRemoved: $data['counters']['labelsRemoved'] ?? 0,
110-
indexesAdded: $data['counters']['indexesAdded'] ?? 0,
111-
indexesRemoved: $data['counters']['indexesRemoved'] ?? 0,
112-
constraintsAdded: $data['counters']['constraintsAdded'] ?? 0,
113-
constraintsRemoved: $data['counters']['constraintsRemoved'] ?? 0,
114-
containsSystemUpdates: $data['counters']['containsSystemUpdates'] ?? false,
115-
systemUpdates: $data['counters']['systemUpdates'] ?? 0
116-
);
117-
118-
return new ResultSet(
119-
$rows,
120-
$resultCounters,
121-
new Bookmarks($data['bookmarks'] ?? []),
122-
$profile,
123-
$accessMode
124-
);
125-
} catch (RequestExceptionInterface $e) {
126-
error_log("Request Exception: " . $e->getMessage());
127-
128-
$response = $e->getResponse();
129-
if ($response !== null) {
130-
$contents = $response->getBody()->getContents();
131-
$errorResponse = json_decode($contents, true);
132-
throw Neo4jException::fromNeo4jResponse($errorResponse, $e);
133-
}
134-
135-
136-
throw new Neo4jException(['message' => $e->getMessage()], 500, $e);
70+
return $this->responseParser->parseRunQueryResponse($response);
71+
} catch (RequestException $e) {
72+
$this->handleRequestException($e);
13773
}
13874
}
13975

140-
141-
14276
/**
143-
* @api
77+
* Starts a transaction.
14478
*/
14579
public function beginTransaction(string $database = 'neo4j'): Transaction
14680
{
147-
unset($database);
148-
$response = $this->client->post("/db/neo4j/query/v2/tx");
81+
$response = $this->client->post("/db/{$database}/query/v2/tx");
14982

15083
$clusterAffinity = $response->getHeaderLine('neo4j-cluster-affinity');
15184
$responseData = json_decode($response->getBody(), true);
@@ -154,49 +87,19 @@ public function beginTransaction(string $database = 'neo4j'): Transaction
15487
return new Transaction($this->client, $clusterAffinity, $transactionId);
15588
}
15689

157-
private function createProfileData(array $data): ProfiledQueryPlan
90+
/**
91+
* Handles request exceptions by parsing error details and throwing a Neo4jException.
92+
*
93+
* @throws Neo4jException
94+
*/
95+
private function handleRequestException(RequestExceptionInterface $e): void
15896
{
159-
$arguments = $data['arguments'];
160-
161-
$queryArguments = new QueryArguments(
162-
$arguments['globalMemory'] ?? 0,
163-
$arguments['plannerImpl'] ?? '',
164-
$arguments['memory'] ?? 0,
165-
$arguments['stringRepresentation'] ?? '',
166-
is_string($arguments['runtime'] ?? '') ? $arguments['runtime'] : json_encode($arguments['runtime']),
167-
$arguments['runtimeImpl'] ?? '',
168-
$arguments['dbHits'] ?? 0,
169-
$arguments['batchSize'] ?? 0,
170-
$arguments['details'] ?? '',
171-
$arguments['plannerVersion'] ?? '',
172-
$arguments['pipelineInfo'] ?? '',
173-
$arguments['runtimeVersion'] ?? '',
174-
$arguments['id'] ?? 0,
175-
$arguments['estimatedRows'] ?? 0.0,
176-
is_string($arguments['planner'] ?? '') ? $arguments['planner'] : json_encode($arguments['planner']),
177-
$arguments['rows'] ?? 0
178-
);
179-
180-
$profiledQueryPlan = new ProfiledQueryPlan(
181-
$data['dbHits'],
182-
$data['records'],
183-
$data['hasPageCacheStats'],
184-
$data['pageCacheHits'],
185-
$data['pageCacheMisses'],
186-
$data['pageCacheHitRatio'],
187-
$data['time'],
188-
$data['operatorType'],
189-
$queryArguments
190-
);
191-
192-
foreach($data['children'] as $child) {
193-
$childQueryPlan = $this->createProfileData($child);
194-
195-
$profiledQueryPlan->addChild($childQueryPlan);
97+
$response = $e->getResponse();
98+
if ($response instanceof ResponseInterface) {
99+
$errorResponse = json_decode((string)$response->getBody(), true);
100+
throw Neo4jException::fromNeo4jResponse($errorResponse, $e);
196101
}
197102

198-
return $profiledQueryPlan;
103+
throw new Neo4jException(['message' => $e->getMessage()], 500, $e);
199104
}
200-
201-
202105
}

0 commit comments

Comments
 (0)