Skip to content

Commit

Permalink
chore: refactor migration component
Browse files Browse the repository at this point in the history
Reorder folder structure
Improve publish and register migration file

Signed-off-by: asciito <ayax.cordova@aydev.mx>
  • Loading branch information
asciito committed Oct 2, 2023
1 parent a7b6a48 commit 0019d46
Show file tree
Hide file tree
Showing 10 changed files with 239 additions and 85 deletions.
104 changes: 44 additions & 60 deletions src/Package/Concerns/HasMigrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,117 +2,101 @@

namespace Asciito\LaravelPackage\Package\Concerns;

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

trait HasMigrations
{
protected string $migrationsPath;

protected array $migrations = [];
protected string $migrationPath;

protected bool $preventLoadDefaultMigrationFolder = false;

protected bool $shouldIncludeMigrationsFromFolder = false;

protected array $excludedMigrations = [];

protected array $unpublishedMigrations = [];
protected bool $shouldIncludeMigrationFromFolder = false;

public function hasMigrations(): bool
{
return $this->shouldLoadDefaultMigrationsFolder() || filled($this->migrations);
return $this->shouldLoadDefaultMigrationFolder()
|| $this->getRegister('migrations')->isNotEmpty();
}

private function shouldLoadDefaultMigrationsFolder(): bool
public function withMigration(string|array $migration = [], bool $publish = true): static
{
return ! $this->preventLoadDefaultMigrationFolder && $this->shouldIncludeMigrationsFromFolder;
}
$this->ensureRegistersInitialize('migrations');

public function withMigrations(string|array $migration = [], bool $publish = true): static
{
if (filled($migration)) {
$this->migrations = collect($migration)
->map(fn (string $migration) => absolute($migration))
->filter()
->mapWithKeys(fn (string $value) => [$value => $publish])
->merge($this->migrations)
->all();
$this->register(
'migrations',
Arr::mapWithKeys(Arr::wrap($migration), fn (string $path): array => [$path => $publish])
);
}

$this->shouldIncludeMigrationsFromFolder = true;
$this->shouldIncludeMigrationFromFolder = true;

return $this;
}

public function preventDefaultMigrations(): static
public function excludeMigration(string|array $path): static
{
$this->preventLoadDefaultMigrationFolder = true;
$this->exclude('migrations', Arr::wrap($path));

return $this;
}

public function getRegisteredMigrations(): Collection
public function getRegisteredMigration(): Collection
{
$migrations = $this->loadMigrationsDefaultFolder();
$files = $this->getDefaultMigrationFiles();

return collect($this->migrations)
->merge($migrations)
->filter(function (bool $_, string $migration) {
return ! in_array($migration, $this->excludedMigrations);
})
return $files
->merge($this->getRegister('migrations'))
->except($this->getExclude('migrations'))
->keys();
}

private function loadMigrationsDefaultFolder(): array
{
if (! $this->shouldLoadDefaultMigrationsFolder()) {
return [];
}

return $this->loadFilesFrom($this->getMigrationPath())->all();
public function getPublishableMigration(): Collection
{
$files = $this->getDefaultMigrationFiles();

return $files
->merge($this->getRegister('migrations'))
->filter()
->except($this->getExclude('migrations'))
->mapWithKeys(fn (bool $_, string $path) => [
$path => database_path('migrations/'.basename($path))
]);
}

public function getMigrationPath(string $path = ''): string
{
return join_paths($this->migrationsPath, $path);
return join_paths($this->migrationPath, $path);
}

public function getPublishableMigrations(): Collection
public function setMigrationPath(string $path): static
{
$migrations = $this->loadMigrationsDefaultFolder();
$this->migrationPath = rtrim($path, DIRECTORY_SEPARATOR);

return collect($this->migrations)
->merge($migrations)
->filter(function (bool $publish, string $migration) {
return $publish && ! in_array($migration, [...$this->excludedMigrations, ...$this->unpublishedMigrations]);
})
->keys();
return $this;
}

public function setMigrationPath(string $path): static
public function getDefaultMigrationFiles(): Collection
{
$this->migrationsPath = rtrim($path, DIRECTORY_SEPARATOR);
if (! $this->shouldLoadDefaultMigrationFolder()) {
return collect();
}

return $this;
return $this->getFilesFrom($this->migrationPath)
->mapWithKeys(fn (string $path) => [$path => true]);
}

/**
* Un-register a previously registered migration
*/
public function unregisterMigration(string $path): static
public function preventDefaultMigration(): static
{
$this->excludedMigrations[] = absolute($path, $this->getMigrationPath());
$this->preventLoadDefaultMigrationFolder = true;

return $this;
}

/**
* Un-publish a previously published migration
*/
public function unpublishMigration(string $path): static
private function shouldLoadDefaultMigrationFolder(): bool
{
$this->unpublishedMigrations[] = absolute($path, $this->getMigrationPath());

return $this;
return ! $this->preventLoadDefaultMigrationFolder && $this->shouldIncludeMigrationFromFolder;
}
}
29 changes: 15 additions & 14 deletions src/Package/Contracts/WithMigrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,48 @@ public function hasMigrations(): bool;
* By calling this method this will try to load your migration
* file(s) from the default migration folder of your package.
*
* @param string|string[] $migration The file(s) you want to register
* @param bool $publish if the file(s) should be publishable, by default is true
*/
public function withMigrations(string|array $migration = [], bool $publish = true): static;
public function withMigration(string|array $migration = [], bool $publish = true): static;

/**
* Prevent publishing the default migrations
*
* Calling this method ensures that the migrations in the default folder
* wouldn't be loaded automatically.
* Exclude a migration from being register
*/
public function preventDefaultMigrations(): static;
public function excludeMigration(string|array $path): static;

/**
* An array with the migration file(s) registered
*
* @return Collection The migration file(s) registered in the package
*/
public function getRegisteredMigrations(): Collection;
public function getRegisteredMigration(): Collection;

/**
* Get the array with the publishable migration file(s)
*/
public function getPublishableMigrations(): Collection;
public function getPublishableMigration(): Collection;

/**
* Set the path to the migrations folder
* Set the path to the migration folder
*/
public function setMigrationPath(string $path): static;

/**
* Get the path to the migrations folder
* Get the path to the migration folder
*/
public function getMigrationPath(string $path = ''): string;

/**
* Un-register a previously registered migration
* Get the files from the migration path
*/
public function unregisterMigration(string $path): static;
public function getDefaultMigrationFiles(): Collection;

/**
* Un-publish a previously published migration
* Prevent publishing the default migration folder
*
* Calling this method ensures that the migration files in the default folder
* wouldn't be loaded automatically.
*/
public function unpublishMigration(string $path): static;
public function preventDefaultMigration(): static;
}
10 changes: 10 additions & 0 deletions src/Package/Package.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
use Asciito\LaravelPackage\Package\Contracts\WithMigrations;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Symfony\Component\Finder\SplFileInfo;

