Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
Allow unknown properties for forward compatability with JsonAPI 1.1
  • Loading branch information
Art4 committed Jul 18, 2024
commit 07c1f61010ccf5014d69c8d0783321fbe950263f
44 changes: 19 additions & 25 deletions src/V1/Document.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,26 @@ protected function parse(mixed $object): void
throw new ValidationException('The properties `data` and `errors` MUST NOT coexist in Document.');
}

if (property_exists($object, 'data')) {
$this->set('data', $this->parseData($object->data));
}

if (property_exists($object, 'meta')) {
$this->set('meta', $this->create('Meta', $object->meta));
}

if (property_exists($object, 'errors')) {
$this->set('errors', $this->create('ErrorCollection', $object->errors));
}

if (property_exists($object, 'included')) {
if (!property_exists($object, 'data')) {
throw new ValidationException('If Document does not contain a `data` property, the `included` property MUST NOT be present either.');
foreach ($object as $key => $value) {
if ($key === 'data') {
$this->set('data', $this->parseData($value));
} else if ($key === 'meta') {
$this->set('meta', $this->create('Meta', $value));
} else if ($key === 'errors') {
$this->set('errors', $this->create('ErrorCollection', $value));
} else if ($key === 'included') {
if (!property_exists($object, 'data')) {
throw new ValidationException('If Document does not contain a `data` property, the `included` property MUST NOT be present either.');
}

$this->set('included', $this->create('ResourceCollection', $object->included));
} else if ($key === 'jsonapi') {
$this->set('jsonapi', $this->create('Jsonapi', $value));
} else if ($key === 'links') {
$this->set('links', $this->create('DocumentLink', $value));
} else {
$this->set($key, $value);
}

$this->set('included', $this->create('ResourceCollection', $object->included));
}

if (property_exists($object, 'jsonapi')) {
$this->set('jsonapi', $this->create('Jsonapi', $object->jsonapi));
}

if (property_exists($object, 'links')) {
$this->set('links', $this->create('DocumentLink', $object->links));
}
}

Expand Down
20 changes: 11 additions & 9 deletions src/V1/Jsonapi.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,18 @@ protected function parse(mixed $object): void
throw new ValidationException('Jsonapi has to be an object, "' . gettype($object) . '" given.');
}

