diff --git a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php index df5e039cb08..b2386b489d3 100644 --- a/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php +++ b/core/modules/file/src/Plugin/Field/FieldWidget/FileWidget.php @@ -325,25 +325,30 @@ class FileWidget extends WidgetBase implements ContainerFactoryPluginInterface { * This validator is used only when cardinality not set to 1 or unlimited. */ public static function validateMultipleCount($element, FormStateInterface $form_state, $form) { - $parents = $element['#parents']; - $values = NestedArray::getValue($form_state->getValues(), $parents); + $values = NestedArray::getValue($form_state->getValues(), $element['#parents']); - array_pop($parents); - $current = count(Element::children(NestedArray::getValue($form, $parents))) - 1; + $array_parents = $element['#array_parents']; + array_pop($array_parents); + $previously_uploaded_count = count(Element::children(NestedArray::getValue($form, $array_parents))) - 1; $field_storage_definitions = \Drupal::entityManager()->getFieldStorageDefinitions($element['#entity_type']); $field_storage = $field_storage_definitions[$element['#field_name']]; - $uploaded = count($values['fids']); - $count = $uploaded + $current; - if ($count > $field_storage->getCardinality()) { - $keep = $uploaded - $count + $field_storage->getCardinality(); + $newly_uploaded_count = count($values['fids']); + $total_uploaded_count = $newly_uploaded_count + $previously_uploaded_count; + if ($total_uploaded_count > $field_storage->getCardinality()) { + $keep = $newly_uploaded_count - $total_uploaded_count + $field_storage->getCardinality(); $removed_files = array_slice($values['fids'], $keep); $removed_names = array(); foreach ($removed_files as $fid) { $file = File::load($fid); $removed_names[] = $file->getFilename(); } - $args = array('%field' => $field_storage->getName(), '@max' => $field_storage->getCardinality(), '@count' => $uploaded, '%list' => implode(', ', $removed_names)); + $args = [ + '%field' => $field_storage->getName(), + '@max' => $field_storage->getCardinality(), + '@count' => $total_uploaded_count, + '%list' => implode(', ', $removed_names), + ]; $message = t('Field %field can only hold @max values but there were @count uploaded. The following files have been omitted as a result: %list.', $args); drupal_set_message($message, 'warning'); $values['fids'] = array_slice($values['fids'], 0, $keep); diff --git a/core/modules/file/src/Tests/FileFieldTestBase.php b/core/modules/file/src/Tests/FileFieldTestBase.php index a725099c226..307eb4d1593 100644 --- a/core/modules/file/src/Tests/FileFieldTestBase.php +++ b/core/modules/file/src/Tests/FileFieldTestBase.php @@ -36,6 +36,8 @@ abstract class FileFieldTestBase extends WebTestBase { /** * Retrieves a sample file of the specified type. + * + * @return \Drupal\file\FileInterface */ function getTestFile($type_name, $size = NULL) { // Get a file to upload. diff --git a/core/modules/file/src/Tests/FileFieldWidgetTest.php b/core/modules/file/src/Tests/FileFieldWidgetTest.php index a0d03937265..414c86b55f3 100644 --- a/core/modules/file/src/Tests/FileFieldWidgetTest.php +++ b/core/modules/file/src/Tests/FileFieldWidgetTest.php @@ -247,32 +247,39 @@ class FileFieldWidgetTest extends FileFieldTestBase { $this->assertTrue(empty($node->{$field_name}->target_id), 'Node was successfully saved without any files.'); } - $upload_files = array($test_file, $test_file); + $upload_files_node_creation = array($test_file, $test_file); // Try to upload multiple files, but fewer than the maximum. - $nid = $this->uploadNodeFiles($upload_files, $field_name, $type_name); + $nid = $this->uploadNodeFiles($upload_files_node_creation, $field_name, $type_name); $node_storage->resetCache(array($nid)); $node = $node_storage->load($nid); - $this->assertEqual(count($node->{$field_name}), count($upload_files), 'Node was successfully saved with mulitple files.'); + $this->assertEqual(count($node->{$field_name}), count($upload_files_node_creation), 'Node was successfully saved with mulitple files.'); // Try to upload more files than allowed on revision. - $this->uploadNodeFiles($upload_files, $field_name, $nid, 1); - $args = array( + $upload_files_node_revision = array($test_file, $test_file, $test_file, $test_file); + $this->uploadNodeFiles($upload_files_node_revision, $field_name, $nid, 1); + $args = [ '%field' => $field_name, - '@count' => $cardinality - ); - $this->assertRaw(t('%field: this field cannot hold more than @count values.', $args)); + '@max' => $cardinality, + '@count' => count($upload_files_node_creation) + count($upload_files_node_revision), + '%list' => implode(', ', array_fill(0, 3, $test_file->getFilename())), + ]; + $this->assertRaw(t('Field %field can only hold @max values but there were @count uploaded. The following files have been omitted as a result: %list.', $args)); $node_storage->resetCache(array($nid)); $node = $node_storage->load($nid); - $this->assertEqual(count($node->{$field_name}), count($upload_files), 'More files than allowed could not be saved to node.'); + $this->assertEqual(count($node->{$field_name}), $cardinality, 'More files than allowed could not be saved to node.'); - // Try to upload exactly the allowed number of files on revision. - $this->uploadNodeFile($test_file, $field_name, $nid, 1); + // Try to upload exactly the allowed number of files on revision. Create an + // empty node first, to fill it in its first revision. + $node = $this->drupalCreateNode([ + 'type' => $type_name + ]); + $this->uploadNodeFile($test_file, $field_name, $node->id(), 1); $node_storage->resetCache(array($nid)); $node = $node_storage->load($nid); $this->assertEqual(count($node->{$field_name}), $cardinality, 'Node was successfully revised to maximum number of files.'); // Try to upload exactly the allowed number of files, new node. - $upload_files[] = $test_file; + $upload_files = array_fill(0, $cardinality, $test_file); $nid = $this->uploadNodeFiles($upload_files, $field_name, $type_name); $node_storage->resetCache(array($nid)); $node = $node_storage->load($nid);