Finalize service option import/export
This commit is contained in:
parent
d608c313c3
commit
6269a08db7
16 changed files with 405 additions and 271 deletions
|
@ -1,132 +0,0 @@
|
|||
<?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 Closure;
|
||||
use Carbon\Carbon;
|
||||
use Sabre\Xml\Writer;
|
||||
use Sabre\Xml\Service;
|
||||
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 $option
|
||||
* @return string
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function handle(int $option): string
|
||||
{
|
||||
$option = $this->repository->getWithCopyAttributes($option);
|
||||
|
||||
$struct = [
|
||||
'meta' => [
|
||||
'version' => 'PTDL_v1',
|
||||
],
|
||||
'exported_at' => $this->carbon->now()->toIso8601String(),
|
||||
'name' => $option->name,
|
||||
'author' => array_get(explode(':', $option->tag), 0),
|
||||
'tag' => $option->tag,
|
||||
'description' => $this->writeCData($option->description),
|
||||
'image' => $option->docker_image,
|
||||
'config' => [
|
||||
'files' => $this->writeCData($option->inherit_config_files),
|
||||
'startup' => $this->writeCData($option->inherit_config_startup),
|
||||
'logs' => $this->writeCData($option->inherit_config_logs),
|
||||
'stop' => $option->inherit_config_stop,
|
||||
],
|
||||
'scripts' => [
|
||||
'installation' => [
|
||||
'script' => $this->writeCData($option->copy_script_install),
|
||||
'container' => $option->copy_script_container,
|
||||
'entrypoint' => $option->copy_script_entry,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a closure to be used by the XML writer to generate a string wrapped in CDATA tags.
|
||||
*
|
||||
* @param string $value
|
||||
* @return \Closure
|
||||
*/
|
||||
protected function writeCData(string $value): Closure
|
||||
{
|
||||
return function (Writer $writer) use ($value) {
|
||||
return $writer->writeCData($value);
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?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\Sharing;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
|
||||
|
||||
class ServiceOptionExporterService
|
||||
{
|
||||
/**
|
||||
* @var \Carbon\Carbon
|
||||
*/
|
||||
protected $carbon;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* XMLExporterService constructor.
|
||||
*
|
||||
* @param \Carbon\Carbon $carbon
|
||||
* @param \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
Carbon $carbon,
|
||||
ServiceOptionRepositoryInterface $repository
|
||||
) {
|
||||
$this->carbon = $carbon;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an XML structure to represent this service option.
|
||||
*
|
||||
* @param int $option
|
||||
* @return string
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function handle(int $option): string
|
||||
{
|
||||
$option = $this->repository->getWithExportAttributes($option);
|
||||
|
||||
$struct = [
|
||||
'_comment' => 'DO NOT EDIT: FILE GENERATED AUTOMATICALLY BY PTERODACTYL PANEL - PTERODACTYL.IO',
|
||||
'meta' => [
|
||||
'version' => 'PTDL_v1',
|
||||
],
|
||||
'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,
|
||||
'startup' => $option->display_startup,
|
||||
'config' => [
|
||||
'files' => $option->inherit_config_files,
|
||||
'startup' => $option->inherit_config_startup,
|
||||
'logs' => $option->inherit_config_logs,
|
||||
'stop' => $option->inherit_config_stop,
|
||||
],
|
||||
'scripts' => [
|
||||
'installation' => [
|
||||
'script' => $option->copy_script_install,
|
||||
'container' => $option->copy_script_container,
|
||||
'entrypoint' => $option->copy_script_entry,
|
||||
],
|
||||
],
|
||||
'variables' => $option->variables->transform(function ($item) {
|
||||
return collect($item->toArray())->except([
|
||||
'id', 'option_id', 'created_at', 'updated_at',
|
||||
])->toArray();
|
||||
}),
|
||||
];
|
||||
|
||||
return json_encode($struct, JSON_PRETTY_PRINT);
|
||||
}
|
||||
}
|
123
app/Services/Services/Sharing/ServiceOptionImporterService.php
Normal file
123
app/Services/Services/Sharing/ServiceOptionImporterService.php
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?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\Sharing;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Pterodactyl\Models\ServiceOption;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use Pterodactyl\Contracts\Repository\ServiceRepositoryInterface;
|
||||
use Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException;
|
||||
use Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface;
|
||||
use Pterodactyl\Exceptions\Service\ServiceOption\DuplicateOptionTagException;
|
||||
|
||||
class ServiceOptionImporterService
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Database\ConnectionInterface
|
||||
*/
|
||||
protected $connection;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ServiceRepositoryInterface
|
||||
*/
|
||||
protected $serviceRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface
|
||||
*/
|
||||
protected $serviceVariableRepository;
|
||||
|
||||
/**
|
||||
* XMLImporterService constructor.
|
||||
*
|
||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||
* @param \Pterodactyl\Contracts\Repository\ServiceRepositoryInterface $serviceRepository
|
||||
* @param \Pterodactyl\Contracts\Repository\ServiceOptionRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Contracts\Repository\ServiceVariableRepositoryInterface $serviceVariableRepository
|
||||
*/
|
||||
public function __construct(
|
||||
ConnectionInterface $connection,
|
||||
ServiceRepositoryInterface $serviceRepository,
|
||||
ServiceOptionRepositoryInterface $repository,
|
||||
ServiceVariableRepositoryInterface $serviceVariableRepository
|
||||
) {
|
||||
$this->connection = $connection;
|
||||
$this->repository = $repository;
|
||||
$this->serviceRepository = $serviceRepository;
|
||||
$this->serviceVariableRepository = $serviceVariableRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an uploaded XML file and parse it into a new service option.
|
||||
*
|
||||
* @param \Illuminate\Http\UploadedFile $file
|
||||
* @param int $service
|
||||
* @return \Pterodactyl\Models\ServiceOption
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileUploadException
|
||||
*/
|
||||
public function handle(UploadedFile $file, int $service): ServiceOption
|
||||
{
|
||||
if (! $file->isValid() || ! $file->isFile()) {
|
||||
throw new InvalidFileUploadException(trans('exceptions.service.exporter.import_file_error'));
|
||||
}
|
||||
|
||||
$parsed = json_decode($file->openFile()->fread($file->getSize()));
|
||||
|
||||
if (object_get($parsed, 'meta.version') !== 'PTDL_v1') {
|
||||
throw new InvalidFileUploadException(trans('exceptions.service.exporter.invalid_json_provided'));
|
||||
}
|
||||
|
||||
$service = $this->serviceRepository->getWithOptions($service);
|
||||
$service->options->each(function ($option) use ($parsed) {
|
||||
if ($option->tag === object_get($parsed, 'tag')) {
|
||||
throw new DuplicateOptionTagException(trans('exceptions.service.options.duplicate_tag'));
|
||||
}
|
||||
});
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
$option = $this->repository->create([
|
||||
'uuid' => Uuid::uuid4()->toString(),
|
||||
'service_id' => $service->id,
|
||||
'name' => object_get($parsed, 'name'),
|
||||
'description' => object_get($parsed, 'description'),
|
||||
'tag' => object_get($parsed, 'tag'),
|
||||
'docker_image' => object_get($parsed, 'image'),
|
||||
'config_files' => object_get($parsed, 'config.files'),
|
||||
'config_startup' => object_get($parsed, 'config.startup'),
|
||||
'config_logs' => object_get($parsed, 'config.logs'),
|
||||
'config_stop' => object_get($parsed, 'config.stop'),
|
||||
'startup' => object_get($parsed, 'startup'),
|
||||
'script_install' => object_get($parsed, 'scripts.installation.script'),
|
||||
'script_entry' => object_get($parsed, 'scripts.installation.entrypoint'),
|
||||
'script_container' => object_get($parsed, 'scripts.installation.container'),
|
||||
'copy_script_from' => null,
|
||||
], true, true);
|
||||
|
||||
collect($parsed->variables)->each(function ($variable) use ($option) {
|
||||
$this->serviceVariableRepository->create(array_merge((array) $variable, [
|
||||
'option_id' => $option->id,
|
||||
]));
|
||||
});
|
||||
|
||||
$this->connection->commit();
|
||||
|
||||
return $option;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue