/** * Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::denormalize(). * * @param array $data * Entity data to restore. * @param string $class * Unused, entity_create() is used to instantiate entity objects. * @param string $format * Format the given data was extracted from. * @param array $context * Options available to the denormalizer. Keys that can be used: * - request_method: if set to "patch" the denormalization will clear out * all default values for entity fields before applying $data to the * entity. * * @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function denormalize($data, $class, $format = NULL, array $context = array()) { // Get type, necessary for determining which bundle to create. if (!isset($data['_links']['type'])) { throw new UnexpectedValueException('The type link relation must be specified.'); } // Create the entity. $typed_data_ids = $this->getTypedDataIds($data['_links']['type'], $context); $entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']); $langcode_key = $entity_type->getKey('langcode'); $values = array(); // Figure out the language to use. if (isset($data[$langcode_key])) { $values[$langcode_key] = $data[$langcode_key][0]['value']; // Remove the langcode so it does not get iterated over below. unset($data[$langcode_key]); } if ($entity_type->hasKey('bundle')) { $bundle_key = $entity_type->getKey('bundle'); $values[$bundle_key] = $typed_data_ids['bundle']; // Unset the bundle key from data, if it's there. unset($data[$bundle_key]); } $entity = $this->entityManager->getStorage($typed_data_ids['entity_type'])->create($values); // Remove links from data array. unset($data['_links']); // Get embedded resources and remove from data array. $embedded = array(); if (isset($data['_embedded'])) { $embedded = $data['_embedded']; unset($data['_embedded']); } // Flatten the embedded values. foreach ($embedded as $relation => $field) { $field_ids = $this->linkManager->getRelationInternalIds($relation); if (!empty($field_ids)) { $field_name = $field_ids['field_name']; $data[$field_name] = $field; } } // Pass the names of the fields whose values can be merged. $entity->_restSubmittedFields = array_keys($data); // Iterate through remaining items in data array. These should all // correspond to fields. foreach ($data as $field_name => $field_data) { $items = $entity->get($field_name); // Remove any values that were set as a part of entity creation (e.g // uuid). If the incoming field data is set to an empty array, this will // also have the effect of emptying the field in REST module. $items->setValue(array()); if ($field_data) { // Denormalize the field data into the FieldItemList object. $context['target_instance'] = $items; $this->serializer->denormalize($field_data, get_class($items), $format, $context); } } return $entity; }
/** * Implements \Symfony\Component\Serializer\Normalizer\DenormalizerInterface::denormalize(). * * @param array $data * Entity data to restore. * @param string $class * Unused, entity_create() is used to instantiate entity objects. * @param string $format * Format the given data was extracted from. * @param array $context * Options available to the denormalizer. Keys that can be used: * - request_method: if set to "patch" the denormalization will clear out * all default values for entity fields before applying $data to the * entity. * * @throws \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function denormalize($data, $class, $format = NULL, array $context = array()) { // Get type, necessary for determining which bundle to create. if (!isset($data['_links']['type'])) { throw new UnexpectedValueException('The type link relation must be specified.'); } // Create the entity. $typed_data_ids = $this->getTypedDataIds($data['_links']['type']); // Figure out the language to use. if (isset($data['langcode'])) { $langcode = $data['langcode'][0]['value']; // Remove the langcode so it does not get iterated over below. unset($data['langcode']); } elseif ($this->moduleHandler->moduleExists('language')) { $langcode = language_get_default_langcode($typed_data_ids['entity_type'], $typed_data_ids['bundle']); } else { $langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED; } $entity_type = $this->entityManager->getDefinition($typed_data_ids['entity_type']); $values = array('langcode' => $langcode); if ($entity_type->hasKey('bundle')) { $bundle_key = $entity_type->getKey('bundle'); $values[$bundle_key] = $typed_data_ids['bundle']; // Unset the bundle key from data, if it's there. unset($data[$bundle_key]); } $entity = $this->entityManager->getStorage($typed_data_ids['entity_type'])->create($values); // Special handling for PATCH: destroy all possible default values that // might have been set on entity creation. We want an "empty" entity that // will only get filled with fields from the data array. if (isset($context['request_method']) && $context['request_method'] == 'patch') { foreach ($entity as $field_name => $field) { $entity->set($field_name, NULL); } } // Remove links from data array. unset($data['_links']); // Get embedded resources and remove from data array. $embedded = array(); if (isset($data['_embedded'])) { $embedded = $data['_embedded']; unset($data['_embedded']); } // Flatten the embedded values. foreach ($embedded as $relation => $field) { $field_ids = $this->linkManager->getRelationInternalIds($relation); if (!empty($field_ids)) { $field_name = $field_ids['field_name']; $data[$field_name] = $field; } } // Iterate through remaining items in data array. These should all // correspond to fields. foreach ($data as $field_name => $field_data) { // Remove any values that were set as a part of entity creation (e.g // uuid). If this field is set to an empty array in the data, this will // also have the effect of marking the field for deletion in REST module. $entity->{$field_name} = array(); $field = $entity->get($field_name); // Get the class of the field. This will generally be the default Field // class. $field_class = get_class($field); // Pass in the empty field object as a target instance. Since the context // is already prepared for the field, any data added to it is // automatically added to the entity. $context['target_instance'] = $field; $this->serializer->denormalize($field_data, $field_class, $format, $context); } return $entity; }