misc_pterodactyl-panel/app/Transformers/Api/Transformer.php
Matthew Penner 363c4fd49f
php-cs-fixer
2022-12-14 17:06:28 -07:00

154 lines
4.8 KiB
PHP

<?php
namespace Pterodactyl\Transformers\Api;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Webmozart\Assert\Assert;
use League\Fractal\Resource\Item;
use Illuminate\Container\Container;
use League\Fractal\Resource\Collection;
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;
}
/**
* {@inheritDoc}
*
* @param mixed $data
* @param callable|\League\Fractal\TransformerAbstract $transformer
*/
protected function item($data, $transformer, ?string $resourceKey = null): Item
{
if (!$transformer instanceof \Closure) {
self::assertSameNamespace($transformer);
}
$item = parent::item($data, $transformer, $resourceKey);
if (!$item->getResourceKey() && method_exists($transformer, 'getResourceName')) {
$item->setResourceKey($transformer->getResourceName());
}
return $item;
}
/**
* {@inheritDoc}
*
* @param mixed $data
* @param callable|\League\Fractal\TransformerAbstract $transformer
*/
protected function collection($data, $transformer, ?string $resourceKey = null): Collection
{
if (!$transformer instanceof \Closure) {
self::assertSameNamespace($transformer);
}
$collection = parent::collection($data, $transformer, $resourceKey);
if (!$collection->getResourceKey() && method_exists($transformer, 'getResourceName')) {
$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 string|\DateTimeInterface|null $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(CarbonInterface::DEFAULT_TO_STRING_FORMAT, $timestamp);
}
return $value->setTimezone($tz ?? self::$timezone)->toAtomString();
}
}