mirror of
https://github.com/pestphp/pest.git
synced 2026-06-05 10:52:14 +02:00
wip
This commit is contained in:
@ -9,18 +9,10 @@ namespace Pest\Plugins\Tia;
|
||||
*/
|
||||
final class TableExtractor
|
||||
{
|
||||
/**
|
||||
* DML prefixes we accept. DDL (`CREATE`, `ALTER`, `DROP`,
|
||||
* `TRUNCATE`, `RENAME`) is deliberately excluded — those come
|
||||
* from migrations fired by `RefreshDatabase`, and capturing them
|
||||
* here would attribute every migration table to every test.
|
||||
*/
|
||||
private const array DML_PREFIXES = ['select', 'insert', 'update', 'delete'];
|
||||
|
||||
/**
|
||||
* @return list<string> Sorted, deduped table names referenced by the
|
||||
* SQL statement. Empty when the statement is
|
||||
* DDL, empty, or unparseable.
|
||||
*/
|
||||
public static function fromSql(string $sql): array
|
||||
{
|
||||
@ -45,9 +37,6 @@ final class TableExtractor
|
||||
return [];
|
||||
}
|
||||
|
||||
// Match `from`, `into`, `update`, `join` and capture the
|
||||
// following identifier, tolerating the common quoting
|
||||
// styles: "double", `back`, [bracket], or bare.
|
||||
$pattern = '/(?:\bfrom|\binto|\bupdate|\bjoin)\s+(?:"([^"]+)"|`([^`]+)`|\[([^\]]+)\]|(\w+))/i';
|
||||
|
||||
if (preg_match_all($pattern, $sql, $matches) === false) {
|
||||
@ -82,35 +71,11 @@ final class TableExtractor
|
||||
|
||||
/**
|
||||
* @return list<string> Table names referenced by `Schema::` calls,
|
||||
* raw DDL, or DML inside the given migration
|
||||
* file contents. Empty when nothing matches —
|
||||
* callers treat that as "fall back to the
|
||||
* broad watch pattern".
|
||||
*
|
||||
* Three passes:
|
||||
* 1. `Schema::create|table|drop|dropIfExists|dropColumn[s]|rename`
|
||||
* captures the conventional Laravel migration shape.
|
||||
* 2. Raw DDL fallback: scans for `CREATE / ALTER / DROP /
|
||||
* TRUNCATE / RENAME TABLE <name>` patterns inside string
|
||||
* literals (i.e. `DB::statement('CREATE TABLE …')`,
|
||||
* `DB::unprepared('ALTER TABLE …')`).
|
||||
* 3. DML inside migration bodies — `INSERT INTO`, `UPDATE … SET`,
|
||||
* `DELETE FROM`, and Laravel's fluent `DB::table('foo')`.
|
||||
* Catches the seeded-lookup-table case where a migration
|
||||
* populates rows that tests later read.
|
||||
*
|
||||
* False positives possible when the same syntax appears in a
|
||||
* comment or unrelated string, but over-attribution is
|
||||
* correctness-safe.
|
||||
*/
|
||||
public static function fromMigrationSource(string $php): array
|
||||
{
|
||||
$tables = [];
|
||||
|
||||
// Pass 1: Schema:: calls. `dropColumn` (singular) covers
|
||||
// `Schema::table('users', fn ($t) => $t->dropColumn('foo'))`
|
||||
// — the closure body's column op is on Blueprint, but the
|
||||
// outer `Schema::table('users', …)` is what we capture here.
|
||||
$schemaPattern = '/Schema::\s*(?:create|table|drop|dropIfExists|dropColumn|dropColumns|rename)\s*\(\s*[\'"]([^\'"]+)[\'"](?:\s*,\s*[\'"]([^\'"]+)[\'"])?/';
|
||||
|
||||
if (preg_match_all($schemaPattern, $php, $matches) !== false) {
|
||||
@ -124,10 +89,6 @@ final class TableExtractor
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 2: raw DDL fallback. Matches the table name following
|
||||
// `CREATE/ALTER/DROP/TRUNCATE/RENAME TABLE` (plus Postgres'
|
||||
// `IF EXISTS` / `IF NOT EXISTS` variants), with optional
|
||||
// ANSI / MySQL / SQL Server quoting.
|
||||
$ddlPattern = '/(?:CREATE|ALTER|DROP|TRUNCATE|RENAME)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?\s+["`\[]?(\w+)["`\]]?/i';
|
||||
|
||||
if (preg_match_all($ddlPattern, $php, $matches) !== false) {
|
||||
@ -139,14 +100,6 @@ final class TableExtractor
|
||||
}
|
||||
}
|
||||
|
||||
// Pass 3: DML inside migration bodies. Migrations that seed
|
||||
// lookup tables via `DB::statement('INSERT INTO roles …')`,
|
||||
// `DB::table('statuses')->insert(…)`, `UPDATE foo SET …`, or
|
||||
// `DELETE FROM bar` are common in Laravel. Without picking
|
||||
// these up, an edit to the seed payload would route through
|
||||
// only the schema'd tables and silently skip every test that
|
||||
// reads from the populated table. Fluent-builder calls
|
||||
// (`DB::table('x')`) and raw SQL strings are both covered.
|
||||
$dmlPatterns = [
|
||||
'/INSERT\s+(?:IGNORE\s+)?INTO\s+["`\[]?(\w+)["`\]]?/i',
|
||||
'/UPDATE\s+["`\[]?(\w+)["`\]]?\s+SET\b/i',
|
||||
@ -172,11 +125,6 @@ final class TableExtractor
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters out driver-internal tables that show up as DB::listen
|
||||
* targets without representing user schema: SQLite's master
|
||||
* catalogue, Laravel's own `migrations` metadata.
|
||||
*/
|
||||
private static function isSchemaMeta(string $name): bool
|
||||
{
|
||||
$lower = strtolower($name);
|
||||
|
||||
Reference in New Issue
Block a user