2021-08-07 20:06:45 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Pterodactyl\Transformers\Api;
|
|
|
|
|
2021-08-07 23:00:04 +00:00
|
|
|
use Closure;
|
2021-08-07 20:06:45 +00:00
|
|
|
use DateTimeInterface;
|
|
|
|
use Carbon\CarbonImmutable;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use Pterodactyl\Models\User;
|
|
|
|
use Webmozart\Assert\Assert;
|
|
|
|
use Illuminate\Container\Container;
|
|
|
|
use League\Fractal\TransformerAbstract;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @method array transform(\Pterodactyl\Models\Model $model)
|
|
|
|
*/
|
|
|
|
abstract class Transformer extends TransformerAbstract
|
|
|
|
{
|
|
|
|
protected static string $timezone = 'UTC';
|
|
|
|
|
|
|
|
protected Request $request;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the request instance onto the transformer abstract from the container. This
|
|
|
|
* will also automatically handle dependency injection for the class implementing
|
|
|
|
* this abstract.
|
|
|
|
*/
|
|
|
|
public function __construct()
|
|
|
|
{
|
|
|
|
$this->request = Container::getInstance()->make('request');
|
|
|
|
|
|
|
|
if (method_exists($this, 'handle')) {
|
|
|
|
Container::getInstance()->call([$this, 'handle']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the resource name for the transformed item.
|
|
|
|
*/
|
|
|
|
abstract public function getResourceName(): string;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the authorized user for the request.
|
|
|
|
*/
|
|
|
|
protected function user(): User
|
|
|
|
{
|
|
|
|
return $this->request->user();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determines if the user making this request is authorized to access the given
|
|
|
|
* resource on the API. This is used when requested included items to ensure that
|
|
|
|
* the user and key are authorized to see the result.
|
|
|
|
*
|
|
|
|
* TODO: implement this with the new API key formats.
|
|
|
|
*/
|
|
|
|
protected function authorize(string $resource): bool
|
|
|
|
{
|
|
|
|
return $this->request->user() instanceof User;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-08-07 23:10:24 +00:00
|
|
|
* {@inheritDoc}
|
|
|
|
*
|
2021-08-07 20:06:45 +00:00
|
|
|
* @param mixed $data
|
|
|
|
* @param callable|\League\Fractal\TransformerAbstract $transformer
|
|
|
|
* @param null $resourceKey
|
2021-08-07 23:10:24 +00:00
|
|
|
*
|
2021-08-07 20:06:45 +00:00
|
|
|
* @return \League\Fractal\Resource\Item
|
|
|
|
*/
|
|
|
|
protected function item($data, $transformer, $resourceKey = null)
|
|
|
|
{
|
2021-08-07 23:00:04 +00:00
|
|
|
if (!$transformer instanceof Closure) {
|
|
|
|
self::assertSameNamespace($transformer);
|
|
|
|
}
|
2021-08-07 20:06:45 +00:00
|
|
|
|
|
|
|
$item = parent::item($data, $transformer, $resourceKey);
|
|
|
|
|
|
|
|
if (!$item->getResourceKey()) {
|
|
|
|
$item->setResourceKey($transformer->getResourceName());
|
|
|
|
}
|
|
|
|
|
|
|
|
return $item;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-08-07 23:10:24 +00:00
|
|
|
* {@inheritDoc}
|
|
|
|
*
|
2021-08-07 20:06:45 +00:00
|
|
|
* @param mixed $data
|
|
|
|
* @param callable|\League\Fractal\TransformerAbstract $transformer
|
|
|
|
* @param null $resourceKey
|
2021-08-07 23:10:24 +00:00
|
|
|
*
|
2021-08-07 20:06:45 +00:00
|
|
|
* @return \League\Fractal\Resource\Collection
|
|
|
|
*/
|
|
|
|
protected function collection($data, $transformer, $resourceKey = null)
|
|
|
|
{
|
2021-08-07 23:00:04 +00:00
|
|
|
if (!$transformer instanceof Closure) {
|
|
|
|
self::assertSameNamespace($transformer);
|
|
|
|
}
|
2021-08-07 20:06:45 +00:00
|
|
|
|
|
|
|
$collection = parent::collection($data, $transformer, $resourceKey);
|
|
|
|
|
|
|
|
if (!$collection->getResourceKey()) {
|
|
|
|
$collection->setResourceKey($transformer->getResourceName());
|
|
|
|
}
|
|
|
|
|
|
|
|
return $collection;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the default timezone to use for transformed responses. Pass a null value
|
|
|
|
* to return back to the default timezone (UTC).
|
|
|
|
*/
|
|
|
|
public static function setTimezone(string $tz = null)
|
|
|
|
{
|
|
|
|
static::$timezone = $tz ?? 'UTC';
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Asserts that the given transformer is the same base namespace as the class that
|
|
|
|
* implements this abstract transformer class. This prevents a client or application
|
|
|
|
* transformer from unintentionally transforming a resource using an unexpected type.
|
|
|
|
*
|
|
|
|
* @param callable|\League\Fractal\TransformerAbstract $transformer
|
|
|
|
*/
|
|
|
|
protected static function assertSameNamespace($transformer)
|
|
|
|
{
|
|
|
|
Assert::subclassOf($transformer, TransformerAbstract::class);
|
|
|
|
|
|
|
|
$namespace = substr(get_class($transformer), 0, strlen(class_basename($transformer)) * -1);
|
|
|
|
$expected = substr(static::class, 0, strlen(class_basename(static::class)) * -1);
|
|
|
|
|
|
|
|
Assert::same($namespace, $expected, 'Cannot invoke a new transformer (%s) that is not in the same namespace (%s).');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an ISO-8601 formatted timestamp to use in API responses. This
|
|
|
|
* time is returned in the default transformer timezone if no timezone value
|
|
|
|
* is provided.
|
|
|
|
*
|
|
|
|
* If no time is provided a null value is returned.
|
|
|
|
*
|
2021-08-07 23:10:24 +00:00
|
|
|
* @param string|\DateTimeInterface|null $timestamp
|
2021-08-07 20:06:45 +00:00
|
|
|
*/
|
|
|
|
protected static function formatTimestamp($timestamp, string $tz = null): ?string
|
|
|
|
{
|
|
|
|
if (empty($timestamp)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($timestamp instanceof DateTimeInterface) {
|
|
|
|
$value = CarbonImmutable::instance($timestamp);
|
|
|
|
} else {
|
|
|
|
$value = CarbonImmutable::createFromFormat(CarbonImmutable::DEFAULT_TO_STRING_FORMAT, $timestamp);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $value->setTimezone($tz ?? self::$timezone)->toIso8601String();
|
|
|
|
}
|
|
|
|
}
|