Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php
namespace Drupal\Tests\hal\Functional\EntityResource;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Url;
use GuzzleHttp\RequestOptions;
/**
* Trait for EntityResourceTestBase subclasses testing formats using HAL.
*/
trait HalEntityNormalizationTrait {
/**
* Applies the HAL entity field normalization to an entity normalization.
*
* The HAL normalization:
* - adds a 'lang' attribute to every translatable field
* - omits reference fields, since references are stored in _links & _embedded
* - omits empty fields (fields without value)
*
* @param array $normalization
* An entity normalization.
*
* @return array
* The updated entity normalization.
*/
protected function applyHalFieldNormalization(array $normalization) {
if (!$this->entity instanceof FieldableEntityInterface) {
throw new \LogicException('This trait should only be used for fieldable entity types.');
}
// In the HAL normalization, all translatable fields get a 'lang' attribute.
$translatable_non_reference_fields = array_keys(array_filter($this->entity->getTranslatableFields(), function (FieldItemListInterface $field) {
return !$field instanceof EntityReferenceFieldItemListInterface;
}));
foreach ($translatable_non_reference_fields as $field_name) {
if (isset($normalization[$field_name])) {
$normalization[$field_name][0]['lang'] = 'en';
}
}
// In the HAL normalization, reference fields are omitted, except for the
// bundle field.
$bundle_key = $this->entity->getEntityType()->getKey('bundle');
$reference_fields = array_keys(array_filter($this->entity->getFields(), function (FieldItemListInterface $field) use ($bundle_key) {
return $field instanceof EntityReferenceFieldItemListInterface && $field->getName() !== $bundle_key;
}));
foreach ($reference_fields as $field_name) {
unset($normalization[$field_name]);
}
// In the HAL normalization, the bundle field omits the 'target_type' and
// 'target_uuid' properties, because it's encoded in the '_links' section.
if ($bundle_key) {
unset($normalization[$bundle_key][0]['target_type']);
unset($normalization[$bundle_key][0]['target_uuid']);
}
// In the HAL normalization, empty fields are omitted.
$empty_fields = array_keys(array_filter($this->entity->getFields(), function (FieldItemListInterface $field) {
return $field->isEmpty();
}));
foreach ($empty_fields as $field_name) {
unset($normalization[$field_name]);
}
return $normalization;
}
/**
* {@inheritdoc}
*/
protected function removeFieldsFromNormalization(array $normalization, $field_names) {
$normalization = parent::removeFieldsFromNormalization($normalization, $field_names);
foreach ($field_names as $field_name) {
$relation_url = Url::fromUri('base:rest/relation/' . static::$entityTypeId . '/' . $this->entity->bundle() . '/' . $field_name)
->setAbsolute(TRUE)
->toString();
$normalization['_links'] = array_diff_key($normalization['_links'], [$relation_url => TRUE]);
if (isset($normalization['_embedded'])) {
$normalization['_embedded'] = array_diff_key($normalization['_embedded'], [$relation_url => TRUE]);
}
}
return array_diff_key($normalization, array_flip($field_names));
}
/**
* {@inheritdoc}
*/
protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) {
catch
committed
// \Drupal\hal\Normalizer\EntityNormalizer::denormalize(): entity
// types with bundles MUST send their bundle field to be denormalizable.
if ($this->entity->getEntityType()->hasKey('bundle')) {
$normalization = $this->getNormalizedPostEntity();
$normalization['_links']['type'] = Url::fromUri('base:rest/type/' . static::$entityTypeId . '/bad_bundle_name');
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
// DX: 422 when incorrect entity type bundle is specified.
$response = $this->request($method, $url, $request_options);
$this->assertResourceErrorResponse(422, 'No entity type(s) specified', $response);
unset($normalization['_links']['type']);
$request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
// DX: 422 when no entity type bundle is specified.
$response = $this->request($method, $url, $request_options);
$this->assertResourceErrorResponse(422, 'The type link relation must be specified.', $response);