Skip to content

Commit f536554

Browse files
committed
allow pdo in constructor, add _id in table schema & fix info queries with model objects
1 parent dcea1fd commit f536554

16 files changed

Lines changed: 782 additions & 312 deletions

phpstan-baseline.neon

Lines changed: 116 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
parameters:
22
ignoreErrors:
3+
-
4+
message: '#^Method Patchlevel\\Rango\\Client\:\:getCollection\(\) return type with generic class Patchlevel\\Rango\\Collection does not specify its types\: TDocument$#'
5+
identifier: missingType.generics
6+
count: 1
7+
path: src/Client.php
8+
9+
-
10+
message: '#^Method Patchlevel\\Rango\\Client\:\:listCollections\(\) should return Iterator\<mixed, Patchlevel\\Rango\\Model\\CollectionInfo\> but returns list\<array\<string, string\>\>\.$#'
11+
identifier: return.type
12+
count: 1
13+
path: src/Client.php
14+
15+
-
16+
message: '#^Method Patchlevel\\Rango\\Client\:\:listDatabases\(\) should return Iterator\<mixed, Patchlevel\\Rango\\Model\\DatabaseInfo\> but returns list\<array\<string, string\>\>\.$#'
17+
identifier: return.type
18+
count: 1
19+
path: src/Client.php
20+
321
-
422
message: '#^Method Patchlevel\\Rango\\Collection\:\:findOne\(\) should return \(TDocument of array\<string, mixed\>\)\|null but returns array\<string, mixed\>\|null\.$#'
523
identifier: return.type
@@ -24,6 +42,12 @@ parameters:
2442
count: 1
2543
path: src/Collection.php
2644

45+
-
46+
message: '#^Parameter \#1 \$operation of method Patchlevel\\Rango\\Client\:\:run\(\) expects Patchlevel\\Rango\\Operation\\Operation\<Iterator\<mixed, Patchlevel\\Rango\\Model\\IndexInfo\>\>, Patchlevel\\Rango\\Operation\\ListIndexes given\.$#'
47+
identifier: argument.type
48+
count: 1
49+
path: src/Collection.php
50+
2751
-
2852
message: '#^Parameter \#1 \$operation of method Patchlevel\\Rango\\Client\:\:run\(\) expects Patchlevel\\Rango\\Operation\\Operation\<list\<mixed\>\>, Patchlevel\\Rango\\Operation\\Distinct given\.$#'
2953
identifier: argument.type
@@ -54,6 +78,54 @@ parameters:
5478
count: 1
5579
path: src/Cursor.php
5680

81+
-
82+
message: '#^Parameter \#1 \$key of function array_key_exists expects int\|string, mixed given\.$#'
83+
identifier: argument.type
84+
count: 1
85+
path: src/Model/CollectionInfo.php
86+
87+
-
88+
message: '#^Possibly invalid array key type mixed\.$#'
89+
identifier: offsetAccess.invalidOffset
90+
count: 1
91+
path: src/Model/CollectionInfo.php
92+
93+
-
94+
message: '#^Parameter \#1 \$key of function array_key_exists expects int\|string, mixed given\.$#'
95+
identifier: argument.type
96+
count: 1
97+
path: src/Model/DatabaseInfo.php
98+
99+
-
100+
message: '#^Possibly invalid array key type mixed\.$#'
101+
identifier: offsetAccess.invalidOffset
102+
count: 1
103+
path: src/Model/DatabaseInfo.php
104+
105+
-
106+
message: '#^Class Patchlevel\\Rango\\Model\\IndexInfo implements generic interface ArrayAccess but does not specify its types\: TKey, TValue$#'
107+
identifier: missingType.generics
108+
count: 1
109+
path: src/Model/IndexInfo.php
110+
111+
-
112+
message: '#^Parameter \#1 \$key of function array_key_exists expects int\|string, mixed given\.$#'
113+
identifier: argument.type
114+
count: 1
115+
path: src/Model/IndexInfo.php
116+
117+
-
118+
message: '#^Possibly invalid array key type mixed\.$#'
119+
identifier: offsetAccess.invalidOffset
120+
count: 1
121+
path: src/Model/IndexInfo.php
122+
123+
-
124+
message: '#^Property Patchlevel\\Rango\\Model\\IndexInfo\:\:\$info on left side of \?\? is not nullable nor uninitialized\.$#'
125+
identifier: nullCoalesce.initializedProperty
126+
count: 1
127+
path: src/Model/IndexInfo.php
128+
57129
-
58130
message: '#^Method Patchlevel\\Rango\\Operation\\Aggregate\:\:execute\(\) return type with generic class Patchlevel\\Rango\\Cursor does not specify its types\: TDocument$#'
59131
identifier: missingType.generics
@@ -90,6 +162,18 @@ parameters:
90162
count: 1
91163
path: src/Operation/FindOneAndUpdate.php
92164

