$parameters
+ */
+ private static function joinParts(Group $group, array $parts, array $parameters): Fragment
+ {
+ if ($parts === []) {
+ return Fragment::of(sql: '', parameters: []);
+ }
+
+ $connective = $group->operator() === LogicalOperator::AND ? ' AND ' : ' OR ';
+ $sql = count($parts) === 1 ? $parts[0] : sprintf('(%s)', implode($connective, $parts));
+
+ return Fragment::of(sql: $sql, parameters: $parameters);
+ }
+
/**
* Renders a group, joining its non-empty children with the group connective.
*
@@ -111,7 +127,7 @@ private static function renderGroup(Group $group, int $offset, FilterColumns $co
foreach ($group->filters() as $child) {
$fragment = self::render(
filter: $child,
- offset: $offset + count($parameters),
+ offset: ($offset + count($parameters)),
columns: $columns,
renderers: $renderers
);
@@ -124,14 +140,7 @@ private static function renderGroup(Group $group, int $offset, FilterColumns $co
$parameters = [...$parameters, ...$fragment->parameters()];
}
- if ($parts === []) {
- return Fragment::of(sql: '', parameters: []);
- }
-
- $connective = $group->operator() === LogicalOperator::AND ? ' AND ' : ' OR ';
- $sql = count($parts) === 1 ? $parts[0] : sprintf('(%s)', implode($connective, $parts));
-
- return Fragment::of(sql: $sql, parameters: $parameters);
+ return self::joinParts(group: $group, parts: $parts, parameters: $parameters);
}
/**
diff --git a/src/Cursor/Criteria.php b/src/Cursor/Criteria.php
index bbb739f..b8cfa15 100644
--- a/src/Cursor/Criteria.php
+++ b/src/Cursor/Criteria.php
@@ -40,14 +40,13 @@ private function __construct(
}
/**
- * Creates a Criteria from the request and an optional schema.
+ * Creates a Criteria from the schema and the request.
*
- * When the schema is omitted, an empty contract applies: the default page-size bounds, no
- * filterable or sortable field, and no default sort. Any incoming filter or sort is then
- * rejected. The pagination always carries the incoming cursor token and the page size.
+ * It parses the request query string and validates it against the schema. The pagination
+ * always carries the incoming cursor token and the page size.
*
+ * @param Schema $schema The query contract the request is validated against.
* @param ServerRequestInterface $request The incoming PSR-7 server request.
- * @param Schema|null $schema The query contract, or null for the empty contract.
* @return Criteria The criteria carrying the validated comparisons, the effective sort, and the pagination.
* @throws FilterExpressionIsInvalid If the filter expression cannot be parsed.
* @throws SortExpressionIsInvalid If the sort expression cannot be parsed.
@@ -58,9 +57,9 @@ private function __construct(
* @throws FilterValueNotAllowed If a compared value falls outside the permitted set or kind.
* @throws SortFieldNotAllowed If the sort orders by a field that was never declared sortable.
*/
- public static function fromQuery(ServerRequestInterface $request, ?Schema $schema = null): Criteria
+ public static function fromQuery(Schema $schema, ServerRequestInterface $request): Criteria
{
- $query = Query::from(schema: $schema ?? Schema::default(), request: $request);
+ $query = Query::from(schema: $schema, request: $request);
$cursor = Token::from(token: $query->cursorToken());
return new Criteria(
@@ -72,6 +71,27 @@ public static function fromQuery(ServerRequestInterface $request, ?Schema $schem
);
}
+ /**
+ * Creates a Criteria from the request under the default schema.
+ *
+ * The default schema is an empty contract: the default page-size bounds, no filterable or
+ * sortable field, and no default sort. Any incoming filter or sort is then rejected, and the
+ * pagination always carries the incoming cursor token and the page size.
+ *
+ * @param ServerRequestInterface $request The incoming PSR-7 server request.
+ * @return Criteria The criteria carrying the validated comparisons, the effective sort, and the pagination.
+ * @throws FilterExpressionIsInvalid If the filter expression cannot be parsed.
+ * @throws SortExpressionIsInvalid If the sort expression cannot be parsed.
+ * @throws PageSizeOutOfRange If the page size falls outside the valid range.
+ * @throws FilterShapeNotSupported If the filter is not a comparison or an AND group of comparisons.
+ * @throws FilterFieldNotAllowed If a comparison targets a field that was never allowed.
+ * @throws SortFieldNotAllowed If the sort orders by a field that was never declared sortable.
+ */
+ public static function fromQueryWithDefaultSchema(ServerRequestInterface $request): Criteria
+ {
+ return Criteria::fromQuery(schema: Schema::default(), request: $request);
+ }
+
/**
* Returns the effective sort.
*
diff --git a/src/Cursor/Keyset.php b/src/Cursor/Keyset.php
index c9f8ea3..dc952bf 100644
--- a/src/Cursor/Keyset.php
+++ b/src/Cursor/Keyset.php
@@ -61,7 +61,7 @@ public function page(iterable $items, ?Closure $keysOf = null): Page
sort: $this->submittedSort,
items: $items,
filter: $this->filter,
- keysOf: $keysOf ?? SortKeys::from(sort: $this->sort),
+ keysOf: ($keysOf ?? SortKeys::from(sort: $this->sort)),
pagination: $this->pagination
);
}
diff --git a/src/Exceptions/PageSizeOutOfRange.php b/src/Exceptions/PageSizeOutOfRange.php
index a05d5bb..cbd564e 100644
--- a/src/Exceptions/PageSizeOutOfRange.php
+++ b/src/Exceptions/PageSizeOutOfRange.php
@@ -5,7 +5,6 @@
namespace TinyBlocks\HttpQuery\Exceptions;
use InvalidArgumentException;
-use TinyBlocks\HttpQuery\Schema;
/**
* Raised when a requested page size falls outside the valid range.
diff --git a/src/Internal/AllowedField.php b/src/Internal/AllowedField.php
index 9e87a06..5849059 100644
--- a/src/Internal/AllowedField.php
+++ b/src/Internal/AllowedField.php
@@ -31,13 +31,7 @@ public function permit(Comparison $comparison): Comparison
}
foreach ($comparison->values() as $value) {
- if (!is_null($this->values) && !in_array($value, $this->values, true)) {
- throw FilterValueNotAllowed::notPermitted(field: $this->field, value: $value);
- }
-
- if (!is_null($this->kind) && !$this->kind->matches(value: $value)) {
- throw FilterValueNotAllowed::kindMismatch(kind: $this->kind, field: $this->field, value: $value);
- }
+ $this->permitValue(value: $value);
}
return $comparison;
@@ -47,4 +41,15 @@ public function hasField(string $field): bool
{
return $this->field === $field;
}
+
+ private function permitValue(string $value): void
+ {
+ if (!is_null($this->values) && !in_array($value, $this->values, true)) {
+ throw FilterValueNotAllowed::notPermitted(field: $this->field, value: $value);
+ }
+
+ if (!is_null($this->kind) && !$this->kind->matches(value: $value)) {
+ throw FilterValueNotAllowed::kindMismatch(kind: $this->kind, field: $this->field, value: $value);
+ }
+ }
}
diff --git a/src/Internal/Cursor/CursorCodec.php b/src/Internal/Cursor/CursorCodec.php
index 5da62d0..b481a2e 100644
--- a/src/Internal/Cursor/CursorCodec.php
+++ b/src/Internal/Cursor/CursorCodec.php
@@ -15,23 +15,12 @@ private function __construct()
public static function decode(string $token): array
{
$decoded = base64_decode(strtr($token, '-_', '+/'), true);
+ $keys = $decoded === false ? null : json_decode($decoded, true);
- if ($decoded === false) {
+ if (!is_array($keys) || !array_is_list($keys) || !CursorCodec::hasOnlyScalarsOrNulls(keys: $keys)) {
throw CursorIsInvalid::from(token: $token);
}
- $keys = json_decode($decoded, true);
-
- if (!is_array($keys) || !array_is_list($keys)) {
- throw CursorIsInvalid::from(token: $token);
- }
-
- foreach ($keys as $value) {
- if (!is_scalar($value) && !is_null($value)) {
- throw CursorIsInvalid::from(token: $token);
- }
- }
-
return $keys;
}
@@ -44,4 +33,15 @@ public static function encode(array $keys): string
|> (static fn(string $encoded): string => strtr($encoded, '+/', '-_'))
|> (static fn(string $encoded): string => rtrim($encoded, '='));
}
+
+ private static function hasOnlyScalarsOrNulls(array $keys): bool
+ {
+ foreach ($keys as $value) {
+ if (!is_scalar($value) && !is_null($value)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
}
diff --git a/src/Internal/FilterClause.php b/src/Internal/FilterClause.php
index dc20e06..38fe908 100644
--- a/src/Internal/FilterClause.php
+++ b/src/Internal/FilterClause.php
@@ -26,7 +26,7 @@ public static function from(FilterColumn $column, int $offset, Comparison $compa
{
$values = array_map($column->normalize(...), $comparison->values());
$names = array_map(
- static fn(int $index): string => sprintf('filter_%d', $offset + $index),
+ static fn(int $index): string => sprintf('filter_%d', ($offset + $index)),
array_keys($values)
);
$parameters = array_combine($names, $values);
diff --git a/src/Internal/Offset/Offset.php b/src/Internal/Offset/Offset.php
index 39f13fa..370fa9b 100644
--- a/src/Internal/Offset/Offset.php
+++ b/src/Internal/Offset/Offset.php
@@ -24,7 +24,7 @@ public static function from(int $value): Offset
public static function fromPage(PageNumber $page, Limit $limit): Offset
{
- return new Offset(value: ($page->value() - 1) * $limit->value());
+ return new Offset(value: (($page->value() - 1) * $limit->value()));
}
public function value(): int
diff --git a/src/Internal/Offset/PageNumber.php b/src/Internal/Offset/PageNumber.php
index 4c7aaff..69b4c4f 100644
--- a/src/Internal/Offset/PageNumber.php
+++ b/src/Internal/Offset/PageNumber.php
@@ -24,12 +24,12 @@ public static function from(int $value): PageNumber
public static function fromOffset(Limit $limit, Offset $offset): PageNumber
{
- return new PageNumber(value: intdiv($offset->value(), $limit->value()) + 1);
+ return new PageNumber(value: (intdiv($offset->value(), $limit->value()) + 1));
}
public function next(): PageNumber
{
- return new PageNumber(value: $this->value + 1);
+ return new PageNumber(value: ($this->value + 1));
}
public function value(): int
@@ -44,6 +44,6 @@ public function isFirst(): bool
public function previous(): ?PageNumber
{
- return $this->isFirst() ? null : new PageNumber(value: $this->value - 1);
+ return $this->isFirst() ? null : new PageNumber(value: ($this->value - 1));
}
}
diff --git a/src/Internal/Query.php b/src/Internal/Query.php
index c4311cd..67d39b5 100644
--- a/src/Internal/Query.php
+++ b/src/Internal/Query.php
@@ -31,9 +31,9 @@ public static function from(Schema $schema, ServerRequestInterface $request): Qu
$parameters = QueryParameters::from(request: $request);
$page = $parameters->get(key: 'page')->toArray();
- $size = Attribute::from(value: $page['size'] ?? null);
- $cursor = Attribute::from(value: $page['cursor'] ?? null);
- $number = Attribute::from(value: $page['number'] ?? null);
+ $size = Attribute::from(value: ($page['size'] ?? null));
+ $cursor = Attribute::from(value: ($page['cursor'] ?? null));
+ $number = Attribute::from(value: ($page['number'] ?? null));
$expression = $parameters->get(key: 'filter')->toString();
$filter = $expression === '' ? Group::none() : FilterParser::from(input: $expression)->parse();
diff --git a/src/Internal/Rsql/FilterParser.php b/src/Internal/Rsql/FilterParser.php
index 7484727..ceea706 100644
--- a/src/Internal/Rsql/FilterParser.php
+++ b/src/Internal/Rsql/FilterParser.php
@@ -64,7 +64,7 @@ private function constraint(int $depth): Filter
}
$this->scanner->expect(character: '(');
- $group = $this->disjunction(depth: $depth + 1);
+ $group = $this->disjunction(depth: ($depth + 1));
$this->scanner->expect(character: ')');
return $group;
diff --git a/src/Internal/Rsql/Scanner.php b/src/Internal/Rsql/Scanner.php
index c9dfba8..e6b3594 100644
--- a/src/Internal/Rsql/Scanner.php
+++ b/src/Internal/Rsql/Scanner.php
@@ -24,7 +24,7 @@ public static function from(string $input): Scanner
public function peek(): string
{
- return $this->input[$this->position] ?? '';
+ return ($this->input[$this->position] ?? '');
}
public function value(): string
@@ -58,7 +58,7 @@ private function quoted(string $quote): string
$character = $this->input[$this->position];
if ($character === '\\') {
- $characters[] = $this->input[$this->position + 1] ?? '';
+ $characters[] = ($this->input[($this->position + 1)] ?? '');
$this->position += 2;
continue;
}
@@ -107,7 +107,7 @@ public function unreserved(): string
$this->position++;
}
- $token = substr($this->input, $start, $this->position - $start);
+ $token = substr($this->input, $start, ($this->position - $start));
if ($token === '') {
throw FilterExpressionIsInvalid::from(expression: $this->input);
diff --git a/src/Limit.php b/src/Limit.php
index f42c1cf..7d0f47a 100644
--- a/src/Limit.php
+++ b/src/Limit.php
@@ -32,7 +32,7 @@ public static function of(int $size): Limit
*/
public function plus(int $extra): Limit
{
- return new Limit(size: $this->size + $extra);
+ return new Limit(size: ($this->size + $extra));
}
/**
diff --git a/src/Offset/Criteria.php b/src/Offset/Criteria.php
index cf19643..a41f2df 100644
--- a/src/Offset/Criteria.php
+++ b/src/Offset/Criteria.php
@@ -42,14 +42,13 @@ private function __construct(
}
/**
- * Creates a Criteria from the request and an optional schema.
+ * Creates a Criteria from the schema and the request.
*
- * When the schema is omitted, an empty contract applies: the default page-size bounds, no
- * filterable or sortable field, and no default sort. Any incoming filter or sort is then
- * rejected. The pagination derives its offset from the one-based page number and the page size.
+ * It parses the request query string and validates it against the schema. The pagination
+ * derives its offset from the one-based page number and the page size.
*
+ * @param Schema $schema The query contract the request is validated against.
* @param ServerRequestInterface $request The incoming PSR-7 server request.
- * @param Schema|null $schema The query contract, or null for the empty contract.
* @return Criteria The criteria carrying the validated comparisons, the effective sort, and the pagination.
* @throws FilterExpressionIsInvalid If the filter expression cannot be parsed.
* @throws SortExpressionIsInvalid If the sort expression cannot be parsed.
@@ -61,9 +60,9 @@ private function __construct(
* @throws FilterValueNotAllowed If a compared value falls outside the permitted set or kind.
* @throws SortFieldNotAllowed If the sort orders by a field that was never declared sortable.
*/
- public static function fromQuery(ServerRequestInterface $request, ?Schema $schema = null): Criteria
+ public static function fromQuery(Schema $schema, ServerRequestInterface $request): Criteria
{
- $query = Query::from(schema: $schema ?? Schema::default(), request: $request);
+ $query = Query::from(schema: $schema, request: $request);
return new Criteria(
sort: $query->sort(),
@@ -74,6 +73,28 @@ public static function fromQuery(ServerRequestInterface $request, ?Schema $schem
);
}
+ /**
+ * Creates a Criteria from the request under the default schema.
+ *
+ * The default schema is an empty contract: the default page-size bounds, no filterable or
+ * sortable field, and no default sort. Any incoming filter or sort is then rejected, and the
+ * pagination derives its offset from the one-based page number and the page size.
+ *
+ * @param ServerRequestInterface $request The incoming PSR-7 server request.
+ * @return Criteria The criteria carrying the validated comparisons, the effective sort, and the pagination.
+ * @throws FilterExpressionIsInvalid If the filter expression cannot be parsed.
+ * @throws SortExpressionIsInvalid If the sort expression cannot be parsed.
+ * @throws PageNumberOutOfRange If the page number is less than 1.
+ * @throws PageSizeOutOfRange If the page size falls outside the valid range.
+ * @throws FilterShapeNotSupported If the filter is not a comparison or an AND group of comparisons.
+ * @throws FilterFieldNotAllowed If a comparison targets a field that was never allowed.
+ * @throws SortFieldNotAllowed If the sort orders by a field that was never declared sortable.
+ */
+ public static function fromQueryWithDefaultSchema(ServerRequestInterface $request): Criteria
+ {
+ return Criteria::fromQuery(schema: Schema::default(), request: $request);
+ }
+
/**
* Creates a Page from the total element count and the items.
*
diff --git a/tests/Unit/Clause/SeekClauseTest.php b/tests/Unit/Clause/SeekClauseTest.php
index e40805b..c69527e 100644
--- a/tests/Unit/Clause/SeekClauseTest.php
+++ b/tests/Unit/Clause/SeekClauseTest.php
@@ -18,8 +18,8 @@ public function testFromWhenNoIncomingCursorThenYieldsAnEmptyPredicate(): void
{
/** @Given a keyset over a sort with no incoming cursor */
$keyset = Criteria::fromQuery(
- request: Query::from(parameters: ['sort' => '-created_at,id', 'page' => ['size' => '2']]),
- schema: Schema::create()->sortable(fields: ['id', 'created_at'])
+ schema: Schema::create()->sortable(fields: ['id', 'created_at']),
+ request: Query::from(parameters: ['sort' => '-created_at,id', 'page' => ['size' => '2']])
)->keyset();
/** @When the seek predicate is assembled */
@@ -43,10 +43,10 @@ public function testFromWhenMultipleOrdersThenRendersTheRowValueComparison(): vo
/** @And a keyset descending by creation time then ascending by identifier following the cursor */
$keyset = Criteria::fromQuery(
+ schema: Schema::create()->sortable(fields: ['id', 'created_at']),
request: Query::from(
parameters: ['sort' => '-created_at,id', 'page' => ['cursor' => $token, 'size' => '2']]
- ),
- schema: Schema::create()->sortable(fields: ['id', 'created_at'])
+ )
)->keyset();
/** @When the seek predicate is assembled */
@@ -81,10 +81,10 @@ public function testFromWhenSingleDescendingOrderThenSelectsRowsBelowTheCursor()
/** @And a keyset descending by that single field following the cursor */
$keyset = Criteria::fromQuery(
+ schema: Schema::create()->sortable(fields: ['created_at']),
request: Query::from(
parameters: ['sort' => '-created_at', 'page' => ['cursor' => $token, 'size' => '2']]
- ),
- schema: Schema::create()->sortable(fields: ['created_at'])
+ )
)->keyset();
/** @When the seek predicate is assembled */
diff --git a/tests/Unit/Cursor/CriteriaTest.php b/tests/Unit/Cursor/CriteriaTest.php
index 9c762a1..afd3184 100644
--- a/tests/Unit/Cursor/CriteriaTest.php
+++ b/tests/Unit/Cursor/CriteriaTest.php
@@ -24,7 +24,7 @@ public function testFromQueryWhenEmptyThenSortIsEmpty(): void
$query = Query::from(parameters: []);
/** @When building the criteria from the query */
- $criteria = Criteria::fromQuery(request: $query);
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: $query);
/** @Then the effective sort is empty */
self::assertTrue($criteria->sort()->isEmpty());
@@ -36,7 +36,7 @@ public function testFromQueryWhenEmptyThenComparisonsAreEmpty(): void
$query = Query::from(parameters: []);
/** @When building the criteria from the query */
- $criteria = Criteria::fromQuery(request: $query);
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: $query);
/** @Then there is no comparison */
self::assertSame([], $criteria->comparisons());
@@ -48,7 +48,7 @@ public function testKeysetWhenBuiltWithoutCursorThenBuildsCursorPage(): void
$schema = Schema::create()->defaultSort(sort: Sort::fromExpression(expression: 'id'));
/** @And a criteria parsed from a request carrying a page size of two and no cursor */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['size' => '2']]), schema: $schema);
+ $criteria = Criteria::fromQuery(schema: $schema, request: Query::from(parameters: ['page' => ['size' => '2']]));
/** @When building a cursor page through the keyset view over the array rows fetched */
$page = $criteria->keyset()->page(items: [['id' => 10], ['id' => 20], ['id' => 30]]);
@@ -70,8 +70,8 @@ public function testKeysetWhenIncomingCursorPresentThenBuildsCursorPage(): void
/** @And a criteria parsed from a request carrying that cursor and a page size of two */
$criteria = Criteria::fromQuery(
- request: Query::from(parameters: ['page' => ['cursor' => $token, 'size' => '2']]),
- schema: $schema
+ schema: $schema,
+ request: Query::from(parameters: ['page' => ['cursor' => $token, 'size' => '2']])
);
/** @When building a cursor page through the keyset view over the items fetched */
@@ -87,7 +87,7 @@ public function testKeysetWhenIncomingCursorPresentThenBuildsCursorPage(): void
public function testKeysetWhenEffectiveSortIsEmptyThenThrowsSortIsRequired(): void
{
/** @Given a criteria parsed from a request carrying no sort and no schema default */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: []));
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: Query::from(parameters: []));
/** @Then an exception indicating a deterministic order is required is raised */
$this->expectException(SortIsRequired::class);
@@ -105,7 +105,7 @@ public function testFromQueryWhenCustomSchemaGivenThenAppliesItsDefaultPageSize(
->defaultSort(sort: Sort::fromExpression(expression: 'id'));
/** @When building the keyset view from a query carrying no page size and the schema */
- $keyset = Criteria::fromQuery(request: Query::from(parameters: []), schema: $schema)->keyset();
+ $keyset = Criteria::fromQuery(schema: $schema, request: Query::from(parameters: []))->keyset();
/** @Then the keyset carries the schema default page size */
self::assertSame(5, $keyset->limit()->toInteger());
@@ -121,8 +121,8 @@ public function testFromQueryWhenCursorPresentThenKeysetCarriesPageSizeAndCursor
/** @And a criteria parsed from a request carrying that cursor and a page size of ten */
$criteria = Criteria::fromQuery(
- request: Query::from(parameters: ['page' => ['cursor' => $token, 'size' => '10']]),
- schema: $schema
+ schema: $schema,
+ request: Query::from(parameters: ['page' => ['cursor' => $token, 'size' => '10']])
);
/** @When building the keyset view */
@@ -145,7 +145,7 @@ public function testFromQueryWhenPerPageAboveMaximumThenThrowsPageSizeOutOfRange
$this->expectExceptionMessage('Page size');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query);
+ Criteria::fromQueryWithDefaultSchema(request: $query);
}
public function testFromQueryWhenFilterAndSortGivenThenEachSpecificationIsValidated(): void
@@ -159,7 +159,7 @@ public function testFromQueryWhenFilterAndSortGivenThenEachSpecificationIsValida
$query = Query::from(parameters: ['sort' => '-created_at', 'filter' => 'status==paid']);
/** @When building the criteria from the query and the schema */
- $criteria = Criteria::fromQuery(request: $query, schema: $schema);
+ $criteria = Criteria::fromQuery(schema: $schema, request: $query);
/** @Then the validated comparisons carry the filtered field and value */
self::assertEquals(
diff --git a/tests/Unit/Cursor/KeysetTest.php b/tests/Unit/Cursor/KeysetTest.php
index ca7eb2a..1edf869 100644
--- a/tests/Unit/Cursor/KeysetTest.php
+++ b/tests/Unit/Cursor/KeysetTest.php
@@ -30,8 +30,8 @@ public function testLimitThenReturnsThePageSize(): void
{
/** @Given a keyset view built from a request carrying a sort and a page size of fifteen */
$keyset = Criteria::fromQuery(
- request: Query::from(parameters: ['sort' => 'id', 'page' => ['size' => '15']]),
- schema: $this->schema
+ schema: $this->schema,
+ request: Query::from(parameters: ['sort' => 'id', 'page' => ['size' => '15']])
)->keyset();
/** @When reading the page size */
@@ -44,7 +44,7 @@ public function testLimitThenReturnsThePageSize(): void
public function testOrdersWhenSortGivenThenReturnsItsOrders(): void
{
/** @Given a keyset view built from a descending sort over a single field */
- $keyset = Criteria::fromQuery(request: Query::from(parameters: ['sort' => '-name']), schema: $this->schema)
+ $keyset = Criteria::fromQuery(schema: $this->schema, request: Query::from(parameters: ['sort' => '-name']))
->keyset();
/** @When reading the orders */
@@ -58,8 +58,8 @@ public function testPageWhenKeysOfGivenThenUsesTheExtractor(): void
{
/** @Given a keyset view built from a request carrying a sort and a page size of two */
$keyset = Criteria::fromQuery(
- request: Query::from(parameters: ['sort' => 'id', 'page' => ['size' => '2']]),
- schema: $this->schema
+ schema: $this->schema,
+ request: Query::from(parameters: ['sort' => 'id', 'page' => ['size' => '2']])
)->keyset();
/** @When building the page from the items and an explicit key extractor */
@@ -76,8 +76,8 @@ public function testCursorWhenNoIncomingCursorThenEverySortFieldIsNull(): void
{
/** @Given a keyset view built from a request carrying a sort over two fields */
$keyset = Criteria::fromQuery(
- request: Query::from(parameters: ['sort' => 'created_at,id', 'page' => ['size' => '2']]),
- schema: $this->schema
+ schema: $this->schema,
+ request: Query::from(parameters: ['sort' => 'created_at,id', 'page' => ['size' => '2']])
)->keyset();
/** @When reading the incoming cursor key values */
@@ -91,8 +91,8 @@ public function testPageWhenNoKeysOfGivenThenDerivesKeysFromTheSortFields(): voi
{
/** @Given a keyset view built from a request carrying a sort and a page size of two */
$keyset = Criteria::fromQuery(
- request: Query::from(parameters: ['sort' => 'id', 'page' => ['size' => '2']]),
- schema: $this->schema
+ schema: $this->schema,
+ request: Query::from(parameters: ['sort' => 'id', 'page' => ['size' => '2']])
)->keyset();
/** @When building the page from array rows without a key extractor */
@@ -112,10 +112,10 @@ public function testCursorWhenIncomingCursorGivenThenKeysValuesBySortField(): vo
/** @And a keyset view built from a request carrying that cursor and a sort over two fields */
$keyset = Criteria::fromQuery(
+ schema: $this->schema,
request: Query::from(
parameters: ['sort' => 'created_at,id', 'page' => ['cursor' => $token, 'size' => '2']]
- ),
- schema: $this->schema
+ )
)->keyset();
/** @When reading the incoming cursor key values */
@@ -132,10 +132,10 @@ public function testCursorWhenDecodedCountMismatchesThenThrowsCursorIsInvalid():
/** @And a keyset view whose sort carries two fields */
$keyset = Criteria::fromQuery(
+ schema: $this->schema,
request: Query::from(
parameters: ['sort' => 'created_at,id', 'page' => ['cursor' => $token, 'size' => '2']]
- ),
- schema: $this->schema
+ )
)->keyset();
/** @Then an exception indicating the cursor is invalid is raised */
diff --git a/tests/Unit/DisjunctionTest.php b/tests/Unit/DisjunctionTest.php
index 9e54873..c85aebf 100644
--- a/tests/Unit/DisjunctionTest.php
+++ b/tests/Unit/DisjunctionTest.php
@@ -29,7 +29,7 @@ public function testCursorWhenDisjunctionAllowedThenExposesTheOrTree(): void
$query = Query::from(parameters: ['filter' => 'a==1,b==2']);
/** @When building the cursor criteria */
- $criteria = CursorCriteria::fromQuery(request: $query, schema: $schema);
+ $criteria = CursorCriteria::fromQuery(schema: $schema, request: $query);
/** @Then the filter tree is the OR group */
self::assertEquals(
@@ -57,7 +57,7 @@ public function testWhenDisjunctionAllowedThenValidatesEveryNestedLeaf(): void
$query = Query::from(parameters: ['filter' => '(a==1,b==2);c==3']);
/** @When building the criteria */
- $criteria = OffsetCriteria::fromQuery(request: $query, schema: $schema);
+ $criteria = OffsetCriteria::fromQuery(schema: $schema, request: $query);
/** @Then every nested leaf is validated and returned in tree order */
self::assertEquals(
@@ -85,7 +85,7 @@ public function testWhenDisjunctionAllowedAndFieldNotAllowedThenStillThrows(): v
$this->expectExceptionMessage('Filter field is not allowed.');
/** @When building the criteria */
- OffsetCriteria::fromQuery(request: $query, schema: $schema);
+ OffsetCriteria::fromQuery(schema: $schema, request: $query);
}
public function testOffsetWhenDisjunctionAllowedThenAcceptsTheOrGroupAndExposesTheTree(): void
@@ -100,7 +100,7 @@ public function testOffsetWhenDisjunctionAllowedThenAcceptsTheOrGroupAndExposesT
$query = Query::from(parameters: ['filter' => 'a==1,b==2']);
/** @When building the offset criteria */
- $criteria = OffsetCriteria::fromQuery(request: $query, schema: $schema);
+ $criteria = OffsetCriteria::fromQuery(schema: $schema, request: $query);
/** @Then the filter tree is the OR group and the comparisons carry every validated leaf */
self::assertEquals(
diff --git a/tests/Unit/EndToEndTest.php b/tests/Unit/EndToEndTest.php
index ab5a113..13fb227 100644
--- a/tests/Unit/EndToEndTest.php
+++ b/tests/Unit/EndToEndTest.php
@@ -30,7 +30,7 @@ public function testPipelineWhenOffsetRequestGivenThenPageRendersTheResponse():
]);
/** @And the criteria parsed from those parameters */
- $criteria = OffsetCriteria::fromQuery(request: $query, schema: $schema);
+ $criteria = OffsetCriteria::fromQuery(schema: $schema, request: $query);
/** @And the base URI the navigation links render against */
$base = '/v1/orders?filter=status==paid;total=ge=100&sort=-created_at,id';
@@ -74,7 +74,7 @@ public function testPipelineWhenCursorRequestGivenThenCursorPageRendersTheRespon
$query = Query::from(parameters: ['sort' => 'id', 'page' => ['cursor' => $token, 'size' => '2']]);
/** @And a cursor page built through the keyset view over the array rows fetched */
- $page = CursorCriteria::fromQuery(request: $query, schema: $schema)
+ $page = CursorCriteria::fromQuery(schema: $schema, request: $query)
->keyset()
->page(items: [['id' => 10], ['id' => 20], ['id' => 30]]);
@@ -114,7 +114,7 @@ public function testPipelineWhenOffsetRequestGivenThenLinkHeaderFoldsEveryRelati
]);
/** @And the criteria parsed from those parameters */
- $criteria = OffsetCriteria::fromQuery(request: $query, schema: $schema);
+ $criteria = OffsetCriteria::fromQuery(schema: $schema, request: $query);
/** @And the base URI the relations render against */
$base = '/v1/orders?filter=status==paid;total=ge=100&sort=-created_at,id';
diff --git a/tests/Unit/FilterTest.php b/tests/Unit/FilterTest.php
index 0cf97bd..3438ba6 100644
--- a/tests/Unit/FilterTest.php
+++ b/tests/Unit/FilterTest.php
@@ -39,7 +39,7 @@ public function testFromQueryWhenNoFilterThenComparisonsAreEmpty(): void
$query = Query::from(parameters: []);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then there is no comparison */
self::assertSame([], $comparisons);
@@ -51,7 +51,7 @@ public function testFromQueryWhenAndGroupThenComparisonsCarryEveryLeaf(): void
$query = Query::from(parameters: ['filter' => 'a==1;b==2']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the comparisons carry both leaves in order */
self::assertEquals([
@@ -66,7 +66,7 @@ public function testFromQueryWhenInListThenComparisonCarriesEveryValue(): void
$query = Query::from(parameters: ['filter' => 'role=in=(admin,user)']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the only comparison is an IN comparison carrying every listed value in order */
self::assertEquals(
@@ -81,7 +81,7 @@ public function testFromQueryWhenNotInListThenComparisonCarriesEveryValue(): voi
$query = Query::from(parameters: ['filter' => 'role=out=(a,b)']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the only comparison is a NOT_IN comparison carrying every listed value in order */
self::assertEquals(
@@ -100,7 +100,7 @@ public function testFromQueryWhenOrGroupThenThrowsFilterShapeNotSupported(): voi
$this->expectExceptionMessage('Filter shape is not supported.');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $this->schema);
+ Criteria::fromQuery(schema: $this->schema, request: $query);
}
public function testFromQueryWhenDoubleQuotedValueThenComparisonStripsQuotes(): void
@@ -109,7 +109,7 @@ public function testFromQueryWhenDoubleQuotedValueThenComparisonStripsQuotes():
$query = Query::from(parameters: ['filter' => 'name=="John Doe"']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the comparison carries the value with the surrounding quotes stripped */
self::assertEquals(
@@ -124,7 +124,7 @@ public function testFromQueryWhenSingleQuotedValueThenComparisonStripsQuotes():
$query = Query::from(parameters: ['filter' => "name=='John Doe'"]);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the comparison carries the value with the surrounding quotes stripped */
self::assertEquals(
@@ -143,7 +143,7 @@ public function testFromQueryWhenNestedGroupThenThrowsFilterShapeNotSupported():
$this->expectExceptionMessage('Filter shape <(a==1,b==2);c==3> is not supported.');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $this->schema);
+ Criteria::fromQuery(schema: $this->schema, request: $query);
}
public function testFromQueryWhenEscapedQuoteInValueThenComparisonKeepsTheQuote(): void
@@ -152,7 +152,7 @@ public function testFromQueryWhenEscapedQuoteInValueThenComparisonKeepsTheQuote(
$query = Query::from(parameters: ['filter' => 'name=="a\\"b"']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the comparison carries the value with the escaped quote unescaped */
self::assertEquals(
@@ -174,7 +174,7 @@ public function testFromQueryWhenFieldNotAllowedThenThrowsFilterFieldNotAllowed(
$this->expectExceptionMessage('Filter field is not allowed.');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
public function testFromQueryWhenValueBreaksKindThenThrowsFilterValueNotAllowed(): void
@@ -194,7 +194,7 @@ public function testFromQueryWhenValueBreaksKindThenThrowsFilterValueNotAllowed(
$this->expectExceptionMessage('does not match the datetime kind');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
public function testFromQueryWhenParenthesizedComparisonThenComparisonIsReturned(): void
@@ -203,7 +203,7 @@ public function testFromQueryWhenParenthesizedComparisonThenComparisonIsReturned
$query = Query::from(parameters: ['filter' => '(status==paid)']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the only comparison is the unwrapped equality */
self::assertEquals(
@@ -225,7 +225,7 @@ public function testFromQueryWhenDateTimeValueMatchesKindThenComparisonIsReturne
$query = Query::from(parameters: ['filter' => 'created_at=gt=2023-01-15T10:30:00Z']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $schema, request: $query)->comparisons();
/** @Then the only comparison carries the date-time value */
self::assertEquals([Comparison::of(
@@ -245,7 +245,7 @@ public function testFromQueryWhenMixedPrecedenceThenThrowsFilterShapeNotSupporte
$this->expectExceptionMessage('is not supported');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $this->schema);
+ Criteria::fromQuery(schema: $this->schema, request: $query);
}
public function testFromQueryWhenValueNotPermittedThenThrowsFilterValueNotAllowed(): void
@@ -265,7 +265,7 @@ public function testFromQueryWhenValueNotPermittedThenThrowsFilterValueNotAllowe
$this->expectExceptionMessage('Value is not permitted for filter field .');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
public function testFromQueryWhenParenthesizedAndGroupThenComparisonsCarryEveryLeaf(): void
@@ -274,7 +274,7 @@ public function testFromQueryWhenParenthesizedAndGroupThenComparisonsCarryEveryL
$query = Query::from(parameters: ['filter' => '(a==1;b==2)']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the comparisons carry both leaves in order */
self::assertEquals([
@@ -289,7 +289,7 @@ public function testFromQueryWhenSingleComparisonThenComparisonCarriesFieldAndVa
$query = Query::from(parameters: ['filter' => 'status==paid']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the only comparison is an equality on the named field with its value */
self::assertEquals(
@@ -307,7 +307,7 @@ public function testFromQueryWhenComparisonOperatorThenComparisonCarriesThatOper
$query = Query::from(parameters: ['filter' => $expression]);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the only comparison carries the expected operator */
self::assertEquals([Comparison::of(field: 'a', values: ['b'], operator: $expected)], $comparisons);
@@ -326,7 +326,7 @@ public function testFromQueryWhenOperatorNotAllowedThenThrowsFilterOperatorNotAl
$this->expectExceptionMessage('Operator is not allowed for filter field .');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
public function testFromQueryWhenFilterNestedToTheMaximumDepthThenComparisonIsReturned(): void
@@ -340,7 +340,7 @@ public function testFromQueryWhenFilterNestedToTheMaximumDepthThenComparisonIsRe
]);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the deeply nested parentheses collapse to the single unwrapped comparison */
self::assertEquals(
@@ -355,7 +355,7 @@ public function testFromQueryWhenEscapedBackslashInValueThenComparisonKeepsTheBa
$query = Query::from(parameters: ['filter' => 'name=="a\\\\b"']);
/** @When reading the validated comparisons */
- $comparisons = Criteria::fromQuery(request: $query, schema: $this->schema)->comparisons();
+ $comparisons = Criteria::fromQuery(schema: $this->schema, request: $query)->comparisons();
/** @Then the comparison carries the value with the escaped backslash unescaped */
self::assertEquals(
@@ -376,7 +376,7 @@ public function testFromQueryWhenMalformedExpressionThenThrowsFilterExpressionIs
$this->expectExceptionMessage('could not be parsed');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $this->schema);
+ Criteria::fromQuery(schema: $this->schema, request: $query);
}
public function testFromQueryWhenInListHasDisallowedValueThenThrowsFilterValueNotAllowed(): void
@@ -395,7 +395,7 @@ public function testFromQueryWhenInListHasDisallowedValueThenThrowsFilterValueNo
$this->expectException(FilterValueNotAllowed::class);
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
public function testFromQueryWhenFilterNestedBeyondTheMaximumDepthThenThrowsFilterExpressionIsInvalid(): void
@@ -413,7 +413,7 @@ public function testFromQueryWhenFilterNestedBeyondTheMaximumDepthThenThrowsFilt
$this->expectExceptionMessage('could not be parsed');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $this->schema);
+ Criteria::fromQuery(schema: $this->schema, request: $query);
}
public static function comparisonOperatorCases(): array
diff --git a/tests/Unit/LinksTest.php b/tests/Unit/LinksTest.php
index 8c943f6..c832fb7 100644
--- a/tests/Unit/LinksTest.php
+++ b/tests/Unit/LinksTest.php
@@ -46,7 +46,7 @@ public function testToArrayWhenReservedCharacterInValueThenQuotesIt(): void
public function testToArrayWhenPageIsTheLastThenOmitsTheNextRelation(): void
{
/** @Given a criteria pointing at the twenty-fourth page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '24', 'size' => '20']])
);
@@ -173,7 +173,7 @@ public function testToArrayWhenOrGroupNestedInAndThenWrapsItInParentheses(): voi
public function testToArrayWhenPageIsTheFirstThenOmitsThePreviousRelation(): void
{
/** @Given a criteria pointing at the first page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -204,7 +204,7 @@ public function testToArrayWhenPageIsTheFirstThenOmitsThePreviousRelation(): voi
public function testToArrayWhenSliceMiddleThenExposesSelfFirstPrevAndNext(): void
{
/** @Given a criteria at a middle page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -256,7 +256,7 @@ public function testToArrayWhenOrGroupFilterThenJoinsChildrenWithTheOrToken(): v
public function testToArrayWhenSliceMiddleThenCarriesAFirstButNoLastRelation(): void
{
/** @Given a criteria pointing at a middle page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -318,7 +318,7 @@ public function testConstructorWhenInvokedThroughReflectionThenInstantiatesTheSt
public function testToHeaderWhenPageInTheMiddleThenFoldsEveryRelationIntoOneCommaJoinedValue(): void
{
/** @Given a criteria at a middle page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -347,7 +347,7 @@ public function testToHeaderWhenPageInTheMiddleThenFoldsEveryRelationIntoOneComm
public function testToArrayWhenPageInTheMiddleThenExposesEveryRelationPreservingFilterAndSort(): void
{
/** @Given a criteria at a middle page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
diff --git a/tests/Unit/Offset/CriteriaTest.php b/tests/Unit/Offset/CriteriaTest.php
index 1b51aaf..c8c512e 100644
--- a/tests/Unit/Offset/CriteriaTest.php
+++ b/tests/Unit/Offset/CriteriaTest.php
@@ -24,7 +24,7 @@ public function testSortWhenNoClientSortAndNoDefaultThenIsEmpty(): void
$schema = Schema::create();
/** @When reading the effective sort from a query carrying no sort */
- $sort = Criteria::fromQuery(request: Query::from(parameters: []), schema: $schema)->sort();
+ $sort = Criteria::fromQuery(schema: $schema, request: Query::from(parameters: []))->sort();
/** @Then the effective sort is empty */
self::assertTrue($sort->isEmpty());
@@ -33,7 +33,7 @@ public function testSortWhenNoClientSortAndNoDefaultThenIsEmpty(): void
public function testPageWhenBuiltFromRequestThenReturnsOffsetPage(): void
{
/** @Given a criteria parsed from a request carrying a page size of three */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: Query::from(parameters: ['page' => ['size' => '3']]));
/** @When building an offset page from the total element count and the items */
$page = $criteria->page(items: ['a', 'b', 'c'], total: 30);
@@ -51,7 +51,7 @@ public function testFromQueryWhenEmptyThenOffsetAndLimitAreDefaults(): void
$query = Query::from(parameters: []);
/** @When building the criteria from the query */
- $criteria = Criteria::fromQuery(request: $query);
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: $query);
/** @Then the offset starts at zero */
self::assertSame(0, $criteria->offset());
@@ -63,7 +63,7 @@ public function testFromQueryWhenEmptyThenOffsetAndLimitAreDefaults(): void
public function testSliceWhenBuiltFromRequestThenReturnsOffsetSlice(): void
{
/** @Given a criteria parsed from a request carrying a page size of three */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: Query::from(parameters: ['page' => ['size' => '3']]));
/** @When building an offset slice from the items fetched for the page size plus one */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -81,7 +81,7 @@ public function testFromQueryWhenPerPageAtMaximumThenLimitIsAccepted(): void
$query = Query::from(parameters: ['page' => ['size' => '100']]);
/** @When building the criteria from the query */
- $criteria = Criteria::fromQuery(request: $query);
+ $criteria = Criteria::fromQueryWithDefaultSchema(request: $query);
/** @Then the limit carries the maximum page size */
self::assertSame(100, $criteria->limit()->toInteger());
@@ -93,7 +93,7 @@ public function testSortWhenClientSortsAllowedFieldsThenReturnsTheClientSort():
$schema = Schema::create()->sortable(fields: ['created_at', 'id']);
/** @When reading the effective sort from a client sort over both fields */
- $sort = Criteria::fromQuery(request: Query::from(parameters: ['sort' => '-created_at,id']), schema: $schema)
+ $sort = Criteria::fromQuery(schema: $schema, request: Query::from(parameters: ['sort' => '-created_at,id']))
->sort();
/** @Then the effective sort is the client sort */
@@ -106,7 +106,7 @@ public function testSortWhenNoClientSortAndDefaultGivenThenReturnsTheDefault():
$schema = Schema::create()->defaultSort(sort: Sort::fromExpression(expression: '-created_at'));
/** @When reading the effective sort from a query carrying no sort */
- $sort = Criteria::fromQuery(request: Query::from(parameters: []), schema: $schema)->sort();
+ $sort = Criteria::fromQuery(schema: $schema, request: Query::from(parameters: []))->sort();
/** @Then the effective sort is the schema default */
self::assertEquals(Sort::fromExpression(expression: '-created_at'), $sort);
@@ -121,7 +121,7 @@ public function testFromQueryWhenCustomSchemaGivenThenAppliesItsDefaultPageSize(
$schema = Schema::create()->defaultPerPage(defaultPerPage: 5);
/** @When building the criteria from the query and the schema */
- $criteria = Criteria::fromQuery(request: $query, schema: $schema);
+ $criteria = Criteria::fromQuery(schema: $schema, request: $query);
/** @Then the offset is derived from the requested page and the schema default page size */
self::assertSame(5, $criteria->offset());
@@ -140,7 +140,7 @@ public function testFromQueryWhenPerPageAboveMaximumThenThrowsPageSizeOutOfRange
$this->expectExceptionMessage('Page size');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query);
+ Criteria::fromQueryWithDefaultSchema(request: $query);
}
public function testSortWhenClientSortsDisallowedFieldThenThrowsSortFieldNotAllowed(): void
@@ -156,7 +156,7 @@ public function testSortWhenClientSortsDisallowedFieldThenThrowsSortFieldNotAllo
$this->expectExceptionMessage('Sort field is not allowed.');
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
public function testFromQueryWhenFilterSortAndPageGivenThenEachSpecificationIsValidated(): void
@@ -174,7 +174,7 @@ public function testFromQueryWhenFilterSortAndPageGivenThenEachSpecificationIsVa
]);
/** @When building the criteria from the query and the schema */
- $criteria = Criteria::fromQuery(request: $query, schema: $schema);
+ $criteria = Criteria::fromQuery(schema: $schema, request: $query);
/** @Then the validated comparisons carry the filtered field and value */
self::assertEquals(
@@ -204,6 +204,6 @@ public function testSortWhenServerControlledAndClientSortsThenThrowsSortFieldNot
$this->expectException(SortFieldNotAllowed::class);
/** @When building the criteria from the query */
- Criteria::fromQuery(request: $query, schema: $schema);
+ Criteria::fromQuery(schema: $schema, request: $query);
}
}
diff --git a/tests/Unit/Offset/PageTest.php b/tests/Unit/Offset/PageTest.php
index e4eb121..7dce5b5 100644
--- a/tests/Unit/Offset/PageTest.php
+++ b/tests/Unit/Offset/PageTest.php
@@ -18,7 +18,7 @@ final class PageTest extends TestCase
public function testNavigationWhenTotalIsZeroThenThereIsNoPage(): void
{
/** @Given a criteria on the first page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -51,7 +51,7 @@ public function testNavigationWhenTotalIsZeroThenThereIsNoPage(): void
public function testNavigationWhenLastPageGivenThenHasNoNextPage(): void
{
/** @Given a criteria on the last page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '24', 'size' => '20']])
);
@@ -74,7 +74,7 @@ public function testNavigationWhenLastPageGivenThenHasNoNextPage(): void
public function testItemsWhenPageGivenThenCarriesTheProvidedItems(): void
{
/** @Given a criteria on the third page with a page size of twenty */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -88,7 +88,7 @@ public function testItemsWhenPageGivenThenCarriesTheProvidedItems(): void
public function testFromWhenTotalIsNegativeThenThrowsTotalIsNegative(): void
{
/** @Given a criteria on the first page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -103,7 +103,7 @@ public function testFromWhenTotalIsNegativeThenThrowsTotalIsNegative(): void
public function testNavigationWhenFirstPageGivenThenHasNoPreviousPage(): void
{
/** @Given a criteria on the first page */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -132,7 +132,7 @@ public function testNavigationWhenFirstPageGivenThenHasNoPreviousPage(): void
public function testTotalWhenPageGivenThenReturnsTheTotalElementCount(): void
{
/** @Given a criteria on the first page with a page size of twenty */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -146,7 +146,7 @@ public function testTotalWhenPageGivenThenReturnsTheTotalElementCount(): void
public function testTotalPagesWhenTotalIsNotAMultipleOfPerPageThenRoundsUp(): void
{
/** @Given a criteria on the first page with a page size of twenty */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -160,7 +160,7 @@ public function testTotalPagesWhenTotalIsNotAMultipleOfPerPageThenRoundsUp(): vo
public function testMetadataWhenMiddlePageGivenThenCarriesEveryFlagAndCount(): void
{
/** @Given a criteria on a middle page with a page size of twenty */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -181,7 +181,7 @@ public function testMetadataWhenMiddlePageGivenThenCarriesEveryFlagAndCount(): v
public function testNavigationWhenFirstPageGivenThenOmitsThePreviousRelation(): void
{
/** @Given a criteria on the first page of a multi-page result */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '20']])
);
@@ -200,7 +200,7 @@ public function testNavigationWhenFirstPageGivenThenOmitsThePreviousRelation():
public function testToResponseWhenMiddlePageGivenThenRendersBodyAndLinkHeader(): void
{
/** @Given a criteria on the third page with a page size of twenty */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -243,7 +243,7 @@ public function testToResponseWhenMiddlePageGivenThenRendersBodyAndLinkHeader():
public function testNavigationWhenMiddlePageGivenThenExposesEverySurroundingPage(): void
{
/** @Given a criteria on a middle page with a page size of twenty */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -275,7 +275,7 @@ public function testNavigationWhenMiddlePageGivenThenExposesEverySurroundingPage
public function testNavigationWhenMiddlePageGivenThenTheFirstTargetPointsAtTheFirstPage(): void
{
/** @Given a criteria on a middle page of a multi-page result */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
@@ -295,7 +295,7 @@ public function testNavigationWhenMiddlePageGivenThenTheFirstTargetPointsAtTheFi
public function testNavigationWhenMiddlePageGivenThenListsFirstPreviousNextAndLastTargets(): void
{
/** @Given a criteria on a middle page of a multi-page result */
- $criteria = Criteria::fromQuery(
+ $criteria = Criteria::fromQueryWithDefaultSchema(
request: Query::from(parameters: ['page' => ['number' => '3', 'size' => '20']])
);
diff --git a/tests/Unit/Offset/SliceTest.php b/tests/Unit/Offset/SliceTest.php
index 0dca7a2..5d7ddfe 100644
--- a/tests/Unit/Offset/SliceTest.php
+++ b/tests/Unit/Offset/SliceTest.php
@@ -17,7 +17,9 @@ final class SliceTest extends TestCase
public function testToResponseWhenSliceGivenThenRendersBodyAndLinkHeader(): void
{
/** @Given a criteria on the second page with a page size of three */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']])
+ );
/** @And a slice built from items fetched for the page size plus one */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -54,7 +56,9 @@ public function testToResponseWhenSliceGivenThenRendersBodyAndLinkHeader(): void
public function testOffsetWhenSecondPageGivenThenReturnsTheZeroBasedOffset(): void
{
/** @Given a criteria on the second page with a page size of three */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']])
+ );
/** @When building the slice from the items fetched for the page size plus one */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -66,7 +70,9 @@ public function testOffsetWhenSecondPageGivenThenReturnsTheZeroBasedOffset(): vo
public function testNavigationWhenExtraElementFetchedThenHasNextAndTrimsItems(): void
{
/** @Given a criteria on the second page with a page size of three */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']])
+ );
/** @When building the slice from the items fetched for the page size plus one */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -104,7 +110,9 @@ public function testNavigationWhenExtraElementFetchedThenHasNextAndTrimsItems():
public function testNavigationWhenNoExtraElementOnFirstPageThenNoNextAndNoPrevious(): void
{
/** @Given a criteria on the first page with a page size of three */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '3']])
+ );
/** @When building the slice from items fetched within the page size */
$slice = $criteria->slice(items: ['a', 'b', 'c']);
@@ -131,7 +139,9 @@ public function testNavigationWhenNoExtraElementOnFirstPageThenNoNextAndNoPrevio
public function testNavigationWhenMiddlePageGivenThenListsFirstPreviousAndNextRelations(): void
{
/** @Given a criteria on a middle page fetched for the page size plus one */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']])
+ );
/** @And a slice on that middle page */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -148,7 +158,9 @@ public function testNavigationWhenMiddlePageGivenThenListsFirstPreviousAndNextRe
public function testNavigationWhenMiddlePageGivenThenTheFirstTargetPointsAtTheFirstPage(): void
{
/** @Given a criteria on a middle page fetched for the page size plus one */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']])
+ );
/** @And a slice on that middle page */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -166,7 +178,9 @@ public function testNavigationWhenMiddlePageGivenThenTheFirstTargetPointsAtTheFi
public function testNavigationWhenMiddlePageGivenThenTheNextTargetPointsAtTheFollowingPage(): void
{
/** @Given a criteria on a middle page fetched for the page size plus one */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '2', 'size' => '3']])
+ );
/** @And a slice on that middle page */
$slice = $criteria->slice(items: ['a', 'b', 'c', 'd']);
@@ -184,7 +198,9 @@ public function testNavigationWhenMiddlePageGivenThenTheNextTargetPointsAtTheFol
public function testNavigationWhenFirstPageWithoutExtraElementThenListsOnlyTheFirstRelation(): void
{
/** @Given a criteria on the first page fetched within the page size */
- $criteria = Criteria::fromQuery(request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '3']]));
+ $criteria = Criteria::fromQueryWithDefaultSchema(
+ request: Query::from(parameters: ['page' => ['number' => '1', 'size' => '3']])
+ );
/** @And a slice on that first page */
$slice = $criteria->slice(items: ['a', 'b', 'c']);