Skip to content

Commit 0d73925

Browse files
committed
First pass at XML exporter for services
1 parent 12faf80 commit 0d73925

File tree

7 files changed

+283
-3
lines changed

7 files changed

+283
-3
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5+
*
6+
* This software is licensed under the terms of the MIT license.
7+
* https://opensource.org/licenses/MIT
8+
*/
9+
10+
namespace Pterodactyl\Http\Controllers\Admin\Services\Options;
11+
12+
use Pterodactyl\Models\ServiceOption;
13+
use Pterodactyl\Http\Controllers\Controller;
14+
use Pterodactyl\Services\Services\Exporter\XMLExporterService;
15+
16+
class OptionShareController extends Controller
17+
{
18+
/**
19+
* @var \Pterodactyl\Services\Services\Exporter\XMLExporterService
20+
*/
21+
protected $exporterService;
22+
23+
/**
24+
* OptionShareController constructor.
25+
*
26+
* @param \Pterodactyl\Services\Services\Exporter\XMLExporterService $exporterService
27+
*/
28+
public function __construct(XMLExporterService $exporterService)
29+
{
30+
$this->exporterService = $exporterService;
31+
}
32+
33+
/**
34+
* @param \Pterodactyl\Models\ServiceOption $option
35+
* @return $this
36+
*
37+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
38+
*/
39+
public function export(ServiceOption $option)
40+
{
41+
return response($this->exporterService->handle($option), 200, [
42+
'Content-Type' => 'application/xml',
43+
]);
44+
}
45+
}
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
/**
3+
* Pterodactyl - Panel
4+
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
5+
*
6+
* This software is licensed under the terms of the MIT license.
7+
* https://opensource.org/licenses/MIT
8+
*/
9+
10+
namespace Pterodactyl\Services\Services\Exporter;
11+
12+
use Carbon\Carbon;
13+
use Sabre\Xml\Writer;
14+
use Sabre\Xml\Service;
15+
use Pterodactyl\Models\ServiceOption;
16+
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
17+
18+
class XMLExporterService
19+
{
20+
const XML_OPTION_NAMESPACE = '{https://pterodactyl.io/exporter/option/}';
21+
22+
/**
23+
* @var \Carbon\Carbon
24+
*/
25+
protected $carbon;
26+
27+
/**
28+
* @var \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface
29+
*/
30+
protected $repository;
31+
32+
/**
33+
* @var \Sabre\Xml\Service
34+
*/
35+
protected $xml;
36+
37+
/**
38+
* XMLExporterService constructor.
39+
*
40+
* @param \Carbon\Carbon $carbon
41+
* @param \Sabre\Xml\Service $xml
42+
* @param \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface $repository
43+
*/
44+
public function __construct(
45+
Carbon $carbon,
46+
Service $xml,
47+
ServiceOptionRepositoryInterface $repository
48+
) {
49+
$this->carbon = $carbon;
50+
$this->repository = $repository;
51+
$this->xml = $xml;
52+
53+
$this->xml->namespaceMap = [
54+
str_replace(['{', '}'], '', self::XML_OPTION_NAMESPACE) => 'p',
55+
];
56+
}
57+
58+
/**
59+
* Return an XML structure to represent this service option.
60+
*
61+
* @param int|\Pterodactyl\Models\ServiceOption $option
62+
* @return string
63+
*
64+
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
65+
*/
66+
public function handle($option): string
67+
{
68+
if (! $option instanceof ServiceOption) {
69+
$option = $this->repository->find($option);
70+
}
71+
72+
$struct = [
73+
'exported_at' => $this->carbon->now()->toIso8601String(),
74+
'name' => $option->name,
75+
'author' => array_get(explode(':', $option->tag), 0),
76+
'tag' => $option->tag,
77+
'description' => $option->description,
78+
'image' => $option->docker_image,
79+
'config' => [
80+
'files' => $option->config_files,
81+
'startup' => $option->config_startup,
82+
'logs' => $option->config_logs,
83+
'stop' => $option->config_stop,
84+
],
85+
'scripts' => [
86+
'installation' => [
87+
'script' => function (Writer $writer) use ($option) {
88+
return $writer->writeCData($option->copy_script_install);
89+
},
90+
],
91+
],
92+
];
93+
94+
return $this->xml->write(self::XML_OPTION_NAMESPACE . 'root', $this->recursiveArrayKeyPrepend($struct));
95+
}
96+
97+
/**
98+
* @param array $array
99+
* @param string $prepend
100+
*
101+
* @return array
102+
*/
103+
protected function recursiveArrayKeyPrepend(array $array, $prepend = self::XML_OPTION_NAMESPACE): array
104+
{
105+
$parsed = [];
106+
foreach ($array as $k => &$v) {
107+
$k = $prepend . $k;
108+
109+
if (is_array($v)) {
110+
$v = $this->recursiveArrayKeyPrepend($v);
111+
}
112+
113+
$parsed[$k] = $v;
114+
}
115+
116+
return $parsed;
117+
}
118+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"prologue/alerts": "^0.4",
3636
"ramsey/uuid": "^3.7",
3737
"s1lentium/iptools": "^1.1",
38+
"sabre/xml": "^2.0",
3839
"sofa/eloquence": "~5.4.1",
3940
"spatie/laravel-fractal": "^4.0",
4041
"watson/validating": "^3.0",

composer.lock

Lines changed: 115 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/themes/pterodactyl/admin/services/options/view.blade.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@
131131
<button id="deleteButton" type="submit" name="_method" value="DELETE" class="btn btn-danger btn-sm muted muted-hover">
132132
<i class="fa fa-trash-o"></i>
133133
</button>
134-
<button type="submit" name="_method" value="PATCH" class="btn btn-primary btn-sm pull-right">Edit Service</button>
134+
<button type="submit" name="_method" value="PATCH" class="btn btn-primary btn-sm pull-right">Edit Option</button>
135+
<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>
135136
</div>
136137
</div>
137138
</div>

resources/themes/pterodactyl/admin/services/view.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@
101101
@foreach($service->options as $option)
102102
<tr>
103103
<td><a href="{{ route('admin.services.option.view', $option->id) }}">{{ $option->name }}</a></td>
104-
<td>{!! $option->description !!}</td>
104+
<td class="col-xs-6">{!! $option->description !!}</td>
105105
<td><code>{{ $option->tag }}</code></td>
106106
<td class="text-center">{{ $option->servers->count() }}</td>
107107
</tr>

routes/admin.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
Route::get('/view/{service}/functions', 'ServiceController@viewFunctions')->name('admin.services.view.functions');
156156
Route::get('/option/new', 'OptionController@create')->name('admin.services.option.new');
157157
Route::get('/option/{option}', 'OptionController@viewConfiguration')->name('admin.services.option.view');
158+
Route::get('/option/{option}/export', 'Services\Options\OptionShareController@export')->name('admin.services.option.export');
158159
Route::get('/option/{option}/variables', 'VariableController@view')->name('admin.services.option.variables');
159160
Route::get('/option/{option}/scripts', 'OptionController@viewScripts')->name('admin.services.option.scripts');
160161

0 commit comments

Comments
 (0)