Skip to content

Instantly share code, notes, and snippets.

@mberizzo
Last active October 4, 2019 14:19
Show Gist options
  • Save mberizzo/013f49d89b96049c5e8c73284efdb071 to your computer and use it in GitHub Desktop.
Save mberizzo/013f49d89b96049c5e8c73284efdb071 to your computer and use it in GitHub Desktop.
<?php
namespace Tests;
use Illuminate\Contracts\Console\Kernel;
/**
* Original source: https://gist.github.com/mberizzo/013f49d89b96049c5e8c73284efdb071
*
*/
trait DatabaseSetup
{
protected static $migrated = false;
public function setupDatabase()
{
if ($this->isInMemory()) {
$this->setupInMemoryDatabase();
} else {
$this->setupTestDatabase();
}
}
protected function isInMemory()
{
return config('database.connections')[config('database.default')]['database'] == ':memory:';
}
protected function setupInMemoryDatabase()
{
$this->artisan('migrate');
$this->app[Kernel::class]->setArtisan(null);
}
protected function setupTestDatabase()
{
if (!static::$migrated) {
$this->whenMigrationsChange(function($command) {
$this->artisan($command);
$this->app[Kernel::class]->setArtisan(null);
});
static::$migrated = true;
}
$this->beginDatabaseTransaction();
}
public function beginDatabaseTransaction()
{
$database = $this->app->make('db');
foreach ($this->connectionsToTransact() as $name) {
$database->connection($name)->beginTransaction();
}
$this->beforeApplicationDestroyed(function () use ($database) {
foreach ($this->connectionsToTransact() as $name) {
$database->connection($name)->rollBack();
}
});
}
protected function connectionsToTransact()
{
return property_exists($this, 'connectionsToTransact')
? $this->connectionsToTransact : [null];
}
protected function whenMigrationsChange($callback)
{
$dbTracker = new DatabaseMigrationsTracker;
if ($dbTracker->dbNameOrMigrationsWereChanged()) {
$cmd = $dbTracker->getMigrationCommand();
$callback($cmd);
$dbTracker->updateContentFiles();
}
}
}
/**
* Track migrations and database name changes
* in 2 files stored in 'storage/app/*'
*
*/
class DatabaseMigrationsTracker
{
protected $storedMigration;
protected $currentMigration;
protected $storedDbName;
protected $currentDbName;
protected $migrationCommand = 'migrate';
protected $filesPath = [
'migrations' => 'app/testing_migrations.txt',
'db_name' => 'app/testing_database_name.txt',
];
public function __construct()
{
$this->readFilesContent();
}
protected function readFilesContent()
{
$this->storedMigration = $this->getStoredMigrationStr();
$this->currentMigration = $this->getCurrentMigrationStr();
$this->storedDbName = $this->getStoredDbName();
$this->currentDbName = env('DB_DATABASE');
}
protected function getStoredMigrationStr()
{
$path = storage_path($this->filesPath['migrations']);
if (file_exists($path)) {
return file_get_contents($path);
}
return '';
}
protected function getCurrentMigrationStr()
{
return md5(collect(glob(base_path('database/migrations/*')))
->map(function ($f) {
return file_get_contents($f);
})->implode(''));
}
protected function getStoredDbName()
{
$path = storage_path($this->filesPath['db_name']);
if (file_exists($path)) {
return file_get_contents($path);
}
return '';
}
public function migrationWasChanged()
{
if ($this->storedMigration !== $this->currentMigration) {
return true;
}
return false;
}
public function dbNameWasChanged()
{
if ($this->storedDbName !== $this->currentDbName) {
$this->migrationCommand = 'migrate:fresh';
return true;
}
return false;
}
public function dbNameOrMigrationsWereChanged()
{
if ($this->migrationWasChanged() || $this->dbNameWasChanged()) {
return true;
}
return false;
}
public function getMigrationCommand()
{
return $this->migrationCommand;
}
public function updateContentFiles()
{
file_put_contents(
storage_path($this->filesPath['migrations']),
$this->currentMigration
);
file_put_contents(
storage_path($this->filesPath['db_name']),
$this->currentDbName
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment