Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 22 additions & 0 deletions src/Dialect/DataApiBuilderDialect.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace GraphqlOrm\Dialect;

use GraphqlOrm\Query\Expr\FilterExpressionInterface;
use GraphqlOrm\Query\QueryOptions;
use GraphqlOrm\Query\Walker\DABGraphqlWalker;
use GraphqlOrm\Query\Walker\GraphqlWalkerInterface;

Expand All @@ -21,4 +23,24 @@ public function createWalker(): GraphqlWalkerInterface
{
return new DABGraphqlWalker();
}

public function applyQueryOptions(array $arguments, QueryOptions $options): array
{
if ($options->limit !== null) {
$arguments['first'] = $options->limit;
}

$arguments['orderBy'] = $options->orderBy;

return $arguments;
}

public function applyFilter(?FilterExpressionInterface $filter): array
{
if (!$filter) {
return [];
}

return ['filter' => $filter->toArray()];
}
}
20 changes: 20 additions & 0 deletions src/Dialect/DefaultDialect.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace GraphqlOrm\Dialect;

use GraphqlOrm\Query\Expr\FilterExpressionInterface;
use GraphqlOrm\Query\QueryOptions;
use GraphqlOrm\Query\Walker\DefaultGraphqlWalker;
use GraphqlOrm\Query\Walker\GraphqlWalkerInterface;

Expand All @@ -18,4 +20,22 @@ public function createWalker(): GraphqlWalkerInterface
{
return new DefaultGraphqlWalker();
}

public function applyQueryOptions(array $arguments, QueryOptions $options): array
{
if ($options->limit !== null) {
$arguments['first'] = $options->limit;
}

return $arguments;
}

public function applyFilter(?FilterExpressionInterface $filter): array
{
if (!$filter) {
return [];
}

return $filter->toArray();
}
}
14 changes: 14 additions & 0 deletions src/Dialect/GraphqlQueryDialect.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace GraphqlOrm\Dialect;

use GraphqlOrm\Query\Expr\FilterExpressionInterface;
use GraphqlOrm\Query\QueryOptions;
use GraphqlOrm\Query\Walker\GraphqlWalkerInterface;

interface GraphqlQueryDialect
Expand All @@ -16,4 +18,16 @@ interface GraphqlQueryDialect
public function extractCollection(array $data): array;

public function createWalker(): GraphqlWalkerInterface;

/**
* @param array<string, mixed> $arguments
*
* @return array<string, mixed>
*/
public function applyQueryOptions(array $arguments, QueryOptions $options): array;

/**
* @return array<string, mixed>
*/
public function applyFilter(?FilterExpressionInterface $filter): array;
}
11 changes: 11 additions & 0 deletions src/Query/Direction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace GraphqlOrm\Query;

enum Direction: string
{
case ASC = 'ASC';
case DESC = 'DESC';
}
24 changes: 24 additions & 0 deletions src/Query/Expr/ComparisonExpression.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace GraphqlOrm\Query\Expr;

final class ComparisonExpression implements FilterExpressionInterface
{
public function __construct(
private string $field,
private string $operator,
private mixed $value,
) {
}

public function toArray(): array
{
return [
$this->field => [
$this->operator => $this->value,
],
];
}
}
61 changes: 61 additions & 0 deletions src/Query/Expr/ExpressionBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

declare(strict_types=1);

namespace GraphqlOrm\Query\Expr;

final class ExpressionBuilder
{
public function eq(string $field, mixed $value): ComparisonExpression
{
return new ComparisonExpression($field, 'eq', $value);
}

public function contains(string $field, string $value): ComparisonExpression
{
return new ComparisonExpression($field, 'contains', $value);
}

public function notContains(string $field, string $value): ComparisonExpression
{
return new ComparisonExpression($field, 'notContains', $value);
}

public function startsWith(string $field, string $value): ComparisonExpression
{
return new ComparisonExpression($field, 'startsWith', $value);
}

public function endsWith(string $field, string $value): ComparisonExpression
{
return new ComparisonExpression($field, 'endsWith', $value);
}

/**
* @param mixed[] $values
*/
public function in(string $field, array $values): ComparisonExpression
{
return new ComparisonExpression($field, 'in', $values);
}

public function isNull(string $field): ComparisonExpression
{
return new ComparisonExpression($field, 'isNull', true);
}

public function neq(string $field, mixed $value): ComparisonExpression
{
return new ComparisonExpression($field, 'neq', $value);
}

public function andX(FilterExpressionInterface ...$expr): LogicalExpression
{
return new LogicalExpression('and', $expr);
}

public function orX(FilterExpressionInterface ...$expr): LogicalExpression
{
return new LogicalExpression('or', $expr);
}
}
13 changes: 13 additions & 0 deletions src/Query/Expr/FilterExpressionInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace GraphqlOrm\Query\Expr;