165+
-
166+
message: '#^Return type \(Iterator\<mixed, Patchlevel\\Rango\\Model\\CollectionInfo\>\) of method Patchlevel\\Rango\\Operation\\ListCollections\:\:execute\(\) should be compatible with return type \(list\<array\{name\: string\}\>\) of method Patchlevel\\Rango\\Operation\\Operation\<list\<array\<string, string\>\>\>\:\:execute\(\)$#'
167+
identifier: method.childReturnType
168+
count: 1
169+
path: src/Operation/ListCollections.php
170+
171+
-
172+
message: '#^Return type \(Iterator\<mixed, Patchlevel\\Rango\\Model\\DatabaseInfo\>\) of method Patchlevel\\Rango\\Operation\\ListDatabases\:\:execute\(\) should be compatible with return type \(list\<array\{name\: string\}\>\) of method Patchlevel\\Rango\\Operation\\Operation\<list\<array\<string, string\>\>\>\:\:execute\(\)$#'
173+
identifier: method.childReturnType
174+
count: 1
175+
path: src/Operation/ListDatabases.php
176+
93177
-
94178
message: '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\.$#'
95179
identifier: foreach.nonIterable
@@ -183,7 +267,7 @@ parameters:
183267
-
184268
message: '#^Cannot cast mixed to string\.$#'
185269
identifier: cast.string
186-
count: 6
270+
count: 9
187271
path: src/Query/FilterBuilder.php
188272

189273
-
@@ -337,8 +421,32 @@ parameters:
337421
path: src/QueryBuilder.php
338422

339423
-
340-
message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertNotNull\(\) with MongoDB\\Database\|Patchlevel\\Rango\\Database will always evaluate to true\.$#'
341-
identifier: method.alreadyNarrowedType
424+
message: '#^Call to function is_array\(\) with Iterator\<int, MongoDB\\Model\\CollectionInfo\>\|Iterator\<mixed, Patchlevel\\Rango\\Model\\CollectionInfo\> will always evaluate to false\.$#'
425+
identifier: function.impossibleType
426+
count: 2
427+
path: tests/IntegrationTest.php
428+
429+
-
430+
message: '#^Call to function is_array\(\) with Iterator\<int, MongoDB\\Model\\DatabaseInfo\>\|Iterator\<mixed, Patchlevel\\Rango\\Model\\DatabaseInfo\> will always evaluate to false\.$#'
431+
identifier: function.impossibleType
432+
count: 1
433+
path: tests/IntegrationTest.php
434+
435+
-
436+
message: '#^Call to function is_array\(\) with MongoDB\\Model\\CollectionInfo\|Patchlevel\\Rango\\Model\\CollectionInfo will always evaluate to false\.$#'
437+
identifier: function.impossibleType
438+
count: 2
439+
path: tests/IntegrationTest.php
440+
441+
-
442+
message: '#^Call to function is_array\(\) with MongoDB\\Model\\DatabaseInfo\|Patchlevel\\Rango\\Model\\DatabaseInfo will always evaluate to false\.$#'
443+
identifier: function.impossibleType
444+
count: 1
445+
path: tests/IntegrationTest.php
446+
447+
-
448+
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertNotNull\(\) with MongoDB\\Database\|Patchlevel\\Rango\\Database will always evaluate to true\.$#'
449+
identifier: staticMethod.alreadyNarrowedType
342450
count: 1
343451
path: tests/IntegrationTest.php
344452

