Skip to content

Commit c56b1eb

Browse files
committed
chore: Fix PHPStan errors
1 parent 959b295 commit c56b1eb

File tree

5 files changed

+205
-101
lines changed

5 files changed

+205
-101
lines changed

composer.json

Lines changed: 87 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,92 @@
11
{
2-
"name": "articulate/concise",
3-
"description": "A super lightweight data mapper ORM for Laravel",
4-
"keywords": [
5-
"laravel",
6-
"orm",
7-
"data mapper",
8-
"datamapper",
9-
"lightweight"
10-
],
11-
"type": "library",
12-
"require": {
13-
"php": "^8.4",
14-
"laravel/framework": "^11.0 | ^12.0"
15-
},
16-
"require-dev": {
17-
"phpunit/phpunit": "^11.0.1",
18-
"orchestra/testbench": "^9.4",
19-
"larastan/larastan": "^2.9",
20-
"infection/infection": "^0.29.8"
21-
},
22-
"license": "MIT",
23-
"autoload": {
24-
"psr-4": {
25-
"Articulate\\Concise\\": "src/"
26-
},
27-
"files": []
28-
},
29-
"autoload-dev": {
30-
"psr-4": {
31-
"Articulate\\Concise\\Tests\\": "tests/",
32-
"App\\": "workbench/app/",
33-
"Database\\Factories\\": "workbench/database/factories/",
34-
"Database\\Mappers\\": "workbench/database/mappers/",
35-
"Database\\Seeders\\": "workbench/database/seeders/"
36-
}
2+
"name" : "articulate/concise",
3+
"description" : "A super lightweight data mapper ORM for Laravel",
4+
"keywords" : [
5+
"laravel",
6+
"orm",
7+
"data mapper",
8+
"datamapper",
9+
"lightweight"
10+
],
11+
"type" : "library",
12+
"require" : {
13+
"php" : "^8.4",
14+
"laravel/framework": "^11.0 | ^12.0"
15+
},
16+
"require-dev" : {
17+
"phpunit/phpunit" : "^11.0.1",
18+
"orchestra/testbench": "^9.4",
19+
"larastan/larastan" : "^3.0",
20+
"infection/infection": "^0.29.8"
21+
},
22+
"license" : "MIT",
23+
"autoload" : {
24+
"psr-4": {
25+
"Articulate\\Concise\\": "src/"
3726
},
38-
"authors": [
39-
{
40-
"name": "Ollie Read",
41-
"email": "code@ollieread.com"
42-
}
27+
"files": []
28+
},
29+
"autoload-dev" : {
30+
"psr-4": {
31+
"Articulate\\Concise\\Tests\\": "tests/",
32+
"App\\" : "workbench/app/",
33+
"Database\\Factories\\" : "workbench/database/factories/",
34+
"Database\\Mappers\\" : "workbench/database/mappers/",
35+
"Database\\Seeders\\" : "workbench/database/seeders/"
36+
}
37+
},
38+
"authors" : [
39+
{
40+
"name" : "Ollie Read",
41+
"email": "code@ollieread.com"
42+
}
43+
],
44+
"minimum-stability": "stable",
45+
"scripts" : {
46+
"post-autoload-dump": [
47+
"@clear",
48+
"@prepare",
49+
"@php vendor/bin/testbench package:discover --ansi"
4350
],
44-
"minimum-stability": "stable",
45-
"scripts": {
46-
"post-autoload-dump": [
47-
"@clear",
48-
"@prepare",
49-
"@php vendor/bin/testbench package:discover --ansi"
50-
],
51-
"phpstan": "@php vendor/bin/phpstan analyse --memory-limit=2G --verbose --ansi",
52-
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
53-
"prepare": "@php vendor/bin/testbench package:discover --ansi",
54-
"build": "@php vendor/bin/testbench workbench:build --ansi",
55-
"serve": [
56-
"Composer\\Config::disableProcessTimeout",
57-
"@build",
58-
"@php vendor/bin/testbench serve --ansi"
59-
],
60-
"analyse": [
61-
"phpstan"
62-
],
63-
"test": [
64-
"@clear",
65-
"@prepare",
66-
"@build",
67-
"@php vendor/bin/phpunit"
68-
],
69-
"mutation": [
70-
"@clear",
71-
"@prepare",
72-
"@build",
73-
"@php vendor/bin/infection --threads=12"
74-
],
75-
"lint": [
76-
"@php vendor/bin/phpstan analyse --verbose --ansi"
77-
]
78-
},
79-
"extra": {
80-
"laravel": {
81-
"providers": [
82-
"Articulate\\Concise\\ConciseServiceProvider"
83-
],
84-
"facades": []
85-
}
86-
},
87-
"config": {
88-
"allow-plugins": {
89-
"infection/extension-installer": true
90-
}
51+
"phpstan" : "@php vendor/bin/phpstan analyse --memory-limit=2G --verbose --ansi",
52+
"clear" : "@php vendor/bin/testbench package:purge-skeleton --ansi",
53+
"prepare" : "@php vendor/bin/testbench package:discover --ansi",
54+
"build" : "@php vendor/bin/testbench workbench:build --ansi",
55+
"serve" : [
56+
"Composer\\Config::disableProcessTimeout",
57+
"@build",
58+
"@php vendor/bin/testbench serve --ansi"
59+
],
60+
"analyse" : [
61+
"phpstan"
62+
],
63+
"test" : [
64+
"@clear",
65+
"@prepare",
66+
"@build",
67+
"@php vendor/bin/phpunit"
68+
],
69+
"mutation" : [
70+
"@clear",
71+
"@prepare",
72+
"@build",
73+
"@php vendor/bin/infection --threads=12"
74+
],
75+
"lint" : [
76+
"@php vendor/bin/phpstan analyse --verbose --ansi"
77+
]
78+
},
79+
"extra" : {
80+
"laravel": {
81+
"providers": [
82+
"Articulate\\Concise\\ConciseServiceProvider"
83+
],
84+
"facades" : []
85+
}
86+
},
87+
"config" : {
88+
"allow-plugins": {
89+
"infection/extension-installer": true
9190
}
91+
}
9292
}

src/Concise.php

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
use Articulate\Concise\Contracts\EntityMapper;
77
use Articulate\Concise\Contracts\Mapper;
88
use Articulate\Concise\Contracts\Repository;
9+
use Illuminate\Database\RecordsNotFoundException;
910
use Illuminate\Foundation\Application;
11+
use Illuminate\Support\Str;
12+
use ReflectionClass;
13+
use RuntimeException;
14+
use Throwable;
1015

1116
final class Concise
1217
{
@@ -85,17 +90,17 @@ public function entity(string $class): ?EntityMapper
8590
*
8691
* @param class-string<EntityObject> $class
8792
*
88-
* @return \Articulate\Concise\Contracts\Repository<EntityObject>|null
93+
* @return \Articulate\Concise\Contracts\Repository<EntityObject>
8994
*
9095
* @throws \Illuminate\Contracts\Container\BindingResolutionException
9196
*/
92-
public function repository(string $class): ?Repository
97+
public function repository(string $class): Repository
9398
{
9499
/** @var \Articulate\Concise\Contracts\EntityMapper<EntityObject>|null $mapper */
95100
$mapper = $this->entity($class);
96101

97102
if ($mapper === null) {
98-
return null;
103+
throw new RuntimeException('No entity mapper registered for class [' . $class . ']');
99104
}
100105

101106
$repository = $mapper->repository();
@@ -107,9 +112,76 @@ public function repository(string $class): ?Repository
107112
);
108113
}
109114

110-
return $this->app->make($repository, [
115+
/** @var \Articulate\Concise\Contracts\Repository<EntityObject> $instance */
116+
$instance = $this->app->make($repository, [
111117
'mapper' => $mapper,
112118
'connection' => $this->app->make('db')->connection($mapper->connection()),
113119
]);
120+
121+
return $instance;
122+
}
123+
124+
/**
125+
* Get a lazy entity instance.
126+
*
127+
* @template EntityObject of object
128+
*
129+
* @param class-string<EntityObject> $class
130+
* @param string|int $identity
131+
* @param array<string, mixed> $data
132+
*
133+
* @return object|null
134+
*
135+
* @phpstan-return EntityObject|null
136+
*
137+
* @throws \Illuminate\Contracts\Container\BindingResolutionException
138+
*/
139+
public function lazy(string $class, string|int $identity, array $data = []): ?object
140+
{
141+
/** @var \Articulate\Concise\Contracts\EntityMapper<EntityObject>|null $mapper */
142+
$mapper = $this->entity($class);
143+
144+
if ($mapper === null) {
145+
return null;
146+
}
147+
148+
$repository = $this->repository($class);
149+
150+
try {
151+
$reflector = new ReflectionClass($class);
152+
$lazy = $reflector->newLazyProxy(
153+
/**
154+
* @phpstan-param EntityObject $proxy
155+
*/
156+
function (object $proxy) use ($repository, $identity, $mapper) {
157+
/** @var EntityObject|null $entity */
158+
$entity = $repository->getOne(Criterion::forIdentifier($identity));
159+
160+
if ($entity === null) {
161+
throw new RecordsNotFoundException('No results for entity [' . $mapper->class() . ']');
162+
}
163+
164+
return $entity;
165+
}
166+
);
167+
} catch (Throwable $e) {
168+
report($e);
169+
170+
return null;
171+
}
172+
173+
foreach ($data as $property => $value) {
174+
if ($reflector->hasProperty($property)) {
175+
$reflector->getProperty($property)->setRawValueWithoutLazyInitialization($lazy, $value);
176+
} else {
177+
$property = Str::studly($property);
178+
179+
if ($reflector->hasProperty($property)) {
180+
$reflector->getProperty($property)->setRawValueWithoutLazyInitialization($lazy, $value);
181+
}
182+
}
183+
}
184+
185+
return $lazy;
114186
}
115187
}

src/EntityRepository.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55

66
use Articulate\Concise\Contracts\Criteria;
77
use Articulate\Concise\Contracts\EntityMapper;
8-
use Articulate\Concise\Criteria\ForIdentifier;
9-
use Articulate\Concise\Criteria\WhereColumn;
108
use Illuminate\Contracts\Pagination\Paginator;
119
use Illuminate\Database\Connection;
1210
use Illuminate\Support\Collection;
@@ -15,6 +13,7 @@
1513
* @template EntityObject of object
1614
*
1715
* @implements \Articulate\Concise\Contracts\Repository<EntityObject>
16+
* @implements \Articulate\Concise\Contracts\RoutableRepository<EntityObject>
1817
*/
1918
final class EntityRepository implements Contracts\Repository, Contracts\RoutableRepository
2019
{

src/Query/Builder.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Articulate\Concise\Query;
55

66
use Articulate\Concise\Contracts\EntityMapper;
7+
use Illuminate\Contracts\Database\Query\Expression;
78
use Illuminate\Database\Concerns\BuildsQueries;
89
use Illuminate\Database\ConnectionInterface;
910
use Illuminate\Database\Query\Builder as BaseBuilder;
@@ -48,19 +49,23 @@ public function __construct(
4849
* @return object|null
4950
*
5051
* @phpstan-return EntityObject|null
51-
* @noinspection PhpHierarchyChecksInspection
5252
*/
5353
private function hydrate(array|object|null $record): ?object
5454
{
5555
if ($record === null) {
5656
return null;
5757
}
5858

59-
return $this->mapper->toObject((array)$record);
59+
if (is_object($record)) {
60+
/** @var array<string, mixed> $record */
61+
$record = (array)$record;
62+
}
63+
64+
return $this->mapper->toObject($record);
6065
}
6166

6267
/**
63-
* @param iterable<array<string, mixed>|\stdClass> $records
68+
* @param iterable<array<string, mixed>|object> $records
6469
*
6570
* @return \Illuminate\Support\Collection<array-key, EntityObject>
6671
*/
@@ -69,7 +74,7 @@ private function hydrateMany(iterable $records): Collection
6974
$entities = [];
7075

7176
foreach ($records as $record) {
72-
$entities[] = $this->hydrate((array)$record);
77+
$entities[] = $this->hydrate($record);
7378
}
7479

7580
return collect(array_filter($entities));
@@ -89,9 +94,29 @@ public function get($columns = ['*']): Collection
8994
$records = parent::get($columns);
9095

9196
if ($records->isEmpty()) {
97+
/** @var \Illuminate\Support\Collection<int, EntityObject> */
9298
return collect();
9399
}
94100

95101
return $this->hydrateMany($records);
96102
}
103+
104+
/**
105+
* Qualify the given column name by the entity table.
106+
*
107+
* @param string|\Illuminate\Contracts\Database\Query\Expression $column
108+
*
109+
* @return string
110+
*/
111+
public function qualifyColumn(string|Expression $column): string
112+
{
113+
$column = $column instanceof Expression ? (string)$column->getValue($this->getGrammar()) : $column;
114+
$table = $this->mapper->table();
115+
116+
if (str_contains($column, '.')) {
117+
return $column;
118+
}
119+
120+
return $table . '.' . $column;
121+
}
97122
}

0 commit comments

Comments
 (0)