From a5892e044835df0e9c67a9e17d002d4f455b7b02 Mon Sep 17 00:00:00 2001 From: inmanturbo <47095624+inmanturbo@users.noreply.github.com> Date: Sun, 4 Feb 2024 02:13:37 -0500 Subject: [PATCH 1/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecd5781..ab4f115 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ Schema::connection('mysql')->emptyTrash(); > [!IMPORTANT] > Tests use [spatie/docker](https://github.com/spatie/docker) for testing against various database servers. -> Docker is required for running tests! +> Docker is required for running tests locally! ```bash composer test From 2925fc4fd16ba601b1a2d79e86a51f2e5aae0310 Mon Sep 17 00:00:00 2001 From: inmanturbo <47095624+inmanturbo@users.noreply.github.com> Date: Sun, 4 Feb 2024 02:23:34 -0500 Subject: [PATCH 2/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ab4f115..5634102 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,7 @@ Schema::connection('mariadb')->trashDatabase('schema_demo'); The `emptyTrash()` method will erase all `trashed` databases from disk which are reachable from the current connection: > [!TIP] -> To only permanently erase databases trahed later than a given age and keep those which are newer, +> To only permanently erase databases trashed later than a given age and keep those which are newer, > you may pass the maximum age in days for the databases you want to keep. ```php From b1e954f7aad2791f07745eb47d31c73f0e50bafa Mon Sep 17 00:00:00 2001 From: = Date: Sun, 4 Feb 2024 15:24:57 -0500 Subject: [PATCH 3/7] refactor to callable classes --- phpstan-baseline.neon | 80 ++---- .../MySql/MySqlCreateDatabaseIfNotExists.php | 31 +++ src/Macros/MySql/MySqlDatabaseExists.php | 27 ++ src/Macros/MySql/MySqlEmptyTrash.php | 49 ++++ src/Macros/MySql/MySqlTrashDatabase.php | 64 +++++ .../SQLiteCreateDatabaseIfNotExists.php | 44 +++ src/Macros/SQLite/SQLiteDatabaseExists.php | 27 ++ src/Macros/SQLite/SQLiteEmptyTrash.php | 44 +++ src/Macros/SQLite/SQLiteTrashDatabase.php | 46 ++++ src/SchemaMacros.php | 8 + src/SchemaMacrosServiceProvider.php | 257 ++++++------------ tests/MariadbMacrosTest.php | 72 +++++ tests/MysqlMacrosTest.php | 11 +- tests/SqliteMacrosTest.php | 8 +- 14 files changed, 519 insertions(+), 249 deletions(-) create mode 100644 src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php create mode 100644 src/Macros/MySql/MySqlDatabaseExists.php create mode 100644 src/Macros/MySql/MySqlEmptyTrash.php create mode 100644 src/Macros/MySql/MySqlTrashDatabase.php create mode 100644 src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php create mode 100644 src/Macros/SQLite/SQLiteDatabaseExists.php create mode 100644 src/Macros/SQLite/SQLiteEmptyTrash.php create mode 100644 src/Macros/SQLite/SQLiteTrashDatabase.php create mode 100644 src/SchemaMacros.php create mode 100644 tests/MariadbMacrosTest.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 4269e1b..5b616ee 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,96 +1,56 @@ parameters: ignoreErrors: - - message: "#^Call to method createDatabase\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" - count: 2 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Call to method createDatabaseIfNotExists\\(\\) on an unknown class Illuminate\\\\Database\\\\SQLiteBuilder\\.$#" + message: "#^Call to an undefined method Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder\\:\\:mysqlDatabaseExists\\(\\)\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Call to method dropDatabaseIfExists\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" - count: 3 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php - message: "#^Call to method getConnection\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" - count: 3 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Call to method getTableListing\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" - count: 1 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Call to method mysqlDatabaseExists\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" - count: 2 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Call to method setConnection\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Instanceof between \\$this\\(Envor\\\\SchemaMacros\\\\SchemaMacrosServiceProvider\\) and Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder will always evaluate to false\\.$#" - count: 4 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^Instanceof between \\$this\\(Envor\\\\SchemaMacros\\\\SchemaMacrosServiceProvider\\) and Illuminate\\\\Database\\\\Schema\\\\SQLiteBuilder will always evaluate to false\\.$#" - count: 3 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/MySql/MySqlDatabaseExists.php - message: "#^PHPDoc tag @var for variable \\$this contains unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" - count: 4 - path: src/SchemaMacrosServiceProvider.php - - - - message: "#^PHPDoc tag @var for variable \\$this contains unknown class Illuminate\\\\Database\\\\SQLiteBuilder\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/MySql/MySqlDatabaseExists.php - - message: "#^Parameter \\#1 \\$format of method Carbon\\\\Carbon\\:\\:format\\(\\) expects string, mixed given\\.$#" + message: "#^Cannot cast mixed to string\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/MySql/MySqlEmptyTrash.php - - message: "#^Parameter \\#1 \\$format of static method Carbon\\\\Carbon\\:\\:createFromFormat\\(\\) expects string, mixed given\\.$#" + message: "#^Call to an undefined method Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder\\:\\:mysqlDatabaseExists\\(\\)\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/MySql/MySqlTrashDatabase.php - - message: "#^Parameter \\#1 \\$object of function get_object_vars expects object, mixed given\\.$#" + message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, mixed given\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/MySql/MySqlTrashDatabase.php - - message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, mixed given\\.$#" + message: "#^Negated boolean expression is always true\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php - - message: "#^Parameter \\#2 \\$string of function explode expects string, mixed given\\.$#" + message: "#^Unreachable statement \\- code above always terminates\\.$#" count: 1 - path: src/SchemaMacrosServiceProvider.php + path: src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php - - message: "#^Unable to resolve the template type TKey in call to function collect$#" - count: 1 + message: "#^Instanceof between \\$this\\(Envor\\\\SchemaMacros\\\\SchemaMacrosServiceProvider\\) and Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder will always evaluate to false\\.$#" + count: 4 path: src/SchemaMacrosServiceProvider.php - - message: "#^Unable to resolve the template type TValue in call to function collect$#" - count: 1 + message: "#^Instanceof between \\$this\\(Envor\\\\SchemaMacros\\\\SchemaMacrosServiceProvider\\) and Illuminate\\\\Database\\\\Schema\\\\SQLiteBuilder will always evaluate to false\\.$#" + count: 4 path: src/SchemaMacrosServiceProvider.php - - message: "#^Unreachable statement \\- code above always terminates\\.$#" - count: 4 + message: "#^Trying to invoke mixed but it's not a callable\\.$#" + count: 2 path: src/SchemaMacrosServiceProvider.php diff --git a/src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php b/src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php new file mode 100644 index 0000000..e9b77b5 --- /dev/null +++ b/src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php @@ -0,0 +1,31 @@ +mysqlDatabaseExists($database)) { + return false; + } + + return $this->createDatabase($database); + }; + } +} diff --git a/src/Macros/MySql/MySqlDatabaseExists.php b/src/Macros/MySql/MySqlDatabaseExists.php new file mode 100644 index 0000000..541c8db --- /dev/null +++ b/src/Macros/MySql/MySqlDatabaseExists.php @@ -0,0 +1,27 @@ +getConnection()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '{$database}'"); + }; + } +} diff --git a/src/Macros/MySql/MySqlEmptyTrash.php b/src/Macros/MySql/MySqlEmptyTrash.php new file mode 100644 index 0000000..caedf82 --- /dev/null +++ b/src/Macros/MySql/MySqlEmptyTrash.php @@ -0,0 +1,49 @@ +getConnection()->select("SHOW DATABASES LIKE 'trashed_%'")) + ->map(fn ($database) => array_values(get_object_vars($database))[0]); + + $deleted = 0; + + foreach ($trashDatabases as $trashDatabase) { + $trashDatabase = (string) $trashDatabase; + + if ($daysOld > 0) { + $dateSlice = array_slice(explode('_', $trashDatabase), 1, 6); + $dateString = implode('_', $dateSlice); + $date = Carbon::createFromFormat(SchemaMacros::TRASH_DATE_FORMAT, $dateString)->getTimestamp(); + + if ($date > now()->subDays($daysOld)->getTimestamp()) { + continue; + } + } + + if ($this->dropDatabaseIfExists($trashDatabase)) { + $deleted++; + } + } + + return $deleted; + }; + } +} diff --git a/src/Macros/MySql/MySqlTrashDatabase.php b/src/Macros/MySql/MySqlTrashDatabase.php new file mode 100644 index 0000000..1d6f2d7 --- /dev/null +++ b/src/Macros/MySql/MySqlTrashDatabase.php @@ -0,0 +1,64 @@ +mysqlDatabaseExists($database)) { + return false; + } + + try { + + $trashedAt = now()->format(SchemaMacros::TRASH_DATE_FORMAT); + $trashedDatabase = "trashed_{$trashedAt}_{$database}"; + $this->dropDatabaseIfExists($trashedDatabase); + $this->createDatabase($trashedDatabase); + + $currentConnection = $this->getConnection(); + $currentConnectionName = $currentConnection->getName(); + + config(['database.connections.new_connection_for_database' => array_merge(config("database.connections.{$currentConnectionName}"), [ + 'database' => $database, + ])]); + + $db = DB::connection('new_connection_for_database'); + + $db->statement("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';"); + + $tables = $this->getTableListing(); + + foreach ($tables as $table) { + $db->statement("create table if not exists `{$trashedDatabase}`.`{$table}` like `{$database}`.`{$table}`;"); + $db->statement("insert into `{$trashedDatabase}`.`{$table}` select * from `{$database}`.`{$table}`;"); + } + + $this->dropDatabaseIfExists($database); + $this->setConnection($currentConnection); + + return $trashedDatabase; + } catch (\Exception $e) { + return false; + } + }; + } +} diff --git a/src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php b/src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php new file mode 100644 index 0000000..0fbf8bf --- /dev/null +++ b/src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php @@ -0,0 +1,44 @@ +createDatabase($database); + } + + return false; + }; + } +} diff --git a/src/Macros/SQLite/SQLiteDatabaseExists.php b/src/Macros/SQLite/SQLiteDatabaseExists.php new file mode 100644 index 0000000..983228b --- /dev/null +++ b/src/Macros/SQLite/SQLiteDatabaseExists.php @@ -0,0 +1,27 @@ +path('.trash'); + + if (! File::isDirectory($trashPath)) { + return false; + } + + $files = File::files($trashPath); + + $deleted = 0; + + collect($files)->each(function ($file) use ($daysOld, &$deleted) { + if ($daysOld > 0 && File::lastModified($file) > now()->subDays($daysOld)->getTimestamp()) { + return; + } + + $deleted += File::delete($file); + }); + + return $deleted; + }; + } +} diff --git a/src/Macros/SQLite/SQLiteTrashDatabase.php b/src/Macros/SQLite/SQLiteTrashDatabase.php new file mode 100644 index 0000000..2ed59fa --- /dev/null +++ b/src/Macros/SQLite/SQLiteTrashDatabase.php @@ -0,0 +1,46 @@ +path('.trash'); + + if (! File::isDirectory($trashPath)) { + File::makeDirectory($trashPath, 0755, true); + } + + $trashFile = $trashPath.DIRECTORY_SEPARATOR.now()->format(SchemaMacros::TRASH_DATE_FORMAT).'_'.basename($database); + + $moved = File::move($database, $trashFile); + + return $moved ? $trashFile : false; + }; + } +} diff --git a/src/SchemaMacros.php b/src/SchemaMacros.php new file mode 100644 index 0000000..6785e43 --- /dev/null +++ b/src/SchemaMacros.php @@ -0,0 +1,8 @@ +bootMysqlMacros(); - $this->bootSQLiteMacros(); - } - - protected function bootMysqlMacros(): void - { - MySqlBuilder::macro('mysqlDatabaseExists', function (string|Stringable $database): bool { - /** @var \Illuminate\Database\MySqlBuilder $this */ - return (bool) $this->getConnection()->select("SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '{$database}'"); - }); - - MySqlBuilder::macro('mysqlCreateDatabaseIfNotExists', function (string|Stringable $database): bool { - /** @var \Illuminate\Database\MySqlBuilder $this */ - if ($this->mysqlDatabaseExists($database)) { - return false; - } - - return $this->createDatabase($database); - }); - - MySqlBuilder::macro('mysqlTrashDatabase', function (string|Stringable $database) { - $database = (string) $database; + Collection::make($this->sqliteBuilderMacros()) + ->reject(fn ($class, $macro) => Builder::hasMacro($macro)) + ->each(fn ($class, $macro) => Builder::macro($macro, app($class)())); - /** @var \Illuminate\Database\MySqlBuilder $this */ - if (! $this->mysqlDatabaseExists($database)) { - return false; - } + Collection::make($this->mysqlBuilderMacros()) + ->reject(fn ($class, $macro) => Builder::hasMacro($macro)) + ->each(fn ($class, $macro) => Builder::macro($macro, app($class)())); - try { - - $trashedAt = now()->format(config('schema-macros.trash-time-format')); - $trashedDatabase = "trashed_{$trashedAt}_{$database}"; - $this->dropDatabaseIfExists($trashedDatabase); - $this->createDatabase($trashedDatabase); - - $currentConnection = $this->getConnection(); - $currentConnectionName = $currentConnection->getName(); - - config(['database.connections.new_connection_for_database' => array_merge(config("database.connections.{$currentConnectionName}"), [ - 'database' => $database, - ])]); - - $db = DB::connection('new_connection_for_database'); + Collection::make($this->builderMacros()) + ->reject(fn ($macro, $name) => Builder::hasMacro($name)) + ->each(fn ($macro, $name) => Builder::macro($name, $macro)); + } - $db->statement("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';"); + /** + * @return array + */ + private function builderMacros(): array + { + return [ + 'databaseExists' => function (string|Stringable $database) { + $database = (string) $database; - $tables = $this->getTableListing(); + if ($this instanceof MySqlBuilder) { + return $this->mysqlDatabaseExists($database); + } - foreach ($tables as $table) { - $db->statement("create table if not exists `{$trashedDatabase}`.`{$table}` like `{$database}`.`{$table}`;"); - $db->statement("insert into `{$trashedDatabase}`.`{$table}` select * from `{$database}`.`{$table}`;"); + if ($this instanceof SQLiteBuilder) { + return $this->sqliteDatabaseExists($database); } - $this->dropDatabaseIfExists($database); - $this->setConnection($currentConnection); + throw new \Exception('The databaseExists() macro does not support'.get_class($this)); + }, + 'createDatabaseIfNotExists' => function (string|Stringable $database, bool $recursive = true) { + $database = (string) $database; - return $trashedDatabase; - } catch (\Exception $e) { - return false; - } - }); + if ($this instanceof MySqlBuilder) { + return $this->mysqlCreateDatabaseIfNotExists($database); + } - MySqlBuilder::macro('mysqlEmptyTrash', function (int $daysOld = 0, $debug = false) { - /** @var \Illuminate\Database\MySqlBuilder $this */ - $trashDatabases = collect($this->getConnection()->select("SHOW DATABASES LIKE 'trashed_%'")) - ->map(fn ($database) => array_values(get_object_vars($database))[0]); + if ($this instanceof SQLiteBuilder) { + return $this->sqliteCreateDatabaseIfNotExists($database, $recursive); + } - $deleted = 0; + throw new \Exception('The createDatabaseIfNotExists() macro does not support'.get_class($this)); + }, + 'trashDatabase' => function (string|Stringable $database, string $trashDisk = 'local') { + $database = (string) $database; - foreach ($trashDatabases as $trashDatabase) { + if ($this instanceof MySqlBuilder) { + return $this->mysqlTrashDatabase($database); + } - if ($daysOld > 0) { - $dateSlice = array_slice(explode('_', $trashDatabase), 1, 6); - $dateString = implode('_', $dateSlice); - $date = Carbon::createFromFormat(config('schema-macros.trash-time-format'), $dateString)->getTimestamp(); + if ($this instanceof SQLiteBuilder) { + return $this->sqliteTrashDatabase($database, $trashDisk); + } - if ($date > now()->subDays($daysOld)->getTimestamp()) { - continue; - } + throw new \Exception('The trashDatabase() macro does not support'.get_class($this)); + }, + 'emptyTrash' => function (int $daysOld = 0, string $trashDisk = 'local') { + if ($this instanceof MySqlBuilder) { + return $this->mysqlEmptyTrash($daysOld); } - if ($this->dropDatabaseIfExists($trashDatabase)) { - $deleted++; + if ($this instanceof SQLiteBuilder) { + return $this->sqliteEmptyTrash($daysOld, $trashDisk); } - } - return $deleted; - }); + throw new \Exception('The emptyTrash() macro does not support'.get_class($this)); + }, + ]; } - protected function bootSQLiteMacros(): void + /** + * @return array + */ + private function sqliteBuilderMacros(): array { - SQLiteBuilder::macro('databaseExists', function (string|Stringable $database) { - if ($this instanceof MySqlBuilder) { - return $this->mysqlDatabaseExists($database); - } - - return File::exists($database); - }); - - SQLiteBuilder::macro('createDatabaseIfNotExists', function (string|Stringable $database, bool $recursive = true) { - if ($this instanceof MySqlBuilder) { - return $this->mysqlCreateDatabaseIfNotExists($database); - } - - if (! $this instanceof SQLiteBuilder) { - throw new \Exception('This macro is only available for SQLite and MySQL databases'); - } - - if (File::exists($database)) { - return false; - } - - $directory = dirname($database); - - if (! File::isDirectory($directory)) { - File::makeDirectory($directory, 0755, true); - } - - if (! File::exists($database)) { - - /** @var \Illuminate\Database\SQLiteBuilder $this */ - return $this->createDatabase($database); - } - - return true; - }); - - SQLiteBuilder::macro('createDatabaseIfNotExistsRecursive', function (string|Stringable $database) { - if (File::exists($database)) { - return false; - } - - /** @var \Illuminate\Database\SQLiteBuilder $this */ - return $this->createDatabaseIfNotExists($database, true); - - return true; - }); - - SQLiteBuilder::macro('trashDatabase', function (string|Stringable $database, string $trashDisk = 'local') { - if ($this instanceof MySqlBuilder) { - return $this->mysqlTrashDatabase($database); - } - - if (! $this instanceof SQLiteBuilder) { - throw new \Exception('This macro is only available for SQLite and MySQL databases'); - } - - if (! File::exists($database) - || ! File::isFile($database) - || ! File::isWritable($database) - ) { - return false; - } - - $trashPath = Storage::disk($trashDisk)->path('.trash'); - - if (! File::isDirectory($trashPath)) { - File::makeDirectory($trashPath, 0755, true); - } - - $trashFile = $trashPath.DIRECTORY_SEPARATOR.now()->format(config('schema-macros.trash-time-format')).'_'.basename($database); - - $moved = File::move($database, $trashFile); - - return $moved ? $trashFile : false; - }); - - SQLiteBuilder::macro('emptyTrash', function (int $daysOld = 0, string $trashDisk = 'local') { - if ($this instanceof MySqlBuilder) { - return $this->mysqlEmptyTrash($daysOld); - } - - if (! $this instanceof SQLiteBuilder) { - throw new \Exception('This macro is only available for SQLite and MySQL databases'); - } - - $trashPath = Storage::disk($trashDisk)->path('.trash'); - - if (! File::isDirectory($trashPath)) { - return false; - } - - $files = File::files($trashPath); - - $deleted = 0; - - collect($files)->each(function ($file) use ($daysOld, &$deleted) { - if ($daysOld > 0 && File::lastModified($file) > now()->subDays($daysOld)->getTimestamp()) { - return; - } - - $deleted += File::delete($file); - }); + return [ + 'sqliteDatabaseExists' => \Envor\SchemaMacros\Macros\SQLite\SQLiteDatabaseExists::class, + 'sqliteCreateDatabaseIfNotExists' => \Envor\SchemaMacros\Macros\SQLite\SQLiteCreateDatabaseIfNotExists::class, + 'sqliteTrashDatabase' => \Envor\SchemaMacros\Macros\SQLite\SQLiteTrashDatabase::class, + 'sqliteEmptyTrash' => \Envor\SchemaMacros\Macros\SQLite\SQLiteEmptyTrash::class, + ]; + } - return $deleted; - }); + /** + * @return array + */ + private function mysqlBuilderMacros(): array + { + return [ + 'mysqlDatabaseExists' => \Envor\SchemaMacros\Macros\MySql\MySqlDatabaseExists::class, + 'mysqlCreateDatabaseIfNotExists' => \Envor\SchemaMacros\Macros\MySql\MySqlCreateDatabaseIfNotExists::class, + 'mysqlTrashDatabase' => \Envor\SchemaMacros\Macros\MySql\MySqlTrashDatabase::class, + 'mysqlEmptyTrash' => \Envor\SchemaMacros\Macros\MySql\MySqlEmptyTrash::class, + ]; } } diff --git a/tests/MariadbMacrosTest.php b/tests/MariadbMacrosTest.php new file mode 100644 index 0000000..0d9b2ce --- /dev/null +++ b/tests/MariadbMacrosTest.php @@ -0,0 +1,72 @@ +fail('MySQL client is not installed'); + } + + if (! `which docker`) { + $this->fail('Docker is not installed'); + } + + $this->containerInstance = DockerContainer::create('mariadb:latest') + ->setEnvironmentVariable('MARIADB_ROOT_PASSWORD', 'root') + ->setEnvironmentVariable('MARIADB_DATABASE', 'mariadb_system') + ->name('mariadb_system') + ->mapPort(10001, 3306) + ->start(); + + $i = 0; + + while ($i < 50) { + $process = Process::run('mysql -u root -proot -P 10001 -h 127.0.0.1 mariadb_system -e "show tables;"'); + if ($process->successful()) { + break; + } + sleep(.5); + } + + config(['database.connections.mariadb_system' => array_merge(config('database.connections.mariadb', config('database.connections.mysql')), [ + 'database' => 'mariadb_system', + 'host' => '127.0.0.1', + 'port' => '10001', + 'username' => 'root', + 'password' => 'root', + ])]); + + $this->connection = 'mariadb_system'; +}); + +afterEach(function () { + $this->containerInstance->stop(); +}); + +it('can perform the macros on mariadb connection', function () { + + expect(DB::connection($this->connection)->getSchemaBuilder()->databaseExists('mariadb_system'))->toBeTrue(); + expect(DB::connection($this->connection)->getSchemaBuilder()->databaseExists('mariadb_system_not_exists'))->toBeFalse(); + + expect(DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('mariadb_system'))->toBeFalse(); + expect(DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('mariadb_system_not_exists'))->toBeTrue(); + + $trashedDatabase = DB::connection($this->connection)->getSchemaBuilder()->trashDatabase('mariadb_system'); + expect(DB::connection($this->connection)->getSchemaBuilder()->trashDatabase('does_not_exists'))->toBeFalse(); + + expect(DB::connection($this->connection)->select("SHOW DATABASES LIKE '{$trashedDatabase}'"))->toHaveCount(1); + expect(DB::connection($this->connection)->getSchemaBuilder()->databaseExists($trashedDatabase))->toBeTrue(); + + expect(DB::connection($this->connection)->getSchemaBuilder()->emptyTrash())->toBe(1); + + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(4)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(3)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(2)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(1)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->format(SchemaMacros::TRASH_DATE_FORMAT)); + + expect(DB::connection($this->connection)->getSchemaBuilder()->emptyTrash(2))->toBe(3); +}); diff --git a/tests/MysqlMacrosTest.php b/tests/MysqlMacrosTest.php index bc6ef8f..ee326bf 100644 --- a/tests/MysqlMacrosTest.php +++ b/tests/MysqlMacrosTest.php @@ -1,5 +1,6 @@ connection)->getSchemaBuilder()->emptyTrash())->toBe(1); - DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(4)->format(config('schema-macros.trash-time-format'))); - DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(3)->format(config('schema-macros.trash-time-format'))); - DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(2)->format(config('schema-macros.trash-time-format'))); - DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(1)->format(config('schema-macros.trash-time-format'))); - DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->format(config('schema-macros.trash-time-format'))); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(4)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(3)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(2)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->subDays(1)->format(SchemaMacros::TRASH_DATE_FORMAT)); + DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists('trashed_'.now()->format(SchemaMacros::TRASH_DATE_FORMAT)); expect(DB::connection($this->connection)->getSchemaBuilder()->emptyTrash(2))->toBe(3); }); diff --git a/tests/SqliteMacrosTest.php b/tests/SqliteMacrosTest.php index 76c8d4f..9a564b8 100644 --- a/tests/SqliteMacrosTest.php +++ b/tests/SqliteMacrosTest.php @@ -47,13 +47,13 @@ it('can create a sqlite database if it does not exist recursively', function () { $path = Storage::path('/path/to/database.sqlite'); - expect(DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExistsRecursive($path))->toBeTrue(); - expect(DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExistsRecursive($path))->toBeFalse(); + expect(DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists($path))->toBeTrue(); + expect(DB::connection($this->connection)->getSchemaBuilder()->createDatabaseIfNotExists($path))->toBeFalse(); Storage::fake('local'); - expect(Schema::connection($this->connection)->createDatabaseIfNotExistsRecursive($path))->toBeTrue(); - expect(Schema::connection($this->connection)->createDatabaseIfNotExistsRecursive($path))->toBeFalse(); + expect(Schema::connection($this->connection)->createDatabaseIfNotExists($path))->toBeTrue(); + expect(Schema::connection($this->connection)->createDatabaseIfNotExists($path))->toBeFalse(); }); it('can trash a sqlite database', function () { From c88ce8e58c04afdcf1d3a4a03dae67baeea5166f Mon Sep 17 00:00:00 2001 From: = Date: Sun, 4 Feb 2024 15:27:53 -0500 Subject: [PATCH 4/7] php8.2 --- src/SchemaMacros.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/SchemaMacros.php b/src/SchemaMacros.php index 6785e43..cc02314 100644 --- a/src/SchemaMacros.php +++ b/src/SchemaMacros.php @@ -4,5 +4,10 @@ class SchemaMacros { - public const string TRASH_DATE_FORMAT = 'Y-m-d_H-i-s'; + /** + * The date format used for the trash table + * + * @var string + */ + public const TRASH_DATE_FORMAT = 'Y-m-d_H-i-s'; } From 1ae6f969567f47302a0ad55c0f23733258890622 Mon Sep 17 00:00:00 2001 From: inmanturbo Date: Sun, 4 Feb 2024 20:28:15 +0000 Subject: [PATCH 5/7] Fix styling --- src/SchemaMacros.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SchemaMacros.php b/src/SchemaMacros.php index cc02314..9c53f43 100644 --- a/src/SchemaMacros.php +++ b/src/SchemaMacros.php @@ -6,7 +6,7 @@ class SchemaMacros { /** * The date format used for the trash table - * + * * @var string */ public const TRASH_DATE_FORMAT = 'Y-m-d_H-i-s'; From 651cccb92925ebac8bd55c2047a95145b9f8c5ef Mon Sep 17 00:00:00 2001 From: = Date: Sun, 4 Feb 2024 15:29:35 -0500 Subject: [PATCH 6/7] typo [skip-ci] --- src/SchemaMacros.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SchemaMacros.php b/src/SchemaMacros.php index cc02314..e17c598 100644 --- a/src/SchemaMacros.php +++ b/src/SchemaMacros.php @@ -5,7 +5,7 @@ class SchemaMacros { /** - * The date format used for the trash table + * The date format used for the trash * * @var string */ From 2780f5bf697123729bdda1da16d623c0a3f38832 Mon Sep 17 00:00:00 2001 From: = Date: Sun, 4 Feb 2024 15:36:08 -0500 Subject: [PATCH 7/7] remove unneeded namespace --- phpstan-baseline.neon | 16 ++++++++-------- .../MySql/MySqlCreateDatabaseIfNotExists.php | 2 +- src/{Macros => }/MySql/MySqlDatabaseExists.php | 2 +- src/{Macros => }/MySql/MySqlEmptyTrash.php | 2 +- src/{Macros => }/MySql/MySqlTrashDatabase.php | 2 +- .../SQLite/SQLiteCreateDatabaseIfNotExists.php | 2 +- src/{Macros => }/SQLite/SQLiteDatabaseExists.php | 2 +- src/{Macros => }/SQLite/SQLiteEmptyTrash.php | 2 +- src/{Macros => }/SQLite/SQLiteTrashDatabase.php | 2 +- src/SchemaMacrosServiceProvider.php | 16 ++++++++-------- 10 files changed, 24 insertions(+), 24 deletions(-) rename src/{Macros => }/MySql/MySqlCreateDatabaseIfNotExists.php (93%) rename src/{Macros => }/MySql/MySqlDatabaseExists.php (93%) rename src/{Macros => }/MySql/MySqlEmptyTrash.php (96%) rename src/{Macros => }/MySql/MySqlTrashDatabase.php (97%) rename src/{Macros => }/SQLite/SQLiteCreateDatabaseIfNotExists.php (95%) rename src/{Macros => }/SQLite/SQLiteDatabaseExists.php (91%) rename src/{Macros => }/SQLite/SQLiteEmptyTrash.php (95%) rename src/{Macros => }/SQLite/SQLiteTrashDatabase.php (96%) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 5b616ee..49b1e66 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -3,42 +3,42 @@ parameters: - message: "#^Call to an undefined method Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder\\:\\:mysqlDatabaseExists\\(\\)\\.$#" count: 1 - path: src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php + path: src/MySql/MySqlCreateDatabaseIfNotExists.php - message: "#^Call to method getConnection\\(\\) on an unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" count: 1 - path: src/Macros/MySql/MySqlDatabaseExists.php + path: src/MySql/MySqlDatabaseExists.php - message: "#^PHPDoc tag @var for variable \\$this contains unknown class Illuminate\\\\Database\\\\MySqlBuilder\\.$#" count: 1 - path: src/Macros/MySql/MySqlDatabaseExists.php + path: src/MySql/MySqlDatabaseExists.php - message: "#^Cannot cast mixed to string\\.$#" count: 1 - path: src/Macros/MySql/MySqlEmptyTrash.php + path: src/MySql/MySqlEmptyTrash.php - message: "#^Call to an undefined method Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder\\:\\:mysqlDatabaseExists\\(\\)\\.$#" count: 1 - path: src/Macros/MySql/MySqlTrashDatabase.php + path: src/MySql/MySqlTrashDatabase.php - message: "#^Parameter \\#1 \\.\\.\\.\\$arrays of function array_merge expects array, mixed given\\.$#" count: 1 - path: src/Macros/MySql/MySqlTrashDatabase.php + path: src/MySql/MySqlTrashDatabase.php - message: "#^Negated boolean expression is always true\\.$#" count: 1 - path: src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php + path: src/SQLite/SQLiteCreateDatabaseIfNotExists.php - message: "#^Unreachable statement \\- code above always terminates\\.$#" count: 1 - path: src/Macros/SQLite/SQLiteCreateDatabaseIfNotExists.php + path: src/SQLite/SQLiteCreateDatabaseIfNotExists.php - message: "#^Instanceof between \\$this\\(Envor\\\\SchemaMacros\\\\SchemaMacrosServiceProvider\\) and Illuminate\\\\Database\\\\Schema\\\\MySqlBuilder will always evaluate to false\\.$#" diff --git a/src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php b/src/MySql/MySqlCreateDatabaseIfNotExists.php similarity index 93% rename from src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php rename to src/MySql/MySqlCreateDatabaseIfNotExists.php index e9b77b5..672197f 100644 --- a/src/Macros/MySql/MySqlCreateDatabaseIfNotExists.php +++ b/src/MySql/MySqlCreateDatabaseIfNotExists.php @@ -1,6 +1,6 @@ \Envor\SchemaMacros\Macros\SQLite\SQLiteDatabaseExists::class, - 'sqliteCreateDatabaseIfNotExists' => \Envor\SchemaMacros\Macros\SQLite\SQLiteCreateDatabaseIfNotExists::class, - 'sqliteTrashDatabase' => \Envor\SchemaMacros\Macros\SQLite\SQLiteTrashDatabase::class, - 'sqliteEmptyTrash' => \Envor\SchemaMacros\Macros\SQLite\SQLiteEmptyTrash::class, + 'sqliteDatabaseExists' => \Envor\SchemaMacros\SQLite\SQLiteDatabaseExists::class, + 'sqliteCreateDatabaseIfNotExists' => \Envor\SchemaMacros\SQLite\SQLiteCreateDatabaseIfNotExists::class, + 'sqliteTrashDatabase' => \Envor\SchemaMacros\SQLite\SQLiteTrashDatabase::class, + 'sqliteEmptyTrash' => \Envor\SchemaMacros\SQLite\SQLiteEmptyTrash::class, ]; } @@ -117,10 +117,10 @@ private function sqliteBuilderMacros(): array private function mysqlBuilderMacros(): array { return [ - 'mysqlDatabaseExists' => \Envor\SchemaMacros\Macros\MySql\MySqlDatabaseExists::class, - 'mysqlCreateDatabaseIfNotExists' => \Envor\SchemaMacros\Macros\MySql\MySqlCreateDatabaseIfNotExists::class, - 'mysqlTrashDatabase' => \Envor\SchemaMacros\Macros\MySql\MySqlTrashDatabase::class, - 'mysqlEmptyTrash' => \Envor\SchemaMacros\Macros\MySql\MySqlEmptyTrash::class, + 'mysqlDatabaseExists' => \Envor\SchemaMacros\MySql\MySqlDatabaseExists::class, + 'mysqlCreateDatabaseIfNotExists' => \Envor\SchemaMacros\MySql\MySqlCreateDatabaseIfNotExists::class, + 'mysqlTrashDatabase' => \Envor\SchemaMacros\MySql\MySqlTrashDatabase::class, + 'mysqlEmptyTrash' => \Envor\SchemaMacros\MySql\MySqlEmptyTrash::class, ]; } }