Skip to content

Commit 9e3df37

Browse files
committed
Improve Query feature codebase
1 parent 00bbff9 commit 9e3df37

15 files changed

+92
-55
lines changed

src/Query/Constraint/Column.php

-6
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,6 @@
2121
use ReflectionException;
2222
use Traversable;
2323

24-
use function is_array;
25-
use function array_filter;
26-
use function iterator_to_array;
27-
28-
use const ARRAY_FILTER_USE_BOTH;
29-
3024
/**
3125
* Enable filtering a record based on the value of a one of its cell.
3226
*

src/Query/Constraint/Comparison.php

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ public static function fromOperator(string $operator): self
7676
}
7777

7878
/**
79+
* Values comparison.
80+
*
81+
* The method return true if the values satisfy the comparison operator, otherwise false is returned.
82+
*
7983
* @throws QueryException
8084
*/
8185
public function compare(mixed $subject, mixed $reference): bool
@@ -108,6 +112,8 @@ private static function isSingleValue(mixed $value): bool
108112
}
109113

110114
/**
115+
* Assert if the reference value can be used with the Enum operator.
116+
*
111117
* @throws QueryException
112118
*/
113119
public function accept(mixed $reference): void

src/Query/Constraint/Criteria.php

+3-6
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,8 @@
2121
use League\Csv\Query\Predicate;
2222
use League\Csv\Query\PredicateCombinator;
2323

24+
use Traversable;
2425
use function array_reduce;
25-
use function is_array;
26-
use function array_filter;
27-
28-
use const ARRAY_FILTER_USE_BOTH;
2926

