Skip to content

Commit e62390e

Browse files
authored
Reduce PHPStan baseline by addressing actual issues (#1083)
* Reduce PHPStan baseline by addressing actual issues Remove 13 stale baseline entries by fixing the underlying issues: - BakeSeedCommand: drop wrong @var annotation, cast option value; rewrite reference foreach to track removable keys explicitly - AbstractAdapter: tighten generateBulkInsertSql @PARAM type and cast keys to string for array_map - AdapterFactory: declare final constructor (allows safe new static) - MysqlAdapter: drop redundant nested isset() checks - Environment: useTransactions() is on the interface, drop the dead method_exists guard; gate up()/down() dispatch with method_exists - Manager: cast strpos result, fall back to 0 in max() - TableFinder: drop redundant isset checks on always-set list keys - MigrationHelper: rewrite as if/else so PHPStan can narrow the type Two entries remain in the baseline: - Index::setUnique dynamic dispatch (handled via continue) - SqliteAdapter null check kept for test mock compatibility * Apply rector fixes Match parent visibility on inherited buildOptionParser overrides, type the closure parameter, simplify if/else to ternary, and add the newline rector wants.
1 parent 9fc2d25 commit e62390e

11 files changed

Lines changed: 39 additions & 110 deletions

File tree

‎phpstan-baseline.neon‎

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,5 @@
11
parameters:
22
ignoreErrors:
3-
-
4-
message: '#^PHPDoc tag @var with type string is not subtype of native type non\-falsy\-string\|true\.$#'
5-
identifier: varTag.nativeType
6-
count: 1
7-
path: src/Command/BakeSeedCommand.php
8-
9-
-
10-
message: '#^Strict comparison using \!\=\= between string and false will always evaluate to true\.$#'
11-
identifier: notIdentical.alwaysTrue
12-
count: 1
13-
path: src/Command/BakeSeedCommand.php
14-
15-
-
16-
message: '#^Parameter \#1 \$callback of function array_map expects \(callable\(int\|string\)\: mixed\)\|null, Closure\(string\)\: string given\.$#'
17-
identifier: argument.type
18-
count: 1
19-
path: src/Db/Adapter/AbstractAdapter.php
20-
21-
-
22-
message: '#^Unsafe usage of new static\(\)\.$#'
23-
identifier: new.static
24-
count: 1
25-
path: src/Db/Adapter/AdapterFactory.php
26-
27-
-
28-
message: '#^Offset ''id'' on non\-empty\-array\<string, mixed\> in isset\(\) always exists and is not nullable\.$#'
29-
identifier: isset.offset
30-
count: 2
31-
path: src/Db/Adapter/MysqlAdapter.php
32-
333
-
344
message: '#^Strict comparison using \!\=\= between Cake\\Database\\StatementInterface and null will always evaluate to true\.$#'
355
identifier: notIdentical.alwaysTrue
@@ -41,51 +11,3 @@ parameters:
4111
identifier: method.notFound
4212
count: 1
4313
path: src/Db/Table/Index.php
44-
45-
-
46-
message: '#^Call to an undefined method Migrations\\MigrationInterface\:\:down\(\)\.$#'
47-
identifier: method.notFound
48-
count: 1
49-
path: src/Migration/Environment.php
50-
51-
-
52-
message: '#^Call to an undefined method Migrations\\MigrationInterface\:\:up\(\)\.$#'
53-
identifier: method.notFound
54-
count: 1
55-
path: src/Migration/Environment.php
56-
57-
-
58-
message: '#^Call to function method_exists\(\) with Migrations\\MigrationInterface and ''useTransactions'' will always evaluate to true\.$#'
59-
identifier: function.alreadyNarrowedType
60-
count: 1
61-
path: src/Migration/Environment.php
62-
63-
-
64-
message: '#^Method Migrations\\Migration\\Manager\:\:getMigrationClassName\(\) should return class\-string\<Migrations\\MigrationInterface\> but returns string\.$#'
65-
identifier: return.type
66-
count: 2
67-
path: src/Migration/Manager.php
68-
69-
-
70-
message: '#^Parameter \#1 \.\.\.\$arg1 of function max expects non\-empty\-array, array given\.$#'
71-
identifier: argument.type
72-
count: 1
73-
path: src/Migration/Manager.php
74-
75-
-
76-
message: '#^Parameter \#3 \$length of function substr expects int\|null, int\<0, max\>\|false given\.$#'
77-
identifier: argument.type
78-
count: 1
79-
path: src/Migration/Manager.php
80-
81-
-
82-
message: '#^Offset 0 on non\-empty\-list\<string\> in isset\(\) always exists and is not nullable\.$#'
83-
identifier: isset.offset
84-
count: 2
85-
path: src/Util/TableFinder.php
86-
87-
-
88-
message: '#^Possibly invalid array key type Cake\\Database\\Schema\\TableSchemaInterface\|string\.$#'
89-
identifier: offsetAccess.invalidOffset
90-
count: 2
91-
path: src/View/Helper/MigrationHelper.php

‎src/Command/BakeSeedCommand.php‎

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ public function templateData(Arguments $arguments): array
116116
if ($arguments->getOption('data')) {
117117
$limit = (int)$arguments->getOption('limit');
118118

119-
/** @var string $fields */
120-
$fields = $arguments->getOption('fields') ?: '*';
119+
$fields = (string)$arguments->getOption('fields') ?: '*';
121120
if ($fields !== '*') {
122121
$fields = explode(',', $fields);
123122
}
@@ -173,7 +172,7 @@ protected function bake(string $name, Arguments $args, ConsoleIo $io): void
173172
* @param \Cake\Console\ConsoleOptionParser $parser Option parser to update.
174173
* @return \Cake\Console\ConsoleOptionParser
175174
*/
176-
public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
175+
protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
177176
{
178177
$parser = parent::buildOptionParser($parser);
179178

@@ -214,6 +213,7 @@ protected function prettifyArray(array $array, int $tabCount = 3, string $indent
214213
$lines = explode("\n", $content);
215214

216215
$inString = false;
216+
$removeKeys = [];
217217

218218
foreach ($lines as $k => &$line) {
219219
if ($k === 0) {
@@ -237,7 +237,7 @@ protected function prettifyArray(array $array, int $tabCount = 3, string $indent
237237
$tabCount--;
238238
} elseif (preg_match("/^\d+\s\=\>\s$/", $line)) {
239239
// Mark '0 =>' kind of lines to remove
240-
$line = false;
240+
$removeKeys[] = $k;
241241
continue;
242242
}
243243

@@ -264,10 +264,9 @@ protected function prettifyArray(array $array, int $tabCount = 3, string $indent
264264
}
265265
unset($line);
266266

267-
// Remove marked lines
268-
$lines = array_filter($lines, function ($line): bool {
269-
return $line !== false;
270-
});
267+
foreach ($removeKeys as $key) {
268+
unset($lines[$key]);
269+
}
271270

272271
return implode("\n", $lines);
273272
}

‎src/Command/BakeSimpleMigrationCommand.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ protected function getMigrationName(?string $name = null): string
236236
* @param \Cake\Console\ConsoleOptionParser $parser Option parser to update.
237237
* @return \Cake\Console\ConsoleOptionParser
238238
*/
239-
public function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
239+
protected function buildOptionParser(ConsoleOptionParser $parser): ConsoleOptionParser
240240
{
241241
$parser = $this->_setCommonOptions($parser);
242242

‎src/Db/Adapter/AbstractAdapter.php‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ public function bulkinsert(
841841
* Generates the SQL for a bulk insert.
842842
*
843843
* @param \Migrations\Db\Table\TableMetadata $table The table to insert into
844-
* @param array $rows The rows to insert
844+
* @param array<int, array<string, mixed>> $rows The rows to insert
845845
* @param \Migrations\Db\InsertMode|null $mode Insert mode
846846
* @param array<string>|null $updateColumns Columns to update on upsert conflict
847847
* @param array<string>|null $conflictColumns Columns that define uniqueness for upsert (unused in MySQL)
@@ -859,15 +859,15 @@ protected function generateBulkInsertSql(
859859
$this->getInsertPrefix($mode),
860860
$this->quoteTableName($table->getName()),
861861
);
862-
$current = current($rows);
863-
$keys = array_keys($current);
862+
$current = (array)current($rows);
863+
$keys = array_map(strval(...), array_keys($current));
864864

865865
$sql .= '(' . implode(', ', array_map($this->quoteColumnName(...), $keys)) . ') VALUES ';
866866

867867
$upsertClause = $this->getUpsertClause($mode, $updateColumns, $conflictColumns);
868868

869869
if ($this->isDryRunEnabled()) {
870-
$values = array_map(function ($row): string {
870+
$values = array_map(function (array $row): string {
871871
return '(' . implode(', ', array_map($this->quoteValue(...), $row)) . ')';
872872
}, $rows);
873873

‎src/Db/Adapter/AdapterFactory.php‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ class AdapterFactory
2323
*/
2424
protected static ?AdapterFactory $instance = null;
2525

26+
/**
27+
* Constructor.
28+
*/
29+
final public function __construct()
30+
{
31+
}
32+
2633
/**
2734
* Get the factory singleton instance.
2835
*

‎src/Db/Adapter/MysqlAdapter.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,11 @@ public function createTable(TableMetadata $table, array $columns = [], array $in
300300
);
301301

302302
// Add the default primary key
303-
if (!isset($options['id']) || (isset($options['id']) && $options['id'] === true)) {
303+
if (!isset($options['id']) || $options['id'] === true) {
304304
$options['id'] = 'id';
305305
}
306306

307-
if (isset($options['id']) && is_string($options['id'])) {
307+
if (is_string($options['id'])) {
308308
$useUnsigned = (bool)Configure::read('Migrations.unsigned_primary_keys');
309309
// Handle id => "field_name" to support AUTO_INCREMENT
310310
$column = new Column();

‎src/Migration/Environment.php‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,7 @@ public function executeMigration(MigrationInterface $migration, string $directio
6767
$migration->{MigrationInterface::INIT}();
6868
}
6969

70-
$atomic = $adapter->hasTransactions();
71-
if (method_exists($migration, 'useTransactions')) {
72-
$atomic = $migration->useTransactions();
73-
}
70+
$atomic = $migration->useTransactions();
7471
// begin the transaction if the adapter supports it
7572
if ($atomic) {
7673
$adapter->beginTransaction();
@@ -97,7 +94,7 @@ public function executeMigration(MigrationInterface $migration, string $directio
9794
} else {
9895
$migration->{MigrationInterface::CHANGE}();
9996
}
100-
} else {
97+
} elseif (method_exists($migration, $direction)) {
10198
$migration->{$direction}();
10299
}
103100
}

‎src/Migration/Manager.php‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,18 +322,25 @@ public function markMigrated(int $version, string $path): bool
322322
* Resolves a migration class name based on $path
323323
*
324324
* @param string $path Path to the migration file of which we want the class name
325-
* @return class-string<\Migrations\MigrationInterface> Migration class name
325+
* @return string Migration class name
326+
* @phpstan-return class-string<\Migrations\MigrationInterface>
326327
*/
327328
protected function getMigrationClassName(string $path): string
328329
{
329330
$class = (string)preg_replace('/^\d+_/', '', basename($path));
330331
$class = str_replace('_', ' ', $class);
331332
$class = ucwords($class);
332333
$class = str_replace(' ', '', $class);
333-
if (str_contains($class, '.')) {
334-
return substr($class, 0, strpos($class, '.'));
334+
335+
$dotPos = strpos($class, '.');
336+
if ($dotPos !== false) {
337+
/** @var class-string<\Migrations\MigrationInterface> $name */
338+
$name = substr($class, 0, $dotPos);
339+
340+
return $name;
335341
}
336342

343+
/** @var class-string<\Migrations\MigrationInterface> $class */
337344
return $class;
338345
}
339346

@@ -448,7 +455,8 @@ public function migrate(?int $version = null, bool $fake = false, ?int $count =
448455
}
449456

450457
if ($version === null) {
451-
$version = max(array_merge($versions, array_keys($migrations)));
458+
$candidates = [...$versions, ...array_keys($migrations)];
459+
$version = $candidates ? max($candidates) : 0;
452460
} elseif ($version !== 0 && !isset($migrations[$version])) {
453461
$this->getIo()->out(sprintf(
454462
'<comment>warning</comment> %s is not a valid version',

‎src/Util/TableFinder.php‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public function getTablesToBake(CollectionInterface $collection, array $options
8181

8282
$config = (array)ConnectionManager::getConfig($this->connection);
8383
$key = isset($config['schema']) ? 'schema' : 'database';
84-
if (isset($split[0], $split[1]) && $config[$key] === $split[1]) {
84+
if (isset($split[1]) && $config[$key] === $split[1]) {
8585
$table = $split[0];
8686
}
8787
}
@@ -191,7 +191,7 @@ public function fetchTableName(string $className, ?string $pluginName = null): a
191191
$config = ConnectionManager::getConfig($this->connection);
192192
if (is_array($config)) {
193193
$key = isset($config['schema']) ? 'schema' : 'database';
194-
if (isset($splitted[0]) && $config[$key] === $splitted[1]) {
194+
if ($config[$key] === $splitted[1]) {
195195
$tableName = $splitted[0];
196196
}
197197
}

‎src/View/Helper/MigrationHelper.php‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -708,10 +708,7 @@ public function getCreateTablesElementData(array $tables): array
708708
'tables' => [],
709709
];
710710
foreach ($tables as $table) {
711-
$tableName = $table;
712-
if ($table instanceof TableSchemaInterface) {
713-
$tableName = $table->name();
714-
}
711+
$tableName = $table instanceof TableSchemaInterface ? $table->name() : $table;
715712
$data = $this->getCreateTableData($table);
716713
$tableConstraintsNoUnique = array_filter(
717714
$data['constraints'],

0 commit comments

Comments
 (0)