Rewrite installer without 3rd party installer lib.

This commit is contained in:
Nabeel Shahzad
2017-12-14 16:38:29 -06:00
parent 7966d6c5aa
commit 277a5f2d33
22 changed files with 581 additions and 174 deletions

View File

@@ -1,5 +1,23 @@
<?php
use Illuminate\Validation\Rule;
return [
'name' => 'Installer'
'php' => [
'version' => '7.0.0'
],
'extensions' => [
'openssl',
'pdo',
'mbstring',
'tokenizer',
'JSON',
'cURL',
],
'permissions' => [
'storage/framework/' => 'writeable',
'storage/logs/' => 'writeable',
'bootstrap/cache/' => 'writable'
],
];

View File

@@ -2,18 +2,131 @@
namespace Modules\Installer\Http\Controllers;
use App\Http\Controllers\AppBaseController;
use Log;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use Modules\Installer\Services\DatabaseService;
use Modules\Installer\Services\EnvironmentService;
use Modules\Installer\Services\RequirementsService;
class InstallerController extends AppBaseController
{
protected $dbService, $envService, $reqService;
public function __construct(
DatabaseService $dbService,
EnvironmentService $envService,
RequirementsService $reqService
) {
$this->dbService = $dbService;
$this->envService = $envService;
$this->reqService = $reqService;
}
/**
* Display a listing of the resource.
*/
public function index()
{
return view('installer::index');
return view('installer::index-start');
}
/**
* Check the database connection
*/
public function dbtest(Request $request)
{
$status = 'success'; # success|warn|danger
$message = 'Database connection looks good!';
try {
$this->dbService->checkDbConnection(
$request->input('db_conn'),
$request->input('db_host'),
$request->input('db_port'),
$request->input('db_name'),
$request->input('db_user'),
$request->input('db_pass')
);
} catch (\Exception $e) {
$status = 'danger';
$message = 'Failed! ' . $e->getMessage();
}
return view('installer::flash/message', [
'status' => $status,
'message' => $message,
]);
}
/**
* Step 1. Check the modules and permissions
*/
public function step1(Request $request)
{
$passed = true;
$php_version = $this->reqService->checkPHPVersion();
if($php_version['passed'] === false) {
$passed = false;
}
$extensions = $this->reqService->checkExtensions();
foreach ($extensions as $ext) {
if($ext['passed'] === false) {
$passed = false;
}
}
return view('installer::steps/step1-requirements', [
'php' => $php_version,
'extensions' => $extensions,
'passed' => $passed,
]);
}
/**
* Step 2. Database Setup
*/
public function step2(Request $request)
{
$db_types = ['mysql' => 'mysql', 'sqlite' => 'sqlite'];
return view('installer::steps/step2-db', [
'db_types' => $db_types,
]);
}
/**
* Step 2a. Do the config and setup
*/
public function dbsetup(Request $request)
{
$log = [];
Log::info('DB Setup', $request->toArray());
$log[] = 'Creating environment file';
$this->envService->createEnvFile(
$request->input('db_conn'),
$request->input('db_host'),
$request->input('db_port'),
$request->input('db_name'),
$request->input('db_user'),
$request->input('db_pass')
);
$log[] = 'Creating database';
$this->dbService->setupDB();
return redirect('/');
}
/**
* Step 3. Setup the admin user and initial settings
*/
public function step3(Request $request)
{
}
}

View File

@@ -1,3 +1,9 @@
<?php
Route::get('/', 'InstallerController@index');
Route::get('/', 'InstallerController@index')->name('index');
Route::get('/step1', 'InstallerController@step1')->name('step1');
Route::get('/step2', 'InstallerController@step2')->name('step2');
Route::get('/step3', 'InstallerController@step3')->name('step3');
Route::post('/dbtest', 'InstallerController@dbtest')->name('dbtest');
Route::post('/dbsetup', 'InstallerController@dbsetup')->name('dbsetup');

View File

@@ -6,7 +6,7 @@
<link rel="apple-touch-icon" sizes="76x76" href="/assets/frontend/img/apple-icon.png">
<link rel="icon" type="image/png" href="/assets/frontend/img/favicon.png">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
<title>phpvms installer</title>
<title>@yield('title') - installer</title>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, shrink-to-fit=no'
name='viewport'/>
<!-- Fonts and icons -->
@@ -39,15 +39,22 @@
</a>
</p>
</div>
<div class="collapse navbar-collapse justify-content-end" id="navigation"></div>
<div class="justify-content-center" id="navigation" style="margin-left: 50px; color: white; font-size: 20px;">
@yield('title')
</div>
</div>
</nav>
<!-- End Navbar -->
<div class="clearfix" style="height: 25px;"></div>
<div class="wrapper">
<div class="clear"></div>
<div class="container-fluid" style="width: 85%!important;">
@yield('content')
<div class="container" style="width: 50%">
<div class="row">
<div class="col-12">
@include('flash::message')
@yield('content')
</div>
</div>
</div>
<div class="clearfix" style="height: 200px;"></div>
</div>