interface FilterExpressionInterface
{
/**
* @return array<string,mixed>
*/
public function toArray(): array;
}
24 changes: 24 additions & 0 deletions src/Query/Expr/LogicalExpression.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace GraphqlOrm\Query\Expr;

final class LogicalExpression implements FilterExpressionInterface
{
/**
* @param FilterExpressionInterface[] $expressions
*/
public function __construct(
private string $operator,
private array $expressions,
) {
}

public function toArray(): array
{
return [
$this->operator => array_map(fn ($expr) => $expr->toArray(), $this->expressions),
];
}
}
36 changes: 34 additions & 2 deletions src/Query/GraphqlQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace GraphqlOrm\Query;

use GraphqlOrm\GraphqlManager;
use GraphqlOrm\Query\Expr\ExpressionBuilder;
use GraphqlOrm\Query\Expr\FilterExpressionInterface;

/**
* @template T of object
Expand All @@ -16,6 +18,7 @@ final class GraphqlQueryBuilder
/** @var string[]|null */
private ?array $selectedFields = null;
private ?string $graphql = null;
private ?FilterExpressionInterface $filter = null;

/**
* @param class-string<T> $entityClass
Expand All @@ -24,6 +27,7 @@ final class GraphqlQueryBuilder
public function __construct(
private readonly string $entityClass,
private readonly GraphqlManager $manager,
private readonly QueryOptions $options = new QueryOptions(),
) {
}

Expand Down Expand Up @@ -53,13 +57,39 @@ public function addSelect(string $field): self
/**
* @return GraphqlQueryBuilder<T>
*/
public function where(string $field, mixed $value): self
public function where(FilterExpressionInterface $expr): self
{
$this->criteria[$field] = $value;
$this->filter = $expr;

return $this;
}

/**
* @return GraphqlQueryBuilder<T>
*/
public function limit(int $limit): self
{
$this->options->limit = $limit;

return $this;
}

/**
* @return GraphqlQueryBuilder<T>
*/
public function orderBy(string $orderBy, Direction $direction): self
{
$this->options->orderBy ??= [];
$this->options->orderBy[$orderBy] = $direction;

return $this;
}

public function expr(): ExpressionBuilder
{
return new ExpressionBuilder();
}

/**
* @return GraphqlQueryBuilder<T>
*/
Expand Down Expand Up @@ -99,6 +129,8 @@ public function getQuery(): GraphqlQuery
->entity($this->entityClass)
->root($metadata->name)
->arguments($this->criteria)
->options($this->options)
->filter($this->filter)
->fields($fields, $manualSelect)
->build();

Expand Down
32 changes: 31 additions & 1 deletion src/Query/GraphqlQueryStringBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use GraphqlOrm\Query\Ast\FieldNode;
use GraphqlOrm\Query\Ast\QueryNode;
use GraphqlOrm\Query\Ast\SelectionSetNode;
use GraphqlOrm\Query\Expr\FilterExpressionInterface;

/**
* @template T of object
Expand All @@ -27,13 +28,16 @@ final class GraphqlQueryStringBuilder
private ?bool $manualSelect = false;
/** @var array<string, bool> */
private array $visited = [];
private QueryOptions $options;
private ?FilterExpressionInterface $filter = null;

/**
* @param GraphqlManager<T> $manager
*/
public function __construct(
private readonly GraphqlManager $manager,
) {
$this->options = new QueryOptions();
}

/**
Expand Down Expand Up @@ -83,13 +87,39 @@ public function entity(string $entityClass): self
return $this;
}

/**
* @return GraphqlQueryStringBuilder<T>
*/
public function options(QueryOptions $options): self
{
$this->options = $options;

return $this;
}

/**
* @return GraphqlQueryStringBuilder<T>
*/
public function filter(?FilterExpressionInterface $filter): self
{
$this->filter = $filter;

return $this;
}

public function build(): QueryNode
{
$query = new QueryNode();

$dialect = $this->manager->getDialect();

$options = $dialect->applyQueryOptions($this->arguments, $this->options);
$filter = $dialect->applyFilter($this->filter);
$args = [...$options, ...$filter];

$root = new FieldNode(
$this->root,
$this->arguments,
$args,
new SelectionSetNode()
);

Expand Down
17 changes: 17 additions & 0 deletions src/Query/QueryOptions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace GraphqlOrm\Query;

use GraphqlOrm\Query\Expr\FilterExpressionInterface;

final class QueryOptions
{
public ?int $limit = null;

public ?FilterExpressionInterface $filter = null;

/** @var array<string, Direction>|null */
public ?array $orderBy = null;
}
Loading