Implement a better management interface for Settings (#809)

This commit is contained in:
Dane Everitt 2017-12-14 21:05:26 -06:00 committed by GitHub
parent 75eb506dab
commit f9df463d32
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1274 additions and 383 deletions

View file

@ -0,0 +1,32 @@
<?php
namespace Pterodactyl\Contracts\Repository;
interface SettingsRepositoryInterface extends RepositoryInterface
{
/**
* Store a new persistent setting in the database.
*
* @param string $key
* @param string $value
* @return mixed
*/
public function set(string $key, string $value);
/**
* Retrieve a persistent setting from the database.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get(string $key, $default);
/**
* Remove a key from the database cache.
*
* @param string $key
* @return mixed
*/
public function forget(string $key);
}

View file

@ -1,51 +1,25 @@
<?php
/**
* Pterodactyl - Panel
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
*
* This software is licensed under the terms of the MIT license.
* https://opensource.org/licenses/MIT
*/
namespace Pterodactyl\Http\Controllers\Admin;
use Krucas\Settings\Settings;
use Prologue\Alerts\AlertsMessageBag;
use Illuminate\View\View;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Http\Requests\Admin\BaseFormRequest;
use Pterodactyl\Services\Helpers\SoftwareVersionService;
class BaseController extends Controller
{
/**
* @var \Prologue\Alerts\AlertsMessageBag
*/
protected $alert;
/**
* @var \Krucas\Settings\Settings
*/
protected $settings;
/**
* @var \Pterodactyl\Services\Helpers\SoftwareVersionService
*/
protected $version;
private $version;
/**
* BaseController constructor.
*
* @param \Prologue\Alerts\AlertsMessageBag $alert
* @param \Krucas\Settings\Settings $settings
* @param \Pterodactyl\Services\Helpers\SoftwareVersionService $version
*/
public function __construct(
AlertsMessageBag $alert,
Settings $settings,
SoftwareVersionService $version
) {
$this->alert = $alert;
$this->settings = $settings;
public function __construct(SoftwareVersionService $version)
{
$this->version = $version;
}
@ -54,34 +28,8 @@ class BaseController extends Controller
*
* @return \Illuminate\View\View
*/
public function getIndex()
public function index(): View
{
return view('admin.index', ['version' => $this->version]);
}
/**
* Return the admin settings view.
*
* @return \Illuminate\View\View
*/
public function getSettings()
{
return view('admin.settings');
}
/**
* Handle settings post request.
*
* @param \Pterodactyl\Http\Requests\Admin\BaseFormRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function postSettings(BaseFormRequest $request)
{
$this->settings->set('company', $request->input('company'));
$this->settings->set('2fa', $request->input('2fa'));
$this->alert->success('Settings have been successfully updated.')->flash();
return redirect()->route('admin.settings');
}
}

View file

@ -0,0 +1,91 @@
<?php
namespace Pterodactyl\Http\Controllers\Admin\Settings;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Prologue\Alerts\AlertsMessageBag;
use Illuminate\Contracts\Console\Kernel;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Settings\AdvancedSettingsFormRequest;
class AdvancedController extends Controller
{
/**
* @var \Prologue\Alerts\AlertsMessageBag
*/
private $alert;
/**
* @var \Illuminate\Contracts\Config\Repository
*/
private $config;
/**
* @var \Illuminate\Contracts\Console\Kernel
*/
private $kernel;
/**
* @var \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface
*/
private $settings;
/**
* AdvancedController constructor.
*
* @param \Prologue\Alerts\AlertsMessageBag $alert
* @param \Illuminate\Contracts\Config\Repository $config
* @param \Illuminate\Contracts\Console\Kernel $kernel
* @param \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface $settings
*/
public function __construct(
AlertsMessageBag $alert,
ConfigRepository $config,
Kernel $kernel,
SettingsRepositoryInterface $settings
) {
$this->alert = $alert;
$this->config = $config;
$this->kernel = $kernel;
$this->settings = $settings;
}
/**
* Render advanced Panel settings UI.
*
* @return \Illuminate\View\View
*/
public function index(): View
{
$showRecaptchaWarning = false;
if (
$this->config->get('recaptcha._shipped_secret_key') === $this->config->get('recaptcha.secret_key')
|| $this->config->get('recaptcha._shipped_website_key') === $this->config->get('recaptcha.website_key')
) {
$showRecaptchaWarning = true;
}
return view('admin.settings.advanced', [
'showRecaptchaWarning' => $showRecaptchaWarning,
]);
}
/**
* @param \Pterodactyl\Http\Requests\Admin\Settings\AdvancedSettingsFormRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(AdvancedSettingsFormRequest $request): RedirectResponse
{
foreach ($request->normalize() as $key => $value) {
$this->settings->set('settings::' . $key, $value);
}
$this->kernel->call('queue:restart');
$this->alert->success('Advanced settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash();
return redirect()->route('admin.settings.advanced');
}
}

View file

@ -0,0 +1,89 @@
<?php
namespace Pterodactyl\Http\Controllers\Admin\Settings;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Prologue\Alerts\AlertsMessageBag;
use Illuminate\Contracts\Console\Kernel;
use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Traits\Helpers\AvailableLanguages;
use Pterodactyl\Services\Helpers\SoftwareVersionService;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Settings\BaseSettingsFormRequest;
class IndexController extends Controller
{
use AvailableLanguages;
/**
* @var \Prologue\Alerts\AlertsMessageBag
*/
private $alert;
/**
* @var \Illuminate\Contracts\Console\Kernel
*/
private $kernel;
/**
* @var \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface
*/
private $settings;
/**
* @var \Pterodactyl\Services\Helpers\SoftwareVersionService
*/
private $versionService;
/**
* IndexController constructor.
*
* @param \Prologue\Alerts\AlertsMessageBag $alert
* @param \Illuminate\Contracts\Console\Kernel $kernel
* @param \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface $settings
* @param \Pterodactyl\Services\Helpers\SoftwareVersionService $versionService
*/
public function __construct(
AlertsMessageBag $alert,
Kernel $kernel,
SettingsRepositoryInterface $settings,
SoftwareVersionService $versionService)
{
$this->alert = $alert;
$this->kernel = $kernel;
$this->settings = $settings;
$this->versionService = $versionService;
}
/**
* Render the UI for basic Panel settings.
*
* @return \Illuminate\View\View
*/
public function index(): View
{
return view('admin.settings.index', [
'version' => $this->versionService,
'languages' => $this->getAvailableLanguages(true),
]);
}
/**
* Handle settings update.
*
* @param \Pterodactyl\Http\Requests\Admin\Settings\BaseSettingsFormRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function update(BaseSettingsFormRequest $request): RedirectResponse
{
foreach ($request->normalize() as $key => $value) {
$this->settings->set('settings::' . $key, $value);
}
$this->kernel->call('queue:restart');
$this->alert->success('Panel settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash();
return redirect()->route('admin.settings');
}
}

View file

@ -0,0 +1,112 @@
<?php
namespace Pterodactyl\Http\Controllers\Admin\Settings;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Prologue\Alerts\AlertsMessageBag;
use Illuminate\Contracts\Console\Kernel;
use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Http\Controllers\Controller;
use Illuminate\Contracts\Encryption\Encrypter;
use Pterodactyl\Providers\SettingsServiceProvider;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Settings\MailSettingsFormRequest;
class MailController extends Controller
{
/**
* @var \Prologue\Alerts\AlertsMessageBag
*/
private $alert;
/**
* @var \Illuminate\Contracts\Config\Repository
*/
private $config;
/**
* @var \Illuminate\Contracts\Encryption\Encrypter
*/
private $encrypter;
/**
* @var \Illuminate\Contracts\Console\Kernel
*/
private $kernel;
/**
* @var \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface
*/
private $settings;
/**
* MailController constructor.
*
* @param \Prologue\Alerts\AlertsMessageBag $alert
* @param \Illuminate\Contracts\Config\Repository $config
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
* @param \Illuminate\Contracts\Console\Kernel $kernel
* @param \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface $settings
*/
public function __construct(
AlertsMessageBag $alert,
ConfigRepository $config,
Encrypter $encrypter,
Kernel $kernel,
SettingsRepositoryInterface $settings
) {
$this->alert = $alert;
$this->config = $config;
$this->encrypter = $encrypter;
$this->kernel = $kernel;
$this->settings = $settings;
}
/**
* Render UI for editing mail settings. This UI should only display if
* the server is configured to send mail using SMTP.
*
* @return \Illuminate\View\View
*/
public function index(): View
{
return view('admin.settings.mail', [
'disabled' => $this->config->get('mail.driver') !== 'smtp',
]);
}
/**
* Handle request to update SMTP mail settings.
*
* @param \Pterodactyl\Http\Requests\Admin\Settings\MailSettingsFormRequest $request
* @return \Illuminate\Http\RedirectResponse
*
* @throws \Pterodactyl\Exceptions\DisplayException
*/
public function update(MailSettingsFormRequest $request): RedirectResponse
{
if ($this->config->get('mail.driver') !== 'smtp') {
throw new DisplayException('This feature is only available if SMTP is the selected email driver for the Panel.');
}
$values = $request->normalize();
if (array_get($values, 'mail:password') === '!e') {
$values['mail:password'] = '';
}
foreach ($values as $key => $value) {
if (in_array($key, SettingsServiceProvider::getEncryptedKeys()) && ! empty($value)) {
$value = $this->encrypter->encrypt($value);
}
$this->settings->set('settings::' . $key, $value);
}
$this->kernel->call('queue:restart');
$this->alert->success('Mail settings have been updated successfully and the queue worker was restarted to apply these changes.')->flash();
return redirect()->route('admin.settings.mail');
}
}

View file

@ -11,7 +11,6 @@ namespace Pterodactyl\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Krucas\Settings\Settings;
use Prologue\Alerts\AlertsMessageBag;
class RequireTwoFactorAuthentication
@ -25,11 +24,6 @@ class RequireTwoFactorAuthentication
*/
private $alert;
/**
* @var \Krucas\Settings\Settings
*/
private $settings;
/**
* The names of routes that should be accessable without 2FA enabled.
*
@ -56,12 +50,10 @@ class RequireTwoFactorAuthentication
* RequireTwoFactorAuthentication constructor.
*
* @param \Prologue\Alerts\AlertsMessageBag $alert
* @param \Krucas\Settings\Settings $settings
*/
public function __construct(AlertsMessageBag $alert, Settings $settings)
public function __construct(AlertsMessageBag $alert)
{
$this->alert = $alert;
$this->settings = $settings;
}
/**
@ -81,10 +73,7 @@ class RequireTwoFactorAuthentication
return $next($request);
}
switch ((int) $this->settings->get('2fa', 0)) {
case self::LEVEL_NONE:
return $next($request);
break;
switch ((int) config('pterodactyl.auth.2fa_required')) {
case self::LEVEL_ADMIN:
if (! $request->user()->root_admin || $request->user()->use_totp) {
return $next($request);
@ -95,6 +84,9 @@ class RequireTwoFactorAuthentication
return $next($request);
}
break;
case self::LEVEL_NONE:
default:
return $next($request);
}
$this->alert->danger(trans('auth.2fa_must_be_enabled'))->flash();

View file

@ -0,0 +1,42 @@
<?php
namespace Pterodactyl\Http\Requests\Admin\Settings;
use Pterodactyl\Http\Requests\Admin\AdminFormRequest;
class AdvancedSettingsFormRequest extends AdminFormRequest
{
/**
* Return all of the rules to apply to this request's data.
*
* @return array
*/
public function rules()
{
return [
'recaptcha:enabled' => 'required|in:true,false',
'recaptcha:secret_key' => 'required|string|max:255',
'recaptcha:website_key' => 'required|string|max:255',
'pterodactyl:guzzle:timeout' => 'required|integer|between:1,60',
'pterodactyl:guzzle:connect_timeout' => 'required|integer|between:1,60',
'pterodactyl:console:count' => 'required|integer|min:1',
'pterodactyl:console:frequency' => 'required|integer|min:10',
];
}
/**
* @return array
*/
public function attributes()
{
return [
'recaptcha:enabled' => 'reCAPTCHA Enabled',
'recaptcha:secret_key' => 'reCAPTCHA Secret Key',
'recaptcha:website_key' => 'reCAPTCHA Website Key',
'pterodactyl:guzzle:timeout' => 'HTTP Request Timeout',
'pterodactyl:guzzle:connect_timeout' => 'HTTP Connection Timeout',
'pterodactyl:console:count' => 'Console Message Count',
'pterodactyl:console:frequency' => 'Console Frequency Tick',
];
}
}

View file

@ -0,0 +1,36 @@
<?php
namespace Pterodactyl\Http\Requests\Admin\Settings;
use Illuminate\Validation\Rule;
use Pterodactyl\Traits\Helpers\AvailableLanguages;
use Pterodactyl\Http\Requests\Admin\AdminFormRequest;
class BaseSettingsFormRequest extends AdminFormRequest
{
use AvailableLanguages;
/**
* @return array
*/
public function rules()
{
return [
'app:name' => 'required|string|max:255',
'pterodactyl:auth:2fa_required' => 'required|integer|in:0,1,2',
'app:locale' => ['required', 'string', Rule::in(array_keys($this->getAvailableLanguages()))],
];
}
/**
* @return array
*/
public function attributes()
{
return [
'app:name' => 'Company Name',
'pterodactyl:auth:2fa_required' => 'Require 2-Factor Authentication',
'app:locale' => 'Default Language',
];
}
}

View file

@ -0,0 +1,44 @@
<?php
namespace Pterodactyl\Http\Requests\Admin\Settings;
use Pterodactyl\Http\Requests\Admin\AdminFormRequest;
class MailSettingsFormRequest extends AdminFormRequest
{
/**
* Return rules to validate mail settings POST data aganist.
*
* @return array
*/
public function rules()
{
return [
'mail:host' => 'required|string',
'mail:port' => 'required|integer|between:1,65535',
'mail:encryption' => 'present|string|in:"",tls,ssl',
'mail:username' => 'string|max:255',
'mail:password' => 'string|max:255',
'mail:from:address' => 'required|string|email',
'mail:from:name' => 'string|max:255',
];
}
/**
* Override the default normalization function for this type of request
* as we need to accept empty values on the keys.
*
* @param array $only
* @return array
*/
public function normalize($only = [])
{
$keys = array_flip(array_keys($this->rules()));
if (empty($this->input('mail:password'))) {
unset($keys['mail:password']);
}
return $this->only(array_flip($keys));
}
}

39
app/Models/Setting.php Normal file
View file

@ -0,0 +1,39 @@
<?php
namespace Pterodactyl\Models;
use Sofa\Eloquence\Eloquence;
use Sofa\Eloquence\Validable;
use Illuminate\Database\Eloquent\Model;
use Sofa\Eloquence\Contracts\CleansAttributes;
use Sofa\Eloquence\Contracts\Validable as ValidableContract;
class Setting extends Model implements CleansAttributes, ValidableContract
{
use Eloquence, Validable;
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'settings';
/**
* @var bool
*/
public $timestamps = false;
/**
* @var array
*/
protected $fillable = ['key', 'value'];
/**
* @var array
*/
protected static $applicationRules = [
'key' => 'required|string|between:1,255',
'value' => 'string',
];
}

View file

@ -13,7 +13,6 @@ use Pterodactyl\Observers\UserObserver;
use Pterodactyl\Observers\ServerObserver;
use Pterodactyl\Observers\SubuserObserver;
use Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider;
use DaneEveritt\LoginNotifications\NotificationServiceProvider;
use Barryvdh\Debugbar\ServiceProvider as DebugbarServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -42,10 +41,6 @@ class AppServiceProvider extends ServiceProvider
$this->app->register(DebugbarServiceProvider::class);
$this->app->register(IdeHelperServiceProvider::class);
}
if (config('pterodactyl.auth.notifications')) {
$this->app->register(NotificationServiceProvider::class);
}
}
/**

View file

@ -26,6 +26,7 @@ use Pterodactyl\Repositories\Eloquent\SubuserRepository;
use Pterodactyl\Repositories\Eloquent\DatabaseRepository;
use Pterodactyl\Repositories\Eloquent\LocationRepository;
use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
use Pterodactyl\Repositories\Eloquent\SettingsRepository;
use Pterodactyl\Repositories\Eloquent\DaemonKeyRepository;
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
use Pterodactyl\Repositories\Eloquent\PermissionRepository;
@ -47,6 +48,7 @@ use Pterodactyl\Contracts\Repository\SubuserRepositoryInterface;
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
use Pterodactyl\Contracts\Repository\DaemonKeyRepositoryInterface;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Contracts\Repository\PermissionRepositoryInterface;
@ -86,10 +88,13 @@ class RepositoryServiceProvider extends ServiceProvider
$this->app->bind(ServerRepositoryInterface::class, ServerRepository::class);
$this->app->bind(ServerVariableRepositoryInterface::class, ServerVariableRepository::class);
$this->app->bind(SessionRepositoryInterface::class, SessionRepository::class);
$this->app->bind(SettingsRepositoryInterface::class, SettingsRepository::class);
$this->app->bind(SubuserRepositoryInterface::class, SubuserRepository::class);
$this->app->bind(TaskRepositoryInterface::class, TaskRepository::class);
$this->app->bind(UserRepositoryInterface::class, UserRepository::class);
$this->app->alias(SettingsRepositoryInterface::class, 'settings');
// Daemon Repositories
if ($this->app->make('config')->get('pterodactyl.daemon.use_new_daemon')) {
$this->app->bind(ConfigurationRepositoryInterface::class, \Pterodactyl\Repositories\Wings\ConfigurationRepository::class);

View file

@ -0,0 +1,101 @@
<?php
namespace Pterodactyl\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\Encryption\Encrypter;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
class SettingsServiceProvider extends ServiceProvider
{
/**
* An array of configuration keys to override with database values
* if they exist.
*
* @var array
*/
protected $keys = [
'app:name',
'app:locale',
'recaptcha:enabled',
'recaptcha:secret_key',
'recaptcha:website_key',
'pterodactyl:guzzle:timeout',
'pterodactyl:guzzle:connect_timeout',
'pterodactyl:console:count',
'pterodactyl:console:frequency',
'pterodactyl:auth:2fa_required',
];
/**
* Keys specific to the mail driver that are only grabbed from the database
* when using the SMTP driver.
*
* @var array
*/
protected $emailKeys = [
'mail:host',
'mail:port',
'mail:from:address',
'mail:from:name',
'mail:encryption',
'mail:username',
'mail:password',
];
/**
* Keys that are encrypted and should be decrypted when set in the
* configuration array.
*
* @var array
*/
protected static $encrypted = [
'mail:password',
];
/**
* Boot the service provider.
*
* @param \Illuminate\Contracts\Config\Repository $config
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
* @param \Pterodactyl\Contracts\Repository\SettingsRepositoryInterface $settings
*/
public function boot(ConfigRepository $config, Encrypter $encrypter, SettingsRepositoryInterface $settings)
{
if ($config->get('pterodactyl.load_environment_only', false)) {
return;
}
// Only set the email driver settings from the database if we
// are configured using SMTP as the driver.
if ($config->get('mail.driver') === 'smtp') {
$this->keys = array_merge($this->keys, $this->emailKeys);
}
$values = $settings->all()->mapWithKeys(function ($setting) {
return [$setting->key => $setting->value];
})->toArray();
foreach ($this->keys as $key) {
$value = array_get($values, 'settings::' . $key, $config->get(str_replace(':', '.', $key)));
if (in_array($key, self::$encrypted)) {
try {
$value = $encrypter->decrypt($value);
} catch (DecryptException $exception) {
}
}
$config->set(str_replace(':', '.', $key), $value);
}
}
/**
* @return array
*/
public static function getEncryptedKeys(): array
{
return self::$encrypted;
}
}

