Skip to content

Commit 0186d98

Browse files
committed
fixed PHPStan errors WIP
1 parent 834d64d commit 0186d98

23 files changed

Lines changed: 406 additions & 129 deletions

phpstan.neon

Lines changed: 158 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,162 @@
11
parameters:
2-
level: 5
2+
level: 8
33

44
paths:
55
- src
6+
7+
excludePaths:
8+
- src/compatibility.php
9+
- src/compatibility-intf.php
10+
11+
fileExtensions:
12+
- php
13+
- phtml
14+
15+
ignoreErrors:
16+
# Readonly lazy-loading via __get magic
17+
-
18+
identifier: property.uninitializedReadonly
19+
paths:
20+
- src/Database/Reflection.php
21+
- src/Database/Reflection/Table.php
22+
-
23+
identifier: unset.readOnlyProperty
24+
paths:
25+
- src/Database/Reflection.php
26+
- src/Database/Reflection/Table.php
27+
-
28+
identifier: property.readOnlyAssignNotInConstructor
29+
paths:
30+
- src/Database/Reflection.php
31+
- src/Database/Reflection/Table.php
32+
33+
# Deprecated interfaces without generic types
34+
-
35+
identifier: missingType.generics
36+
paths:
37+
- src/Database/IRow.php
38+
- src/Database/IRowContainer.php
39+
40+
# Generic conflicts from deprecated IRowContainer/IRow extending Traversable without type params
41+
-
42+
identifier: generics.interfaceConflict
43+
paths:
44+
- src/Database/ResultSet.php
45+
- src/Database/Row.php
46+
- src/Database/Table/GroupedSelection.php
47+
- src/Database/Table/ActiveRow.php
48+
- src/Database/Table/Selection.php
49+
50+
# Iterator/ArrayAccess covariance/contravariance (PHP interface limitation)
51+
-
52+
identifier: method.childReturnType
53+
paths:
54+
- src/Database/ResultSet.php
55+
- src/Database/Table/Selection.php
56+
-
57+
identifier: method.childParameterType
58+
paths:
59+
- src/Database/Row.php
60+
- src/Database/Table/Selection.php
61+
62+
# Intentional new static() in exception hierarchy
63+
-
64+
identifier: new.static
65+
path: src/Database/DriverException.php
66+
67+
# Closure variables consumed by require'd phtml template
68+
-
69+
identifier: closure.unusedUse
70+
path: src/Bridges/DatabaseTracy/ConnectionPanel.php
71+
72+
# Lazy-loading side effect via __get magic
73+
-
74+
identifier: expr.resultUnused
75+
path: src/Database/Reflection.php
76+
77+
# DI extension: $this->config is array|object from Nette Schema
78+
-
79+
identifier: foreach.nonIterable
80+
path: src/Bridges/DatabaseDI/DatabaseExtension.php
81+
82+
# PDOException::$queryString is set by PDO engine, not formally declared
83+
-
84+
identifier: property.notFound
85+
path: src/Bridges/DatabaseTracy/ConnectionPanel.php
86+
87+
# Dynamic callable construction: "is_$type"($value) where $type is always valid
88+
-
89+
identifier: callable.nonCallable
90+
path: src/Database/SqlPreprocessor.php
91+
92+
# Defensive runtime checks unreachable per @param type
93+
-
94+
identifier: instanceof.alwaysTrue
95+
path: src/Database/SqlPreprocessor.php
96+
-
97+
identifier: booleanAnd.alwaysFalse
98+
path: src/Database/SqlPreprocessor.php
99+
100+
# getPrimary() returns string for single-column PK (composite PK not supported here)
101+
-
102+
identifier: argument.type
103+
path: src/Database/Table/ActiveRow.php
104+
-
105+
identifier: array.invalidKey
106+
path: src/Database/Table/ActiveRow.php
107+
108+
# Internal SQL built from trusted components, generic covariance, getPrimary() type unions
109+
-
110+
identifier: argument.type
111+
paths:
112+
- src/Database/Table/Selection.php
113+
- src/Database/Table/GroupedSelection.php
114+
- src/Database/Table/SqlBuilder.php
115+
116+
# Generic T vs concrete ActiveRow assignments
117+
-
118+
identifier: assign.propertyType
119+
path: src/Database/Table/Selection.php
120+
121+
# Return type mismatches from generic covariance and internal caching
122+
-
123+
identifier: return.type
124+
paths:
125+
- src/Database/ResultSet.php
126+
- src/Database/Structure.php
127+
- src/Database/Table/Selection.php
128+
- src/Database/Table/GroupedSelection.php
129+
130+
# Array offset access on Row/ActiveRow objects and nullable arrays
131+
-
132+
identifier: offsetAccess.notFound
133+
paths:
134+
- src/Database/Helpers.php
135+
- src/Database/Table/Selection.php
136+
- src/Database/Table/SqlBuilder.php
137+
138+
# Defensive checks that are always true/false per PHPStan type narrowing
139+
-
140+
identifier: notIdentical.alwaysTrue
141+
path: src/Database/Helpers.php
142+
-
143+
identifier: isset.offset
144+
path: src/Database/Helpers.php
145+
-
146+
identifier: identical.alwaysFalse
147+
path: src/Database/Table/GroupedSelection.php
148+
149+
# Dynamic string concatenation in binary operations
150+
-
151+
identifier: binaryOp.invalid
152+
path: src/Database/Table/Selection.php
153+
154+
# isList() on iterable that could be array or Selection
155+
-
156+
identifier: staticMethod.impossibleType
157+
path: src/Database/Table/GroupedSelection.php
158+
159+
# Setting column value on iterable data
160+
-
161+
identifier: offsetAssign.valueType
162+
path: src/Database/Table/GroupedSelection.php