View File

@@ -0,0 +1,8 @@
<div class="alert alert-{!! $status !!}" role="alert">
<div class="container">
<div class="alert-icon">
<i class="now-ui-icons ui-2_like"></i>
</div>
{!! $message !!}
</div>
</div>

View File

@@ -0,0 +1,11 @@
@extends('installer::app')
@section('content')
<h2>phpvms installer</h2>
<p>Press continue to start</p>
{!! Form::open(['route' => 'installer.step1', 'method' => 'post']) !!}
<p style="text-align: right">
{!! Form::submit('Start >>', ['class' => 'btn btn-success']) !!}
</p>
{!! Form::close() !!}
@endsection

View File

@@ -1,6 +0,0 @@
@extends('installer::app')
@section('content')
<h2>phpvms installer</h2>
<p>This view is loaded from module: {!! config('installer.name') !!}</p>
@endsection

View File

@@ -0,0 +1,43 @@
@extends('installer::app')
@section('title', 'Requirements Check')
@section('content')
<div style="align-content: center;">
{!! Form::open(['route' => 'installer.step2', 'method' => 'GET']) !!}
<table class="table" width="25%">
<tr><td colspan="2"><h4>php version</h4></td></tr>
<tr>
<td>PHP Version: {!! $php['version'] !!}</td>
<td style="text-align:center;">
@if($php['passed'] === true)
<span class="badge badge-success">OK!</span>
@else
<span class="badge badge-danger">Failed!</span>
@endif
</td>
</tr>
<tr><td colspan="2"><h4>php extensions</h4></td></tr>
@foreach($extensions as $ext)
<tr>
<td>{!! $ext['ext'] !!}</td>
<td style="text-align:center;">
@if($ext['passed'] === true)
<span class="badge badge-success">OK!</span>
@else
<span class="badge badge-danger">Failed!</span>
@endif
</td>
</tr>
@endforeach
</table>
@if($passed === true)
<p style="text-align: right">
{!! Form::submit('Database Setup >>', ['class' => 'btn btn-success']) !!}
</p>
@endif
{{--{!! $php_version !!}
{!! $extensions !!}
{!! $passed !!}--}}
{!! Form::close() !!}
</div>
@endsection

View File

@@ -0,0 +1,116 @@
@extends('installer::app')
@section('title', 'Database Setup')
@section('content')
<div style="align-content: center;">
{!! Form::open(['route' => 'installer.dbsetup', 'method' => 'POST']) !!}
<table class="table" width="25%">
<tr>
<td>Select Database Type</td>
<td style="text-align:center;">
<div class="form-group">
{!! Form::select('db_conn', $db_types, null, ['class' => 'form-control', 'id' => 'db_conn']) !!}
</div>
</td>
</tr>
<tbody id="mysql_settings" class="settings_panel">
<tr>
<td>Database Host</td>
<td style="text-align:center;">
<div class="form-group">
{!! Form::input('text', 'db_host', null, ['class' => 'form-control']) !!}
</div>
</td>
</tr>
<tr>
<td>Database Port</td>
<td style="text-align:center;">
<div class="form-group">
{!! Form::input('text', 'db_port', '3307', ['class' => 'form-control']) !!}
</div>
</td>
</tr>
<tr>
<td>Database Name</td>
<td style="text-align:center;">
<div class="form-group">
{!! Form::input('text', 'db_name', 'phpvms', ['class' => 'form-control']) !!}
</div>
</td>
</tr>
<tr>
<td>Database User</td>
<td style="text-align:center;">
<div class="form-group">
{!! Form::input('text', 'db_user', null, ['class' => 'form-control']) !!}
</div>
</td>
</tr>
<tr>
<td>Database Password</td>
<td style="text-align:center;">
<div class="form-group">
{!! Form::input('text', 'db_pass', null, ['class' => 'form-control']) !!}
</div>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: right;">
{!! Form::submit('Test Database Credentials', ['class' => 'btn btn-info', 'id' => 'dbtest_button']) !!}
</td>
</tr>
</tbody>
<tbody id="sqlite_settings" class="settings_panel">
</tbody>
</table>
<div id="dbtest"></div>
<p style="text-align: right">
{!! Form::submit('Complete Setup >>', ['class' => 'btn btn-success']) !!}
</p>
{!! Form::close() !!}
</div>
@endsection
@section('scripts')
<script>
function changeForm(selected) {
$("tbody.settings_panel").hide();
$("tbody#" + selected + "_settings").show();
}
$(document).ready(function() {
var selValue = $("#db_conn option:selected").text();
changeForm(selValue);
$("#db_conn").change(function(e) {
var selValue = $("#db_conn option:selected").text();
changeForm(selValue);
});
$("#dbtest_button").click(function(e) {
e.preventDefault();
var opts = {
db_conn: $("#db_conn option:selected").text(),
db_host: $("input[name=db_host]").val(),
db_port: $("input[name=db_port]").val(),
db_name: $("input[name=db_name]").val(),
db_user: $("input[name=db_user]").val(),
db_pass: $("input[name=db_pass]").val(),
};
console.log(opts);
$.post("{!! route('installer.dbtest') !!}", opts, function(data) {
$("#dbtest").html(data);
})
})
});
</script>
@endsection