View file

@ -0,0 +1,96 @@
<?php
namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Setting;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
class SettingsRepository extends EloquentRepository implements SettingsRepositoryInterface
{
/**
* @var array
*/
private $cache = [];
/**
* @var array
*/
private $databaseMiss = [];
/**
* Return an instance of the model that acts as the base for
* this repository.
*
* @return string
*/
public function model()
{
return Setting::class;
}
/**
* Store a new persistent setting in the database.
*
* @param string $key
* @param string $value
*/
public function set(string $key, string $value)
{
// Clear item from the cache.
$this->clearCache($key);
$this->withoutFresh()->updateOrCreate(['key' => $key], ['value' => $value]);
}
/**
* Retrieve a persistent setting from the database.
*
* @param string $key
* @param mixed $default
* @return mixed
*/
public function get(string $key, $default = null)
{
// If item has already been requested return it from the cache. If
// we already know it is missing, immediately return the default
// value.
if (array_key_exists($key, $this->cache)) {
return $this->cache[$key];
} elseif (array_key_exists($key, $this->databaseMiss)) {
return $default;
}
$instance = $this->getBuilder()->where('key', $key)->first();
if (is_null($instance)) {
$this->databaseMiss[$key] = true;
return $default;
}
$this->cache[$key] = $instance->value;
return $this->cache[$key];
}
/**
* Remove a key from the database cache.
*
* @param string $key
* @return mixed
*/
public function forget(string $key)
{
$this->clearCache($key);
$this->deleteWhere(['key' => $key]);
}
/**
* Remove a key from the cache.
*
* @param string $key
*/
protected function clearCache(string $key)
{
unset($this->cache[$key], $this->databaseMiss[$key]);
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace Pterodactyl\Traits\Helpers;
use Matriphe\ISO639\ISO639;
use Illuminate\Filesystem\Filesystem;
trait AvailableLanguages
{
/**
* @var \Illuminate\Filesystem\Filesystem
*/
private $filesystem;
/**
* @var \Matriphe\ISO639\ISO639
*/
private $iso639;
/**
* Return all of the available languages on the Panel based on those
* that are present in the language folder.
*
* @param bool $localize
* @return array
*/
public function getAvailableLanguages($localize = false): array
{
return collect($this->getFilesystemInstance()->directories(resource_path('lang')))->mapWithKeys(function ($path) use ($localize) {
$code = basename($path);
$value = $localize ? $this->getIsoInstance()->nativeByCode1($code) : $this->getIsoInstance()->languageByCode1($code);
return [$code => title_case($value)];
})->toArray();
}
/**
* Return an instance of the filesystem for getting a folder listing.
*
* @return \Illuminate\Filesystem\Filesystem
*/
private function getFilesystemInstance(): Filesystem
{
return $this->filesystem = $this->filesystem ?: app()->make(Filesystem::class);
}
/**
* Return an instance of the ISO639 class for generating names.
*
* @return \Matriphe\ISO639\ISO639
*/
private function getIsoInstance(): ISO639
{
return $this->iso639 = $this->iso639 ?: app()->make(ISO639::class);
}
}