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(); } }