diff --git a/multifield.field.inc b/multifield.field.inc index a10305d..0bea3e0 100644 --- a/multifield.field.inc +++ b/multifield.field.inc @@ -329,10 +329,17 @@ function multifield_field_update($entity_type, $entity, $field, $instance, $lang $machine_name = multifield_extract_multifield_machine_name($field); //array_walk($items, 'multifield_item_unserialize', $machine_name); + // Gather the original field values from the parent entity if it has them. + $original_items = isset($entity->original) ? field_get_items($entity_type, $entity->original, $field['field_name'], $langcode) : array(); + // Run each sub-field through hook_field_update(). foreach ($items as $delta => $item) { $pseudo_entity = _multifield_field_item_to_entity($machine_name, $item); + if (isset($original_items[$delta])) { + $pseudo_entity->original = _multifield_field_item_to_entity($machine_name, $original_items[$delta]); + } _multifield_field_attach_update('multifield', $pseudo_entity); + unset($pseudo_entity->original); $items[$delta] = _multifield_field_entity_to_item($pseudo_entity); } diff --git a/multifield.info b/multifield.info index 4e50a68..5b3cec0 100644 --- a/multifield.info +++ b/multifield.info @@ -9,6 +9,7 @@ files[] = MultifieldEntityController.php files[] = tests/MultifieldAdministrationTestCase.test files[] = tests/MultifieldDevelGenerateTestCase.test files[] = tests/MultifieldEntityTranslationTestCase.test +files[] = tests/MultifieldFileUsageTestCase.test files[] = tests/MultifieldUnitTestCase.test test_dependencies[] = entity_translation test_dependencies[] = devel diff --git a/multifield.module b/multifield.module index a1e1fc1..e97114c 100644 --- a/multifield.module +++ b/multifield.module @@ -440,6 +440,12 @@ function multifield_item_serialize(&$item, $delta, $machine_name) { foreach (multifield_type_get_subfields($machine_name) as $subfield_name) { $subfield = field_info_field($subfield_name); foreach ($subfield['columns'] as $column => $details) { + // If the subfield is empty, skip it. + if (empty($item[$subfield_name][LANGUAGE_NONE][0])) { + unset($item[$subfield_name . '_' . $column]); + continue; + } + // @see field_sql_storage_field_storage_write() // @todo Should this be using array_key_exists() instead of isset()? if (!isset($item[$subfield_name][LANGUAGE_NONE][0][$column])) { @@ -451,7 +457,6 @@ function multifield_item_serialize(&$item, $delta, $machine_name) { // multifield_field_insert() or multifield_field_update(). $item[$subfield_name . '_' . $column] = &$item[$subfield_name][LANGUAGE_NONE][0][$column]; } - //unset($item[$subfield_name]); } } diff --git a/tests/MultifieldFileUsageTestCase.test b/tests/MultifieldFileUsageTestCase.test new file mode 100644 index 0000000..41e55cd --- /dev/null +++ b/tests/MultifieldFileUsageTestCase.test @@ -0,0 +1,103 @@ + 'File usage', + 'description' => 'Ensure file usage is tracked properly for both the multifield pseudo entity and the parent entity.', + 'group' => 'Multifield', + ); + } + + public function setUp() { + parent::setUp(array('multifield', 'file', 'image')); + } + + public function testFileUsage() { + // Add the test node type. + $node_type = $this->drupalCreateContentType(); + + // Get the test files. + $text_files = $this->drupalGetTestFiles('text'); + $text_file_1 = file_save($text_files[0]); + $text_file_2 = file_save($text_files[1]); + $image_files = $this->drupalGetTestFiles('image'); + $image_file_1 = file_save($image_files[0]); + $image_file_2 = file_save($image_files[1]); + + $multifield_field = array( + 'field_name' => 'test_file_usage', + 'type' => 'multifield', + 'cardinality' => FIELD_CARDINALITY_UNLIMITED, + ); + $multifield_field = field_create_field($multifield_field); + + $file_field = array( + 'field_name' => 'field_file', + 'type' => 'file', + ); + $file_field = field_create_field($file_field); + $file_field_instance = array( + 'field_name' => $file_field['field_name'], + 'entity_type' => 'multifield', + 'bundle' => $multifield_field['field_name'], + ); + $file_field_instance = field_create_instance($file_field_instance); + + $image_field = array( + 'field_name' => 'field_image', + 'type' => 'image', + ); + $image_field = field_create_field($image_field); + $image_field_instance = array( + 'field_name' => $image_field['field_name'], + 'entity_type' => 'multifield', + 'bundle' => $multifield_field['field_name'], + ); + $image_field_instance = field_create_instance($image_field_instance); + + $multifield_field_instance = array( + 'field_name' => $multifield_field['field_name'], + 'entity_type' => 'node', + 'bundle' => $node_type->type, + ); + field_create_instance($multifield_field_instance); + + $node = new stdClass(); + $node->type = $node_type->type; + $node->language = LANGUAGE_NONE; + $node->test_file_usage[LANGUAGE_NONE][0]['field_file'][LANGUAGE_NONE][0]['fid'] = $text_file_1->fid; + $node->test_file_usage[LANGUAGE_NONE][1]['field_image'][LANGUAGE_NONE][0]['fid'] = $image_file_1->fid; + node_save($node); + debug($node); + + $id1 = $node->test_file_usage[LANGUAGE_NONE][0]['id']; + $id2 = $node->test_file_usage[LANGUAGE_NONE][1]['id']; + $this->assertFileUsage($text_file_1, 'file', 'multifield', $id1, 1); + $this->assertFileUsage($text_file_1, 'file', 'node', $node->nid, 1); + $this->assertFileUsage($image_file_1, 'file', 'multifield', $id2, 1); + $this->assertFileUsage($image_file_1, 'file', 'node', $node->nid, 1); + + $node->test_file_usage[LANGUAGE_NONE][0]['field_file'][LANGUAGE_NONE][0]['fid'] = $text_file_2->fid; + $node->test_file_usage[LANGUAGE_NONE][1]['field_image'][LANGUAGE_NONE][0] = array(); + node_save($node); + debug($node); + + $this->assertFileUsage($text_file_1, 'file', 'multifield', $id1, 0); + $this->assertFileUsage($text_file_1, 'file', 'node', $node->nid, 0); + $this->assertFileUsage($text_file_2, 'file', 'multifield', $id1, 1); + $this->assertFileUsage($text_file_2, 'file', 'node', $node->nid, 1); + $this->assertFileUsage($image_file_1, 'file', 'multifield', $id2, 0); + $this->assertFileUsage($image_file_1, 'file', 'node', $node->nid, 0); + } + + public function assertFileUsage($file, $module, $type, $id, $count) { + // @todo Uncomment this line when https://www.drupal.org/node/2054243 is fixed. + if ($type == 'node') { return TRUE; } + $usage = file_usage_list($file); + $actual_count = isset($usage[$module][$type][$id]) ? $usage[$module][$type][$id] : 0; + return $this->assertEqual($actual_count, $count, "File usage for fid {$file->fid} on {$module}:{$type}:{$id} is {$actual_count}, expected {$count}."); + } +}