.../Value/RelationshipNormalizerValue.php | 46 ++++++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/Normalizer/Value/RelationshipNormalizerValue.php b/src/Normalizer/Value/RelationshipNormalizerValue.php index 2549879..df0d653 100644 --- a/src/Normalizer/Value/RelationshipNormalizerValue.php +++ b/src/Normalizer/Value/RelationshipNormalizerValue.php @@ -74,9 +74,49 @@ class RelationshipNormalizerValue extends FieldNormalizerValue { // Empty 'to-many' relationships must be an empty array. // @link http://jsonapi.org/format/#document-resource-object-linkage $data = parent::rasterizeValue() ?: []; - return empty($data) && $this->cardinality == 1 - ? ['data' => NULL, 'links' => $links] - : ['data' => $data, 'links' => $links]; + + if ($this->cardinality === 1) { + return empty($data) + ? ['data' => NULL, 'links' => $links] + : ['data' => $data, 'links' => $links]; + } + else { + return ['data' => static::ensureUniqueResourceLinkage($data), 'links' => $links]; + } + } + + /** + * Ensures unique resource linkage. + * + * @param array $resource_identifier_objects + * A list of JSON API resource identifier objects. + * @return array + * A set of JSON API resource identifier objects, with those having multiple + * occurrences getting [meta][arity]. + * + * @see http://jsonapi.org/format/#document-resource-object-relationships + * @see https://github.com/json-api/json-api/pull/1156#issuecomment-325377995 + */ + protected static function ensureUniqueResourceLinkage(array $resource_identifier_objects) { + if (count($resource_identifier_objects) <= 1) { + return $resource_identifier_objects; + } + + $unique_resource_identifier_objects = array_reduce($resource_identifier_objects, function ($carry, $resource_identifier_object) { + $id = $resource_identifier_object['id']; + if (!isset($carry[$id])) { + $carry[$id] = $resource_identifier_object; + } + else { + if (!isset($carry[$id]['meta'])) { + $carry[$id]['meta']['arity'] = 1; + } + $carry[$id]['meta']['arity']++; + } + return $carry; + }, []); + + return array_values($unique_resource_identifier_objects); } /**