danielebarchiesi@4
|
1 <?php
|
danielebarchiesi@4
|
2
|
danielebarchiesi@4
|
3 /**
|
danielebarchiesi@4
|
4 * @file
|
danielebarchiesi@4
|
5 * RESTful web services module formats.
|
danielebarchiesi@4
|
6 */
|
danielebarchiesi@4
|
7
|
danielebarchiesi@4
|
8 /**
|
danielebarchiesi@4
|
9 * Interface implemented by formatter implementations for the http client.
|
danielebarchiesi@4
|
10 */
|
danielebarchiesi@4
|
11 interface RestWSFormatInterface {
|
danielebarchiesi@4
|
12
|
danielebarchiesi@4
|
13 /**
|
danielebarchiesi@4
|
14 * Gets the representation of a resource.
|
danielebarchiesi@4
|
15 *
|
danielebarchiesi@4
|
16 * @param RestWSResourceControllerInterface $resourceController
|
danielebarchiesi@4
|
17 * The controller used to retrieve the resource.
|
danielebarchiesi@4
|
18 * @param int|string $id
|
danielebarchiesi@4
|
19 * The id of the resource that should be returned.
|
danielebarchiesi@4
|
20 *
|
danielebarchiesi@4
|
21 * @return string
|
danielebarchiesi@4
|
22 * The representation of the resource.
|
danielebarchiesi@4
|
23 */
|
danielebarchiesi@4
|
24 public function viewResource($resourceController, $id);
|
danielebarchiesi@4
|
25
|
danielebarchiesi@4
|
26 /**
|
danielebarchiesi@4
|
27 * Create a resource.
|
danielebarchiesi@4
|
28 *
|
danielebarchiesi@4
|
29 * @param RestWSResourceControllerInterface $resourceController
|
danielebarchiesi@4
|
30 * The controller used to create the resource.
|
danielebarchiesi@4
|
31 * @param string $data
|
danielebarchiesi@4
|
32 * The representation of the resource.
|
danielebarchiesi@4
|
33 *
|
danielebarchiesi@4
|
34 * @return int|string
|
danielebarchiesi@4
|
35 * The id of the newly created resource.
|
danielebarchiesi@4
|
36 */
|
danielebarchiesi@4
|
37 public function createResource($resourceController, $data);
|
danielebarchiesi@4
|
38
|
danielebarchiesi@4
|
39 /**
|
danielebarchiesi@4
|
40 * Update a resource.
|
danielebarchiesi@4
|
41 *
|
danielebarchiesi@4
|
42 * @param RestWSResourceControllerInterface $resourceController
|
danielebarchiesi@4
|
43 * The controller used to update the resource.
|
danielebarchiesi@4
|
44 * @param int|string $id
|
danielebarchiesi@4
|
45 * The id of the resource that should be updated.
|
danielebarchiesi@4
|
46 * @param string $data
|
danielebarchiesi@4
|
47 * The representation of the resource.
|
danielebarchiesi@4
|
48 */
|
danielebarchiesi@4
|
49 public function updateResource($resourceController, $id, $data);
|
danielebarchiesi@4
|
50
|
danielebarchiesi@4
|
51 /**
|
danielebarchiesi@4
|
52 * Delete a resource.
|
danielebarchiesi@4
|
53 *
|
danielebarchiesi@4
|
54 * @param RestWSResourceControllerInterface $resourceController
|
danielebarchiesi@4
|
55 * The controller used to update the resource.
|
danielebarchiesi@4
|
56 * @param int|string $id
|
danielebarchiesi@4
|
57 * The id of the resource that should be deleted.
|
danielebarchiesi@4
|
58 */
|
danielebarchiesi@4
|
59 public function deleteResource($resourceController, $id);
|
danielebarchiesi@4
|
60
|
danielebarchiesi@4
|
61 /**
|
danielebarchiesi@4
|
62 * Query for a resource.
|
danielebarchiesi@4
|
63 *
|
danielebarchiesi@4
|
64 * If a format doesn't want to implement querying, then it should throw an
|
danielebarchiesi@4
|
65 * RestWSException with the 501 HTTP status code.
|
danielebarchiesi@4
|
66 *
|
danielebarchiesi@4
|
67 * @param RestWSResourceControllerInterface $resourceController
|
danielebarchiesi@4
|
68 * The controller used to query the resource.
|
danielebarchiesi@4
|
69 * @param array $payload
|
danielebarchiesi@4
|
70 * An optional way to pass the query parameters.
|
danielebarchiesi@4
|
71 *
|
danielebarchiesi@4
|
72 * @return string
|
danielebarchiesi@4
|
73 * The serialized representation of a list of resources.
|
danielebarchiesi@4
|
74 */
|
danielebarchiesi@4
|
75 public function queryResource($resourceController, $payload);
|
danielebarchiesi@4
|
76
|
danielebarchiesi@4
|
77
|
danielebarchiesi@4
|
78 /**
|
danielebarchiesi@4
|
79 * Returns the mime type of this format, e.g. 'application/json' or
|
danielebarchiesi@4
|
80 * 'application/xml'.
|
danielebarchiesi@4
|
81 */
|
danielebarchiesi@4
|
82 public function mimeType();
|
danielebarchiesi@4
|
83
|
danielebarchiesi@4
|
84 /**
|
danielebarchiesi@4
|
85 * Returns the short name of this format.
|
danielebarchiesi@4
|
86 *
|
danielebarchiesi@4
|
87 * @return string
|
danielebarchiesi@4
|
88 * The format name, example: "json".
|
danielebarchiesi@4
|
89 */
|
danielebarchiesi@4
|
90 public function getName();
|
danielebarchiesi@4
|
91 }
|
danielebarchiesi@4
|
92
|
danielebarchiesi@4
|
93 /**
|
danielebarchiesi@4
|
94 * A base for all simple formats that are just serializing/unserializing an
|
danielebarchiesi@4
|
95 * array of property values.
|
danielebarchiesi@4
|
96 */
|
danielebarchiesi@4
|
97 abstract class RestWSBaseFormat implements RestWSFormatInterface {
|
danielebarchiesi@4
|
98
|
danielebarchiesi@4
|
99 protected $formatName;
|
danielebarchiesi@4
|
100 protected $formatInfo;
|
danielebarchiesi@4
|
101
|
danielebarchiesi@4
|
102 public function __construct($name, $info) {
|
danielebarchiesi@4
|
103 $this->formatName = $name;
|
danielebarchiesi@4
|
104 $this->formatInfo = $info;
|
danielebarchiesi@4
|
105 }
|
danielebarchiesi@4
|
106
|
danielebarchiesi@4
|
107 /**
|
danielebarchiesi@4
|
108 * Gets the representation of a resource.
|
danielebarchiesi@4
|
109 */
|
danielebarchiesi@4
|
110 public function viewResource($resourceController, $id) {
|
danielebarchiesi@4
|
111 $values = self::getData($resourceController->wrapper($id));
|
danielebarchiesi@4
|
112 $function = __FUNCTION__;
|
danielebarchiesi@4
|
113 drupal_alter('restws_response', $values, $function, $this->formatName);
|
danielebarchiesi@4
|
114
|
danielebarchiesi@4
|
115 return $this->serialize($values);
|
danielebarchiesi@4
|
116 }
|
danielebarchiesi@4
|
117
|
danielebarchiesi@4
|
118 /**
|
danielebarchiesi@4
|
119 * Creates a new resource.
|
danielebarchiesi@4
|
120 */
|
danielebarchiesi@4
|
121 public function createResource($resourceController, $data) {
|
danielebarchiesi@4
|
122 $values = $this->unserialize($resourceController->propertyInfo(), $data);
|
danielebarchiesi@4
|
123 $id = $resourceController->create($values);
|
danielebarchiesi@4
|
124 $ref = self::getResourceReference($resourceController->resource(), $id);
|
danielebarchiesi@4
|
125 $function = __FUNCTION__;
|
danielebarchiesi@4
|
126 drupal_alter('restws_response', $ref, $function, $this->formatName);
|
danielebarchiesi@4
|
127
|
danielebarchiesi@4
|
128 return $this->serialize($ref);
|
danielebarchiesi@4
|
129 }
|
danielebarchiesi@4
|
130
|
danielebarchiesi@4
|
131 /**
|
danielebarchiesi@4
|
132 * Updates a resource.
|
danielebarchiesi@4
|
133 */
|
danielebarchiesi@4
|
134 public function updateResource($resourceController, $id, $data) {
|
danielebarchiesi@4
|
135 $values = $this->unserialize($resourceController->propertyInfo(), $data);
|
danielebarchiesi@4
|
136 $resourceController->update($id, $values);
|
danielebarchiesi@4
|
137 // Return an empty representation by default.
|
danielebarchiesi@4
|
138 $value = array();
|
danielebarchiesi@4
|
139 $function = __FUNCTION__;
|
danielebarchiesi@4
|
140 drupal_alter('restws_response', $value, $function, $this->formatName);
|
danielebarchiesi@4
|
141
|
danielebarchiesi@4
|
142 return $this->serialize($value);
|
danielebarchiesi@4
|
143 }
|
danielebarchiesi@4
|
144
|
danielebarchiesi@4
|
145 /**
|
danielebarchiesi@4
|
146 * Deletes a resource.
|
danielebarchiesi@4
|
147 */
|
danielebarchiesi@4
|
148 public function deleteResource($resourceController, $id) {
|
danielebarchiesi@4
|
149 $resourceController->delete($id);
|
danielebarchiesi@4
|
150 // Return an empty representation by default.
|
danielebarchiesi@4
|
151 $value = array();
|
danielebarchiesi@4
|
152 $function = __FUNCTION__;
|
danielebarchiesi@4
|
153 drupal_alter('restws_response', $value, $function, $this->formatName);
|
danielebarchiesi@4
|
154
|
danielebarchiesi@4
|
155 return $this->serialize($value);
|
danielebarchiesi@4
|
156 }
|
danielebarchiesi@4
|
157
|
danielebarchiesi@4
|
158 /**
|
danielebarchiesi@4
|
159 * Implements RestWSFormatInterface::queryResource().
|
danielebarchiesi@4
|
160 */
|
danielebarchiesi@4
|
161 public function queryResource($resourceController, $payload) {
|
danielebarchiesi@4
|
162 // Get the parameter from the URL.
|
danielebarchiesi@4
|
163 $parameters = drupal_get_query_parameters();
|
danielebarchiesi@4
|
164
|
danielebarchiesi@4
|
165 $rest_controls = restws_meta_controls();
|
danielebarchiesi@4
|
166 $properties = $resourceController->propertyInfo();
|
danielebarchiesi@4
|
167 $split_parameters = $this->splitParameters($properties, $parameters);
|
danielebarchiesi@4
|
168
|
danielebarchiesi@4
|
169 $values = $this->generateQueryURIs($resourceController, $parameters, $split_parameters['filters']);
|
danielebarchiesi@4
|
170
|
danielebarchiesi@4
|
171 $full = (isset($split_parameters['meta_controls'][$rest_controls['full']])) ? $split_parameters['meta_controls'][$rest_controls['full']] : 1;
|
danielebarchiesi@4
|
172
|
danielebarchiesi@4
|
173 $result = $resourceController->query($split_parameters['filters'], $split_parameters['meta_controls']);
|
danielebarchiesi@4
|
174 if ($full === '0') {
|
danielebarchiesi@4
|
175 foreach ($result as $id) {
|
danielebarchiesi@4
|
176 $values['list'][] = $this->getResourceReference($resourceController->resource(), $id);
|
danielebarchiesi@4
|
177 }
|
danielebarchiesi@4
|
178 }
|
danielebarchiesi@4
|
179 else {
|
danielebarchiesi@4
|
180 foreach ($result as $id) {
|
danielebarchiesi@4
|
181 $values['list'][] = self::getData($resourceController->wrapper($id));
|
danielebarchiesi@4
|
182 }
|
danielebarchiesi@4
|
183 }
|
danielebarchiesi@4
|
184
|
danielebarchiesi@4
|
185 $function = __FUNCTION__;
|
danielebarchiesi@4
|
186 drupal_alter('restws_response', $values, $function, $this->formatName);
|
danielebarchiesi@4
|
187
|
danielebarchiesi@4
|
188 return $this->serialize($values);
|
danielebarchiesi@4
|
189 }
|
danielebarchiesi@4
|
190
|
danielebarchiesi@4
|
191 public function mimeType() {
|
danielebarchiesi@4
|
192 return $this->formatInfo['mime type'];
|
danielebarchiesi@4
|
193 }
|
danielebarchiesi@4
|
194
|
danielebarchiesi@4
|
195 public function getName() {
|
danielebarchiesi@4
|
196 return $this->formatName;
|
danielebarchiesi@4
|
197 }
|
danielebarchiesi@4
|
198
|
danielebarchiesi@4
|
199 /**
|
danielebarchiesi@4
|
200 * Gets a simple PHP array using URI references for some wrapped data.
|
danielebarchiesi@4
|
201 *
|
danielebarchiesi@4
|
202 * This is the counter-part of self::getPropertyValues().
|
danielebarchiesi@4
|
203 */
|
danielebarchiesi@4
|
204 public static function getData($wrapper) {
|
danielebarchiesi@4
|
205 $data = array();
|
danielebarchiesi@4
|
206 $filtered = restws_property_access_filter($wrapper);
|
danielebarchiesi@4
|
207 foreach ($filtered as $name => $property) {
|
danielebarchiesi@4
|
208 try {
|
danielebarchiesi@4
|
209 if ($property instanceof EntityDrupalWrapper) {
|
danielebarchiesi@4
|
210 // For referenced entities only return the URI.
|
danielebarchiesi@4
|
211 if ($id = $property->getIdentifier()) {
|
danielebarchiesi@4
|
212 $data[$name] = self::getResourceReference($property->type(), $id);
|
danielebarchiesi@4
|
213 }
|
danielebarchiesi@4
|
214 }
|
danielebarchiesi@4
|
215 elseif ($property instanceof EntityValueWrapper) {
|
danielebarchiesi@4
|
216 $data[$name] = $property->value();
|
danielebarchiesi@4
|
217 }
|
danielebarchiesi@4
|
218 elseif ($property instanceof EntityListWrapper || $property instanceof EntityStructureWrapper) {
|
danielebarchiesi@4
|
219 $data[$name] = self::getData($property);
|
danielebarchiesi@4
|
220 }
|
danielebarchiesi@4
|
221 }
|
danielebarchiesi@4
|
222 catch (EntityMetadataWrapperException $e) {
|
danielebarchiesi@4
|
223 // A property causes problems - ignore that.
|
danielebarchiesi@4
|
224 }
|
danielebarchiesi@4
|
225 }
|
danielebarchiesi@4
|
226 return $data;
|
danielebarchiesi@4
|
227 }
|
danielebarchiesi@4
|
228
|
danielebarchiesi@4
|
229 public static function getResourceReference($resource, $id) {
|
danielebarchiesi@4
|
230 $return = array(
|
danielebarchiesi@4
|
231 'uri' => restws_resource_uri($resource, $id),
|
danielebarchiesi@4
|
232 'id' => $id,
|
danielebarchiesi@4
|
233 'resource' => $resource,
|
danielebarchiesi@4
|
234 );
|
danielebarchiesi@4
|
235 if (module_exists('uuid') && entity_get_info($resource)) {
|
danielebarchiesi@4
|
236 $ids = entity_get_uuid_by_id($resource, array($id));
|
danielebarchiesi@4
|
237 if ($id = reset($ids)) {
|
danielebarchiesi@4
|
238 $return['uuid'] = $id;
|
danielebarchiesi@4
|
239 }
|
danielebarchiesi@4
|
240 }
|
danielebarchiesi@4
|
241 return $return;
|
danielebarchiesi@4
|
242 }
|
danielebarchiesi@4
|
243
|
danielebarchiesi@4
|
244 /**
|
danielebarchiesi@4
|
245 * Transforms simple-array data values to valid entity property values.
|
danielebarchiesi@4
|
246 *
|
danielebarchiesi@4
|
247 * This is the counter-part of self::getData(), thus it converts resource
|
danielebarchiesi@4
|
248 * references to the required value(s).
|
danielebarchiesi@4
|
249 *
|
danielebarchiesi@4
|
250 * @param array $values
|
danielebarchiesi@4
|
251 * The array representation of the data values.
|
danielebarchiesi@4
|
252 * @param $property_info
|
danielebarchiesi@4
|
253 * The property info array of the entity type for which we are transforming
|
danielebarchiesi@4
|
254 * the values.
|
danielebarchiesi@4
|
255 */
|
danielebarchiesi@4
|
256 protected function getPropertyValues(array &$values, $property_info) {
|
danielebarchiesi@4
|
257 foreach ($values as $name => &$property_value) {
|
danielebarchiesi@4
|
258 if (isset($property_info[$name]) && $info = $property_info[$name]) {
|
danielebarchiesi@4
|
259
|
danielebarchiesi@4
|
260 // Check if there is a resource array and if the property has a type.
|
danielebarchiesi@4
|
261 if (is_array($property_value) && isset($info['type'])) {
|
danielebarchiesi@4
|
262
|
danielebarchiesi@4
|
263 // Check if the field is a list or a single value field.
|
danielebarchiesi@4
|
264 if (entity_property_list_extract_type($info['type'])) {
|
danielebarchiesi@4
|
265 // Check if the list values consist of structure wrappers.
|
danielebarchiesi@4
|
266 if (array_key_exists('property info', $info)) {
|
danielebarchiesi@4
|
267 foreach ($property_value as &$list_values) {
|
danielebarchiesi@4
|
268 $this->getPropertyValues($list_values, $info['property info']);
|
danielebarchiesi@4
|
269 }
|
danielebarchiesi@4
|
270 }
|
danielebarchiesi@4
|
271 else {
|
danielebarchiesi@4
|
272 $list_type = entity_property_list_extract_type($info['type']);
|
danielebarchiesi@4
|
273 foreach ($property_value as &$list_value) {
|
danielebarchiesi@4
|
274 $list_value = $this->getResourceReferenceValue($list_type, $list_value);
|
danielebarchiesi@4
|
275 }
|
danielebarchiesi@4
|
276 }
|
danielebarchiesi@4
|
277 }
|
danielebarchiesi@4
|
278 else {
|
danielebarchiesi@4
|
279 // Check if the property is a structure wrapper.
|
danielebarchiesi@4
|
280 if (array_key_exists('property info', $info)) {
|
danielebarchiesi@4
|
281 $this->getPropertyValues($property_value, $info['property info']);
|
danielebarchiesi@4
|
282 }
|
danielebarchiesi@4
|
283 else {
|
danielebarchiesi@4
|
284 $property_value = $this->getResourceReferenceValue($info['type'], $property_value);
|
danielebarchiesi@4
|
285 }
|
danielebarchiesi@4
|
286 }
|
danielebarchiesi@4
|
287 }
|
danielebarchiesi@4
|
288 }
|
danielebarchiesi@4
|
289 }
|
danielebarchiesi@4
|
290 }
|
danielebarchiesi@4
|
291
|
danielebarchiesi@4
|
292 /**
|
danielebarchiesi@4
|
293 * Gets the resource reference value.
|
danielebarchiesi@4
|
294 *
|
danielebarchiesi@4
|
295 * @param $type
|
danielebarchiesi@4
|
296 * The data type of the reference property.
|
danielebarchiesi@4
|
297 * @param array $reference
|
danielebarchiesi@4
|
298 * The input data specifying the resource reference in one supported way.
|
danielebarchiesi@4
|
299 *
|
danielebarchiesi@4
|
300 * @return mixed
|
danielebarchiesi@4
|
301 * The value to be set for the reference. Usually this is an entity or
|
danielebarchiesi@4
|
302 * resource id, but for generic entity references it's an
|
danielebarchiesi@4
|
303 * EntityDrupalWrapper.
|
danielebarchiesi@4
|
304 *
|
danielebarchiesi@4
|
305 * @see RestWSBaseFormat::getResourceReference()
|
danielebarchiesi@4
|
306 */
|
danielebarchiesi@4
|
307 protected function getResourceReferenceValue($type, array $reference) {
|
danielebarchiesi@4
|
308
|
danielebarchiesi@4
|
309 if (isset($reference['id']) && $type != 'entity') {
|
danielebarchiesi@4
|
310 return $reference['id'];
|
danielebarchiesi@4
|
311 }
|
danielebarchiesi@4
|
312 // Handle setting generic entity references, i.e. of type entity.
|
danielebarchiesi@4
|
313 elseif ($type == 'entity' && isset($reference['id']) && isset($reference['resource'])) {
|
danielebarchiesi@4
|
314 if (!entity_get_info($reference['resource'])) {
|
danielebarchiesi@4
|
315 throw new RestWSException('Invalid resource for entity reference given.', 406);
|
danielebarchiesi@4
|
316 }
|
danielebarchiesi@4
|
317 return entity_metadata_wrapper($reference['resource'], $reference['id']);
|
danielebarchiesi@4
|
318 }
|
danielebarchiesi@4
|
319 elseif (isset($reference['uri'])) {
|
danielebarchiesi@4
|
320 // @todo: Implement setting references by URI by parsing resource/id from
|
danielebarchiesi@4
|
321 // the URI.
|
danielebarchiesi@4
|
322 }
|
danielebarchiesi@4
|
323 elseif (isset($reference['uuid']) && module_exists('uuid') && $type != 'entity') {
|
danielebarchiesi@4
|
324 $ids = entity_get_id_by_uuid($type, array($reference['uuid']));
|
danielebarchiesi@4
|
325 if (!$ids) {
|
danielebarchiesi@4
|
326 throw new RestWSException('Invalid UUID for resource reference given.', 406);
|
danielebarchiesi@4
|
327 }
|
danielebarchiesi@4
|
328 return reset($ids);
|
danielebarchiesi@4
|
329 }
|
danielebarchiesi@4
|
330
|
danielebarchiesi@4
|
331 throw new RestWSException('Invalid value for resource reference given.', 406);
|
danielebarchiesi@4
|
332 }
|
danielebarchiesi@4
|
333
|
danielebarchiesi@4
|
334 /**
|
danielebarchiesi@4
|
335 * Splits a query parameter into two sub arrays containing the filters and
|
danielebarchiesi@4
|
336 * meta controls.
|
danielebarchiesi@4
|
337 *
|
danielebarchiesi@4
|
338 * @param array $properties
|
danielebarchiesi@4
|
339 * An array containing the properties of the resource.
|
danielebarchiesi@4
|
340 *
|
danielebarchiesi@4
|
341 * @param array $parameters
|
danielebarchiesi@4
|
342 * An array which contains filters and meta controls.
|
danielebarchiesi@4
|
343 *
|
danielebarchiesi@4
|
344 * @return array
|
danielebarchiesi@4
|
345 * An array containing two sub arrays, one for filters and one for meta
|
danielebarchiesi@4
|
346 * controls with corresponding keys.
|
danielebarchiesi@4
|
347 *
|
danielebarchiesi@4
|
348 * @throws RestWSException
|
danielebarchiesi@4
|
349 * If a filter isn't valid, the function will throw a RestWSException with
|
danielebarchiesi@4
|
350 * the 412 HTTP status code.
|
danielebarchiesi@4
|
351 */
|
danielebarchiesi@4
|
352 protected function splitParameters($properties, array $parameters) {
|
danielebarchiesi@4
|
353 $meta_controls = array();
|
danielebarchiesi@4
|
354 $rest_controls = restws_meta_controls();
|
danielebarchiesi@4
|
355 foreach ($parameters as $control_name => $property) {
|
danielebarchiesi@4
|
356 if (isset($rest_controls[$control_name])) {
|
danielebarchiesi@4
|
357 $meta_controls[$control_name] = $property;
|
danielebarchiesi@4
|
358 unset($parameters[$control_name]);
|
danielebarchiesi@4
|
359 }
|
danielebarchiesi@4
|
360 }
|
danielebarchiesi@4
|
361
|
danielebarchiesi@4
|
362 $filters = array();
|
danielebarchiesi@4
|
363 foreach ($parameters as $parameter => $value) {
|
danielebarchiesi@4
|
364 // Check if the property is prefixed.
|
danielebarchiesi@4
|
365 if (substr($parameter, 0, 9) == 'property_') {
|
danielebarchiesi@4
|
366 $parameter = substr($parameter, 9, strlen($parameter) - 9);
|
danielebarchiesi@4
|
367 }
|
danielebarchiesi@4
|
368
|
danielebarchiesi@4
|
369 // If the parameter doesn't exist, we can not filter for and need to
|
danielebarchiesi@4
|
370 // notify the client about it.
|
danielebarchiesi@4
|
371 if (!isset($properties[$parameter])) {
|
danielebarchiesi@4
|
372 throw new RestWSException('Not a valid filter: ' . $parameter, 412);
|
danielebarchiesi@4
|
373 }
|
danielebarchiesi@4
|
374 $filters[$parameter] = $value;
|
danielebarchiesi@4
|
375 }
|
danielebarchiesi@4
|
376 return array('meta_controls' => $meta_controls, 'filters' => $filters);
|
danielebarchiesi@4
|
377 }
|
danielebarchiesi@4
|
378
|
danielebarchiesi@4
|
379 /**
|
danielebarchiesi@4
|
380 * Generates all navigation links for querying.
|
danielebarchiesi@4
|
381 *
|
danielebarchiesi@4
|
382 * @param RestWSResourceControllerInterface $resourceController
|
danielebarchiesi@4
|
383 * The controller used to query the resource.
|
danielebarchiesi@4
|
384 *
|
danielebarchiesi@4
|
385 * @param array $parameters
|
danielebarchiesi@4
|
386 * The HTTP GET parameters for the query.
|
danielebarchiesi@4
|
387 *
|
danielebarchiesi@4
|
388 * @param array $filters
|
danielebarchiesi@4
|
389 * The filters for the query.
|
danielebarchiesi@4
|
390 *
|
danielebarchiesi@4
|
391 * @return array
|
danielebarchiesi@4
|
392 * An array containing all navigation links.
|
danielebarchiesi@4
|
393 *
|
danielebarchiesi@4
|
394 * @throws RestWSException
|
danielebarchiesi@4
|
395 * If the page is out of range the function will throw a new RestWSException
|
danielebarchiesi@4
|
396 * with HTTP status code 404.
|
danielebarchiesi@4
|
397 */
|
danielebarchiesi@4
|
398 protected function generateQueryURIs(RestWSResourceControllerInterface $resourceController, array $parameters, array $filters) {
|
danielebarchiesi@4
|
399 $rest_controls = restws_meta_controls();
|
danielebarchiesi@4
|
400
|
danielebarchiesi@4
|
401 $count = $resourceController->count($filters);
|
danielebarchiesi@4
|
402 $limit = isset($parameters[$rest_controls['limit']]) ? $parameters[$rest_controls['limit']] : NULL;
|
danielebarchiesi@4
|
403 $limit = $resourceController->limit($limit);
|
danielebarchiesi@4
|
404 $page = isset($parameters[$rest_controls['page']]) ? $parameters[$rest_controls['page']] : 0;
|
danielebarchiesi@4
|
405
|
danielebarchiesi@4
|
406 $last = ceil($count / $limit) - 1;
|
danielebarchiesi@4
|
407
|
danielebarchiesi@4
|
408 if ($page > $last || $page < 0) {
|
danielebarchiesi@4
|
409 throw new RestWSException('Page doesn\'t exist.', 404);
|
danielebarchiesi@4
|
410 }
|
danielebarchiesi@4
|
411
|
danielebarchiesi@4
|
412 $uris = array();
|
danielebarchiesi@4
|
413 $options = array(
|
danielebarchiesi@4
|
414 'query' => &$parameters,
|
danielebarchiesi@4
|
415 );
|
danielebarchiesi@4
|
416
|
danielebarchiesi@4
|
417 $uris['self'] = restws_resource_uri($resourceController->resource(), null, $options);
|
danielebarchiesi@4
|
418 $parameters['page'] = 0;
|
danielebarchiesi@4
|
419 $uris['first'] = restws_resource_uri($resourceController->resource(), null, $options);
|
danielebarchiesi@4
|
420 $parameters['page'] = $last;
|
danielebarchiesi@4
|
421 $uris['last'] = restws_resource_uri($resourceController->resource(), null, $options);
|
danielebarchiesi@4
|
422
|
danielebarchiesi@4
|
423
|
danielebarchiesi@4
|
424 if ($page != 0) {
|
danielebarchiesi@4
|
425 $parameters['page'] = $page - 1;
|
danielebarchiesi@4
|
426 $uris['prev'] = restws_resource_uri($resourceController->resource(), null, $options);
|
danielebarchiesi@4
|
427 }
|
danielebarchiesi@4
|
428
|
danielebarchiesi@4
|
429 if ($page != $last) {
|
danielebarchiesi@4
|
430 $parameters['page'] = $page + 1;
|
danielebarchiesi@4
|
431 $uris['next'] = restws_resource_uri($resourceController->resource(), null, $options);
|
danielebarchiesi@4
|
432 }
|
danielebarchiesi@4
|
433
|
danielebarchiesi@4
|
434 return $uris;
|
danielebarchiesi@4
|
435 }
|
danielebarchiesi@4
|
436 }
|
danielebarchiesi@4
|
437
|
danielebarchiesi@4
|
438 /**
|
danielebarchiesi@4
|
439 * Filters out properties where view access is not allowed for the current user.
|
danielebarchiesi@4
|
440 *
|
danielebarchiesi@4
|
441 * @param EntityMetadataWrapper $wrapper
|
danielebarchiesi@4
|
442 * EntityMetadataWrapper that should be checked.
|
danielebarchiesi@4
|
443 *
|
danielebarchiesi@4
|
444 * @return
|
danielebarchiesi@4
|
445 * An array of properties where access is allowed, keyed by their property
|
danielebarchiesi@4
|
446 * name.
|
danielebarchiesi@4
|
447 */
|
danielebarchiesi@4
|
448 function restws_property_access_filter($wrapper) {
|
danielebarchiesi@4
|
449 $filtered = array();
|
danielebarchiesi@4
|
450 foreach ($wrapper as $name => $property) {
|
danielebarchiesi@4
|
451 if ($property->access('view')) {
|
danielebarchiesi@4
|
452 $filtered[$name] = $property;
|
danielebarchiesi@4
|
453 }
|
danielebarchiesi@4
|
454 }
|
danielebarchiesi@4
|
455 return $filtered;
|
danielebarchiesi@4
|
456 }
|
danielebarchiesi@4
|
457
|
danielebarchiesi@4
|
458 /**
|
danielebarchiesi@4
|
459 * A formatter to format json.
|
danielebarchiesi@4
|
460 */
|
danielebarchiesi@4
|
461 class RestWSFormatJSON extends RestWSBaseFormat {
|
danielebarchiesi@4
|
462
|
danielebarchiesi@4
|
463 public function serialize($values) {
|
danielebarchiesi@4
|
464 return drupal_json_encode($values);
|
danielebarchiesi@4
|
465 }
|
danielebarchiesi@4
|
466
|
danielebarchiesi@4
|
467 public function unserialize($properties, $data) {
|
danielebarchiesi@4
|
468 $values = drupal_json_decode($data);
|
danielebarchiesi@4
|
469 $this->getPropertyValues($values, $properties);
|
danielebarchiesi@4
|
470 return $values;
|
danielebarchiesi@4
|
471 }
|
danielebarchiesi@4
|
472 }
|
danielebarchiesi@4
|
473
|
danielebarchiesi@4
|
474 /**
|
danielebarchiesi@4
|
475 * A formatter for XML.
|
danielebarchiesi@4
|
476 */
|
danielebarchiesi@4
|
477 class RestWSFormatXML extends RestWSBaseFormat {
|
danielebarchiesi@4
|
478
|
danielebarchiesi@4
|
479 /**
|
danielebarchiesi@4
|
480 * Gets the representation of a resource.
|
danielebarchiesi@4
|
481 */
|
danielebarchiesi@4
|
482 public function viewResource($resourceController, $id) {
|
danielebarchiesi@4
|
483 $xml = new DOMDocument('1.0', 'utf-8');
|
danielebarchiesi@4
|
484 $element = $xml->createElement($resourceController->resource());
|
danielebarchiesi@4
|
485 self::addToXML($xml, $element, $resourceController->wrapper($id));
|
danielebarchiesi@4
|
486 $xml->appendChild($element);
|
danielebarchiesi@4
|
487
|
danielebarchiesi@4
|
488 $function = __FUNCTION__;
|
danielebarchiesi@4
|
489 drupal_alter('restws_response', $xml, $function, $this->formatName);
|
danielebarchiesi@4
|
490
|
danielebarchiesi@4
|
491 return $xml->saveXML();
|
danielebarchiesi@4
|
492 }
|
danielebarchiesi@4
|
493
|
danielebarchiesi@4
|
494 /**
|
danielebarchiesi@4
|
495 * Creates a new resource.
|
danielebarchiesi@4
|
496 */
|
danielebarchiesi@4
|
497 public function createResource($resourceController, $data) {
|
danielebarchiesi@4
|
498 $values = $this->unserialize($resourceController->propertyInfo(), $data);
|
danielebarchiesi@4
|
499 $id = $resourceController->create($values);
|
danielebarchiesi@4
|
500
|
danielebarchiesi@4
|
501 $xml = new DOMDocument('1.0', 'utf-8');
|
danielebarchiesi@4
|
502 $element = $xml->createElement('uri');
|
danielebarchiesi@4
|
503 self::setXMLReference($element, $resourceController->resource(), $id);
|
danielebarchiesi@4
|
504 $xml->appendChild($element);
|
danielebarchiesi@4
|
505
|
danielebarchiesi@4
|
506 $function = __FUNCTION__;
|
danielebarchiesi@4
|
507 drupal_alter('restws_response', $xml, $function, $this->formatName);
|
danielebarchiesi@4
|
508
|
danielebarchiesi@4
|
509 return $xml->saveXML();
|
danielebarchiesi@4
|
510 }
|
danielebarchiesi@4
|
511
|
danielebarchiesi@4
|
512 /**
|
danielebarchiesi@4
|
513 * Overrides RestWSBaseFormat::queryResource().
|
danielebarchiesi@4
|
514 */
|
danielebarchiesi@4
|
515 public function queryResource($resourceController, $payload) {
|
danielebarchiesi@4
|
516 $xml = new DOMDocument('1.0', 'utf-8');
|
danielebarchiesi@4
|
517 $element = $xml->createElement('list');
|
danielebarchiesi@4
|
518
|
danielebarchiesi@4
|
519 $rest_controls = restws_meta_controls();
|
danielebarchiesi@4
|
520 $parameters = drupal_get_query_parameters();
|
danielebarchiesi@4
|
521 $properties = $resourceController->propertyInfo();
|
danielebarchiesi@4
|
522 $split_parameters = $this->splitParameters($properties, $parameters);
|
danielebarchiesi@4
|
523
|
danielebarchiesi@4
|
524 $links = $this->generateQueryURIs($resourceController, $parameters, $split_parameters['filters']);
|
danielebarchiesi@4
|
525
|
danielebarchiesi@4
|
526 foreach ($links as $rel => $link) {
|
danielebarchiesi@4
|
527 $item = $xml->createElement('link');
|
danielebarchiesi@4
|
528 $item->setAttribute('rel', $rel);
|
danielebarchiesi@4
|
529 $item->setAttribute('href', $link);
|
danielebarchiesi@4
|
530 $element->appendChild($item);
|
danielebarchiesi@4
|
531 }
|
danielebarchiesi@4
|
532
|
danielebarchiesi@4
|
533 $full = (isset($split_parameters['meta_controls'][$rest_controls['full']])) ? $split_parameters['meta_controls'][$rest_controls['full']] : 1;
|
danielebarchiesi@4
|
534
|
danielebarchiesi@4
|
535 $result = $resourceController->query($split_parameters['filters'], $split_parameters['meta_controls']);
|
danielebarchiesi@4
|
536
|
danielebarchiesi@4
|
537 if ($full === '0') {
|
danielebarchiesi@4
|
538 foreach ($result as $id) {
|
danielebarchiesi@4
|
539 $item = $xml->createElement($resourceController->resource());
|
danielebarchiesi@4
|
540 self::setXMLReference($item, $resourceController->resource(), $id);
|
danielebarchiesi@4
|
541 $element->appendChild($item);
|
danielebarchiesi@4
|
542 }
|
danielebarchiesi@4
|
543 }
|
danielebarchiesi@4
|
544 else {
|
danielebarchiesi@4
|
545 foreach ($result as $id) {
|
danielebarchiesi@4
|
546 $item = $xml->createElement($resourceController->resource());
|
danielebarchiesi@4
|
547 self::addToXML($xml, $item, $resourceController->wrapper($id));
|
danielebarchiesi@4
|
548 $element->appendChild($item);
|
danielebarchiesi@4
|
549 }
|
danielebarchiesi@4
|
550 }
|
danielebarchiesi@4
|
551
|
danielebarchiesi@4
|
552 $xml->appendChild($element);
|
danielebarchiesi@4
|
553
|
danielebarchiesi@4
|
554 $function = __FUNCTION__;
|
danielebarchiesi@4
|
555 drupal_alter('restws_response', $xml, $function, $this->formatName);
|
danielebarchiesi@4
|
556
|
danielebarchiesi@4
|
557 return $xml->saveXML();
|
danielebarchiesi@4
|
558 }
|
danielebarchiesi@4
|
559
|
danielebarchiesi@4
|
560 public function serialize($data) {
|
danielebarchiesi@4
|
561 // Return an empty XML document.
|
danielebarchiesi@4
|
562 $xml = new DOMDocument('1.0', 'utf-8');
|
danielebarchiesi@4
|
563 return $xml->saveXML();
|
danielebarchiesi@4
|
564 }
|
danielebarchiesi@4
|
565
|
danielebarchiesi@4
|
566 public function unserialize($properties, $data) {
|
danielebarchiesi@4
|
567 $xml = simplexml_load_string($data);
|
danielebarchiesi@4
|
568 return $this->xmlToArray($properties, $xml);
|
danielebarchiesi@4
|
569 }
|
danielebarchiesi@4
|
570
|
danielebarchiesi@4
|
571 /**
|
danielebarchiesi@4
|
572 * Turns the xml structure into an array of values.
|
danielebarchiesi@4
|
573 */
|
danielebarchiesi@4
|
574 public function xmlToArray($properties, SimpleXMLElement $xml, $listItemType = NULL) {
|
danielebarchiesi@4
|
575 foreach ($xml->children() as $name => $element) {
|
danielebarchiesi@4
|
576 // Check if we are processing an entity, an item from a list or a list.
|
danielebarchiesi@4
|
577 if ((isset($properties[$name]['type']) && (entity_property_list_extract_type($properties[$name]['type']) || entity_get_info($properties[$name]['type']))) || isset($listItemType)) {
|
danielebarchiesi@4
|
578 // If we are processing a list, then set the type of the list and save
|
danielebarchiesi@4
|
579 // the results into a a numeric array.
|
danielebarchiesi@4
|
580 if (isset($listItemType)) {
|
danielebarchiesi@4
|
581 $type = $listItemType;
|
danielebarchiesi@4
|
582 $result_pointer = &$result[];
|
danielebarchiesi@4
|
583 }
|
danielebarchiesi@4
|
584 else {
|
danielebarchiesi@4
|
585 $type = $properties[$name]['type'];
|
danielebarchiesi@4
|
586 $result_pointer = &$result[$name];
|
danielebarchiesi@4
|
587 }
|
danielebarchiesi@4
|
588
|
danielebarchiesi@4
|
589 // Check if the type is a list.
|
danielebarchiesi@4
|
590 if (entity_property_list_extract_type($type)) {
|
danielebarchiesi@4
|
591 $result_pointer = $this->xmlToArray($properties, $element, entity_property_list_extract_type($type));
|
danielebarchiesi@4
|
592 }
|
danielebarchiesi@4
|
593 else {
|
danielebarchiesi@4
|
594 $attributes = $element->attributes();
|
danielebarchiesi@4
|
595 $values['id'] = (string)$attributes['id'];
|
danielebarchiesi@4
|
596 $values['resource'] = (string)$attributes['resource'];
|
danielebarchiesi@4
|
597 $values['uri'] = $this->xmlToArray($properties, $element);
|
danielebarchiesi@4
|
598 $id = $this->getResourceReferenceValue($type, $values);
|
danielebarchiesi@4
|
599 // If an id could be extracted, then a resource array was send.
|
danielebarchiesi@4
|
600 if ($id !== FALSE) {
|
danielebarchiesi@4
|
601 $result_pointer = $id;
|
danielebarchiesi@4
|
602 }
|
danielebarchiesi@4
|
603 else {
|
danielebarchiesi@4
|
604 // If no ID could be extracted, then save the inner text content of
|
danielebarchiesi@4
|
605 // the node, which is saved in the $values['uri'].
|
danielebarchiesi@4
|
606 $result_pointer = $values['uri'];
|
danielebarchiesi@4
|
607 }
|
danielebarchiesi@4
|
608 }
|
danielebarchiesi@4
|
609 }
|
danielebarchiesi@4
|
610 else {
|
danielebarchiesi@4
|
611 $result[$name] = $this->xmlToArray($properties, $element);
|
danielebarchiesi@4
|
612 }
|
danielebarchiesi@4
|
613 foreach ($xml->attributes() as $attribute_name => $attribute_value) {
|
danielebarchiesi@4
|
614 $result[$attribute_name] = $attribute_value;
|
danielebarchiesi@4
|
615 }
|
danielebarchiesi@4
|
616 }
|
danielebarchiesi@4
|
617 if (!isset($result)) {
|
danielebarchiesi@4
|
618 $result = ($string = (string) $xml) ? $string : NULL;
|
danielebarchiesi@4
|
619 }
|
danielebarchiesi@4
|
620 return $result;
|
danielebarchiesi@4
|
621 }
|
danielebarchiesi@4
|
622
|
danielebarchiesi@4
|
623 /**
|
danielebarchiesi@4
|
624 * Adds the data of the given wrapper to the given XML element.
|
danielebarchiesi@4
|
625 */
|
danielebarchiesi@4
|
626 public static function addToXML(DOMDocument $doc, DOMNode $parent, $wrapper) {
|
danielebarchiesi@4
|
627 $filtered = restws_property_access_filter($wrapper);
|
danielebarchiesi@4
|
628 foreach ($filtered as $name => $property) {
|
danielebarchiesi@4
|
629 try {
|
danielebarchiesi@4
|
630 if ($property instanceof EntityDrupalWrapper) {
|
danielebarchiesi@4
|
631 // For referenced entities only return the URI.
|
danielebarchiesi@4
|
632 if ($id = $property->getIdentifier()) {
|
danielebarchiesi@4
|
633 $element = $doc->createElement(is_numeric($name) ? 'item' : $name);
|
danielebarchiesi@4
|
634 $parent->appendChild($element);
|
danielebarchiesi@4
|
635 self::setXMLReference($element, $property->type(), $id);
|
danielebarchiesi@4
|
636 }
|
danielebarchiesi@4
|
637 }
|
danielebarchiesi@4
|
638 elseif ($property instanceof EntityValueWrapper) {
|
danielebarchiesi@4
|
639 // Only primitive data types are allowed here. There might be complex
|
danielebarchiesi@4
|
640 // arrays/objects in EntityValueWrapper if no property information is
|
danielebarchiesi@4
|
641 // provided (example: the "data" property of commerce_price fields.
|
danielebarchiesi@4
|
642 if (is_scalar($property->value())) {
|
danielebarchiesi@4
|
643 $escaped = $doc->createTextNode($property->value());
|
danielebarchiesi@4
|
644 $element = $doc->createElement(is_numeric($name) ? 'item' : $name);
|
danielebarchiesi@4
|
645 $element->appendChild($escaped);
|
danielebarchiesi@4
|
646 $parent->appendChild($element);
|
danielebarchiesi@4
|
647 }
|
danielebarchiesi@4
|
648 }
|
danielebarchiesi@4
|
649 elseif ($property instanceof EntityListWrapper || $property instanceof EntityStructureWrapper) {
|
danielebarchiesi@4
|
650 $element = $doc->createElement(is_numeric($name) ? 'item' : $name);
|
danielebarchiesi@4
|
651 $parent->appendChild($element);
|
danielebarchiesi@4
|
652 self::addToXML($doc, $element, $property);
|
danielebarchiesi@4
|
653 }
|
danielebarchiesi@4
|
654 }
|
danielebarchiesi@4
|
655 catch (EntityMetadataWrapperException $e) {
|
danielebarchiesi@4
|
656 // A property causes problems - ignore that.
|
danielebarchiesi@4
|
657 }
|
danielebarchiesi@4
|
658 }
|
danielebarchiesi@4
|
659 }
|
danielebarchiesi@4
|
660
|
danielebarchiesi@4
|
661 public static function setXMLReference(DOMElement $node, $resource, $id) {
|
danielebarchiesi@4
|
662 $node->nodeValue = restws_resource_uri($resource, $id);
|
danielebarchiesi@4
|
663 $node->setAttribute('resource', $resource);
|
danielebarchiesi@4
|
664 $node->setAttribute('id', $id);
|
danielebarchiesi@4
|
665 }
|
danielebarchiesi@4
|
666 }
|
danielebarchiesi@4
|
667
|
danielebarchiesi@4
|
668 /**
|
danielebarchiesi@4
|
669 * A simple formatter for RDF. Requires the RDF module for the mapping.
|
danielebarchiesi@4
|
670 */
|
danielebarchiesi@4
|
671 class RestWSFormatRDF extends RestWSBaseFormat {
|
danielebarchiesi@4
|
672
|
danielebarchiesi@4
|
673 protected $namespaces;
|
danielebarchiesi@4
|
674
|
danielebarchiesi@4
|
675 public function __construct($name, $info) {
|
danielebarchiesi@4
|
676 parent::__construct($name, $info);
|
danielebarchiesi@4
|
677 $this->namespaces = rdf_get_namespaces();
|
danielebarchiesi@4
|
678 $this->namespaces['rdf'] = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
|
danielebarchiesi@4
|
679 }
|
danielebarchiesi@4
|
680
|
danielebarchiesi@4
|
681 /**
|
danielebarchiesi@4
|
682 * Gets the representation of a resource.
|
danielebarchiesi@4
|
683 */
|
danielebarchiesi@4
|
684 public function viewResource($resourceController, $id) {
|
danielebarchiesi@4
|
685 $xml = new DOMDocument('1.0', 'utf-8');
|
danielebarchiesi@4
|
686 $rdf_element = $xml->createElementNS($this->namespaces['rdf'], 'rdf:RDF');
|
danielebarchiesi@4
|
687 $xml->appendChild($rdf_element);
|
danielebarchiesi@4
|
688
|
danielebarchiesi@4
|
689 $element = $xml->createElementNS($this->namespaces['rdf'], 'rdf:Description');
|
danielebarchiesi@4
|
690 $element->setAttributeNS($this->namespaces['rdf'], 'rdf:about', restws_resource_uri($resourceController->resource(), $id));
|
danielebarchiesi@4
|
691
|
danielebarchiesi@4
|
692 // Add the RDF type of the resource if there is a mapping.
|
danielebarchiesi@4
|
693 $entity = $resourceController->read($id);
|
danielebarchiesi@4
|
694 if (!empty($entity->rdf_mapping['rdftype'])) {
|
danielebarchiesi@4
|
695 foreach ($entity->rdf_mapping['rdftype'] as $rdf_type) {
|
danielebarchiesi@4
|
696 $type_element = $xml->createElementNS($this->namespaces['rdf'], 'rdf:type');
|
danielebarchiesi@4
|
697 list($ns, $name) = explode(':', $rdf_type);
|
danielebarchiesi@4
|
698 $type_element->setAttributeNS($this->namespaces['rdf'], 'rdf:resource', $this->namespaces[$ns] . $name);
|
danielebarchiesi@4
|
699 $element->appendChild($type_element);
|
danielebarchiesi@4
|
700 }
|
danielebarchiesi@4
|
701 }
|
danielebarchiesi@4
|
702
|
danielebarchiesi@4
|
703 $this->addToXML($xml, $element, $resourceController->wrapper($id));
|
danielebarchiesi@4
|
704 $rdf_element->appendChild($element);
|
danielebarchiesi@4
|
705
|
danielebarchiesi@4
|
706 $function = __FUNCTION__;
|
danielebarchiesi@4
|
707 drupal_alter('restws_response', $xml, $function, $this->formatName);
|
danielebarchiesi@4
|
708
|
danielebarchiesi@4
|
709 return $xml->saveXML();
|
danielebarchiesi@4
|
710 }
|
danielebarchiesi@4
|
711
|
danielebarchiesi@4
|
712 public function createResource($resourceController, $data) {
|
danielebarchiesi@4
|
713 throw new RestWSException('Not implemented', 501);
|
danielebarchiesi@4
|
714 }
|
danielebarchiesi@4
|
715
|
danielebarchiesi@4
|
716 public function updateResource($resourceController, $id, $data) {
|
danielebarchiesi@4
|
717 throw new RestWSException('Not implemented', 501);
|
danielebarchiesi@4
|
718 }
|
danielebarchiesi@4
|
719
|
danielebarchiesi@4
|
720 public function queryResource($resourceController, $parameters) {
|
danielebarchiesi@4
|
721 throw new RestWSException('Not implemented', 501);
|
danielebarchiesi@4
|
722 }
|
danielebarchiesi@4
|
723
|
danielebarchiesi@4
|
724 /**
|
danielebarchiesi@4
|
725 * Adds the data of the given wrapper to the given XML element.
|
danielebarchiesi@4
|
726 */
|
danielebarchiesi@4
|
727 public function addToXML(DOMDocument $doc, DOMNode $parent, $wrapper) {
|
danielebarchiesi@4
|
728 $filtered = restws_property_access_filter($wrapper);
|
danielebarchiesi@4
|
729 foreach ($filtered as $name => $property) {
|
danielebarchiesi@4
|
730 try {
|
danielebarchiesi@4
|
731 if ($property instanceof EntityDrupalWrapper) {
|
danielebarchiesi@4
|
732 // For referenced entities only return the URI.
|
danielebarchiesi@4
|
733 if ($id = $property->getIdentifier()) {
|
danielebarchiesi@4
|
734 $element = $this->addRdfElement($doc, $wrapper, $name);
|
danielebarchiesi@4
|
735 $parent->appendChild($element);
|
danielebarchiesi@4
|
736 $this->addReference($doc, $element, $property->type(), $id);
|
danielebarchiesi@4
|
737 }
|
danielebarchiesi@4
|
738 }
|
danielebarchiesi@4
|
739 elseif ($property instanceof EntityValueWrapper) {
|
danielebarchiesi@4
|
740 $element = $this->addRdfElement($doc, $wrapper, $name);
|
danielebarchiesi@4
|
741 $parent->appendChild($element);
|
danielebarchiesi@4
|
742 $element->nodeValue = $property->value();
|
danielebarchiesi@4
|
743 }
|
danielebarchiesi@4
|
744 elseif ($property instanceof EntityListWrapper || $property instanceof EntityStructureWrapper) {
|
danielebarchiesi@4
|
745 $element = $this->addRdfElement($doc, $wrapper, $name);
|
danielebarchiesi@4
|
746 $parent->appendChild($element);
|
danielebarchiesi@4
|
747 $node = $doc->createElementNS($this->namespaces['rdf'], 'rdf:Description');
|
danielebarchiesi@4
|
748 $element->appendChild($node);
|
danielebarchiesi@4
|
749 $this->addToXML($doc, $node, $property);
|
danielebarchiesi@4
|
750 }
|
danielebarchiesi@4
|
751 }
|
danielebarchiesi@4
|
752 catch (EntityMetadataWrapperException $e) {
|
danielebarchiesi@4
|
753 // A property causes problems - ignore that.
|
danielebarchiesi@4
|
754 }
|
danielebarchiesi@4
|
755 }
|
danielebarchiesi@4
|
756 }
|
danielebarchiesi@4
|
757
|
danielebarchiesi@4
|
758 public function addReference(DomDocument $doc, DOMElement $node, $resource, $id) {
|
danielebarchiesi@4
|
759 $element = $doc->createElementNS($this->namespaces['rdf'], 'rdf:Description');
|
danielebarchiesi@4
|
760 $element->setAttributeNS($this->namespaces['rdf'], 'rdf:about', restws_resource_uri($resource, $id));
|
danielebarchiesi@4
|
761 $node->appendChild($element);
|
danielebarchiesi@4
|
762 }
|
danielebarchiesi@4
|
763
|
danielebarchiesi@4
|
764 /**
|
danielebarchiesi@4
|
765 * Adds an RDF element for the given property of the wrapper using the RDF
|
danielebarchiesi@4
|
766 * mapping.
|
danielebarchiesi@4
|
767 */
|
danielebarchiesi@4
|
768 public function addRdfElement(DOMDOcument $doc, EntityMetadataWrapper $wrapper, $name) {
|
danielebarchiesi@4
|
769 if ($wrapper instanceof EntityDrupalWrapper) {
|
danielebarchiesi@4
|
770 $entity = $wrapper->value();
|
danielebarchiesi@4
|
771 if (!empty($entity->rdf_mapping[$name])) {
|
danielebarchiesi@4
|
772 // Just make use of the first predicate for now.
|
danielebarchiesi@4
|
773 $predicate = reset($entity->rdf_mapping[$name]['predicates']);
|
danielebarchiesi@4
|
774 list($ns, $qname) = explode(':', $predicate);
|
danielebarchiesi@4
|
775 $element = $doc->createElementNS($this->namespaces[$ns], $predicate);
|
danielebarchiesi@4
|
776
|
danielebarchiesi@4
|
777 if (!empty($entity->rdf_mapping[$name]['datatype'])) {
|
danielebarchiesi@4
|
778 $element->setAttributeNS($this->namespaces['rdf'], 'rdf:datatype', $entity->rdf_mapping[$name]['datatype']);
|
danielebarchiesi@4
|
779 }
|
danielebarchiesi@4
|
780 }
|
danielebarchiesi@4
|
781 }
|
danielebarchiesi@4
|
782 if (!isset($element)) {
|
danielebarchiesi@4
|
783 // For other elements just use the site URL as namespace.
|
danielebarchiesi@4
|
784 $element = $doc->createElementNS(url('', array('absolute' => TRUE)), 'site:' . (is_numeric($name) ? 'item' : $name));
|
danielebarchiesi@4
|
785 }
|
danielebarchiesi@4
|
786 return $element;
|
danielebarchiesi@4
|
787 }
|
danielebarchiesi@4
|
788 }
|