Upgraded drupal core with security updates
[yaffs-website] / web / core / modules / hal / tests / src / Functional / EntityResource / HalEntityNormalizationTrait.php
1 <?php
2
3 namespace Drupal\Tests\hal\Functional\EntityResource;
4
5 use Drupal\Core\Entity\FieldableEntityInterface;
6 use Drupal\Core\Field\EntityReferenceFieldItemListInterface;
7 use Drupal\Core\Field\FieldItemListInterface;
8 use Drupal\Core\Url;
9 use GuzzleHttp\RequestOptions;
10
11 /**
12  * Trait for EntityResourceTestBase subclasses testing formats using HAL.
13  */
14 trait HalEntityNormalizationTrait {
15
16   /**
17    * Applies the HAL entity field normalization to an entity normalization.
18    *
19    * The HAL normalization:
20    * - adds a 'lang' attribute to every translatable field
21    * - omits reference fields, since references are stored in _links & _embedded
22    * - omits empty fields (fields without value)
23    *
24    * @param array $normalization
25    *   An entity normalization.
26    *
27    * @return array
28    *   The updated entity normalization.
29    */
30   protected function applyHalFieldNormalization(array $normalization) {
31     if (!$this->entity instanceof FieldableEntityInterface) {
32       throw new \LogicException('This trait should only be used for fieldable entity types.');
33     }
34
35     // In the HAL normalization, all translatable fields get a 'lang' attribute.
36     $translatable_non_reference_fields = array_keys(array_filter($this->entity->getTranslatableFields(), function (FieldItemListInterface $field) {
37       return !$field instanceof EntityReferenceFieldItemListInterface;
38     }));
39     foreach ($translatable_non_reference_fields as $field_name) {
40       if (isset($normalization[$field_name])) {
41         $normalization[$field_name][0]['lang'] = 'en';
42       }
43     }
44
45     // In the HAL normalization, reference fields are omitted, except for the
46     // bundle field.
47     $bundle_key = $this->entity->getEntityType()->getKey('bundle');
48     $reference_fields = array_keys(array_filter($this->entity->getFields(), function (FieldItemListInterface $field) use ($bundle_key) {
49       return $field instanceof EntityReferenceFieldItemListInterface && $field->getName() !== $bundle_key;
50     }));
51     foreach ($reference_fields as $field_name) {
52       unset($normalization[$field_name]);
53     }
54
55     // In the HAL normalization, the bundle field  omits the 'target_type' and
56     // 'target_uuid' properties, because it's encoded in the '_links' section.
57     if ($bundle_key) {
58       unset($normalization[$bundle_key][0]['target_type']);
59       unset($normalization[$bundle_key][0]['target_uuid']);
60     }
61
62     // In the HAL normalization, empty fields are omitted.
63     $empty_fields = array_keys(array_filter($this->entity->getFields(), function (FieldItemListInterface $field) {
64       return $field->isEmpty();
65     }));
66     foreach ($empty_fields as $field_name) {
67       unset($normalization[$field_name]);
68     }
69
70     return $normalization;
71   }
72
73   /**
74    * {@inheritdoc}
75    */
76   protected function removeFieldsFromNormalization(array $normalization, $field_names) {
77     $normalization = parent::removeFieldsFromNormalization($normalization, $field_names);
78     foreach ($field_names as $field_name) {
79       $relation_url = Url::fromUri('base:rest/relation/' . static::$entityTypeId . '/' . $this->entity->bundle() . '/' . $field_name)
80         ->setAbsolute(TRUE)
81         ->toString();
82       $normalization['_links'] = array_diff_key($normalization['_links'], [$relation_url => TRUE]);
83       if (isset($normalization['_embedded'])) {
84         $normalization['_embedded'] = array_diff_key($normalization['_embedded'], [$relation_url => TRUE]);
85       }
86     }
87
88     return array_diff_key($normalization, array_flip($field_names));
89   }
90
91   /**
92    * {@inheritdoc}
93    */
94   protected function assertNormalizationEdgeCases($method, Url $url, array $request_options) {
95     // \Drupal\hal\Normalizer\EntityNormalizer::denormalize(): entity
96     // types with bundles MUST send their bundle field to be denormalizable.
97     if ($this->entity->getEntityType()->hasKey('bundle')) {
98       $normalization = $this->getNormalizedPostEntity();
99
100
101       $normalization['_links']['type'] = Url::fromUri('base:rest/type/' . static::$entityTypeId . '/bad_bundle_name');
102       $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
103
104       // DX: 400 when incorrect entity type bundle is specified.
105       $response = $this->request($method, $url, $request_options);
106       $this->assertResourceErrorResponse(400, 'No entity type(s) specified', $response);
107
108
109       unset($normalization['_links']['type']);
110       $request_options[RequestOptions::BODY] = $this->serializer->encode($normalization, static::$format);
111
112
113       // DX: 400 when no entity type bundle is specified.
114       $response = $this->request($method, $url, $request_options);
115       $this->assertResourceErrorResponse(400, 'The type link relation must be specified.', $response);
116     }
117   }
118
119 }