if (property_exists($object, 'version')) {
if (is_object($object->version) or is_array($object->version)) {
throw new ValidationException('property "version" cannot be an object or array, "' . gettype($object->version) . '" given.');
foreach ($object as $key => $value) {
if ($key === 'version') {
if (is_object($value) or is_array($value)) {
throw new ValidationException('property "version" cannot be an object or array, "' . gettype($value) . '" given.');
}

$this->set('version', strval($value));
} else if ($key === 'meta') {
$this->set('meta', $this->create('Meta', $value));
} else {
$this->set($key, $value);
}

$this->set('version', strval($object->version));
}

if (property_exists($object, 'meta')) {
$this->set('meta', $this->create('Meta', $object->meta));
}
}

Expand Down
8 changes: 3 additions & 5 deletions tests/Functional/ParsingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ public function testParseNormativeStatementsForVersion10Correctly(): void
$document = Parser::parseResponseString($string);

$this->assertInstanceOf(Document::class, $document);
$this->assertSame(['data', 'included', 'jsonapi'], $document->getKeys());
$this->assertSame(['jsonapi', 'data', 'included'], $document->getKeys());
$this->assertSame('1.0', $document->get('jsonapi.version'));
$this->assertInstanceOf(Accessable::class, $document->get('data'));
$this->assertCount(6, $document->get('data')->getKeys());
Expand All @@ -643,7 +643,7 @@ public function testParseNormativeStatementsForVersion11Correctly(): void
$document = Parser::parseResponseString($string);

$this->assertInstanceOf(Document::class, $document);
$this->assertSame(['data', 'included', 'jsonapi'], $document->getKeys());
$this->assertSame(['jsonapi', 'data', 'included'], $document->getKeys());
$this->assertSame('1.1', $document->get('jsonapi.version'));
$this->assertInstanceOf(Accessable::class, $document->get('data'));
$this->assertCount(6, $document->get('data')->getKeys());
Expand All @@ -659,9 +659,7 @@ public function testParseJsonApiObjectWithVersion11Correctly(): void
$this->assertInstanceOf(Document::class, $document);
$this->assertSame(['meta', 'jsonapi'], $document->getKeys());
$this->assertInstanceOf(Accessable::class, $document->get('jsonapi'));
$this->assertSame(['version'], $document->get('jsonapi')->getKeys());
// TODO #90: Add support for unknown properties
// $this->assertSame(['version', 'ext', 'profile'], $document->get('jsonapi')->getKeys());
$this->assertSame(['version', 'ext', 'profile'], $document->get('jsonapi')->getKeys());
$this->assertSame('1.1', $document->get('jsonapi.version'));
}
}
5 changes: 0 additions & 5 deletions tests/Functional/SerializerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,6 @@ public function testParseJsonapiDataWithErrorAbortManager(string $filename, bool
$document = $manager->parse($input);

$expected = json_decode($string, true);
// TODO #90: Add support for unknown properties
//** @phpstan-ignore-next-line */
unset($expected['jsonapi']['ext']);
//** @phpstan-ignore-next-line */
unset($expected['jsonapi']['profile']);

// Test full array
$this->assertEquals(
Expand Down
15 changes: 8 additions & 7 deletions tests/Unit/V1/DocumentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ public function testCreateWithObjectReturnsSelf(): void
{
$object = new \stdClass();
$object->meta = new \stdClass();
$object->ignore = 'this property must be ignored';
$object->fc = 'test property for forward compatability';

$document = new Document($object, $this->manager, $this->parent);

$this->assertInstanceOf(Document::class, $document);
$this->assertInstanceOf(Accessable::class, $document);
$this->assertSame($document->getKeys(), ['meta']);
$this->assertSame($document->getKeys(), ['meta', 'fc']);
$this->assertTrue($document->has('meta'));
$this->assertTrue($document->has('fc'));
$this->assertInstanceOf(Accessable::class, $document->get('meta'));
$this->assertFalse($document->has('data'));
$this->assertFalse($document->has('errors'));
Expand All @@ -63,26 +64,26 @@ public function testCreateWithAllPossibleValues(): void
$object->data = new \stdClass();
$object->data->type = 'types';
$object->data->id = 'id';
$object->meta = new \stdClass();
$object->included = [];
$object->included[0] = new \stdClass();
$object->included[0]->type = 'types';
$object->included[0]->id = 'id';
$object->links = new \stdClass();
$object->jsonapi = new \stdClass();
$object->meta = new \stdClass();
$object->ignore = 'this property must be ignored';
$object->links = new \stdClass();
$object->fc = 'test property for forward compatability';

$document = new Document($object, $this->manager, $this->parent);

$this->assertInstanceOf(Document::class, $document);
$this->assertSame($document->getKeys(), ['data', 'meta', 'included', 'jsonapi', 'links']);
$this->assertSame($document->getKeys(), ['data', 'meta', 'included', 'jsonapi', 'links', 'fc']);
$this->assertTrue($document->has('data'));
$this->assertTrue($document->has('meta'));
$this->assertFalse($document->has('errors'));
$this->assertTrue($document->has('jsonapi'));
$this->assertTrue($document->has('links'));
$this->assertTrue($document->has('included'));
$this->assertFalse($document->has('ignore'));
$this->assertTrue($document->has('fc'));
}

/**
Expand Down
12 changes: 6 additions & 6 deletions tests/Unit/V1/JsonapiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,18 @@ public function testCreateWithObject(): void
// This object MAY also contain a meta member, whose value is a meta object
$object->meta = new \stdClass();

// these properties must be ignored
$object->testobj = new \stdClass();
$object->teststring = 'http://example.org/link';
// test properties for forward compatability
$object->fcobj = new \stdClass();
$object->fcstring = 'http://example.org/link';

$jsonapi = new Jsonapi($object, $this->manager, $this->parent);

$this->assertInstanceOf(Jsonapi::class, $jsonapi);
$this->assertInstanceOf(Accessable::class, $jsonapi);
$this->assertSame($jsonapi->getKeys(), ['version', 'meta']);
$this->assertSame($jsonapi->getKeys(), ['version', 'meta', 'fcobj', 'fcstring']);

$this->assertFalse($jsonapi->has('testobj'));
$this->assertFalse($jsonapi->has('teststring'));
$this->assertTrue($jsonapi->has('fcobj'));
$this->assertTrue($jsonapi->has('fcstring'));
$this->assertTrue($jsonapi->has('version'));
$this->assertSame($jsonapi->get('version'), '1.0');
$this->assertTrue($jsonapi->has('meta'));
Expand Down