misc_pterodactyl-panel/app/Transformers/Api/Transformer.php

152 lines
4.6 KiB
PHP

<?php
namespace Pterodactyl\Transformers\Api;
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.
*
* @return \Pterodactyl\Models\User
*/
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;
}
/**
* @inheritDoc
* @param mixed $data
* @param callable|\League\Fractal\TransformerAbstract $transformer
* @param null $resourceKey
* @return \League\Fractal\Resource\Item
*/
protected function item($data, $transformer, $resourceKey = null)
{
self::assertSameNamespace($transformer);
$item = parent::item($data, $transformer, $resourceKey);
if (!$item->getResourceKey()) {
$item->setResourceKey($transformer->getResourceName());
}
return $item;
}
/**
* @inheritDoc
* @param mixed $data
* @param callable|\League\Fractal\TransformerAbstract $transformer
* @param null $resourceKey
* @return \League\Fractal\Resource\Collection
*/
protected function collection($data, $transformer, $resourceKey = null)
{
self::assertSameNamespace($transformer);
$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.
*
* @param null|string|\DateTimeInterface $timestamp
*/
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();
}
}