blue-twilight/app/Http/Middleware/AppInstallation.php

138 lines
4.3 KiB
PHP

<?php
namespace App\Http\Middleware;
use App\DataMigration;
use App\Facade\UserConfig;
use App\Helpers\MiscHelper;
use Closure;
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Log;
class AppInstallation
{
private $baseDirectory;
private $environmentFilePath;
/**
* The application instance.
*
* @var \Illuminate\Foundation\Application
*/
protected $app;
/**
* Create a new middleware instance.
*
* @param \Illuminate\Foundation\Application $app
* @return void
*/
public function __construct(Application $app)
{
$this->app = $app;
$this->baseDirectory = dirname(dirname(dirname(__DIR__)));
$this->environmentFilePath = sprintf('%s/.env', $this->baseDirectory);
}
public function handle(Request $request, Closure $next)
{
// We always need an encryption key if not already present
$this->generateAppKey();
if ($this->app->runningInConsole())
{
// Allow the console to run successfully even if we're not installed
return $next($request);
}
// See if the successful flag has been written to the .env file
$isAppInstalled = MiscHelper::getEnvironmentSetting('APP_INSTALLED');
if ($request->is('install/*'))
{
// Already in the installer
// For security reasons, don't allow the installer to be used if it has been previously completed
if (boolval($isAppInstalled))
{
return redirect(route('home'));
}
return $next($request);
}
if ($isAppInstalled)
{
// See if an update is necessary
$this->updateDatabaseIfRequired();
// App is configured, continue on
return $next($request);
}
return redirect(route('install.check'));
}
private function generateAppKey()
{
// Generate an application key and store to the .env file
if (!file_exists($this->environmentFilePath))
{
$key = MiscHelper::randomString(32);
file_put_contents($this->environmentFilePath, sprintf('APP_KEY=%s', $key) . PHP_EOL);
app('config')->set(['app' => ['key' => $key]]);
}
}
private function updateDatabaseIfRequired()
{
$versionNumber = UserConfig::getOrCreateModel('app_version');
$appVersionNumber = config('app.version');
if (is_null($appVersionNumber) || $versionNumber->value != $appVersionNumber)
{
Log::info('Upgrading database', ['new_version' => $appVersionNumber]);
Artisan::call('config:cache');
Artisan::call('cache:clear');
Artisan::call('view:clear');
Artisan::call('migrate', ['--force' => true]);
Artisan::call('db:seed', ['--force' => true]);
// Run any data migrations relevant to the new version
$dataMigrationsFolder = join(DIRECTORY_SEPARATOR, [dirname(dirname(dirname(__DIR__))), 'database', 'data_migrations']);
$di = new \RecursiveDirectoryIterator($dataMigrationsFolder, \RecursiveDirectoryIterator::SKIP_DOTS);
$updateClasses = [];
// First load all data migration classes and examine the version number to decide if we need it or not
/** @var \SplFileInfo $fileInfo */
foreach ($di as $fileInfo)
{
if (!$di->isFile() || $di->getExtension() != 'php')
{
continue;
}
$className = substr($fileInfo->getFilename(), 0, strlen($fileInfo->getFilename()) - 4);
/** @var DataMigration $upgradeClass */
$upgradeClass = new $className;
if (version_compare($versionNumber->value, $upgradeClass->getVersion()) < 0)
{
$updateClasses[] = $upgradeClass;
}
}
// Now run the migrations
foreach ($updateClasses as $upgradeClass)
{
$upgradeClass->run($versionNumber);
}
// Save the new version number
$versionNumber->value = $appVersionNumber;
$versionNumber->save();
}
}
}