瀏覽代碼

Support inferring transformer model in Transformer attribute

shalvah 2 年之前
父節點
當前提交
2b2a0c5505

+ 1 - 1
src/Attributes/ResponseFromApiResource.php

@@ -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 = '',
 

+ 6 - 6
src/Attributes/ResponseFromTransformer.php

@@ -8,15 +8,15 @@ use Attribute;
 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] */

+ 19 - 2
src/Extracting/InstantiatesExampleModels.php

@@ -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 = [

+ 3 - 14
src/Extracting/Strategies/Responses/UseTransformerTags.php

@@ -40,9 +40,9 @@ class UseTransformerTags extends Strategy
     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');
 
@@ -72,13 +72,12 @@ class UseTransformerTags extends Strategy
 
     /**
      * @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'));
 
@@ -91,16 +90,6 @@ class UseTransformerTags extends Strategy
             $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];