First pass at XML exporter for services
This commit is contained in:
parent
12faf80faf
commit
0d739257a9
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pterodactyl - Panel
|
||||||
|
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||||
|
*
|
||||||
|
* This software is licensed under the terms of the MIT license.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Pterodactyl\Http\Controllers\Admin\Services\Options;
|
||||||
|
|
||||||
|
use Pterodactyl\Models\ServiceOption;
|
||||||
|
use Pterodactyl\Http\Controllers\Controller;
|
||||||
|
use Pterodactyl\Services\Services\Exporter\XMLExporterService;
|
||||||
|
|
||||||
|
class OptionShareController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Services\Services\Exporter\XMLExporterService
|
||||||
|
*/
|
||||||
|
protected $exporterService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OptionShareController constructor.
|
||||||
|
*
|
||||||
|
* @param \Pterodactyl\Services\Services\Exporter\XMLExporterService $exporterService
|
||||||
|
*/
|
||||||
|
public function __construct(XMLExporterService $exporterService)
|
||||||
|
{
|
||||||
|
$this->exporterService = $exporterService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Pterodactyl\Models\ServiceOption $option
|
||||||
|
* @return $this
|
||||||
|
*
|
||||||
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
|
*/
|
||||||
|
public function export(ServiceOption $option)
|
||||||
|
{
|
||||||
|
return response($this->exporterService->handle($option), 200, [
|
||||||
|
'Content-Type' => 'application/xml',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Pterodactyl - Panel
|
||||||
|
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||||
|
*
|
||||||
|
* This software is licensed under the terms of the MIT license.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Pterodactyl\Services\Services\Exporter;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Sabre\Xml\Writer;
|
||||||
|
use Sabre\Xml\Service;
|
||||||
|
use Pterodactyl\Models\ServiceOption;
|
||||||
|
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
|
||||||
|
|
||||||
|
class XMLExporterService
|
||||||
|
{
|
||||||
|
const XML_OPTION_NAMESPACE = '{https://pterodactyl.io/exporter/option/}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Carbon\Carbon
|
||||||
|
*/
|
||||||
|
protected $carbon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface
|
||||||
|
*/
|
||||||
|
protected $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Sabre\Xml\Service
|
||||||
|
*/
|
||||||
|
protected $xml;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XMLExporterService constructor.
|
||||||
|
*
|
||||||
|
* @param \Carbon\Carbon $carbon
|
||||||
|
* @param \Sabre\Xml\Service $xml
|
||||||
|
* @param \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface $repository
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Carbon $carbon,
|
||||||
|
Service $xml,
|
||||||
|
ServiceOptionRepositoryInterface $repository
|
||||||
|
) {
|
||||||
|
$this->carbon = $carbon;
|
||||||
|
$this->repository = $repository;
|
||||||
|
$this->xml = $xml;
|
||||||
|
|
||||||
|
$this->xml->namespaceMap = [
|
||||||
|
str_replace(['{', '}'], '', self::XML_OPTION_NAMESPACE) => 'p',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an XML structure to represent this service option.
|
||||||
|
*
|
||||||
|
* @param int|\Pterodactyl\Models\ServiceOption $option
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||||
|
*/
|
||||||
|
public function handle($option): string
|
||||||
|
{
|
||||||
|
if (! $option instanceof ServiceOption) {
|
||||||
|
$option = $this->repository->find($option);
|
||||||
|
}
|
||||||
|
|
||||||
|
$struct = [
|
||||||
|
'exported_at' => $this->carbon->now()->toIso8601String(),
|
||||||
|
'name' => $option->name,
|
||||||
|
'author' => array_get(explode(':', $option->tag), 0),
|
||||||
|
'tag' => $option->tag,
|
||||||
|
'description' => $option->description,
|
||||||
|
'image' => $option->docker_image,
|
||||||
|
'config' => [
|
||||||
|
'files' => $option->config_files,
|
||||||
|
'startup' => $option->config_startup,
|
||||||
|
'logs' => $option->config_logs,
|
||||||
|
'stop' => $option->config_stop,
|
||||||
|
],
|
||||||
|
'scripts' => [
|
||||||
|
'installation' => [
|
||||||
|
'script' => function (Writer $writer) use ($option) {
|
||||||
|
return $writer->writeCData($option->copy_script_install);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this->xml->write(self::XML_OPTION_NAMESPACE . 'root', $this->recursiveArrayKeyPrepend($struct));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $array
|
||||||
|
* @param string $prepend
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function recursiveArrayKeyPrepend(array $array, $prepend = self::XML_OPTION_NAMESPACE): array
|
||||||
|
{
|
||||||
|
$parsed = [];
|
||||||
|
foreach ($array as $k => &$v) {
|
||||||
|
$k = $prepend . $k;
|
||||||
|
|
||||||
|
if (is_array($v)) {
|
||||||
|
$v = $this->recursiveArrayKeyPrepend($v);
|
||||||
|
}
|
||||||
|
|
||||||
|
$parsed[$k] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parsed;
|
||||||
|
}
|
||||||
|
}
|
|
@ -35,6 +35,7 @@
|
||||||
"prologue/alerts": "^0.4",
|
"prologue/alerts": "^0.4",
|
||||||
"ramsey/uuid": "^3.7",
|
"ramsey/uuid": "^3.7",
|
||||||
"s1lentium/iptools": "^1.1",
|
"s1lentium/iptools": "^1.1",
|
||||||
|
"sabre/xml": "^2.0",
|
||||||
"sofa/eloquence": "~5.4.1",
|
"sofa/eloquence": "~5.4.1",
|
||||||
"spatie/laravel-fractal": "^4.0",
|
"spatie/laravel-fractal": "^4.0",
|
||||||
"watson/validating": "^3.0",
|
"watson/validating": "^3.0",
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "46a0a06ec8f3af50ed6ec05c2bb3b9a3",
|
"content-hash": "bc8c88f86ea043406bce2f8fddf704b3",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "aws/aws-sdk-php",
|
"name": "aws/aws-sdk-php",
|
||||||
|
@ -2510,6 +2510,120 @@
|
||||||
],
|
],
|
||||||
"time": "2016-08-21T15:57:09+00:00"
|
"time": "2016-08-21T15:57:09+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "sabre/uri",
|
||||||
|
"version": "2.1.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/fruux/sabre-uri.git",
|
||||||
|
"reference": "a42126042c7dcb53e2978dadb6d22574d1359b4c"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/fruux/sabre-uri/zipball/a42126042c7dcb53e2978dadb6d22574d1359b4c",
|
||||||
|
"reference": "a42126042c7dcb53e2978dadb6d22574d1359b4c",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^6.0",
|
||||||
|
"sabre/cs": "~1.0.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"lib/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Sabre\\Uri\\": "lib/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Evert Pot",
|
||||||
|
"email": "me@evertpot.com",
|
||||||
|
"homepage": "http://evertpot.com/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Functions for making sense out of URIs.",
|
||||||
|
"homepage": "http://sabre.io/uri/",
|
||||||
|
"keywords": [
|
||||||
|
"rfc3986",
|
||||||
|
"uri",
|
||||||
|
"url"
|
||||||
|
],
|
||||||
|
"time": "2017-02-20T20:02:35+00:00"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "sabre/xml",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/fruux/sabre-xml.git",
|
||||||
|
"reference": "054292959a1f2b64c10c9c7a03a816ba1872b8a3"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/fruux/sabre-xml/zipball/054292959a1f2b64c10c9c7a03a816ba1872b8a3",
|
||||||
|
"reference": "054292959a1f2b64c10c9c7a03a816ba1872b8a3",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-dom": "*",
|
||||||
|
"ext-xmlreader": "*",
|
||||||
|
"ext-xmlwriter": "*",
|
||||||
|
"lib-libxml": ">=2.6.20",
|
||||||
|
"php": ">=7.0",
|
||||||
|
"sabre/uri": ">=1.0,<3.0.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "*",
|
||||||
|
"sabre/cs": "~1.0.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Sabre\\Xml\\": "lib/"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/Deserializer/functions.php",
|
||||||
|
"lib/Serializer/functions.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-3-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Evert Pot",
|
||||||
|
"email": "me@evertpot.com",
|
||||||
|
"homepage": "http://evertpot.com/",
|
||||||
|
"role": "Developer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Markus Staab",
|
||||||
|
"email": "markus.staab@redaxo.de",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "sabre/xml is an XML library that you may not hate.",
|
||||||
|
"homepage": "https://sabre.io/xml/",
|
||||||
|
"keywords": [
|
||||||
|
"XMLReader",
|
||||||
|
"XMLWriter",
|
||||||
|
"dom",
|
||||||
|
"xml"
|
||||||
|
],
|
||||||
|
"time": "2016-11-16T00:41:01+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "sofa/eloquence",
|
"name": "sofa/eloquence",
|
||||||
"version": "5.4.1",
|
"version": "5.4.1",
|
||||||
|
|
|
@ -131,7 +131,8 @@
|
||||||
<button id="deleteButton" type="submit" name="_method" value="DELETE" class="btn btn-danger btn-sm muted muted-hover">
|
<button id="deleteButton" type="submit" name="_method" value="DELETE" class="btn btn-danger btn-sm muted muted-hover">
|
||||||
<i class="fa fa-trash-o"></i>
|
<i class="fa fa-trash-o"></i>
|
||||||
</button>
|
</button>
|
||||||
<button type="submit" name="_method" value="PATCH" class="btn btn-primary btn-sm pull-right">Edit Service</button>
|
<button type="submit" name="_method" value="PATCH" class="btn btn-primary btn-sm pull-right">Edit Option</button>
|
||||||
|
<a href="{{ route('admin.services.option.export', ['option' => $option->id]) }}" class="btn btn-sm btn-info pull-right" style="margin-right:10px;">Export Option Configuration</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
@foreach($service->options as $option)
|
@foreach($service->options as $option)
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{{ route('admin.services.option.view', $option->id) }}">{{ $option->name }}</a></td>
|
<td><a href="{{ route('admin.services.option.view', $option->id) }}">{{ $option->name }}</a></td>
|
||||||
<td>{!! $option->description !!}</td>
|
<td class="col-xs-6">{!! $option->description !!}</td>
|
||||||
<td><code>{{ $option->tag }}</code></td>
|
<td><code>{{ $option->tag }}</code></td>
|
||||||
<td class="text-center">{{ $option->servers->count() }}</td>
|
<td class="text-center">{{ $option->servers->count() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -155,6 +155,7 @@ Route::group(['prefix' => 'services'], function () {
|
||||||
Route::get('/view/{service}/functions', 'ServiceController@viewFunctions')->name('admin.services.view.functions');
|
Route::get('/view/{service}/functions', 'ServiceController@viewFunctions')->name('admin.services.view.functions');
|
||||||
Route::get('/option/new', 'OptionController@create')->name('admin.services.option.new');
|
Route::get('/option/new', 'OptionController@create')->name('admin.services.option.new');
|
||||||
Route::get('/option/{option}', 'OptionController@viewConfiguration')->name('admin.services.option.view');
|
Route::get('/option/{option}', 'OptionController@viewConfiguration')->name('admin.services.option.view');
|
||||||
|
Route::get('/option/{option}/export', 'Services\Options\OptionShareController@export')->name('admin.services.option.export');
|
||||||
Route::get('/option/{option}/variables', 'VariableController@view')->name('admin.services.option.variables');
|
Route::get('/option/{option}/variables', 'VariableController@view')->name('admin.services.option.variables');
|
||||||
Route::get('/option/{option}/scripts', 'OptionController@viewScripts')->name('admin.services.option.scripts');
|
Route::get('/option/{option}/scripts', 'OptionController@viewScripts')->name('admin.services.option.scripts');
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue