2017-10-04 04:31:04 +00:00
< ? php
2017-10-07 21:19:07 +00:00
namespace Pterodactyl\Services\Eggs\Sharing ;
2017-10-04 04:31:04 +00:00
use Ramsey\Uuid\Uuid ;
2021-01-27 05:08:53 +00:00
use Illuminate\Support\Arr ;
2021-01-28 04:52:11 +00:00
use Pterodactyl\Models\Egg ;
2017-10-04 04:31:04 +00:00
use Illuminate\Http\UploadedFile ;
2021-01-27 05:08:53 +00:00
use Illuminate\Support\Collection ;
2017-10-04 04:31:04 +00:00
use Illuminate\Database\ConnectionInterface ;
2017-10-07 04:57:53 +00:00
use Pterodactyl\Contracts\Repository\EggRepositoryInterface ;
use Pterodactyl\Contracts\Repository\NestRepositoryInterface ;
2017-10-09 04:50:52 +00:00
use Pterodactyl\Exceptions\Service\InvalidFileUploadException ;
2017-10-07 04:57:53 +00:00
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface ;
2017-10-04 04:31:04 +00:00
2017-10-07 04:57:53 +00:00
class EggImporterService
2017-10-04 04:31:04 +00:00
{
/**
* @ var \Illuminate\Database\ConnectionInterface
*/
protected $connection ;
/**
2017-10-07 04:57:53 +00:00
* @ var \Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface
2017-10-04 04:31:04 +00:00
*/
2017-10-07 04:57:53 +00:00
protected $eggVariableRepository ;
2017-10-04 04:31:04 +00:00
/**
2017-10-08 04:29:08 +00:00
* @ var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
2017-10-04 04:31:04 +00:00
*/
2017-10-08 04:29:08 +00:00
protected $nestRepository ;
2017-10-04 04:31:04 +00:00
/**
2017-10-08 04:29:08 +00:00
* @ var \Pterodactyl\Contracts\Repository\EggRepositoryInterface
2017-10-04 04:31:04 +00:00
*/
2017-10-08 04:29:08 +00:00
protected $repository ;
2017-10-04 04:31:04 +00:00
/**
2017-10-07 04:57:53 +00:00
* EggImporterService constructor .
2017-10-04 04:31:04 +00:00
*/
public function __construct (
ConnectionInterface $connection ,
2017-10-07 04:57:53 +00:00
EggRepositoryInterface $repository ,
EggVariableRepositoryInterface $eggVariableRepository ,
2017-10-08 04:29:08 +00:00
NestRepositoryInterface $nestRepository
2017-10-04 04:31:04 +00:00
) {
$this -> connection = $connection ;
2017-10-07 04:57:53 +00:00
$this -> eggVariableRepository = $eggVariableRepository ;
2017-10-08 04:29:08 +00:00
$this -> repository = $repository ;
$this -> nestRepository = $nestRepository ;
2017-10-04 04:31:04 +00:00
}
/**
2017-10-07 04:57:53 +00:00
* Take an uploaded JSON file and parse it into a new egg .
2017-10-04 04:31:04 +00:00
*
* @ throws \Pterodactyl\Exceptions\Model\DataValidationException
* @ throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
2017-10-09 04:50:52 +00:00
* @ throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
2022-05-07 21:45:22 +00:00
* @ throws \JsonException
2017-10-04 04:31:04 +00:00
*/
2017-10-07 04:57:53 +00:00
public function handle ( UploadedFile $file , int $nest ) : Egg
2017-10-04 04:31:04 +00:00
{
2021-01-23 20:33:34 +00:00
if ( $file -> getError () !== UPLOAD_ERR_OK || ! $file -> isFile ()) {
throw new InvalidFileUploadException ( sprintf ( 'The selected file ["%s"] was not in a valid format to import. (is_file: %s is_valid: %s err_code: %s err: %s)' , $file -> getFilename (), $file -> isFile () ? 'true' : 'false' , $file -> isValid () ? 'true' : 'false' , $file -> getError (), $file -> getErrorMessage ()));
2017-10-04 04:31:04 +00:00
}
2021-01-27 05:08:53 +00:00
/** @var array $parsed */
2022-05-07 21:45:22 +00:00
$parsed = json_decode ( $file -> openFile () -> fread ( $file -> getSize ()), true , 512 , JSON_THROW_ON_ERROR );
if ( ! in_array ( Arr :: get ( $parsed , 'meta.version' ) ? ? '' , [ 'PTDL_v1' , 'PTDL_v2' ])) {
throw new InvalidFileUploadException ( trans ( 'exceptions.nest.importer.invalid_json_provided' ));
2017-10-09 04:50:52 +00:00
}
2017-10-04 04:31:04 +00:00
2022-05-07 21:45:22 +00:00
if ( $parsed [ 'meta' ][ 'version' ] !== Egg :: EXPORT_VERSION ) {
$parsed = $this -> convertV1ToV2 ( $parsed );
2017-10-04 04:31:04 +00:00
}
2017-10-08 04:29:08 +00:00
$nest = $this -> nestRepository -> getWithEggs ( $nest );
2017-10-04 04:31:04 +00:00
$this -> connection -> beginTransaction ();
2017-10-07 04:57:53 +00:00
2021-01-27 05:08:53 +00:00
/** @var \Pterodactyl\Models\Egg $egg */
2017-10-07 04:57:53 +00:00
$egg = $this -> repository -> create ([
2017-10-04 04:31:04 +00:00
'uuid' => Uuid :: uuid4 () -> toString (),
2017-10-07 04:57:53 +00:00
'nest_id' => $nest -> id ,
2021-01-27 05:08:53 +00:00
'author' => Arr :: get ( $parsed , 'author' ),
'name' => Arr :: get ( $parsed , 'name' ),
'description' => Arr :: get ( $parsed , 'description' ),
'features' => Arr :: get ( $parsed , 'features' ),
2022-05-07 21:45:22 +00:00
'docker_images' => Arr :: get ( $parsed , 'docker_images' ),
2021-01-27 05:08:53 +00:00
'file_denylist' => Collection :: make ( Arr :: get ( $parsed , 'file_denylist' )) -> filter ( function ( $value ) {
return ! empty ( $value );
}),
'update_url' => Arr :: get ( $parsed , 'meta.update_url' ),
'config_files' => Arr :: get ( $parsed , 'config.files' ),
'config_startup' => Arr :: get ( $parsed , 'config.startup' ),
'config_logs' => Arr :: get ( $parsed , 'config.logs' ),
'config_stop' => Arr :: get ( $parsed , 'config.stop' ),
'startup' => Arr :: get ( $parsed , 'startup' ),
'script_install' => Arr :: get ( $parsed , 'scripts.installation.script' ),
'script_entry' => Arr :: get ( $parsed , 'scripts.installation.entrypoint' ),
'script_container' => Arr :: get ( $parsed , 'scripts.installation.container' ),
2017-10-04 04:31:04 +00:00
'copy_script_from' => null ,
], true , true );
2021-01-27 05:08:53 +00:00
Collection :: make ( $parsed [ 'variables' ] ? ? []) -> each ( function ( array $variable ) use ( $egg ) {
2022-05-07 21:45:22 +00:00
unset ( $variable [ 'field_type' ]);
2021-01-27 05:08:53 +00:00
$this -> eggVariableRepository -> create ( array_merge ( $variable , [
2017-10-07 04:57:53 +00:00
'egg_id' => $egg -> id ,
2017-10-04 04:31:04 +00:00
]));
});
$this -> connection -> commit ();
2017-10-07 04:57:53 +00:00
return $egg ;
2017-10-04 04:31:04 +00:00
}
2022-05-07 21:45:22 +00:00
/**
* Converts a PTDL_V1 egg into the expected PTDL_V2 egg format . This just handles
* the " docker_images " field potentially not being present , and not being in the
* expected " key => value " format .
*/
protected function convertV1ToV2 ( array $parsed ) : array
{
// Maintain backwards compatability for eggs that are still using the old single image
// string format. New eggs can provide an array of Docker images that can be used.
if ( ! isset ( $parsed [ 'images' ])) {
$images = [ Arr :: get ( $parsed , 'image' ) ? ? 'nil' ];
} else {
$images = $parsed [ 'images' ];
}
unset ( $parsed [ 'images' ], $parsed [ 'image' ]);
$parsed [ 'docker_images' ] = [];
foreach ( $images as $image ) {
$parsed [ 'docker_images' ][ $image ] = $image ;
}
$parsed [ 'variables' ] = array_map ( function ( $value ) {
return array_merge ( $value , [ 'field_type' => 'text' ]);
}, $parsed [ 'variables' ]);
return $parsed ;
}
2017-10-04 04:31:04 +00:00
}