Skip to content

Commit 042dba3

Browse files
David DiersMateu Aguiló Bosch
David Diers
authored and
Mateu Aguiló Bosch
committed
Issue #355: Fix bad HAL+JSON
Squashed commit of the following: commit 29966be Merge: ce7eeb2 3ac61a6 Author: David Diers <[email protected]> Date: Fri Mar 6 14:12:04 2015 -0600 Merge branch '7.x-1.x' of github.com:RESTful-Drupal/restful into 355-Bad_Hal commit ce7eeb2 Merge: 86d5a7d 10e9284 Author: David Diers <[email protected]> Date: Thu Mar 5 14:19:18 2015 -0600 merged upstream commit 10e9284 Merge: 2b188a4 64c4ba0 Author: David Diers <[email protected]> Date: Thu Mar 5 14:17:27 2015 -0600 Merged in master. commit 86d5a7d Author: David Diers <[email protected]> Date: Thu Mar 5 14:13:22 2015 -0600 Resolved single resource issue with _embedded property not nesting at the resource root. commit fbeb594 Merge: 2b188a4 1f47b49 Author: David Diers <[email protected]> Date: Thu Mar 5 13:06:58 2015 -0600 Merge branch '355-Bad_Hal' of github.com:adaddinsane/restful into 355-Bad_Hal commit 2b188a4 Author: David Diers <[email protected]> Date: Thu Feb 19 09:22:08 2015 -0600 Check to see if _links is set before declaring. closes #414 commit 1f47b49 Author: steve.turnbull <[email protected]> Date: Wed Jan 14 09:05:09 2015 +0000 355: Tidy up variables. commit 31fc533 Author: steve.turnbull <[email protected]> Date: Tue Jan 13 16:26:51 2015 +0000 355: Fix HAL:JSON so that it embeds resources, and in the right place.
1 parent e0b858c commit 042dba3

File tree

1 file changed

+70
-57
lines changed

1 file changed

+70
-57
lines changed

plugins/formatter/hal_json/RestfulFormatterHalJson.class.php

