Merge pull request 'Improved Bootstrap experience and services improvements' (#154) from feature/146-bootstrap-experience into master
This commit is contained in:
commit
e95967b3b0
@ -1,7 +1,7 @@
|
||||
APP_ENV=local
|
||||
APP_ENV=production
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_LOG_LEVEL=debug
|
||||
APP_DEBUG=false
|
||||
APP_LOG_LEVEL=warning
|
||||
APP_URL=http://localhost
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
|
30
Gruntfile.js
30
Gruntfile.js
@ -14,7 +14,9 @@ module.exports = function(grunt)
|
||||
const sass = require('node-sass');
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-curl');
|
||||
grunt.loadNpmTasks('grunt-dart-sass');
|
||||
grunt.loadNpmTasks('grunt-exec');
|
||||
@ -97,6 +99,23 @@ module.exports = function(grunt)
|
||||
ext: '.css'
|
||||
}]
|
||||
},
|
||||
},
|
||||
cssmin: {
|
||||
bt_css: {
|
||||
files: {
|
||||
'public/css/blue-twilight.min.css': ['public/css/blue-twilight.css']
|
||||
}
|
||||
}
|
||||
},
|
||||
uglify: {
|
||||
bt_js: {
|
||||
options: {
|
||||
sourceMap: true
|
||||
},
|
||||
files: {
|
||||
'public/js/blue-twilight.min.js': ['public/js/blue-twilight.js']
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -121,7 +140,18 @@ module.exports = function(grunt)
|
||||
'concat:bt_js'
|
||||
]);
|
||||
|
||||
grunt.registerTask('build-css-release', [
|
||||
'build-css-debug',
|
||||
'cssmin:bt_css'
|
||||
]);
|
||||
|
||||
grunt.registerTask('build-js-release', [
|
||||
'build-js-debug',
|
||||
'uglify:bt_js'
|
||||
]);
|
||||
|
||||
// Shortcut tasks for the ones above
|
||||
grunt.registerTask('clean-all', ['clean:build_css', 'clean:build_js', 'clean:output']);
|
||||
grunt.registerTask('build-debug', ['clean-all', 'build-css-debug', 'build-js-debug']);
|
||||
grunt.registerTask('build-release', ['clean-all', 'build-css-release', 'build-js-release']);
|
||||
};
|
@ -16,7 +16,7 @@ class ExternalService extends Model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = ['name', 'service_type'];
|
||||
protected $fillable = ['name', 'service_type', 'app_id', 'app_secret'];
|
||||
|
||||
/**
|
||||
* Gets all possible service configurations for the given service type.
|
||||
@ -28,19 +28,27 @@ class ExternalService extends Model
|
||||
return ExternalService::where('service_type', $serviceType)->get();
|
||||
}
|
||||
|
||||
public function hasOAuthStandardOptions()
|
||||
{
|
||||
// This logic must be mirrored in external_services.js
|
||||
return in_array($this->service_type, [
|
||||
self::FACEBOOK,
|
||||
self::GOOGLE,
|
||||
self::TWITTER
|
||||
]);
|
||||
}
|
||||
|
||||
public function isDropbox()
|
||||
{
|
||||
// This logic must be mirrored in external_services.js
|
||||
return $this->service_type == self::DROPBOX;
|
||||
}
|
||||
|
||||
public function isFacebook()
|
||||
{
|
||||
// This logic must be mirrored in external_services.js
|
||||
return $this->service_type == self::FACEBOOK;
|
||||
}
|
||||
|
||||
public function isGoogle()
|
||||
{
|
||||
// This logic must be mirrored in external_services.js
|
||||
return $this->service_type == self::GOOGLE;
|
||||
}
|
||||
|
||||
public function isTwitter()
|
||||
{
|
||||
// This logic must be mirrored in external_services.js
|
||||
return $this->service_type == self::TWITTER;
|
||||
}
|
||||
}
|
@ -113,10 +113,8 @@ class ConfigHelper
|
||||
'date_format' => $this->allowedDateFormats()[0],
|
||||
'default_album_view' => $this->allowedAlbumViews()[0],
|
||||
'enable_visitor_hits' => false,
|
||||
'facebook_app_id' => '',
|
||||
'facebook_app_secret' => '',
|
||||
'google_app_id' => '',
|
||||
'google_app_secret' => '',
|
||||
'facebook_external_service_id' => 0,
|
||||
'google_external_service_id' => 0,
|
||||
'hotlink_protection' => false,
|
||||
'items_per_page' => 12,
|
||||
'items_per_page_admin' => 10,
|
||||
@ -151,8 +149,7 @@ class ConfigHelper
|
||||
'social_user_feeds' => false,
|
||||
'social_user_profiles' => false,
|
||||
'theme' => 'default',
|
||||
'twitter_app_id' => '',
|
||||
'twitter_app_secret' => '',
|
||||
'twitter_external_service_id' => 0
|
||||
);
|
||||
}
|
||||
|
||||
@ -219,11 +216,29 @@ class ConfigHelper
|
||||
!empty($this->get('rabbitmq_vhost'));
|
||||
}
|
||||
|
||||
public function isLoginWithFacebookEnabled()
|
||||
{
|
||||
return boolval($this->get('social_facebook_login')) &&
|
||||
intval($this->get('facebook_external_service_id')) > 0;
|
||||
}
|
||||
|
||||
public function isLoginWithGoogleEnabled()
|
||||
{
|
||||
return boolval($this->get('social_google_login')) &&
|
||||
intval($this->get('google_external_service_id')) > 0;
|
||||
}
|
||||
|
||||
public function isLoginWithTwitterEnabled()
|
||||
{
|
||||
return boolval($this->get('social_twitter_login')) &&
|
||||
intval($this->get('twitter_external_service_id')) > 0;
|
||||
}
|
||||
|
||||
public function isSocialMediaLoginEnabled()
|
||||
{
|
||||
return $this->get('social_facebook_login') ||
|
||||
$this->get('social_twitter_login') ||
|
||||
$this->get('social_google_login');
|
||||
return $this->isLoginWithFacebookEnabled() ||
|
||||
$this->isLoginWithGoogleEnabled() ||
|
||||
$this->isLoginWithTwitterEnabled();
|
||||
}
|
||||
|
||||
private function loadCache()
|
||||
|
@ -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))
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Album;
|
||||
use App\ExternalService;
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Group;
|
||||
@ -260,10 +261,8 @@ class DefaultController extends Controller
|
||||
'analysis_queue_storage_location',
|
||||
'app_name',
|
||||
'date_format',
|
||||
'facebook_app_id',
|
||||
'facebook_app_secret',
|
||||
'google_app_id',
|
||||
'google_app_secret',
|
||||
'facebook_external_service_id',
|
||||
'google_external_service_id',
|
||||
'photo_comments_allowed_html',
|
||||
'photo_comments_thread_depth',
|
||||
'rabbitmq_server',
|
||||
@ -279,8 +278,7 @@ class DefaultController extends Controller
|
||||
'smtp_username',
|
||||
'smtp_password',
|
||||
'theme',
|
||||
'twitter_app_id',
|
||||
'twitter_app_secret',
|
||||
'twitter_external_service_id',
|
||||
'recaptcha_site_key',
|
||||
'recaptcha_secret_key',
|
||||
'analytics_code'
|
||||
@ -374,12 +372,30 @@ class DefaultController extends Controller
|
||||
// Storage sources for the Image Processing tab
|
||||
$storageSources = AnalysisQueueHelper::getCompatibleStorages();
|
||||
|
||||
// External services
|
||||
$externalServices = ExternalService::all();
|
||||
$facebookServices = $externalServices->filter(function (ExternalService $item)
|
||||
{
|
||||
return $item->service_type == ExternalService::FACEBOOK;
|
||||
});
|
||||
$googleServices = $externalServices->filter(function (ExternalService $item)
|
||||
{
|
||||
return $item->service_type == ExternalService::GOOGLE;
|
||||
});
|
||||
$twitterServices = $externalServices->filter(function (ExternalService $item)
|
||||
{
|
||||
return $item->service_type == ExternalService::TWITTER;
|
||||
});
|
||||
|
||||
return Theme::render('admin.settings', [
|
||||
'config' => $config,
|
||||
'date_formats' => $dateFormatsLookup,
|
||||
'facebookServices' => $facebookServices,
|
||||
'googleServices' => $googleServices,
|
||||
'storage_sources' => $storageSources,
|
||||
'success' => $request->session()->get('success'),
|
||||
'theme_names' => $themeNamesLookup
|
||||
'theme_names' => $themeNamesLookup,
|
||||
'twitterServices' => $twitterServices
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Configuration;
|
||||
use App\ExternalService;
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
@ -90,14 +91,30 @@ class ServiceController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->authorizeAccessToAdminPanel('admin:manage-services');
|
||||
|
||||
$serviceTypes = $this->serviceTypeList();
|
||||
$selectedServiceType = old('service_type', $request->get('service_type'));
|
||||
|
||||
if (!array_key_exists($selectedServiceType, $serviceTypes))
|
||||
{
|
||||
$selectedServiceType = '';
|
||||
}
|
||||
|
||||
$returnTo = old('return_to', $request->get('return_to'));
|
||||
if (!array_key_exists($returnTo, $this->validReturnLocations()))
|
||||
{
|
||||
$returnTo = '';
|
||||
}
|
||||
|
||||
return Theme::render('admin.create_service', [
|
||||
'callbackUrls' => $this->callbackList(),
|
||||
'returnTo' => $returnTo,
|
||||
'selectedServiceType' => $selectedServiceType,
|
||||
'service' => new ExternalService(),
|
||||
'serviceTypes' => $this->serviceTypeList()
|
||||
'serviceTypes' => $serviceTypes
|
||||
]);
|
||||
}
|
||||
|
||||
@ -236,6 +253,14 @@ class ServiceController extends Controller
|
||||
|
||||
$service->save();
|
||||
|
||||
$returnToLocations = $this->validReturnLocations();
|
||||
$returnTo = $request->get('return_to');
|
||||
|
||||
if (array_key_exists($returnTo, $returnToLocations))
|
||||
{
|
||||
return redirect($returnToLocations[$returnTo]);
|
||||
}
|
||||
|
||||
return redirect(route('services.index'));
|
||||
}
|
||||
|
||||
@ -278,14 +303,37 @@ class ServiceController extends Controller
|
||||
$dropboxService = new DropboxService();
|
||||
|
||||
return [
|
||||
ExternalService::DROPBOX => $dropboxService->callbackUrl()
|
||||
ExternalService::DROPBOX => $dropboxService->callbackUrl(),
|
||||
ExternalService::FACEBOOK => route('login_callback.facebook'),
|
||||
ExternalService::GOOGLE => route('login_callback.google'),
|
||||
ExternalService::TWITTER => route('login_callback.twitter')
|
||||
];
|
||||
}
|
||||
|
||||
private function isServiceInUse(ExternalService $service)
|
||||
{
|
||||
// TODO check if the service is in use anywhere else and prevent it being deleted if so
|
||||
return false;
|
||||
switch ($service->service_type)
|
||||
{
|
||||
case ExternalService::FACEBOOK:
|
||||
// Cannot delete Facebook service if it's set as the login provider
|
||||
$facebookConfig = Configuration::where('key', 'facebook_external_service_id')->first();
|
||||
return !is_null($facebookConfig) && intval($facebookConfig->value) == $service->id;
|
||||
|
||||
case ExternalService::GOOGLE:
|
||||
// Cannot delete Google service if it's set as the login provider
|
||||
$googleConfig = Configuration::where('key', 'google_external_service_id')->first();
|
||||
return !is_null($googleConfig) && intval($googleConfig->value) == $service->id;
|
||||
|
||||
case ExternalService::DROPBOX:
|
||||
return Storage::where('external_service_id', $service->id)->count() > 0;
|
||||
|
||||
case ExternalService::TWITTER:
|
||||
// Cannot delete Twitter service if it's set as the login provider
|
||||
$twitterConfig = Configuration::where('key', 'twitter_external_service_id')->first();
|
||||
return !is_null($twitterConfig) && intval($twitterConfig->value) == $service->id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function serviceTypeList()
|
||||
@ -297,4 +345,11 @@ class ServiceController extends Controller
|
||||
ExternalService::TWITTER => trans(sprintf('services.%s', ExternalService::TWITTER))
|
||||
];
|
||||
}
|
||||
|
||||
private function validReturnLocations()
|
||||
{
|
||||
return [
|
||||
'settings' => route('admin.settings')
|
||||
];
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use App\ExternalService;
|
||||
use App\Facade\Theme;
|
||||
use App\Facade\UserConfig;
|
||||
use App\Helpers\MiscHelper;
|
||||
@ -152,7 +153,12 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function redirectToFacebook()
|
||||
{
|
||||
$socialite = $this->setSocialiteConfigs();
|
||||
$socialite = $this->setSocialiteConfigForFacebook();
|
||||
if (is_null($socialite))
|
||||
{
|
||||
return redirect(route('login'));
|
||||
}
|
||||
|
||||
return $socialite->driver('facebook')->redirect();
|
||||
}
|
||||
|
||||
@ -163,7 +169,12 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function redirectToGoogle()
|
||||
{
|
||||
$socialite = $this->setSocialiteConfigs();
|
||||
$socialite = $this->setSocialiteConfigForGoogle();
|
||||
if (is_null($socialite))
|
||||
{
|
||||
return redirect(route('login'));
|
||||
}
|
||||
|
||||
return $socialite->driver('google')->redirect();
|
||||
}
|
||||
|
||||
@ -174,7 +185,12 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function redirectToTwitter()
|
||||
{
|
||||
$socialite = $this->setSocialiteConfigs();
|
||||
$socialite = $this->setSocialiteConfigForTwitter();
|
||||
if (is_null($socialite))
|
||||
{
|
||||
return redirect(route('login'));
|
||||
}
|
||||
|
||||
return $socialite->driver('twitter')->redirect();
|
||||
}
|
||||
|
||||
@ -185,7 +201,12 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function handleFacebookCallback(Request $request)
|
||||
{
|
||||
$socialite = $this->setSocialiteConfigs();
|
||||
$socialite = $this->setSocialiteConfigForFacebook();
|
||||
if (is_null($socialite))
|
||||
{
|
||||
return redirect(route('login'));
|
||||
}
|
||||
|
||||
$facebookUser = $socialite->driver('facebook')->user();
|
||||
|
||||
return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser);
|
||||
@ -198,7 +219,12 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function handleGoogleCallback(Request $request)
|
||||
{
|
||||
$socialite = $this->setSocialiteConfigs();
|
||||
$socialite = $this->setSocialiteConfigForGoogle();
|
||||
if (is_null($socialite))
|
||||
{
|
||||
return redirect(route('login'));
|
||||
}
|
||||
|
||||
$googleUser = $socialite->driver('google')->user();
|
||||
|
||||
return $this->processSocialMediaLogin($request, 'google_id', $googleUser);
|
||||
@ -211,12 +237,30 @@ class LoginController extends Controller
|
||||
*/
|
||||
public function handleTwitterCallback(Request $request)
|
||||
{
|
||||
$socialite = $this->setSocialiteConfigs();
|
||||
$socialite = $this->setSocialiteConfigForTwitter();
|
||||
if (is_null($socialite))
|
||||
{
|
||||
return redirect(route('login'));
|
||||
}
|
||||
|
||||
$twitterUser = $socialite->driver('twitter')->user();
|
||||
|
||||
return $this->processSocialMediaLogin($request, 'twitter_id', $twitterUser);
|
||||
}
|
||||
|
||||
private function getSocialMediaConfig($socialMediaEnabledField, $socialMediaExternalServiceIdField)
|
||||
{
|
||||
if (boolval(UserConfig::get($socialMediaEnabledField)))
|
||||
{
|
||||
$externalServiceID = intval(UserConfig::get($socialMediaExternalServiceIdField));
|
||||
$externalService = ExternalService::where('id', $externalServiceID)->first();
|
||||
|
||||
return $externalService;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function processSocialMediaLogin(Request $request, $socialMediaIdField, $socialMediaUser)
|
||||
{
|
||||
$userBySocialMediaId = User::where($socialMediaIdField, $socialMediaUser->getId())->first();
|
||||
@ -260,38 +304,81 @@ class LoginController extends Controller
|
||||
return redirect(route('auth.register_sso'));
|
||||
}
|
||||
|
||||
private function setSocialiteConfigs()
|
||||
private function setSocialiteConfigForFacebook()
|
||||
{
|
||||
// Force Socialite to use our config from the database instead of hard-coded in config/services.php
|
||||
$facebookConfig = $this->getSocialMediaConfig(
|
||||
'social_facebook_login',
|
||||
'facebook_external_service_id'
|
||||
);
|
||||
|
||||
if (is_null($facebookConfig))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class);
|
||||
$socialite->extend(
|
||||
'facebook',
|
||||
function ($app) use ($socialite) {
|
||||
function ($app) use ($socialite, $facebookConfig) {
|
||||
$config = [
|
||||
'client_id' => trim(UserConfig::get('facebook_app_id')),
|
||||
'client_secret' => trim(decrypt(UserConfig::get('facebook_app_secret'))),
|
||||
'client_id' => trim(decrypt($facebookConfig->app_id)),
|
||||
'client_secret' => trim(decrypt($facebookConfig->app_secret)),
|
||||
'redirect' => route('login_callback.facebook')
|
||||
];
|
||||
return $socialite->buildProvider(FacebookProvider::class, $config);
|
||||
}
|
||||
);
|
||||
|
||||
return $socialite;
|
||||
}
|
||||
|
||||
private function setSocialiteConfigForGoogle()
|
||||
{
|
||||
$googleConfig = $this->getSocialMediaConfig(
|
||||
'social_google_login',
|
||||
'google_external_service_id'
|
||||
);
|
||||
|
||||
if (is_null($googleConfig))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class);
|
||||
$socialite->extend(
|
||||
'google',
|
||||
function ($app) use ($socialite) {
|
||||
function ($app) use ($socialite, $googleConfig) {
|
||||
$config = [
|
||||
'client_id' => trim(UserConfig::get('google_app_id')),
|
||||
'client_secret' => trim(decrypt(UserConfig::get('google_app_secret'))),
|
||||
'client_id' => trim(decrypt($googleConfig->app_id)),
|
||||
'client_secret' => trim(decrypt($googleConfig->app_secret)),
|
||||
'redirect' => route('login_callback.google')
|
||||
];
|
||||
return $socialite->buildProvider(GoogleProvider::class, $config);
|
||||
}
|
||||
);
|
||||
|
||||
return $socialite;
|
||||
}
|
||||
|
||||
private function setSocialiteConfigForTwitter()
|
||||
{
|
||||
$twitterConfig = $this->getSocialMediaConfig(
|
||||
'social_twitter_login',
|
||||
'twitter_external_service_id'
|
||||
);
|
||||
|
||||
if (is_null($twitterConfig))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
$socialite = app()->make(\Laravel\Socialite\Contracts\Factory::class);
|
||||
$socialite->extend(
|
||||
'twitter',
|
||||
function ($app) use ($socialite) {
|
||||
function ($app) use ($socialite, $twitterConfig) {
|
||||
$config = [
|
||||
'identifier' => trim(UserConfig::get('twitter_app_id')),
|
||||
'secret' => trim(decrypt(UserConfig::get('twitter_app_secret'))),
|
||||
'identifier' => trim(decrypt($twitterConfig->app_id)),
|
||||
'secret' => trim(decrypt($twitterConfig->app_secret)),
|
||||
'callback_uri' => route('login_callback.twitter')
|
||||
];
|
||||
return new TwitterProvider($app['request'], new TwitterServer($config));
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
@ -66,26 +69,40 @@ class AppInstallation
|
||||
if ($isAppInstalled)
|
||||
{
|
||||
// See if an update is necessary
|
||||
$this->updateDatabaseIfRequired();
|
||||
if ($this->updateDatabaseIfRequired())
|
||||
{
|
||||
return redirect($request->fullUrl());
|
||||
}
|
||||
|
||||
// App is configured, continue on
|
||||
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');
|
||||
@ -138,6 +155,10 @@ class AppInstallation
|
||||
// Rebuild the permissions cache
|
||||
$helper = new PermissionsHelper();
|
||||
$helper->rebuildCache();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
@ -6,11 +6,34 @@ class GiteaService
|
||||
{
|
||||
private $cacheFile = null;
|
||||
private $config = [];
|
||||
private $currentVersionNumber;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(array $config = null, $currentVersionNumber = null)
|
||||
{
|
||||
$this->config = config('services.gitea');
|
||||
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||
// This class is used in the Bootstrapper to fetch release information, therefore
|
||||
// we need to check if the Laravel helper functions are loaded before we use them
|
||||
if (is_null($config) && function_exists('config'))
|
||||
{
|
||||
$this->config = config('services.gitea');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
if (is_null($currentVersionNumber) && function_exists('config'))
|
||||
{
|
||||
$this->currentVersionNumber = config('app.version');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->currentVersionNumber = $currentVersionNumber;
|
||||
}
|
||||
|
||||
if (function_exists('storage_path'))
|
||||
{
|
||||
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkForLatestRelease()
|
||||
@ -26,7 +49,7 @@ class GiteaService
|
||||
{
|
||||
// Lookup and store the version information
|
||||
$statusCode = -1;
|
||||
$result = $this->getLatestReleaseFromGitea($statusCode);
|
||||
$result = $this->getReleasesFromGitea($statusCode);
|
||||
|
||||
if ($statusCode == 200)
|
||||
{
|
||||
@ -51,6 +74,31 @@ class GiteaService
|
||||
return $cacheData;
|
||||
}
|
||||
|
||||
public function getSpecificRelease($versionNumber)
|
||||
{
|
||||
$cacheData = null;
|
||||
|
||||
// Lookup and store the version information
|
||||
$statusCode = -1;
|
||||
$result = $this->getReleasesFromGitea($statusCode);
|
||||
|
||||
if ($statusCode == 200)
|
||||
{
|
||||
$releases = json_decode($result[1]);
|
||||
|
||||
$foundRelease = null;
|
||||
foreach ($releases as $release)
|
||||
{
|
||||
if (version_compare($release->tag_name, $versionNumber) === 0)
|
||||
{
|
||||
return $release;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function doesCacheExist()
|
||||
{
|
||||
$exists = file_exists($this->cacheFile);
|
||||
@ -75,10 +123,10 @@ class GiteaService
|
||||
return json_decode(file_get_contents($this->cacheFile));
|
||||
}
|
||||
|
||||
private function getLatestReleaseFromGitea(&$statusCode)
|
||||
private function getReleasesFromGitea(&$statusCode)
|
||||
{
|
||||
$httpHeaders = [
|
||||
sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', config('app.version'))
|
||||
sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', $this->currentVersionNumber)
|
||||
];
|
||||
|
||||
if (isset($this->config['api_key']) && !empty($this->config['api_key']))
|
||||
@ -106,7 +154,11 @@ class GiteaService
|
||||
|
||||
private function setCacheData($data)
|
||||
{
|
||||
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||
if (!is_null($this->cacheFile))
|
||||
{
|
||||
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
453
composer.lock
generated
453
composer.lock
generated
@ -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"
|
||||
}
|
||||
|
@ -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' => [
|
||||
|
112
database/data_migrations/DataMigrationV2_2_0_beta_2.php
Normal file
112
database/data_migrations/DataMigrationV2_2_0_beta_2.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php
|
||||
|
||||
use App\Configuration;
|
||||
use App\DataMigration;
|
||||
use App\ExternalService;
|
||||
use App\Facade\UserConfig;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DataMigrationV2_2_0_beta_2 extends DataMigration
|
||||
{
|
||||
public function getVersion()
|
||||
{
|
||||
return '2.2.0-beta.2';
|
||||
}
|
||||
|
||||
public function run($currentVersion)
|
||||
{
|
||||
DB::transaction(function()
|
||||
{
|
||||
$this->moveFacebookSettingsToService();
|
||||
$this->moveGoogleSettingsToService();
|
||||
$this->moveTwitterSettingsToService();
|
||||
});
|
||||
}
|
||||
|
||||
private function moveFacebookSettingsToService()
|
||||
{
|
||||
/** @var Configuration $facebookAppID */
|
||||
$facebookAppID = Configuration::where(['key' => 'facebook_app_id'])->first();
|
||||
|
||||
/** @var Configuration $facebookAppID */
|
||||
$facebookAppSecret = Configuration::where(['key' => 'facebook_app_secret'])->first();
|
||||
|
||||
if (is_null($facebookAppID) || is_null($facebookAppSecret))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$externalService = ExternalService::create([
|
||||
'service_type' => ExternalService::FACEBOOK,
|
||||
'name' => 'Facebook (migrated from settings)',
|
||||
'app_id' => encrypt($facebookAppID->value), // app ID needs to be encrypted now
|
||||
'app_secret' => $facebookAppSecret->value // secret is already encrypted
|
||||
]);
|
||||
|
||||
/** @var ExternalService $facebookExternalServiceConfig */
|
||||
$facebookExternalServiceConfig = UserConfig::getOrCreateModel('facebook_external_service_id');
|
||||
$facebookExternalServiceConfig->value = $externalService->id;
|
||||
$facebookExternalServiceConfig->save();
|
||||
|
||||
$facebookAppID->delete();
|
||||
$facebookAppSecret->delete();
|
||||
}
|
||||
|
||||
private function moveGoogleSettingsToService()
|
||||
{
|
||||
/** @var Configuration $googleAppID */
|
||||
$googleAppID = Configuration::where(['key' => 'google_app_id'])->first();
|
||||
|
||||
/** @var Configuration $facebookAppID */
|
||||
$googleAppSecret = Configuration::where(['key' => 'google_app_secret'])->first();
|
||||
|
||||
if (is_null($googleAppID) || is_null($googleAppSecret))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$externalService = ExternalService::create([
|
||||
'service_type' => ExternalService::GOOGLE,
|
||||
'name' => 'Google (migrated from settings)',
|
||||
'app_id' => encrypt($googleAppID->value), // app ID needs to be encrypted now
|
||||
'app_secret' => $googleAppSecret->value // secret is already encrypted
|
||||
]);
|
||||
|
||||
/** @var ExternalService $googleExternalServiceConfig */
|
||||
$googleExternalServiceConfig = UserConfig::getOrCreateModel('google_external_service_id');
|
||||
$googleExternalServiceConfig->value = $externalService->id;
|
||||
$googleExternalServiceConfig->save();
|
||||
|
||||
$googleAppID->delete();
|
||||
$googleAppSecret->delete();
|
||||
}
|
||||
|
||||
private function moveTwitterSettingsToService()
|
||||
{
|
||||
/** @var Configuration $twitterAppID */
|
||||
$twitterAppID = Configuration::where(['key' => 'twitter_app_id'])->first();
|
||||
|
||||
/** @var Configuration $facebookAppID */
|
||||
$twitterAppSecret = Configuration::where(['key' => 'twitter_app_secret'])->first();
|
||||
|
||||
if (is_null($twitterAppID) || is_null($twitterAppSecret))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$externalService = ExternalService::create([
|
||||
'service_type' => ExternalService::TWITTER,
|
||||
'name' => 'Twitter (migrated from settings)',
|
||||
'app_id' => encrypt($twitterAppID->value), // app ID needs to be encrypted now
|
||||
'app_secret' => $twitterAppSecret->value // secret is already encrypted
|
||||
]);
|
||||
|
||||
/** @var ExternalService $twitterExternalServiceConfig */
|
||||
$twitterExternalServiceConfig = UserConfig::getOrCreateModel('twitter_external_service_id');
|
||||
$twitterExternalServiceConfig->value = $externalService->id;
|
||||
$twitterExternalServiceConfig->save();
|
||||
|
||||
$twitterAppID->delete();
|
||||
$twitterAppSecret->delete();
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
71
installer/AppRequirements.php
Normal file
71
installer/AppRequirements.php
Normal 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);
|
||||
}
|
||||
}
|
394
installer/Installer.php
Normal file
394
installer/Installer.php
Normal file
@ -0,0 +1,394 @@
|
||||
<?php
|
||||
|
||||
namespace AppInstaller;
|
||||
|
||||
use App\Services\GiteaService;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
/**
|
||||
* This class handles the downloading and extracting of the vendors directory.
|
||||
* Because Laravel and other vendors are not yet available, it uses "raw" PHP and the odd few classes within Blue
|
||||
* Twilight, such as GiteaService.
|
||||
*
|
||||
* @package AppInstaller
|
||||
*/
|
||||
class Installer
|
||||
{
|
||||
/**
|
||||
* Path to /app/config
|
||||
* @var string
|
||||
*/
|
||||
private $configDir;
|
||||
|
||||
/**
|
||||
* Path to /installer
|
||||
* @var string
|
||||
*/
|
||||
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
|
||||
*/
|
||||
private $rootDir;
|
||||
|
||||
/**
|
||||
* Path to /installer/temp
|
||||
* @var string
|
||||
*/
|
||||
private $tempDir;
|
||||
|
||||
/**
|
||||
* Path to /vendor
|
||||
* @var string
|
||||
*/
|
||||
private $vendorDir;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $versionNumber;
|
||||
|
||||
/**
|
||||
* Path to /installer/views
|
||||
* @var string
|
||||
*/
|
||||
private $viewsDir;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->installerDir = __DIR__;
|
||||
$this->rootDir = 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);
|
||||
|
||||
$appConfig = require_once sprintf('%s/app.php', $this->configDir);
|
||||
$this->versionNumber = $appConfig['version'];
|
||||
}
|
||||
|
||||
public function handleRequest()
|
||||
{
|
||||
if (!isset($_GET['act']))
|
||||
{
|
||||
$this->checkInstallation();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (trim($_GET['act']))
|
||||
{
|
||||
case 'download':
|
||||
$this->download();
|
||||
return;
|
||||
|
||||
case 'extract':
|
||||
$this->extract();
|
||||
return;
|
||||
|
||||
case 'finalise':
|
||||
$this->finalise();
|
||||
return;
|
||||
|
||||
default:
|
||||
throw new \Exception(sprintf('Action \'%s\' was not recognised.', $_GET['act']));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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()
|
||||
{
|
||||
$servicesConfig = require_once sprintf('%s/services.php', $this->configDir);
|
||||
|
||||
$versionNumber = sprintf('v%s', $this->versionNumber);
|
||||
|
||||
$gitea = new GiteaService($servicesConfig['gitea'], $versionNumber);
|
||||
$releaseInfo = $gitea->getSpecificRelease($versionNumber);
|
||||
|
||||
if (is_null($releaseInfo))
|
||||
{
|
||||
throw new \Exception(sprintf('No release info found in Gitea for Blue Twilight version \'%s\'', $versionNumber));
|
||||
}
|
||||
else if (!isset($releaseInfo->assets))
|
||||
{
|
||||
throw new \Exception(sprintf('No assets found in Gitea for Blue Twilight version \'%s\'', $versionNumber));
|
||||
}
|
||||
|
||||
$vendorsPrefix = 'vendors';
|
||||
$vendorsSuffix = '.tar.gz';
|
||||
$selectedAsset = null;
|
||||
|
||||
foreach ($releaseInfo->assets as $asset)
|
||||
{
|
||||
/*
|
||||
Ignore anything that is not "vendors<something>.tar.gz" were the <something> is also optional - e.g.
|
||||
vendors_2.1.2.tar.gz
|
||||
vendors.tar.gz
|
||||
but NOT 2.1.2_vendors.zip
|
||||
*/
|
||||
if (!starts_with($asset->name, $vendorsPrefix) || !ends_with($asset->name, $vendorsSuffix))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$selectedAsset = $asset;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_null($selectedAsset))
|
||||
{
|
||||
throw new \Exception(sprintf('No vendors.tar.gz found in Gitea for Blue Twilight version \'%s\'', $versionNumber));
|
||||
}
|
||||
|
||||
$targetFileName = $this->getVendorsTempFileName();
|
||||
|
||||
$this->downloadFile($selectedAsset->browser_download_url, $targetFileName);
|
||||
$this->json([
|
||||
'result' => true,
|
||||
'fileName' => $targetFileName
|
||||
]);
|
||||
}
|
||||
|
||||
protected function extract()
|
||||
{
|
||||
$targetFileName = $this->getVendorsTempFileName();
|
||||
if (!file_exists($targetFileName) || !is_readable($targetFileName))
|
||||
{
|
||||
throw new \Exception(sprintf('The file \'%s\' does not exist or is not readable', $targetFileName));
|
||||
}
|
||||
|
||||
$phar = new \PharData($targetFileName);
|
||||
$phar->extractTo($this->rootDir, null, true);
|
||||
|
||||
// We should always have a vendor/autoload.php
|
||||
$vendorsTestFile = $this->getVendorsAutoloadFileName();
|
||||
|
||||
if (file_exists($vendorsTestFile))
|
||||
{
|
||||
$this->writeVersionFile();
|
||||
|
||||
$this->json([
|
||||
'result' => true,
|
||||
'testFile' => $vendorsTestFile
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new \Exception('The extraction failed');
|
||||
}
|
||||
}
|
||||
|
||||
protected function finalise()
|
||||
{
|
||||
$result = [
|
||||
'cacheFilesRemoved' => 0,
|
||||
'envFileCreated' => false
|
||||
];
|
||||
|
||||
$result['cacheFilesRemoved'] = $this->clearCacheIfExists();
|
||||
$result['envFileCreated'] = !$this->isUpgrade && $this->createEnvFileIfNotExist();
|
||||
|
||||
require sprintf('%s/bootstrap/autoload.php', $this->rootDir);
|
||||
|
||||
$app = require_once sprintf('%s/bootstrap/app.php', $this->rootDir);
|
||||
|
||||
$kernel = $app->make(\Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
|
||||
if ($result['envFileCreated'])
|
||||
{
|
||||
Artisan::call('key:generate');
|
||||
}
|
||||
|
||||
$kernel->terminate(null, null);
|
||||
|
||||
$this->json($result);
|
||||
}
|
||||
|
||||
private function downloadFile($sourceURL, $targetFilename)
|
||||
{
|
||||
$urlHandle = @fopen($sourceURL, 'r');
|
||||
$tempFilename = @fopen($targetFilename, 'w');
|
||||
|
||||
if ($urlHandle === false)
|
||||
{
|
||||
throw new \Exception(sprintf('Failed downloading the file from %s', $sourceURL));
|
||||
}
|
||||
else if ($tempFilename === false)
|
||||
{
|
||||
throw new \Exception(sprintf('Failed opening the file \'%s\' for writing', $targetFilename));
|
||||
}
|
||||
|
||||
while (!feof($urlHandle))
|
||||
{
|
||||
$buffer = fread($urlHandle, 8192);
|
||||
fwrite($tempFilename, $buffer);
|
||||
}
|
||||
|
||||
@fclose($urlHandle);
|
||||
@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();
|
||||
|
||||
if (!file_exists($envFile))
|
||||
{
|
||||
copy($this->getEnvExampleFileName(), $envFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getEnvExampleFileName()
|
||||
{
|
||||
return sprintf('%s/.env.example', $this->rootDir);
|
||||
}
|
||||
|
||||
private function getEnvFileName()
|
||||
{
|
||||
return sprintf('%s/.env', $this->rootDir);
|
||||
}
|
||||
|
||||
private function getVendorsAutoloadFileName()
|
||||
{
|
||||
return sprintf('%s/autoload.php', $this->vendorDir);
|
||||
}
|
||||
|
||||
private function getVendorsTempFileName()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
private function view($name, array $viewData = [])
|
||||
{
|
||||
$viewFile = sprintf('%s/%s.php', $this->viewsDir, $name);
|
||||
if (!file_exists($viewFile) || !is_readable($viewFile))
|
||||
{
|
||||
throw new \Exception(sprintf('ERROR: View file \'%s\' does not exist.', $viewFile));
|
||||
}
|
||||
|
||||
// Provide keys as variables - e.g. $viewData['something'] becomes accessible via $something
|
||||
extract($viewData);
|
||||
|
||||
require_once $viewFile;
|
||||
}
|
||||
|
||||
private function writeVersionFile()
|
||||
{
|
||||
file_put_contents($this->getVendorsVersionFileName(), $this->versionNumber . PHP_EOL);
|
||||
}
|
||||
}
|
26
installer/composer.json
Normal file
26
installer/composer.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "aheathershaw/blue-twilight-installer",
|
||||
"description": "Installer for Blue Twilight - self-hosted photo gallery software.",
|
||||
"keywords": [
|
||||
"blue",
|
||||
"twilight",
|
||||
"photo",
|
||||
"photograph",
|
||||
"portfolio",
|
||||
"gallery",
|
||||
"self-hosted"
|
||||
],
|
||||
"license": "MIT",
|
||||
"type": "project",
|
||||
"require": {
|
||||
"php": ">=7.2.0",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"App\\": "../app/",
|
||||
"AppInstaller\\": "./"
|
||||
}
|
||||
}
|
||||
}
|
29
installer/helpers.php
Normal file
29
installer/helpers.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
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) &&
|
||||
substr(strtolower($stringToCheck), 0, strlen($stringToFind)) == strtolower($stringToFind);
|
||||
}
|
0
installer/temp/.gitignore
vendored
Normal file
0
installer/temp/.gitignore
vendored
Normal file
7
installer/vendor/autoload.php
vendored
Normal file
7
installer/vendor/autoload.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInitae1de26c658d13c195b98449ea1bf6a1::getLoader();
|
445
installer/vendor/composer/ClassLoader.php
vendored
Normal file
445
installer/vendor/composer/ClassLoader.php
vendored
Normal file
@ -0,0 +1,445 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Composer.
|
||||
*
|
||||
* (c) Nils Adermann <naderman@naderman.de>
|
||||
* Jordi Boggiano <j.boggiano@seld.be>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
/**
|
||||
* ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
|
||||
*
|
||||
* $loader = new \Composer\Autoload\ClassLoader();
|
||||
*
|
||||
* // register classes with namespaces
|
||||
* $loader->add('Symfony\Component', __DIR__.'/component');
|
||||
* $loader->add('Symfony', __DIR__.'/framework');
|
||||
*
|
||||
* // activate the autoloader
|
||||
* $loader->register();
|
||||
*
|
||||
* // to enable searching the include path (eg. for PEAR packages)
|
||||
* $loader->setUseIncludePath(true);
|
||||
*
|
||||
* In this example, if you try to use a class in the Symfony\Component
|
||||
* namespace or one of its children (Symfony\Component\Console for instance),
|
||||
* the autoloader will first look for the class under the component/
|
||||
* directory, and it will then fallback to the framework/ directory if not
|
||||
* found before giving up.
|
||||
*
|
||||
* This class is loosely based on the Symfony UniversalClassLoader.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Jordi Boggiano <j.boggiano@seld.be>
|
||||
* @see http://www.php-fig.org/psr/psr-0/
|
||||
* @see http://www.php-fig.org/psr/psr-4/
|
||||
*/
|
||||
class ClassLoader
|
||||
{
|
||||
// PSR-4
|
||||
private $prefixLengthsPsr4 = array();
|
||||
private $prefixDirsPsr4 = array();
|
||||
private $fallbackDirsPsr4 = array();
|
||||
|
||||
// PSR-0
|
||||
private $prefixesPsr0 = array();
|
||||
private $fallbackDirsPsr0 = array();
|
||||
|
||||
private $useIncludePath = false;
|
||||
private $classMap = array();
|
||||
private $classMapAuthoritative = false;
|
||||
private $missingClasses = array();
|
||||
private $apcuPrefix;
|
||||
|
||||
public function getPrefixes()
|
||||
{
|
||||
if (!empty($this->prefixesPsr0)) {
|
||||
return call_user_func_array('array_merge', $this->prefixesPsr0);
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getPrefixesPsr4()
|
||||
{
|
||||
return $this->prefixDirsPsr4;
|
||||
}
|
||||
|
||||
public function getFallbackDirs()
|
||||
{
|
||||
return $this->fallbackDirsPsr0;
|
||||
}
|
||||
|
||||
public function getFallbackDirsPsr4()
|
||||
{
|
||||
return $this->fallbackDirsPsr4;
|
||||
}
|
||||
|
||||
public function getClassMap()
|
||||
{
|
||||
return $this->classMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $classMap Class to filename map
|
||||
*/
|
||||
public function addClassMap(array $classMap)
|
||||
{
|
||||
if ($this->classMap) {
|
||||
$this->classMap = array_merge($this->classMap, $classMap);
|
||||
} else {
|
||||
$this->classMap = $classMap;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix, either
|
||||
* appending or prepending to the ones previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 root directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*/
|
||||
public function add($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr0
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr0 = array_merge(
|
||||
$this->fallbackDirsPsr0,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$first = $prefix[0];
|
||||
if (!isset($this->prefixesPsr0[$first][$prefix])) {
|
||||
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
|
||||
|
||||
return;
|
||||
}
|
||||
if ($prepend) {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixesPsr0[$first][$prefix]
|
||||
);
|
||||
} else {
|
||||
$this->prefixesPsr0[$first][$prefix] = array_merge(
|
||||
$this->prefixesPsr0[$first][$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace, either
|
||||
* appending or prepending to the ones previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
* @param bool $prepend Whether to prepend the directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function addPsr4($prefix, $paths, $prepend = false)
|
||||
{
|
||||
if (!$prefix) {
|
||||
// Register directories for the root namespace.
|
||||
if ($prepend) {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
(array) $paths,
|
||||
$this->fallbackDirsPsr4
|
||||
);
|
||||
} else {
|
||||
$this->fallbackDirsPsr4 = array_merge(
|
||||
$this->fallbackDirsPsr4,
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
|
||||
// Register directories for a new namespace.
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
} elseif ($prepend) {
|
||||
// Prepend directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
(array) $paths,
|
||||
$this->prefixDirsPsr4[$prefix]
|
||||
);
|
||||
} else {
|
||||
// Append directories for an already registered namespace.
|
||||
$this->prefixDirsPsr4[$prefix] = array_merge(
|
||||
$this->prefixDirsPsr4[$prefix],
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-0 directories for a given prefix,
|
||||
* replacing any others previously set for this prefix.
|
||||
*
|
||||
* @param string $prefix The prefix
|
||||
* @param array|string $paths The PSR-0 base directories
|
||||
*/
|
||||
public function set($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr0 = (array) $paths;
|
||||
} else {
|
||||
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of PSR-4 directories for a given namespace,
|
||||
* replacing any others previously set for this namespace.
|
||||
*
|
||||
* @param string $prefix The prefix/namespace, with trailing '\\'
|
||||
* @param array|string $paths The PSR-4 base directories
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function setPsr4($prefix, $paths)
|
||||
{
|
||||
if (!$prefix) {
|
||||
$this->fallbackDirsPsr4 = (array) $paths;
|
||||
} else {
|
||||
$length = strlen($prefix);
|
||||
if ('\\' !== $prefix[$length - 1]) {
|
||||
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
|
||||
}
|
||||
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
|
||||
$this->prefixDirsPsr4[$prefix] = (array) $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns on searching the include path for class files.
|
||||
*
|
||||
* @param bool $useIncludePath
|
||||
*/
|
||||
public function setUseIncludePath($useIncludePath)
|
||||
{
|
||||
$this->useIncludePath = $useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can be used to check if the autoloader uses the include path to check
|
||||
* for classes.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseIncludePath()
|
||||
{
|
||||
return $this->useIncludePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns off searching the prefix and fallback directories for classes
|
||||
* that have not been registered with the class map.
|
||||
*
|
||||
* @param bool $classMapAuthoritative
|
||||
*/
|
||||
public function setClassMapAuthoritative($classMapAuthoritative)
|
||||
{
|
||||
$this->classMapAuthoritative = $classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should class lookup fail if not found in the current class map?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isClassMapAuthoritative()
|
||||
{
|
||||
return $this->classMapAuthoritative;
|
||||
}
|
||||
|
||||
/**
|
||||
* APCu prefix to use to cache found/not-found classes, if the extension is enabled.
|
||||
*
|
||||
* @param string|null $apcuPrefix
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APCu prefix in use, or null if APCu caching is not enabled.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getApcuPrefix()
|
||||
{
|
||||
return $this->apcuPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param bool $prepend Whether to prepend the autoloader or not
|
||||
*/
|
||||
public function register($prepend = false)
|
||||
{
|
||||
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this instance as an autoloader.
|
||||
*/
|
||||
public function unregister()
|
||||
{
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the given class or interface.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
* @return bool|null True if loaded, null otherwise
|
||||
*/
|
||||
public function loadClass($class)
|
||||
{
|
||||
if ($file = $this->findFile($class)) {
|
||||
includeFile($file);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param string $class The name of the class
|
||||
*
|
||||
* @return string|false The path if found, false otherwise
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
// class map lookup
|
||||
if (isset($this->classMap[$class])) {
|
||||
return $this->classMap[$class];
|
||||
}
|
||||
if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
|
||||
return false;
|
||||
}
|
||||
if (null !== $this->apcuPrefix) {
|
||||
$file = apcu_fetch($this->apcuPrefix.$class, $hit);
|
||||
if ($hit) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
$file = $this->findFileWithExtension($class, '.php');
|
||||
|
||||
// Search for Hack files if we are running on HHVM
|
||||
if (false === $file && defined('HHVM_VERSION')) {
|
||||
$file = $this->findFileWithExtension($class, '.hh');
|
||||
}
|
||||
|
||||
if (null !== $this->apcuPrefix) {
|
||||
apcu_add($this->apcuPrefix.$class, $file);
|
||||
}
|
||||
|
||||
if (false === $file) {
|
||||
// Remember that this class does not exist.
|
||||
$this->missingClasses[$class] = true;
|
||||
}
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
private function findFileWithExtension($class, $ext)
|
||||
{
|
||||
// PSR-4 lookup
|
||||
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
|
||||
|
||||
$first = $class[0];
|
||||
if (isset($this->prefixLengthsPsr4[$first])) {
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath.'\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
if (file_exists($file = $dir . $pathEnd)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr4 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 lookup
|
||||
if (false !== $pos = strrpos($class, '\\')) {
|
||||
// namespaced class name
|
||||
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
|
||||
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
|
||||
} else {
|
||||
// PEAR-like class name
|
||||
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
|
||||
}
|
||||
|
||||
if (isset($this->prefixesPsr0[$first])) {
|
||||
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
|
||||
if (0 === strpos($class, $prefix)) {
|
||||
foreach ($dirs as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 fallback dirs
|
||||
foreach ($this->fallbackDirsPsr0 as $dir) {
|
||||
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-0 include paths.
|
||||
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
|
||||
return $file;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope isolated include.
|
||||
*
|
||||
* Prevents access to $this/self from included files.
|
||||
*/
|
||||
function includeFile($file)
|
||||
{
|
||||
include $file;
|
||||
}
|
21
installer/vendor/composer/LICENSE
vendored
Normal file
21
installer/vendor/composer/LICENSE
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
Copyright (c) Nils Adermann, Jordi Boggiano
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
9
installer/vendor/composer/autoload_classmap.php
vendored
Normal file
9
installer/vendor/composer/autoload_classmap.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_classmap.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
9
installer/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
installer/vendor/composer/autoload_namespaces.php
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
// autoload_namespaces.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
);
|
11
installer/vendor/composer/autoload_psr4.php
vendored
Normal file
11
installer/vendor/composer/autoload_psr4.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// autoload_psr4.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'App\\' => array($baseDir . '/../app'),
|
||||
'AppInstaller\\' => array($baseDir . '/'),
|
||||
);
|
52
installer/vendor/composer/autoload_real.php
vendored
Normal file
52
installer/vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInitae1de26c658d13c195b98449ea1bf6a1
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
public static function loadClassLoader($class)
|
||||
{
|
||||
if ('Composer\Autoload\ClassLoader' === $class) {
|
||||
require __DIR__ . '/ClassLoader.php';
|
||||
}
|
||||
}
|
||||
|
||||
public static function getLoader()
|
||||
{
|
||||
if (null !== self::$loader) {
|
||||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInitae1de26c658d13c195b98449ea1bf6a1', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitae1de26c658d13c195b98449ea1bf6a1', 'loadClassLoader'));
|
||||
|
||||
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
|
||||
if ($useStaticLoader) {
|
||||
require_once __DIR__ . '/autoload_static.php';
|
||||
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitae1de26c658d13c195b98449ea1bf6a1::getInitializer($loader));
|
||||
} else {
|
||||
$map = require __DIR__ . '/autoload_namespaces.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->set($namespace, $path);
|
||||
}
|
||||
|
||||
$map = require __DIR__ . '/autoload_psr4.php';
|
||||
foreach ($map as $namespace => $path) {
|
||||
$loader->setPsr4($namespace, $path);
|
||||
}
|
||||
|
||||
$classMap = require __DIR__ . '/autoload_classmap.php';
|
||||
if ($classMap) {
|
||||
$loader->addClassMap($classMap);
|
||||
}
|
||||
}
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
36
installer/vendor/composer/autoload_static.php
vendored
Normal file
36
installer/vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitae1de26c658d13c195b98449ea1bf6a1
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'A' =>
|
||||
array (
|
||||
'App\\' => 4,
|
||||
'AppInstaller\\' => 13,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'App\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/../app',
|
||||
),
|
||||
'AppInstaller\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/../..' . '/',
|
||||
),
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitae1de26c658d13c195b98449ea1bf6a1::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitae1de26c658d13c195b98449ea1bf6a1::$prefixDirsPsr4;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
}
|
96
installer/views/index.php
Normal file
96
installer/views/index.php
Normal file
@ -0,0 +1,96 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<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">
|
||||
* {
|
||||
font-family: "Raleway", sans-serif;
|
||||
}
|
||||
</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="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>
|
||||
|
||||
<?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 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>
|
||||
</div>
|
||||
|
||||
<script src="../js/blue-twilight.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function()
|
||||
{
|
||||
var vm = new BootstrapperViewModel();
|
||||
var app = new Vue(vm);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -12,4 +12,4 @@
|
||||
"grunt-exec": "^3.0.0",
|
||||
"node-sass": "^4.13.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,143 +0,0 @@
|
||||
<?php
|
||||
|
||||
function b2_authorize_account()
|
||||
{
|
||||
$application_key_id = "0023254ec9bda08000000000a"; // Obtained from your B2 account page
|
||||
$application_key = "K002eARNPUlxdj1XaVJbwEYPMz0c7e8"; // Obtained from your B2 account page
|
||||
$credentials = base64_encode($application_key_id . ":" . $application_key);
|
||||
$url = "https://api.backblazeb2.com/b2api/v2/b2_authorize_account";
|
||||
|
||||
$session = curl_init($url);
|
||||
|
||||
// Add headers
|
||||
$headers = array();
|
||||
$headers[] = "Accept: application/json";
|
||||
$headers[] = "Authorization: Basic " . $credentials;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers); // Add headers
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
$server_output = curl_exec($session);
|
||||
curl_close ($session);
|
||||
echo ($server_output);
|
||||
|
||||
return json_decode($server_output);
|
||||
}
|
||||
|
||||
function b2_download_file_by_id($download_url, $auth_token)
|
||||
{
|
||||
//$download_url = ""; // From b2_authorize_account call
|
||||
$file_id = "4_z731245f41efc196b6dda0018_f116729ca6de74b38_d20190910_m132847_c002_v0001127_t0021"; // The ID of the file you want to download
|
||||
$uri = $download_url . "/b2api/v2/b2_download_file_by_id?fileId=" . $file_id;
|
||||
|
||||
$session = curl_init($uri);
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
|
||||
echo '<p>' . $uri . '</p>';
|
||||
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
|
||||
if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200)
|
||||
{
|
||||
echo '<p>' . $server_output . '</p>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<p>' . (strlen($server_output) . ' bytes received') . '</p>'; // Tell me about the rabbits, George!
|
||||
}
|
||||
|
||||
curl_close ($session); // Clean up
|
||||
|
||||
//$download_url = ""; // From b2_authorize_account call
|
||||
$file_id = "4_z731245f41efc196b6dda0018_f116729ca6de74b38_d20190910_m132847_c002_v0001127_t0021"; // The ID of the file you want to download
|
||||
$uri = $download_url . "/b2api/v2/b2_download_file_by_id?fileId=" . $file_id . '&Authorization=' . $auth_token;
|
||||
|
||||
$session = curl_init($uri);
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
|
||||
echo '<p>' . $uri . '</p>';
|
||||
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
|
||||
if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200)
|
||||
{
|
||||
echo '<p>' . $server_output . '</p>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<p>' . (strlen($server_output) . ' bytes received') . '</p>'; // Tell me about the rabbits, George!
|
||||
}
|
||||
|
||||
curl_close ($session); // Clean up
|
||||
}
|
||||
|
||||
function b2_download_file_by_name($download_url, $auth_token)
|
||||
{
|
||||
//$download_url = ""; // From b2_authorize_account call
|
||||
$bucket_name = "andysh-bt-test"; // The NAME of the bucket you want to download from
|
||||
$file_name = "B2-Test-Album/preview/7tgoy55do1vjv180ytlp.jpeg"; // The name of the file you want to download
|
||||
$uri = $download_url . "/file/" . $bucket_name . "/" . $file_name;
|
||||
|
||||
$session = curl_init($uri);
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP GET
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
|
||||
echo '<p>' . $uri . '</p>';
|
||||
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
|
||||
if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200)
|
||||
{
|
||||
echo '<p>' . $server_output . '</p>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<p>' . (strlen($server_output) . ' bytes received') . '</p>'; // Tell me about the rabbits, George!
|
||||
}
|
||||
|
||||
curl_close ($session); // Clean up
|
||||
|
||||
// You will need to use the account authorization token if your bucket's type is allPrivate.
|
||||
|
||||
//$download_url = ""; // From b2_authorize_account call
|
||||
$bucket_name = "andysh-bt-test"; // The NAME of the bucket you want to download from
|
||||
$file_name = "B2-Test-Album/preview/7tgoy55do1vjv180ytlp.jpeg"; // The name of the file you want to download
|
||||
//$auth_token = ""; // From b2_authorize_account call
|
||||
$uri = $download_url . "/file/" . $bucket_name . "/" . $file_name . '?Authorization=' . $auth_token;
|
||||
|
||||
$session = curl_init($uri);
|
||||
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true); // HTTP POST
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true); // Receive server response
|
||||
|
||||
echo '<p>' . $uri . '</p>';
|
||||
|
||||
$server_output = curl_exec($session); // Let's do this!
|
||||
|
||||
if (curl_getinfo($session, CURLINFO_HTTP_CODE) != 200)
|
||||
{
|
||||
echo '<p>' . $server_output . '</p>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo '<p>' . (strlen($server_output) . ' bytes received') . '</p>'; // Tell me about the rabbits, George!
|
||||
}
|
||||
|
||||
curl_close ($session); // Clean up
|
||||
}
|
||||
|
||||
?>
|
||||
<h2>b2_authorize_account</h2>
|
||||
<?php $authorize_account_result = b2_authorize_account(); ?>
|
||||
|
||||
<h2>b2_download_file_by_name</h2>
|
||||
<?php b2_download_file_by_name($authorize_account_result->downloadUrl, $authorize_account_result->authorizationToken); ?>
|
||||
|
||||
<h2>b2_download_file_by_id</h2>
|
||||
<?php b2_download_file_by_id($authorize_account_result->downloadUrl, $authorize_account_result->authorizationToken); ?>
|
@ -10260,6 +10260,29 @@ a.text-dark:hover, a.text-dark:focus {
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
#bootstrapper [v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
#bootstrapper .operation .status {
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
}
|
||||
#bootstrapper .operation .status i,
|
||||
#bootstrapper .operation .status img {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
#bootstrapper .operation .status span {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#bootstrapper ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.activity-grid {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
6
public/css/blue-twilight.min.css
vendored
Normal file
6
public/css/blue-twilight.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -10,7 +10,9 @@
|
||||
/* Added by Andy - check to see if Composer/vendors are installed */
|
||||
if (!file_exists(__DIR__.'/../vendor/autoload.php'))
|
||||
{
|
||||
header('Location: install.php');
|
||||
$currentUrl = $_SERVER['PHP_SELF']; // e.g. /some/directory/index.php
|
||||
$bootstrapUrl = sprintf('%sinstall', dirname($currentUrl));
|
||||
header(sprintf('Location: %s', $bootstrapUrl));
|
||||
exit();
|
||||
}
|
||||
/* End Added by Andy */
|
||||
|
@ -1,256 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace BtwInstaller;
|
||||
|
||||
class BlueTwilightInstaller
|
||||
{
|
||||
private $baseDirectory;
|
||||
private $composerSignature;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->baseDirectory = dirname(__DIR__);
|
||||
chdir($this->baseDirectory);
|
||||
putenv('HOME=' . $this->baseDirectory);
|
||||
|
||||
// Display errors so installer never gets a WSOD!
|
||||
ini_set('display_errors', true);
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST')
|
||||
{
|
||||
// Handle post
|
||||
$this->runInstall();
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<title>Blue Twilight Setup</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Blue Twilight Setup</h1>
|
||||
<p>We need to download a few things - namely <a href="http://getcomposer.org" target="_blank">Composer</a> and related packages - before we can kick off the Blue Twilight installer.</p>
|
||||
<p>We can do this for you - simply click the button below.</p>
|
||||
<p style="font-weight: bold; color: #ff0000;">This can take a few minutes so please be patient, and only click the button once!</p>
|
||||
<form method="post">
|
||||
<button type="submit">Install Composer and dependencies for me</button>
|
||||
</form>
|
||||
|
||||
<hr/>
|
||||
<h2>Got Composer?</h2>
|
||||
|
||||
<p>If you already have Composer installed, however, you may want to use that instead. Just run the below commands on your server, changing the path to Composer as appropriate:</p>
|
||||
<p><em>Please note: "composer.phar" may actually be "composer" on your system.</em></p>
|
||||
<pre>cd <?php echo $this->baseDirectory; ?><br/>/path/to/composer.phar install</pre>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function runInstall()
|
||||
{
|
||||
|
||||
?>
|
||||
<h1>Installing Blue Twilight Setup Files</h1>
|
||||
|
||||
<ul>
|
||||
<?php
|
||||
$steps = [
|
||||
['Checking PHP modules', 'checkPhpModules'],
|
||||
['Fetching Composer signature', 'fetchComposerSignature'],
|
||||
['Installing Composer', 'installComposer'],
|
||||
['Installing dependencies using Composer', 'runComposer'],
|
||||
['Generating application key', 'generateAppKey']
|
||||
];
|
||||
|
||||
$successful = true;
|
||||
foreach ($steps as $step)
|
||||
{
|
||||
echo sprintf("<li>%s...</li>%s", $step[0], PHP_EOL);
|
||||
$result = call_user_func([$this, $step[1]]);
|
||||
|
||||
if (!$result)
|
||||
{
|
||||
$successful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($successful)
|
||||
{
|
||||
header('Location: install/check');
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function checkPhpModules()
|
||||
{
|
||||
$requiredModules = [
|
||||
'simplexml',
|
||||
'curl',
|
||||
'mbstring',
|
||||
'dom'
|
||||
];
|
||||
$invalidModules = [];
|
||||
|
||||
foreach ($requiredModules as $module)
|
||||
{
|
||||
if (!extension_loaded($module))
|
||||
{
|
||||
$invalidModules[] = $module;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($invalidModules) > 0)
|
||||
{
|
||||
$this->echoError(sprintf('The following PHP modules are missing and need to be installed to continue: %s', join(', ', $invalidModules)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function echoError($message)
|
||||
{
|
||||
echo sprintf("<span style=\"color: #ff0000;\">%s.</span>%s", $message, PHP_EOL);
|
||||
}
|
||||
|
||||
private function echoOK($message = '')
|
||||
{
|
||||
echo "<span style=\"color: #008800;\">OK";
|
||||
|
||||
if (strlen($message) > 0)
|
||||
{
|
||||
echo sprintf('... %s', $message);
|
||||
}
|
||||
|
||||
echo '</span>' . PHP_EOL;
|
||||
}
|
||||
|
||||
private function fetchComposerSignature()
|
||||
{
|
||||
if (!boolval(ini_get('allow_url_fopen')))
|
||||
{
|
||||
$this->echoError('allow_url_fopen is disabled so we cannot use Composer');
|
||||
echo '<br/>';
|
||||
$this->echoError('You will need to install the vendor libraries manually - <a href="https://github.com/pandy06269/blue-twilight/wiki/Install-Vendor-libraries-manually" target="_blank">see this page for more details</a>');
|
||||
return false;
|
||||
}
|
||||
|
||||
$signatureUrl = 'https://composer.github.io/installer.sig';
|
||||
$this->composerSignature = trim(file_get_contents($signatureUrl));
|
||||
if (strlen($this->composerSignature) == 0)
|
||||
{
|
||||
$this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->echoOK($this->composerSignature);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function generateAppKey()
|
||||
{
|
||||
if (!file_exists('.env') && file_exists('.env.example'))
|
||||
{
|
||||
copy('.env.example', '.env');
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('touch .env', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
|
||||
ob_start();
|
||||
system('php artisan key:generate', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to generate application key');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
|
||||
private function installComposer()
|
||||
{
|
||||
$rc = -1;
|
||||
|
||||
ob_start();
|
||||
system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to fetch Composer');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Composer verification failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php composer-setup.php', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to install Composer');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php -r "unlink(\'composer-setup.php\');"', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to remove Composer setup file');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
|
||||
private function runComposer()
|
||||
{
|
||||
ob_start();
|
||||
system('php composer.phar install', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Installing Composer packages failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$installer = new BlueTwilightInstaller();
|
||||
$installer->run();
|
1
public/install/images/completed.svg
Normal file
1
public/install/images/completed.svg
Normal 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 |
7
public/install/images/loading.svg
Normal file
7
public/install/images/loading.svg
Normal 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 |
1
public/install/images/waiting.svg
Normal file
1
public/install/images/waiting.svg
Normal 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 |
16
public/install/index.php
Normal file
16
public/install/index.php
Normal file
@ -0,0 +1,16 @@
|
||||
<?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->handleRequest();
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
echo sprintf('ERROR: %s', $ex);
|
||||
}
|
@ -35700,6 +35700,12 @@ function AnalyseAlbumViewModel() {
|
||||
});
|
||||
item.isSuccessful = false;
|
||||
item.isPending = false;
|
||||
|
||||
var indexToRemove = self.imagesInProgress.indexOf(item);
|
||||
if (indexToRemove > -1)
|
||||
{
|
||||
self.imagesInProgress.splice(indexToRemove, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -35824,6 +35830,7 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
deletePhoto: function (e) {
|
||||
var self = this;
|
||||
this.selectPhotoSingle(e.target);
|
||||
var parent = $(e.target).closest('.photo');
|
||||
|
||||
var photo_id = self.photoIDs[0];
|
||||
this.photoIDs = [];
|
||||
@ -35846,7 +35853,7 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
$('.loading', parent).show();
|
||||
|
||||
$.post(url, {'_method': 'DELETE'}, function (data) {
|
||||
window.location.reload();
|
||||
$(parent).remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -35875,10 +35882,11 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
}
|
||||
|
||||
$('.loading', parent).show();
|
||||
$.post(url, function () {
|
||||
$.post(url, function (response) {
|
||||
var image = $('img.photo-thumbnail', parent);
|
||||
var originalUrl = image.data('original-src');
|
||||
image.attr('src', originalUrl + "&_=" + new Date().getTime());
|
||||
|
||||
// response from server is the URL to the modified image
|
||||
image.attr('src', response);
|
||||
|
||||
$('.loading', parent).hide();
|
||||
});
|
||||
@ -35958,10 +35966,10 @@ function EditPhotosViewModel(album_id, language, urls) {
|
||||
url = url.replace(/\/0$/, '/' + this.photoIDs[0]);
|
||||
|
||||
$('.loading', parent).show();
|
||||
$.post(url, function () {
|
||||
$.post(url, function (response) {
|
||||
var image = $('img.photo-thumbnail', parent);
|
||||
var originalUrl = image.data('original-src');
|
||||
image.attr('src', originalUrl + "&_=" + new Date().getTime());
|
||||
|
||||
image.attr('src', response.thumbnail_url);
|
||||
|
||||
$('.loading', parent).hide();
|
||||
});
|
||||
@ -36310,6 +36318,79 @@ function UploadPhotosViewModel(album_id, queue_token, language, urls) {
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This model is used by the system bootstrapper in public/bootstrap.
|
||||
* @constructor
|
||||
*/
|
||||
function BootstrapperViewModel() {
|
||||
this.el = '#bootstrapper';
|
||||
this.data = {
|
||||
isCompleted: false,
|
||||
isRunning: false,
|
||||
operations: []
|
||||
}
|
||||
this.methods = {
|
||||
bootstrap: function()
|
||||
{
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Removing any previous versions',
|
||||
'url': '?act=removePrevious'
|
||||
});
|
||||
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Downloading new files',
|
||||
'url': '?act=download'
|
||||
});
|
||||
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Extracting new files',
|
||||
'url': '?act=extract'
|
||||
});
|
||||
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Cleaning up',
|
||||
'url': '?act=finalise'
|
||||
});
|
||||
|
||||
this.isRunning = true;
|
||||
|
||||
this.runOperation(this.operations[0], 0);
|
||||
},
|
||||
runOperation: function(operation, index)
|
||||
{
|
||||
var self = this;
|
||||
operation.isRunning = true;
|
||||
|
||||
$.post(operation.url)
|
||||
.done(function(result)
|
||||
{
|
||||
operation.isRunning = false;
|
||||
operation.isCompleted = true;
|
||||
|
||||
index++;
|
||||
if (index < self.operations.length)
|
||||
{
|
||||
self.runOperation(self.operations[index], index);
|
||||
}
|
||||
else
|
||||
{
|
||||
//self.isRunning = false;
|
||||
self.isCompleted = true;
|
||||
|
||||
window.location = '../';
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
/*!
|
||||
* Chart.js
|
||||
* http://chartjs.org/
|
||||
@ -54804,6 +54885,27 @@ module.exports = function(Chart) {
|
||||
|
||||
},{"25":25,"45":45,"6":6}]},{},[7])(7)
|
||||
});
|
||||
function ExternalServiceViewModel()
|
||||
{
|
||||
this.el = '#external-service-options';
|
||||
this.data = {
|
||||
service_type: ''
|
||||
};
|
||||
this.computed = {
|
||||
hasOAuthStandardOptions: function()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'facebook' ||
|
||||
this.service_type === 'google' ||
|
||||
this.service_type === 'twitter';
|
||||
},
|
||||
isDropbox: function()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'dropbox';
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* This model is used by gallery/explore_users.blade.php, to handle following/unfollowing users profiles.
|
||||
* @constructor
|
||||
|
2
public/js/blue-twilight.min.js
vendored
Normal file
2
public/js/blue-twilight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/js/blue-twilight.min.js.map
Normal file
1
public/js/blue-twilight.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -1,255 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace BtwInstaller;
|
||||
|
||||
class BlueTwilightUpdater
|
||||
{
|
||||
private $baseDirectory;
|
||||
private $composerSignature;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->baseDirectory = dirname(__DIR__);
|
||||
chdir($this->baseDirectory);
|
||||
putenv('HOME=' . $this->baseDirectory);
|
||||
|
||||
// Display errors so installer never gets a WSOD!
|
||||
ini_set('display_errors', true);
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
if (strtoupper($_SERVER['REQUEST_METHOD']) == 'POST')
|
||||
{
|
||||
// Handle post
|
||||
$this->runUpdate();
|
||||
exit();
|
||||
}
|
||||
?>
|
||||
<html>
|
||||
<head>
|
||||
<title>Blue Twilight Update</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Blue Twilight Update</h1>
|
||||
<p>This update routine ensures your Blue Twilight Composer packages are up-to-date.</p>
|
||||
<p>To get started, simply click the button below.</p>
|
||||
<p style="font-weight: bold; color: #ff0000;">This can take a few minutes so please be patient, and only click the button once!</p>
|
||||
<form method="post">
|
||||
<button type="submit">Update Composer and dependencies for me</button>
|
||||
</form>
|
||||
|
||||
<hr/>
|
||||
<h2>Got Composer?</h2>
|
||||
|
||||
<p>If you already have Composer installed, however, you may want to use that instead. Just run the below commands on your server, changing the path to Composer as appropriate:</p>
|
||||
<p><em>Please note: "composer.phar" may actually be "composer" on your system.</em></p>
|
||||
<pre>
|
||||
cd <?php echo $this->baseDirectory; ?>
|
||||
|
||||
php artisan clear-compiled
|
||||
php artisan cache:clear
|
||||
php artisan config:clear
|
||||
php artisan view:clear
|
||||
/path/to/composer.phar install
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function runUpdate()
|
||||
{
|
||||
|
||||
?>
|
||||
<h1>Updating Blue Twilight Composer packages</h1>
|
||||
|
||||
<ul>
|
||||
<?php
|
||||
$steps = [
|
||||
['Removing compiled cache', 'removeCompiledCached'],
|
||||
['Fetching Composer signature', 'fetchComposerSignature'],
|
||||
['Installing Composer', 'installComposer'],
|
||||
['Updating dependencies using Composer', 'runComposer']
|
||||
];
|
||||
|
||||
$successful = true;
|
||||
foreach ($steps as $step)
|
||||
{
|
||||
echo sprintf("<li>%s...</li>%s", $step[0], PHP_EOL);
|
||||
$result = call_user_func([$this, $step[1]]);
|
||||
|
||||
if (!$result)
|
||||
{
|
||||
$successful = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($successful)
|
||||
{
|
||||
header('Location: admin');
|
||||
exit();
|
||||
}
|
||||
|
||||
?>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
private function fetchComposerSignature()
|
||||
{
|
||||
if (!boolval(ini_get('allow_url_fopen')))
|
||||
{
|
||||
$this->echoError('allow_url_fopen is disabled so we cannot use Composer');
|
||||
echo '<br/>';
|
||||
$this->echoError('You will need to install the vendor libraries manually - <a href="https://github.com/pandy06269/blue-twilight/wiki/Install-Vendor-libraries-manually" target="_blank">see this page for more details</a>');
|
||||
return false;
|
||||
}
|
||||
|
||||
$signatureUrl = 'https://composer.github.io/installer.sig';
|
||||
$this->composerSignature = trim(file_get_contents($signatureUrl));
|
||||
if (strlen($this->composerSignature) == 0)
|
||||
{
|
||||
$this->echoError(sprintf("Failed downloading the Composer signature from %s", $signatureUrl));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->echoOK($this->composerSignature);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function removeCompiledCached()
|
||||
{
|
||||
ob_start();
|
||||
system('php artisan clear-compiled', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('clear-compiled command failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php artisan cache:clear', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('cache:clear command failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php artisan config:clear', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('config:clear command failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php artisan view:clear', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('view:clear command failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
|
||||
private function echoError($message)
|
||||
{
|
||||
echo sprintf("<span style=\"color: #ff0000;\">%s.</span>%s", $message, PHP_EOL);
|
||||
}
|
||||
|
||||
private function echoOK($message = '')
|
||||
{
|
||||
echo "<span style=\"color: #008800;\">OK";
|
||||
|
||||
if (strlen($message) > 0)
|
||||
{
|
||||
echo sprintf('... %s', $message);
|
||||
}
|
||||
|
||||
echo '</span>' . PHP_EOL;
|
||||
}
|
||||
|
||||
private function installComposer()
|
||||
{
|
||||
$rc = -1;
|
||||
|
||||
ob_start();
|
||||
system('php -r "copy(\'https://getcomposer.org/installer\', \'composer-setup.php\');"', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to fetch Composer');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system(sprintf('php -r "if (hash_file(\'SHA384\', \'composer-setup.php\') === \'%s\') { echo \'Installer verified\'; } else { echo \'Installer corrupt\'; unlink(\'composer-setup.php\'); } echo PHP_EOL;"', $this->composerSignature), $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Composer verification failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php composer-setup.php', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to install Composer');
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
system('php -r "unlink(\'composer-setup.php\');"', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Failed to remove Composer setup file');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
|
||||
private function runComposer()
|
||||
{
|
||||
ob_start();
|
||||
system('php composer.phar --no-interaction install', $rc);
|
||||
$result = ob_get_clean();
|
||||
echo nl2br($result);
|
||||
if ($rc != 0)
|
||||
{
|
||||
$this->echoError('Updating Composer packages failed');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->echoOK();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
$installer = new BlueTwilightUpdater();
|
||||
$installer->run();
|
1
public/update/images/completed.svg
Normal file
1
public/update/images/completed.svg
Normal 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 |
7
public/update/images/loading.svg
Normal file
7
public/update/images/loading.svg
Normal 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 |
1
public/update/images/waiting.svg
Normal file
1
public/update/images/waiting.svg
Normal 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
17
public/update/index.php
Normal 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);
|
||||
}
|
73
resources/js/bootstrapper.js
vendored
Normal file
73
resources/js/bootstrapper.js
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* This model is used by the system bootstrapper in public/bootstrap.
|
||||
* @constructor
|
||||
*/
|
||||
function BootstrapperViewModel() {
|
||||
this.el = '#bootstrapper';
|
||||
this.data = {
|
||||
isCompleted: false,
|
||||
isRunning: false,
|
||||
operations: []
|
||||
}
|
||||
this.methods = {
|
||||
bootstrap: function()
|
||||
{
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Removing any previous versions',
|
||||
'url': '?act=removePrevious'
|
||||
});
|
||||
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Downloading new files',
|
||||
'url': '?act=download'
|
||||
});
|
||||
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Extracting new files',
|
||||
'url': '?act=extract'
|
||||
});
|
||||
|
||||
this.operations.push({
|
||||
'isCompleted': false,
|
||||
'isRunning': false,
|
||||
'name': 'Cleaning up',
|
||||
'url': '?act=finalise'
|
||||
});
|
||||
|
||||
this.isRunning = true;
|
||||
|
||||
this.runOperation(this.operations[0], 0);
|
||||
},
|
||||
runOperation: function(operation, index)
|
||||
{
|
||||
var self = this;
|
||||
operation.isRunning = true;
|
||||
|
||||
$.post(operation.url)
|
||||
.done(function(result)
|
||||
{
|
||||
operation.isRunning = false;
|
||||
operation.isCompleted = true;
|
||||
|
||||
index++;
|
||||
if (index < self.operations.length)
|
||||
{
|
||||
self.runOperation(self.operations[index], index);
|
||||
}
|
||||
else
|
||||
{
|
||||
//self.isRunning = false;
|
||||
self.isCompleted = true;
|
||||
|
||||
window.location = '../';
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -5,17 +5,25 @@ function ExternalServiceViewModel()
|
||||
service_type: ''
|
||||
};
|
||||
this.computed = {
|
||||
hasOAuthStandardOptions()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'facebook' ||
|
||||
this.service_type === 'google' ||
|
||||
this.service_type === 'twitter';
|
||||
},
|
||||
isDropbox()
|
||||
isDropbox: function()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'dropbox';
|
||||
},
|
||||
isFacebook: function()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'facebook';
|
||||
},
|
||||
isGoogle: function()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'google';
|
||||
},
|
||||
isTwitter: function()
|
||||
{
|
||||
// This logic must be mirrored in App\ExternalService
|
||||
return this.service_type === 'twitter';
|
||||
}
|
||||
}
|
||||
}
|
@ -72,7 +72,7 @@ return [
|
||||
'bulk_photos_changed' => ':number photo was updated successfully.|:number photos were updated successfully.',
|
||||
'bulk_photos_changed_queued' => 'Your requested change has been queued. :number photo will be updated shortly.|Your requested change has been queued. :number photos will be updated shortly.',
|
||||
'cannot_delete_own_user_account' => 'It is not possible to delete your own user account. Please ask another administrator to delete it for you.',
|
||||
'cannot_delete_service_in_use' => 'This service is still in use and cannot be deleted. Please remove any references to it in your configuration and try again.',
|
||||
'cannot_delete_service_in_use' => 'This service is still in use and cannot be deleted. Please remove any references to it in your configuration or storages and try again.',
|
||||
'cannot_remove_own_admin' => 'You cannot remove your own administrator permissions. Please ask another administrator to remove the administrator permissions for you.',
|
||||
'change_album_message' => 'Please select the album to move the photo(s) to:',
|
||||
'change_album_title' => 'Move photo(s) to another album',
|
||||
@ -314,10 +314,14 @@ return [
|
||||
'rebuild_permissions_cache_succeeded' => 'The permissions cache rebuild completed successfully.',
|
||||
'security_allow_self_registration' => 'Allow self-registration',
|
||||
'security_allow_self_registration_description' => 'With this option enabled, users can sign up for their own accounts. You can grant permissions to accounts to allow users to upload their own photos or manage yours.',
|
||||
'social_add_external_services_link' => 'Add a new service',
|
||||
'social_facebook' => 'Facebook',
|
||||
'social_facebook_no_services' => 'You haven\'t defined any services for Facebook. Add a new service with your Facebook app ID and secret.',
|
||||
'social_google' => 'Google',
|
||||
'social_google_no_services' => 'You haven\'t defined any services for Google. Add a new service with your Google app ID and secret.',
|
||||
'social_tab' => 'Social',
|
||||
'social_twitter' => 'Twitter'
|
||||
'social_twitter' => 'Twitter',
|
||||
'social_twitter_no_services' => 'You haven\'t defined any services for Twitter. Add a new service with your Twitter app API key and secret.',
|
||||
],
|
||||
'settings_email_tab' => 'E-mail',
|
||||
'settings_general_tab' => 'General',
|
||||
|
@ -82,16 +82,14 @@ return [
|
||||
'settings_moderate_known_users_help' => 'If this option is enabled, comments posted by logged-in users must be moderated before being displayed.',
|
||||
'settings_restrict_originals_download' => 'Restrict access to original images',
|
||||
'settings_restrict_originals_download_help' => 'With this option enabled, only the photo\'s owner can download the original high-resolution images.',
|
||||
'settings_social_facebook_app_id' => 'Facebook App ID:',
|
||||
'settings_social_facebook_app_secret' => 'Facebook App Secret:',
|
||||
'settings_social_external_services_edit_link' => 'Add or change these details in Services',
|
||||
'settings_social_facebook_external_service' => 'Facebook service:',
|
||||
'settings_social_facebook_login' => 'Allow login/registration with a Facebook account.',
|
||||
'settings_social_facebook_login_help' => 'With this option enabled, users can register (if enabled) and login with their Facebook account.',
|
||||
'settings_social_google_app_id' => 'Google App ID:',
|
||||
'settings_social_google_app_secret' => 'Google App Secret:',
|
||||
'settings_social_google_external_service' => 'Google service:',
|
||||
'settings_social_google_login' => 'Allow login/registration with a Google account.',
|
||||
'settings_social_google_login_help' => 'With this option enabled, users can register (if enabled) and login with their Google account.',
|
||||
'settings_social_twitter_app_id' => 'Twitter App ID:',
|
||||
'settings_social_twitter_app_secret' => 'Twitter App Secret:',
|
||||
'settings_social_twitter_external_service' => 'Twitter service:',
|
||||
'settings_social_twitter_login' => 'Allow login/registration with a Twitter account',
|
||||
'settings_social_twitter_login_help' => 'With this option enabled, users can register (if enabled) and login with their Twitter account.',
|
||||
'settings_social_user_feeds' => 'Enable user feeds and following',
|
||||
|
@ -31,8 +31,4 @@
|
||||
|
||||
.text-red {
|
||||
color: #ff0000;
|
||||
}
|
||||
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
35
resources/sass/bootstrapper.scss
vendored
Normal file
35
resources/sass/bootstrapper.scss
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
#bootstrapper
|
||||
{
|
||||
[v-cloak] { display: none }
|
||||
|
||||
.operation
|
||||
{
|
||||
.status
|
||||
{
|
||||
display: inline-block;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
||||
i,
|
||||
img
|
||||
{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
span
|
||||
{
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul
|
||||
{
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
@ -27,4 +27,8 @@ textarea {
|
||||
border: solid 1px rgb(221, 221, 221);
|
||||
border-top: 0;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
{{-- As these files are shipped with core (not a theme) use the main app.version instead of the current theme's version --}}
|
||||
@if (App::environment() == 'production')
|
||||
<link href="css/blue-twilight.min.css?v={{ $app_version_url }}" rel="stylesheet" />
|
||||
<link href="themes/default/theme.css?v={{ $app_version_url }}" rel="stylesheet" />
|
||||
@else
|
||||
<link href="css/blue-twilight.css?v={{ $app_version_url }}" rel="stylesheet" />
|
||||
@endif
|
||||
|
@ -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>
|
||||
|
@ -19,6 +19,8 @@
|
||||
<form action="{{ route('services.store') }}" method="post" id="external-service-options">
|
||||
{{ csrf_field() }}
|
||||
|
||||
<input type="hidden" name="return_to" value="{{ $returnTo }}"/>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="service-type">@lang('forms.service_type_label')</label>
|
||||
<select class="form-control{{ $errors->has('service_type') ? ' is-invalid' : '' }}" id="service-type" name="service_type" value="{{ old('service_type') }}" v-model="service_type">
|
||||
@ -47,11 +49,17 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div v-if="hasOAuthStandardOptions">
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'))
|
||||
<div v-if="isDropbox" v-cloak>
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::DROPBOX])
|
||||
</div>
|
||||
<div v-elseif="isDropbox">
|
||||
@include(Theme::viewName('partials.admin_services_dropbox_options'))
|
||||
<div v-else-if="isFacebook" v-cloak>
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::FACEBOOK])
|
||||
</div>
|
||||
<div v-else-if="isTwitter" v-cloak>
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::TWITTER])
|
||||
</div>
|
||||
<div v-else-if="isGoogle" v-cloak>
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::GOOGLE])
|
||||
</div>
|
||||
|
||||
<div class="text-right">
|
||||
@ -71,8 +79,8 @@
|
||||
var viewModel = new ExternalServiceViewModel();
|
||||
var app = new Vue(viewModel);
|
||||
|
||||
@if (strlen(old('service_type')) > 0)
|
||||
app.service_type = '{{ old('service_type') }}';
|
||||
@if (strlen($selectedServiceType) > 0)
|
||||
app.service_type = '{{ $selectedServiceType }}';
|
||||
@endif
|
||||
});
|
||||
</script>
|
||||
|
@ -48,10 +48,14 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@if ($service->hasOAuthStandardOptions())
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'))
|
||||
@if ($service->isFacebook())
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::FACEBOOK])
|
||||
@elseif ($service->isGoogle())
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::GOOGLE])
|
||||
@elseif ($service->isDropbox())
|
||||
@include(Theme::viewName('partials.admin_services_dropbox_options'))
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::DROPBOX])
|
||||
@elseif ($service->isTwitter())
|
||||
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::TWITTER])
|
||||
@endif
|
||||
|
||||
<div class="text-right" style="margin-top: 20px;">
|
||||
|
@ -499,35 +499,37 @@
|
||||
@lang('admin.settings.social_facebook')
|
||||
</legend>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="social-facebook-login" name="social_facebook_login" @if (old('social_facebook_login', $config['social_facebook_login']))checked="checked"@endif>
|
||||
<label class="form-check-label" for="social-facebook-login">
|
||||
<strong>@lang('forms.settings_social_facebook_login')</strong><br/>
|
||||
@lang('forms.settings_social_facebook_login_help')
|
||||
</label>
|
||||
</div>
|
||||
@if (count($facebookServices) == 0)
|
||||
<div class="alert alert-info">
|
||||
<p>@lang('admin.settings.social_facebook_no_services')</p>
|
||||
<p class="mb-0"><a href="{{ route('services.create', ['service_type' => \App\ExternalService::FACEBOOK, 'return_to' => 'settings']) }}"><i class="fas fa-fw fa-sync"></i> @lang('admin.settings.social_add_external_services_link')</a></p>
|
||||
</div>
|
||||
@else
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="social-facebook-login" name="social_facebook_login" @if (old('social_facebook_login', $config['social_facebook_login']))checked="checked"@endif>
|
||||
<label class="form-check-label" for="social-facebook-login">
|
||||
<strong>@lang('forms.settings_social_facebook_login')</strong><br/>
|
||||
@lang('forms.settings_social_facebook_login_help')
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="facebook-app-id">@lang('forms.settings_social_facebook_app_id')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('facebook_app_id') ? ' is-invalid' : '' }}" id="facebook-app-id" name="facebook_app_id" value="{{ old('facebook_app_id', $config['facebook_app_id']) }}">
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="facebook-app-id">@lang('forms.settings_social_facebook_external_service')</label>
|
||||
<select name="facebook_external_service_id" class="form-control{{ $errors->has('facebook_external_service_id') ? ' is-invalid' : '' }}">
|
||||
<option value="0"{{ is_null(old('facebook_external_service_id', $config['facebook_external_service_id']) ? ' selected="selected"' : '') }}>@lang('forms.please_select')</option>
|
||||
@foreach ($facebookServices as $service)
|
||||
<option value="{{ $service->id }}"{{ old('facebook_external_service_id', $config['facebook_external_service_id'] == $service->id ? ' selected="selected"' : '') }}>{{ $service->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="form-text text-muted mt-2"><a href="{{ route('services.index') }}"><i class="fas fa-sync fa-fw"></i> @lang('forms.settings_social_external_services_edit_link')</a></span>
|
||||
|
||||
@if ($errors->has('facebook_app_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('facebook_app_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="facebook-app-secret">@lang('forms.settings_social_facebook_app_secret')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('facebook_app_secret') ? ' is-invalid' : '' }}" id="facebook-app-secret" name="facebook_app_secret" value="{{ old('facebook_app_secret', $config['facebook_app_secret']) }}">
|
||||
|
||||
@if ($errors->has('facebook_app_secret'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('facebook_app_secret') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($errors->has('facebook_external_service_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('facebook_external_service_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
@ -546,35 +548,37 @@
|
||||
@lang('admin.settings.social_twitter')
|
||||
</legend>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="social-twitter-login" name="social_twitter_login" @if (old('social_twitter_login', $config['social_twitter_login']))checked="checked"@endif>
|
||||
<label class="form-check-label" for="social-twitter-login">
|
||||
<strong>@lang('forms.settings_social_twitter_login')</strong><br/>
|
||||
@lang('forms.settings_social_twitter_login_help')
|
||||
</label>
|
||||
</div>
|
||||
@if (count($twitterServices) == 0)
|
||||
<div class="alert alert-info">
|
||||
<p>@lang('admin.settings.social_twitter_no_services')</p>
|
||||
<p class="mb-0"><a href="{{ route('services.create', ['service_type' => \App\ExternalService::TWITTER, 'return_to' => 'settings']) }}"><i class="fas fa-fw fa-sync"></i> @lang('admin.settings.social_add_external_services_link')</a></p>
|
||||
</div>
|
||||
@else
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="social-twitter-login" name="social_twitter_login" @if (old('social_twitter_login', $config['social_twitter_login']))checked="checked"@endif>
|
||||
<label class="form-check-label" for="social-twitter-login">
|
||||
<strong>@lang('forms.settings_social_twitter_login')</strong><br/>
|
||||
@lang('forms.settings_social_twitter_login_help')
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="twitter-app-id">@lang('forms.settings_social_twitter_app_id')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('twitter_app_id') ? ' is-invalid' : '' }}" id="twitter-app-id" name="twitter_app_id" value="{{ old('twitter_app_id', $config['twitter_app_id']) }}">
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="twitter-app-id">@lang('forms.settings_social_twitter_external_service')</label>
|
||||
<select name="twitter_external_service_id" class="form-control{{ $errors->has('twitter_external_service_id') ? ' is-invalid' : '' }}">
|
||||
<option value="0"{{ is_null(old('twitter_external_service_id', $config['twitter_external_service_id']) ? ' selected="selected"' : '') }}>@lang('forms.please_select')</option>
|
||||
@foreach ($twitterServices as $service)
|
||||
<option value="{{ $service->id }}"{{ old('twitter_external_service_id', $config['twitter_external_service_id'] == $service->id ? ' selected="selected"' : '') }}>{{ $service->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="form-text text-muted mt-2"><a href="{{ route('services.index') }}"><i class="fas fa-sync fa-fw"></i> @lang('forms.settings_social_external_services_edit_link')</a></span>
|
||||
|
||||
@if ($errors->has('twitter_app_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('twitter_app_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="twitter-app-secret">@lang('forms.settings_social_twitter_app_secret')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('twitter_app_secret') ? ' is-invalid' : '' }}" id="twitter-app-secret" name="twitter_app_secret" value="{{ old('twitter_app_secret', $config['twitter_app_secret']) }}">
|
||||
|
||||
@if ($errors->has('twitter_app_secret'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('twitter_app_secret') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@if ($errors->has('twitter_external_service_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('twitter_external_service_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
@ -593,32 +597,34 @@
|
||||
@lang('admin.settings.social_google')
|
||||
</legend>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="social-google-login" name="social_google_login" @if (old('social_google_login', $config['social_google_login']))checked="checked"@endif>
|
||||
<label class="form-check-label" for="social-google-login">
|
||||
<strong>@lang('forms.settings_social_google_login')</strong><br/>
|
||||
@lang('forms.settings_social_google_login_help')
|
||||
</label>
|
||||
</div>
|
||||
@if (count($googleServices) == 0)
|
||||
<div class="alert alert-info">
|
||||
<p>@lang('admin.settings.social_google_no_services')</p>
|
||||
<p class="mb-0"><a href="{{ route('services.create', ['service_type' => \App\ExternalService::GOOGLE, 'return_to' => 'settings']) }}"><i class="fas fa-fw fa-sync"></i> @lang('admin.settings.social_add_external_services_link')</a></p>
|
||||
</div>
|
||||
@else
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="social-google-login" name="social_google_login" @if (old('social_google_login', $config['social_google_login']))checked="checked"@endif>
|
||||
<label class="form-check-label" for="social-google-login">
|
||||
<strong>@lang('forms.settings_social_google_login')</strong><br/>
|
||||
@lang('forms.settings_social_google_login_help')
|
||||
</label>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="google-app-id">@lang('forms.settings_social_google_app_id')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('google_app_id') ? ' is-invalid' : '' }}" id="google-app-id" name="google_app_id" value="{{ old('google_app_id', $config['google_app_id']) }}">
|
||||
<label class="form-control-label" for="google-app-id">@lang('forms.settings_social_google_external_service')</label>
|
||||
<select name="google_external_service_id" class="form-control{{ $errors->has('google_external_service_id') ? ' is-invalid' : '' }}">
|
||||
<option value="0"{{ is_null(old('google_external_service_id', $config['google_external_service_id']) ? ' selected="selected"' : '') }}>@lang('forms.please_select')</option>
|
||||
@foreach ($googleServices as $service)
|
||||
<option value="{{ $service->id }}"{{ old('google_external_service_id', $config['google_external_service_id'] == $service->id ? ' selected="selected"' : '') }}>{{ $service->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="form-text text-muted mt-2"><a href="{{ route('services.index') }}"><i class="fas fa-sync fa-fw"></i> @lang('forms.settings_social_external_services_edit_link')</a></span>
|
||||
|
||||
@if ($errors->has('google_app_id'))
|
||||
@if ($errors->has('google_external_service_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('google_app_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-3">
|
||||
<label class="form-control-label" for="google-app-secret">@lang('forms.settings_social_google_app_secret')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('google_app_secret') ? ' is-invalid' : '' }}" id="google-app-secret" name="google_app_secret" value="{{ old('google_app_secret', $config['google_app_secret']) }}">
|
||||
|
||||
@if ($errors->has('google_app_secret'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('google_app_secret') }}</strong>
|
||||
<strong>{{ $errors->first('google_external_service_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
@ -1,31 +0,0 @@
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="access-key">@lang('forms.service_app_id_label')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('app_id') ? ' is-invalid' : '' }}" id="app-id" name="app_id" value="{{ old('app_id', $service->app_id) }}">
|
||||
|
||||
@if ($errors->has('app_id'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('app_id') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="secret-key">@lang('forms.service_app_secret_label')</label>
|
||||
<input type="text" class="form-control{{ $errors->has('app_secret') ? ' is-invalid' : '' }}" id="app-secret" name="app_secret" value="{{ old('app_secret', $service->app_secret) }}">
|
||||
|
||||
@if ($errors->has('app_secret'))
|
||||
<div class="invalid-feedback">
|
||||
<strong>{{ $errors->first('app_secret') }}</strong>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<p>@lang('admin.service_callback_intro', ['name' => trans(sprintf('services.%s', \App\ExternalService::DROPBOX))])</p>
|
||||
<p class="mb-0"><b>{{ $callbackUrls[\App\ExternalService::DROPBOX] }}</b></p>
|
||||
</div>
|
@ -23,4 +23,11 @@
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (isset($callbackUrls[$oauthService]))
|
||||
<div class="alert alert-info">
|
||||
<p>@lang('admin.service_callback_intro', ['name' => trans(sprintf('services.%s', $oauthService))])</p>
|
||||
<p class="mb-0"><b>{{ $callbackUrls[$oauthService] }}</b></p>
|
||||
</div>
|
||||
@endif
|
@ -1,11 +1,11 @@
|
||||
<p class="text-center" style="font-size: xx-large;">
|
||||
@if (UserConfig::get('social_facebook_login'))
|
||||
<a href="{{ route('login.facebook') }}"><i class="fa fa-facebook fa-fw"></i></a>
|
||||
@if (UserConfig::isLoginWithFacebookEnabled())
|
||||
<a href="{{ route('login.facebook') }}"><i class="fab fa-facebook fa-fw"></i></a>
|
||||
@endif
|
||||
@if (UserConfig::get('social_twitter_login'))
|
||||
<a href="{{ route('login.twitter') }}"><i class="fa fa-twitter fa-fw"></i></a>
|
||||
@if (UserConfig::isLoginWithTwitterEnabled())
|
||||
<a href="{{ route('login.twitter') }}"><i class="fab fa-twitter fa-fw"></i></a>
|
||||
@endif
|
||||
@if (UserConfig::get('social_google_login'))
|
||||
<a href="{{ route('login.google') }}"><i class="fa fa-google fa-fw"></i></a>
|
||||
@if (UserConfig::isLoginWithGoogleEnabled())
|
||||
<a href="{{ route('login.google') }}"><i class="fab fa-google fa-fw"></i></a>
|
||||
@endif
|
||||
</p>
|
@ -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');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user