session()->get('install_stage')) < $stage) { return redirect(route('install.check')); } // If we already have an admin account, this step can be skipped $canSkip = User::where('is_admin', true)->count() > 0; if ($canSkip && $request->has('skip')) { return $this->completeSetup(); } if ($request->method() == 'POST') { $user = new User(); $user->name = $request->get('name'); $user->email = $request->get('email'); $user->password = bcrypt($request->get('password')); $user->is_admin = true; $user->is_activated = true; $user->enable_profile_page = true; $user->save(); return $this->completeSetup(); } return view('install.administrator', [ 'can_skip' => $canSkip ]); } 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')); } if ($request->method() == 'POST') { $baseDirectory = dirname(dirname(dirname(__DIR__))); $data = [ sprintf('APP_KEY=%s', config('app.key')), 'DB_CONNECTION=mysql', sprintf('DB_HOST=%s', $request->get('mysql-server')), sprintf('DB_PORT=%s', intval($request->get('mysql-port'))), sprintf('DB_DATABASE=%s', $request->get('mysql-database')), sprintf('DB_USERNAME=%s', $request->get('mysql-username')), sprintf('DB_PASSWORD=%s', $request->get('mysql-password')) ]; file_put_contents(sprintf('%s/.env', $baseDirectory), join(PHP_EOL, $data) . PHP_EOL); // Update the in-memory configuration ready for Artisan :) $configData = [ 'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'host' => $request->get('mysql-server'), 'port' => intval($request->get('mysql-port')), 'database' => $request->get('mysql-database'), 'username' => $request->get('mysql-username'), 'password' => $request->get('mysql-password') ] ] ]; config(['database' => array_replace_recursive(config('database'), $configData)]); try { DB::reconnect(); Artisan::call('cache:clear'); Artisan::call('migrate', ['--force' => true]); Artisan::call('db:seed', ['--force' => true]); $versionNumber = UserConfig::getOrCreateModel('app_version'); $versionNumber->value = config('app.version'); $versionNumber->save(); // Default settings $this->setConfigurationForNewSystems(); $request->session()->put('install_stage', 3); return redirect(route('install.administrator')); } catch (\Exception $ex) { $request->session()->flash('database_error', $ex->getMessage()); return redirect(route('install.database')) ->withInput($request->input()); } } return view('install.database', [ 'database_error' => $request->session()->get('database_error') ]); } private function completeSetup() { // Flag as installed MiscHelper::setEnvironmentSetting('APP_INSTALLED', true); // Switch to database sessions (more reliable) MiscHelper::setEnvironmentSetting('SESSION_DRIVER', 'database'); // Add an internal storage if it doesn't already exist $this->createInternalStorageLocationIfNotExist(); // Skip forward. If you go past Go, collect £200! return redirect(route('home', ['install_completed' => true])); } private function createInternalStorageLocationIfNotExist() { $storage = Storage::where('is_internal', true)->first(); if (is_null($storage)) { $location = sprintf('%s/storage/app/albums', dirname(dirname(dirname(__DIR__)))); $storage = new Storage(); $storage->name = trans('installer.default_storage_name'); $storage->is_active = true; $storage->is_default = true; $storage->is_internal = true; $storage->location = $location; $storage->source = 'LocalFilesystemSource'; $storage->save(); // Try and create the physical location if (!file_exists($location)) { @mkdir($location); } } } private function setDefaultAnonymousPermission($section, $permission) { $permission = Permission::where([ ['section', $section], ['description', $permission] ])->first(); if (is_null($permission)) { return; } $adap = new AlbumDefaultAnonymousPermission(); $adap->permission_id = $permission->id; $adap->save(); } private function setConfigurationForNewSystems() { /** @var Configuration $socialFeeds */ $socialFeeds = UserConfig::getOrCreateModel('social_user_feeds'); $socialFeeds->value = true; $socialFeeds->save(); /** @var Configuration $socialProfiles */ $socialProfiles = UserConfig::getOrCreateModel('social_user_profiles'); $socialProfiles->value = true; $socialProfiles->save(); /** @var Configuration $photoComments */ $photoComments = UserConfig::getOrCreateModel('allow_photo_comments'); $photoComments->value = true; $photoComments->save(); $defaultPermissions = ['album.list', 'album.view', 'album.post-comment']; foreach ($defaultPermissions as $defaultPermission) { $permissionParts = explode('.', $defaultPermission); $this->setDefaultAnonymousPermission($permissionParts[0], $permissionParts[1]); } } }