+70-57
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
class RestfulFormatterHalJson extends \RestfulFormatterBase implements \RestfulFormatterInterface {
9+
910
/**
1011
* Content Type
1112
*
@@ -24,8 +25,8 @@ public function prepare(array $data) {
2425
return $data;
2526
}
2627
// Here we get the data after calling the backend storage for the resources.
27-
2828
$curies_resource = $this->withCurie($this->handler->getResourceName());
29+
2930
$output = array();
3031

3132
foreach ($data as &$row) {
@@ -40,7 +41,7 @@ public function prepare(array $data) {
4041
method_exists($this->handler, 'isListRequest') &&
4142
$this->handler->isListRequest()
4243
) {
43-
// Get the total number of items for the current request without pagination.
44+
// Get total number of items for the current request w/out pagination.
4445
$output['count'] = $this->handler->getTotalCount();
4546
}
4647
if (method_exists($this->handler, 'additionalHateoas')) {
@@ -68,7 +69,7 @@ public function prepare(array $data) {
6869
/**
6970
* Add HATEOAS links to list of item.
7071
*
71-
* @param $data
72+
* @param array $data
7273
* The data array after initial massaging.
7374
*/
7475
protected function addHateoas(array &$data) {
@@ -142,20 +143,31 @@ public function prepareRow(array $row, array &$output) {
142143
return $row;
143144
}
144145

145-
foreach ($this->handler->getPublicFields() as $pubilc_field_name => $public_field) {
146+
$embedded = array();
147+
148+
foreach ($this->handler->getPublicFields() as $public_field_name => $public_field) {
146149
if (empty($public_field['resource'])) {
147150
// Not a resource.
148151
continue;
149152
}
150153

151-
if (empty($row[$pubilc_field_name])) {
154+
if (empty($row[$public_field_name])) {
152155
// No value.
153156
continue;
154157
}
155158

156-
$output += array('_embedded' => array());
159+
$nested_embed = $this->handler->isListRequest();
160+
161+
if ($nested_embed) {
162+
$output += array('_embedded' => array());
163+
}
164+
165+
$this->moveReferencesToEmbeds($embedded, $row, $public_field, $public_field_name, $output);
157166

158-
$this->moveReferencesToEmbeds($output, $row, $public_field, $pubilc_field_name);
167+
}
168+
169+
if (!empty($embedded) && $nested_embed) {
170+
$row['_embedded'] = $embedded;
159171
}
160172

161173
return $row;
@@ -219,70 +231,71 @@ protected function getCurie() {
219231
/**
220232
* Move the fields referencing other resources to the _embed key.
221233
*
222-
* @param array $output
223-
* Output array to be modified.
234+
* Note that for multiple value entityreference
235+
* fields $row[$public_field_name] will be an array of values rather than a
236+
* single value.
237+
*
238+
* @param array $embedded
239+
* Embedded array to be modified.
224240
* @param array $row
225241
* The row being processed.
226242
* @param array $public_field
227243
* The public field configuration array.
228-
* @param $public_field_name
244+
* @param string $public_field_name
229245
* The name of the public field.
246+
* @param array $output
247+
* Output array to be modified.
230248
*/
231-
protected function moveReferencesToEmbeds(array &$output, array &$row, $public_field, $public_field_name) {
232-
$value_metadata = $this->handler->getValueMetadata($row['id'], $public_field_name);
233-
if (\RestfulBase::isArrayNumeric($row[$public_field_name])) {
234-
foreach ($row[$public_field_name] as $index => $resource_row) {
235-
if (empty($value_metadata[$index])) {
249+
protected function moveReferencesToEmbeds(array &$embedded, array &$row, $public_field, $public_field_name, array &$output) {
250+
$values_metadata = $this->handler->getValueMetadata($row['id'], $public_field_name);
251+
252+
// Wrap the row in an array if it isn't.
253+
if (!is_array($row[$public_field_name])) {
254+
$row[$public_field_name] = array();
255+
}
256+
$rows = RestfulBase::isArrayNumeric($row[$public_field_name]) ? $row[$public_field_name] : array($row[$public_field_name]);
257+
258+
foreach ($rows as $subindex => $subrow) {
259+
$metadata = $values_metadata[$subindex];
260+
261+
// Loop through each value for the field.
262+
foreach ($subrow as $index => $resource_row) {
263+
if (empty($metadata[$index])) {
236264
// No metadata.
237265
continue;
238266
}
239-
$metadata = $value_metadata[$index];
240-
$this->moveMetadataResource($output, $public_field, $metadata, $resource_row);
241-
}
242-
}
243-
else {
244-
$this->moveMetadataResource($output, $public_field, $value_metadata, $row[$public_field_name]);
245-
}
246267

247-
// Remove the original reference.
248-
unset($row[$public_field_name]);
249-
}
268+
// If there is no resource name in the metadata for this particular
269+
// value, assume that we are referring to the first resource in the
270+
// field definition.
271+
$resource_name = NULL;
272+
if (!empty($metadata['resource_name'])) {
273+
// Make sure that the resource in the metadata exists in the list of
274+
// resources available for this particular public field.
275+
foreach ($public_field['resource'] as $resource) {
276+
if ($resource['name'] != $metadata['resource_name']) {
277+
continue;
278+
}
279+
$resource_name = $metadata['resource_name'];
280+
}
281+
}
282+
if (empty($resource_name)) {
283+
$resource = reset($public_field['resource']);
284+
$resource_name = $resource['name'];
285+
}
250286

251-
/**
252-
* Move a single "embedded resource" to be under the "_embedded" property.
253-
*
254-
* @param array $output
255-
* Output array to be modified. Passed by reference.
256-
* @param array $public_field
257-
* The public field configuration array.
258-
* @param $metadata
259-
* The metadata to add.
260-
* @param $resource_row
261-
* The resource row.
262-
*/
263-
protected function moveMetadataResource(array &$output, $public_field, $metadata, $resource_row) {
264-
// If there is no resource name in the metadata for this particular value,
265-
// assume that we are referring to the first resource in the field
266-
// definition.
267-
$resource_name = NULL;
268-
if (!empty($metadata['resource_name'])) {
269-
// Make sure that the resource in the metadata exists in the list of
270-
// resources available for this particular public field.
271-
foreach ($public_field['resource'] as $resource) {
272-
if ($resource['name'] != $metadata['resource_name']) {
273-
continue;
287+
$curies_resource = $this->withCurie($resource_name);
288+
$prepared_row = $this->prepareRow($subrow, $output);
289+
if ($this->handler->isListRequest()) {
290+
$embedded[$curies_resource][] = $prepared_row;
291+
}
292+
else {
293+
$output['_embedded'][$curies_resource][] = $prepared_row;
274294
}
275-
$resource_name = $metadata['resource_name'];
276295
}
277296
}
278-
if (empty($resource_name)) {
279-
$resource = reset($public_field['resource']);
280-
$resource_name = $resource['name'];
281-
}
282297

283-
$curies_resource = $this->withCurie($resource_name);
284-
$resource_row = $this->prepareRow($resource_row, $output);
285-
$output['_embedded'][$curies_resource][] = $resource_row;
298+
// Remove the original reference.
299+
unset($row[$public_field_name]);
286300
}
287-
288301
}

0 commit comments

Comments
 (0)