9ed447aaf25e969eee31621e04e7f588791f8ed0
[yaffs-website] / web / core / modules / file / tests / src / Functional / FileFieldTestBase.php
1 <?php
2
3 namespace Drupal\Tests\file\Functional;
4
5 use Drupal\field\Entity\FieldStorageConfig;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\file\FileInterface;
8 use Drupal\Tests\BrowserTestBase;
9 use Drupal\file\Entity\File;
10
11 /**
12  * Provides methods specifically for testing File module's field handling.
13  */
14 abstract class FileFieldTestBase extends BrowserTestBase {
15
16   /**
17   * Modules to enable.
18   *
19   * @var array
20   */
21   public static $modules = ['node', 'file', 'file_module_test', 'field_ui'];
22
23   /**
24    * An user with administration permissions.
25    *
26    * @var \Drupal\user\UserInterface
27    */
28   protected $adminUser;
29
30   protected function setUp() {
31     parent::setUp();
32     $this->adminUser = $this->drupalCreateUser(['access content', 'access administration pages', 'administer site configuration', 'administer users', 'administer permissions', 'administer content types', 'administer node fields', 'administer node display', 'administer nodes', 'bypass node access']);
33     $this->drupalLogin($this->adminUser);
34     $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
35   }
36
37   /**
38    * Retrieves a sample file of the specified type.
39    *
40    * @return \Drupal\file\FileInterface
41    */
42   public function getTestFile($type_name, $size = NULL) {
43     // Get a file to upload.
44     $file = current($this->drupalGetTestFiles($type_name, $size));
45
46     // Add a filesize property to files as would be read by
47     // \Drupal\file\Entity\File::load().
48     $file->filesize = filesize($file->uri);
49
50     return File::create((array) $file);
51   }
52
53   /**
54    * Retrieves the fid of the last inserted file.
55    */
56   public function getLastFileId() {
57     return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
58   }
59
60   /**
61    * Creates a new file field.
62    *
63    * @param string $name
64    *   The name of the new field (all lowercase), exclude the "field_" prefix.
65    * @param string $entity_type
66    *   The entity type.
67    * @param string $bundle
68    *   The bundle that this field will be added to.
69    * @param array $storage_settings
70    *   A list of field storage settings that will be added to the defaults.
71    * @param array $field_settings
72    *   A list of instance settings that will be added to the instance defaults.
73    * @param array $widget_settings
74    *   A list of widget settings that will be added to the widget defaults.
75    */
76   public function createFileField($name, $entity_type, $bundle, $storage_settings = [], $field_settings = [], $widget_settings = []) {
77     $field_storage = FieldStorageConfig::create([
78       'entity_type' => $entity_type,
79       'field_name' => $name,
80       'type' => 'file',
81       'settings' => $storage_settings,
82       'cardinality' => !empty($storage_settings['cardinality']) ? $storage_settings['cardinality'] : 1,
83     ]);
84     $field_storage->save();
85
86     $this->attachFileField($name, $entity_type, $bundle, $field_settings, $widget_settings);
87     return $field_storage;
88   }
89
90   /**
91    * Attaches a file field to an entity.
92    *
93    * @param string $name
94    *   The name of the new field (all lowercase), exclude the "field_" prefix.
95    * @param string $entity_type
96    *   The entity type this field will be added to.
97    * @param string $bundle
98    *   The bundle this field will be added to.
99    * @param array $field_settings
100    *   A list of field settings that will be added to the defaults.
101    * @param array $widget_settings
102    *   A list of widget settings that will be added to the widget defaults.
103    */
104   public function attachFileField($name, $entity_type, $bundle, $field_settings = [], $widget_settings = []) {
105     $field = [
106       'field_name' => $name,
107       'label' => $name,
108       'entity_type' => $entity_type,
109       'bundle' => $bundle,
110       'required' => !empty($field_settings['required']),
111       'settings' => $field_settings,
112     ];
113     FieldConfig::create($field)->save();
114
115     entity_get_form_display($entity_type, $bundle, 'default')
116       ->setComponent($name, [
117         'type' => 'file_generic',
118         'settings' => $widget_settings,
119       ])
120       ->save();
121     // Assign display settings.
122     entity_get_display($entity_type, $bundle, 'default')
123       ->setComponent($name, [
124         'label' => 'hidden',
125         'type' => 'file_default',
126       ])
127       ->save();
128   }
129
130   /**
131    * Updates an existing file field with new settings.
132    */
133   public function updateFileField($name, $type_name, $field_settings = [], $widget_settings = []) {
134     $field = FieldConfig::loadByName('node', $type_name, $name);
135     $field->setSettings(array_merge($field->getSettings(), $field_settings));
136     $field->save();
137
138     entity_get_form_display('node', $type_name, 'default')
139       ->setComponent($name, [
140         'settings' => $widget_settings,
141       ])
142       ->save();
143   }
144
145   /**
146    * Uploads a file to a node.
147    *
148    * @param \Drupal\file\FileInterface $file
149    *   The File to be uploaded.
150    * @param string $field_name
151    *   The name of the field on which the files should be saved.
152    * @param $nid_or_type
153    *   A numeric node id to upload files to an existing node, or a string
154    *   indicating the desired bundle for a new node.
155    * @param bool $new_revision
156    *   The revision number.
157    * @param array $extras
158    *   Additional values when a new node is created.
159    *
160    * @return int
161    *   The node id.
162    */
163   public function uploadNodeFile(FileInterface $file, $field_name, $nid_or_type, $new_revision = TRUE, array $extras = []) {
164     return $this->uploadNodeFiles([$file], $field_name, $nid_or_type, $new_revision, $extras);
165   }
166
167   /**
168    * Uploads multiple files to a node.
169    *
170    * @param \Drupal\file\FileInterface[] $files
171    *   The files to be uploaded.
172    * @param string $field_name
173    *   The name of the field on which the files should be saved.
174    * @param $nid_or_type
175    *   A numeric node id to upload files to an existing node, or a string
176    *   indicating the desired bundle for a new node.
177    * @param bool $new_revision
178    *   The revision number.
179    * @param array $extras
180    *   Additional values when a new node is created.
181    *
182    * @return int
183    *   The node id.
184    */
185   public function uploadNodeFiles(array $files, $field_name, $nid_or_type, $new_revision = TRUE, array $extras = []) {
186     $edit = [
187       'title[0][value]' => $this->randomMachineName(),
188       'revision' => (string) (int) $new_revision,
189     ];
190
191     $node_storage = $this->container->get('entity.manager')->getStorage('node');
192     if (is_numeric($nid_or_type)) {
193       $nid = $nid_or_type;
194       $node_storage->resetCache([$nid]);
195       $node = $node_storage->load($nid);
196     }
197     else {
198       // Add a new node.
199       $extras['type'] = $nid_or_type;
200       $node = $this->drupalCreateNode($extras);
201       $nid = $node->id();
202       // Save at least one revision to better simulate a real site.
203       $node->setNewRevision();
204       $node->save();
205       $node_storage->resetCache([$nid]);
206       $node = $node_storage->load($nid);
207       $this->assertNotEqual($nid, $node->getRevisionId(), 'Node revision exists.');
208     }
209
210     // Attach files to the node.
211     $field_storage = FieldStorageConfig::loadByName('node', $field_name);
212     // File input name depends on number of files already uploaded.
213     $field_num = count($node->{$field_name});
214     $name = 'files[' . $field_name . "_$field_num]";
215     if ($field_storage->getCardinality() != 1) {
216       $name .= '[]';
217     }
218     foreach ($files as $file) {
219       $file_path = $this->container->get('file_system')->realpath($file->getFileUri());
220       if (count($files) == 1) {
221         $edit[$name] = $file_path;
222       }
223       else {
224         $edit[$name][] = $file_path;
225       }
226     }
227     $this->drupalPostForm("node/$nid/edit", $edit, t('Save and keep published'));
228
229     return $nid;
230   }
231
232   /**
233    * Removes a file from a node.
234    *
235    * Note that if replacing a file, it must first be removed then added again.
236    */
237   public function removeNodeFile($nid, $new_revision = TRUE) {
238     $edit = [
239       'revision' => (string) (int) $new_revision,
240     ];
241
242     $this->drupalPostForm('node/' . $nid . '/edit', [], t('Remove'));
243     $this->drupalPostForm(NULL, $edit, t('Save and keep published'));
244   }
245
246   /**
247    * Replaces a file within a node.
248    */
249   public function replaceNodeFile($file, $field_name, $nid, $new_revision = TRUE) {
250     $edit = [
251       'files[' . $field_name . '_0]' => drupal_realpath($file->getFileUri()),
252       'revision' => (string) (int) $new_revision,
253     ];
254
255     $this->drupalPostForm('node/' . $nid . '/edit', [], t('Remove'));
256     $this->drupalPostForm(NULL, $edit, t('Save and keep published'));
257   }
258
259   /**
260    * Asserts that a file exists physically on disk.
261    *
262    * Overrides PHPUnit_Framework_Assert::assertFileExists() to also work with
263    * file entities.
264    *
265    * @param \Drupal\File\FileInterface|string $file
266    *   Either the file entity or the file URI.
267    * @param string $message
268    *   (optional) A message to display with the assertion.
269    */
270   public static function assertFileExists($file, $message = NULL) {
271     $message = isset($message) ? $message : format_string('File %file exists on the disk.', ['%file' => $file->getFileUri()]);
272     $filename = $file instanceof FileInterface ? $file->getFileUri() : $file;
273     parent::assertFileExists($filename, $message);
274   }
275
276   /**
277    * Asserts that a file exists in the database.
278    */
279   public function assertFileEntryExists($file, $message = NULL) {
280     $this->container->get('entity.manager')->getStorage('file')->resetCache();
281     $db_file = File::load($file->id());
282     $message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', ['%file' => $file->getFileUri()]);
283     $this->assertEqual($db_file->getFileUri(), $file->getFileUri(), $message);
284   }
285
286   /**
287    * Asserts that a file does not exist on disk.
288    *
289    * Overrides PHPUnit_Framework_Assert::assertFileExists() to also work with
290    * file entities.
291    *
292    * @param \Drupal\File\FileInterface|string $file
293    *   Either the file entity or the file URI.
294    * @param string $message
295    *   (optional) A message to display with the assertion.
296    */
297   public static function assertFileNotExists($file, $message = NULL) {
298     $message = isset($message) ? $message : format_string('File %file exists on the disk.', ['%file' => $file->getFileUri()]);
299     $filename = $file instanceof FileInterface ? $file->getFileUri() : $file;
300     parent::assertFileNotExists($filename, $message);
301   }
302
303   /**
304    * Asserts that a file does not exist in the database.
305    */
306   public function assertFileEntryNotExists($file, $message) {
307     $this->container->get('entity.manager')->getStorage('file')->resetCache();
308     $message = isset($message) ? $message : format_string('File %file exists in database at the correct path.', ['%file' => $file->getFileUri()]);
309     $this->assertFalse(File::load($file->id()), $message);
310   }
311
312   /**
313    * Asserts that a file's status is set to permanent in the database.
314    */
315   public function assertFileIsPermanent(FileInterface $file, $message = NULL) {
316     $message = isset($message) ? $message : format_string('File %file is permanent.', ['%file' => $file->getFileUri()]);
317     $this->assertTrue($file->isPermanent(), $message);
318   }
319
320 }