From d8b5a54ee51d25edc6a4557999765edd4a193d33 Mon Sep 17 00:00:00 2001 From: Teoh Han Hui Date: Thu, 18 Feb 2016 21:16:21 +0800 Subject: [PATCH] Handle circular references in ApiParser Fixes nelmio/NelmioApiDocBundle#678 --- Nelmio/Parser/ApiParser.php | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Nelmio/Parser/ApiParser.php b/Nelmio/Parser/ApiParser.php index cdf95a7ef2a..3c8acfd9c70 100644 --- a/Nelmio/Parser/ApiParser.php +++ b/Nelmio/Parser/ApiParser.php @@ -84,11 +84,14 @@ public function parse(array $item) * @param ResourceInterface $resource * @param string $entityClass * @param string $io + * @param string[] $visited * * @return array */ - private function parseClass(ResourceInterface $resource, $entityClass, $io) + private function parseClass(ResourceInterface $resource, $entityClass, $io, array $visited = array()) { + $visited[] = $entityClass; + $classMetadata = $this->classMetadataFactory->getMetadataFor( $entityClass, $resource->getNormalizationGroups(), @@ -103,7 +106,7 @@ private function parseClass(ResourceInterface $resource, $entityClass, $io) ($attributeMetadata->isReadable() && self::OUT_PREFIX === $io) || ($attributeMetadata->isWritable() && self::IN_PREFIX === $io) ) { - $data[$name] = $this->parseAttribute($resource, $attributeMetadata, $io); + $data[$name] = $this->parseAttribute($resource, $attributeMetadata, $io, null, $visited); } } @@ -117,10 +120,11 @@ private function parseClass(ResourceInterface $resource, $entityClass, $io) * @param AttributeMetadataInterface $attributeMetadata * @param string $io * @param Type|null $type + * @param string[] $visited * * @return array */ - private function parseAttribute(ResourceInterface $resource, AttributeMetadataInterface $attributeMetadata, $io, Type $type = null) + private function parseAttribute(ResourceInterface $resource, AttributeMetadataInterface $attributeMetadata, $io, Type $type = null, array $visited = array()) { $data = array( 'dataType' => null, @@ -144,7 +148,7 @@ private function parseAttribute(ResourceInterface $resource, AttributeMetadataIn $data['actualType'] = DataTypes::COLLECTION; if ($collectionType = $type->getCollectionType()) { - $subAttribute = $this->parseAttribute($resource, $attributeMetadata, $io, $collectionType); + $subAttribute = $this->parseAttribute($resource, $attributeMetadata, $io, $collectionType, $visited); if (self::IRI === $subAttribute['dataType']) { $data['dataType'] = 'array of IRIs'; $data['subType'] = DataTypes::STRING; @@ -182,7 +186,7 @@ private function parseAttribute(ResourceInterface $resource, AttributeMetadataIn $data['actualType'] = DataTypes::MODEL; $data['subType'] = $class; - $data['children'] = $this->parseClass($resource, $class, $io); + $data['children'] = in_array($class, $visited) ? [] : $this->parseClass($resource, $class, $io, $visited); return $data; }