3027
/**
3128
* @phpstan-import-type Condition from PredicateCombinator
@@ -116,9 +113,9 @@ public function __invoke(mixed $value, int|string $key): bool
116113
public function filter(iterable $value): Iterator
117114
{
118115
return new CallbackFilterIterator(match (true) {
119-
is_array($value) => new ArrayIterator($value),
120116
$value instanceof Iterator => $value,
121-
default => new IteratorIterator($value),
117+
$value instanceof Traversable => new IteratorIterator($value),
118+
default => new ArrayIterator($value),
122119
}, $this);
123120
}
124121

src/Query/Limit.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,6 @@
1919
use LimitIterator;
2020
use Traversable;
2121

22-
use function array_slice;
23-
use function is_array;
24-
use function iterator_to_array;
25-
2622
final class Limit
2723
{
2824
private function __construct(
@@ -43,6 +39,9 @@ public static function new(int $offset, int $length): self
4339
return new self($offset, $length);
4440
}
4541

42+
/**
43+
* Allows iteration over a limited subset of items in an iterable structure.
44+
*/
4645
public function slice(iterable $value): LimitIterator
4746
{
4847
return new LimitIterator(

src/Query/Ordering/Column.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
use OutOfBoundsException;
2323
use ReflectionException;
2424

25+
use function is_array;
26+
use function is_string;
27+
use function iterator_to_array;
2528
use function strtoupper;
2629
use function trim;
2730

@@ -45,8 +48,10 @@ private function __construct(
4548

4649
/**
4750
* @param ?Closure(mixed, mixed): int $callback
51+
*
52+
* @throws QueryException
4853
*/
49-
public static function sortBy(
54+
public static function sortOn(
5055
string|int $column,
5156
string|int $direction,
5257
?Closure $callback = null

src/Query/Ordering/ColumnTest.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ final class ColumnTest extends QueryTestCase
2323
public function it_can_order_the_tabular_date_in_descending_order(): void
2424
{
2525
$stmt = $this->stmt->orderBy(
26-
Column::sortBy('Country', 'down')
26+
Column::sortOn('Country', 'down')
2727
);
2828

2929
self::assertSame('UK', $stmt->process($this->document)->first()['Country']);
@@ -33,7 +33,7 @@ public function it_can_order_the_tabular_date_in_descending_order(): void
3333
public function it_can_order_the_tabular_date_in_ascending_order(): void
3434
{
3535
$stmt = $this->stmt->orderBy(
36-
Column::sortBy('Country', 'up')
36+
Column::sortOn('Country', 'up')
3737
);
3838

3939
self::assertSame('UK', $stmt->process($this->document)->nth(4)['Country']);
@@ -43,7 +43,7 @@ public function it_can_order_the_tabular_date_in_ascending_order(): void
4343
public function it_can_order_using_a_specific_order_algo(): void
4444
{
4545
$stmt = $this->stmt->orderBy(
46-
Column::sortBy(
46+
Column::sortOn(
4747
'Country',
4848
'desc',
4949
fn (string $first, string $second): int => strlen($first) <=> strlen($second) /* @phpstan-ignore-line */

src/Query/Ordering/MultiSort.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515

1616
use ArrayIterator;
1717
use Closure;
18-
1918
use Iterator;
2019
use IteratorIterator;
2120
use League\Csv\Query\Sort;
2221
use League\Csv\Query\SortCombinator;
2322
use OutOfBoundsException;
2423
use Traversable;
24+
2525
use function array_map;
2626

2727
/**

src/Query/Ordering/MultiSortTest.php

+3-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use PHPUnit\Framework\Attributes\Test;
1818

1919
final class MultiSortTest extends QueryTestCase
20-
2120
{
2221
#[Test]
2322
public function it_will_sort_nothing_if_no_sort_algorithm_is_provided(): void
@@ -32,7 +31,7 @@ public function it_will_sort_nothing_if_no_sort_algorithm_is_provided(): void
3231
public function it_can_order_the_tabular_date_when_an_algo_is_provided(): void
3332
{
3433
$stmt = $this->stmt->orderBy(
35-
MultiSort::all()->append(Column::sortBy('Country', 'up'))
34+
MultiSort::all()->append(Column::sortOn('Country', 'up'))
3635
);
3736

3837
self::assertSame('UK', $stmt->process($this->document)->nth(4)['Country']);
@@ -41,8 +40,8 @@ public function it_can_order_the_tabular_date_when_an_algo_is_provided(): void
4140
#[Test]
4241
public function it_respect_the_fifo_order_to_apply_sorting(): void
4342
{
44-
$countryOrder = Column::sortBy('Country', 'ASC');
45-
$idOrder = Column::sortBy('CustomerID', 'DeSc');
43+
$countryOrder = Column::sortOn('Country', 'ASC');
44+
$idOrder = Column::sortOn('CustomerID', 'DeSc');
4645

4746
self::assertNotSame(
4847
$this->stmt

src/Query/Predicate.php

+11
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,18 @@
2626
*/
2727
interface Predicate
2828
{
29+
/**
30+
* The class predicate method.
31+
*
32+
* Evaluates each element of an iterable structure based on its value and its offset.
33+
* The method must return true if the predicate is satisfied, false otherwise.
34+
*/
2935
public function __invoke(mixed $value, string|int $key): bool;
3036

37+
/**
38+
* Filters elements of an iterable structure using the class predicate method.
39+
*
40+
* @see Predicate::__invoke
41+
*/
3142
public function filter(iterable $value): Iterator;
3243
}

src/Query/PredicateCombinator.php

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
namespace League\Csv\Query;
1515

1616
use Closure;
17-
use League\Csv\Query\Predicate;
1817

1918
/**
2019
* @phpstan-type Condition Predicate|Closure(mixed, array-key): bool

src/Query/Row.php

+24-24
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public static function from(mixed $value): Row
4242
});
4343
}
4444

45-
private function __construct(private readonly array|object $record)
45+
private function __construct(private readonly array|object $row)
4646
{
4747
}
4848

@@ -51,7 +51,7 @@ private function __construct(private readonly array|object $record)
5151
*
5252
* @throws ReflectionException
5353
* @throws QueryException If the value can not be retrieved
54-
*@see Row::select()
54+
* @see Row::select()
5555
*
5656
*/
5757
public function value(string|int $key): mixed
@@ -74,8 +74,8 @@ public function value(string|int $key): mixed
7474
public function select(string|int ...$key): array
7575
{
7676
return match (true) {
77-
is_object($this->record) => self::getObjectPropertyValue($this->record, ...$key),
78-
default => self::getArrayEntry($this->record, ...$key),
77+
is_object($this->row) => self::getObjectPropertyValue($this->row, ...$key),
78+
default => self::getArrayEntry($this->row, ...$key),
7979
};
8080
}
8181

@@ -84,26 +84,26 @@ public function select(string|int ...$key): array
8484
*
8585
* @return non-empty-array<array-key, mixed>
8686
*/
87-
private function getArrayEntry(array $value, string|int ...$keys): array
87+
private function getArrayEntry(array $row, string|int ...$keys): array
8888
{
8989
$res = [];
90-
$arrValues = array_values($value);
90+
$arrValues = array_values($row);
9191
foreach ($keys as $key) {
9292
if (array_key_exists($key, $res)) {
9393
continue;
9494
}
9595
$offset = $key;
9696
if (is_int($offset)) {
97-
if (!array_is_list($value)) {
98-
$value = $arrValues;
97+
if (!array_is_list($row)) {
98+
$row = $arrValues;
9999
}
100100

101101
if ($offset < 0) {
102-
$offset += count($value);
102+
$offset += count($row);
103103
}
104104
}
105105

106-
$res[$key] = array_key_exists($offset, $value) ? $value[$offset] : throw QueryException::dueToUnknownColumn($key, $value);
106+
$res[$key] = array_key_exists($offset, $row) ? $row[$offset] : throw QueryException::dueToUnknownColumn($key, $row);
107107
}
108108

109109
return [] !== $res ? $res : throw QueryException::dueToMissingColumn();
@@ -115,21 +115,21 @@ private function getArrayEntry(array $value, string|int ...$keys): array
115115
*
116116
* @return non-empty-array<array-key, mixed>
117117
*/
118-
private static function getObjectPropertyValue(object $value, string|int ...$keys): array
118+
private static function getObjectPropertyValue(object $row, string|int ...$keys): array
119119
{
120120
$res = [];
121-
$refl = new ReflectionObject($value);
121+
$object = new ReflectionObject($row);
122122
foreach ($keys as $key) {
123123
if (array_key_exists($key, $res)) {
124124
continue;
125125
}
126126

127127
if (is_int($key)) {
128-
throw QueryException::dueToUnknownColumn($key, $value);
128+
throw QueryException::dueToUnknownColumn($key, $row);
129129
}
130130

131-
if ($refl->hasProperty($key) && $refl->getProperty($key)->isPublic()) {
132-
$res[$key] = $refl->getProperty($key)->getValue($value);
131+
if ($object->hasProperty($key) && $object->getProperty($key)->isPublic()) {
132+
$res[$key] = $object->getProperty($key)->getValue($row);
133133
continue;
134134
}
135135

@@ -139,26 +139,26 @@ private static function getObjectPropertyValue(object $value, string|int ...$key
139139
}
140140
$methodNameList[] = self::camelCase($key, 'get');
141141
foreach ($methodNameList as $methodName) {
142-
if ($refl->hasMethod($methodName)
143-
&& $refl->getMethod($methodName)->isPublic()
144-
&& 1 > $refl->getMethod($methodName)->getNumberOfRequiredParameters()
142+
if ($object->hasMethod($methodName)
143+
&& $object->getMethod($methodName)->isPublic()
144+
&& 1 > $object->getMethod($methodName)->getNumberOfRequiredParameters()
145145
) {
146-
$res[$key] = $refl->getMethod($methodName)->invoke($value);
146+
$res[$key] = $object->getMethod($methodName)->invoke($row);
147147
continue 2;
148148
}
149149
}
150150

151-
if (method_exists($value, '__call')) {
152-
$res[$key] = $refl->getMethod('__call')->invoke($value, $methodNameList[1]);
151+
if (method_exists($row, '__call')) {
152+
$res[$key] = $object->getMethod('__call')->invoke($row, $methodNameList[1]);
153153
continue;
154154
}
155155

156-
if ($value instanceof ArrayAccess && $value->offsetExists($key)) {
157-
$res[$key] = $value->offsetGet($key);
156+
if ($row instanceof ArrayAccess && $row->offsetExists($key)) {
157+
$res[$key] = $row->offsetGet($key);
158158
continue;
159159
}
160160

161-
throw QueryException::dueToUnknownColumn($key, $value);
161+
throw QueryException::dueToUnknownColumn($key, $row);
162162
}
163163

164164
return [] !== $res ? $res : throw QueryException::dueToMissingColumn();

src/Query/Sort.php

+10
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,17 @@
2727
*/
2828
interface Sort
2929
{
30+
/**
31+
* The class comparison method.
32+
*
33+
* The method must return an integer less than, equal to, or greater than zero
34+
* if the first argument is considered to be respectively less than, equal to,
35+
* or greater than the second.
36+
*/
3037
public function __invoke(mixed $valueA, mixed $valueB): int;
3138

39+
/**
40+
* Sort an iterable structure with the class comparison method and maintain index association.
41+
*/
3242
public function sort(iterable $value): Iterator;
3343
}

src/Serializer/Denormalizer.php

+17
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,39 @@ public function __construct(string $className, array $propertyNames = [])
5555
$this->postMapCalls = $this->setPostMapCalls();
5656
}
5757

58+
/**
59+
* Enable converting empty string to the null value.
60+
*/
5861
public static function allowEmptyStringAsNull(): void
5962
{
6063
self::$emptyStringAsNull = true;
6164
}
6265

66+
/**
67+
* Disable converting empty string to the null value.
68+
*/
6369
public static function disallowEmptyStringAsNull(): void
6470
{
6571
self::$emptyStringAsNull = false;
6672
}
6773

6874
/**
75+
* Register a global type conversion callback to convert a field into a specific type.
76+
*
6977
* @throws MappingFailed
7078
*/
7179
public static function registerType(string $type, Closure $callback): void
7280
{
7381
CallbackCasting::register($type, $callback);
7482
}
7583

84+
/**
85+
* Unregister a global type conversion callback to convert a field into a specific type.
86+
*
87+
* @param string $type
88+
*
89+
* @return bool
90+
*/
7691
public static function unregisterType(string $type): bool
7792
{
7893
return CallbackCasting::unregisterType($type);
@@ -84,6 +99,8 @@ public static function unregisterAllTypes(): void
8499
}
85100

86101
/**
102+
* Register a callback to convert a field into a specific type.
103+
*
87104
* @throws MappingFailed
88105
*/
89106
public static function registerAlias(string $alias, string $type, Closure $callback): void

0 commit comments

Comments
 (0)