From 9edcbd266b5587c616c580833d523c5030dba8c0 Mon Sep 17 00:00:00 2001 From: Marcel Thole Date: Fri, 11 Mar 2022 14:53:41 +0100 Subject: [PATCH 1/2] Resolve 156 with introduce a simple cache and build a new ReferenceContext only when needed --- src/spec/Reference.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/spec/Reference.php b/src/spec/Reference.php index cda612a9..6d8e5221 100644 --- a/src/spec/Reference.php +++ b/src/spec/Reference.php @@ -29,6 +29,9 @@ */ class Reference implements SpecObjectInterface, DocumentContextInterface { + /** @var array */ + private static $relativeReferencesCache = []; + /** * @var string */ @@ -296,7 +299,6 @@ private function resolveTransitiveReference(Reference $referencedObject, Referen */ private function adjustRelativeReferences($referencedDocument, $basePath, $baseDocument = null, $oContext = null) { - $context = new ReferenceContext(null, $basePath); if ($baseDocument === null) { $baseDocument = $referencedDocument; } @@ -304,6 +306,11 @@ private function adjustRelativeReferences($referencedDocument, $basePath, $baseD foreach ($referencedDocument as $key => $value) { // adjust reference URLs if ($key === '$ref' && is_string($value)) { + $fullPath = $basePath . $value; + if (array_key_exists($fullPath, self::$relativeReferencesCache)) { + return self::$relativeReferencesCache[$fullPath]; + } + if (isset($value[0]) && $value[0] === '#') { // direcly inline references in the same document, // these are not going to be valid in the new context anymore @@ -315,8 +322,10 @@ private function adjustRelativeReferences($referencedDocument, $basePath, $baseD $this->_recursingInsideFile = true; $return = $this->adjustRelativeReferences($inlineDocument, $basePath, $baseDocument, $oContext); $this->_recursingInsideFile = false; + self::$relativeReferencesCache[$fullPath] = $return; return $return; } + $context = new ReferenceContext(null, $basePath); $referencedDocument[$key] = $context->resolveRelativeUri($value); $parts = explode('#', $referencedDocument[$key], 2); if ($parts[0] === $oContext->getUri()) { @@ -329,6 +338,7 @@ private function adjustRelativeReferences($referencedDocument, $basePath, $baseD // adjust URLs for 'externalValue' references in Example Objects // https://spec.openapis.org/oas/v3.0.3#example-object if ($key === 'externalValue' && is_string($value)) { + $context = new ReferenceContext(null, $basePath); $referencedDocument[$key] = $this->makeRelativePath($oContext->getUri(), $context->resolveRelativeUri($value)); continue; } From 6162a39cb0ce28e4509d8792c2446e0adc81f872 Mon Sep 17 00:00:00 2001 From: Marcel Thole Date: Wed, 20 Apr 2022 16:41:04 +0200 Subject: [PATCH 2/2] use ReferenceContext to cache the relativeReferences and prevent errors with multiple files in a single process --- src/spec/Reference.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/spec/Reference.php b/src/spec/Reference.php index 6d8e5221..d80ac495 100644 --- a/src/spec/Reference.php +++ b/src/spec/Reference.php @@ -29,9 +29,6 @@ */ class Reference implements SpecObjectInterface, DocumentContextInterface { - /** @var array */ - private static $relativeReferencesCache = []; - /** * @var string */ @@ -297,7 +294,7 @@ private function resolveTransitiveReference(Reference $referencedObject, Referen /** * Adjust relative references inside of the file to match the context of the base file */ - private function adjustRelativeReferences($referencedDocument, $basePath, $baseDocument = null, $oContext = null) + private function adjustRelativeReferences($referencedDocument, $basePath, $baseDocument = null, ?ReferenceContext $oContext = null) { if ($baseDocument === null) { $baseDocument = $referencedDocument; @@ -307,8 +304,8 @@ private function adjustRelativeReferences($referencedDocument, $basePath, $baseD // adjust reference URLs if ($key === '$ref' && is_string($value)) { $fullPath = $basePath . $value; - if (array_key_exists($fullPath, self::$relativeReferencesCache)) { - return self::$relativeReferencesCache[$fullPath]; + if ($oContext !== null && $oContext->getCache()->has($fullPath, 'relativeReferences')) { + return $oContext->getCache()->get($fullPath, 'relativeReferences'); } if (isset($value[0]) && $value[0] === '#') { @@ -322,7 +319,9 @@ private function adjustRelativeReferences($referencedDocument, $basePath, $baseD $this->_recursingInsideFile = true; $return = $this->adjustRelativeReferences($inlineDocument, $basePath, $baseDocument, $oContext); $this->_recursingInsideFile = false; - self::$relativeReferencesCache[$fullPath] = $return; + if ($oContext !== null) { + $oContext->getCache()->set($fullPath, 'relativeReferences', $return); + } return $return; } $context = new ReferenceContext(null, $basePath);