Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / hal / src / Normalizer / FieldItemNormalizer.php
1 <?php
2
3 namespace Drupal\hal\Normalizer;
4
5 use Drupal\Core\Field\FieldItemInterface;
6 use Symfony\Component\Serializer\Exception\InvalidArgumentException;
7
8 /**
9  * Converts the Drupal field item object structure to HAL array structure.
10  */
11 class FieldItemNormalizer extends NormalizerBase {
12
13   /**
14    * The interface or class that this Normalizer supports.
15    *
16    * @var string
17    */
18   protected $supportedInterfaceOrClass = 'Drupal\Core\Field\FieldItemInterface';
19
20   /**
21    * {@inheritdoc}
22    */
23   public function normalize($field_item, $format = NULL, array $context = []) {
24     // The values are wrapped in an array, and then wrapped in another array
25     // keyed by field name so that field items can be merged by the
26     // FieldNormalizer. This is necessary for the EntityReferenceItemNormalizer
27     // to be able to place values in the '_links' array.
28     $field = $field_item->getParent();
29     return [
30       $field->getName() => [$this->normalizedFieldValues($field_item, $format, $context)],
31     ];
32   }
33
34   /**
35    * {@inheritdoc}
36    */
37   public function denormalize($data, $class, $format = NULL, array $context = []) {
38     if (!isset($context['target_instance'])) {
39       throw new InvalidArgumentException('$context[\'target_instance\'] must be set to denormalize with the FieldItemNormalizer');
40     }
41     if ($context['target_instance']->getParent() == NULL) {
42       throw new InvalidArgumentException('The field item passed in via $context[\'target_instance\'] must have a parent set.');
43     }
44
45     $field_item = $context['target_instance'];
46
47     // If this field is translatable, we need to create a translated instance.
48     if (isset($data['lang'])) {
49       $langcode = $data['lang'];
50       unset($data['lang']);
51       $field_definition = $field_item->getFieldDefinition();
52       if ($field_definition->isTranslatable()) {
53         $field_item = $this->createTranslatedInstance($field_item, $langcode);
54       }
55     }
56
57     $field_item->setValue($this->constructValue($data, $context));
58     return $field_item;
59   }
60
61   /**
62    * Build the field item value using the incoming data.
63    *
64    * @param $data
65    *   The incoming data for this field item.
66    * @param $context
67    *   The context passed into the Normalizer.
68    *
69    * @return mixed
70    *   The value to use in Entity::setValue().
71    */
72   protected function constructValue($data, $context) {
73     return $data;
74   }
75
76   /**
77    * Normalizes field values for an item.
78    *
79    * @param \Drupal\Core\Field\FieldItemInterface $field_item
80    *   The field item instance.
81    * @param string|null $format
82    *   The normalization format.
83    * @param array $context
84    *   The context passed into the normalizer.
85    *
86    * @return array
87    *   An array of field item values, keyed by property name.
88    */
89   protected function normalizedFieldValues(FieldItemInterface $field_item, $format, array $context) {
90     $normalized = [];
91     // We normalize each individual property, so each can do their own casting,
92     // if needed.
93     /** @var \Drupal\Core\TypedData\TypedDataInterface $property */
94     foreach ($field_item as $property_name => $property) {
95       $normalized[$property_name] = $this->serializer->normalize($property, $format, $context);
96     }
97
98     if (isset($context['langcode'])) {
99       $normalized['lang'] = $context['langcode'];
100     }
101
102     return $normalized;
103   }
104
105   /**
106    * Get a translated version of the field item instance.
107    *
108    * To indicate that a field item applies to one translation of an entity and
109    * not another, the property path must originate with a translation of the
110    * entity. This is the reason for using target_instances, from which the
111    * property path can be traversed up to the root.
112    *
113    * @param \Drupal\Core\Field\FieldItemInterface $item
114    *   The untranslated field item instance.
115    * @param $langcode
116    *   The langcode.
117    *
118    * @return \Drupal\Core\Field\FieldItemInterface
119    *   The translated field item instance.
120    */
121   protected function createTranslatedInstance(FieldItemInterface $item, $langcode) {
122     // Remove the untranslated item that was created for the default language
123     // by FieldNormalizer::denormalize().
124     $items = $item->getParent();
125     $delta = $item->getName();
126     unset($items[$delta]);
127
128     // Instead, create a new item for the entity in the requested language.
129     $entity = $item->getEntity();
130     $entity_translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
131     $field_name = $item->getFieldDefinition()->getName();
132     return $entity_translation->get($field_name)->appendItem();
133   }
134
135 }