Improved Bootstrap experience and services improvements #154
@ -6,11 +6,34 @@ class GiteaService
|
||||
{
|
||||
private $cacheFile = null;
|
||||
private $config = [];
|
||||
private $currentVersionNumber;
|
||||
|
||||
public function __construct()
|
||||
public function __construct(array $config = null, $currentVersionNumber = null)
|
||||
{
|
||||
$this->config = config('services.gitea');
|
||||
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||
// This class is used in the Bootstrapper to fetch release information, therefore
|
||||
// we need to check if the Laravel helper functions are loaded before we use them
|
||||
if (is_null($config) && function_exists('config'))
|
||||
{
|
||||
$this->config = config('services.gitea');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
if (is_null($currentVersionNumber) && function_exists('config'))
|
||||
{
|
||||
$this->currentVersionNumber = config('app.version');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->currentVersionNumber = $currentVersionNumber;
|
||||
}
|
||||
|
||||
if (function_exists('storage_path'))
|
||||
{
|
||||
$this->cacheFile = storage_path('app/gitea_cache.txt');
|
||||
}
|
||||
}
|
||||
|
||||
public function checkForLatestRelease()
|
||||
@ -26,7 +49,7 @@ class GiteaService
|
||||
{
|
||||
// Lookup and store the version information
|
||||
$statusCode = -1;
|
||||
$result = $this->getLatestReleaseFromGitea($statusCode);
|
||||
$result = $this->getReleasesFromGitea($statusCode);
|
||||
|
||||
if ($statusCode == 200)
|
||||
{
|
||||
@ -51,6 +74,31 @@ class GiteaService
|
||||
return $cacheData;
|
||||
}
|
||||
|
||||
public function getSpecificRelease($versionNumber)
|
||||
{
|
||||
$cacheData = null;
|
||||
|
||||
// Lookup and store the version information
|
||||
$statusCode = -1;
|
||||
$result = $this->getReleasesFromGitea($statusCode);
|
||||
|
||||
if ($statusCode == 200)
|
||||
{
|
||||
$releases = json_decode($result[1]);
|
||||
|
||||
$foundRelease = null;
|
||||
foreach ($releases as $release)
|
||||
{
|
||||
if (version_compare($release->tag_name, $versionNumber) === 0)
|
||||
{
|
||||
return $release;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function doesCacheExist()
|
||||
{
|
||||
$exists = file_exists($this->cacheFile);
|
||||
@ -75,10 +123,10 @@ class GiteaService
|
||||
return json_decode(file_get_contents($this->cacheFile));
|
||||
}
|
||||
|
||||
private function getLatestReleaseFromGitea(&$statusCode)
|
||||
private function getReleasesFromGitea(&$statusCode)
|
||||
{
|
||||
$httpHeaders = [
|
||||
sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', config('app.version'))
|
||||
sprintf('User-Agent: aheathershaw/blue-twilight (v%s)', $this->currentVersionNumber)
|
||||
];
|
||||
|
||||
if (isset($this->config['api_key']) && !empty($this->config['api_key']))
|
||||
@ -106,7 +154,11 @@ class GiteaService
|
||||
|
||||
private function setCacheData($data)
|
||||
{
|
||||
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||
if (!is_null($this->cacheFile))
|
||||
{
|
||||
file_put_contents($this->cacheFile, json_encode(get_object_vars($data)));
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
return [
|
||||
// Version number of Blue Twilight
|
||||
'version' => '2.2.0-beta.2',
|
||||
'version' => '2.1.2',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -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); ?>
|
26
public/bootstrap/composer.json
Normal file
26
public/bootstrap/composer.json
Normal file
@ -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/"
|
||||
}
|
||||
}
|
||||
}
|
12
public/bootstrap/helpers.php
Normal file
12
public/bootstrap/helpers.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
function ends_with($stringToCheck, $stringToFind)
|
||||
{
|
||||
return strlen($stringToCheck) >= 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);
|
||||
}
|
1
public/bootstrap/images/completed.svg
Normal file
1
public/bootstrap/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/bootstrap/images/loading.svg
Normal file
7
public/bootstrap/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/bootstrap/images/waiting.svg
Normal file
1
public/bootstrap/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 |
25
public/bootstrap/index.php
Normal file
25
public/bootstrap/index.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
require_once sprintf('%s/vendor/autoload.php', __DIR__);
|
||||
require_once sprintf('%s/helpers.php', __DIR__);
|
||||
|
||||
ini_set('display_errors', 'on');
|
||||
|
||||
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
|
||||
{
|
||||
$bs = new \AppBootstrap\Bootstrapper();
|
||||
$bs->handleRequest();
|
||||
}
|
||||
catch (\Exception $ex)
|
||||
{
|
||||
echo sprintf('ERROR: %s', $ex);
|
||||
}
|
136
public/bootstrap/src/Bootstrapper.php
Normal file
136
public/bootstrap/src/Bootstrapper.php
Normal file
@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
namespace AppBootstrap;
|
||||
|
||||
use App\Services\GiteaService;
|
||||
|
||||
/**
|
||||
* 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 AppBootstrap
|
||||
*/
|
||||
class Bootstrapper
|
||||
{
|
||||
private $configDir;
|
||||
private $rootDir;
|
||||
private $tempDir;
|
||||
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);
|
||||
}
|
||||
|
||||
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<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('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;
|
||||
}
|
||||
}
|
0
public/bootstrap/temp/.gitignore
vendored
Normal file
0
public/bootstrap/temp/.gitignore
vendored
Normal file
7
public/bootstrap/vendor/autoload.php
vendored
Normal file
7
public/bootstrap/vendor/autoload.php
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInitae2939a73e74219a5e53fe33357ebb1a::getLoader();
|
445
public/bootstrap/vendor/composer/ClassLoader.php
vendored
Normal file
445
public/bootstrap/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
public/bootstrap/vendor/composer/LICENSE
vendored
Normal file
21
public/bootstrap/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
public/bootstrap/vendor/composer/autoload_classmap.php
vendored
Normal file
9
public/bootstrap/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
public/bootstrap/vendor/composer/autoload_namespaces.php
vendored
Normal file
9
public/bootstrap/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
public/bootstrap/vendor/composer/autoload_psr4.php
vendored
Normal file
11
public/bootstrap/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'),
|
||||
'AppBootstrap\\' => array($baseDir . '/src'),
|
||||
);
|
52
public/bootstrap/vendor/composer/autoload_real.php
vendored
Normal file
52
public/bootstrap/vendor/composer/autoload_real.php
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInitae2939a73e74219a5e53fe33357ebb1a
|
||||
{
|
||||
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('ComposerAutoloaderInitae2939a73e74219a5e53fe33357ebb1a', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitae2939a73e74219a5e53fe33357ebb1a', '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\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;
|
||||
}
|
||||
}
|
36
public/bootstrap/vendor/composer/autoload_static.php
vendored
Normal file
36
public/bootstrap/vendor/composer/autoload_static.php
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
// autoload_static.php @generated by Composer
|
||||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitae2939a73e74219a5e53fe33357ebb1a
|
||||
{
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'A' =>
|
||||
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);
|
||||
}
|
||||
}
|
57
public/bootstrap/views/index.php
Normal file
57
public/bootstrap/views/index.php
Normal file
@ -0,0 +1,57 @@
|
||||
<!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.css">
|
||||
<title><?php echo $appName; ?></title>
|
||||
<style type="text/css">
|
||||
* {
|
||||
font-family: "Raleway", sans-serif;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container" id="bootstrapper">
|
||||
<div class="row">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<p class="mb-0"><?php echo $appName; ?></p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="lead"><b>Welcome to Blue Twilight - the self-hosted PHP photo gallery.</b></p>
|
||||
|
||||
<div v-if="!isRunning">
|
||||
<p>We need to download and install a few more files before you get started.</p>
|
||||
<p>Click the "Let's Go" button below to begin.</p>
|
||||
<p class="mb-0 mt-4"><button class="btn btn-primary btn-lg" @click.prevent="bootstrap">Let's Go</button></p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<ul>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../js/blue-twilight.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function()
|
||||
{
|
||||
var vm = new BootstrapperViewModel();
|
||||
var app = new Vue(vm);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -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 */
|
||||
|
@ -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,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();
|
71
resources/js/bootstrapper.js
vendored
Normal file
71
resources/js/bootstrapper.js
vendored
Normal file
@ -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;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
33
resources/sass/bootstrapper.scss
vendored
Normal file
33
resources/sass/bootstrapper.scss
vendored
Normal file
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user