RestWS - Request fully loaded entitys in references

Public

This provides a modifier to the default implementation of RestWS module to allow you to load more then the default data structure. By default, if you request node/1.json from a site running RestWS you'll return the node and if there's a reference to other data, a structure that indicates its referencing something. This requires you to make an additional request to node/2.json if it was referenced in node/1 (for example).

If this snippet you can make a request to node/1.json?deep-load-refs which will load the full data model walking into 1 level deep of reference and fully loading that item, then delivering it as an array. This is useful when working with things like field collections where you may want to request a node but actually pull a node and all its field collection items. This helps reduce the number of calls you'd potentially have to make if the referenced item is whats more important then the requested item.

This is only for walking 1 level deep though as referencing could become recursive / infinite otherwise pretty quickly.

Get raw version
php
  1. /**
  2.  * Alter the outgoing response.
  3.  *
  4.  * related support issue https://drupal.org/node/2024603
  5.  *
  6.  * @param mixed $response
  7.  * The response data being returned by the REST service (not yet serialized).
  8.  *
  9.  * @param string $function
  10.  * The function being called on the REST service.
  11.  *
  12.  * @param string $format
  13.  * The name of the format serializing the response.
  14.  */
  15. function YOURMODULE_restws_response_alter(&$response, $function, $formatName) {
  16. // specific modifications based common request type
  17. if ($function == 'viewResource' && $formatName == 'json') {
  18. // allow for deep loading of resources
  19. if (isset($_GET['deep-load-refs'])) {
  20. foreach ($response as $key => &$val) {
  21. // check for a single resource verses many
  22. if (is_array($val) && isset($val[0]['id'])) {
  23. // loop through items loading them in
  24. foreach ($val as &$item) {
  25. // load the entity
  26. $entity = entity_load_single($item['resource'], $item['id']);
  27. // ensure they can view this specific item
  28. if (entity_access('view', $item['resource'], $entity)) {
  29. // create a meta wrapper to act on for entity
  30. $wrapper = entity_metadata_wrapper($item['resource'], $entity);
  31. // filter out these values
  32. $wrap = restws_property_access_filter($wrapper);
  33. $eary = (array) $entity;
  34. foreach ($eary as $property => $value) {
  35. // value needs to be removed as it didn't pass wrapper validation
  36. if (!isset($wrap[$property])) {
  37. unset($eary[$property]);
  38. }
  39. }
  40. // add values based on wrapper passing correctly
  41. $item[$item['resource']] = $eary;
  42. }
  43. }
  44. }
  45. elseif (is_array($val) && isset($val['id'])) {
  46. // load the entity
  47. $entity = entity_load_single($val['resource'], $val['id']);
  48. // ensure they can view this specific item
  49. if (entity_access('view', $val['resource'], $entity)) {
  50. // create a meta wrapper to act on for entity
  51. $wrapper = entity_metadata_wrapper($val['resource'], $entity);
  52. // filter out fields
  53. $wrap = restws_property_access_filter($wrapper);
  54. // typecast entity as array for property evaluation
  55. $eary = (array) $entity;
  56. foreach ($eary as $property => $value) {
  57. // value needs to be removed as it didn't pass wrapper validation
  58. if (!isset($wrap[$property])) {
  59. unset($eary[$property]);
  60. }
  61. }
  62. // add values based on wrapper passing correctly
  63. $val[$val['resource']] = $eary;
  64. }
  65. }
  66. }
  67. }
  68. }
  69. }

Comments

Hayden Kibble's picture

Fantastic, you just helped me make a project for a big client even more awesome :)

I hade to apply the patch found here to add the required hook to restws:
https://drupal.org/node/1878064

tim's picture

Nice idea but this only works from loading a node I need it to work for queries, any ideas as it doesnt effect multiple nodes brought back?

btopro's picture

Yeah I just noticed the issue you are describing. $function == 'viewResource' is what's limiting it. This could become extremely expensive transaction if done against a queried resource set. Take out that function viewresource part and see if it works for generic node querying.

G.Drakakis's picture

I have a strange problem, I would appretiate any help. 2 levels works just find with taxonomy and field_collections but not with files! So I keep getting the usual uri 'domain.com/file/123' instead of the full path of the image. Any idea how to fix this?