src/Bridges/DatabaseDI/DatabaseExtension.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public function beforeCompile(): void
6262
foreach ($this->config as $name => $config) {
6363
if ($config->debugger ?? $builder->getByType(Tracy\BlueScreen::class)) {
6464
$connection = $builder->getDefinition($this->prefix("$name.connection"));
65+
assert($connection instanceof Nette\DI\Definitions\ServiceDefinition);
6566
$connection->addSetup(
6667
[Nette\Bridges\DatabaseTracy\ConnectionPanel::class, 'initialize'],
6768
[$connection, $this->debugMode, $name, !empty($config->explain)],

src/Bridges/DatabaseTracy/ConnectionPanel.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ private function logQuery(Connection $connection, $result): void
8080
: debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
8181

8282
foreach ($trace as $row) {
83-
if (preg_match('~\.(php.?|phtml)$~', $row['file'] ?? '') && !$this->blueScreen->isCollapsed($row['file'])) {
83+
if (is_string($row['file'] ?? null)
84+
&& preg_match('~\.(php.?|phtml)$~', $row['file'])
85+
&& !$this->blueScreen->isCollapsed($row['file'])
86+
) {
8487
break;
8588
}
8689
array_shift($trace);
@@ -91,7 +94,7 @@ private function logQuery(Connection $connection, $result): void
9194
if ($this->count < $this->maxQueries) {
9295
$this->queries[] = [$connection, $result->getQueryString(), $result->getParameters(), $trace, $result->getTime(), $result->getRowCount(), null];
9396
}
94-
} elseif ($result instanceof \PDOException && $this->count < $this->maxQueries) {
97+
} elseif ($this->count < $this->maxQueries) {
9598
$this->queries[] = [$connection, $result->queryString, null, $trace, null, null, $result->getMessage()];
9699
}
97100
}
@@ -136,6 +139,7 @@ public function getPanel(): ?string
136139
}
137140

138141
$queries = [];
142+
$connection = null;
139143
foreach ($this->queries as $query) {
140144
[$connection, $sql, $params, , , , $error] = $query;
141145
$explain = null;
@@ -147,7 +151,7 @@ public function getPanel(): ?string
147151
$cmd = is_string($this->explain)
148152
? $this->explain
149153
: 'EXPLAIN';
150-
$explain = (new Nette\Database\ResultSet($connection, "$cmd $sql", $params))->fetchAll();
154+
$explain = (new Nette\Database\ResultSet($connection, "$cmd $sql", $params ?? []))->fetchAll();
151155
} catch (\PDOException) {
152156
}
153157
}

src/Bridges/DatabaseTracy/dist/panel.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php declare(strict_types=1); ?>
2-
<style class="tracy-debug">
2+
<?php /** @var Nette\Database\Connection $connection */ ?><?php /** @var list<array> $queries */ ?><?php /** @var string $name */ ?><?php /** @var int $count */ ?><?php /** @var float $totalTime */ ?><?php /** @var float $performanceScale */ ?><style class="tracy-debug">
33
#tracy-debug td.nette-DbConnectionPanel-sql { background: white !important; overflow-x: auto; max-width: 0; }
44
#tracy-debug .nette-DbConnectionPanel-source { color: #BBB !important }
55
#tracy-debug .nette-DbConnectionPanel-explain td { white-space: pre }

src/Bridges/DatabaseTracy/dist/tab.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?php declare(strict_types=1); ?>
2-
<span title="Nette\Database <?= Tracy\Helpers::escapeHtml($name) ?>
2+
<?php /** @var string $name */ ?><?php /** @var int $count */ ?><?php /** @var float $totalTime */ ?><span title="Nette\Database <?= Tracy\Helpers::escapeHtml($name) ?>
33
">
44
<svg viewBox="0 0 2048 2048">
55
<path fill="<?= Tracy\Helpers::escapeHtml($count ? '#b079d6' : '#aaa') ?>

src/Bridges/DatabaseTracy/panel.latte

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
{varType Nette\Database\Connection $connection}
2+
{varType list<array> $queries}
3+
{varType string $name}
4+
{varType int $count}
5+
{varType float $totalTime}
6+
{varType float $performanceScale}
17
<style class="tracy-debug">
28
#tracy-debug td.nette-DbConnectionPanel-sql { background: white !important; overflow-x: auto; max-width: 0; }
39
#tracy-debug .nette-DbConnectionPanel-source { color: #BBB !important }

src/Bridges/DatabaseTracy/tab.latte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
{varType string $name}
2+
{varType int $count}
3+
{varType float $totalTime}
14
<span title="Nette\Database {$name}">
25
<svg viewBox="0 0 2048 2048">
36
<path fill="{$count ? '#b079d6' : '#aaa'}" d="M1024 896q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0 768q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-384q237 0 443-43t325-127v170q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-170q119 84 325 127t443 43zm0-1152q208 0 385 34.5t280 93.5 103 128v128q0 69-103 128t-280 93.5-385 34.5-385-34.5-280-93.5-103-128v-128q0-69 103-128t280-93.5 385-34.5z"/>

src/Database/Connection.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ public function connect(): void
7171
$class = empty($this->options['driverClass'])
7272
? 'Nette\Database\Drivers\\' . ucfirst(str_replace('sql', 'Sql', $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME))) . 'Driver'
7373
: $this->options['driverClass'];
74-
$this->driver = new $class;
74+
$driver = new $class;
75+
\assert($driver instanceof Driver);
76+
$this->driver = $driver;
7577
$this->preprocessor = new SqlPreprocessor($this);
7678
$this->driver->initialize($this, $this->options);
7779
Arrays::invoke($this->onConnect, $this);
@@ -106,6 +108,7 @@ public function getDsn(): string
106108
public function getPdo(): PDO
107109
{
108110
$this->connect();
111+
assert($this->pdo !== null);
109112
return $this->pdo;
110113
}
111114

