@@ -564,6 +564,15 @@ public function analyzeResourceNew(New_ $node, string $controller, string $metho
564564
565565 $ resourceClass = $ node ->class ->toString ();
566566
567+ if (!class_exists ($ resourceClass )) {
568+ $ resolvedClass = $ this ->resolveClassNameFromController ($ resourceClass , $ controller );
569+ if ($ resolvedClass && class_exists ($ resolvedClass )) {
570+ $ resourceClass = $ resolvedClass ;
571+ } else {
572+ return ;
573+ }
574+ }
575+
567576 // Use existing ResponseAnalyzer for resource analysis
568577 $ analysis = $ this ->responseAnalyzer ->analyzeJsonResourceResponse ($ resourceClass );
569578
@@ -579,6 +588,50 @@ public function analyzeResourceNew(New_ $node, string $controller, string $metho
579588 }
580589 }
581590
591+ private function resolveClassNameFromController (string $ shortClassName , string $ controllerClass ): ?string
592+ {
593+ if (!class_exists ($ controllerClass )) {
594+ return null ;
595+ }
596+
597+ try {
598+ $ reflection = new \ReflectionClass ($ controllerClass );
599+ $ filename = $ reflection ->getFileName ();
600+
601+ if (!$ filename || !file_exists ($ filename )) {
602+ return null ;
603+ }
604+
605+ $ content = file_get_contents ($ filename );
606+ $ namespace = $ reflection ->getNamespaceName ();
607+
608+ if (preg_match ('/^use\s+([^\s;]+ \\\\' . preg_quote ($ shortClassName , '/ ' ) . ')\s*;/m ' , $ content , $ matches )) {
609+ return $ matches [1 ];
610+ }
611+
612+ $ sameNamespaceClass = $ namespace . '\\' . $ shortClassName ;
613+ if (class_exists ($ sameNamespaceClass )) {
614+ return $ sameNamespaceClass ;
615+ }
616+
617+ $ resourceNamespaces = [
618+ str_replace ('\\Controllers \\' , '\\Resources \\' , $ namespace ),
619+ str_replace ('\\Http \\Controllers \\' , '\\Http \\Resources \\' , $ namespace ),
620+ ];
621+
622+ foreach ($ resourceNamespaces as $ resourceNamespace ) {
623+ $ potentialClass = $ resourceNamespace . '\\' . $ shortClassName ;
624+ if (class_exists ($ potentialClass )) {
625+ return $ potentialClass ;
626+ }
627+ }
628+
629+ return null ;
630+ } catch (\Throwable $ e ) {
631+ return null ;
632+ }
633+ }
634+
582635 /**
583636 * Detect resource wrapping configuration with inheritance support
584637 */
@@ -735,6 +788,7 @@ private function processDataResponseAttributes(ReflectionMethod $method): void
735788 $ description = $ instance ->description ?: $ this ->getStatusDescription ($ statusCode );
736789 $ resource = $ instance ->resource ;
737790 $ headers = $ instance ->headers ;
791+ $ isCollection = $ instance ->isCollection ;
738792
739793 // Create response schema based on resource if specified
740794 $ schema = null ;
@@ -752,7 +806,8 @@ private function processDataResponseAttributes(ReflectionMethod $method): void
752806 'application/json ' ,
753807 $ schema ,
754808 $ headers ,
755- is_string ($ resource ) ? $ resource : null
809+ is_string ($ resource ) ? $ resource : null ,
810+ $ isCollection
756811 );
757812 } else {
758813 $ this ->addResponse ($ statusCode , $ description , 'application/json ' , $ schema , $ headers );
@@ -1426,22 +1481,45 @@ private function addResponse(string $statusCode, string $description, ?string $c
14261481 /**
14271482 * Add success response with detailed schema analysis
14281483 */
1429- private function addSuccessResponse (string $ statusCode , string $ description , string $ controller , string $ method , ?string $ contentType = 'application/json ' , ?array $ additionalSchema = null , array $ headers = [], ?string $ resourceClass = null ): void
1484+ private function addSuccessResponse (string $ statusCode , string $ description , string $ controller , string $ method , ?string $ contentType = 'application/json ' , ?array $ additionalSchema = null , array $ headers = [], ?string $ resourceClass = null , bool $ isCollection = false ): void
14301485 {
14311486 if (! isset ($ this ->detectedResponses [$ statusCode ])) {
14321487 // Use existing ResponseAnalyzer for detailed schema analysis
14331488 $ detailedSchema = $ this ->responseAnalyzer ->analyzeControllerMethod ($ controller , $ method );
14341489
1435- // Merge with any additional schema information
1436- if ($ additionalSchema ) {
1490+ // Prefer additionalSchema (from resource class) if provided and has properties
1491+ if ($ additionalSchema && !empty ($ additionalSchema ['properties ' ])) {
1492+ $ detailedSchema = $ additionalSchema ;
1493+ } elseif ($ additionalSchema ) {
14371494 $ detailedSchema = array_merge ($ detailedSchema ?: [], $ additionalSchema );
14381495 }
14391496
14401497 // Apply Parameter attributes to enhance the schema
14411498 $ detailedSchema = $ this ->applyParameterAttributesToSchema ($ detailedSchema , $ controller , $ method );
14421499
1500+ // Wrap schema in array if isCollection is true
1501+ if ($ isCollection ) {
1502+ // Ensure we have at least a basic schema for collections
1503+ if (empty ($ detailedSchema )) {
1504+ $ detailedSchema = [
1505+ 'type ' => 'object ' ,
1506+ 'properties ' => [],
1507+ ];
1508+ }
1509+
1510+ $ detailedSchema = [
1511+ 'type ' => 'array ' ,
1512+ 'items ' => $ detailedSchema ,
1513+ ];
1514+ }
1515+
14431516 // Generate MediaType-level example from schema property examples
1444- $ responseExample = $ this ->generateResponseExampleFromSchema ($ detailedSchema );
1517+ $ responseExample = $ this ->generateResponseExampleFromSchema ($ isCollection ? ($ detailedSchema ['items ' ] ?? null ) : $ detailedSchema );
1518+
1519+ // Wrap example in array if isCollection is true
1520+ if ($ isCollection && $ responseExample ) {
1521+ $ responseExample = [$ responseExample ];
1522+ }
14451523
14461524 $ response = [
14471525 'description ' => $ description ,
0 commit comments