Improved Bootstrap experience and services improvements #154
@ -1,7 +1,7 @@
|
|||||||
APP_ENV=local
|
APP_ENV=production
|
||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=false
|
||||||
APP_LOG_LEVEL=debug
|
APP_LOG_LEVEL=warning
|
||||||
APP_URL=http://localhost
|
APP_URL=http://localhost
|
||||||
|
|
||||||
DB_CONNECTION=mysql
|
DB_CONNECTION=mysql
|
||||||
|
30
Gruntfile.js
30
Gruntfile.js
@ -14,7 +14,9 @@ module.exports = function(grunt)
|
|||||||
const sass = require('node-sass');
|
const sass = require('node-sass');
|
||||||
|
|
||||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-cssmin');
|
||||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||||
|
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||||
grunt.loadNpmTasks('grunt-curl');
|
grunt.loadNpmTasks('grunt-curl');
|
||||||
grunt.loadNpmTasks('grunt-dart-sass');
|
grunt.loadNpmTasks('grunt-dart-sass');
|
||||||
grunt.loadNpmTasks('grunt-exec');
|
grunt.loadNpmTasks('grunt-exec');
|
||||||
@ -97,6 +99,23 @@ module.exports = function(grunt)
|
|||||||
ext: '.css'
|
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'
|
'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
|
// Shortcut tasks for the ones above
|
||||||
grunt.registerTask('clean-all', ['clean:build_css', 'clean:build_js', 'clean:output']);
|
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-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
|
* @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.
|
* 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();
|
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()
|
public function isDropbox()
|
||||||
{
|
{
|
||||||
// This logic must be mirrored in external_services.js
|
// This logic must be mirrored in external_services.js
|
||||||
return $this->service_type == self::DROPBOX;
|
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],
|
'date_format' => $this->allowedDateFormats()[0],
|
||||||
'default_album_view' => $this->allowedAlbumViews()[0],
|
'default_album_view' => $this->allowedAlbumViews()[0],
|
||||||
'enable_visitor_hits' => false,
|
'enable_visitor_hits' => false,
|
||||||
'facebook_app_id' => '',
|
'facebook_external_service_id' => 0,
|
||||||
'facebook_app_secret' => '',
|
'google_external_service_id' => 0,
|
||||||
'google_app_id' => '',
|
|
||||||
'google_app_secret' => '',
|
|
||||||
'hotlink_protection' => false,
|
'hotlink_protection' => false,
|
||||||
'items_per_page' => 12,
|
'items_per_page' => 12,
|
||||||
'items_per_page_admin' => 10,
|
'items_per_page_admin' => 10,
|
||||||
@ -151,8 +149,7 @@ class ConfigHelper
|
|||||||
'social_user_feeds' => false,
|
'social_user_feeds' => false,
|
||||||
'social_user_profiles' => false,
|
'social_user_profiles' => false,
|
||||||
'theme' => 'default',
|
'theme' => 'default',
|
||||||
'twitter_app_id' => '',
|
'twitter_external_service_id' => 0
|
||||||
'twitter_app_secret' => '',
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,11 +216,29 @@ class ConfigHelper
|
|||||||
!empty($this->get('rabbitmq_vhost'));
|
!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()
|
public function isSocialMediaLoginEnabled()
|
||||||
{
|
{
|
||||||
return $this->get('social_facebook_login') ||
|
return $this->isLoginWithFacebookEnabled() ||
|
||||||
$this->get('social_twitter_login') ||
|
$this->isLoginWithGoogleEnabled() ||
|
||||||
$this->get('social_google_login');
|
$this->isLoginWithTwitterEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadCache()
|
private function loadCache()
|
||||||
|
@ -111,9 +111,9 @@ class MiscHelper
|
|||||||
return sprintf('%s/.env', dirname(dirname(__DIR__)));
|
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))
|
if (!file_exists($envFile))
|
||||||
{
|
{
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
use App\Album;
|
use App\Album;
|
||||||
|
use App\ExternalService;
|
||||||
use App\Facade\Theme;
|
use App\Facade\Theme;
|
||||||
use App\Facade\UserConfig;
|
use App\Facade\UserConfig;
|
||||||
use App\Group;
|
use App\Group;
|
||||||
@ -260,10 +261,8 @@ class DefaultController extends Controller
|
|||||||
'analysis_queue_storage_location',
|
'analysis_queue_storage_location',
|
||||||
'app_name',
|
'app_name',
|
||||||
'date_format',
|
'date_format',
|
||||||
'facebook_app_id',
|
'facebook_external_service_id',
|
||||||
'facebook_app_secret',
|
'google_external_service_id',
|
||||||
'google_app_id',
|
|
||||||
'google_app_secret',
|
|
||||||
'photo_comments_allowed_html',
|
'photo_comments_allowed_html',
|
||||||
'photo_comments_thread_depth',
|
'photo_comments_thread_depth',
|
||||||
'rabbitmq_server',
|
'rabbitmq_server',
|
||||||
@ -279,8 +278,7 @@ class DefaultController extends Controller
|
|||||||
'smtp_username',
|
'smtp_username',
|
||||||
'smtp_password',
|
'smtp_password',
|
||||||
'theme',
|
'theme',
|
||||||
'twitter_app_id',
|
'twitter_external_service_id',
|
||||||
'twitter_app_secret',
|
|
||||||
'recaptcha_site_key',
|
'recaptcha_site_key',
|
||||||
'recaptcha_secret_key',
|
'recaptcha_secret_key',
|
||||||
'analytics_code'
|
'analytics_code'
|
||||||
@ -374,12 +372,30 @@ class DefaultController extends Controller
|
|||||||
// Storage sources for the Image Processing tab
|
// Storage sources for the Image Processing tab
|
||||||
$storageSources = AnalysisQueueHelper::getCompatibleStorages();
|
$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', [
|
return Theme::render('admin.settings', [
|
||||||
'config' => $config,
|
'config' => $config,
|
||||||
'date_formats' => $dateFormatsLookup,
|
'date_formats' => $dateFormatsLookup,
|
||||||
|
'facebookServices' => $facebookServices,
|
||||||
|
'googleServices' => $googleServices,
|
||||||
'storage_sources' => $storageSources,
|
'storage_sources' => $storageSources,
|
||||||
'success' => $request->session()->get('success'),
|
'success' => $request->session()->get('success'),
|
||||||
'theme_names' => $themeNamesLookup
|
'theme_names' => $themeNamesLookup,
|
||||||
|
'twitterServices' => $twitterServices
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Http\Controllers\Admin;
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Configuration;
|
||||||
use App\ExternalService;
|
use App\ExternalService;
|
||||||
use App\Facade\Theme;
|
use App\Facade\Theme;
|
||||||
use App\Facade\UserConfig;
|
use App\Facade\UserConfig;
|
||||||
@ -90,14 +91,30 @@ class ServiceController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Http\Response
|
* @return \Illuminate\Http\Response
|
||||||
*/
|
*/
|
||||||
public function create()
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
$this->authorizeAccessToAdminPanel('admin:manage-services');
|
$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', [
|
return Theme::render('admin.create_service', [
|
||||||
'callbackUrls' => $this->callbackList(),
|
'callbackUrls' => $this->callbackList(),
|
||||||
|
'returnTo' => $returnTo,
|
||||||
|
'selectedServiceType' => $selectedServiceType,
|
||||||
'service' => new ExternalService(),
|
'service' => new ExternalService(),
|
||||||
'serviceTypes' => $this->serviceTypeList()
|
'serviceTypes' => $serviceTypes
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +253,14 @@ class ServiceController extends Controller
|
|||||||
|
|
||||||
$service->save();
|
$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'));
|
return redirect(route('services.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,14 +303,37 @@ class ServiceController extends Controller
|
|||||||
$dropboxService = new DropboxService();
|
$dropboxService = new DropboxService();
|
||||||
|
|
||||||
return [
|
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)
|
private function isServiceInUse(ExternalService $service)
|
||||||
{
|
{
|
||||||
// TODO check if the service is in use anywhere else and prevent it being deleted if so
|
switch ($service->service_type)
|
||||||
return false;
|
{
|
||||||
|
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()
|
private function serviceTypeList()
|
||||||
@ -297,4 +345,11 @@ class ServiceController extends Controller
|
|||||||
ExternalService::TWITTER => trans(sprintf('services.%s', ExternalService::TWITTER))
|
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;
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use App\ExternalService;
|
||||||
use App\Facade\Theme;
|
use App\Facade\Theme;
|
||||||
use App\Facade\UserConfig;
|
use App\Facade\UserConfig;
|
||||||
use App\Helpers\MiscHelper;
|
use App\Helpers\MiscHelper;
|
||||||
@ -152,7 +153,12 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function redirectToFacebook()
|
public function redirectToFacebook()
|
||||||
{
|
{
|
||||||
$socialite = $this->setSocialiteConfigs();
|
$socialite = $this->setSocialiteConfigForFacebook();
|
||||||
|
if (is_null($socialite))
|
||||||
|
{
|
||||||
|
return redirect(route('login'));
|
||||||
|
}
|
||||||
|
|
||||||
return $socialite->driver('facebook')->redirect();
|
return $socialite->driver('facebook')->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +169,12 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function redirectToGoogle()
|
public function redirectToGoogle()
|
||||||
{
|
{
|
||||||
$socialite = $this->setSocialiteConfigs();
|
$socialite = $this->setSocialiteConfigForGoogle();
|
||||||
|
if (is_null($socialite))
|
||||||
|
{
|
||||||
|
return redirect(route('login'));
|
||||||
|
}
|
||||||
|
|
||||||
return $socialite->driver('google')->redirect();
|
return $socialite->driver('google')->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +185,12 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function redirectToTwitter()
|
public function redirectToTwitter()
|
||||||
{
|
{
|
||||||
$socialite = $this->setSocialiteConfigs();
|
$socialite = $this->setSocialiteConfigForTwitter();
|
||||||
|
if (is_null($socialite))
|
||||||
|
{
|
||||||
|
return redirect(route('login'));
|
||||||
|
}
|
||||||
|
|
||||||
return $socialite->driver('twitter')->redirect();
|
return $socialite->driver('twitter')->redirect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,7 +201,12 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function handleFacebookCallback(Request $request)
|
public function handleFacebookCallback(Request $request)
|
||||||
{
|
{
|
||||||
$socialite = $this->setSocialiteConfigs();
|
$socialite = $this->setSocialiteConfigForFacebook();
|
||||||
|
if (is_null($socialite))
|
||||||
|
{
|
||||||
|
return redirect(route('login'));
|
||||||
|
}
|
||||||
|
|
||||||
$facebookUser = $socialite->driver('facebook')->user();
|
$facebookUser = $socialite->driver('facebook')->user();
|
||||||
|
|
||||||
return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser);
|
return $this->processSocialMediaLogin($request, 'facebook_id', $facebookUser);
|
||||||
@ -198,7 +219,12 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function handleGoogleCallback(Request $request)
|
public function handleGoogleCallback(Request $request)
|
||||||
{
|
{
|
||||||
$socialite = $this->setSocialiteConfigs();
|
$socialite = $this->setSocialiteConfigForGoogle();
|
||||||
|
if (is_null($socialite))
|
||||||
|
{
|
||||||
|
return redirect(route('login'));
|
||||||
|
}
|
||||||
|
|
||||||
$googleUser = $socialite->driver('google')->user();
|
$googleUser = $socialite->driver('google')->user();
|
||||||
|
|
||||||
return $this->processSocialMediaLogin($request, 'google_id', $googleUser);
|
return $this->processSocialMediaLogin($request, 'google_id', $googleUser);
|
||||||
@ -211,12 +237,30 @@ class LoginController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function handleTwitterCallback(Request $request)
|
public function handleTwitterCallback(Request $request)
|
||||||
{
|
{
|
||||||
$socialite = $this->setSocialiteConfigs();
|
$socialite = $this->setSocialiteConfigForTwitter();
|
||||||
|
if (is_null($socialite))
|
||||||
|
{
|
||||||
|
return redirect(route('login'));
|
||||||
|
}
|
||||||
|
|
||||||
$twitterUser = $socialite->driver('twitter')->user();
|
$twitterUser = $socialite->driver('twitter')->user();
|
||||||
|
|
||||||
return $this->processSocialMediaLogin($request, 'twitter_id', $twitterUser);
|
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)
|
private function processSocialMediaLogin(Request $request, $socialMediaIdField, $socialMediaUser)
|
||||||
{
|
{
|
||||||
$userBySocialMediaId = User::where($socialMediaIdField, $socialMediaUser->getId())->first();
|
$userBySocialMediaId = User::where($socialMediaIdField, $socialMediaUser->getId())->first();
|
||||||
@ -260,38 +304,81 @@ class LoginController extends Controller
|
|||||||
return redirect(route('auth.register_sso'));
|
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 = app()->make(\Laravel\Socialite\Contracts\Factory::class);
|
||||||
$socialite->extend(
|
$socialite->extend(
|
||||||
'facebook',
|
'facebook',
|
||||||
function ($app) use ($socialite) {
|
function ($app) use ($socialite, $facebookConfig) {
|
||||||
$config = [
|
$config = [
|
||||||
'client_id' => trim(UserConfig::get('facebook_app_id')),
|
'client_id' => trim(decrypt($facebookConfig->app_id)),
|
||||||
'client_secret' => trim(decrypt(UserConfig::get('facebook_app_secret'))),
|
'client_secret' => trim(decrypt($facebookConfig->app_secret)),
|
||||||
'redirect' => route('login_callback.facebook')
|
'redirect' => route('login_callback.facebook')
|
||||||
];
|
];
|
||||||
return $socialite->buildProvider(FacebookProvider::class, $config);
|
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(
|
$socialite->extend(
|
||||||
'google',
|
'google',
|
||||||
function ($app) use ($socialite) {
|
function ($app) use ($socialite, $googleConfig) {
|
||||||
$config = [
|
$config = [
|
||||||
'client_id' => trim(UserConfig::get('google_app_id')),
|
'client_id' => trim(decrypt($googleConfig->app_id)),
|
||||||
'client_secret' => trim(decrypt(UserConfig::get('google_app_secret'))),
|
'client_secret' => trim(decrypt($googleConfig->app_secret)),
|
||||||
'redirect' => route('login_callback.google')
|
'redirect' => route('login_callback.google')
|
||||||
];
|
];
|
||||||
return $socialite->buildProvider(GoogleProvider::class, $config);
|
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(
|
$socialite->extend(
|
||||||
'twitter',
|
'twitter',
|
||||||
function ($app) use ($socialite) {
|
function ($app) use ($socialite, $twitterConfig) {
|
||||||
$config = [
|
$config = [
|
||||||
'identifier' => trim(UserConfig::get('twitter_app_id')),
|
'identifier' => trim(decrypt($twitterConfig->app_id)),
|
||||||
'secret' => trim(decrypt(UserConfig::get('twitter_app_secret'))),
|
'secret' => trim(decrypt($twitterConfig->app_secret)),
|
||||||
'callback_uri' => route('login_callback.twitter')
|
'callback_uri' => route('login_callback.twitter')
|
||||||
];
|
];
|
||||||
return new TwitterProvider($app['request'], new TwitterServer($config));
|
return new TwitterProvider($app['request'], new TwitterServer($config));
|
||||||
|
@ -19,10 +19,10 @@ class InstallController extends Controller
|
|||||||
public function administrator(StoreUserRequest $request)
|
public function administrator(StoreUserRequest $request)
|
||||||
{
|
{
|
||||||
// Validate we're at the required stage
|
// Validate we're at the required stage
|
||||||
$stage = 3;
|
$stage = 2;
|
||||||
if (intval($request->session()->get('install_stage')) < $stage)
|
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
|
// 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)
|
public function database(Request $request)
|
||||||
{
|
{
|
||||||
// Validate we're at the required stage
|
// This is the first installation step therefore it doesn't need to verify the stage
|
||||||
$stage = 2;
|
|
||||||
if (intval($request->session()->get('install_stage')) < $stage)
|
|
||||||
{
|
|
||||||
return redirect(route('install.check'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->method() == 'POST')
|
if ($request->method() == 'POST')
|
||||||
{
|
{
|
||||||
@ -162,7 +101,7 @@ class InstallController extends Controller
|
|||||||
// Default settings
|
// Default settings
|
||||||
$this->setConfigurationForNewSystems();
|
$this->setConfigurationForNewSystems();
|
||||||
|
|
||||||
$request->session()->put('install_stage', 3);
|
$request->session()->put('install_stage', 2);
|
||||||
return redirect(route('install.administrator'));
|
return redirect(route('install.administrator'));
|
||||||
}
|
}
|
||||||
catch (\Exception $ex)
|
catch (\Exception $ex)
|
||||||
|
@ -14,9 +14,6 @@ use Illuminate\Support\Facades\Log;
|
|||||||
|
|
||||||
class AppInstallation
|
class AppInstallation
|
||||||
{
|
{
|
||||||
private $baseDirectory;
|
|
||||||
private $environmentFilePath;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The application instance.
|
* The application instance.
|
||||||
*
|
*
|
||||||
@ -33,8 +30,6 @@ class AppInstallation
|
|||||||
public function __construct(Application $app)
|
public function __construct(Application $app)
|
||||||
{
|
{
|
||||||
$this->app = $app;
|
$this->app = $app;
|
||||||
$this->baseDirectory = dirname(dirname(dirname(__DIR__)));
|
|
||||||
$this->environmentFilePath = sprintf('%s/.env', $this->baseDirectory);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle(Request $request, Closure $next)
|
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
|
// See if the successful flag has been written to the .env file
|
||||||
$isAppInstalled = MiscHelper::getEnvironmentSetting('APP_INSTALLED');
|
$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/*'))
|
if ($request->is('install/*'))
|
||||||
{
|
{
|
||||||
// Already in the installer
|
// Already in the installer
|
||||||
@ -66,26 +69,40 @@ class AppInstallation
|
|||||||
if ($isAppInstalled)
|
if ($isAppInstalled)
|
||||||
{
|
{
|
||||||
// See if an update is necessary
|
// See if an update is necessary
|
||||||
$this->updateDatabaseIfRequired();
|
if ($this->updateDatabaseIfRequired())
|
||||||
|
{
|
||||||
|
return redirect($request->fullUrl());
|
||||||
|
}
|
||||||
|
|
||||||
// App is configured, continue on
|
// App is configured, continue on
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect(route('install.check'));
|
return redirect(route('install.database'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateAppKey()
|
private function generateAppKey()
|
||||||
{
|
{
|
||||||
// Generate an application key and store to the .env file
|
// Generate an application key and store to the .env file
|
||||||
if (!file_exists($this->environmentFilePath))
|
if (!file_exists(MiscHelper::getEnvironmentFilePath()))
|
||||||
{
|
{
|
||||||
$key = MiscHelper::randomString(32);
|
$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]]);
|
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()
|
private function updateDatabaseIfRequired()
|
||||||
{
|
{
|
||||||
$versionNumber = UserConfig::getOrCreateModel('app_version');
|
$versionNumber = UserConfig::getOrCreateModel('app_version');
|
||||||
@ -138,6 +155,10 @@ class AppInstallation
|
|||||||
// Rebuild the permissions cache
|
// Rebuild the permissions cache
|
||||||
$helper = new PermissionsHelper();
|
$helper = new PermissionsHelper();
|
||||||
$helper->rebuildCache();
|
$helper->rebuildCache();
|
||||||
}
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,12 +6,35 @@ class GiteaService
|
|||||||
{
|
{
|
||||||
private $cacheFile = null;
|
private $cacheFile = null;
|
||||||
private $config = [];
|
private $config = [];
|
||||||
|
private $currentVersionNumber;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct(array $config = null, $currentVersionNumber = null)
|
||||||
|
{
|
||||||
|
// 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');
|
$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');
|
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function checkForLatestRelease()
|
public function checkForLatestRelease()
|
||||||
{
|
{
|
||||||
@ -26,7 +49,7 @@ class GiteaService
|
|||||||
{
|
{
|
||||||
// Lookup and store the version information
|
// Lookup and store the version information
|
||||||
$statusCode = -1;
|
$statusCode = -1;
|
||||||
$result = $this->getLatestReleaseFromGitea($statusCode);
|
$result = $this->getReleasesFromGitea($statusCode);
|
||||||
|
|
||||||
if ($statusCode == 200)
|
if ($statusCode == 200)
|
||||||
{
|
{
|
||||||
@ -51,6 +74,31 @@ class GiteaService
|
|||||||
return $cacheData;
|
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()
|
private function doesCacheExist()
|
||||||
{
|
{
|
||||||
$exists = file_exists($this->cacheFile);
|
$exists = file_exists($this->cacheFile);
|
||||||
@ -75,10 +123,10 @@ class GiteaService
|
|||||||
return json_decode(file_get_contents($this->cacheFile));
|
return json_decode(file_get_contents($this->cacheFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getLatestReleaseFromGitea(&$statusCode)
|
private function getReleasesFromGitea(&$statusCode)
|
||||||
{
|
{
|
||||||
$httpHeaders = [
|
$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']))
|
if (isset($this->config['api_key']) && !empty($this->config['api_key']))
|
||||||
@ -105,8 +153,12 @@ class GiteaService
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function setCacheData($data)
|
private function setCacheData($data)
|
||||||
|
{
|
||||||
|
if (!is_null($this->cacheFile))
|
||||||
{
|
{
|
||||||
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||||
|
}
|
||||||
|
|
||||||
return $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",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9a11d044f41aef4c08fcddf00fd6f7ed",
|
"content-hash": "9dfa65a2590e8d0d5305a4be35a8b140",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-sdk-php",
|
"name": "aws/aws-sdk-php",
|
||||||
"version": "3.134.8",
|
"version": "3.135.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/aws/aws-sdk-php.git",
|
"url": "https://github.com/aws/aws-sdk-php.git",
|
||||||
"reference": "8a9b598a0ede2165be5988899dcebead6fcc4d41"
|
"reference": "fb6f4a12d9ad1b8fc1481aef61ed1f8a9fe2164b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/8a9b598a0ede2165be5988899dcebead6fcc4d41",
|
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/fb6f4a12d9ad1b8fc1481aef61ed1f8a9fe2164b",
|
||||||
"reference": "8a9b598a0ede2165be5988899dcebead6fcc4d41",
|
"reference": "fb6f4a12d9ad1b8fc1481aef61ed1f8a9fe2164b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -88,7 +88,7 @@
|
|||||||
"s3",
|
"s3",
|
||||||
"sdk"
|
"sdk"
|
||||||
],
|
],
|
||||||
"time": "2020-04-17T18:11:57+00:00"
|
"time": "2020-04-24T18:14:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/cache",
|
"name": "doctrine/cache",
|
||||||
@ -174,16 +174,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "doctrine/dbal",
|
"name": "doctrine/dbal",
|
||||||
"version": "v2.10.1",
|
"version": "2.10.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/doctrine/dbal.git",
|
"url": "https://github.com/doctrine/dbal.git",
|
||||||
"reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8"
|
"reference": "aab745e7b6b2de3b47019da81e7225e14dcfdac8"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/doctrine/dbal/zipball/c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8",
|
"url": "https://api.github.com/repos/doctrine/dbal/zipball/aab745e7b6b2de3b47019da81e7225e14dcfdac8",
|
||||||
"reference": "c2b8e6e82732a64ecde1cddf9e1e06cb8556e3d8",
|
"reference": "aab745e7b6b2de3b47019da81e7225e14dcfdac8",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -195,9 +195,11 @@
|
|||||||
"require-dev": {
|
"require-dev": {
|
||||||
"doctrine/coding-standard": "^6.0",
|
"doctrine/coding-standard": "^6.0",
|
||||||
"jetbrains/phpstorm-stubs": "^2019.1",
|
"jetbrains/phpstorm-stubs": "^2019.1",
|
||||||
"phpstan/phpstan": "^0.11.3",
|
"nikic/php-parser": "^4.4",
|
||||||
|
"phpstan/phpstan": "^0.12",
|
||||||
"phpunit/phpunit": "^8.4.1",
|
"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": {
|
"suggest": {
|
||||||
"symfony/console": "For helpful console commands such as SQL execution and import of files."
|
"symfony/console": "For helpful console commands such as SQL execution and import of files."
|
||||||
@ -262,7 +264,21 @@
|
|||||||
"sqlserver",
|
"sqlserver",
|
||||||
"sqlsrv"
|
"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",
|
"name": "doctrine/event-manager",
|
||||||
@ -838,16 +854,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/framework",
|
"name": "laravel/framework",
|
||||||
"version": "v6.18.8",
|
"version": "v6.18.10",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/laravel/framework.git",
|
"url": "https://github.com/laravel/framework.git",
|
||||||
"reference": "852c91c46adfbc2f5a0f6985cba3d7b7a769b773"
|
"reference": "9177744ccdd8d5db970fdff2383fe89c2e94aabe"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/laravel/framework/zipball/852c91c46adfbc2f5a0f6985cba3d7b7a769b773",
|
"url": "https://api.github.com/repos/laravel/framework/zipball/9177744ccdd8d5db970fdff2383fe89c2e94aabe",
|
||||||
"reference": "852c91c46adfbc2f5a0f6985cba3d7b7a769b773",
|
"reference": "9177744ccdd8d5db970fdff2383fe89c2e94aabe",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -980,7 +996,7 @@
|
|||||||
"framework",
|
"framework",
|
||||||
"laravel"
|
"laravel"
|
||||||
],
|
],
|
||||||
"time": "2020-04-15T20:56:03+00:00"
|
"time": "2020-04-21T18:53:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "laravel/socialite",
|
"name": "laravel/socialite",
|
||||||
@ -1048,16 +1064,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/commonmark",
|
"name": "league/commonmark",
|
||||||
"version": "1.3.4",
|
"version": "1.4.2",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/commonmark.git",
|
"url": "https://github.com/thephpleague/commonmark.git",
|
||||||
"reference": "dd3261eb9a322e009fa5d96d19b9ae19708ce04b"
|
"reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/dd3261eb9a322e009fa5d96d19b9ae19708ce04b",
|
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/9e780d972185e4f737a03bade0fd34a9e67bbf31",
|
||||||
"reference": "dd3261eb9a322e009fa5d96d19b9ae19708ce04b",
|
"reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1075,7 +1091,7 @@
|
|||||||
"github/gfm": "0.29.0",
|
"github/gfm": "0.29.0",
|
||||||
"michelf/php-markdown": "~1.4",
|
"michelf/php-markdown": "~1.4",
|
||||||
"mikehaertl/php-shellcommand": "^1.4",
|
"mikehaertl/php-shellcommand": "^1.4",
|
||||||
"phpstan/phpstan-shim": "^0.11.5",
|
"phpstan/phpstan": "^0.12",
|
||||||
"phpunit/phpunit": "^7.5",
|
"phpunit/phpunit": "^7.5",
|
||||||
"scrutinizer/ocular": "^1.5",
|
"scrutinizer/ocular": "^1.5",
|
||||||
"symfony/finder": "^4.2"
|
"symfony/finder": "^4.2"
|
||||||
@ -1118,7 +1134,33 @@
|
|||||||
"md",
|
"md",
|
||||||
"parser"
|
"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",
|
"name": "league/flysystem",
|
||||||
@ -1202,6 +1244,12 @@
|
|||||||
"sftp",
|
"sftp",
|
||||||
"storage"
|
"storage"
|
||||||
],
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://offset.earth/frankdejonge",
|
||||||
|
"type": "other"
|
||||||
|
}
|
||||||
|
],
|
||||||
"time": "2020-04-16T13:21:26+00:00"
|
"time": "2020-04-16T13:21:26+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1474,6 +1522,16 @@
|
|||||||
"datetime",
|
"datetime",
|
||||||
"time"
|
"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"
|
"time": "2020-03-31T13:43:19+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1584,16 +1642,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "php-amqplib/php-amqplib",
|
"name": "php-amqplib/php-amqplib",
|
||||||
"version": "v2.11.0",
|
"version": "v2.11.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/php-amqplib/php-amqplib.git",
|
"url": "https://github.com/php-amqplib/php-amqplib.git",
|
||||||
"reference": "9ee212baced63442ca1ab029acde38e1144a00b8"
|
"reference": "cfbfaf6262cd8d017f29862164f75e265d832434"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/9ee212baced63442ca1ab029acde38e1144a00b8",
|
"url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/cfbfaf6262cd8d017f29862164f75e265d832434",
|
||||||
"reference": "9ee212baced63442ca1ab029acde38e1144a00b8",
|
"reference": "cfbfaf6262cd8d017f29862164f75e265d832434",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -1602,6 +1660,9 @@
|
|||||||
"php": ">=5.6.3",
|
"php": ">=5.6.3",
|
||||||
"phpseclib/phpseclib": "^2.0.0"
|
"phpseclib/phpseclib": "^2.0.0"
|
||||||
},
|
},
|
||||||
|
"conflict": {
|
||||||
|
"php": "7.4.0 - 7.4.1"
|
||||||
|
},
|
||||||
"replace": {
|
"replace": {
|
||||||
"videlalvaro/php-amqplib": "self.version"
|
"videlalvaro/php-amqplib": "self.version"
|
||||||
},
|
},
|
||||||
@ -1654,7 +1715,7 @@
|
|||||||
"queue",
|
"queue",
|
||||||
"rabbitmq"
|
"rabbitmq"
|
||||||
],
|
],
|
||||||
"time": "2019-11-19T15:15:19+00:00"
|
"time": "2020-02-24T17:37:52+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "php-opencloud/openstack",
|
"name": "php-opencloud/openstack",
|
||||||
@ -1864,6 +1925,20 @@
|
|||||||
"x.509",
|
"x.509",
|
||||||
"x509"
|
"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"
|
"time": "2020-04-04T23:17:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2323,6 +2398,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Console Component",
|
"description": "Symfony Console Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-30T11:41:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2376,6 +2465,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony CssSelector Component",
|
"description": "Symfony CssSelector Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-27T16:56:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2432,6 +2535,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Debug Component",
|
"description": "Symfony Debug Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-27T16:54:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2488,6 +2605,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony ErrorHandler Component",
|
"description": "Symfony ErrorHandler Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-30T14:07:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2558,6 +2689,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony EventDispatcher Component",
|
"description": "Symfony EventDispatcher Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-27T16:54:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2665,6 +2810,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Finder Component",
|
"description": "Symfony Finder Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-27T16:54:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2720,6 +2879,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpFoundation Component",
|
"description": "Symfony HttpFoundation Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-30T14:07:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2810,6 +2983,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony HttpKernel Component",
|
"description": "Symfony HttpKernel Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-30T14:59:15+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2872,6 +3059,20 @@
|
|||||||
"mime",
|
"mime",
|
||||||
"mime-type"
|
"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"
|
"time": "2020-03-27T16:56:45+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2930,6 +3131,20 @@
|
|||||||
"polyfill",
|
"polyfill",
|
||||||
"portable"
|
"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"
|
"time": "2020-02-27T09:26:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2989,6 +3204,20 @@
|
|||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"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"
|
"time": "2020-03-09T19:04:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3051,6 +3280,20 @@
|
|||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"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"
|
"time": "2020-03-09T19:04:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3110,6 +3353,20 @@
|
|||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"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"
|
"time": "2020-03-09T19:04:49+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3165,6 +3422,20 @@
|
|||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"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"
|
"time": "2020-02-27T09:26:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3223,6 +3494,20 @@
|
|||||||
"portable",
|
"portable",
|
||||||
"shim"
|
"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"
|
"time": "2020-02-27T09:26:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3272,6 +3557,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Process Component",
|
"description": "Symfony Process Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-27T16:54:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3348,6 +3647,20 @@
|
|||||||
"uri",
|
"uri",
|
||||||
"url"
|
"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"
|
"time": "2020-03-30T11:41:10+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3482,6 +3795,20 @@
|
|||||||
],
|
],
|
||||||
"description": "Symfony Translation Component",
|
"description": "Symfony Translation Component",
|
||||||
"homepage": "https://symfony.com",
|
"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"
|
"time": "2020-03-27T16:54:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3615,6 +3942,20 @@
|
|||||||
"debug",
|
"debug",
|
||||||
"dump"
|
"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"
|
"time": "2020-03-27T16:54:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3727,6 +4068,12 @@
|
|||||||
"env",
|
"env",
|
||||||
"environment"
|
"environment"
|
||||||
],
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
"time": "2020-04-12T15:18:03+00:00"
|
"time": "2020-04-12T15:18:03+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -3839,6 +4186,12 @@
|
|||||||
"flare",
|
"flare",
|
||||||
"reporting"
|
"reporting"
|
||||||
],
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://www.patreon.com/spatie",
|
||||||
|
"type": "patreon"
|
||||||
|
}
|
||||||
|
],
|
||||||
"time": "2020-03-02T15:52:04+00:00"
|
"time": "2020-03-02T15:52:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -4332,24 +4685,21 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-common",
|
"name": "phpdocumentor/reflection-common",
|
||||||
"version": "2.0.0",
|
"version": "2.1.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
|
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
|
||||||
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
|
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
|
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
|
||||||
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
|
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=7.1"
|
"php": ">=7.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
|
||||||
"phpunit/phpunit": "~6"
|
|
||||||
},
|
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
"extra": {
|
||||||
"branch-alias": {
|
"branch-alias": {
|
||||||
@ -4380,7 +4730,7 @@
|
|||||||
"reflection",
|
"reflection",
|
||||||
"static analysis"
|
"static analysis"
|
||||||
],
|
],
|
||||||
"time": "2018-08-07T13:53:10+00:00"
|
"time": "2020-04-27T09:25:28+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpdocumentor/reflection-docblock",
|
"name": "phpdocumentor/reflection-docblock",
|
||||||
@ -4798,16 +5148,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "8.5.3",
|
"version": "8.5.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf"
|
"reference": "8474e22d7d642f665084ba5ec780626cbd1efd23"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8474e22d7d642f665084ba5ec780626cbd1efd23",
|
||||||
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf",
|
"reference": "8474e22d7d642f665084ba5ec780626cbd1efd23",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@ -4877,7 +5227,17 @@
|
|||||||
"testing",
|
"testing",
|
||||||
"xunit"
|
"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",
|
"name": "scrivo/highlight.php",
|
||||||
@ -4946,6 +5306,12 @@
|
|||||||
"highlight.php",
|
"highlight.php",
|
||||||
"syntax"
|
"syntax"
|
||||||
],
|
],
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/allejo",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
"time": "2020-03-02T05:59:21+00:00"
|
"time": "2020-03-02T05:59:21+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -5662,5 +6028,6 @@
|
|||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
"ext-json": "*"
|
"ext-json": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": []
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "1.1.0"
|
||||||
}
|
}
|
||||||
|
@ -28,11 +28,11 @@ return [
|
|||||||
],
|
],
|
||||||
|
|
||||||
'gitea' => [
|
'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,
|
'cache_time_seconds' => 3600,
|
||||||
'releases_url' => 'https://apps.andysh.uk/%s/%s/releases',
|
'releases_url' => env('GITEA_RELEASES_URL', 'https://apps.andysh.uk/%s/%s/releases'),
|
||||||
'repo_name' => 'blue-twilight',
|
'repo_name' => env('GITEA_REPO_NAME', 'blue-twilight'),
|
||||||
'repo_owner' => 'aheathershaw'
|
'repo_owner' => env('GITEA_REPO_OWNER', 'aheathershaw')
|
||||||
],
|
],
|
||||||
|
|
||||||
'rackspace' => [
|
'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()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::table('storages', function (Blueprint $table) {
|
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>
|
@ -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] {
|
[v-cloak] {
|
||||||
display: none;
|
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 {
|
.activity-grid {
|
||||||
font-size: smaller;
|
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 */
|
/* Added by Andy - check to see if Composer/vendors are installed */
|
||||||
if (!file_exists(__DIR__.'/../vendor/autoload.php'))
|
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();
|
exit();
|
||||||
}
|
}
|
||||||
/* End Added by Andy */
|
/* 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.isSuccessful = false;
|
||||||
item.isPending = 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) {
|
deletePhoto: function (e) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.selectPhotoSingle(e.target);
|
this.selectPhotoSingle(e.target);
|
||||||
|
var parent = $(e.target).closest('.photo');
|
||||||
|
|
||||||
var photo_id = self.photoIDs[0];
|
var photo_id = self.photoIDs[0];
|
||||||
this.photoIDs = [];
|
this.photoIDs = [];
|
||||||
@ -35846,7 +35853,7 @@ function EditPhotosViewModel(album_id, language, urls) {
|
|||||||
$('.loading', parent).show();
|
$('.loading', parent).show();
|
||||||
|
|
||||||
$.post(url, {'_method': 'DELETE'}, function (data) {
|
$.post(url, {'_method': 'DELETE'}, function (data) {
|
||||||
window.location.reload();
|
$(parent).remove();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35875,10 +35882,11 @@ function EditPhotosViewModel(album_id, language, urls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$('.loading', parent).show();
|
$('.loading', parent).show();
|
||||||
$.post(url, function () {
|
$.post(url, function (response) {
|
||||||
var image = $('img.photo-thumbnail', parent);
|
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();
|
$('.loading', parent).hide();
|
||||||
});
|
});
|
||||||
@ -35958,10 +35966,10 @@ function EditPhotosViewModel(album_id, language, urls) {
|
|||||||
url = url.replace(/\/0$/, '/' + this.photoIDs[0]);
|
url = url.replace(/\/0$/, '/' + this.photoIDs[0]);
|
||||||
|
|
||||||
$('.loading', parent).show();
|
$('.loading', parent).show();
|
||||||
$.post(url, function () {
|
$.post(url, function (response) {
|
||||||
var image = $('img.photo-thumbnail', parent);
|
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();
|
$('.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
|
* Chart.js
|
||||||
* http://chartjs.org/
|
* http://chartjs.org/
|
||||||
@ -54804,6 +54885,27 @@ module.exports = function(Chart) {
|
|||||||
|
|
||||||
},{"25":25,"45":45,"6":6}]},{},[7])(7)
|
},{"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.
|
* This model is used by gallery/explore_users.blade.php, to handle following/unfollowing users profiles.
|
||||||
* @constructor
|
* @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: ''
|
service_type: ''
|
||||||
};
|
};
|
||||||
this.computed = {
|
this.computed = {
|
||||||
hasOAuthStandardOptions()
|
isDropbox: function()
|
||||||
{
|
|
||||||
// This logic must be mirrored in App\ExternalService
|
|
||||||
return this.service_type === 'facebook' ||
|
|
||||||
this.service_type === 'google' ||
|
|
||||||
this.service_type === 'twitter';
|
|
||||||
},
|
|
||||||
isDropbox()
|
|
||||||
{
|
{
|
||||||
// This logic must be mirrored in App\ExternalService
|
// This logic must be mirrored in App\ExternalService
|
||||||
return this.service_type === 'dropbox';
|
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' => ':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.',
|
'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_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.',
|
'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_message' => 'Please select the album to move the photo(s) to:',
|
||||||
'change_album_title' => 'Move photo(s) to another album',
|
'change_album_title' => 'Move photo(s) to another album',
|
||||||
@ -314,10 +314,14 @@ return [
|
|||||||
'rebuild_permissions_cache_succeeded' => 'The permissions cache rebuild completed successfully.',
|
'rebuild_permissions_cache_succeeded' => 'The permissions cache rebuild completed successfully.',
|
||||||
'security_allow_self_registration' => 'Allow self-registration',
|
'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.',
|
'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' => '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' => '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_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_email_tab' => 'E-mail',
|
||||||
'settings_general_tab' => 'General',
|
'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_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' => '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_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_external_services_edit_link' => 'Add or change these details in Services',
|
||||||
'settings_social_facebook_app_secret' => 'Facebook App Secret:',
|
'settings_social_facebook_external_service' => 'Facebook service:',
|
||||||
'settings_social_facebook_login' => 'Allow login/registration with a Facebook account.',
|
'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_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_external_service' => 'Google service:',
|
||||||
'settings_social_google_app_secret' => 'Google App Secret:',
|
|
||||||
'settings_social_google_login' => 'Allow login/registration with a Google account.',
|
'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_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_external_service' => 'Twitter service:',
|
||||||
'settings_social_twitter_app_secret' => 'Twitter App Secret:',
|
|
||||||
'settings_social_twitter_login' => 'Allow login/registration with a Twitter account',
|
'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_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',
|
'settings_social_user_feeds' => 'Enable user feeds and following',
|
||||||
|
@ -32,7 +32,3 @@
|
|||||||
.text-red {
|
.text-red {
|
||||||
color: #ff0000;
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -28,3 +28,7 @@ textarea {
|
|||||||
border-top: 0;
|
border-top: 0;
|
||||||
padding: 20px;
|
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 --}}
|
{{-- 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')
|
@if (App::environment() == 'production')
|
||||||
<link href="css/blue-twilight.min.css?v={{ $app_version_url }}" rel="stylesheet" />
|
<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
|
@else
|
||||||
<link href="css/blue-twilight.css?v={{ $app_version_url }}" rel="stylesheet" />
|
<link href="css/blue-twilight.css?v={{ $app_version_url }}" rel="stylesheet" />
|
||||||
@endif
|
@endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<nav class="navbar bg-primary navbar-dark">
|
<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">
|
<div class="collapse navbar-collapse" id="navbar-content">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
<form action="{{ route('services.store') }}" method="post" id="external-service-options">
|
<form action="{{ route('services.store') }}" method="post" id="external-service-options">
|
||||||
{{ csrf_field() }}
|
{{ csrf_field() }}
|
||||||
|
|
||||||
|
<input type="hidden" name="return_to" value="{{ $returnTo }}"/>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-control-label" for="service-type">@lang('forms.service_type_label')</label>
|
<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">
|
<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
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="hasOAuthStandardOptions">
|
<div v-if="isDropbox" v-cloak>
|
||||||
@include(Theme::viewName('partials.admin_services_oauth_options'))
|
@include(Theme::viewName('partials.admin_services_oauth_options'), ['oauthService' => \App\ExternalService::DROPBOX])
|
||||||
</div>
|
</div>
|
||||||
<div v-elseif="isDropbox">
|
<div v-else-if="isFacebook" v-cloak>
|
||||||
@include(Theme::viewName('partials.admin_services_dropbox_options'))
|
@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>
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
@ -71,8 +79,8 @@
|
|||||||
var viewModel = new ExternalServiceViewModel();
|
var viewModel = new ExternalServiceViewModel();
|
||||||
var app = new Vue(viewModel);
|
var app = new Vue(viewModel);
|
||||||
|
|
||||||
@if (strlen(old('service_type')) > 0)
|
@if (strlen($selectedServiceType) > 0)
|
||||||
app.service_type = '{{ old('service_type') }}';
|
app.service_type = '{{ $selectedServiceType }}';
|
||||||
@endif
|
@endif
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -48,10 +48,14 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if ($service->hasOAuthStandardOptions())
|
@if ($service->isFacebook())
|
||||||
@include(Theme::viewName('partials.admin_services_oauth_options'))
|
@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())
|
@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
|
@endif
|
||||||
|
|
||||||
<div class="text-right" style="margin-top: 20px;">
|
<div class="text-right" style="margin-top: 20px;">
|
||||||
|
@ -499,6 +499,12 @@
|
|||||||
@lang('admin.settings.social_facebook')
|
@lang('admin.settings.social_facebook')
|
||||||
</legend>
|
</legend>
|
||||||
|
|
||||||
|
@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">
|
<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>
|
<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">
|
<label class="form-check-label" for="social-facebook-login">
|
||||||
@ -508,26 +514,22 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group mt-3">
|
<div class="form-group mt-3">
|
||||||
<label class="form-control-label" for="facebook-app-id">@lang('forms.settings_social_facebook_app_id')</label>
|
<label class="form-control-label" for="facebook-app-id">@lang('forms.settings_social_facebook_external_service')</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']) }}">
|
<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'))
|
@if ($errors->has('facebook_external_service_id'))
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
<strong>{{ $errors->first('facebook_app_id') }}</strong>
|
<strong>{{ $errors->first('facebook_external_service_id') }}</strong>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</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
|
@endif
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -546,6 +548,12 @@
|
|||||||
@lang('admin.settings.social_twitter')
|
@lang('admin.settings.social_twitter')
|
||||||
</legend>
|
</legend>
|
||||||
|
|
||||||
|
@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">
|
<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>
|
<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">
|
<label class="form-check-label" for="social-twitter-login">
|
||||||
@ -555,26 +563,22 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group mt-3">
|
<div class="form-group mt-3">
|
||||||
<label class="form-control-label" for="twitter-app-id">@lang('forms.settings_social_twitter_app_id')</label>
|
<label class="form-control-label" for="twitter-app-id">@lang('forms.settings_social_twitter_external_service')</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']) }}">
|
<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'))
|
@if ($errors->has('twitter_external_service_id'))
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
<strong>{{ $errors->first('twitter_app_id') }}</strong>
|
<strong>{{ $errors->first('twitter_external_service_id') }}</strong>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</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
|
@endif
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -593,6 +597,12 @@
|
|||||||
@lang('admin.settings.social_google')
|
@lang('admin.settings.social_google')
|
||||||
</legend>
|
</legend>
|
||||||
|
|
||||||
|
@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">
|
<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>
|
<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">
|
<label class="form-check-label" for="social-google-login">
|
||||||
@ -600,25 +610,21 @@
|
|||||||
@lang('forms.settings_social_google_login_help')
|
@lang('forms.settings_social_google_login_help')
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<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']) }}">
|
|
||||||
|
|
||||||
@if ($errors->has('google_app_id'))
|
|
||||||
<div class="invalid-feedback">
|
|
||||||
<strong>{{ $errors->first('google_app_id') }}</strong>
|
|
||||||
</div>
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group mt-3">
|
<div class="form-group mt-3">
|
||||||
<label class="form-control-label" for="google-app-secret">@lang('forms.settings_social_google_app_secret')</label>
|
<label class="form-control-label" for="google-app-id">@lang('forms.settings_social_google_external_service')</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']) }}">
|
<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_secret'))
|
@if ($errors->has('google_external_service_id'))
|
||||||
<div class="invalid-feedback">
|
<div class="invalid-feedback">
|
||||||
<strong>{{ $errors->first('google_app_secret') }}</strong>
|
<strong>{{ $errors->first('google_external_service_id') }}</strong>
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</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>
|
|
@ -24,3 +24,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</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;">
|
<p class="text-center" style="font-size: xx-large;">
|
||||||
@if (UserConfig::get('social_facebook_login'))
|
@if (UserConfig::isLoginWithFacebookEnabled())
|
||||||
<a href="{{ route('login.facebook') }}"><i class="fa fa-facebook fa-fw"></i></a>
|
<a href="{{ route('login.facebook') }}"><i class="fab fa-facebook fa-fw"></i></a>
|
||||||
@endif
|
@endif
|
||||||
@if (UserConfig::get('social_twitter_login'))
|
@if (UserConfig::isLoginWithTwitterEnabled())
|
||||||
<a href="{{ route('login.twitter') }}"><i class="fa fa-twitter fa-fw"></i></a>
|
<a href="{{ route('login.twitter') }}"><i class="fab fa-twitter fa-fw"></i></a>
|
||||||
@endif
|
@endif
|
||||||
@if (UserConfig::get('social_google_login'))
|
@if (UserConfig::isLoginWithGoogleEnabled())
|
||||||
<a href="{{ route('login.google') }}"><i class="fa fa-google fa-fw"></i></a>
|
<a href="{{ route('login.google') }}"><i class="fab fa-google fa-fw"></i></a>
|
||||||
@endif
|
@endif
|
||||||
</p>
|
</p>
|
@ -91,8 +91,6 @@ Route::group(['prefix' => 'admin'], function () {
|
|||||||
Route::group(['prefix' => 'install'], function () {
|
Route::group(['prefix' => 'install'], function () {
|
||||||
Route::get('/administrator', 'InstallController@administrator')->name('install.administrator');
|
Route::get('/administrator', 'InstallController@administrator')->name('install.administrator');
|
||||||
Route::post('/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::get('/database', 'InstallController@database')->name('install.database');
|
||||||
Route::post('/database', 'InstallController@database')->name('install.database');
|
Route::post('/database', 'InstallController@database')->name('install.database');
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user