Skip to content

Commit f1c8d4c

Browse files
committed
Merge branch 'wildcards' into 3.x
2 parents daf67f2 + 5bbca6c commit f1c8d4c

File tree

5 files changed

+102
-68
lines changed

5 files changed

+102
-68
lines changed

docs/custom-config-parameters.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,26 @@ These parameters are related to the `NoUnnecessaryCollectionCall` rule. You can
1111
By default, the default Laravel database migration path (`database/migrations`) is used to scan migration files to understand the table structure and model properties. If you have database migrations in other place than the default, you can use this config parameter to tell Larastan where the database migrations are stored.
1212

1313
You can give absolute paths, or paths relative to the PHPStan config file.
14+
Paths with wildcards are also supported (passed to `glob` function).
1415

1516
#### Example
17+
1618
```neon
1719
parameters:
1820
databaseMigrationsPath:
19-
- app/Domain/DomainA/migrations
20-
- app/Domain/DomainB/migrations
21+
- app/Domain/*/migrations
2122
```
2223

2324
**Note:** If your migrations are using `if` statements to conditionally alter database structure (ex: create table only if it's not there, add column only if table exists and column does not etc...) Larastan will assume those if statements evaluate to true and will consider everything from the `if` body.
2425

2526
## `disableMigrationScan`
27+
2628
**default**: `false`
2729

2830
You can disable use this config to disable migration scanning.
2931

3032
#### Example
33+
3134
```neon
3235
parameters:
3336
disableMigrationScan: true
@@ -37,12 +40,14 @@ parameters:
3740

3841
By default, Larastan will check `database/schema` directory to find schema dumps. If you have them in other locations or if you have multiple folders, you can use this config option to add them.
3942

43+
Paths with wildcards are also supported (passed to `glob` function).
44+
4045
#### Example
46+
4147
```neon
4248
parameters:
4349
squashedMigrationsPath:
44-
- app/Domain/DomainA/schema
45-
- app/Domain/DomainB/schema
50+
- app/Domain/*/schema
4651
```
4752

4853
#### PostgreSQL
@@ -51,21 +56,25 @@ The package used to parse the schema dumps, [phpmyadmin/sql-parser](https://gith
5156
It can read (or rather, try to read) PostgreSQL dumps provided they are in the *plain text (and not the 'custom') format*, but the mileage may vary as problems have been noted with timestamp columns and lengthy parse time on more complicated dumps.
5257

5358
The viable options for PostgreSQL at the moment are:
54-
1. Use the [laravel-ide-helper](https://github.com/barryvdh/laravel-ide-helper) package to write PHPDocs directly to the Models.
59+
60+
1. Use the [laravel-ide-helper](https://github.com/barryvdh/laravel-ide-helper) package to write PHPDocs directly to the Models.
5561
2. Use the [laravel-migrations-generator](https://github.com/kitloong/laravel-migrations-generator) to generate migration files (or a singular squashed migration file) for Larastan to scan with the `databaseMigrationsPath` setting.
5662

5763
## `disableSchemaScan`
64+
5865
**default**: `false`
5966

6067
You can disable use this config to disable schema scanning.
6168

6269
#### Example
70+
6371
```neon
6472
parameters:
6573
disableSchemaScan: true
6674
```
6775

6876
## `checkModelProperties`
77+
6978
**default**: `false`
7079

7180
This config parameter enables the checks for model properties that are passed to methods. You can read the details [here](rules.md#modelpropertyrule).
@@ -78,6 +87,7 @@ parameters:
7887
```
7988

8089
## `checkModelAppends`
90+
8191
**default**: `false`
8292

8393
This config parameter enables the checks the model's $appends property for computed properties. You can read the details [here](rules.md#modelappendsrule).

extension.neon

+3
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,9 @@ services:
564564
-
565565
class: Larastan\Larastan\Internal\ConsoleApplicationHelper
566566

567+
-
568+
class: Larastan\Larastan\Internal\FileHelper
569+
567570
-
568571
class: Larastan\Larastan\Support\HigherOrderCollectionProxyHelper
569572

src/Internal/FileHelper.php

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Larastan\Larastan\Internal;
6+
7+
use PHPStan\File\FileHelper as PHPStanFileHelper;
8+
use RecursiveDirectoryIterator;
9+
use RecursiveIteratorIterator;
10+
use RegexIterator;
11+
use SplFileInfo;
12+
13+
use function array_reduce;
14+
use function glob;
15+
use function is_dir;
16+
use function is_string;
17+
use function iterator_to_array;
18+
use function preg_match;
19+
20+
use const GLOB_ONLYDIR;
21+
22+
/** @internal */
23+
final class FileHelper
24+
{
25+
public function __construct(
26+
private PHPStanFileHelper $fileHelper,
27+
) {
28+
}
29+
30+
/**
31+
* @param array<array-key, string> $directories
32+
*
33+
* @return array<string, SplFileInfo>
34+
*/
35+
public function getFiles(array $directories, string|null $filter = null): array
36+
{
37+
return array_reduce(
38+
$directories,
39+
function (array $carry, string $path) use ($filter): array {
40+
$absolutePath = $this->fileHelper->absolutizePath($path);
41+
42+
if ($this->isGlobPattern($absolutePath)) {
43+
$glob = glob($absolutePath, GLOB_ONLYDIR);
44+
45+
if ($glob === false) {
46+
return $carry;
47+
}
48+
49+
$directories = $glob;
50+
} else {
51+
if (! is_dir($absolutePath)) {
52+
return $carry;
53+
}
54+
55+
$directories = [$absolutePath];
56+
}
57+
58+
foreach ($directories as $directory) {
59+
$iterator = new RecursiveIteratorIterator(
60+
new RecursiveDirectoryIterator($directory),
61+
);
62+
63+
if (is_string($filter)) {
64+
$iterator = new RegexIterator($iterator, $filter);
65+
}
66+
67+
$carry += iterator_to_array($iterator);
68+
}
69+
70+
return $carry;
71+
},
72+
[],
73+
);
74+
}
75+
76+
private function isGlobPattern(string $path): bool
77+
{
78+
return preg_match('~[*?[\]]~', $path) > 0;
79+
}
80+
}

src/Properties/MigrationHelper.php

+2-31
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,13 @@
44

55
namespace Larastan\Larastan\Properties;
66

7-
use PHPStan\File\FileHelper;
7+
use Larastan\Larastan\Internal\FileHelper;
88
use PHPStan\Parser\Parser;
99
use PHPStan\Parser\ParserErrorsException;
10-
use RecursiveDirectoryIterator;
11-
use RecursiveIteratorIterator;
12-
use RegexIterator;
1310
use SplFileInfo;
1411

1512
use function count;
1613
use function database_path;
17-
use function is_dir;
18-
use function iterator_to_array;
1914
use function uasort;
2015

2116
class MigrationHelper
@@ -40,7 +35,7 @@ public function parseMigrations(ModelDatabaseHelper &$modelDatabaseHelper): void
4035
}
4136

4237
$schemaAggregator = new SchemaAggregator($modelDatabaseHelper);
43-
$filesArray = $this->getMigrationFiles();
38+
$filesArray = $this->fileHelper->getFiles($this->databaseMigrationPath, '/\.php$/i');
4439

4540
if (empty($filesArray)) {
4641
return;
@@ -58,28 +53,4 @@ public function parseMigrations(ModelDatabaseHelper &$modelDatabaseHelper): void
5853
}
5954
}
6055
}
61-
62-
/** @return SplFileInfo[] */
63-
private function getMigrationFiles(): array
64-
{
65-
/** @var SplFileInfo[] $migrationFiles */
66-
$migrationFiles = [];
67-
68-
foreach ($this->databaseMigrationPath as $additionalPath) {
69-
$absolutePath = $this->fileHelper->absolutizePath($additionalPath);
70-
71-
if (! is_dir($absolutePath)) {
72-
continue;
73-
}
74-
75-
$migrationFiles += iterator_to_array(
76-
new RegexIterator(
77-
new RecursiveIteratorIterator(new RecursiveDirectoryIterator($absolutePath)),
78-
'/\.php$/i',
79-
),
80-
);
81-
}
82-
83-
return $migrationFiles;
84-
}
8556
}

src/Properties/SquashedMigrationHelper.php

+2-32
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,20 @@
44

55
namespace Larastan\Larastan\Properties;
66

7+
use Larastan\Larastan\Internal\FileHelper;
78
use Larastan\Larastan\Properties\Schema\PhpMyAdminDataTypeToPhpTypeConverter;
89
use PhpMyAdmin\SqlParser\Components\CreateDefinition;
910
use PhpMyAdmin\SqlParser\Exceptions\ParserException;
1011
use PhpMyAdmin\SqlParser\Parser;
1112
use PhpMyAdmin\SqlParser\Statement;
1213
use PhpMyAdmin\SqlParser\Statements\CreateStatement;
13-
use PHPStan\File\FileHelper;
14-
use RecursiveDirectoryIterator;
15-
use RecursiveIteratorIterator;
16-
use RegexIterator;
17-
use SplFileInfo;
1814

1915
use function array_filter;
2016
use function array_key_exists;
2117
use function database_path;
2218
use function explode;
2319
use function file_get_contents;
2420
use function is_array;
25-
use function is_dir;
26-
use function iterator_to_array;
2721
use function ksort;
2822

2923
final class SquashedMigrationHelper
@@ -47,7 +41,7 @@ public function parseSchemaDumps(ModelDatabaseHelper &$modelDatabaseHelper): voi
4741
$this->schemaPaths = [database_path('schema')];
4842
}
4943

50-
$filesArray = $this->getSchemaFiles();
44+
$filesArray = $this->fileHelper->getFiles($this->schemaPaths, '/\.dump|\.sql/i');
5145

5246
if (empty($filesArray)) {
5347
return;
@@ -105,30 +99,6 @@ public function parseSchemaDumps(ModelDatabaseHelper &$modelDatabaseHelper): voi
10599
}
106100
}
107101

108-
/** @return SplFileInfo[] */
109-
private function getSchemaFiles(): array
110-
{
111-
/** @var SplFileInfo[] $schemaFiles */
112-
$schemaFiles = [];
113-
114-
foreach ($this->schemaPaths as $additionalPath) {
115-
$absolutePath = $this->fileHelper->absolutizePath($additionalPath);
116-
117-
if (! is_dir($absolutePath)) {
118-
continue;
119-
}
120-
121-
$schemaFiles += iterator_to_array(
122-
new RegexIterator(
123-
new RecursiveIteratorIterator(new RecursiveDirectoryIterator($absolutePath)),
124-
'/\.dump|\.sql/i',
125-
),
126-
);
127-
}
128-
129-
return $schemaFiles;
130-
}
131-
132102
private function isNullable(CreateDefinition $definition): bool
133103
{
134104
return ! $definition->options?->has('NOT NULL');

0 commit comments

Comments
 (0)