dc5aec98994ada8055135dff94b6680b0ed271ea
[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     $values = [];
25     // We normalize each individual property, so each can do their own casting,
26     // if needed.
27     /** @var \Drupal\Core\TypedData\TypedDataInterface $property */
28     foreach ($field_item as $property_name => $property) {
29       $values[$property_name] = $this->serializer->normalize($property, $format, $context);
30     }
31
32     if (isset($context['langcode'])) {
33       $values['lang'] = $context['langcode'];
34     }
35
36     // The values are wrapped in an array, and then wrapped in another array
37     // keyed by field name so that field items can be merged by the
38     // FieldNormalizer. This is necessary for the EntityReferenceItemNormalizer
39     // to be able to place values in the '_links' array.
40     $field = $field_item->getParent();
41     return [
42       $field->getName() => [$values],
43     ];
44   }
45
46   /**
47    * {@inheritdoc}
48    */
49   public function denormalize($data, $class, $format = NULL, array $context = []) {
50     if (!isset($context['target_instance'])) {
51       throw new InvalidArgumentException('$context[\'target_instance\'] must be set to denormalize with the FieldItemNormalizer');
52     }
53     if ($context['target_instance']->getParent() == NULL) {
54       throw new InvalidArgumentException('The field item passed in via $context[\'target_instance\'] must have a parent set.');
55     }
56
57     $field_item = $context['target_instance'];
58
59     // If this field is translatable, we need to create a translated instance.
60     if (isset($data['lang'])) {
61       $langcode = $data['lang'];
62       unset($data['lang']);
63       $field_definition = $field_item->getFieldDefinition();
64       if ($field_definition->isTranslatable()) {
65         $field_item = $this->createTranslatedInstance($field_item, $langcode);
66       }
67     }
68
69     $field_item->setValue($this->constructValue($data, $context));
70     return $field_item;
71   }
72
73   /**
74    * Build the field item value using the incoming data.
75    *
76    * @param $data
77    *   The incoming data for this field item.
78    * @param $context
79    *   The context passed into the Normalizer.
80    *
81    * @return mixed
82    *   The value to use in Entity::setValue().
83    */
84   protected function constructValue($data, $context) {
85     return $data;
86   }
87
88   /**
89    * Get a translated version of the field item instance.
90    *
91    * To indicate that a field item applies to one translation of an entity and
92    * not another, the property path must originate with a translation of the
93    * entity. This is the reason for using target_instances, from which the
94    * property path can be traversed up to the root.
95    *
96    * @param \Drupal\Core\Field\FieldItemInterface $field_item
97    *   The untranslated field item instance.
98    * @param $langcode
99    *   The langcode.
100    *
101    * @return \Drupal\Core\Field\FieldItemInterface
102    *   The translated field item instance.
103    */
104   protected function createTranslatedInstance(FieldItemInterface $item, $langcode) {
105     // Remove the untranslated item that was created for the default language
106     // by FieldNormalizer::denormalize().
107     $items = $item->getParent();
108     $delta = $item->getName();
109     unset($items[$delta]);
110
111     // Instead, create a new item for the entity in the requested language.
112     $entity = $item->getEntity();
113     $entity_translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
114     $field_name = $item->getFieldDefinition()->getName();
115     return $entity_translation->get($field_name)->appendItem();
116   }
117
118 }