Skip to content

Commit

Permalink
Support inferring transformer model in Transformer attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
shalvah committed Sep 8, 2022
1 parent 61e51d0 commit 2b2a0c5
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 23 deletions.
2 changes: 1 addition & 1 deletion src/Attributes/ResponseFromApiResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ResponseFromApiResource
{
public function __construct(
public string $name,
public string $model,
public ?string $model = null,
public int $status = 200,
public ?string $description = '',

Expand Down
12 changes: 6 additions & 6 deletions src/Attributes/ResponseFromTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
class ResponseFromTransformer
{
public function __construct(
public string $name,
public string $model,
public int $status = 200,
public string $name,
public ?string $model = null,
public int $status = 200,
public ?string $description = '',

/* Mark if this should be used as a collection. Only needed if not using a CollectionTransformer. */
public bool $collection = false,
public array $factoryStates = [],
public array $with = [],
public bool $collection = false,
public array $factoryStates = [],
public array $with = [],
public ?string $resourceKey = null,

/* Format: [adapter, numberPerPage]. Example: [SomePaginator::class, 10] */
Expand Down
21 changes: 19 additions & 2 deletions src/Extracting/InstantiatesExampleModels.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,39 @@

namespace Knuckles\Scribe\Extracting;

use Illuminate\Support\Arr;
use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
use Knuckles\Scribe\Tools\ErrorHandlingUtils as e;
use Knuckles\Scribe\Tools\Utils;
use ReflectionFunctionAbstract;
use Throwable;

trait InstantiatesExampleModels
{
/**
* @param class-string $type
* @param string|null $type
* @param string[] $factoryStates
* @param string[] $relations
* @param \ReflectionFunctionAbstract|null $transformationMethod A method which has the model as its first parameter. Useful if the `$type` is empty.
*
* @return \Illuminate\Database\Eloquent\Model|object
*/
protected function instantiateExampleModel(string $type, array $factoryStates = [], array $relations = [])
protected function instantiateExampleModel(
?string $type = null, array $factoryStates = [],
array $relations = [], ?ReflectionFunctionAbstract $transformationMethod = null
)
{
if ($type == null) {
$parameter = Arr::first($transformationMethod->getParameters());
if ($parameter->hasType() && !$parameter->getType()->isBuiltin() && class_exists($parameter->getType()->getName())) {
// Ladies and gentlemen, we have a type!
$type = $parameter->getType()->getName();
}
}
if ($type == null) {
throw new Exception("Couldn't detect a transformer model from your doc block. Did you remember to specify a model using @transformerModel?");
}

$configuredStrategies = $this->config->get('examples.models_source', ['factoryCreate', 'factoryMake', 'databaseFirst']);

$strategies = [
Expand Down
17 changes: 3 additions & 14 deletions src/Extracting/Strategies/Responses/UseTransformerTags.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,9 @@ public function __invoke(ExtractedEndpointData $endpointData, array $routeRules
public function getTransformerResponseFromTag(Tag $transformerTag, array $allTags): ?array
{
[$statusCode, $transformerClass, $isCollection] = $this->getStatusCodeAndTransformerClass($transformerTag);
[$model, $factoryStates, $relations, $resourceKey] = $this->getClassToBeTransformed($allTags, (new ReflectionClass($transformerClass))->getMethod('transform'));
[$model, $factoryStates, $relations, $resourceKey] = $this->getClassToBeTransformed($allTags);

$modelInstantiator = fn() => $this->instantiateExampleModel($model, $factoryStates, $relations);
$modelInstantiator = fn() => $this->instantiateExampleModel($model, $factoryStates, $relations, (new ReflectionClass($transformerClass))->getMethod('transform'));
$pagination = $this->getTransformerPaginatorData($allTags);
$serializer = $this->config->get('fractal.serializer');

Expand Down Expand Up @@ -72,13 +72,12 @@ private function getStatusCodeAndTransformerClass(Tag $tag): array

/**
* @param array $tags
* @param ReflectionFunctionAbstract $transformerMethod
*
* @return array
* @throws Exception
*
*/
private function getClassToBeTransformed(array $tags, ReflectionFunctionAbstract $transformerMethod): array
private function getClassToBeTransformed(array $tags): array
{
$modelTag = Arr::first(Utils::filterDocBlockTags($tags, 'transformermodel'));

Expand All @@ -91,16 +90,6 @@ private function getClassToBeTransformed(array $tags, ReflectionFunctionAbstract
$states = $fields['states'] ? explode(',', $fields['states']) : [];
$relations = $fields['with'] ? explode(',', $fields['with']) : [];
$resourceKey = $fields['resourceKey'] ?? null;
} else {
$parameter = Arr::first($transformerMethod->getParameters());
if ($parameter->hasType() && !$parameter->getType()->isBuiltin() && class_exists($parameter->getType()->getName())) {
// Ladies and gentlemen, we have a type!
$type = $parameter->getType()->getName();
}
}

if ($type == null) {
throw new Exception("Couldn't detect a transformer model from your doc block. Did you remember to specify a model using @transformerModel?");
}

return [$type, $states, $relations, $resourceKey];
Expand Down

0 comments on commit 2b2a0c5

Please sign in to comment.