Improved Bootstrap experience and services improvements #154

Manually merged
aheathershaw merged 8 commits from feature/146-bootstrap-experience into master 2020-04-30 08:48:54 +01:00
18 changed files with 742 additions and 166 deletions
Showing only changes of commit cb849c7928 - Show all commits

View File

@ -111,9 +111,9 @@ class MiscHelper
return sprintf('%s/.env', dirname(dirname(__DIR__)));
}
public static function getEnvironmentSetting($settingName)
public static function getEnvironmentSetting($settingName, $envFile = null)
{
$envFile = MiscHelper::getEnvironmentFilePath();
$envFile = $envFile ?? MiscHelper::getEnvironmentFilePath();
if (!file_exists($envFile))
{

View File

@ -19,10 +19,10 @@ class InstallController extends Controller
public function administrator(StoreUserRequest $request)
{
// Validate we're at the required stage
$stage = 3;
$stage = 2;
if (intval($request->session()->get('install_stage')) < $stage)
{
return redirect(route('install.check'));
return redirect(route('install.database'));
}
// If we already have an admin account, this step can be skipped
@ -52,70 +52,9 @@ class InstallController extends Controller
]);
}
public function check(Request $request)
{
// This is the first installation step therefore it doesn't need to verify the stage
if ($request->getMethod() == 'POST')
{
$request->session()->put('install_stage', 2);
return redirect(route('install.database'));
}
$canContinue = true;
$runtimeMinimum = '7.0.0'; // this minimum is imposed by Laravel 5.5
$runtimeVersion = phpversion();
$phpIsValid = version_compare($runtimeVersion, $runtimeMinimum) >= 0;
if (!$phpIsValid)
{
$canContinue = false;
}
$requiredModules = [
'curl' => 'installer.php_modules.curl',
'pdo_mysql' => 'installer.php_modules.mysql',
'gd' => 'installer.php_modules.gd'
];
$availableModules = [];
foreach ($requiredModules as $key => $langString)
{
$availableModules[$key] = extension_loaded($key);
if (!$availableModules[$key])
{
$canContinue = false;
}
}
$uploadLimit = MiscHelper::convertToBytes(ini_get('upload_max_filesize'));
$postMaxSize = MiscHelper::convertToBytes(ini_get('post_max_size'));
$recommendedMinimum = 4 * 1024 * 1024;
return view('install.check', [
'available_modules' => $availableModules,
'can_continue' => $canContinue,
'php_is_valid' => $phpIsValid,
'php_version_current' => $runtimeVersion,
'php_version_required' => $runtimeMinimum,
'post_max_size' => ($postMaxSize / 1024 / 1024),
'post_max_size_warning' => $postMaxSize < $recommendedMinimum,
'recommended_minimum_upload' => ($recommendedMinimum / 1024 / 1024),
'upload_limit' => ($uploadLimit / 1024 / 1024),
'upload_limit_warning' => $uploadLimit < $recommendedMinimum,
'required_modules' => $requiredModules
]);
}
public function database(Request $request)
{
// Validate we're at the required stage
$stage = 2;
if (intval($request->session()->get('install_stage')) < $stage)
{
return redirect(route('install.check'));
}
// This is the first installation step therefore it doesn't need to verify the stage
if ($request->method() == 'POST')
{
@ -162,7 +101,7 @@ class InstallController extends Controller
// Default settings
$this->setConfigurationForNewSystems();
$request->session()->put('install_stage', 3);
$request->session()->put('install_stage', 2);
return redirect(route('install.administrator'));
}
catch (\Exception $ex)

View File

@ -14,9 +14,6 @@ use Illuminate\Support\Facades\Log;
class AppInstallation
{
private $baseDirectory;
private $environmentFilePath;
/**
* The application instance.
*
@ -33,8 +30,6 @@ class AppInstallation
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)
@ -51,6 +46,14 @@ class AppInstallation
// See if the successful flag has been written to the .env file
$isAppInstalled = MiscHelper::getEnvironmentSetting('APP_INSTALLED');
// See if the vendors are out-of-date
if ($this->isVendorUpdateRequired())
{
return $isAppInstalled
? redirect('/update')
: redirect('/install');
}
if ($request->is('install/*'))
{
// Already in the installer
@ -72,20 +75,31 @@ class AppInstallation
return $next($request);
}
return redirect(route('install.check'));
return redirect(route('install.database'));
}
private function generateAppKey()
{
// Generate an application key and store to the .env file
if (!file_exists($this->environmentFilePath))
if (!file_exists(MiscHelper::getEnvironmentFilePath()))
{
$key = MiscHelper::randomString(32);
file_put_contents($this->environmentFilePath, sprintf('APP_KEY=%s', $key) . PHP_EOL);
file_put_contents(MiscHelper::getEnvironmentFilePath(), sprintf('APP_KEY=%s', $key) . PHP_EOL);
app('config')->set(['app' => ['key' => $key]]);
}
}
private function isVendorUpdateRequired()
{
$vendorsVersionFilename = $this->app->basePath('vendor/version.txt');
if (!file_exists($vendorsVersionFilename))
{
return true;
}
return trim(file_get_contents($vendorsVersionFilename)) != trim(config('app.version'));
}
private function updateDatabaseIfRequired()
{
$versionNumber = UserConfig::getOrCreateModel('app_version');

453
composer.lock generated
View File

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9a11d044f41aef4c08fcddf00fd6f7ed",
"content-hash": "9dfa65a2590e8d0d5305a4be35a8b140",
"packages": [
{
"name": "aws/aws-sdk-php",
"version": "3.134.8",
"version": "3.135.4",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "8a9b598a0ede2165be5988899dcebead6fcc4d41"
"reference": "fb6f4a12d9ad1b8fc1481aef61ed1f8a9fe2164b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8a9b598a0ede2165be5988899dcebead6fcc4d41",
"reference": "8a9b598a0ede2165be5988899dcebead6fcc4d41",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fb6f4a12d9ad1b8fc1481aef61ed1f8a9fe2164b",
"reference": "fb6f4a12d9ad1b8fc1481aef61ed1f8a9fe2164b",
"shasum": ""
},
"require": {
@ -88,7 +88,7 @@
"s3",
"sdk"
],
"time": "2020-04-17T18:11:57+00:00"
"time": "2020-04-24T18:14:04+00:00"
},
{
"name": "doctrine/cache",
@ -174,16 +174,16 @@
},
{
"name": "doctrine/dbal",
"version": "v2.10.1",
"version": "2.10.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/dbal.git",
"reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8"
"reference": "aab745e7b6b2de3b47019da81e7225e14dcfdac8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8",
"reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/aab745e7b6b2de3b47019da81e7225e14dcfdac8",
"reference": "aab745e7b6b2de3b47019da81e7225e14dcfdac8",
"shasum": ""
},
"require": {
@ -195,9 +195,11 @@
"require-dev": {
"doctrine/coding-standard": "^6.0",
"jetbrains/phpstorm-stubs": "^2019.1",
"phpstan/phpstan": "^0.11.3",
"nikic/php-parser": "^4.4",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^8.4.1",
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0"
"symfony/console": "^2.0.5|^3.0|^4.0|^5.0",
"vimeo/psalm": "^3.11"
},
"suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files."
@ -262,7 +264,21 @@
"sqlserver",
"sqlsrv"
],
"time": "2020-01-04T12:56:21+00:00"
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdbal",
"type": "tidelift"
}
],
"time": "2020-04-20T17:19:26+00:00"
},
{
"name": "doctrine/event-manager",
@ -838,16 +854,16 @@
},
{
"name": "laravel/framework",
"version": "v6.18.8",
"version": "v6.18.10",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "852c91c46adfbc2f5a0f6985cba3d7b7a769b773"
"reference": "9177744ccdd8d5db970fdff2383fe89c2e94aabe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/852c91c46adfbc2f5a0f6985cba3d7b7a769b773",
"reference": "852c91c46adfbc2f5a0f6985cba3d7b7a769b773",
"url": "https://api.github.com/repos/laravel/framework/zipball/9177744ccdd8d5db970fdff2383fe89c2e94aabe",
"reference": "9177744ccdd8d5db970fdff2383fe89c2e94aabe",
"shasum": ""
},
"require": {
@ -980,7 +996,7 @@
"framework",
"laravel"
],
"time": "2020-04-15T20:56:03+00:00"
"time": "2020-04-21T18:53:10+00:00"
},
{
"name": "laravel/socialite",
@ -1048,16 +1064,16 @@
},
{
"name": "league/commonmark",
"version": "1.3.4",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "dd3261eb9a322e009fa5d96d19b9ae19708ce04b"
"reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/dd3261eb9a322e009fa5d96d19b9ae19708ce04b",
"reference": "dd3261eb9a322e009fa5d96d19b9ae19708ce04b",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/9e780d972185e4f737a03bade0fd34a9e67bbf31",
"reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31",
"shasum": ""
},
"require": {
@ -1075,7 +1091,7 @@
"github/gfm": "0.29.0",
"michelf/php-markdown": "~1.4",
"mikehaertl/php-shellcommand": "^1.4",
"phpstan/phpstan-shim": "^0.11.5",
"phpstan/phpstan": "^0.12",
"phpunit/phpunit": "^7.5",
"scrutinizer/ocular": "^1.5",
"symfony/finder": "^4.2"
@ -1118,7 +1134,33 @@
"md",
"parser"
],
"time": "2020-04-13T20:52:18+00:00"
"funding": [
{
"url": "https://enjoy.gitstore.app/repositories/thephpleague/commonmark",
"type": "custom"
},
{
"url": "https://www.colinodell.com/sponsor",
"type": "custom"
},
{
"url": "https://www.paypal.me/colinpodell/10.00",
"type": "custom"
},
{
"url": "https://github.com/colinodell",
"type": "github"
},
{
"url": "https://www.patreon.com/colinodell",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/league/commonmark",
"type": "tidelift"
}
],
"time": "2020-04-24T13:39:56+00:00"
},
{
"name": "league/flysystem",
@ -1202,6 +1244,12 @@
"sftp",
"storage"
],
"funding": [
{
"url": "https://offset.earth/frankdejonge",
"type": "other"
}
],
"time": "2020-04-16T13:21:26+00:00"
},
{
@ -1474,6 +1522,16 @@
"datetime",
"time"
],
"funding": [
{
"url": "https://opencollective.com/Carbon",
"type": "open_collective"
},
{
"url": "https://tidelift.com/funding/github/packagist/nesbot/carbon",
"type": "tidelift"
}
],
"time": "2020-03-31T13:43:19+00:00"
},
{
@ -1584,16 +1642,16 @@
},
{
"name": "php-amqplib/php-amqplib",
"version": "v2.11.0",
"version": "v2.11.1",
"source": {
"type": "git",
"url": "https://github.com/php-amqplib/php-amqplib.git",
"reference": "9ee212baced63442ca1ab029acde38e1144a00b8"
"reference": "cfbfaf6262cd8d017f29862164f75e265d832434"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9ee212baced63442ca1ab029acde38e1144a00b8",
"reference": "9ee212baced63442ca1ab029acde38e1144a00b8",
"url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/cfbfaf6262cd8d017f29862164f75e265d832434",
"reference": "cfbfaf6262cd8d017f29862164f75e265d832434",
"shasum": ""
},
"require": {
@ -1602,6 +1660,9 @@
"php": ">=5.6.3",
"phpseclib/phpseclib": "^2.0.0"
},
"conflict": {
"php": "7.4.0 - 7.4.1"
},
"replace": {
"videlalvaro/php-amqplib": "self.version"
},
@ -1654,7 +1715,7 @@
"queue",
"rabbitmq"
],
"time": "2019-11-19T15:15:19+00:00"
"time": "2020-02-24T17:37:52+00:00"
},
{
"name": "php-opencloud/openstack",
@ -1864,6 +1925,20 @@
"x.509",
"x509"
],
"funding": [
{
"url": "https://github.com/terrafrost",
"type": "github"
},
{
"url": "https://www.patreon.com/phpseclib",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
"type": "tidelift"
}
],
"time": "2020-04-04T23:17:33+00:00"
},
{
@ -2323,6 +2398,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-30T11:41:10+00:00"
},
{
@ -2376,6 +2465,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:56:45+00:00"
},
{
@ -2432,6 +2535,20 @@
],
"description": "Symfony Debug Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:54:36+00:00"
},
{
@ -2488,6 +2605,20 @@
],
"description": "Symfony ErrorHandler Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-30T14:07:33+00:00"
},
{
@ -2558,6 +2689,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:54:36+00:00"
},
{
@ -2665,6 +2810,20 @@
],
"description": "Symfony Finder Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:54:36+00:00"
},
{
@ -2720,6 +2879,20 @@
],
"description": "Symfony HttpFoundation Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-30T14:07:33+00:00"
},
{
@ -2810,6 +2983,20 @@
],
"description": "Symfony HttpKernel Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-30T14:59:15+00:00"
},
{
@ -2872,6 +3059,20 @@
"mime",
"mime-type"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:56:45+00:00"
},
{
@ -2930,6 +3131,20 @@
"polyfill",
"portable"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
},
{
@ -2989,6 +3204,20 @@
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
@ -3051,6 +3280,20 @@
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
@ -3110,6 +3353,20 @@
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-09T19:04:49+00:00"
},
{
@ -3165,6 +3422,20 @@
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
},
{
@ -3223,6 +3494,20 @@
"portable",
"shim"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-02-27T09:26:54+00:00"
},
{
@ -3272,6 +3557,20 @@
],
"description": "Symfony Process Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:54:36+00:00"
},
{
@ -3348,6 +3647,20 @@
"uri",
"url"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-30T11:41:10+00:00"
},
{
@ -3482,6 +3795,20 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:54:36+00:00"
},
{
@ -3615,6 +3942,20 @@
"debug",
"dump"
],
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2020-03-27T16:54:36+00:00"
},
{
@ -3727,6 +4068,12 @@
"env",
"environment"
],
"funding": [
{
"url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
"type": "tidelift"
}
],
"time": "2020-04-12T15:18:03+00:00"
}
],
@ -3839,6 +4186,12 @@
"flare",
"reporting"
],
"funding": [
{
"url": "https://www.patreon.com/spatie",
"type": "patreon"
}
],
"time": "2020-03-02T15:52:04+00:00"
},
{
@ -4332,24 +4685,21 @@
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.0.0",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library",
"extra": {
"branch-alias": {
@ -4380,7 +4730,7 @@
"reflection",
"static analysis"
],
"time": "2018-08-07T13:53:10+00:00"
"time": "2020-04-27T09:25:28+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
@ -4798,16 +5148,16 @@
},
{
"name": "phpunit/phpunit",
"version": "8.5.3",
"version": "8.5.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf"
"reference": "8474e22d7d642f665084ba5ec780626cbd1efd23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8474e22d7d642f665084ba5ec780626cbd1efd23",
"reference": "8474e22d7d642f665084ba5ec780626cbd1efd23",
"shasum": ""
},
"require": {
@ -4877,7 +5227,17 @@
"testing",
"xunit"
],
"time": "2020-03-31T08:52:04+00:00"
"funding": [
{
"url": "https://phpunit.de/donate.html",
"type": "custom"
},
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
}
],
"time": "2020-04-23T04:39:42+00:00"
},
{
"name": "scrivo/highlight.php",
@ -4946,6 +5306,12 @@
"highlight.php",
"syntax"
],
"funding": [
{
"url": "https://github.com/allejo",
"type": "github"
}
],
"time": "2020-03-02T05:59:21+00:00"
},
{
@ -5662,5 +6028,6 @@
"ext-curl": "*",
"ext-json": "*"
},
"platform-dev": []
"platform-dev": [],
"plugin-api-version": "1.1.0"
}

View File

@ -2,7 +2,7 @@
return [
// Version number of Blue Twilight
'version' => '2.2.0-beta.1',
'version' => '2.2.0-beta.2',
/*
|--------------------------------------------------------------------------

View File

@ -28,11 +28,11 @@ return [
],
'gitea' => [
'api_url' => 'https://apps.andysh.uk/api/v1',
'api_url' => env('GITEA_API_URL', 'https://apps.andysh.uk/api/v1'),
'cache_time_seconds' => 3600,
'releases_url' => 'https://apps.andysh.uk/%s/%s/releases',
'repo_name' => 'blue-twilight',
'repo_owner' => 'aheathershaw'
'releases_url' => env('GITEA_RELEASES_URL', 'https://apps.andysh.uk/%s/%s/releases'),
'repo_name' => env('GITEA_REPO_NAME', 'blue-twilight'),
'repo_owner' => env('GITEA_REPO_OWNER', 'aheathershaw')
],
'rackspace' => [

View File

@ -14,7 +14,7 @@ class AddS3SignedUrlsColumnToStoragesTable extends Migration
public function up()
{
Schema::table('storages', function (Blueprint $table) {
$table->boolean('s3_signed_urls');
$table->boolean('s3_signed_urls')->default(false);
});
}

View File

@ -0,0 +1,71 @@
<?php
namespace AppInstaller;
use App\Helpers\MiscHelper;
class AppRequirements
{
const STATUS_OK = 0;
const STATUS_WARNING = 1;
const STATUS_NOT_MET = 2;
public static function hasCurlLibrary()
{
return self::isModuleLoaded('curl') ? self::STATUS_OK : self::STATUS_NOT_MET;
}
public static function hasGdLibrary()
{
return self::isModuleLoaded('gd') ? self::STATUS_OK : self::STATUS_NOT_MET;
}
public static function hasMySqlClientLibrary()
{
return self::isModuleLoaded('pdo_mysql') ? self::STATUS_OK : self::STATUS_NOT_MET;
}
public static function maxPostRequestSize(&$status)
{
$bytes = self::getPhpIniValueAsBytes('post_max_size');
$recommendedMinimum = 4 * 1024 * 1024;
if ($bytes < $recommendedMinimum)
{
return self::STATUS_WARNING;
}
$status = sprintf('%0.2f MB', $bytes / 1024 / 1024);
return self::STATUS_OK;
}
public static function maxUploadSize(&$status)
{
$bytes = self::getPhpIniValueAsBytes('upload_max_filesize');
$recommendedMinimum = 4 * 1024 * 1024;
if ($bytes < $recommendedMinimum)
{
return self::STATUS_WARNING;
}
$status = sprintf('%0.2f MB', $bytes / 1024 / 1024);
return self::STATUS_OK;
}
public static function php72OrLater(&$status)
{
$status = phpversion();
return version_compare(phpversion(), '7.4.5', '>=') ? self::STATUS_OK : self::STATUS_NOT_MET;
}
private static function getPhpIniValueAsBytes($settingName)
{
return MiscHelper::convertToBytes(ini_get($settingName));
}
private static function isModuleLoaded($name)
{
return extension_loaded($name);
}
}

View File

@ -26,6 +26,12 @@ class Installer
*/
private $installerDir;
/**
* True if we're upgrading Blue Twilight, false if it's a new install
* @var bool
*/
private $isUpgrade;
/**
* Path to / - the app's root
* @var string
@ -44,6 +50,11 @@ class Installer
*/
private $vendorDir;
/**
* @var string
*/
private $versionNumber;
/**
* Path to /installer/views
* @var string
@ -55,20 +66,20 @@ class Installer
$this->installerDir = __DIR__;
$this->rootDir = dirname($this->installerDir);
$this->configDir = sprintf('%s/config', dirname(dirname($this->installerDir)));
$this->configDir = sprintf('%s/config', $this->rootDir);
$this->tempDir = sprintf('%s/temp', $this->installerDir);
$this->vendorDir = sprintf('%s/vendor', $this->rootDir);
$this->viewsDir = sprintf('%s/views', $this->installerDir);
chdir($this->rootDir);
putenv('HOME=' . $this->rootDir);
$appConfig = require_once sprintf('%s/app.php', $this->configDir);
$this->versionNumber = $appConfig['version'];
}
public function handleRequest()
{
if (!isset($_GET['act']))
{
$this->view('index', ['appName' => 'Blue Twilight Bootstrapper']);
$this->checkInstallation();
}
else
{
@ -92,12 +103,88 @@ class Installer
}
}
/**
* @param bool $isUpgrade
*/
public function setIsUpgrade(bool $isUpgrade): void
{
$this->isUpgrade = $isUpgrade;
}
protected function checkInstallation()
{
$requirements = [
'core:php72OrLater',
'php:hasCurlLibrary',
'php:hasMySqlClientLibrary',
'php:hasGdLibrary',
'config:maxUploadSize',
'config:maxPostRequestSize'
];
$requirementsGrouped = [];
$canInstall = true;
foreach ($requirements as $requirement)
{
$requirementSplit = explode(':', $requirement);
$groupName = $requirementSplit[0];
$functionName = $requirementSplit[1];
$status = null;
$result = call_user_func_array([AppRequirements::class, $functionName], [&$status]);
if ($result == AppRequirements::STATUS_NOT_MET)
{
$canInstall = false;
}
if (!array_key_exists($groupName, $requirementsGrouped))
{
$requirementsGrouped[$groupName] = [];
}
if (!array_key_exists($functionName, $requirementsGrouped[$groupName]))
{
$requirementsGrouped[$groupName][$functionName] = [
'result' => $result,
'status' => $status
];
}
}
$requirementGroupNames = [
'config' => 'PHP configuration',
'core' => 'Core requirements',
'php' => 'Required PHP modules'
];
$requirementNames = [
'hasCurlLibrary' => 'cURL Web Requests Library',
'hasGdLibrary' => 'GD Graphics Procesisng Library',
'hasMySqlClientLibrary' => 'MySQL PDO Data Access Library',
'maxPostRequestSize' => 'Maximum POST request size (recommended: 4 MB)',
'maxUploadSize' => 'Maximum file size allowed to upload (recommended: 4 MB)',
'php72OrLater' => 'Requires PHP 7.2.0 minimum',
];
$this->view('index', [
'appName' => 'Blue Twilight Installer',
'canInstall' => $canInstall,
'isUpgrade' => $this->isUpgrade,
'requirementGroupNames' => $requirementGroupNames,
'requirementNames' => $requirementNames,
'statusNotMet' => AppRequirements::STATUS_NOT_MET,
'statusOK' => AppRequirements::STATUS_OK,
'statusWarning' => AppRequirements::STATUS_WARNING,
'systemRequirements' => $requirementsGrouped
]);
}
protected function download()
{
$appConfig = require_once sprintf('%s/app.php', $this->configDir);
$servicesConfig = require_once sprintf('%s/services.php', $this->configDir);
$versionNumber = sprintf('v%s', $appConfig['version']);
$versionNumber = sprintf('v%s', $this->versionNumber);
$gitea = new GiteaService($servicesConfig['gitea'], $versionNumber);
$releaseInfo = $gitea->getSpecificRelease($versionNumber);
@ -162,6 +249,8 @@ class Installer
if (file_exists($vendorsTestFile))
{
$this->writeVersionFile();
$this->json([
'result' => true,
'testFile' => $vendorsTestFile
@ -176,10 +265,12 @@ class Installer
protected function finalise()
{
$result = [
'cacheFilesRemoved' => 0,
'envFileCreated' => false
];
$result['envFileCreated'] = $this->createEnvFileIfNotExist();
$result['cacheFilesRemoved'] = $this->clearCacheIfExists();
$result['envFileCreated'] = !$this->isUpgrade && $this->createEnvFileIfNotExist();
require sprintf('%s/bootstrap/autoload.php', $this->rootDir);
@ -222,6 +313,23 @@ class Installer
@fclose($tempFilename);
}
private function clearCacheIfExists()
{
$filesDeleted = 0;
$cacheDir = sprintf('%s/bootstrap/cache', $this->rootDir);
$di = new \DirectoryIterator($cacheDir);
foreach ($di as $fileInfo)
{
if (@unlink($fileInfo->getRealPath()))
{
$filesDeleted++;
}
}
return $filesDeleted;
}
private function createEnvFileIfNotExist()
{
$envFile = $this->getEnvFileName();
@ -255,6 +363,11 @@ class Installer
return sprintf('%s/vendors.tar.gz', $this->tempDir);
}
private function getVendorsVersionFileName()
{
return sprintf('%s/version.txt', $this->vendorDir);
}
private function json($data)
{
echo json_encode($data);
@ -273,4 +386,9 @@ class Installer
require_once $viewFile;
}
private function writeVersionFile()
{
file_put_contents($this->getVendorsVersionFileName(), $this->versionNumber . PHP_EOL);
}
}

View File

@ -1,13 +1,27 @@
<?php
namespace AppInstaller;
function ends_with($stringToCheck, $stringToFind)
{
return strlen($stringToCheck) >= strlen($stringToFind) &&
substr(strtolower($stringToCheck), strlen($stringToCheck) - strlen($stringToFind), strlen($stringToFind)) == strtolower($stringToFind);
}
/**
* A crude implementation of a .env reader to allow the installer to have overriden values from .env.install.
* @param $key
* @param null $default
*/
function env($key, $default = null)
{
$envFilePath = sprintf('%s/.env.install', dirname(__DIR__));
if (!file_exists($envFilePath))
{
return $default;
}
return \App\Helpers\MiscHelper::getEnvironmentSetting($key, $envFilePath) ?? $default;
}
function starts_with($stringToCheck, $stringToFind)
{
return strlen($stringToCheck) >= strlen($stringToFind) &&

View File

@ -4,6 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="../css/blue-twilight.min.css">
<link rel="stylesheet" href="../themes/default/theme.css">
<title><?php echo $appName; ?></title>
<style type="text/css">
* {
@ -12,34 +13,72 @@
</style>
</head>
<body>
<nav class="navbar bg-primary navbar-dark">
<a class="navbar-brand" href="" style="color: #fff;"><i class="fa fa-fw fa-image"></i> Blue Twilight - Install</a>
<div class="collapse navbar-collapse" id="navbar-content">
<ul class="navbar-nav mr-auto">
</ul>
</div>
</nav>
<div class="container" id="bootstrapper">
<h3>Welcome to Blue Twilight - the self-hosted PHP photo gallery.</h3>
<p>Your application/PHP environment have been checked and the results are below. Please correct any failed items before continuing.</p>
<div class="row">
<div class="col-md-8 offset-md-2">
<div class="card">
<div class="card-header">
<p class="mb-0"><?php echo $appName; ?></p>
<div class="mt-4" v-if="!isRunning">
<div class="alert alert-info">
Blue Twilight will automatically download the required third-party libraries when you
click Continue.
</div>
<div class="card-body">
<p class="lead"><b>Welcome to Blue Twilight - the self-hosted PHP photo gallery.</b></p>
<div v-if="!isRunning">
<p>We need to download and install a few more files before you get started.</p>
<p>Click the &quot;Let's Go&quot; button below to begin.</p>
<p class="mb-0 mt-4"><button class="btn btn-primary btn-lg" @click.prevent="bootstrap">Let's Go</button></p>
<?php foreach ($systemRequirements as $groupName => $items): ?>
<div class="card mb-4">
<div class="card-header">
<p class="m-0"><b><?php echo $requirementGroupNames[$groupName]; ?></b></p>
</div>
<div v-else>
<ul v-cloak>
<li class="operation mb-3" v-for="operation in operations">
<div class="status mr-1">
<img src="images/waiting.svg" v-if="!operation.isRunning && !operation.isCompleted"></img>
<img src="images/loading.svg" v-if="operation.isRunning && !operation.isCompleted"/>
<img src="images/completed.svg" v-if="!operation.isRunning && operation.isCompleted"></img>
</div>
<span v-text="operation.name"></span>
</li>
</ul>
<div class="card-body p-0">
<table class="table mb-0">
<tbody>
<?php foreach ($items as $itemName => $result): ?>
<tr>
<td style="width: 75%;"><?php echo $requirementNames[$itemName]; ?></td>
<td style="width: 25%;">
<?php if ($result['result'] == $statusOK): ?>
<i class="fas fa-check text-success mr-2"></i>
<?php elseif ($result['result'] == $statusNotMet): ?>
<i class="fas fa-times text-danger mr-2"></i>
<?php endif; ?>
<?php echo $result['status'] ?? ''; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endforeach; ?>
<?php if ($canInstall): ?>
<p class="mb-0 mt-4 text-right"><button class="btn btn-success" @click.prevent="bootstrap"><i class="fas fa-check"></i> Continue</button></p>
<?php else: ?>
<div class="alert alert-danger">
Blue Twilight cannot be installed until the issues identified above are rectified.
</div>
<?php endif; ?>
</div>
<div class="mt-5" v-else>
<ul v-cloak>
<li class="operation mb-3" v-for="operation in operations">
<div class="status mr-1">
<img src="images/waiting.svg" v-if="!operation.isRunning && !operation.isCompleted"></img>
<img src="images/loading.svg" v-if="operation.isRunning && !operation.isCompleted"/>
<img src="images/completed.svg" v-if="!operation.isRunning && operation.isCompleted"></img>
</div>
<span v-text="operation.name"></span>
</li>
</ul>
</div>
</div>
</div>

View File

@ -5,16 +5,6 @@ $installerDir = sprintf('%s/installer', dirname(dirname(__DIR__)));
require_once sprintf('%s/vendor/autoload.php', $installerDir);
require_once sprintf('%s/helpers.php', $installerDir);
if (!function_exists('env'))
{
// Define a dummy env() function that always returns the default value so we can load the config/app.php file
// to get the current version number
function env($key, $default = null)
{
return $default;
}
}
try
{
$installer = new \AppInstaller\Installer();

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="100px" height="100px"><path fill="#43A047" d="M40.6 12.1L17 35.7 7.4 26.1 4.6 29 17 41.3 43.4 14.9z"/></svg>

After

Width:  |  Height:  |  Size: 175 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="margin: auto; background: none; display: block; shape-rendering: auto;"
width="200px" height="200px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<path d="M10 50A40 40 0 0 0 90 50A40 42 0 0 1 10 50" fill="#1d3f72" stroke="none" transform="rotate(222.794 50 51)">
<animateTransform attributeName="transform" type="rotate" dur="1s" repeatCount="indefinite" keyTimes="0;1" values="0 50 51;360 50 51"></animateTransform>
</path>
<!-- [ldio] generated by https://loading.io/ --></svg>

After

Width:  |  Height:  |  Size: 581 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="100px" height="100px"><path fill="#00acc1" d="M44,24c0,11.044-8.956,20-20,20S4,35.044,4,24S12.956,4,24,4S44,12.956,44,24z"/><path fill="#eee" d="M40,24c0,8.838-7.162,16-16,16S8,32.838,8,24S15.163,8,24,8S40,15.163,40,24z"/><path d="M23 11H25V24H23z"/><path d="M26.082 22.654H28.419V31.846H26.082z" transform="rotate(-45.001 27.25 27.25)"/><path d="M27,24c0,1.657-1.344,3-3,3c-1.657,0-3-1.343-3-3s1.343-3,3-3C25.656,21,27,22.343,27,24"/><path fill="#00acc1" d="M25,24c0,0.551-0.448,1-1,1s-1-0.449-1-1c0-0.553,0.448-1,1-1S25,23.447,25,24"/></svg>

After

Width:  |  Height:  |  Size: 610 B

17
public/update/index.php Normal file
View File

@ -0,0 +1,17 @@
<?php
ini_set('display_errors', 'on');
$installerDir = sprintf('%s/installer', dirname(dirname(__DIR__)));
require_once sprintf('%s/vendor/autoload.php', $installerDir);
require_once sprintf('%s/helpers.php', $installerDir);
try
{
$installer = new \AppInstaller\Installer();
$installer->setIsUpgrade(true);
$installer->handleRequest();
}
catch (\Exception $ex)
{
echo sprintf('ERROR: %s', $ex);
}

View File

@ -1,5 +1,5 @@
<nav class="navbar bg-primary navbar-dark">
<a class="navbar-brand" href="{{ route('install.check') }}" style="color: #fff;"><i class="fa fa-fw fa-image"></i> @lang('installer.app_name')</a>
<a class="navbar-brand" href="{{ route('home') }}" style="color: #fff;"><i class="fa fa-fw fa-image"></i> @lang('installer.app_name')</a>
<div class="collapse navbar-collapse" id="navbar-content">
<ul class="navbar-nav mr-auto">
</ul>

View File

@ -91,8 +91,6 @@ Route::group(['prefix' => 'admin'], function () {
Route::group(['prefix' => 'install'], function () {
Route::get('/administrator', 'InstallController@administrator')->name('install.administrator');
Route::post('/administrator', 'InstallController@administrator')->name('install.administrator');
Route::get('/check', 'InstallController@check')->name('install.check');
Route::post('/check', 'InstallController@check')->name('install.check');
Route::get('/database', 'InstallController@database')->name('install.database');
Route::post('/database', 'InstallController@database')->name('install.database');
});