Skip to content
Merged
1 change: 0 additions & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@
MultilineCommentOpeningClosingAloneFixer::name() => true,
MultilinePromotedPropertiesFixer::name() => true,
PhpUnitAssertArgumentsOrderFixer::name() => true,
PhpdocNoSuperfluousParamFixer::name() => true,
PhpdocParamOrderFixer::name() => true,
StringableInterfaceFixer::name() => true,
])
Expand Down
15 changes: 4 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,21 +308,16 @@ composer require nyholm/psr7 nyholm/psr7-server kriswallsmith/buzz

## Result formats/hydration

In order to make the results of the bolt protocol and the http uniform, the driver provides result formatters (aka hydrators). The client is configurable with these formatters. You can even implement your own.
In order to make the results of the bolt protocol and the http uniform, the driver provides and summarizes the results.

The default formatter is the `\Laudis\Neo4j\Formatters\OGMFormatter`, which is explained extensively in [the result format section](#accessing-the-results).
The default formatter is the `\Laudis\Neo4j\Formatters\SummarizedResultFormatter`, which is explained extensively in [the result format section](#accessing-the-results).

The driver provides three formatters by default, which are all found in the Formatter namespace:
- `\Laudis\Neo4j\Formatter\BasicFormatter` which erases all the Cypher types and simply returns every value in the resulting map as a [scalar](https://www.php.net/manual/en/function.is-scalar.php), null or array value.
- `\Laudis\Neo4j\Formatter\OGMFormatter` which maps the cypher types to php types as explained [here](#accessing-the-results).
- `\Laudis\Neo4j\Formatter\SummarizedResultFormatter` which decorates any formatter and adds an extensive result summary.
`\Laudis\Neo4j\Formatter\SummarizedResultFormatter` adds an extensive result summary.

The client builder provides an easy way to change the formatter:

```php
$client = \Laudis\Neo4j\ClientBuilder::create()
->withFormatter(\Laudis\Neo4j\Formatter\SummarizedResultFormatter::create())
->build();
$client = \Laudis\Neo4j\ClientBuilder::create()->build();

/**
* The client will now return a result, decorated with a summary.
Expand All @@ -339,8 +334,6 @@ $summary = $summarisedResult->getSummary();
$result = $summarisedResult->getResult();
```

In order to use a custom formatter, implement the `Laudis\Neo4j\Contracts\FormatterInterface` and provide it when using the client builder.

## Concepts

The driver API described [here](https://neo4j.com/docs/driver-manual/current/) is the main target of the driver. Because of this, the client is nothing more than a driver manager. The driver creates sessions. A session runs queries through a transaction.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"nyholm/psr7-server": "^1.0",
"kriswallsmith/buzz": "^1.2",
"vimeo/psalm": "^5.0",
"friendsofphp/php-cs-fixer": "3.15.0",
"friendsofphp/php-cs-fixer": "3.68.5",
"psalm/plugin-phpunit": "^0.18",
"monolog/monolog": "^2.2",
"symfony/uid": "^5.0",
Expand Down
3 changes: 2 additions & 1 deletion src/Authentication/BasicAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public function __construct(
private readonly string $username,
private readonly string $password,
private readonly ?Neo4jLogger $logger,
) {}
) {
}

/**
* @throws Exception
Expand Down
4 changes: 3 additions & 1 deletion src/Authentication/KerberosAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ final class KerberosAuth implements AuthenticateInterface
public function __construct(
private readonly string $token,
private readonly ?Neo4jLogger $logger,
) {}
) {
}

public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
{
$this->logger?->log(LogLevel::DEBUG, 'Authenticating using KerberosAuth');

/**
* @psalm-suppress ImpureMethodCall Request is a pure object:
*
Expand Down
6 changes: 4 additions & 2 deletions src/Authentication/NoAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@ final class NoAuth implements AuthenticateInterface
* @pure
*/
public function __construct(
private readonly ?Neo4jLogger $logger
) {}
private readonly ?Neo4jLogger $logger,
) {
}

public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
{
$this->logger?->log(LogLevel::DEBUG, 'Authentication disabled');

/**
* @psalm-suppress ImpureMethodCall Request is a pure object:
*
Expand Down
6 changes: 4 additions & 2 deletions src/Authentication/OpenIDConnectAuth.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ final class OpenIDConnectAuth implements AuthenticateInterface
*/
public function __construct(
private readonly string $token,
private readonly ?Neo4jLogger $logger
) {}
private readonly ?Neo4jLogger $logger,
) {
}

public function authenticateHttp(RequestInterface $request, UriInterface $uri, string $userAgent): RequestInterface
{
$this->logger?->log(LogLevel::DEBUG, 'Authenticating using OpenIDConnectAuth');

/**
* @psalm-suppress ImpureMethodCall Request is a pure object:
*
Expand Down
12 changes: 3 additions & 9 deletions src/Basic/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,13 @@
use Laudis\Neo4j\Databags\SummarizedResult;
use Laudis\Neo4j\Databags\TransactionConfiguration;
use Laudis\Neo4j\Types\CypherList;
use Laudis\Neo4j\Types\CypherMap;

/**
* @implements ClientInterface<SummarizedResult<CypherMap>>
*/
final class Client implements ClientInterface
{
/**
* @param ClientInterface<SummarizedResult<CypherMap>> $client
*/
public function __construct(
private readonly ClientInterface $client
) {}
private readonly ClientInterface $client,
) {
}

public function run(string $statement, iterable $parameters = [], ?string $alias = null): SummarizedResult
{
Expand Down
13 changes: 3 additions & 10 deletions src/Basic/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,19 @@
use Laudis\Neo4j\Contracts\DriverInterface;
use Laudis\Neo4j\Databags\DriverConfiguration;
use Laudis\Neo4j\Databags\SessionConfiguration;
use Laudis\Neo4j\Databags\SummarizedResult;
use Laudis\Neo4j\DriverFactory;
use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
use Laudis\Neo4j\Types\CypherMap;
use Psr\Http\Message\UriInterface;

/**
* @implements DriverInterface<SummarizedResult<CypherMap>>
*/
final class Driver implements DriverInterface
{
/**
* @param DriverInterface<SummarizedResult<CypherMap>> $driver
*
* @psalm-external-mutation-free
*/
public function __construct(
private readonly DriverInterface $driver
) {}
private readonly DriverInterface $driver,
) {
}

/**
* @psalm-mutation-free
Expand All @@ -52,7 +46,6 @@ public function verifyConnectivity(?SessionConfiguration $config = null): bool

public static function create(string|UriInterface $uri, ?DriverConfiguration $configuration = null, ?AuthenticateInterface $authenticate = null): self
{
/** @var DriverInterface<SummarizedResult<CypherMap>> */
$driver = DriverFactory::create($uri, $configuration, $authenticate, SummarizedResultFormatter::create());

return new self($driver);
Expand Down
19 changes: 4 additions & 15 deletions src/Basic/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,31 @@
use Laudis\Neo4j\Databags\SummarizedResult;
use Laudis\Neo4j\Databags\TransactionConfiguration;
use Laudis\Neo4j\Types\CypherList;
use Laudis\Neo4j\Types\CypherMap;

/**
* @implements SessionInterface<SummarizedResult<CypherMap>>
*/
final class Session implements SessionInterface
{
/**
* @param SessionInterface<SummarizedResult<CypherMap>> $session
*/
public function __construct(
private readonly SessionInterface $session
) {}
private readonly SessionInterface $session,
) {
}

/**
* @param iterable<Statement> $statements
*
* @return CypherList<SummarizedResult<CypherMap>>
* @return CypherList<SummarizedResult>
*/
public function runStatements(iterable $statements, ?TransactionConfiguration $config = null): CypherList
{
return $this->session->runStatements($statements, $config);
}

/**
* @return SummarizedResult<CypherMap>
*/
public function runStatement(Statement $statement, ?TransactionConfiguration $config = null): SummarizedResult
{
return $this->session->runStatement($statement, $config);
}

/**
* @param iterable<string, mixed> $parameters
*
* @return SummarizedResult<CypherMap>
*/
public function run(string $statement, iterable $parameters = [], ?TransactionConfiguration $config = null): SummarizedResult
{
Expand Down
21 changes: 5 additions & 16 deletions src/Basic/UnmanagedTransaction.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,33 +17,22 @@
use Laudis\Neo4j\Databags\Statement;
use Laudis\Neo4j\Databags\SummarizedResult;
use Laudis\Neo4j\Types\CypherList;
use Laudis\Neo4j\Types\CypherMap;

/**
* @implements UnmanagedTransactionInterface<SummarizedResult<CypherMap>>
*/
final class UnmanagedTransaction implements UnmanagedTransactionInterface
{
/**
* @param UnmanagedTransactionInterface<SummarizedResult<CypherMap>> $tsx
*/
public function __construct(
private readonly UnmanagedTransactionInterface $tsx
) {}
private readonly UnmanagedTransactionInterface $tsx,
) {
}

/**
* @param iterable<string, mixed> $parameters
*
* @return SummarizedResult<CypherMap>
*/
public function run(string $statement, iterable $parameters = []): SummarizedResult
{
return $this->tsx->run($statement, $parameters);
}

/**
* @return SummarizedResult<CypherMap>
*/
public function runStatement(Statement $statement): SummarizedResult
{
return $this->tsx->runStatement($statement);
Expand All @@ -52,7 +41,7 @@ public function runStatement(Statement $statement): SummarizedResult
/**
* @param iterable<Statement> $statements
*
* @return CypherList<SummarizedResult<CypherMap>>
* @return CypherList<SummarizedResult>
*/
public function runStatements(iterable $statements): CypherList
{
Expand All @@ -62,7 +51,7 @@ public function runStatements(iterable $statements): CypherList
/**
* @param iterable<Statement> $statements
*
* @return CypherList<SummarizedResult<CypherMap>>
* @return CypherList<SummarizedResult>
*/
public function commit(iterable $statements = []): CypherList
{
Expand Down
13 changes: 8 additions & 5 deletions src/Bolt/BoltConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,23 @@
use Laudis\Neo4j\Common\Neo4jLogger;
use Laudis\Neo4j\Contracts\AuthenticateInterface;
use Laudis\Neo4j\Contracts\ConnectionInterface;
use Laudis\Neo4j\Contracts\FormatterInterface;
use Laudis\Neo4j\Databags\BookmarkHolder;
use Laudis\Neo4j\Databags\DatabaseInfo;
use Laudis\Neo4j\Databags\Neo4jError;
use Laudis\Neo4j\Enum\AccessMode;
use Laudis\Neo4j\Enum\ConnectionProtocol;
use Laudis\Neo4j\Exception\Neo4jException;
use Laudis\Neo4j\Formatter\SummarizedResultFormatter;
use Laudis\Neo4j\Types\CypherList;
use Psr\Http\Message\UriInterface;
use Psr\Log\LogLevel;
use Throwable;
use WeakReference;

/**
* @implements ConnectionInterface<array{0: V4_4|V5|V5_1|V5_2|V5_3|V5_4|null, 1: Connection}>
*
* @psalm-import-type BoltMeta from FormatterInterface
* @psalm-import-type BoltMeta from SummarizedResultFormatter
*/
class BoltConnection implements ConnectionInterface
{
Expand Down Expand Up @@ -80,7 +81,8 @@ public function __construct(
/** @psalm-readonly */
private readonly ConnectionConfiguration $config,
private readonly ?Neo4jLogger $logger,
) {}
) {
}

public function getEncryptionLevel(): string
{
Expand Down Expand Up @@ -247,14 +249,15 @@ public function run(
?string $database,
?float $timeout,
BookmarkHolder $holder,
?AccessMode $mode
?AccessMode $mode,
): array {
$extra = $this->buildRunExtra($database, $timeout, $holder, $mode);
$this->logger?->log(LogLevel::DEBUG, 'RUN', $extra);
$response = $this->protocol()
->run($text, $parameters, $extra)
->getResponse();
$this->assertNoFailure($response);

/** @var BoltMeta */
return $response->content;
}
Expand Down Expand Up @@ -341,7 +344,7 @@ public function close(): void

unset($this->boltProtocol); // has to be set to null as the sockets don't recover nicely contrary to what the underlying code might lead you to believe;
}
} catch (\Throwable) {
} catch (Throwable) {
}
}

Expand Down
Loading
Loading