View File

@@ -0,0 +1,34 @@
#
# Before you go live, remember to change the APP_ENV to production
# and APP_DEBUG to false
#
APP_ENV=dev
APP_KEY=base64:{!! $app_key !!}
APP_DEBUG=true
APP_LOCALE=en
APP_LOG=daily
APP_LOG_LEVEL=debug
APP_LOG_MAX_FILES=3
APP_URL=http://localhost
DB_CONNECTION={!! $db_conn !!}
DB_HOST={!! $db_host !!}
DB_PORT={!! $db_port !!}
DB_DATABASE={!! $db_name !!}
DB_USERNAME={!! $db_user !!}
DB_PASSWORD={!! $db_pass !!}
DB_PREFIX=
CACHE_DRIVER=array
CACHE_PREFIX=
REDIS_HOST=localhost
REDIS_PASSWORD=
REDIS_PORT=6379
REDIS_DATABASE=1
SESSION_DRIVER=array
QUEUE_DRIVER=sync

View File

@@ -0,0 +1,50 @@
<?php
namespace Modules\Installer\Services;
use Log;
use PDO;
class DatabaseService {
/**
* Check the PHP version that it meets the minimum requirement
* @throws \PDOException
* @return boolean
*/
public function checkDbConnection($type, $host, $port, $name, $user, $pass)
{
Log::info('Testing Connection: '.$type.'::'.$user.':'.$pass.'@'.$host.':'.$port.';'.$name);
if($type === 'mysql') {
$dsn = "mysql:host=$host;port=$port;dbname=$name";
Log::info('Connection string: '. $dsn);
try {
$conn = new PDO($dsn, $user, $pass);
} catch (\PDOException $e) {
throw $e;
}
}
// Needs testing
elseif ($type === 'postgres') {
$dsn = "pgsql:host=$host;port=$port;dbname=$name";
try {
$conn = new PDO($dsn, $user, $pass);
} catch (\PDOException $e) {
throw $e;
}
}
return true;
}
/**
* Setup the database by running the migration commands
*/
public function setupDB()
{
\Artisan::call('database:create');
\Artisan::call('migrate:refresh');
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Modules\Installer\Services;
use Illuminate\Encryption\Encrypter;
use Log;
use PDO;
class EnvironmentService
{
/**
* Check the PHP version that it meets the minimum requirement
* @return boolean
*/
public function createEnvFile($type, $host, $port, $name, $user, $pass)
{
$env_opts = [
'db_conn' => $type,
'db_host' => $host,
'db_port' => $port,
'db_name' => $name,
'db_user' => $user,
'db_pass' => $pass,
];
$env_opts['app_key'] = base64_encode(Encrypter::generateKey(config('app.cipher')));
$this->writeEnvFile($env_opts);
return true;
}
/**
* Get the template file name and write it out
*/
protected function writeEnvFile($env_opts)
{
$app = app();
$env_file = $app->environmentFilePath();
# TODO: Remove this post-testing
$env_file .= '.generated';
$env_contents = view('installer::stubs/env', $env_opts);
Log::info($env_contents);
$fp = fopen($env_file, 'w');
fwrite($fp, $env_contents);
fclose($fp);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Modules\Installer\Services;
class RequirementsService {
/**
* Check the PHP version that it meets the minimum requirement
* @return array
*/
public function checkPHPVersion(): array
{
$passed = false;
if(version_compare(PHP_VERSION, config('installer.php.version')) >= 0) {
$passed = true;
}
return ['version' => PHP_VERSION, 'passed' => $passed];
}
/**
* Make sure the minimal extensions required are loaded
* @return array
*/
public function checkExtensions(): array
{
$extensions = [];
foreach(config('installer.extensions') as $ext) {
$pass = true;
if(!extension_loaded($ext)) {
$pass = false;
}
$extensions[] = [
'ext' => $ext,
'passed' => $pass,
];
}
return $extensions;
}
}