diff --git a/core/modules/hal/lib/Drupal/hal/Normalizer/FieldItemNormalizer.php b/core/modules/hal/lib/Drupal/hal/Normalizer/FieldItemNormalizer.php index eee77e9..9b4ca14 100644 --- a/core/modules/hal/lib/Drupal/hal/Normalizer/FieldItemNormalizer.php +++ b/core/modules/hal/lib/Drupal/hal/Normalizer/FieldItemNormalizer.php @@ -7,6 +7,8 @@ namespace Drupal\hal\Normalizer; +use Drupal\Core\Entity\Field\FieldItemInterface; + /** * Converts the Drupal field item object structure to HAL array structure. */ @@ -43,12 +45,62 @@ public function normalize($field_item, $format = NULL, array $context = array()) */ public function denormalize($data, $class, $format = NULL, array $context = array()) { if (!isset($context['target_instance'])) { - throw new LogicException('The target_instance must be passed in via the $context to denormalize with the FieldItemNormalizer.'); + throw new LogicException('$context[\'target_instance\'] must be set to denormalize with the FieldItemNormalizer'); + } + if ($context['target_instance']->getParent() == NULL) { + throw new LogicException('The field item passed in via $context[\'target_instance\'] must have a parent set.'); } $field_item = $context['target_instance']; + + // If this field is translatable, we need to create a translated instance. + if (isset($data['lang'])) { + $langcode = $data['lang']; + unset($data['lang']); + $field_definition = $field_item->getDefinition(); + if ($field_definition['translatable'] == TRUE) { + $field_item = $this->createTranslatedInstance($field_item, $langcode); + } + } + $field_item->setValue($data); return $field_item; } + /** + * Get a translated version of the field item instance. + * + * @param \Drupal\Core\Entity\Field\FieldItemInterface $field_item + * The untranslated field item instance. + * @param $langcode + * The langcode. + * + * @return \Drupal\Core\Entity\Field\FieldItemInterface + * The translated field item instance. + */ + protected function createTranslatedInstance(FieldItemInterface $field_item, $langcode) { + $parent = $field_item->getParent(); + $ancestors = array(); + + // Remove the untranslated instance from the field's list of items. + $parent->offsetUnset($field_item->getName()); + + // Get the property chain. + while (!method_exists($parent, 'getTranslation')) { + array_unshift($ancestors, $parent); + $parent = $parent->getParent(); + } + + // Recreate the property path. + $translation = $parent->getTranslation($langcode); + foreach ($ancestors as $ancestor) { + $ancestor_name = $ancestor->getName(); + $translation = $translation->get($ancestor_name); + } + + // Create a new instance at the end of the property path and return it. + $count = $translation->isEmpty() ? 0 : $translation->count(); + return $translation->offsetGet($count); + } + } diff --git a/core/modules/hal/lib/Drupal/hal/Normalizer/FieldNormalizer.php b/core/modules/hal/lib/Drupal/hal/Normalizer/FieldNormalizer.php index 77b040a..ae48b57 100644 --- a/core/modules/hal/lib/Drupal/hal/Normalizer/FieldNormalizer.php +++ b/core/modules/hal/lib/Drupal/hal/Normalizer/FieldNormalizer.php @@ -60,25 +60,16 @@ public function normalize($field, $format = NULL, array $context = array()) { */ public function denormalize($data, $class, $format = NULL, array $context = array()) { if (!isset($context['target_instance'])) { - throw new LogicException('The target_instance must be passed in via the $context to denormalize with the FieldNormalizer'); + throw new LogicException('$context[\'target_instance\'] must be set to denormalize with the FieldNormalizer'); + } + if ($context['target_instance']->getParent() == NULL) { + throw new LogicException('The field passed in via $context[\'target_instance\'] must have a parent set.'); } $field = $context['target_instance']; foreach ($data as $field_item_data) { - $langcode = LANGUAGE_DEFAULT; - if (isset($field_item_data['lang'])) { - $langcode = $field_item_data['lang']; - unset($field_item_data['lang']); - $entity = $field->getParent(); - $translation = $entity->getTranslation($langcode); - $translated_field = $translation->get($field->getName()); - $count = $field->isEmpty() ? 0 : $translated_field->count(); - $field_item = $translation->get($field->getName())->offsetGet($count); - } - else { - $count = $field->count(); - $field_item = $field->offsetGet($count); - } + $count = $field->isEmpty() ? 0 : $field->count(); + $field_item = $field->offsetGet($count); $field_item_class = get_class($field_item); $context['target_instance'] = $field_item; $this->serializer->denormalize($field_item_data, $field_item_class, $format, $context); diff --git a/core/modules/hal/lib/Drupal/hal/Tests/DenormalizeTest.php b/core/modules/hal/lib/Drupal/hal/Tests/DenormalizeTest.php index f74265b..a046720 100644 --- a/core/modules/hal/lib/Drupal/hal/Tests/DenormalizeTest.php +++ b/core/modules/hal/lib/Drupal/hal/Tests/DenormalizeTest.php @@ -25,7 +25,7 @@ public static function getInfo() { /** * Tests that the type link relation in incoming data is handled correctly. */ - /*public function testTypeHandling() { + public function testTypeHandling() { // Valid type. $data_with_valid_type = array( '_links' => array( @@ -65,12 +65,12 @@ public static function getInfo() { catch (UnexpectedValueException $e) { $this->pass('Exception thrown when no type is provided.'); } - }*/ + } /** * Test that a field set to an empty array is different than an empty field. */ - /*public function testMarkFieldForDeletion() { + public function testMarkFieldForDeletion() { $no_field_data = array( '_links' => array( 'type' => array( @@ -93,7 +93,7 @@ public static function getInfo() { $empty_field_value = $empty_field_denormalized->field_test_text->getValue(); $this->assertTrue(!empty($no_field_value) && empty($empty_field_value), 'A field set to an empty array in the data is structured differently than an empty field.'); - } */ + } /** * Test that non-reference fields can be denormalized. @@ -105,31 +105,59 @@ public function testBasicFieldDenormalization() { 'href' => url('rest/types/entity_test/entity_test', array('absolute' => TRUE)), ), ), + 'field_test_text' => array( + array( + 'value' => $this->randomName(), + 'format' => 'full_html', + ), + ), 'field_test_translatable_text' => array( array( - 'value' => 'foobar', + 'value' => $this->randomName(), 'format' => 'full_html', 'lang' => 'en', ), array( - 'value' => 'foobar2', - 'format' => 'full_html', + 'value' => $this->randomName(), + 'format' => 'filtered_html', 'lang' => 'en', ), array( - 'value' => 'bar', - 'format' => 'full_html', + 'value' => $this->randomName(), + 'format' => 'filtered_html', 'lang' => 'de', ), array( - 'value' => 'bar2', + 'value' => $this->randomName(), 'format' => 'full_html', 'lang' => 'de', ), ), ); + + $expected_value_en = array( + array ( + 'value' => $data['field_test_translatable_text'][0]['value'], + 'format' => 'full_html', + ), + array ( + 'value' => $data['field_test_translatable_text'][1]['value'], + 'format' => 'filtered_html', + ), + ); + $expected_value_de = array( + array ( + 'value' => $data['field_test_translatable_text'][2]['value'], + 'format' => 'filtered_html', + ), + array ( + 'value' => $data['field_test_translatable_text'][3]['value'], + 'format' => 'full_html', + ), + ); $denormalized = $this->container->get('serializer')->denormalize($data, $this->entityClass, $this->format); - debug($denormalized->get('field_test_translatable_text')->getValue()); - debug($denormalized->getTranslation('de')->get('field_test_translatable_text')->getValue()); + $this->assertEqual($data['field_test_text'], $denormalized->get('field_test_text')->getValue(), 'A basic text field is denormalized.'); + $this->assertEqual($expected_value_en, $denormalized->get('field_test_translatable_text')->getValue(), 'Values in the default language are properly handled for a translatable field.'); + $this->assertEqual($expected_value_de, $denormalized->getTranslation('de')->get('field_test_translatable_text')->getValue(), 'Values in a translation language are properly handled for a translatable field.'); } }