src/Database/Conventions/DiscoveredConventions.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function getPrimary(string $table): string|array|null
3535
public function getHasManyReference(string $nsTable, string $key): ?array
3636
{
3737
$candidates = $columnCandidates = [];
38-
$targets = $this->structure->getHasManyReference($nsTable);
38+
$targets = $this->structure->getHasManyReference($nsTable) ?? [];
3939
$table = preg_replace('#^(.*\.)?(.*)$#', '$2', $nsTable);
4040

4141
foreach ($targets as $targetNsTable => $targetColumns) {
@@ -87,7 +87,7 @@ public function getHasManyReference(string $nsTable, string $key): ?array
8787
*/
8888
public function getBelongsToReference(string $table, string $key): ?array
8989
{
90-
$tableColumns = $this->structure->getBelongsToReference($table);
90+
$tableColumns = $this->structure->getBelongsToReference($table) ?? [];
9191

9292
foreach ($tableColumns as $column => $targetTable) {
9393
if (stripos($column, $key) !== false) {

src/Database/Drivers/MsSqlDriver.php

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,10 @@ public function getTables(): array
105105

106106
while ($row = $rows->fetch()) {
107107
$tables[] = [
108-
'name' => $row['TABLE_SCHEMA'] . '.' . $row['TABLE_NAME'],
108+
'name' => (string) $row['TABLE_SCHEMA'] . '.' . (string) $row['TABLE_NAME'],
109+
'fullName' => null,
109110
'view' => ($row['TABLE_TYPE'] ?? null) === 'VIEW',
110-
'comment' => $row['comment'] ?? '',
111+
'comment' => (string) ($row['comment'] ?? ''),
111112
];
112113
}
113114

@@ -185,13 +186,23 @@ public function getIndexes(string $table): array
185186
X, $table_name);
186187

187188
while ($row = $rows->fetch()) {
188-
$id = $row['name_index'];
189-
$indexes[$id]['name'] = $id;
190-
$indexes[$id]['unique'] = $row['is_unique'] !== 'False';
191-
$indexes[$id]['primary'] = $row['is_primary_key'] !== 'False';
189+
$id = (string) $row['name_index'];
190+
if (!isset($indexes[$id])) {
191+
$indexes[$id] = [
192+
'name' => $id,
193+
'unique' => $row['is_unique'] !== 'False',
194+
'primary' => $row['is_primary_key'] !== 'False',
195+
'columns' => [],
196+
];
197+
}
198+
192199
$indexes[$id]['columns'][$row['id_column'] - 1] = $row['name_column'];
193200
}
194201

202+
foreach ($indexes as &$index) {
203+
$index['columns'] = array_values($index['columns']);
204+
}
205+
195206
return array_values($indexes);
196207
}
197208

@@ -225,15 +236,16 @@ public function getForeignKeys(string $table): array
225236
tab1.name = ?
226237
X, $table_name);
227238

228-
$id = 0;
229239
while ($row = $rows->fetch()) {
230-
$keys[$id]['name'] = $row['fk_name'];
231-
$keys[$id]['local'] = $row['column'];
232-
$keys[$id]['table'] = $table_schema . '.' . $row['referenced_table'];
233-
$keys[$id++]['foreign'] = $row['referenced_column'];
240+
$keys[] = [
241+
'name' => (string) $row['fk_name'],
242+
'local' => (string) $row['column'],
243+
'table' => $table_schema . '.' . (string) $row['referenced_table'],
244+
'foreign' => (string) $row['referenced_column'],
245+
];
234246
}
235247

236-
return array_values($keys);
248+
return $keys;
237249
}
238250

239251

0 commit comments

Comments
 (0)