@@ -595,31 +703,31 @@ parameters:
595703
path: tests/IntegrationTest.php
596704

597705
-
598-
message: '#^Parameter \#2 \$array of method PHPUnit\\Framework\\Assert\:\:assertArrayHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, array\|object\|null given\.$#'
706+
message: '#^Parameter \#2 \$array of static method PHPUnit\\Framework\\Assert\:\:assertArrayHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, array\|object\|null given\.$#'
599707
identifier: argument.type
600708
count: 9
601709
path: tests/IntegrationTest.php
602710

603711
-
604-
message: '#^Parameter \#2 \$array of method PHPUnit\\Framework\\Assert\:\:assertArrayHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, mixed given\.$#'
712+
message: '#^Parameter \#2 \$array of static method PHPUnit\\Framework\\Assert\:\:assertArrayHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, mixed given\.$#'
605713
identifier: argument.type
606714
count: 4
607715
path: tests/IntegrationTest.php
608716

609717
-
610-
message: '#^Parameter \#2 \$array of method PHPUnit\\Framework\\Assert\:\:assertArrayNotHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, array\|object\|null given\.$#'
718+
message: '#^Parameter \#2 \$array of static method PHPUnit\\Framework\\Assert\:\:assertArrayNotHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, array\|object\|null given\.$#'
611719
identifier: argument.type
612720
count: 4
613721
path: tests/IntegrationTest.php
614722

615723
-
616-
message: '#^Parameter \#2 \$array of method PHPUnit\\Framework\\Assert\:\:assertArrayNotHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, mixed given\.$#'
724+
message: '#^Parameter \#2 \$array of static method PHPUnit\\Framework\\Assert\:\:assertArrayNotHasKey\(\) expects array\<mixed\>\|ArrayAccess\<\(int\|string\), mixed\>, mixed given\.$#'
617725
identifier: argument.type
618726
count: 5
619727
path: tests/IntegrationTest.php
620728

621729
-
622-
message: '#^Parameter \#2 \$haystack of method PHPUnit\\Framework\\Assert\:\:assertCount\(\) expects Countable\|iterable, mixed given\.$#'
730+
message: '#^Parameter \#2 \$haystack of static method PHPUnit\\Framework\\Assert\:\:assertCount\(\) expects Countable\|iterable, mixed given\.$#'
623731
identifier: argument.type
624732
count: 2
625733
path: tests/IntegrationTest.php

src/Client.php

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace Patchlevel\Rango;
66

7+
use Iterator;
8+
use Patchlevel\Rango\Model\CollectionInfo;
9+
use Patchlevel\Rango\Model\DatabaseInfo;
710
use Patchlevel\Rango\Sql\Identifier;
811
use PDO;
912

@@ -14,11 +17,16 @@ final class Client
1417
private readonly PDO $pdo;
1518
private readonly QueryBuilder $queryBuilder;
1619

17-
public function __construct(string $uri)
20+
public function __construct(string|PDO $uri)
1821
{
19-
$this->pdo = new PDO($uri, null, null, [
20-
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
21-
]);
22+
if ($uri instanceof PDO) {
23+
$this->pdo = $uri;
24+
} else {
25+
$this->pdo = new PDO($uri, null, null, [
26+
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
27+
]);
28+
}
29+
2230
$this->queryBuilder = new QueryBuilder($this->pdo);
2331
}
2432

@@ -34,33 +42,32 @@ public function selectDatabase(string $name): Database
3442
return $this->getDatabase($name);
3543
}
3644

45+
public function getCollection(string $databaseName, string $collectionName): Collection
46+
{
47+
return $this->getDatabase($databaseName)->getCollection($collectionName);
48+
}
49+
3750
/** @return Collection<array<string, mixed>> */
3851
public function selectCollection(string $databaseName, string $collectionName): Collection
3952
{
40-
return $this->getDatabase($databaseName)->getCollection($collectionName);
53+
return $this->getCollection($databaseName, $collectionName);
4154
}
4255

4356
public function dropDatabase(string $name): void
4457
{
4558
SqlRunner::exec($this->pdo, sprintf('DROP SCHEMA IF EXISTS %s CASCADE', Identifier::quote($name)));
4659
}
4760