class Package implements WithCommands, WithConfig, WithMigrations
Expand Down Expand Up @@ -167,4 +169,12 @@ public function getFilesFrom(string $path): Collection
->filter(fn (SplFileInfo $file) => $file->getExtension() === 'php')
->map(fn (SplFileInfo $file): string => $file);
}
public function makeMigrationName(string $migration): string
{
if (Str::isMatch('/\d{4}_\d{2}_\d{2}_\d{6}/', $migration)) {
return $migration;
}

return Carbon::now()->format('Y_m_d_His_').trim($migration, '_');
}
}
10 changes: 2 additions & 8 deletions src/Package/PackageServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,11 @@ protected function publishesMigrations(Package $package): void
{
if ($package->hasMigrations()) {
$this->publishes(
$package->getPublishableMigrations()
->mapWithKeys(function (string $migration) {
$databaseMigration = database_path('migrations/'.basename($migration));

return [$migration => $databaseMigration];
})
->all(),
$package->getPublishableMigration()->all(),
$package->prefixWithPackageName('migrations')
);

$this->loadMigrationsFrom($package->getRegisteredMigrations()->all());
$this->loadMigrationsFrom($package->getRegisteredMigration()->all());
}
}

Expand Down
76 changes: 76 additions & 0 deletions tests/Feature/Migration/PackageRegisterMigrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

use Asciito\LaravelPackage\Package\Package;
use function Pest\Laravel\artisan;
use function Pest\Laravel\assertDatabaseCount;

trait PackageRegisterMigrationTest
{
protected function configurePackage(Package $package): void
{
$package
->setName('package')
->withMigration($package->getMigrationPath('extra/create_package_test_three_table.php'))
->withMigration([$package->getMigrationPath('extra/create_package_test_four_table.php')]);
}
}

uses(PackageRegisterMigrationTest::class);

test('package has registered files from folder', function () {
expect($this->package)
->getPublishableMigration()
->toHaveCount(4)
->getRegisteredMigration()
->toHaveCount(4);
});

test('package register migration files without publishing it', function () {
expect(database_path('migrations/create_package_test_one_table.php'))
->not->toBeFile()
->and(database_path('migrations/create_package_test_two_table.php'))
->not->toBeFile()
->and(database_path('migrations/create_package_test_three_table.php'))
->not->toBeFile()
->and(database_path('migrations/create_package_test_four_table.php'))
->not->toBeFile();

artisan('migrate')
->assertSuccessful();

assertDatabaseCount('package_test_one', 0);
assertDatabaseCount('package_test_two', 0);
assertDatabaseCount('package_test_three', 0);
assertDatabaseCount('package_test_four', 0);
});

it('publish package migration files', function () {
expect(database_path('migrations/create_package_test_one_table.php'))
->not->toBeFile()
->and(database_path('migrations/create_package_test_two_table.php'))
->not->toBeFile()
->and(database_path('migrations/create_package_test_three_table.php'))
->not->toBeFile()
->and(database_path('migrations/create_package_test_four_table.php'))
->not->toBeFile();

artisan('vendor:publish', ['--tag' => 'package-migrations']);

expect(database_path('migrations/create_package_test_one_table.php'))
->toBeFile()
->and(database_path('migrations/create_package_test_two_table.php'))
->toBeFile()
->and(database_path('migrations/create_package_test_three_table.php'))
->toBeFile()
->and(database_path('migrations/create_package_test_four_table.php'))
->toBeFile();

artisan('migrate');

assertDatabaseCount('package_test_one', 0);
assertDatabaseCount('package_test_two', 0);
assertDatabaseCount('package_test_three', 0);
assertDatabaseCount('package_test_four', 0);
});


Loading

0 comments on commit 0019d46

Please sign in to comment.