-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDatabaseContextFactory.php
More file actions
95 lines (81 loc) · 3.04 KB
/
Copy pathDatabaseContextFactory.php
File metadata and controls
95 lines (81 loc) · 3.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<?php
declare(strict_types=1);
namespace Difflock\Database;
use Difflock\Contracts\SchemaInspector;
use Difflock\Migration\DatabaseContext;
use Difflock\Migration\Thresholds;
use Difflock\Schema\DatabaseSchema;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Database\Connection;
use Illuminate\Database\ConnectionResolverInterface;
use PDO;
use Throwable;
/**
* Assembles the one {@see DatabaseContext} every rule in a run shares.
*
* Built once per analysis and handed to every rule, so a hundred migrations against
* forty tables read the schema once and the size metadata once. Rules cannot reach
* the database themselves, which is what makes that guarantee hold.
*
* A database that cannot be reached is not an error here. Linting a migration in CI
* with no database attached is a legitimate thing to want, and it still catches
* every rule that reads only the source — the drop, the rename, the cascade. The
* context is simply marked unavailable, every size comes back unknown, and the
* report says so at the top rather than quietly grading on a curve.
*/
final class DatabaseContextFactory
{
private ?DatabaseContext $context = null;
public function __construct(
private readonly SchemaInspector $inspector,
private readonly ConnectionResolverInterface $connections,
private readonly Application $app,
private readonly Thresholds $thresholds,
private readonly ?string $connection = null,
) {}
public function make(): DatabaseContext
{
return $this->context ??= $this->build();
}
private function build(): DatabaseContext
{
try {
$schema = $this->inspector->inspect($this->connection);
} catch (Throwable) {
return new DatabaseContext(
schema: new DatabaseSchema,
statistics: new NullTableStatistics,
thresholds: $this->thresholds,
environment: $this->environment(),
available: false,
);
}
return new DatabaseContext(
schema: $schema,
statistics: new ConnectionTableStatistics($this->connections, $this->connection),
thresholds: $this->thresholds,
environment: $this->environment(),
version: $this->version(),
available: true,
indexes: new ConnectionIndexStatistics($this->connections, $this->connection),
);
}
private function environment(): string
{
$environment = $this->app->environment();
return is_string($environment) ? $environment : 'unknown';
}
private function version(): ?string
{
try {
$connection = $this->connections->connection($this->connection);
if (! $connection instanceof Connection) {
return null;
}
$version = $connection->getPdo()->getAttribute(PDO::ATTR_SERVER_VERSION);
} catch (Throwable) {
return null;
}
return is_scalar($version) ? (string) $version : null;
}
}