engelsystem/src/Database/Migration/Migrate.php

193 lines
4.4 KiB
PHP

<?php
namespace Engelsystem\Database\Migration;
use Engelsystem\Application;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder as SchemaBuilder;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
class Migrate
{
const UP = 'up';
const DOWN = 'down';
/** @var Application */
protected $app;
/** @var SchemaBuilder */
protected $schema;
/** @var callable */
protected $output;
/** @var string */
protected $table = 'migrations';
/**
* Migrate constructor
*
* @param SchemaBuilder $schema
* @param Application $app
*/
public function __construct(SchemaBuilder $schema, Application $app)
{
$this->app = $app;
$this->schema = $schema;
$this->output = function () { };
}
/**
* Run a migration
*
* @param string $path
* @param string $type (up|down)
* @param bool $oneStep
*/
public function run($path, $type = self::UP, $oneStep = false)
{
$this->initMigration();
$migrations = $this->getMigrations($path);
$migrated = $this->getMigrated();
if ($type == self::DOWN) {
$migrations = array_reverse($migrations, true);
}
foreach ($migrations as $file => $migration) {
if (
($type == self::UP && $migrated->contains('migration', $migration))
|| ($type == self::DOWN && !$migrated->contains('migration', $migration))
) {
call_user_func($this->output, 'Skipping ' . $migration);
continue;
}
call_user_func($this->output, 'Migrating ' . $migration . ' (' . $type . ')');
$this->migrate($file, $migration, $type);
$this->setMigrated($migration, $type);
if ($oneStep) {
return;
}
}
}
/**
* Get all migrated migrations
*
* @return Collection
*/
protected function getMigrated()
{
return $this->getTableQuery()->get();
}
/**
* Migrate a migration
*
* @param string $file
* @param string $migration
* @param string $type (up|down)
*/
protected function migrate($file, $migration, $type = self::UP)
{
require_once $file;
$className = Str::studly(preg_replace('/\d+_/', '', $migration));
/** @var Migration $class */
$class = $this->app->make($className);
if (method_exists($class, $type)) {
$class->{$type}();
}
}
/**
* Set a migration to migrated
*
* @param string $migration
* @param string $type (up|down)
*/
protected function setMigrated($migration, $type = self::UP)
{
$table = $this->getTableQuery();
if ($type == self::DOWN) {
$table->where(['migration' => $migration])->delete();
return;
}
$table->insert(['migration' => $migration]);
}
/**
* Get a list of migration files
*
* @param string $dir
* @return array
*/
protected function getMigrations($dir)
{
$files = $this->getMigrationFiles($dir);
$migrations = [];
foreach ($files as $dir) {
$name = str_replace('.php', '', basename($dir));
$migrations[$dir] = $name;
}
asort($migrations);
return $migrations;
}
/**
* List all migration files from the given directory
*
* @param string $dir
* @return array
*/
protected function getMigrationFiles($dir)
{
return glob($dir . '/*_*.php');
}
/**
* Setup migration tables
*/
protected function initMigration()
{
if ($this->schema->hasTable($this->table)) {
return;
}
$this->schema->create($this->table, function (Blueprint $table) {
$table->increments('id');
$table->string('migration');
});
}
/**
* Init a table query
*
* @return Builder
*/
protected function getTableQuery()
{
return $this->schema->getConnection()->table($this->table);
}
/**
* Set the output function
*
* @param callable $output
*/
public function setOutput(callable $output)
{
$this->output = $output;
}
}