2018-02-06 06:16:24 +08:00
|
|
|
<?php
|
|
|
|
|
2019-04-08 07:53:24 +08:00
|
|
|
namespace App\Services\Installer;
|
2018-02-06 06:16:24 +08:00
|
|
|
|
2019-07-16 03:44:31 +08:00
|
|
|
use App\Contracts\Service;
|
2018-09-03 01:18:32 +08:00
|
|
|
use App\Models\Setting;
|
|
|
|
use DB;
|
2018-02-06 06:16:24 +08:00
|
|
|
use Log;
|
|
|
|
use Nwidart\Modules\Facades\Module;
|
2018-09-03 01:18:32 +08:00
|
|
|
use Symfony\Component\Yaml\Yaml;
|
2018-02-06 06:16:24 +08:00
|
|
|
|
2018-03-20 09:50:40 +08:00
|
|
|
class MigrationService extends Service
|
2018-02-06 06:16:24 +08:00
|
|
|
{
|
2018-09-03 01:18:32 +08:00
|
|
|
private $counters = [];
|
|
|
|
private $offsets = [];
|
|
|
|
|
2018-02-06 06:16:24 +08:00
|
|
|
protected function getMigrator()
|
|
|
|
{
|
|
|
|
$m = app('migrator');
|
|
|
|
$m->setConnection(config('database.default'));
|
|
|
|
return $m;
|
|
|
|
}
|
|
|
|
|
2018-09-03 01:18:32 +08:00
|
|
|
/**
|
2019-04-08 11:12:45 +08:00
|
|
|
* Syncronize all of the seed files, run this after the migrations
|
|
|
|
* and on first install.
|
2018-09-03 01:18:32 +08:00
|
|
|
*/
|
2019-04-08 07:53:24 +08:00
|
|
|
public function syncAllSeeds(): void
|
2018-09-03 01:18:32 +08:00
|
|
|
{
|
2019-04-08 07:53:24 +08:00
|
|
|
$this->syncAllSettings();
|
2019-07-23 20:41:20 +08:00
|
|
|
$this->syncAllPermissions();
|
2019-04-08 07:53:24 +08:00
|
|
|
}
|
|
|
|
|
2019-04-08 08:23:44 +08:00
|
|
|
public function syncAllSettings(): void
|
|
|
|
{
|
2018-09-03 01:18:32 +08:00
|
|
|
$data = file_get_contents(database_path('/seeds/settings.yml'));
|
|
|
|
$yml = Yaml::parse($data);
|
|
|
|
foreach ($yml as $setting) {
|
2019-04-08 07:53:24 +08:00
|
|
|
if (\trim($setting['key']) === '') {
|
2018-09-03 01:18:32 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->addSetting($setting['key'], $setting);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-23 20:41:20 +08:00
|
|
|
public function syncAllPermissions(): void
|
|
|
|
{
|
|
|
|
$data = file_get_contents(database_path('/seeds/permissions.yml'));
|
|
|
|
$yml = Yaml::parse($data);
|
|
|
|
foreach ($yml as $perm) {
|
|
|
|
$count = DB::table('permissions')->where('name', $perm['name'])->count('name');
|
|
|
|
if ($count === 0) {
|
|
|
|
DB::table('permissions')->insert($perm);
|
|
|
|
} else {
|
|
|
|
DB::table('settings')
|
|
|
|
->where('name', $perm['name'])
|
|
|
|
->update($perm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-03 01:18:32 +08:00
|
|
|
/**
|
|
|
|
* @param $key
|
|
|
|
* @param $attrs
|
|
|
|
*/
|
|
|
|
public function addSetting($key, $attrs): void
|
|
|
|
{
|
|
|
|
$id = Setting::formatKey($key);
|
|
|
|
$group = $attrs['group'];
|
|
|
|
$order = $this->getNextOrderNumber($group);
|
|
|
|
|
|
|
|
$attrs = array_merge(
|
|
|
|
[
|
|
|
|
'id' => $id,
|
|
|
|
'key' => $key,
|
|
|
|
'offset' => $this->offsets[$group],
|
|
|
|
'order' => $order,
|
|
|
|
'name' => '',
|
|
|
|
'group' => $group,
|
|
|
|
'value' => '',
|
|
|
|
'default' => $attrs['value'],
|
|
|
|
'options' => '',
|
|
|
|
'type' => 'hidden',
|
|
|
|
'description' => '',
|
|
|
|
],
|
|
|
|
$attrs
|
|
|
|
);
|
|
|
|
|
|
|
|
$count = DB::table('settings')->where('id', $id)->count('id');
|
|
|
|
if ($count === 0) {
|
|
|
|
DB::table('settings')->insert($attrs);
|
|
|
|
} else {
|
|
|
|
unset($attrs['value']); // Don't overwrite this
|
|
|
|
DB::table('settings')
|
|
|
|
->where('id', $id)
|
|
|
|
->update($attrs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Dynamically figure out the offset and the start number for a group.
|
|
|
|
* This way we don't need to mess with how to order things
|
|
|
|
* When calling getNextOrderNumber(users) 31, will be returned, then 32, and so on
|
|
|
|
*
|
|
|
|
* @param $name
|
|
|
|
* @param null $offset
|
|
|
|
* @param int $start_offset
|
|
|
|
*/
|
|
|
|
private function addCounterGroup($name, $offset = null, $start_offset = 0): void
|
|
|
|
{
|
|
|
|
if ($offset === null) {
|
|
|
|
$group = DB::table('settings')
|
|
|
|
->where('group', $name)
|
|
|
|
->first();
|
|
|
|
|
|
|
|
if ($group === null) {
|
2019-04-08 08:23:44 +08:00
|
|
|
$offset = (int) DB::table('settings')->max('offset');
|
2018-09-03 01:18:32 +08:00
|
|
|
if ($offset === null) {
|
|
|
|
$offset = 0;
|
|
|
|
$start_offset = 1;
|
|
|
|
} else {
|
|
|
|
$offset += 100;
|
|
|
|
$start_offset = $offset + 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Now find the number to start from
|
2019-04-08 08:23:44 +08:00
|
|
|
$start_offset = (int) DB::table('settings')->where('group', $name)->max('order');
|
2018-09-03 01:18:32 +08:00
|
|
|
if ($start_offset === null) {
|
|
|
|
$start_offset = $offset + 1;
|
|
|
|
} else {
|
|
|
|
$start_offset++;
|
|
|
|
}
|
|
|
|
|
|
|
|
$offset = $group->offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->counters[$name] = $start_offset;
|
|
|
|
$this->offsets[$name] = $offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the next increment number from a group
|
|
|
|
*
|
|
|
|
* @param $group
|
|
|
|
*
|
|
|
|
* @return int
|
|
|
|
*/
|
|
|
|
private function getNextOrderNumber($group): int
|
|
|
|
{
|
|
|
|
if (!\in_array($group, $this->counters, true)) {
|
|
|
|
$this->addCounterGroup($group);
|
|
|
|
}
|
|
|
|
|
|
|
|
$idx = $this->counters[$group];
|
|
|
|
$this->counters[$group]++;
|
|
|
|
|
|
|
|
return $idx;
|
|
|
|
}
|
|
|
|
|
2018-02-06 06:16:24 +08:00
|
|
|
/**
|
|
|
|
* Find all of the possible paths that migrations exist.
|
|
|
|
* Include looking in all of the modules Database/migrations directories
|
2019-04-08 08:23:44 +08:00
|
|
|
*
|
2018-02-06 06:16:24 +08:00
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function getMigrationPaths(): array
|
|
|
|
{
|
|
|
|
$paths = [
|
2019-04-08 11:12:45 +08:00
|
|
|
'core' => \App::databasePath().'/migrations',
|
2018-02-06 06:16:24 +08:00
|
|
|
];
|
|
|
|
|
2018-06-22 22:26:08 +08:00
|
|
|
$modules = Module::allEnabled();
|
2018-02-06 06:16:24 +08:00
|
|
|
foreach ($modules as $module) {
|
2019-04-08 08:23:44 +08:00
|
|
|
$module_path = $module->getPath().'/Database/migrations';
|
2019-04-08 11:12:45 +08:00
|
|
|
if (file_exists($module_path)) {
|
2018-02-06 06:16:24 +08:00
|
|
|
$paths[$module->getName()] = $module_path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Log::info('Update - migration paths', $paths);
|
|
|
|
|
|
|
|
return $paths;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return what migrations are available
|
|
|
|
*/
|
|
|
|
public function migrationsAvailable(): array
|
|
|
|
{
|
|
|
|
$migrator = $this->getMigrator();
|
|
|
|
$migration_dirs = $this->getMigrationPaths();
|
|
|
|
|
|
|
|
$files = $migrator->getMigrationFiles(array_values($migration_dirs));
|
|
|
|
$availMigrations = array_diff(array_keys($files), $migrator->getRepository()->getRan());
|
|
|
|
|
|
|
|
Log::info('Migrations available:', $availMigrations);
|
|
|
|
|
|
|
|
return $availMigrations;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Run all of the migrations that are available. Just call artisan since
|
|
|
|
* it looks into all of the module directories, etc
|
|
|
|
*/
|
|
|
|
public function runAllMigrations()
|
|
|
|
{
|
|
|
|
$output = '';
|
|
|
|
|
|
|
|
\Artisan::call('migrate');
|
|
|
|
$output .= trim(\Artisan::output());
|
|
|
|
|
|
|
|
return $output;
|
|
|
|
}
|
|
|
|
}
|