Skip to content

Recursion Update for php-json-schema #167

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ User::export($user); // Exception: Required property missing: id at #->propertie

#### Nested structures

Nested structures allow you to make composition: flatten several objects in one and separate back.
Nested structures allow you to make composition: flatten several objects in one and separate back. For nested structures that exceed a depth of the default 200 recursion limit, submit a Context maxNestLevel of an appropriate amount.

```php
$user = new User();
Expand Down Expand Up @@ -462,14 +462,16 @@ $this->assertSame(4, $res->one);
#### Overriding mapping classes

If you want to map data to a different class you can register mapping at top level of your importer structure.

Additionally, you can use the option property, maxNestLevel to increase your depth beyond the default 200 which may be
useful for certain complex Schema's.
```php
class CustomSwaggerSchema extends SwaggerSchema
{
public static function import($data, ?Context $options = null)
{
if ($options === null) {
$options = new Context();
$options->maxNestLevel = 500;
}
$options->objectItemClassMapping[Schema::className()] = CustomSchema::className();
return parent::import($data, $options);
Expand Down
7 changes: 6 additions & 1 deletion src/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

class Context extends MagicMap
{
const DEFAULT_MAX_NEST = 200;

public $import = true;

/** @var DataPreProcessor */
Expand Down Expand Up @@ -51,6 +53,9 @@ class Context extends MagicMap

public $isRef = false;

/** @var int property max recursive nesting depth */
public $maxNestLevel = self::DEFAULT_MAX_NEST;

/**
* Dereference $ref unless there is a $ref property defined with format not equal to `uri-reference`.
* Default JSON Schema behavior is to dereference only if there is a $ref property defined with format
Expand Down Expand Up @@ -134,4 +139,4 @@ public function withDefault()
}


}
}
10 changes: 6 additions & 4 deletions src/RefResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class RefResolver
public $url;
/** @var null|RefResolver */
private $rootResolver;
private int $maxNestLevel = 200; //Change this via options submitted to ::import if needed

/**
* @param mixed $resolutionScope
Expand Down Expand Up @@ -102,9 +103,10 @@ public function setupResolutionScope($id, $data)
* RefResolver constructor.
* @param JsonSchema $rootData
*/
public function __construct($rootData = null)
public function __construct($rootData = null, int $maxNestLevel = 200)
{
$this->rootData = $rootData;
$this->maxNestLevel = $max_nest_level;
}

public function setRootData($rootData)
Expand Down Expand Up @@ -224,8 +226,8 @@ public function resolveReference($referencePath)
*/
public function preProcessReferences($data, Context $options, $nestingLevel = 0)
{
if ($nestingLevel > 200) {
throw new Exception('Too deep nesting level', Exception::DEEP_NESTING);
if ($nestingLevel > $this->maxNestLevel) { //Updated due to specific recursion depth from Amazon product JSON Schemas - yep 200 was not enough
throw new Exception('Too deep nesting level. Nesting / Recursion level (' . $nestingLevel . ') exceeds ' . $this->maxNestLevel , Exception::DEEP_NESTING);
}
if (is_array($data)) {
foreach ($data as $key => $item) {
Expand Down Expand Up @@ -264,4 +266,4 @@ public function preProcessReferences($data, Context $options, $nestingLevel = 0)
}


}
}
2 changes: 1 addition & 1 deletion src/Schema.php
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public function in($data, ?Context $options = null)
$options->import = true;

if ($options->refResolver === null) {
$options->refResolver = new RefResolver($data);
$options->refResolver = new RefResolver($data, $options->maxNestLevel ?? Context::DEFAULT_MAX_NEST);
} else {
$options->refResolver->setRootData($data);
}
Expand Down