summaryrefslogtreecommitdiffstatshomepage
path: root/core/modules/file/tests/src/Functional/FileFieldValidateTest.php
blob: 22ff5044ac374b7d0fe317333a454b40402f0c6c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
<?php

declare(strict_types=1);

namespace Drupal\Tests\file\Functional;

use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\StringTranslation\ByteSizeMarkup;
use Drupal\field\Entity\FieldConfig;
use Drupal\file\Entity\File;

/**
 * Tests file field validation functions.
 *
 * Values validated include the file type, max file size, max size per node,
 * and whether the field is required.
 *
 * @group file
 */
class FileFieldValidateTest extends FileFieldTestBase {

  /**
   * {@inheritdoc}
   */
  protected $defaultTheme = 'stark';

  /**
   * Tests the required property on file fields.
   */
  public function testRequired(): void {
    $node_storage = $this->container->get('entity_type.manager')->getStorage('node');
    $type_name = 'article';
    $field_name = $this->randomMachineName();
    $storage = $this->createFileField($field_name, 'node', $type_name, [], ['required' => '1']);
    $field = FieldConfig::loadByName('node', $type_name, $field_name);

    $test_file = $this->getTestFile('text');

    // Try to post a new node without uploading a file.
    $edit = [];
    $edit['title[0][value]'] = $this->randomMachineName();
    $this->drupalGet('node/add/' . $type_name);
    $this->submitForm($edit, 'Save');
    $this->assertSession()->pageTextContains("{$field->getLabel()} field is required.");

    // Create a new node with the uploaded file.
    $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
    $this->assertNotFalse($nid, "uploadNodeFile({$test_file->getFileUri()}, $field_name, $type_name) succeeded");

    $node = $node_storage->load($nid);

    $node_file = File::load($node->{$field_name}->target_id);
    $this->assertFileExists($node_file->getFileUri());
    $this->assertFileEntryExists($node_file, 'File entry exists after uploading to the required field.');

    // Try again with a multiple value field.
    $storage->delete();
    $this->createFileField($field_name, 'node', $type_name, ['cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED], ['required' => '1']);

    // Try to post a new node without uploading a file in the multivalue field.
    $edit = [];
    $edit['title[0][value]'] = $this->randomMachineName();
    $this->drupalGet('node/add/' . $type_name);
    $this->submitForm($edit, 'Save');
    $this->assertSession()->pageTextContains("{$field->getLabel()} field is required.");

    // Create a new node with the uploaded file into the multivalue field.
    $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
    $node = $node_storage->load($nid);
    $node_file = File::load($node->{$field_name}->target_id);
    $this->assertFileExists($node_file->getFileUri());
    $this->assertFileEntryExists($node_file, 'File entry exists after uploading to the required multiple value field.');
  }

  /**
   * Tests the max file size validator.
   */
  public function testFileMaxSize(): void {
    $node_storage = $this->container->get('entity_type.manager')->getStorage('node');
    $type_name = 'article';
    $field_name = $this->randomMachineName();
    $this->createFileField($field_name, 'node', $type_name, [], ['required' => '1']);

    // 128KB.
    $small_file = $this->getTestFile('text', 131072);
    // 1.2MB
    $large_file = $this->getTestFile('text', 1310720);

    // Test uploading both a large and small file with different increments.
    $sizes = [
      '1M' => 1048576,
      '1024K' => 1048576,
      '1048576' => 1048576,
    ];

    foreach ($sizes as $max_filesize => $file_limit) {
      // Set the max file upload size.
      $this->updateFileField($field_name, $type_name, ['max_filesize' => $max_filesize]);

      // Create a new node with the small file, which should pass.
      $nid = $this->uploadNodeFile($small_file, $field_name, $type_name);
      $node = $node_storage->load($nid);
      $node_file = File::load($node->{$field_name}->target_id);
      $this->assertFileExists($node_file->getFileUri());
      $this->assertFileEntryExists($node_file, sprintf('File entry exists after uploading a file (%s) under the max limit (%s).', ByteSizeMarkup::create($small_file->getSize()), $max_filesize));

      // Check that uploading the large file fails (1M limit).
      $this->uploadNodeFile($large_file, $field_name, $type_name);
      $filesize = ByteSizeMarkup::create($large_file->getSize());
      $maxsize = ByteSizeMarkup::create($file_limit);
      $this->assertSession()->pageTextContains("The file is {$filesize} exceeding the maximum file size of {$maxsize}.");
    }

    // Turn off the max filesize.
    $this->updateFileField($field_name, $type_name, ['max_filesize' => '']);

    // Upload the big file successfully.
    $nid = $this->uploadNodeFile($large_file, $field_name, $type_name);
    $node = $node_storage->load($nid);
    $node_file = File::load($node->{$field_name}->target_id);
    $this->assertFileExists($node_file->getFileUri());
    $this->assertFileEntryExists($node_file, sprintf('File entry exists after uploading a file (%s) with no max limit.', ByteSizeMarkup::create($large_file->getSize())));
  }

  /**
   * Tests file extension checking.
   */
  public function testFileExtension(): void {
    $node_storage = $this->container->get('entity_type.manager')->getStorage('node');
    $type_name = 'article';
    $field_name = $this->randomMachineName();
    $this->createFileField($field_name, 'node', $type_name);

    $test_file = $this->getTestFile('image');
    [, $test_file_extension] = explode('.', $test_file->getFilename());

    // Disable extension checking.
    $this->updateFileField($field_name, $type_name, ['file_extensions' => '']);

    // Check that the file can be uploaded with no extension checking.
    $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
    $node = $node_storage->load($nid);
    $node_file = File::load($node->{$field_name}->target_id);
    $this->assertFileExists($node_file->getFileUri());
    $this->assertFileEntryExists($node_file, 'File entry exists after uploading a file with no extension checking.');

    // Enable extension checking for text files.
    $this->updateFileField($field_name, $type_name, ['file_extensions' => 'txt']);

    // Check that the file with the wrong extension cannot be uploaded.
    $this->uploadNodeFile($test_file, $field_name, $type_name);
    $this->assertSession()->pageTextContains("Only files with the following extensions are allowed: txt.");

    // Enable extension checking for text and image files.
    $this->updateFileField($field_name, $type_name, ['file_extensions' => "txt $test_file_extension"]);

    // Check that the file can be uploaded with extension checking.
    $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
    $node = $node_storage->load($nid);
    $node_file = File::load($node->{$field_name}->target_id);
    $this->assertFileExists($node_file->getFileUri());
    $this->assertFileEntryExists($node_file, 'File entry exists after uploading a file with extension checking.');
  }

  /**
   * Checks that a file can always be removed if it does not pass validation.
   */
  public function testFileRemoval(): void {
    $node_storage = $this->container->get('entity_type.manager')->getStorage('node');
    $type_name = 'article';
    $field_name = 'file_test';
    $this->createFileField($field_name, 'node', $type_name);

    $test_file = $this->getTestFile('image');

    // Disable extension checking.
    $this->updateFileField($field_name, $type_name, ['file_extensions' => '']);

    // Check that the file can be uploaded with no extension checking.
    $nid = $this->uploadNodeFile($test_file, $field_name, $type_name);
    $node = $node_storage->load($nid);
    $node_file = File::load($node->{$field_name}->target_id);
    $this->assertFileExists($node_file->getFileUri());
    $this->assertFileEntryExists($node_file, 'File entry exists after uploading a file with no extension checking.');

    // Enable extension checking for text files.
    $this->updateFileField($field_name, $type_name, ['file_extensions' => 'txt']);

    // Check that the file can still be removed.
    $this->removeNodeFile($nid);
    $this->assertSession()->pageTextNotContains('Only files with the following extensions are allowed: txt.');
    $this->assertSession()->pageTextContains('Article ' . $node->getTitle() . ' has been updated.');
  }

}