48-
/** @return list<array{name: string}> */
49-
public function listDatabases(): array
61+
/** @return Iterator<DatabaseInfo> */
62+
public function listDatabases(): Iterator
5063
{
51-
/** @var list<array{name: string}> $databases */
52-
$databases = $this->run(new Operation\ListDatabases());
53-
54-
return $databases;
64+
return $this->run(new Operation\ListDatabases());
5565
}
5666

57-
/** @return list<array{name: string}> */
58-
public function listCollections(string $database): array
67+
/** @return Iterator<CollectionInfo> */
68+
public function listCollections(string $database): Iterator
5969
{
60-
/** @var list<array{name: string}> $collections */
61-
$collections = $this->run(new Operation\ListCollections($database));
62-
63-
return $collections;
70+
return $this->run(new Operation\ListCollections($database));
6471
}
6572

6673
public function renameCollection(string $database, string $oldName, string $newName): void

src/Collection.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace Patchlevel\Rango;
66

7+
use Iterator;
8+
use Patchlevel\Rango\Model\IndexInfo;
9+
710
/** @template TDocument of array<string, mixed> */
811
final class Collection
912
{
@@ -220,8 +223,8 @@ public function dropIndex(string $name): void
220223
$this->client->run(new Operation\DropIndex($this->databaseName, $this->collectionName, $name));
221224
}
222225

223-
/** @return list<array{name: string}> */
224-
public function listIndexes(): array
226+
/** @return Iterator<IndexInfo> */
227+
public function listIndexes(): Iterator
225228
{
226229
return $this->client->run(new Operation\ListIndexes($this->databaseName, $this->collectionName));
227230
}

src/Database.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
namespace Patchlevel\Rango;
66

7+
use Iterator;
8+
use Patchlevel\Rango\Model\CollectionInfo;
9+
710
final class Database
811
{
912
public function __construct(
@@ -24,20 +27,23 @@ public function selectCollection(string $collectionName): Collection
2427
return $this->getCollection($collectionName);
2528
}
2629

27-
/** @return list<array{name: string}> */
28-
public function listCollections(): array
30+
/** @return Iterator<CollectionInfo> */
31+
public function listCollections(): Iterator
2932
{
30-
/** @var list<array{name: string}> $collections */
31-
$collections = $this->client->listCollections($this->databaseName);
32-
33-
return $collections;
33+
return $this->client->listCollections($this->databaseName);
3434
}
3535

3636
public function renameCollection(string $oldName, string $newName): void
3737
{
3838
$this->client->renameCollection($this->databaseName, $oldName, $newName);
3939
}
4040

41+
/** @param array<string, mixed> $options */
42+
public function dropCollection(string $collectionName, array $options = []): void
43+
{
44+
$this->client->getCollection($this->databaseName, $collectionName)->drop();
45+
}
46+
4147
public function drop(): void
4248
{
4349
$this->client->dropDatabase($this->databaseName);

src/Model/CollectionInfo.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Rango\Model;
6+
7+
use BadMethodCallException;
8+
9+
use function array_key_exists;
10+
11+
final readonly class CollectionInfo
12+
{
13+
/** @param array{name: string} $info */
14+
public function __construct(
15+
private array $info,
16+
) {
17+
}
18+
19+
public function __toString(): string
20+
{
21+
return $this->info['name'];
22+
}
23+
24+
public function getName(): string
25+
{
26+
return $this->info['name'];
27+
}
28+
29+
public function offsetExists(mixed $offset): bool
30+
{
31+
return array_key_exists($offset, $this->info);
32+
}
33+
34+
public function offsetGet(mixed $offset): mixed
35+
{
36+
return $this->info[$offset];
37+
}
38+
39+
public function offsetSet(mixed $offset, mixed $value): void
40+
{
41+
throw new BadMethodCallException('IndexInfo is read only');
42+
}
43+
44+
public function offsetUnset(mixed $offset): void
45+
{
46+
throw new BadMethodCallException('IndexInfo is read only');
47+
}
48+
}

0 commit comments

Comments
 (0)