276 lines
7.3 KiB
PHP
276 lines
7.3 KiB
PHP
<?php
|
|
|
|
namespace AppBootstrap;
|
|
|
|
use App\Services\GiteaService;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
|
|
/**
|
|
* This class handles the downloading and extracting of the vendors directory.
|
|
* Because Laravel and other vendors are not yet available, it uses "raw" PHP and the odd few classes within Blue
|
|
* Twilight, such as GiteaService.
|
|
*
|
|
* @package AppBootstrap
|
|
*/
|
|
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->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()
|
|
{
|
|
if (!isset($_GET['act']))
|
|
{
|
|
$this->view('index', ['appName' => 'Blue Twilight Bootstrapper']);
|
|
}
|
|
else
|
|
{
|
|
switch (trim($_GET['act']))
|
|
{
|
|
case 'download':
|
|
$this->download();
|
|
return;
|
|
|
|
case 'extract':
|
|
$this->extract();
|
|
return;
|
|
|
|
case 'finalise':
|
|
$this->finalise();
|
|
return;
|
|
|
|
default:
|
|
throw new \Exception(sprintf('Action \'%s\' was not recognised.', $_GET['act']));
|
|
}
|
|
}
|
|
}
|
|
|
|
protected 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 \'%s\'', $versionNumber));
|
|
}
|
|
else if (!isset($releaseInfo->assets))
|
|
{
|
|
throw new \Exception(sprintf('No assets found in Gitea for Blue Twilight version \'%s\'', $versionNumber));
|
|
}
|
|
|
|
$vendorsPrefix = 'vendors';
|
|
$vendorsSuffix = '.tar.gz';
|
|
$selectedAsset = null;
|
|
|
|
foreach ($releaseInfo->assets as $asset)
|
|
{
|
|
/*
|
|
Ignore anything that is not "vendors<something>.tar.gz" were the <something> is also optional - e.g.
|
|
vendors_2.1.2.tar.gz
|
|
vendors.tar.gz
|
|
but NOT 2.1.2_vendors.zip
|
|
*/
|
|
if (!starts_with($asset->name, $vendorsPrefix) || !ends_with($asset->name, $vendorsSuffix))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
$selectedAsset = $asset;
|
|
break;
|
|
}
|
|
|
|
if (is_null($selectedAsset))
|
|
{
|
|
throw new \Exception(sprintf('No vendors.tar.gz found in Gitea for Blue Twilight version \'%s\'', $versionNumber));
|
|
}
|
|
|
|
$targetFileName = $this->getVendorsTempFileName();
|
|
|
|
$this->downloadFile($selectedAsset->browser_download_url, $targetFileName);
|
|
$this->json([
|
|
'result' => true,
|
|
'fileName' => $targetFileName
|
|
]);
|
|
}
|
|
|
|
protected function extract()
|
|
{
|
|
$targetFileName = $this->getVendorsTempFileName();
|
|
if (!file_exists($targetFileName) || !is_readable($targetFileName))
|
|
{
|
|
throw new \Exception(sprintf('The file \'%s\' does not exist or is not readable', $targetFileName));
|
|
}
|
|
|
|
$phar = new \PharData($targetFileName);
|
|
$phar->extractTo($this->rootDir, null, true);
|
|
|
|
// We should always have a vendor/autoload.php
|
|
$vendorsTestFile = $this->getVendorsAutoloadFileName();
|
|
|
|
if (file_exists($vendorsTestFile))
|
|
{
|
|
$this->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)
|
|
{
|
|
$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 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);
|
|
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;
|
|
}
|
|
} |