'; // 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 '
-downloadUrl, $authorize_account_result->authorizationToken); ?>
diff --git a/public/bootstrap/composer.json b/public/bootstrap/composer.json
new file mode 100644
index 0000000..27c2f40
--- /dev/null
+++ b/public/bootstrap/composer.json
@@ -0,0 +1,26 @@
+{
+ "name": "aheathershaw/blue-twilight-bootstrapper",
+ "description": "Bootstrapper component 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/",
+ "AppBootstrap\\": "src/"
+ }
+ }
+}
\ No newline at end of file
diff --git a/public/bootstrap/helpers.php b/public/bootstrap/helpers.php
new file mode 100644
index 0000000..867f9fc
--- /dev/null
+++ b/public/bootstrap/helpers.php
@@ -0,0 +1,12 @@
+= strlen($stringToFind) &&
+ substr(strtolower($stringToCheck), strlen($stringToCheck) - strlen($stringToFind), strlen($stringToFind)) == strtolower($stringToFind);
+}
+
+function starts_with($stringToCheck, $stringToFind)
+{
+ return strlen($stringToCheck) >= strlen($stringToFind) &&
+ substr(strtolower($stringToCheck), 0, strlen($stringToFind)) == strtolower($stringToFind);
+}
\ No newline at end of file
diff --git a/public/bootstrap/images/completed.svg b/public/bootstrap/images/completed.svg
new file mode 100644
index 0000000..517ce74
--- /dev/null
+++ b/public/bootstrap/images/completed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/bootstrap/images/loading.svg b/public/bootstrap/images/loading.svg
new file mode 100644
index 0000000..c0f8953
--- /dev/null
+++ b/public/bootstrap/images/loading.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/public/bootstrap/images/waiting.svg b/public/bootstrap/images/waiting.svg
new file mode 100644
index 0000000..f93f32a
--- /dev/null
+++ b/public/bootstrap/images/waiting.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/bootstrap/index.php b/public/bootstrap/index.php
new file mode 100644
index 0000000..da5781b
--- /dev/null
+++ b/public/bootstrap/index.php
@@ -0,0 +1,25 @@
+handleRequest();
+}
+catch (\Exception $ex)
+{
+ echo sprintf('ERROR: %s', $ex);
+}
\ No newline at end of file
diff --git a/public/bootstrap/src/Bootstrapper.php b/public/bootstrap/src/Bootstrapper.php
new file mode 100644
index 0000000..36f9e7e
--- /dev/null
+++ b/public/bootstrap/src/Bootstrapper.php
@@ -0,0 +1,136 @@
+rootDir = dirname(__DIR__);
+ $this->configDir = sprintf('%s/config', dirname(dirname($this->rootDir)));
+ $this->tempDir = sprintf('%s/temp', $this->rootDir);
+ $this->viewsDir = sprintf('%s/views', $this->rootDir);
+ }
+
+ public function handleRequest()
+ {
+ if (!isset($_GET['act']))
+ {
+ $this->view('index', ['appName' => 'Blue Twilight Bootstrapper']);
+ }
+ else
+ {
+ switch (trim($_GET['act']))
+ {
+ case 'download':
+ $this->download();
+ return;
+
+ default:
+ throw new \Exception(sprintf('ERROR: Action \'%s\' was not recognised.', $_GET['act']));
+ }
+ }
+ }
+
+ private function download()
+ {
+ $appConfig = require_once sprintf('%s/app.php', $this->configDir);
+ $servicesConfig = require_once sprintf('%s/services.php', $this->configDir);
+
+ $versionNumber = sprintf('v%s', $appConfig['version']);
+
+ $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 \'%\'', $versionNumber));
+ }
+ else if (!isset($releaseInfo->assets))
+ {
+ throw new \Exception(sprintf('No assets found in Gitea for Blue Twilight version \'%\'', $versionNumber));
+ }
+
+ $vendorsPrefix = 'vendors';
+ $vendorsSuffix = '.tar.gz';
+ $selectedAsset = null;
+ foreach ($releaseInfo->assets as $asset)
+ {
+ /*
+ Ignore anything that is not "vendors.tar.gz" were the 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('No vendors.tar.gz found in Gitea for Blue Twilight version \'%\'', $versionNumber);
+ }
+
+ $targetFileName = sprintf('%s/vendors.tar.gz', $this->tempDir);
+
+ $this->downloadFile($selectedAsset->browser_download_url, $targetFileName);
+ var_dump('done');
+ }
+
+ 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 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;
+ }
+}
\ No newline at end of file
diff --git a/public/bootstrap/temp/.gitignore b/public/bootstrap/temp/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/public/bootstrap/vendor/autoload.php b/public/bootstrap/vendor/autoload.php
new file mode 100644
index 0000000..400d928
--- /dev/null
+++ b/public/bootstrap/vendor/autoload.php
@@ -0,0 +1,7 @@
+
+ * Jordi Boggiano
+ *
+ * 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
+ * @author Jordi Boggiano
+ * @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;
+}
diff --git a/public/bootstrap/vendor/composer/LICENSE b/public/bootstrap/vendor/composer/LICENSE
new file mode 100644
index 0000000..f27399a
--- /dev/null
+++ b/public/bootstrap/vendor/composer/LICENSE
@@ -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.
+
diff --git a/public/bootstrap/vendor/composer/autoload_classmap.php b/public/bootstrap/vendor/composer/autoload_classmap.php
new file mode 100644
index 0000000..7a91153
--- /dev/null
+++ b/public/bootstrap/vendor/composer/autoload_classmap.php
@@ -0,0 +1,9 @@
+ array($baseDir . '/../../app'),
+ 'AppBootstrap\\' => array($baseDir . '/src'),
+);
diff --git a/public/bootstrap/vendor/composer/autoload_real.php b/public/bootstrap/vendor/composer/autoload_real.php
new file mode 100644
index 0000000..60669ec
--- /dev/null
+++ b/public/bootstrap/vendor/composer/autoload_real.php
@@ -0,0 +1,52 @@
+= 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\ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a::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;
+ }
+}
diff --git a/public/bootstrap/vendor/composer/autoload_static.php b/public/bootstrap/vendor/composer/autoload_static.php
new file mode 100644
index 0000000..23bfb55
--- /dev/null
+++ b/public/bootstrap/vendor/composer/autoload_static.php
@@ -0,0 +1,36 @@
+
+ array (
+ 'App\\' => 4,
+ 'AppBootstrap\\' => 13,
+ ),
+ );
+
+ public static $prefixDirsPsr4 = array (
+ 'App\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/../../app',
+ ),
+ 'AppBootstrap\\' =>
+ array (
+ 0 => __DIR__ . '/../..' . '/src',
+ ),
+ );
+
+ public static function getInitializer(ClassLoader $loader)
+ {
+ return \Closure::bind(function () use ($loader) {
+ $loader->prefixLengthsPsr4 = ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a::$prefixLengthsPsr4;
+ $loader->prefixDirsPsr4 = ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a::$prefixDirsPsr4;
+
+ }, null, ClassLoader::class);
+ }
+}
diff --git a/public/bootstrap/views/index.php b/public/bootstrap/views/index.php
new file mode 100644
index 0000000..641ab83
--- /dev/null
+++ b/public/bootstrap/views/index.php
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Welcome to Blue Twilight - the self-hosted PHP photo gallery.
+
+
+
We need to download and install a few more files before you get started.
+
Click the "Let's Go" button below to begin.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/public/index.php b/public/index.php
index 82fa173..7708cc8 100644
--- a/public/index.php
+++ b/public/index.php
@@ -10,7 +10,7 @@
/* Added by Andy - check to see if Composer/vendors are installed */
if (!file_exists(__DIR__.'/../vendor/autoload.php'))
{
- header('Location: install.php');
+ header('Location: bootstrap/');
exit();
}
/* End Added by Andy */
diff --git a/public/install.php b/public/install.php
deleted file mode 100644
index 0e6de00..0000000
--- a/public/install.php
+++ /dev/null
@@ -1,256 +0,0 @@
-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();
- }
-?>
-
-
- Blue Twilight Setup
-
-
-
Blue Twilight Setup
-
We need to download a few things - namely Composer and related packages - before we can kick off the Blue Twilight installer.
-
We can do this for you - simply click the button below.
-
This can take a few minutes so please be patient, and only click the button once!
-
-
-
-
Got Composer?
-
-
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:
-
Please note: "composer.phar" may actually be "composer" on your system.
-
cd baseDirectory; ?> /path/to/composer.phar install
This update routine ensures your Blue Twilight Composer packages are up-to-date.
-
To get started, simply click the button below.
-
This can take a few minutes so please be patient, and only click the button once!
-
-
-
-
Got Composer?
-
-
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:
-
Please note: "composer.phar" may actually be "composer" on your system.
- echoError('allow_url_fopen is disabled so we cannot use Composer');
- echo ' ';
- $this->echoError('You will need to install the vendor libraries manually - see this page for more details');
- 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("%s.%s", $message, PHP_EOL);
- }
-
- private function echoOK($message = '')
- {
- echo "OK";
-
- if (strlen($message) > 0)
- {
- echo sprintf('... %s', $message);
- }
-
- echo '' . 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();
\ No newline at end of file
diff --git a/resources/js/bootstrapper.js b/resources/js/bootstrapper.js
new file mode 100644
index 0000000..6a39dba
--- /dev/null
+++ b/resources/js/bootstrapper.js
@@ -0,0 +1,71 @@
+/**
+ * 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()
+ {
+ 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=cleanup'
+ });
+
+ this.isRunning = true;
+
+ this.runOperation(this.operations[0], 0);
+ },
+ runOperation(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;
+ }
+ })
+ }
+ }
+}
\ No newline at end of file
diff --git a/resources/sass/bootstrapper.scss b/resources/sass/bootstrapper.scss
new file mode 100644
index 0000000..d0ff4d4
--- /dev/null
+++ b/resources/sass/bootstrapper.scss
@@ -0,0 +1,33 @@
+#bootstrapper
+{
+ .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;
+ }
+}
\ No newline at end of file
From e06b227147356fe564fb3ede75ab0929b9fb6d80 Mon Sep 17 00:00:00 2001
From: Andy Heathershaw
Date: Sun, 26 Apr 2020 21:53:24 +0100
Subject: [PATCH 2/8] Completed the first interation of the new Bootstrapper
experience. Downloads and extracts vendors from Gitea and configures the
encryption key. Still need to get upgrades implemented. #146
---
.env.example | 6 +-
Gruntfile.js | 30 +++++
config/app.php | 2 +-
package.json | 2 +-
public/bootstrap/src/Bootstrapper.php | 162 ++++++++++++++++++++++++--
public/bootstrap/views/index.php | 12 +-
public/css/blue-twilight.css | 23 ++++
public/css/blue-twilight.min.css | 6 +
public/js/blue-twilight.js | 116 ++++++++++++++++--
public/js/blue-twilight.min.js | 2 +
public/js/blue-twilight.min.js.map | 1 +
resources/js/bootstrapper.js | 8 +-
resources/js/external_services.js | 4 +-
resources/sass/bootstrapper.scss | 2 +
14 files changed, 342 insertions(+), 34 deletions(-)
create mode 100644 public/css/blue-twilight.min.css
create mode 100644 public/js/blue-twilight.min.js
create mode 100644 public/js/blue-twilight.min.js.map
diff --git a/.env.example b/.env.example
index 3ba91c8..7b22e46 100644
--- a/.env.example
+++ b/.env.example
@@ -1,7 +1,7 @@
-APP_ENV=local
+APP_ENV=production
APP_KEY=
-APP_DEBUG=true
-APP_LOG_LEVEL=debug
+APP_DEBUG=false
+APP_LOG_LEVEL=warning
APP_URL=http://localhost
DB_CONNECTION=mysql
diff --git a/Gruntfile.js b/Gruntfile.js
index f2117c8..df50c8a 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -14,7 +14,9 @@ module.exports = function(grunt)
const sass = require('node-sass');
grunt.loadNpmTasks('grunt-contrib-clean');
+ grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-concat');
+ grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-curl');
grunt.loadNpmTasks('grunt-dart-sass');
grunt.loadNpmTasks('grunt-exec');
@@ -97,6 +99,23 @@ module.exports = function(grunt)
ext: '.css'
}]
},
+ },
+ cssmin: {
+ bt_css: {
+ files: {
+ 'public/css/blue-twilight.min.css': ['public/css/blue-twilight.css']
+ }
+ }
+ },
+ uglify: {
+ bt_js: {
+ options: {
+ sourceMap: true
+ },
+ files: {
+ 'public/js/blue-twilight.min.js': ['public/js/blue-twilight.js']
+ }
+ }
}
});
@@ -121,7 +140,18 @@ module.exports = function(grunt)
'concat:bt_js'
]);
+ grunt.registerTask('build-css-release', [
+ 'build-css-debug',
+ 'cssmin:bt_css'
+ ]);
+
+ grunt.registerTask('build-js-release', [
+ 'build-js-debug',
+ 'uglify:bt_js'
+ ]);
+
// Shortcut tasks for the ones above
grunt.registerTask('clean-all', ['clean:build_css', 'clean:build_js', 'clean:output']);
grunt.registerTask('build-debug', ['clean-all', 'build-css-debug', 'build-js-debug']);
+ grunt.registerTask('build-release', ['clean-all', 'build-css-release', 'build-js-release']);
};
\ No newline at end of file
diff --git a/config/app.php b/config/app.php
index 62c7e52..763a831 100644
--- a/config/app.php
+++ b/config/app.php
@@ -2,7 +2,7 @@
return [
// Version number of Blue Twilight
- 'version' => '2.1.2',
+ 'version' => '2.2.0-beta.1',
/*
|--------------------------------------------------------------------------
diff --git a/package.json b/package.json
index ca23a02..ed35856 100644
--- a/package.json
+++ b/package.json
@@ -12,4 +12,4 @@
"grunt-exec": "^3.0.0",
"node-sass": "^4.13.0"
}
-}
\ No newline at end of file
+}
diff --git a/public/bootstrap/src/Bootstrapper.php b/public/bootstrap/src/Bootstrapper.php
index 36f9e7e..19283a1 100644
--- a/public/bootstrap/src/Bootstrapper.php
+++ b/public/bootstrap/src/Bootstrapper.php
@@ -3,6 +3,7 @@
namespace AppBootstrap;
use App\Services\GiteaService;
+use Illuminate\Support\Facades\Artisan;
/**
* This class handles the downloading and extracting of the vendors directory.
@@ -13,17 +14,54 @@ use App\Services\GiteaService;
*/
class Bootstrapper
{
+ /**
+ * Path to /public/bootstrap
+ * @var string
+ */
+ private $bootstrapDir;
+
+ /**
+ * Path to /app/config
+ * @var string
+ */
private $configDir;
+
+ /**
+ * Path to / - the app's root
+ * @var string
+ */
private $rootDir;
+
+ /**
+ * Path to /public/bootstrap/temp
+ * @var string
+ */
private $tempDir;
+
+ /**
+ * Path to /vendor
+ * @var string
+ */
+ private $vendorDir;
+
+ /**
+ * Path to /public/bootstrap/views
+ * @var string
+ */
private $viewsDir;
public function __construct()
{
- $this->rootDir = dirname(__DIR__);
- $this->configDir = sprintf('%s/config', dirname(dirname($this->rootDir)));
- $this->tempDir = sprintf('%s/temp', $this->rootDir);
- $this->viewsDir = sprintf('%s/views', $this->rootDir);
+ $this->bootstrapDir = dirname(__DIR__);
+ $this->rootDir = dirname(dirname($this->bootstrapDir));
+
+ $this->configDir = sprintf('%s/config', dirname(dirname($this->bootstrapDir)));
+ $this->tempDir = sprintf('%s/temp', $this->bootstrapDir);
+ $this->vendorDir = sprintf('%s/vendor', $this->rootDir);
+ $this->viewsDir = sprintf('%s/views', $this->bootstrapDir);
+
+ chdir($this->rootDir);
+ putenv('HOME=' . $this->rootDir);
}
public function handleRequest()
@@ -40,13 +78,21 @@ class Bootstrapper
$this->download();
return;
+ case 'extract':
+ $this->extract();
+ return;
+
+ case 'finalise':
+ $this->finalise();
+ return;
+
default:
- throw new \Exception(sprintf('ERROR: Action \'%s\' was not recognised.', $_GET['act']));
+ throw new \Exception(sprintf('Action \'%s\' was not recognised.', $_GET['act']));
}
}
}
- private function download()
+ protected function download()
{
$appConfig = require_once sprintf('%s/app.php', $this->configDir);
$servicesConfig = require_once sprintf('%s/services.php', $this->configDir);
@@ -58,16 +104,17 @@ class Bootstrapper
if (is_null($releaseInfo))
{
- throw new \Exception(sprintf('No release info found in Gitea for Blue Twilight version \'%\'', $versionNumber));
+ 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 \'%\'', $versionNumber));
+ 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)
{
/*
@@ -87,13 +134,68 @@ class Bootstrapper
if (is_null($selectedAsset))
{
- throw new \Exception('No vendors.tar.gz found in Gitea for Blue Twilight version \'%\'', $versionNumber);
+ throw new \Exception(sprintf('No vendors.tar.gz found in Gitea for Blue Twilight version \'%s\'', $versionNumber));
}
- $targetFileName = sprintf('%s/vendors.tar.gz', $this->tempDir);
+ $targetFileName = $this->getVendorsTempFileName();
$this->downloadFile($selectedAsset->browser_download_url, $targetFileName);
- var_dump('done');
+ $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->json([
+ 'result' => true,
+ 'testFile' => $vendorsTestFile
+ ]);
+ }
+ else
+ {
+ throw new \Exception('The extraction failed');
+ }
+ }
+
+ protected function finalise()
+ {
+ $result = [
+ 'envFileCreated' => false
+ ];
+
+ $result['envFileCreated'] = $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)
@@ -120,6 +222,44 @@ class Bootstrapper
@fclose($tempFilename);
}
+ 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 json($data)
+ {
+ echo json_encode($data);
+ }
+
private function view($name, array $viewData = [])
{
$viewFile = sprintf('%s/%s.php', $this->viewsDir, $name);
diff --git a/public/bootstrap/views/index.php b/public/bootstrap/views/index.php
index 641ab83..58b3dce 100644
--- a/public/bootstrap/views/index.php
+++ b/public/bootstrap/views/index.php
@@ -3,7 +3,7 @@
-
+
+
+
+
Welcome to Blue Twilight - the self-hosted PHP photo gallery.
+
Your application/PHP environment have been checked and the results are below. Please correct any failed items before continuing.
+
-
-
-
+
+
+ Blue Twilight will automatically download the required third-party libraries when you
+ click Continue.
-
-
Welcome to Blue Twilight - the self-hosted PHP photo gallery.
-
-
We need to download and install a few more files before you get started.
-
Click the "Let's Go" button below to begin.
-
+ $items): ?>
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ $result): ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Blue Twilight cannot be installed until the issues identified above are rectified.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/public/install/index.php b/public/install/index.php
index a3fbeb2..9df9553 100644
--- a/public/install/index.php
+++ b/public/install/index.php
@@ -5,16 +5,6 @@ $installerDir = sprintf('%s/installer', dirname(dirname(__DIR__)));
require_once sprintf('%s/vendor/autoload.php', $installerDir);
require_once sprintf('%s/helpers.php', $installerDir);
-if (!function_exists('env'))
-{
- // Define a dummy env() function that always returns the default value so we can load the config/app.php file
- // to get the current version number
- function env($key, $default = null)
- {
- return $default;
- }
-}
-
try
{
$installer = new \AppInstaller\Installer();
diff --git a/public/update/images/completed.svg b/public/update/images/completed.svg
new file mode 100644
index 0000000..517ce74
--- /dev/null
+++ b/public/update/images/completed.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/update/images/loading.svg b/public/update/images/loading.svg
new file mode 100644
index 0000000..c0f8953
--- /dev/null
+++ b/public/update/images/loading.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/public/update/images/waiting.svg b/public/update/images/waiting.svg
new file mode 100644
index 0000000..f93f32a
--- /dev/null
+++ b/public/update/images/waiting.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/update/index.php b/public/update/index.php
new file mode 100644
index 0000000..f9b7ce8
--- /dev/null
+++ b/public/update/index.php
@@ -0,0 +1,17 @@
+setIsUpgrade(true);
+ $installer->handleRequest();
+}
+catch (\Exception $ex)
+{
+ echo sprintf('ERROR: %s', $ex);
+}
\ No newline at end of file
diff --git a/resources/views/install/navbar.blade.php b/resources/views/install/navbar.blade.php
index cb21d84..216162b 100644
--- a/resources/views/install/navbar.blade.php
+++ b/resources/views/install/navbar.blade.php
@@ -1,5 +1,5 @@
+@endif
\ No newline at end of file
diff --git a/resources/views/themes/base/partials/social_login_providers.blade.php b/resources/views/themes/base/partials/social_login_providers.blade.php
index 13b9377..f327bae 100644
--- a/resources/views/themes/base/partials/social_login_providers.blade.php
+++ b/resources/views/themes/base/partials/social_login_providers.blade.php
@@ -1,11 +1,11 @@
\ No newline at end of file
From 8f9a38649487f1f5835578a8db9487196452586f Mon Sep 17 00:00:00 2001
From: Andy Heathershaw
Date: Thu, 30 Apr 2020 08:38:37 +0100
Subject: [PATCH 8/8] Prevent deleting service definitions when they are in use
throughout the system. Closes #153
---
.../Controllers/Admin/ServiceController.php | 25 +++++++++++++++++--
resources/lang/en/admin.php | 2 +-
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/app/Http/Controllers/Admin/ServiceController.php b/app/Http/Controllers/Admin/ServiceController.php
index 464878c..32e3e0f 100644
--- a/app/Http/Controllers/Admin/ServiceController.php
+++ b/app/Http/Controllers/Admin/ServiceController.php
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Admin;
+use App\Configuration;
use App\ExternalService;
use App\Facade\Theme;
use App\Facade\UserConfig;
@@ -311,8 +312,28 @@ class ServiceController extends Controller
private function isServiceInUse(ExternalService $service)
{
- // TODO check if the service is in use anywhere else and prevent it being deleted if so
- return false;
+ switch ($service->service_type)
+ {
+ case ExternalService::FACEBOOK:
+ // Cannot delete Facebook service if it's set as the login provider
+ $facebookConfig = Configuration::where('key', 'facebook_external_service_id')->first();
+ return !is_null($facebookConfig) && intval($facebookConfig->value) == $service->id;
+
+ case ExternalService::GOOGLE:
+ // Cannot delete Google service if it's set as the login provider
+ $googleConfig = Configuration::where('key', 'google_external_service_id')->first();
+ return !is_null($googleConfig) && intval($googleConfig->value) == $service->id;
+
+ case ExternalService::DROPBOX:
+ return Storage::where('external_service_id', $service->id)->count() > 0;
+
+ case ExternalService::TWITTER:
+ // Cannot delete Twitter service if it's set as the login provider
+ $twitterConfig = Configuration::where('key', 'twitter_external_service_id')->first();
+ return !is_null($twitterConfig) && intval($twitterConfig->value) == $service->id;
+ }
+
+ return true;
}
private function serviceTypeList()
diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php
index 65a714a..2e5e9e1 100644
--- a/resources/lang/en/admin.php
+++ b/resources/lang/en/admin.php
@@ -72,7 +72,7 @@ return [
'bulk_photos_changed' => ':number photo was updated successfully.|:number photos were updated successfully.',
'bulk_photos_changed_queued' => 'Your requested change has been queued. :number photo will be updated shortly.|Your requested change has been queued. :number photos will be updated shortly.',
'cannot_delete_own_user_account' => 'It is not possible to delete your own user account. Please ask another administrator to delete it for you.',
- 'cannot_delete_service_in_use' => 'This service is still in use and cannot be deleted. Please remove any references to it in your configuration and try again.',
+ 'cannot_delete_service_in_use' => 'This service is still in use and cannot be deleted. Please remove any references to it in your configuration or storages and try again.',
'cannot_remove_own_admin' => 'You cannot remove your own administrator permissions. Please ask another administrator to remove the administrator permissions for you.',
'change_album_message' => 'Please select the album to move the photo(s) to:',
'change_album_title' => 'Move photo(s) to another album',