安装引导程序

This commit is contained in:
TL 2022-08-12 18:13:38 +08:00
parent 7b53d76a43
commit 77197021cd
30 changed files with 1918 additions and 0 deletions

View File

@ -49,6 +49,11 @@ class Kernel extends HttpKernel
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'installer' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,

View File

@ -0,0 +1,35 @@
<?php
namespace Beike\Installer\Controllers;
use Illuminate\Routing\Controller;
use RachidLaasri\LaravelInstaller\Helpers\DatabaseManager;
class DatabaseController extends Controller
{
/**
* @var DatabaseManager
*/
private $databaseManager;
/**
* @param DatabaseManager $databaseManager
*/
public function __construct(DatabaseManager $databaseManager)
{
$this->databaseManager = $databaseManager;
}
/**
* Migrate and seed the database.
*
* @return \Illuminate\View\View
*/
public function index()
{
$response = $this->databaseManager->migrateAndSeed();
return redirect()->route('installer.final')
->with(['message' => $response]);
}
}

View File

@ -0,0 +1,112 @@
<?php
namespace Beike\Installer\Controllers;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\DB;
use RachidLaasri\LaravelInstaller\Events\EnvironmentSaved;
use RachidLaasri\LaravelInstaller\Helpers\EnvironmentManager;
use Validator;
class EnvironmentController extends Controller
{
/**
* @var EnvironmentManager
*/
protected $EnvironmentManager;
/**
* @param EnvironmentManager $environmentManager
*/
public function __construct(EnvironmentManager $environmentManager)
{
$this->EnvironmentManager = $environmentManager;
}
/**
* Display the Environment page.
*
* @return \Illuminate\View\View
*/
public function index()
{
return view('installer::environment-wizard');
}
/**
* Processes the newly saved environment configuration (Form Wizard).
*
* @param Request $request
* @param Redirector $redirect
* @return \Illuminate\Http\RedirectResponse
*/
public function saveWizard(Request $request, Redirector $redirect)
{
$rules = config('installer.environment.form.rules');
$messages = [
'environment_custom.required_if' => trans('installer_messages.environment.wizard.form.name_required'),
];
$validator = Validator::make($request->all(), $rules, $messages);
if ($validator->fails()) {
return $redirect->route('installer.environment')->withInput()->withErrors($validator->errors());
}
if (! $this->checkDatabaseConnection($request)) {
return $redirect->route('installer.environment')->withInput()->withErrors([
'database_connection' => trans('installer_messages.environment.wizard.form.db_connection_failed'),
]);
}
$results = $this->EnvironmentManager->saveFileWizard($request);
event(new EnvironmentSaved($request));
return $redirect->route('installer.database')
->with(['results' => $results]);
}
/**
* TODO: We can remove this code if PR will be merged: https://github.com/RachidLaasri/LaravelInstaller/pull/162
* Validate database connection with user credentials (Form Wizard).
*
* @param Request $request
* @return bool
*/
private function checkDatabaseConnection(Request $request)
{
$connection = $request->input('database_connection');
$settings = config("database.connections.$connection");
config([
'database' => [
'default' => $connection,
'connections' => [
$connection => array_merge($settings, [
'driver' => $connection,
'host' => $request->input('database_hostname'),
'port' => $request->input('database_port'),
'database' => $request->input('database_name'),
'username' => $request->input('database_username'),
'password' => $request->input('database_password'),
]),
],
],
]);
DB::purge();
try {
DB::connection()->getPdo();
return true;
} catch (Exception $e) {
return false;
}
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Beike\Installer\Controllers;
use Illuminate\Routing\Controller;
use RachidLaasri\LaravelInstaller\Events\LaravelInstallerFinished;
use RachidLaasri\LaravelInstaller\Helpers\EnvironmentManager;
use RachidLaasri\LaravelInstaller\Helpers\FinalInstallManager;
use RachidLaasri\LaravelInstaller\Helpers\InstalledFileManager;
class FinalController extends Controller
{
/**
* Update installed file and display finished view.
*
* @param \RachidLaasri\LaravelInstaller\Helpers\InstalledFileManager $fileManager
* @param \RachidLaasri\LaravelInstaller\Helpers\FinalInstallManager $finalInstall
* @param \RachidLaasri\LaravelInstaller\Helpers\EnvironmentManager $environment
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(InstalledFileManager $fileManager, FinalInstallManager $finalInstall, EnvironmentManager $environment)
{
$finalMessages = $finalInstall->runFinal();
$finalStatusMessage = $fileManager->update();
$finalEnvFile = $environment->getEnvContent();
event(new LaravelInstallerFinished);
return view('installer::finished', compact('finalMessages', 'finalStatusMessage', 'finalEnvFile'));
}
}

View File

@ -0,0 +1,36 @@
<?php
namespace Beike\Installer\Controllers;
use Illuminate\Routing\Controller;
use RachidLaasri\LaravelInstaller\Helpers\PermissionsChecker;
class PermissionsController extends Controller
{
/**
* @var PermissionsChecker
*/
protected $permissions;
/**
* @param PermissionsChecker $checker
*/
public function __construct(PermissionsChecker $checker)
{
$this->permissions = $checker;
}
/**
* Display the permissions check page.
*
* @return \Illuminate\View\View
*/
public function index()
{
$permissions = $this->permissions->check(
config('installer.permissions')
);
return view('installer::permissions', compact('permissions'));
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace Beike\Installer\Controllers;
use Illuminate\Routing\Controller;
use Beike\Installer\Helpers\RequirementsChecker;
class RequirementsController extends Controller
{
/**
* @var RequirementsChecker
*/
protected $requirements;
/**
* @param RequirementsChecker $checker
*/
public function __construct(RequirementsChecker $checker)
{
$this->requirements = $checker;
}
/**
* Display the requirements page.
*
* @return \Illuminate\View\View
*/
public function index()
{
$phpSupportInfo = $this->requirements->checkPHPversion(
config('installer.core.minPhpVersion')
);
$requirements = $this->requirements->check(
config('installer.requirements')
);
return view('installer::requirements', compact('requirements', 'phpSupportInfo'));
}
}

View File

@ -0,0 +1,23 @@
<?php
/**
* WelcomeController.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-08-12 20:17:04
* @modified 2022-08-12 20:17:04
*/
namespace Beike\Installer\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class WelcomeController extends Controller
{
public function index()
{
return view('installer::welcome');
}
}

View File

@ -0,0 +1,95 @@
<?php
namespace Beike\Installer\Helpers;
use Exception;
use Illuminate\Database\SQLiteConnection;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Console\Output\BufferedOutput;
class DatabaseManager
{
/**
* Migrate and seed the database.
*
* @return array
*/
public function migrateAndSeed()
{
$outputLog = new BufferedOutput;
$this->sqlite($outputLog);
return $this->migrate($outputLog);
}
/**
* Run the migration and call the seeder.
*
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
* @return array
*/
private function migrate(BufferedOutput $outputLog)
{
try {
Artisan::call('migrate', ['--force'=> true], $outputLog);
} catch (Exception $e) {
return $this->response($e->getMessage(), 'error', $outputLog);
}
return $this->seed($outputLog);
}
/**
* Seed the database.
*
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
* @return array
*/
private function seed(BufferedOutput $outputLog)
{
try {
Artisan::call('db:seed', ['--force' => true], $outputLog);
} catch (Exception $e) {
return $this->response($e->getMessage(), 'error', $outputLog);
}
return $this->response(trans('installer_messages.final.finished'), 'success', $outputLog);
}
/**
* Return a formatted error messages.
*
* @param string $message
* @param string $status
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
* @return array
*/
private function response($message, $status, BufferedOutput $outputLog)
{
return [
'status' => $status,
'message' => $message,
'dbOutputLog' => $outputLog->fetch(),
];
}
/**
* Check database type. If SQLite, then create the database file.
*
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
*/
private function sqlite(BufferedOutput $outputLog)
{
if (DB::connection() instanceof SQLiteConnection) {
$database = DB::connection()->getDatabaseName();
if (! file_exists($database)) {
touch($database);
DB::reconnect(Config::get('database.default'));
}
$outputLog->write('Using SqlLite database: '.$database, 1);
}
}
}

View File

@ -0,0 +1,135 @@
<?php
namespace Beike\Installer\Helpers;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class EnvironmentManager
{
/**
* @var string
*/
private $envPath;
/**
* @var string
*/
private $envExamplePath;
/**
* Set the .env and .env.example paths.
*/
public function __construct()
{
$this->envPath = base_path('.env');
$this->envExamplePath = base_path('.env.example');
}
/**
* Get the content of the .env file.
*
* @return string
*/
public function getEnvContent()
{
if (! file_exists($this->envPath)) {
if (file_exists($this->envExamplePath)) {
copy($this->envExamplePath, $this->envPath);
} else {
touch($this->envPath);
}
}
return file_get_contents($this->envPath);
}
/**
* Get the the .env file path.
*
* @return string
*/
public function getEnvPath()
{
return $this->envPath;
}
/**
* Get the the .env.example file path.
*
* @return string
*/
public function getEnvExamplePath()
{
return $this->envExamplePath;
}
/**
* Save the edited content to the .env file.
*
* @param Request $input
* @return string
*/
public function saveFileClassic(Request $input)
{
$message = trans('installer_messages.environment.success');
try {
file_put_contents($this->envPath, $input->get('envConfig'));
} catch (Exception $e) {
$message = trans('installer_messages.environment.errors');
}
return $message;
}
/**
* Save the form content to the .env file.
*
* @param Request $request
* @return string
*/
public function saveFileWizard(Request $request)
{
$results = trans('installer_messages.environment.success');
$envFileData =
'APP_NAME=\''.$request->app_name."'\n".
'APP_ENV='.$request->environment."\n".
'APP_KEY='.'base64:'.base64_encode(Str::random(32))."\n".
'APP_DEBUG='.$request->app_debug."\n".
'APP_LOG_LEVEL='.$request->app_log_level."\n".
'APP_URL='.$request->app_url."\n\n".
'DB_CONNECTION='.$request->database_connection."\n".
'DB_HOST='.$request->database_hostname."\n".
'DB_PORT='.$request->database_port."\n".
'DB_DATABASE='.$request->database_name."\n".
'DB_USERNAME='.$request->database_username."\n".
'DB_PASSWORD='.$request->database_password."\n\n".
'BROADCAST_DRIVER='.$request->broadcast_driver."\n".
'CACHE_DRIVER='.$request->cache_driver."\n".
'SESSION_DRIVER='.$request->session_driver."\n".
'QUEUE_DRIVER='.$request->queue_driver."\n\n".
'REDIS_HOST='.$request->redis_hostname."\n".
'REDIS_PASSWORD='.$request->redis_password."\n".
'REDIS_PORT='.$request->redis_port."\n\n".
'MAIL_DRIVER='.$request->mail_driver."\n".
'MAIL_HOST='.$request->mail_host."\n".
'MAIL_PORT='.$request->mail_port."\n".
'MAIL_USERNAME='.$request->mail_username."\n".
'MAIL_PASSWORD='.$request->mail_password."\n".
'MAIL_ENCRYPTION='.$request->mail_encryption."\n\n".
'PUSHER_APP_ID='.$request->pusher_app_id."\n".
'PUSHER_APP_KEY='.$request->pusher_app_key."\n".
'PUSHER_APP_SECRET='.$request->pusher_app_secret;
try {
file_put_contents($this->envPath, $envFileData);
} catch (Exception $e) {
$results = trans('installer_messages.environment.errors');
}
return $results;
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace Beike\Installer\Helpers;
use Exception;
use Illuminate\Support\Facades\Artisan;
use Symfony\Component\Console\Output\BufferedOutput;
class FinalInstallManager
{
/**
* Run final commands.
*
* @return string
*/
public function runFinal()
{
$outputLog = new BufferedOutput;
$this->generateKey($outputLog);
$this->publishVendorAssets($outputLog);
return $outputLog->fetch();
}
/**
* Generate New Application Key.
*
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
* @return \Symfony\Component\Console\Output\BufferedOutput|array
*/
private static function generateKey(BufferedOutput $outputLog)
{
try {
if (config('installer.final.key')) {
Artisan::call('key:generate', ['--force'=> true], $outputLog);
}
} catch (Exception $e) {
return static::response($e->getMessage(), $outputLog);
}
return $outputLog;
}
/**
* Publish vendor assets.
*
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
* @return \Symfony\Component\Console\Output\BufferedOutput|array
*/
private static function publishVendorAssets(BufferedOutput $outputLog)
{
try {
if (config('installer.final.publish')) {
Artisan::call('vendor:publish', ['--all' => true], $outputLog);
}
} catch (Exception $e) {
return static::response($e->getMessage(), $outputLog);
}
return $outputLog;
}
/**
* Return a formatted error messages.
*
* @param $message
* @param \Symfony\Component\Console\Output\BufferedOutput $outputLog
* @return array
*/
private static function response($message, BufferedOutput $outputLog)
{
return [
'status' => 'error',
'message' => $message,
'dbOutputLog' => $outputLog->fetch(),
];
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace Beike\Installer\Helpers;
class InstalledFileManager
{
/**
* Create installed file.
*
* @return int
*/
public function create()
{
$installedLogFile = storage_path('installed');
$dateStamp = date('Y/m/d h:i:sa');
if (! file_exists($installedLogFile)) {
$message = trans('installer_messages.installed.success_log_message').$dateStamp."\n";
file_put_contents($installedLogFile, $message);
} else {
$message = trans('installer_messages.updater.log.success_message').$dateStamp;
file_put_contents($installedLogFile, $message.PHP_EOL, FILE_APPEND | LOCK_EX);
}
return $message;
}
/**
* Update installed file.
*
* @return int
*/
public function update()
{
return $this->create();
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace Beike\Installer\Helpers;
use Illuminate\Support\Facades\DB;
trait MigrationsHelper
{
/**
* Get the migrations in /database/migrations.
*
* @return array Array of migrations name, empty if no migrations are existing
*/
public function getMigrations()
{
$migrations = glob(database_path().DIRECTORY_SEPARATOR.'migrations'.DIRECTORY_SEPARATOR.'*.php');
return str_replace('.php', '', $migrations);
}
/**
* Get the migrations that have already been ran.
*
* @return \Illuminate\Support\Collection List of migrations
*/
public function getExecutedMigrations()
{
// migrations table should exist, if not, user will receive an error.
return DB::table('migrations')->get()->pluck('migration');
}
}

View File

@ -0,0 +1,83 @@
<?php
namespace Beike\Installer\Helpers;
class PermissionsChecker
{
/**
* @var array
*/
protected $results = [];
/**
* Set the result array permissions and errors.
*
* @return mixed
*/
public function __construct()
{
$this->results['permissions'] = [];
$this->results['errors'] = null;
}
/**
* Check for the folders permissions.
*
* @param array $folders
* @return array
*/
public function check(array $folders)
{
foreach ($folders as $folder => $permission) {
if (! ($this->getPermission($folder) >= $permission)) {
$this->addFileAndSetErrors($folder, $permission, false);
} else {
$this->addFile($folder, $permission, true);
}
}
return $this->results;
}
/**
* Get a folder permission.
*
* @param $folder
* @return string
*/
private function getPermission($folder)
{
return substr(sprintf('%o', fileperms(base_path($folder))), -4);
}
/**
* Add the file to the list of results.
*
* @param $folder
* @param $permission
* @param $isSet
*/
private function addFile($folder, $permission, $isSet)
{
array_push($this->results['permissions'], [
'folder' => $folder,
'permission' => $permission,
'isSet' => $isSet,
]);
}
/**
* Add the file and set the errors.
*
* @param $folder
* @param $permission
* @param $isSet
*/
private function addFileAndSetErrors($folder, $permission, $isSet)
{
$this->addFile($folder, $permission, $isSet);
$this->results['errors'] = true;
}
}

View File

@ -0,0 +1,114 @@
<?php
namespace Beike\Installer\Helpers;
class RequirementsChecker
{
/**
* Minimum PHP Version Supported (Override is in installer.php config file).
*
* @var _minPhpVersion
*/
private $_minPhpVersion = '7.0.0';
/**
* Check for the server requirements.
*
* @param array $requirements
* @return array
*/
public function check(array $requirements)
{
$results = [];
foreach ($requirements as $type => $requirement) {
switch ($type) {
// check php requirements
case 'php':
foreach ($requirements[$type] as $requirement) {
$results['requirements'][$type][$requirement] = true;
if (! extension_loaded($requirement)) {
$results['requirements'][$type][$requirement] = false;
$results['errors'] = true;
}
}
break;
// check apache requirements
case 'apache':
foreach ($requirements[$type] as $requirement) {
// if function doesn't exist we can't check apache modules
if (function_exists('apache_get_modules')) {
$results['requirements'][$type][$requirement] = true;
if (! in_array($requirement, apache_get_modules())) {
$results['requirements'][$type][$requirement] = false;
$results['errors'] = true;
}
}
}
break;
}
}
return $results;
}
/**
* Check PHP version requirement.
*
* @return array
*/
public function checkPHPversion(string $minPhpVersion = null)
{
$minVersionPhp = $minPhpVersion;
$currentPhpVersion = $this->getPhpVersionInfo();
$supported = false;
if ($minPhpVersion == null) {
$minVersionPhp = $this->getMinPhpVersion();
}
if (version_compare($currentPhpVersion['version'], $minVersionPhp) >= 0) {
$supported = true;
}
$phpStatus = [
'full' => $currentPhpVersion['full'],
'current' => $currentPhpVersion['version'],
'minimum' => $minVersionPhp,
'supported' => $supported,
];
return $phpStatus;
}
/**
* Get current Php version information.
*
* @return array
*/
private static function getPhpVersionInfo()
{
$currentVersionFull = PHP_VERSION;
preg_match("#^\d+(\.\d+)*#", $currentVersionFull, $filtered);
$currentVersion = $filtered[0];
return [
'full' => $currentVersionFull,
'version' => $currentVersion,
];
}
/**
* Get minimum PHP version ID.
*
* @return string _minPhpVersion
*/
protected function getMinPhpVersion()
{
return $this->_minPhpVersion;
}
}

View File

@ -0,0 +1,23 @@
<?php
if (! function_exists('isActive')) {
/**
* Set the active class to the current opened menu.
*
* @param string|array $route
* @param string $className
* @return string
*/
function isActive($route, $className = 'active')
{
if (is_array($route)) {
return in_array(Route::currentRouteName(), $route) ? $className : '';
}
if (Route::currentRouteName() == $route) {
return $className;
}
if (strpos(URL::current(), $route)) {
return $className;
}
}
}

View File

@ -0,0 +1,247 @@
<?php
return [
/*
*
* Shared translations.
*
*/
'title' => 'Laravel Installer',
'next' => 'Next Step',
'back' => 'Previous',
'finish' => 'Install',
'forms' => [
'errorTitle' => 'The Following errors occurred:',
],
/*
*
* Home page translations.
*
*/
'welcome' => [
'templateTitle' => 'Welcome',
'title' => 'Laravel Installer',
'message' => 'Easy Installation and Setup Wizard.',
'next' => 'Check Requirements',
],
/*
*
* Requirements page translations.
*
*/
'requirements' => [
'templateTitle' => 'Step 1 | Server Requirements',
'title' => 'Server Requirements',
'next' => 'Check Permissions',
],
/*
*
* Permissions page translations.
*
*/
'permissions' => [
'templateTitle' => 'Step 2 | Permissions',
'title' => 'Permissions',
'next' => 'Configure Environment',
],
/*
*
* Environment page translations.
*
*/
'environment' => [
'menu' => [
'templateTitle' => 'Step 3 | Environment Settings',
'title' => 'Environment Settings',
'desc' => 'Please select how you want to configure the apps <code>.env</code> file.',
'wizard-button' => 'Form Wizard Setup',
'classic-button' => 'Classic Text Editor',
],
'wizard' => [
'templateTitle' => 'Step 3 | Environment Settings | Guided Wizard',
'title' => 'Guided <code>.env</code> Wizard',
'tabs' => [
'environment' => 'Environment',
'database' => 'Database',
'application' => 'Application',
],
'form' => [
'name_required' => 'An environment name is required.',
'app_name_label' => 'App Name',
'app_name_placeholder' => 'App Name',
'app_environment_label' => 'App Environment',
'app_environment_label_local' => 'Local',
'app_environment_label_developement' => 'Development',
'app_environment_label_qa' => 'Qa',
'app_environment_label_production' => 'Production',
'app_environment_label_other' => 'Other',
'app_environment_placeholder_other' => 'Enter your environment...',
'app_debug_label' => 'App Debug',
'app_debug_label_true' => 'True',
'app_debug_label_false' => 'False',
'app_log_level_label' => 'App Log Level',
'app_log_level_label_debug' => 'debug',
'app_log_level_label_info' => 'info',
'app_log_level_label_notice' => 'notice',
'app_log_level_label_warning' => 'warning',
'app_log_level_label_error' => 'error',
'app_log_level_label_critical' => 'critical',
'app_log_level_label_alert' => 'alert',
'app_log_level_label_emergency' => 'emergency',
'app_url_label' => 'App Url',
'app_url_placeholder' => 'App Url',
'db_connection_failed' => 'Could not connect to the database.',
'db_connection_label' => 'Database Connection',
'db_connection_label_mysql' => 'mysql',
'db_connection_label_sqlite' => 'sqlite',
'db_connection_label_pgsql' => 'pgsql',
'db_connection_label_sqlsrv' => 'sqlsrv',
'db_host_label' => 'Database Host',
'db_host_placeholder' => 'Database Host',
'db_port_label' => 'Database Port',
'db_port_placeholder' => 'Database Port',
'db_name_label' => 'Database Name',
'db_name_placeholder' => 'Database Name',
'db_username_label' => 'Database User Name',
'db_username_placeholder' => 'Database User Name',
'db_password_label' => 'Database Password',
'db_password_placeholder' => 'Database Password',
'app_tabs' => [
'more_info' => 'More Info',
'broadcasting_title' => 'Broadcasting, Caching, Session, &amp; Queue',
'broadcasting_label' => 'Broadcast Driver',
'broadcasting_placeholder' => 'Broadcast Driver',
'cache_label' => 'Cache Driver',
'cache_placeholder' => 'Cache Driver',
'session_label' => 'Session Driver',
'session_placeholder' => 'Session Driver',
'queue_label' => 'Queue Driver',
'queue_placeholder' => 'Queue Driver',
'redis_label' => 'Redis Driver',
'redis_host' => 'Redis Host',
'redis_password' => 'Redis Password',
'redis_port' => 'Redis Port',
'mail_label' => 'Mail',
'mail_driver_label' => 'Mail Driver',
'mail_driver_placeholder' => 'Mail Driver',
'mail_host_label' => 'Mail Host',
'mail_host_placeholder' => 'Mail Host',
'mail_port_label' => 'Mail Port',
'mail_port_placeholder' => 'Mail Port',
'mail_username_label' => 'Mail Username',
'mail_username_placeholder' => 'Mail Username',
'mail_password_label' => 'Mail Password',
'mail_password_placeholder' => 'Mail Password',
'mail_encryption_label' => 'Mail Encryption',
'mail_encryption_placeholder' => 'Mail Encryption',
'pusher_label' => 'Pusher',
'pusher_app_id_label' => 'Pusher App Id',
'pusher_app_id_palceholder' => 'Pusher App Id',
'pusher_app_key_label' => 'Pusher App Key',
'pusher_app_key_palceholder' => 'Pusher App Key',
'pusher_app_secret_label' => 'Pusher App Secret',
'pusher_app_secret_palceholder' => 'Pusher App Secret',
],
'buttons' => [
'setup_database' => 'Setup Database',
'setup_application' => 'Setup Application',
'install' => 'Install',
],
],
],
'classic' => [
'templateTitle' => 'Step 3 | Environment Settings | Classic Editor',
'title' => 'Classic Environment Editor',
'save' => 'Save .env',
'back' => 'Use Form Wizard',
'install' => 'Save and Install',
],
'success' => 'Your .env file settings have been saved.',
'errors' => 'Unable to save the .env file, Please create it manually.',
],
'install' => 'Install',
/*
*
* Installed Log translations.
*
*/
'installed' => [
'success_log_message' => 'Laravel Installer successfully INSTALLED on ',
],
/*
*
* Final page translations.
*
*/
'final' => [
'title' => 'Installation Finished',
'templateTitle' => 'Installation Finished',
'finished' => 'Application has been successfully installed.',
'migration' => 'Migration &amp; Seed Console Output:',
'console' => 'Application Console Output:',
'log' => 'Installation Log Entry:',
'env' => 'Final .env File:',
'exit' => 'Click here to exit',
],
/*
*
* Update specific translations
*
*/
'updater' => [
/*
*
* Shared translations.
*
*/
'title' => 'Laravel Updater',
/*
*
* Welcome page translations for update feature.
*
*/
'welcome' => [
'title' => 'Welcome To The Updater',
'message' => 'Welcome to the update wizard.',
],
/*
*
* Welcome page translations for update feature.
*
*/
'overview' => [
'title' => 'Overview',
'message' => 'There is 1 update.|There are :number updates.',
'install_updates' => 'Install Updates',
],
/*
*
* Final page translations.
*
*/
'final' => [
'title' => 'Finished',
'finished' => 'Application\'s database has been successfully updated.',
'exit' => 'Click here to exit',
],
'log' => [
'success_message' => 'Laravel Installer successfully UPDATED on ',
],
],
];

View File

@ -0,0 +1,64 @@
<?php
return [
/*
*
* Shared translations.
*
*/
'title' => 'Laravel安装程序',
'next' => '下一步',
'finish' => '安装',
/*
*
* Home page translations.
*
*/
'welcome' => [
'title' => '欢迎来到Laravel安装程序',
'message' => '欢迎来到安装向导.',
],
/*
*
* Requirements page translations.
*
*/
'requirements' => [
'title' => '环境要求',
],
/*
*
* Permissions page translations.
*
*/
'permissions' => [
'title' => '权限',
],
/*
*
* Environment page translations.
*
*/
'environment' => [
'title' => '环境设置',
'save' => '保存 .env',
'success' => '.env 文件保存成功.',
'errors' => '无法保存 .env 文件, 请手动创建它.',
],
/*
*
* Final page translations.
*
*/
'final' => [
'title' => '完成',
'finished' => '应用已成功安装.',
'exit' => '点击退出',
],
];

View File

@ -0,0 +1,29 @@
<?php
namespace Beike\Installer\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
class InstallerServiceProvider extends ServiceProvider
{
/**
* @throws \Exception
*/
public function boot()
{
$this->loadRoutesFrom(__DIR__ . '/../Routes/installer.php');
$uri = request()->getRequestUri();
if (!Str::startsWith($uri, "/installer")) {
return;
}
$this->mergeConfigFrom(__DIR__ . '/../config.php', 'installer');
$this->loadViewsFrom(__DIR__ . '/../views', 'installer');
$pathInstaller = base_path('installer');
$this->loadTranslationsFrom("{$pathInstaller}/Lang", '');
}
}

View File

@ -0,0 +1,22 @@
<?php
use Beike\Installer\Controllers\DatabaseController;
use Beike\Installer\Controllers\EnvironmentController;
use Beike\Installer\Controllers\FinalController;
use Beike\Installer\Controllers\PermissionsController;
use Beike\Installer\Controllers\RequirementsController;
use Beike\Installer\Controllers\WelcomeController;
Route::prefix('installer')
->name('installer.')
->middleware(['installer'])
->group(function () {
Route::get('/', [WelcomeController::class, 'index'])->name('welcome');
Route::get('requirements', [RequirementsController::class, 'index'])->name('requirements');
Route::get('permissions', [PermissionsController::class, 'index'])->name('permissions');
Route::get('environment', [EnvironmentController::class, 'index'])->name('environment');
Route::post('environment/save', [EnvironmentController::class, 'saveWizard'])->name('environment.save');
Route::get('database', [DatabaseController::class, 'index'])->name('database');
Route::get('final', [FinalController::class, 'index'])->name('final');
});

View File

@ -0,0 +1,167 @@
@extends('vendor.installer.layouts.master')
@section('template_title')
{{ trans('installer_messages.environment.wizard.templateTitle') }}
@endsection
@section('title')
<i class="fa fa-magic fa-fw" aria-hidden="true"></i>
{!! trans('installer_messages.environment.wizard.title') !!}
@endsection
@section('container')
<div class="tabs tabs-full">
<input id="tab1" type="radio" name="tabs" class="tab-input" checked />
<label for="tab1" class="tab-label">
<i class="fa fa-cog fa-2x fa-fw" aria-hidden="true"></i>
<br />
{{ trans('installer_messages.environment.wizard.tabs.environment') }}
</label>
<input id="tab2" type="radio" name="tabs" class="tab-input" />
<label for="tab2" class="tab-label">
<i class="fa fa-database fa-2x fa-fw" aria-hidden="true"></i>
<br />
{{ trans('installer_messages.environment.wizard.tabs.database') }}
</label>
<form method="post" action="{{ route('installer.environment.save') }}" class="tabs-wrap">
<div class="tab" id="tab1content">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group {{ $errors->has('app_url') ? ' has-error ' : '' }}">
<label for="app_url">
{{ trans('installer_messages.environment.wizard.form.app_url_label') }}
</label>
<input type="url" name="app_url" id="app_url" value="http://localhost" placeholder="{{ trans('installer_messages.environment.wizard.form.app_url_placeholder') }}" />
@if ($errors->has('app_url'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('app_url') }}
</span>
@endif
</div>
<div class="buttons">
<button class="button" onclick="showDatabaseSettings();return false">
{{ trans('installer_messages.environment.wizard.form.buttons.setup_database') }}
<i class="fa fa-angle-right fa-fw" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="tab" id="tab2content">
<div class="form-group {{ $errors->has('database_connection') ? ' has-error ' : '' }}">
<label for="database_connection">
{{ trans('installer_messages.environment.wizard.form.db_connection_label') }}
</label>
<select name="database_connection" id="database_connection">
<option value="mysql" selected>{{ trans('installer_messages.environment.wizard.form.db_connection_label_mysql') }}</option>
<option value="sqlite">{{ trans('installer_messages.environment.wizard.form.db_connection_label_sqlite') }}</option>
<option value="pgsql">{{ trans('installer_messages.environment.wizard.form.db_connection_label_pgsql') }}</option>
<option value="sqlsrv">{{ trans('installer_messages.environment.wizard.form.db_connection_label_sqlsrv') }}</option>
</select>
@if ($errors->has('database_connection'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('database_connection') }}
</span>
@endif
</div>
<div class="form-group {{ $errors->has('database_hostname') ? ' has-error ' : '' }}">
<label for="database_hostname">
{{ trans('installer_messages.environment.wizard.form.db_host_label') }}
</label>
<input type="text" name="database_hostname" id="database_hostname" value="127.0.0.1" placeholder="{{ trans('installer_messages.environment.wizard.form.db_host_placeholder') }}" />
@if ($errors->has('database_hostname'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('database_hostname') }}
</span>
@endif
</div>
<div class="form-group {{ $errors->has('database_port') ? ' has-error ' : '' }}">
<label for="database_port">
{{ trans('installer_messages.environment.wizard.form.db_port_label') }}
</label>
<input type="number" name="database_port" id="database_port" value="3306" placeholder="{{ trans('installer_messages.environment.wizard.form.db_port_placeholder') }}" />
@if ($errors->has('database_port'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('database_port') }}
</span>
@endif
</div>
<div class="form-group {{ $errors->has('database_name') ? ' has-error ' : '' }}">
<label for="database_name">
{{ trans('installer_messages.environment.wizard.form.db_name_label') }}
</label>
<input type="text" name="database_name" id="database_name" value="" placeholder="{{ trans('installer_messages.environment.wizard.form.db_name_placeholder') }}" />
@if ($errors->has('database_name'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('database_name') }}
</span>
@endif
</div>
<div class="form-group {{ $errors->has('database_username') ? ' has-error ' : '' }}">
<label for="database_username">
{{ trans('installer_messages.environment.wizard.form.db_username_label') }}
</label>
<input type="text" name="database_username" id="database_username" value="" placeholder="{{ trans('installer_messages.environment.wizard.form.db_username_placeholder') }}" />
@if ($errors->has('database_username'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('database_username') }}
</span>
@endif
</div>
<div class="form-group {{ $errors->has('database_password') ? ' has-error ' : '' }}">
<label for="database_password">
{{ trans('installer_messages.environment.wizard.form.db_password_label') }}
</label>
<input type="password" name="database_password" id="database_password" value="" placeholder="{{ trans('installer_messages.environment.wizard.form.db_password_placeholder') }}" />
@if ($errors->has('database_password'))
<span class="error-block">
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ $errors->first('database_password') }}
</span>
@endif
</div>
<div class="buttons">
<button class="button" onclick="showApplicationSettings();return false">
{{ trans('installer_messages.environment.wizard.form.buttons.setup_application') }}
<i class="fa fa-angle-right fa-fw" aria-hidden="true"></i>
</button>
</div>
</div>
</form>
</div>
@endsection
@section('scripts')
<script type="text/javascript">
function checkEnvironment(val) {
var element=document.getElementById('environment_text_input');
if(val=='other') {
element.style.display='block';
} else {
element.style.display='none';
}
}
function showDatabaseSettings() {
document.getElementById('tab2').checked = true;
}
function showApplicationSettings() {
document.getElementById('tab3').checked = true;
}
</script>
@endsection

View File

@ -0,0 +1,32 @@
@extends('vendor.installer.layouts.master')
@section('template_title')
{{ trans('installer_messages.final.templateTitle') }}
@endsection
@section('title')
<i class="fa fa-flag-checkered fa-fw" aria-hidden="true"></i>
{{ trans('installer_messages.final.title') }}
@endsection
@section('container')
@if(session('message')['dbOutputLog'])
<p><strong><small>{{ trans('installer_messages.final.migration') }}</small></strong></p>
<pre><code>{{ session('message')['dbOutputLog'] }}</code></pre>
@endif
<p><strong><small>{{ trans('installer_messages.final.console') }}</small></strong></p>
<pre><code>{{ $finalMessages }}</code></pre>
<p><strong><small>{{ trans('installer_messages.final.log') }}</small></strong></p>
<pre><code>{{ $finalStatusMessage }}</code></pre>
<p><strong><small>{{ trans('installer_messages.final.env') }}</small></strong></p>
<pre><code>{{ $finalEnvFile }}</code></pre>
<div class="buttons">
<a href="{{ url('/') }}" class="button">{{ trans('installer_messages.final.exit') }}</a>
</div>
@endsection

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>@if (trim($__env->yieldContent('template_title')))@yield('template_title') | @endif {{ trans('installer_messages.updater.title') }}</title>
<link rel="icon" type="image/png" href="{{ asset('installer/img/favicon/favicon-16x16.png') }}" sizes="16x16"/>
<link rel="icon" type="image/png" href="{{ asset('installer/img/favicon/favicon-32x32.png') }}" sizes="32x32"/>
<link rel="icon" type="image/png" href="{{ asset('installer/img/favicon/favicon-96x96.png') }}" sizes="96x96"/>
<link href="{{ asset('installer/css/style.min.css') }}" rel="stylesheet"/>
@yield('style')
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
</head>
<body>
<div class="master">
<div class="box">
<div class="header">
<h1 class="header__title">@yield('title')</h1>
</div>
<ul class="step">
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelUpdater::final') }}">
<i class="step__icon fa fa-database" aria-hidden="true"></i>
</li>
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelUpdater::overview') }}">
<i class="step__icon fa fa-reorder" aria-hidden="true"></i>
</li>
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelUpdater::welcome') }}">
<i class="step__icon fa fa-refresh" aria-hidden="true"></i>
</li>
<li class="step__divider"></li>
</ul>
<div class="main">
@yield('container')
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,114 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@if (trim($__env->yieldContent('template_title')))@yield('template_title') | @endif {{ trans('installer_messages.title') }}</title>
<link rel="icon" type="image/png" href="{{ asset('installer/img/favicon/favicon-16x16.png') }}" sizes="16x16"/>
<link rel="icon" type="image/png" href="{{ asset('installer/img/favicon/favicon-32x32.png') }}" sizes="32x32"/>
<link rel="icon" type="image/png" href="{{ asset('installer/img/favicon/favicon-96x96.png') }}" sizes="96x96"/>
<link href="{{ asset('installer/css/style.min.css') }}" rel="stylesheet"/>
@yield('style')
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
</head>
<body>
<div class="master">
<div class="box">
<div class="header">
<h1 class="header__title">@yield('title')</h1>
</div>
<ul class="step">
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelInstaller::final') }}">
<i class="step__icon fa fa-server" aria-hidden="true"></i>
</li>
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelInstaller::environment')}} {{ isActive('LaravelInstaller::environmentWizard')}} {{ isActive('LaravelInstaller::environmentClassic')}}">
@if(Request::is('install/environment') || Request::is('install/environment/wizard') || Request::is('install/environment/classic') )
<a href="{{ route('LaravelInstaller::environment') }}">
<i class="step__icon fa fa-cog" aria-hidden="true"></i>
</a>
@else
<i class="step__icon fa fa-cog" aria-hidden="true"></i>
@endif
</li>
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelInstaller::permissions') }}">
@if(Request::is('install/permissions') || Request::is('install/environment') || Request::is('install/environment/wizard') || Request::is('install/environment/classic') )
<a href="{{ route('LaravelInstaller::permissions') }}">
<i class="step__icon fa fa-key" aria-hidden="true"></i>
</a>
@else
<i class="step__icon fa fa-key" aria-hidden="true"></i>
@endif
</li>
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelInstaller::requirements') }}">
@if(Request::is('install') || Request::is('install/requirements') || Request::is('install/permissions') || Request::is('install/environment') || Request::is('install/environment/wizard') || Request::is('install/environment/classic') )
<a href="{{ route('LaravelInstaller::requirements') }}">
<i class="step__icon fa fa-list" aria-hidden="true"></i>
</a>
@else
<i class="step__icon fa fa-list" aria-hidden="true"></i>
@endif
</li>
<li class="step__divider"></li>
<li class="step__item {{ isActive('LaravelInstaller::welcome') }}">
@if(Request::is('install') || Request::is('install/requirements') || Request::is('install/permissions') || Request::is('install/environment') || Request::is('install/environment/wizard') || Request::is('install/environment/classic') )
<a href="{{ route('LaravelInstaller::welcome') }}">
<i class="step__icon fa fa-home" aria-hidden="true"></i>
</a>
@else
<i class="step__icon fa fa-home" aria-hidden="true"></i>
@endif
</li>
<li class="step__divider"></li>
</ul>
<div class="main">
@if (session('message'))
<p class="alert text-center">
<strong>
@if(is_array(session('message')))
{{ session('message')['message'] }}
@else
{{ session('message') }}
@endif
</strong>
</p>
@endif
@if(session()->has('errors'))
<div class="alert alert-danger" id="error_alert">
<button type="button" class="close" id="close_alert" data-dismiss="alert" aria-hidden="true">
<i class="fa fa-close" aria-hidden="true"></i>
</button>
<h4>
<i class="fa fa-fw fa-exclamation-triangle" aria-hidden="true"></i>
{{ trans('installer_messages.forms.errorTitle') }}
</h4>
<ul>
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@yield('container')
</div>
</div>
</div>
@yield('scripts')
<script type="text/javascript">
var x = document.getElementById('error_alert');
var y = document.getElementById('close_alert');
y.onclick = function() {
x.style.display = "none";
};
</script>
</body>
</html>

View File

@ -0,0 +1,35 @@
@extends('installer::layouts.master')
@section('template_title')
{{ trans('installer_messages.permissions.templateTitle') }}
@endsection
@section('title')
<i class="fa fa-key fa-fw" aria-hidden="true"></i>
{{ trans('installer_messages.permissions.title') }}
@endsection
@section('container')
<ul class="list">
@foreach($permissions['permissions'] as $permission)
<li class="list__item list__item--permissions {{ $permission['isSet'] ? 'success' : 'error' }}">
{{ $permission['folder'] }}
<span>
<i class="fa fa-fw fa-{{ $permission['isSet'] ? 'check-circle-o' : 'exclamation-circle' }}"></i>
{{ $permission['permission'] }}
</span>
</li>
@endforeach
</ul>
@if ( ! isset($permissions['errors']))
<div class="buttons">
<a href="{{ route('installer.environment') }}" class="button">
{{ trans('installer_messages.permissions.next') }}
<i class="fa fa-angle-right fa-fw" aria-hidden="true"></i>
</a>
</div>
@endif
@endsection

View File

@ -0,0 +1,50 @@
@extends('installer::layouts.master')
@section('template_title')
{{ trans('installer_messages.requirements.templateTitle') }}
@endsection
@section('title')
<i class="fa fa-list-ul fa-fw" aria-hidden="true"></i>
{{ trans('installer_messages.requirements.title') }}
@endsection
@section('container')
@foreach($requirements['requirements'] as $type => $requirement)
<ul class="list">
<li class="list__item list__title {{ $phpSupportInfo['supported'] ? 'success' : 'error' }}">
<strong>{{ ucfirst($type) }}</strong>
@if($type == 'php')
<strong>
<small>
(version {{ $phpSupportInfo['minimum'] }} required)
</small>
</strong>
<span class="float-right">
<strong>
{{ $phpSupportInfo['current'] }}
</strong>
<i class="fa fa-fw fa-{{ $phpSupportInfo['supported'] ? 'check-circle-o' : 'exclamation-circle' }} row-icon" aria-hidden="true"></i>
</span>
@endif
</li>
@foreach($requirements['requirements'][$type] as $extention => $enabled)
<li class="list__item {{ $enabled ? 'success' : 'error' }}">
{{ $extention }}
<i class="fa fa-fw fa-{{ $enabled ? 'check-circle-o' : 'exclamation-circle' }} row-icon" aria-hidden="true"></i>
</li>
@endforeach
</ul>
@endforeach
@if ( ! isset($requirements['errors']) && $phpSupportInfo['supported'] )
<div class="buttons">
<a class="button" href="{{ route('installer.permissions') }}">
{{ trans('installer_messages.requirements.next') }}
<i class="fa fa-angle-right fa-fw" aria-hidden="true"></i>
</a>
</div>
@endif
@endsection

View File

@ -0,0 +1,21 @@
@extends('installer::layouts.master')
@section('template_title')
{{ trans('installer_messages.welcome.templateTitle') }}
@endsection
@section('title')
{{ trans('installer_messages.welcome.title') }}
@endsection
@section('container')
<p class="text-center">
{{ trans('installer_messages.welcome.message') }}
</p>
<p class="text-center">
<a href="{{ route('installer.requirements') }}" class="button">
{{ trans('installer_messages.welcome.next') }}
<i class="fa fa-angle-right fa-fw" aria-hidden="true"></i>
</a>
</p>
@endsection

129
beike/Installer/config.php Normal file
View File

@ -0,0 +1,129 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Server Requirements
|--------------------------------------------------------------------------
|
| This is the default Laravel server requirements, you can add as many
| as your application require, we check if the extension is enabled
| by looping through the array and run "extension_loaded" on it.
|
*/
'core' => [
'minPhpVersion' => '7.0.0',
],
'final' => [
'key' => true,
'publish' => false,
],
'requirements' => [
'php' => [
'openssl',
'pdo',
'mbstring',
'tokenizer',
'JSON',
'cURL',
],
'apache' => [
'mod_rewrite',
],
],
/*
|--------------------------------------------------------------------------
| Folders Permissions
|--------------------------------------------------------------------------
|
| This is the default Laravel folders permissions, if your application
| requires more permissions just add them to the array list bellow.
|
*/
'permissions' => [
'storage/framework/' => '775',
'storage/logs/' => '775',
'bootstrap/cache/' => '775',
],
/*
|--------------------------------------------------------------------------
| Environment Form Wizard Validation Rules & Messages
|--------------------------------------------------------------------------
|
| This are the default form field validation rules. Available Rules:
| https://laravel.com/docs/5.4/validation#available-validation-rules
|
*/
'environment' => [
'form' => [
'rules' => [
'app_url' => 'required|url',
'database_connection' => 'required|string|max:50',
'database_hostname' => 'required|string|max:50',
'database_port' => 'required|numeric',
'database_name' => 'required|string|max:50',
'database_username' => 'required|string|max:50',
'database_password' => 'nullable|string|max:50',
'mail_driver' => 'required|string|max:50',
'mail_host' => 'required|string|max:50',
'mail_port' => 'required|string|max:50',
'mail_username' => 'required|string|max:50',
'mail_password' => 'required|string|max:50',
'mail_encryption' => 'required|string|max:50',
'pusher_app_id' => 'max:50',
'pusher_app_key' => 'max:50',
'pusher_app_secret' => 'max:50',
],
],
],
/*
|--------------------------------------------------------------------------
| Installed Middleware Options
|--------------------------------------------------------------------------
| Different available status switch configuration for the
| canInstall middleware located in `canInstall.php`.
|
*/
'installed' => [
'redirectOptions' => [
'route' => [
'name' => 'welcome',
'data' => [],
],
'abort' => [
'type' => '404',
],
'dump' => [
'data' => 'Dumping a not found message.',
],
],
],
/*
|--------------------------------------------------------------------------
| Selected Installed Middleware Option
|--------------------------------------------------------------------------
| The selected option fo what happens when an installer instance has been
| Default output is to `/resources/views/error/404.blade.php` if none.
| The available middleware options include:
| route, abort, dump, 404, default, ''
|
*/
'installedAlreadyAction' => '',
/*
|--------------------------------------------------------------------------
| Updater Enabled
|--------------------------------------------------------------------------
| Can the application run the '/update' route with the migrations.
| The default option is set to False if none is present.
| Boolean value
|
*/
'updaterEnabled' => 'true',
];

View File

@ -0,0 +1,39 @@
<?php
/**
* LoginController.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-06-22 20:22:54
* @modified 2022-06-22 20:22:54
*/
namespace Beike\Shop\Http\Controllers;
use Beike\Models\Customer;
use Illuminate\Http\Request;
class LoginController extends Controller
{
public function index()
{
return view('login');
}
public function store(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (auth(Customer::AUTH_GUARD)->attempt($credentials)) {
return redirect(route('home'));
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
}

View File

@ -178,6 +178,7 @@ return [
Beike\Admin\Providers\AdminServiceProvider::class,
Beike\Shop\Providers\ShopServiceProvider::class,
Beike\Shop\Providers\PluginServiceProvider::class,
Beike\Installer\Providers\InstallerServiceProvider::class,
],

View File

@ -0,0 +1,41 @@
@extends('layout.master')
@section('content')
<h1>Login</h1>
<form action="{{ route('shop.login.store') }}" method="post">
@csrf
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="email">邮箱</span>
</div>
<input type="text" name="email" class="form-control" value="{{ old('email') }}" placeholder="邮箱地址">
</div>
@error('email')
<x-admin::form.error :message="$message" />
@enderror
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="password">密码</span>
</div>
<input type="password" name="password" class="form-control" placeholder="密码">
</div>
@error('password')
<x-admin::form.error :message="$message" />
@enderror
</div>
@if (session('error'))
<div class="alert alert-success">
{{ session('error') }}
</div>
@endif
<button type="submit" class="btn btn-primary btn-block mb-4">登录</button>
</form>
@endsection