Project

General

Profile

Paste
Download (66.1 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / file_entity / file_entity.test @ a8cee257

1
<?php
2

    
3
/**
4
 * @file
5
 * Test integration for the file_entity module.
6
 */
7

    
8
class FileEntityTestHelper extends DrupalWebTestCase {
9
  function setUp() {
10
    $modules = func_get_args();
11
    if (isset($modules[0]) && is_array($modules[0])) {
12
      $modules = $modules[0];
13
    }
14
    $modules[] = 'file_entity';
15
    parent::setUp($modules);
16
  }
17

    
18
  /**
19
   * Retrieves a sample file of the specified type.
20
   */
21
  function getTestFile($type_name, $size = NULL) {
22
    // Get a file to upload.
23
    $file = current($this->drupalGetTestFiles($type_name, $size));
24

    
25
    // Add a filesize property to files as would be read by file_load().
26
    $file->filesize = filesize($file->uri);
27

    
28
    return $file;
29
  }
30

    
31
  /**
32
   * Retrieves the fid of the last inserted file.
33
   */
34
  function getLastFileId() {
35
    return (int) db_query('SELECT MAX(fid) FROM {file_managed}')->fetchField();
36
  }
37

    
38
  /**
39
   * Get a file from the database based on its filename.
40
   *
41
   * @param $filename
42
   *   A file filename, usually generated by $this->randomName().
43
   * @param $reset
44
   *   (optional) Whether to reset the internal file_load() cache.
45
   *
46
   * @return
47
   *   A file object matching $filename.
48
   */
49
  function getFileByFilename($filename, $reset = FALSE) {
50
    $files = file_load_multiple(array(), array('filename' => $filename), $reset);
51
    // Load the first file returned from the database.
52
    $returned_file = reset($files);
53
    return $returned_file;
54
  }
55

    
56
  protected function createFileEntity($settings = array()) {
57
    // Populate defaults array.
58
    $settings += array(
59
      'filepath' => 'Файл для тестирования ' . $this->randomName(), // Prefix with non-latin characters to ensure that all file-related tests work with international filenames.
60
      'filemime' => 'text/plain',
61
      'uid' => 1,
62
      'timestamp' => REQUEST_TIME,
63
      'status' => FILE_STATUS_PERMANENT,
64
      'contents' => "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.",
65
      'scheme' => file_default_scheme(),
66
      'type' => NULL,
67
    );
68

    
69
    $filepath = $settings['scheme'] . '://' . $settings['filepath'];
70

    
71
    file_put_contents($filepath, $settings['contents']);
72
    $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
73

    
74
    $file = new stdClass();
75
    $file->uri = $filepath;
76
    $file->filename = drupal_basename($file->uri);
77
    $file->filemime = $settings['filemime'];
78
    $file->uid = $settings['uid'];
79
    $file->timestamp = $settings['timestamp'];
80
    $file->filesize = filesize($file->uri);
81
    $file->status = $settings['status'];
82
    $file->type = $settings['type'];
83

    
84
    // The file type is used as a bundle key, and therefore, must not be NULL.
85
    if (!isset($file->type)) {
86
      $file->type = FILE_TYPE_NONE;
87
    }
88

    
89
    // If the file isn't already assigned a real type, determine what type should
90
    // be assigned to it.
91
    if ($file->type === FILE_TYPE_NONE) {
92
      $type = file_get_type($file);
93
      if (isset($type)) {
94
        $file->type = $type;
95
      }
96
    }
97

    
98
    // Write the record directly rather than calling file_save() so we don't
99
    // invoke the hooks.
100
    $this->assertNotIdentical(drupal_write_record('file_managed', $file), FALSE, t('The file was added to the database.'), 'Create test file');
101

    
102
    return $file;
103
  }
104

    
105
  protected function createFileType($overrides = array()) {
106
    $type = new stdClass();
107
    $type->type = 'test';
108
    $type->label = "Test";
109
    $type->description = '';
110
    $type->mimetypes = array('image/jpeg', 'image/gif', 'image/png', 'image/tiff');
111

    
112
    foreach ($overrides as $k => $v) {
113
      $type->$k = $v;
114
    }
115

    
116
    file_type_save($type);
117
    return $type;
118
  }
119

    
120
  /**
121
   * Overrides DrupalWebTestCase::drupalGetToken() to support the hash salt.
122
   *
123
   * @todo Remove when http://drupal.org/node/1555862 is fixed in core.
124
   */
125
  protected function drupalGetToken($value = '') {
126
    $private_key = drupal_get_private_key();
127
    return drupal_hmac_base64($value, $this->session_id . $private_key . drupal_get_hash_salt());
128
  }
129
}
130

    
131
/**
132
 * Tests file type classification functionality.
133
 */
134
class FileEntityFileTypeClassificationTestCase extends DrupalWebTestCase {
135
  public static function getInfo() {
136
    return array(
137
      'name' => 'File entity classification',
138
      'description' => 'Test existing file entity classification functionality.',
139
      'group' => 'File entity',
140
    );
141
  }
142

    
143
  function setUp() {
144
    parent::setUp();
145
  }
146

    
147
  /**
148
   * Test that existing files are properly classified by file type.
149
   */
150
  function testFileTypeClassification() {
151
    // Get test text and image files.
152
    $file = current($this->drupalGetTestFiles('text'));
153
    $text_file = file_save($file);
154
    $file = current($this->drupalGetTestFiles('image'));
155
    $image_file = file_save($file);
156

    
157
    // Enable file entity which adds adds a file type property to files and
158
    // queues up existing files for classification.
159
    module_enable(array('file_entity'));
160

    
161
    // Existing files have yet to be classified and should have an undefined
162
    // file type.
163
    $file_type = $this->getFileType($text_file);
164
    $this->assertEqual($file_type['type'], 'undefined', t('The text file has an undefined file type.'));
165
    $file_type = $this->getFileType($image_file);
166
    $this->assertEqual($file_type['type'], 'undefined', t('The image file has an undefined file type.'));
167

    
168
    // The classification queue is processed during cron runs. Run cron to
169
    // trigger the classification process.
170
    $this->cronRun();
171

    
172
    // The classification process should assign a file type to any file whose
173
    // MIME type is assigned to a file type. Check to see if each file was
174
    // assigned a proper file type.
175
    $file_type = $this->getFileType($text_file);
176
    $this->assertEqual($file_type['type'], 'document', t('The text file was properly assigned the Document file type.'));
177
    $file_type = $this->getFileType($image_file);
178
    $this->assertEqual($file_type['type'], 'image', t('The image file was properly assigned the Image file type.'));
179
  }
180

    
181
  /**
182
   * Get the file type of a given file.
183
   *
184
   * @param $file
185
   *   A file object.
186
   *
187
   * @return
188
   *   The file's file type as a string.
189
   */
190
  function getFileType($file) {
191
    $type = db_select('file_managed', 'fm')
192
      ->fields('fm', array('type'))
193
      ->condition('fid', $file->fid, '=')
194
      ->execute()
195
      ->fetchAssoc();
196

    
197
    return $type;
198
  }
199
}
200

    
201
/**
202
 * Tests basic file entity functionality.
203
 */
204
class FileEntityUnitTestCase extends FileEntityTestHelper {
205
  public static function getInfo() {
206
    return array(
207
      'name' => 'File entity unit tests',
208
      'description' => 'Test basic file entity functionality.',
209
      'group' => 'File entity',
210
    );
211
  }
212

    
213
  /**
214
   * Regression tests for core issue http://drupal.org/node/1239376.
215
   */
216
  function testMimeTypeMappings() {
217
    $tests = array(
218
      'public://test.ogg' => 'audio/ogg',
219
      'public://test.mkv' => 'video/x-m4v',
220
      'public://test.mka' => 'audio/x-matroska',
221
      'public://test.mkv' => 'video/x-matroska',
222
      'public://test.webp' => 'image/webp',
223
    );
224
    foreach ($tests as $input => $expected) {
225
      $this->assertEqual(file_get_mimetype($input), $expected);
226
    }
227
  }
228

    
229
  /**
230
   * Tests basic file entity properties.
231
   */
232
  function testFileEntity() {
233
    // Save a raw file, turning it into a file entity.
234
    $file = $this->getTestFile('text');
235
    $file->uid = 1;
236
    $file->status = FILE_STATUS_PERMANENT;
237
    file_save($file);
238

    
239
    // Test entity ID, revision ID, and bundle.
240
    $ids = entity_extract_ids('file', $file);
241
    $this->assertIdentical($ids, array($file->fid, NULL, 'document'));
242

    
243
    // Test the entity URI callback.
244
    $uri = entity_uri('file', $file);
245
    $this->assertEqual($uri['path'], "file/{$file->fid}");
246
  }
247

    
248
  /**
249
   * Tests storing image height and width as file metadata.
250
   */
251
  function testImageDimensions() {
252
    // Test hook_file_insert().
253
    $file = current($this->drupalGetTestFiles('image'));
254
    $image_file = file_save($file);
255
    $this->assertTrue(isset($image_file->metadata['height']), 'Image height retrieved on file_save() for an image file.');
256
    $this->assertTrue(isset($image_file->metadata['width']), 'Image width retrieved on file_save() for an image file.');
257

    
258
    $file = current($this->drupalGetTestFiles('text'));
259
    $text_file = file_save($file);
260
    $this->assertFalse(isset($text_file->metadata['height']), 'No image height retrieved on file_save() for an text file.');
261
    $this->assertFalse(isset($text_file->metadata['width']), 'No image width retrieved on file_save() for an text file.');
262

    
263
    // Test hook_file_load().
264
    // Clear the cache and load fresh files objects to test file_load behavior.
265
    entity_get_controller('file')->resetCache();
266

    
267
    $file = file_load($image_file->fid);
268
    $this->assertTrue(isset($file->metadata['height']), 'Image dimensions retrieved on file_load() for an image file.');
269
    $this->assertTrue(isset($file->metadata['width']), 'Image dimensions retrieved on file_load() for an image file.');
270

    
271
    $this->assertEqual($file->metadata['height'], $image_file->metadata['height'], 'Loaded image height is equal to saved image height.');
272
    $this->assertEqual($file->metadata['width'], $image_file->metadata['width'], 'Loaded image width is equal to saved image width.');
273

    
274
    $file = file_load($text_file->fid);
275
    $this->assertFalse(isset($file->metadata['height']), 'No image height retrieved on file_load() for an text file.');
276
    $this->assertFalse(isset($file->metadata['width']), 'No image width retrieved on file_load() for an text file.');
277

    
278
    // Test hook_file_update().
279
    // Load the first image file and resize it.
280
    $height = $image_file->metadata['width'] / 2;
281
    $width = $image_file->metadata['height'] / 2;
282
    $image = image_load($image_file->uri);
283
    image_resize($image, $width, $height);
284
    image_save($image);
285
    file_save($image_file);
286

    
287
    $this->assertEqual($image_file->metadata['height'], $height, 'Image file height updated by file_save().');
288
    $this->assertEqual($image_file->metadata['width'], $width, 'Image file width updated by file_save().');
289

    
290
    // Clear the cache and reload the file.
291
    entity_get_controller('file')->resetCache();
292

    
293
    $file = file_load($image_file->fid);
294
    $this->assertEqual($file->metadata['height'], $height, 'Updated image height retrieved by file_load().');
295
    $this->assertEqual($file->metadata['width'], $width, 'Updated image width retrieved by file_load().');
296

    
297
    // Verify that the image dimension metadata is removed on file deletion.
298
    file_delete($file, TRUE);
299
    $this->assertFalse(db_query('SELECT COUNT(*) FROM {file_metadata} WHERE fid = :fid', array(':fid' => 'fid'))->fetchField(), 'Row deleted in {file_metadata} on file_delete().');
300
  }
301
}
302

    
303
/**
304
 * Tests editing existing file entities.
305
 */
306
class FileEntityEditTestCase extends FileEntityTestHelper {
307
  protected $web_user;
308
  protected $admin_user;
309

    
310
  public static function getInfo() {
311
    return array(
312
      'name' => 'File entity edit',
313
      'description' => 'Create a file and test file edit functionality.',
314
      'group' => 'File entity',
315
    );
316
  }
317

    
318
  function setUp() {
319
    parent::setUp();
320

    
321
    $this->web_user = $this->drupalCreateUser(array('edit own document files', 'create files'));
322
    $this->admin_user = $this->drupalCreateUser(array('bypass file access', 'administer files'));
323
  }
324

    
325
  /**
326
   * Check file edit functionality.
327
   */
328
  function testFileEntityEdit() {
329
    $this->drupalLogin($this->web_user);
330

    
331
    $test_file = $this->getTestFile('text');
332
    $name_key = "filename";
333

    
334
    // Create file to edit.
335
    $edit = array();
336
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
337
    $this->drupalPost('file/add', $edit, t('Next'));
338
    if ($this->xpath('//input[@name="scheme"]')) {
339
      $this->drupalPost(NULL, array(), t('Next'));
340
    }
341

    
342
    // Check that the file exists in the database.
343
    $file = $this->getFileByFilename($test_file->filename);
344
    $this->assertTrue($file, t('File found in database.'));
345

    
346
    // Check that "edit" link points to correct page.
347
    $this->clickLink(t('Edit'));
348
    $edit_url = url("file/$file->fid/edit", array('absolute' => TRUE));
349
    $actual_url = $this->getURL();
350
    $this->assertEqual($edit_url, $actual_url, t('On edit page.'));
351

    
352
    // Check that the name field is displayed with the correct value.
353
    $active = '<span class="element-invisible">' . t('(active tab)') . '</span>';
354
    $link_text = t('!local-task-title!active', array('!local-task-title' => t('Edit'), '!active' => $active));
355
    $this->assertText(strip_tags($link_text), 0, t('Edit tab found and marked active.'));
356
    $this->assertFieldByName($name_key, $file->filename, t('Name field displayed.'));
357

    
358
    // The user does not have "delete" permissions so no delete button should be found.
359
    $this->assertNoFieldByName('op', t('Delete'), 'Delete button not found.');
360

    
361
    // Edit the content of the file.
362
    $edit = array();
363
    $edit[$name_key] = $this->randomName(8);
364
    // Stay on the current page, without reloading.
365
    $this->drupalPost(NULL, $edit, t('Save'));
366

    
367
    // Check that the name field is displayed with the updated values.
368
    $this->assertText($edit[$name_key], t('Name displayed.'));
369
  }
370

    
371
  /**
372
   * Check changing file associated user fields.
373
   */
374
  function testFileEntityAssociatedUser() {
375
    $this->drupalLogin($this->admin_user);
376

    
377
    // Create file to edit.
378
    $test_file = $this->getTestFile('text');
379
    $name_key = "filename";
380
    $edit = array();
381
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
382
    $this->drupalPost('file/add', $edit, t('Next'));
383

    
384
    // Check that the file was associated with the currently logged in user.
385
    $file = $this->getFileByFilename($test_file->filename);
386
    $this->assertIdentical($file->uid, $this->admin_user->uid, 'File associated with admin user.');
387

    
388
    // Try to change the 'associated user' field to an invalid user name.
389
    $edit = array(
390
      'name' => 'invalid-name',
391
    );
392
    $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
393
    $this->assertText('The username invalid-name does not exist.');
394

    
395
    // Change the associated user field to an empty string, which should assign
396
    // association to the anonymous user (uid 0).
397
    $edit['name'] = '';
398
    $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
399
    $file = file_load($file->fid);
400
    $this->assertIdentical($file->uid, '0', 'File associated with anonymous user.');
401

    
402
    // Change the associated user field to another user's name (that is not
403
    // logged in).
404
    $edit['name'] = $this->web_user->name;
405
    $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
406
    $file = file_load($file->fid);
407
    $this->assertIdentical($file->uid, $this->web_user->uid, 'File associated with normal user.');
408

    
409
    // Check that normal users cannot change the associated user information.
410
    $this->drupalLogin($this->web_user);
411
    $this->drupalGet('file/' . $file->fid . '/edit');
412
    $this->assertNoFieldByName('name');
413
  }
414
}
415

    
416
/**
417
 * Tests creating new file entities through the file upload wizard.
418
 */
419
class FileEntityUploadWizardTestCase extends FileEntityTestHelper {
420
  public static function getInfo() {
421
    return array(
422
      'name' => 'File entity upload wizard',
423
      'description' => 'Upload a file using the multi-step wizard.',
424
      'group' => 'File entity',
425
      'dependencies' => array('token'),
426
    );
427
  }
428

    
429
  function setUp() {
430
    parent::setUp('token');
431

    
432
    // Disable the private file system which is automatically enabled by
433
    // DrupalTestCase so we can test the upload wizard correctly.
434
    variable_del('file_private_path');
435

    
436
    $web_user = $this->drupalCreateUser(array('create files', 'view own private files'));
437
    $this->drupalLogin($web_user);
438
  }
439

    
440
  /**
441
   * Test the basic file upload wizard functionality.
442
   */
443
  function testFileEntityUploadWizardBasic() {
444
    $test_file = $this->getTestFile('text');
445

    
446
    // Step 1: Upload a basic document file.
447
    $edit = array();
448
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
449
    $this->drupalPost('file/add', $edit, t('Next'));
450

    
451
    // Check that the file exists in the database.
452
    $fid = $this->getLastFileId();
453
    $file = file_load($fid);
454
    $this->assertTrue($file, t('File found in database.'));
455

    
456
    // Check that the document file has been uploaded.
457
    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document', '%name' => $file->filename)), t('Document file uploaded.'));
458
  }
459

    
460
  /**
461
   * Test the file upload wizard type step.
462
   */
463
  function testFileEntityUploadWizardTypes() {
464
    $test_file = $this->getTestFile('text');
465

    
466
    // Create multiple file types with the same mime types.
467
    $this->createFileType(array('type' => 'document1', 'label' => 'Document 1', 'mimetypes' => array('text/plain')));
468
    $this->createFileType(array('type' => 'document2', 'label' => 'Document 2', 'mimetypes' => array('text/plain')));
469

    
470
    // Step 1: Upload a basic document file.
471
    $edit = array();
472
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
473
    $this->drupalPost('file/add', $edit, t('Next'));
474

    
475
    // Step 2: File type selection.
476
    $edit = array();
477
    $edit['type'] = 'document2';
478
    $this->drupalPost(NULL, $edit, t('Next'));
479

    
480
    // Check that the file exists in the database.
481
    $fid = $this->getLastFileId();
482
    $file = file_load($fid);
483
    $this->assertTrue($file, t('File found in database.'));
484

    
485
    // Check that the document file has been uploaded.
486
    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document 2', '%name' => $file->filename)), t('Document 2 file uploaded.'));
487
  }
488

    
489
  /**
490
   * Test the file upload wizard scheme step.
491
   */
492
  function testFileEntityUploadWizardSchemes() {
493
    $test_file = $this->getTestFile('text');
494

    
495
    // Enable the private file system.
496
    variable_set('file_private_path', $this->private_files_directory);
497

    
498
    // Step 1: Upload a basic document file.
499
    $edit = array();
500
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
501
    $this->drupalPost('file/add', $edit, t('Next'));
502

    
503
    // Step 3: Scheme selection.
504
    $edit = array();
505
    $edit['scheme'] = 'private';
506
    $this->drupalPost(NULL, $edit, t('Next'));
507

    
508
    // Check that the file exists in the database.
509
    $fid = $this->getLastFileId();
510
    $file = file_load($fid);
511
    $this->assertTrue($file, t('File found in database.'));
512

    
513
    // Check that the document file has been uploaded.
514
    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Document', '%name' => $file->filename)), t('Document file uploaded.'));
515
  }
516

    
517
  /**
518
   * Test the file upload wizard field step.
519
   */
520
  function testFileEntityUploadWizardFields() {
521
    $test_file = $this->getTestFile('image');
522
    $filename = $this->randomName();
523
    $alt = $this->randomName();
524
    $title = $this->randomName();
525

    
526
    // Step 1: Upload a basic image file.
527
    $edit = array();
528
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
529
    $this->drupalPost('file/add', $edit, t('Next'));
530

    
531
    // Step 4: Attached fields.
532
    $edit = array();
533
    $edit['filename'] = $filename;
534
    $edit['field_file_image_alt_text[' . LANGUAGE_NONE . '][0][value]'] = $alt;
535
    $edit['field_file_image_title_text[' . LANGUAGE_NONE . '][0][value]'] = $title;
536
    $this->drupalPost(NULL, $edit, t('Save'));
537

    
538
    // Check that the file exists in the database.
539
    $fid = $this->getLastFileId();
540
    $file = file_load($fid);
541
    $this->assertTrue($file, t('File found in database.'));
542

    
543
    // Check that the image file has been uploaded.
544
    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Image', '%name' => $filename)), t('Image file uploaded.'));
545

    
546
    // Check that the alt and title text was loaded from the fields.
547
    $this->assertEqual($file->alt, $alt, t('Alt text was stored as file metadata.'));
548
    $this->assertEqual($file->title, $title, t('Title text was stored as file metadata.'));
549
  }
550

    
551
  /**
552
   * Test skipping each of the file upload wizard steps.
553
   */
554
  function testFileEntityUploadWizardStepSkipping() {
555
    $test_file = $this->getTestFile('image');
556
    $filename = $this->randomName();
557

    
558
    // Ensure that the file is affected by every step.
559
    variable_set('file_private_path', $this->private_files_directory);
560

    
561
    $this->createFileType(array('type' => 'image1', 'label' => 'Image 1', 'mimetypes' => array('image/jpeg', 'image/gif', 'image/png', 'image/tiff')));
562
    $this->createFileType(array('type' => 'image2', 'label' => 'Image 2', 'mimetypes' => array('image/jpeg', 'image/gif', 'image/png', 'image/tiff')));
563

    
564
    $field_name = drupal_strtolower($this->randomName() . '_field_name');
565
    $field = array('field_name' => $field_name, 'type' => 'text');
566
    field_create_field($field);
567
    $instance = array(
568
      'field_name' => $field_name,
569
      'entity_type' => 'file',
570
      'bundle' => 'image2',
571
      'label' => $this->randomName() . '_label',
572
    );
573
    field_create_instance($instance);
574

    
575
    // Test skipping each upload wizard step.
576
    foreach (array('types', 'schemes', 'fields') as $step) {
577
      // Step to skip.
578
      switch ($step) {
579
        case 'types':
580
          variable_set('file_entity_file_upload_wizard_skip_file_type', TRUE);
581
          break;
582
        case 'schemes':
583
          variable_set('file_entity_file_upload_wizard_skip_scheme', TRUE);
584
          break;
585
        case 'fields':
586
          variable_set('file_entity_file_upload_wizard_skip_fields', TRUE);
587
          break;
588
      }
589

    
590
      // Step 1: Upload a basic image file.
591
      $edit = array();
592
      $edit['files[upload]'] = drupal_realpath($test_file->uri);
593
      $this->drupalPost('file/add', $edit, t('Next'));
594

    
595
      // Step 2: File type selection.
596
      if ($step != 'types') {
597
        $edit = array();
598
        $edit['type'] = 'image2';
599
        $this->drupalPost(NULL, $edit, t('Next'));
600
      }
601

    
602
      // Step 3: Scheme selection.
603
      if ($step != 'schemes') {
604
        $edit = array();
605
        $edit['scheme'] = 'private';
606
        $this->drupalPost(NULL, $edit, t('Next'));
607
      }
608

    
609
      // Step 4: Attached fields.
610
      if ($step != 'fields') {
611
        // Skipping file type selection essentially skips this step as well
612
        // because the file will not be assigned a type so no fields will be
613
        // available.
614
        if ($step != 'types') {
615
          $edit = array();
616
          $edit['filename'] = $filename;
617
          $edit[$field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $this->randomName();
618
          $this->drupalPost(NULL, $edit, t('Save'));
619
        }
620
      }
621

    
622
      // Check that the file exists in the database.
623
      $fid = $this->getLastFileId();
624
      $file = file_load($fid);
625
      $this->assertTrue($file, t('File found in database.'));
626

    
627
      // Determine the file's file type.
628
      $type = file_type_load($file->type);
629

    
630
      // Check that the image file has been uploaded.
631
      $this->assertRaw(t('!type %name was uploaded.', array('!type' => $type->label, '%name' => $file->filename)), t('Image file uploaded.'));
632

    
633
      // Reset 'skip' variables.
634
      variable_del('file_entity_file_upload_wizard_skip_file_type');
635
      variable_del('file_entity_file_upload_wizard_skip_scheme');
636
      variable_del('file_entity_file_upload_wizard_skip_fields');
637
    }
638
  }
639
}
640

    
641
/**
642
 * Test file administration page functionality.
643
 */
644
class FileEntityAdminTestCase extends FileEntityTestHelper {
645
  public static function getInfo() {
646
    return array(
647
      'name' => 'File administration',
648
      'description' => 'Test file administration page functionality.',
649
      'group' => 'File entity',
650
    );
651
  }
652

    
653
  function setUp() {
654
    parent::setUp();
655

    
656
    // Remove the "view files" permission which is set
657
    // by default for all users so we can test this permission
658
    // correctly.
659
    $roles = user_roles();
660
    foreach ($roles as $rid => $role) {
661
      user_role_revoke_permissions($rid, array('view files'));
662
    }
663

    
664
    $this->admin_user = $this->drupalCreateUser(array('administer files', 'bypass file access'));
665
    $this->base_user_1 = $this->drupalCreateUser(array('administer files'));
666
    $this->base_user_2 = $this->drupalCreateUser(array('administer files', 'view own private files'));
667
    $this->base_user_3 = $this->drupalCreateUser(array('administer files', 'view private files'));
668
    $this->base_user_4 = $this->drupalCreateUser(array('administer files', 'edit any document files', 'delete any document files', 'edit any image files', 'delete any image files'));
669
  }
670

    
671
  /**
672
   * Tests that the table sorting works on the files admin pages.
673
   */
674
  function testFilesAdminSort() {
675
    $this->drupalLogin($this->admin_user);
676
    $i = 0;
677
    foreach (array('dd', 'aa', 'DD', 'bb', 'cc', 'CC', 'AA', 'BB') as $prefix) {
678
      $this->createFileEntity(array('filepath' => $prefix . $this->randomName(6), 'timestamp' => $i));
679
      $i++;
680
    }
681

    
682
    // Test that the default sort by file_managed.timestamp DESC actually fires properly.
683
    $files_query = db_select('file_managed', 'fm')
684
      ->fields('fm', array('fid'))
685
      ->orderBy('timestamp', 'DESC')
686
      ->execute()
687
      ->fetchCol();
688

    
689
    $files_form = array();
690
    $this->drupalGet('admin/content/file');
691
    foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
692
      $files_form[] = $input;
693
    }
694
    $this->assertEqual($files_query, $files_form, 'Files are sorted in the form according to the default query.');
695

    
696
    // Compare the rendered HTML node list to a query for the files ordered by
697
    // filename to account for possible database-dependent sort order.
698
    $files_query = db_select('file_managed', 'fm')
699
      ->fields('fm', array('fid'))
700
      ->orderBy('filename')
701
      ->execute()
702
      ->fetchCol();
703

    
704
    $files_form = array();
705
    $this->drupalGet('admin/content/file', array('query' => array('sort' => 'asc', 'order' => 'Title')));
706
    foreach ($this->xpath('//table/tbody/tr/td/div/input/@value') as $input) {
707
      $files_form[] = $input;
708
    }
709
    $this->assertEqual($files_query, $files_form, 'Files are sorted in the form the same as they are in the query.');
710
  }
711

    
712
  /**
713
   * Tests files overview with different user permissions.
714
   */
715
  function testFilesAdminPages() {
716
    $this->drupalLogin($this->admin_user);
717

    
718
    $files['public_image'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
719
    $files['public_document'] = $this->createFileEntity(array('scheme' => 'public', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
720
    $files['private_image'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_1->uid, 'type' => 'image'));
721
    $files['private_document'] = $this->createFileEntity(array('scheme' => 'private', 'uid' => $this->base_user_2->uid, 'type' => 'document'));
722

    
723
    // Verify view, usage, edit, and delete links for any file.
724
    $this->drupalGet('admin/content/file');
725
    $this->assertResponse(200);
726
    foreach ($files as $file) {
727
      $this->assertLinkByHref('file/' . $file->fid);
728
      $this->assertLinkByHref('file/' . $file->fid . '/usage');
729
      $this->assertLinkByHref('file/' . $file->fid . '/edit');
730
      $this->assertLinkByHref('file/' . $file->fid . '/delete');
731
      // Verify tableselect.
732
      $this->assertFieldByName('files[' . $file->fid . ']', '', t('Tableselect found.'));
733
    }
734

    
735
    // Verify no operation links are displayed for regular users.
736
    $this->drupalLogout();
737
    $this->drupalLogin($this->base_user_1);
738
    $this->drupalGet('admin/content/file');
739
    $this->assertResponse(200);
740
    $this->assertLinkByHref('file/' . $files['public_image']->fid);
741
    $this->assertLinkByHref('file/' . $files['public_document']->fid);
742
    $this->assertNoLinkByHref('file/' . $files['public_image']->fid . '/edit');
743
    $this->assertNoLinkByHref('file/' . $files['public_image']->fid . '/delete');
744
    $this->assertNoLinkByHref('file/' . $files['public_document']->fid . '/edit');
745
    $this->assertNoLinkByHref('file/' . $files['public_document']->fid . '/delete');
746

    
747
    // Verify no tableselect.
748
    $this->assertNoFieldByName('files[' . $files['public_image']->fid . ']', '', t('No tableselect found.'));
749

    
750
    // Verify private file is displayed with permission.
751
    $this->drupalLogout();
752
    $this->drupalLogin($this->base_user_2);
753
    $this->drupalGet('admin/content/file');
754
    $this->assertResponse(200);
755
    $this->assertLinkByHref('file/' . $files['private_document']->fid);
756
    // Verify no operation links are displayed.
757
    $this->assertNoLinkByHref('file/' . $files['private_document']->fid . '/edit');
758
    $this->assertNoLinkByHref('file/' . $files['private_document']->fid . '/delete');
759

    
760
    // Verify user cannot see private file of other users.
761
    $this->assertNoLinkByHref('file/' . $files['private_image']->fid);
762
    $this->assertNoLinkByHref('file/' . $files['private_image']->fid . '/edit');
763
    $this->assertNoLinkByHref('file/' . $files['private_image']->fid . '/delete');
764

    
765
    // Verify no tableselect.
766
    $this->assertNoFieldByName('files[' . $files['private_document']->fid . ']', '', t('No tableselect found.'));
767

    
768
    // Verify private file is displayed with permission.
769
    $this->drupalLogout();
770
    $this->drupalLogin($this->base_user_3);
771
    $this->drupalGet('admin/content/file');
772
    $this->assertResponse(200);
773

    
774
    // Verify user can see private file of other users.
775
    $this->assertLinkByHref('file/' . $files['private_document']->fid);
776
    $this->assertLinkByHref('file/' . $files['private_image']->fid);
777

    
778
    // Verify operation links are displayed for users with appropriate permission.
779
    $this->drupalLogout();
780
    $this->drupalLogin($this->base_user_4);
781
    $this->drupalGet('admin/content/file');
782
    $this->assertResponse(200);
783
    foreach ($files as $file) {
784
      $this->assertLinkByHref('file/' . $file->fid);
785
      $this->assertLinkByHref('file/' . $file->fid . '/usage');
786
      $this->assertLinkByHref('file/' . $file->fid . '/edit');
787
      $this->assertLinkByHref('file/' . $file->fid . '/delete');
788
    }
789

    
790
    // Verify file access can be bypassed.
791
    $this->drupalLogout();
792
    $this->drupalLogin($this->admin_user);
793
    $this->drupalGet('admin/content/file');
794
    $this->assertResponse(200);
795
    foreach ($files as $file) {
796
      $this->assertLinkByHref('file/' . $file->fid);
797
      $this->assertLinkByHref('file/' . $file->fid . '/usage');
798
      $this->assertLinkByHref('file/' . $file->fid . '/edit');
799
      $this->assertLinkByHref('file/' . $file->fid . '/delete');
800
    }
801
  }
802
}
803

    
804
/**
805
 * Tests the file usage page.
806
 */
807
class FileEntityUsageTestCase extends FileEntityTestHelper {
808
  public static function getInfo() {
809
    return array(
810
      'name' => 'File entity usage',
811
      'description' => 'Create a file and verify its usage.',
812
      'group' => 'File entity',
813
    );
814
  }
815

    
816
  function setUp() {
817
    parent::setUp();
818

    
819
    $web_user = $this->drupalCreateUser(array('create files', 'bypass file access', 'edit own article content'));
820
    $this->drupalLogin($web_user);
821
  }
822

    
823
  /**
824
   * Create a file and verify its usage information.
825
   */
826
  function testFileEntityUsagePage() {
827
    $image_field = 'field_image';
828
    $image = $this->getTestFile('image');
829

    
830
    // Create a node, save it, then edit it to upload a file.
831
    $edit = array(
832
      "files[" . $image_field . "_" . LANGUAGE_NONE . "_0]" => drupal_realpath($image->uri),
833
    );
834
    $node = $this->drupalCreateNode(array('type' => 'article'));
835
    $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
836

    
837
    // Load the uploaded file.
838
    $fid = $this->getLastFileId();
839
    $file = file_load($fid);
840

    
841
    // View the file's usage page.
842
    $this->drupalGet('file/' . $file->fid . '/usage');
843

    
844
    // Verify that a link to the entity is available.
845
    $this->assertLink($node->title);
846
    $this->assertLinkByHref('node/' . $node->nid);
847

    
848
    // Verify that the entity type and use count information is also present.
849
    $expected_values = array(
850
      'type' => 'node',
851
      'count' => 1,
852
    );
853
    foreach ($expected_values as $name => $value) {
854
      $this->assertTrue($this->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(':text' => $value)), t('File usage @name was found in the table.', array('@name' => $name)));
855
    }
856

    
857
    // Add a reference to the file from the same entity but registered by a
858
    // different module to ensure that the usage count is incremented and no
859
    // additional table rows are created.
860
    file_usage_add($file, 'example_module', 'node', $node->nid, 2);
861

    
862
    // Reload the page and verify that the expected values are present.
863
    $this->drupalGet('file/' . $file->fid . '/usage');
864
    $expected_values['count'] = 3;
865
    foreach ($expected_values as $name => $value) {
866
      $this->assertTrue($this->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(':text' => $value)), t('File usage @name was found in the table.', array('@name' => $name)));
867
    }
868

    
869
    // Add a reference to the file from an entity that doesn't exist to ensure
870
    // that this case is handled.
871
    file_usage_add($file, 'test_module', 'imaginary', 1);
872

    
873
    // Reload the page.
874
    $this->drupalGet('file/' . $file->fid . '/usage');
875

    
876
    // Verify that the module name is used in place of a link to the entity.
877
    $this->assertNoLink('test_module');
878
    $this->assertRaw('test_module', 'Module name used in place of link to the entity.');
879

    
880
    // Verify that the entity type and use count information is also present.
881
    $expected_values = array(
882
      'type' => 'imaginary',
883
      'count' => 1,
884
    );
885
    foreach ($expected_values as $name => $value) {
886
      $this->assertTrue($this->xpath('//table/tbody/tr/td[normalize-space(text())=:text]', array(':text' => $value)), t('File usage @name was found in the table.', array('@name' => $name)));
887
    }
888
  }
889
}
890

    
891
/**
892
 * Tests image alt and title text.
893
 */
894
class FileEntityAltTitleTestCase extends FileEntityTestHelper {
895
  public static function getInfo() {
896
    return array(
897
      'name' => 'File entity alt and title text',
898
      'description' => 'Create an image file with alt and title text.',
899
      'group' => 'File entity',
900
      'dependencies' => array('token'),
901
    );
902
  }
903

    
904
  function setUp() {
905
    parent::setUp('token');
906

    
907
    $web_user = $this->drupalCreateUser(array('create files', 'edit own image files'));
908
    $this->drupalLogin($web_user);
909
  }
910

    
911
  /**
912
   * Create an "image" file and verify its associated alt and title text.
913
   */
914
  function testFileEntityAltTitle() {
915
    $test_file = $this->getTestFile('image');
916
    $alt_field_name = 'field_file_image_alt_text'; // Name of the default alt text field added to the image file type.
917
    $title_field_name = 'field_file_image_title_text'; // Name of the default title text field added to the image file type.
918

    
919
    // Create a file.
920
    $edit = array();
921
    $edit['files[upload]'] = drupal_realpath($test_file->uri);
922
    $this->drupalPost('file/add', $edit, t('Next'));
923

    
924
    // Step 2: Scheme selection.
925
    if ($this->xpath('//input[@name="scheme"]')) {
926
      $this->drupalPost(NULL, array(), t('Next'));
927
    }
928

    
929
    // Step 3: Attached fields.
930
    $alt = 'Quote&quot; Amp&amp; ' . 'Файл для тестирования ' . $this->randomName(); // Generate alt text containing HTML entities, spaces and non-latin characters.
931
    $title = 'Quote&quot; Amp&amp; ' . 'Файл для тестирования ' . $this->randomName(); // Generate title text containing HTML entities, spaces and non-latin characters.
932

    
933
    $edit = array();
934
    $edit[$alt_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $alt;
935
    $edit[$title_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $title;
936
    $this->drupalPost(NULL, $edit, t('Save'));
937

    
938
    // Check that the image file has been uploaded.
939
    $this->assertRaw(t('!type %name was uploaded.', array('!type' => 'Image', '%name' => $test_file->filename)), t('Image file uploaded.'));
940

    
941
    // Check that the file exists in the database.
942
    $file = $this->getFileByFilename($test_file->filename);
943
    $this->assertTrue($file, t('File found in database.'));
944

    
945
    // Check that the alt and title text was loaded from the fields.
946
    $this->assertEqual($file->alt, $alt, t('Alt text was stored as file metadata.'));
947
    $this->assertEqual($file->title, $title, t('Title text was stored as file metadata.'));
948

    
949
    // Verify that the alt and title text is present on the page.
950
    $image_info = array(
951
      'path' => $file->uri,
952
      'alt' => $alt,
953
      'title' => $title,
954
      'width' => $file->width,
955
      'height' => $file->height,
956
    );
957
    $default_output = theme('image', $image_info);
958
    $this->assertRaw($default_output, 'Image displayed using user supplied alt and title attributes.');
959

    
960
    // Verify that the alt and title text can be edited.
961
    $new_alt = $this->randomName();
962
    $new_title = $this->randomName();
963

    
964
    $edit = array();
965
    $edit[$alt_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $new_alt;
966
    $edit[$title_field_name . '[' . LANGUAGE_NONE . '][0][value]'] = $new_title;
967
    $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
968

    
969
    $image_info = array(
970
      'path' => $file->uri,
971
      'alt' => $new_alt,
972
      'title' => $new_title,
973
      'width' => $file->width,
974
      'height' => $file->height,
975
    );
976
    $default_output = theme('image', $image_info);
977
    $this->assertRaw($default_output, 'Image displayed using updated alt and title attributes.');
978
  }
979
}
980

    
981
/**
982
 * Test changing the scheme of a file.
983
 */
984
class FileEntityChangeSchemeTestCase extends FileEntityTestHelper {
985

    
986
  public static function getInfo() {
987
    return array(
988
      'name' => 'Changing file scheme',
989
      'description' => 'Test changing the scheme of a file.',
990
      'group' => 'File entity',
991
    );
992
  }
993

    
994
  function testChangeScheme() {
995
    // Select the first text test file to use.
996
    $file = $this->createFileEntity(array('type' => 'document'));
997
    $this->assertEqual(file_uri_scheme($file->uri), 'public', 'File is public.');
998

    
999
    // Create a user with file edit permissions.
1000
    $user = $this->drupalCreateUser(array('edit any document files'));
1001
    $this->drupalLogin($user);
1002

    
1003
    $this->drupalGet('file/' . $file->fid . '/edit');
1004
    $this->assertNoFieldByName('scheme');
1005

    
1006
    // Create a user with file admin permissions.
1007
    $user = $this->drupalCreateUser(array('edit any document files', 'administer files'));
1008
    $this->drupalLogin($user);
1009

    
1010
    $this->drupalGet('file/' . $file->fid . '/edit');
1011
    $this->assertFieldByName('scheme', 'public');
1012

    
1013
    $this->drupalPost(NULL, array('scheme' => 'private'), 'Save');
1014
    $file = entity_load_unchanged('file', $file->fid);
1015
    $this->assertEqual(file_uri_scheme($file->uri), 'private', 'File has changed to private.');
1016
  }
1017

    
1018
}
1019

    
1020
/**
1021
 * Tests replacing the file associated with a file entity.
1022
 */
1023
class FileEntityReplaceTestCase extends FileEntityTestHelper {
1024
  public static function getInfo() {
1025
    return array(
1026
      'name' => 'File replacement',
1027
      'description' => 'Test file replace functionality.',
1028
      'group' => 'File entity',
1029
    );
1030
  }
1031

    
1032
  function setUp() {
1033
    parent::setUp();
1034
  }
1035

    
1036
  /**
1037
   * @todo Test image dimensions for an image field are reset when a file is replaced.
1038
   * @todo Test image styles are cleared when an image is updated.
1039
   */
1040
  function testReplaceFile() {
1041
    // Select the first text test file to use.
1042
    $file = $this->createFileEntity(array('type' => 'document'));
1043

    
1044
    // Create a user with file edit permissions.
1045
    $user = $this->drupalCreateUser(array('edit any document files'));
1046
    $this->drupalLogin($user);
1047

    
1048
    // Test that the Upload widget appears for a local file.
1049
    $this->drupalGet('file/' . $file->fid . '/edit');
1050
    $this->assertFieldByName('files[replace_upload]');
1051

    
1052
    // Test that file saves without uploading a file.
1053
    $this->drupalPost(NULL, array(), t('Save'));
1054
    $this->assertText(t('Document @file has been updated.', array('@file' => $file->filename)), 'File was updated without file upload.');
1055

    
1056
    // Get a text file to use as a replacement.
1057
    $original = clone $file;
1058
    $replacement = $this->getTestFile('text');
1059

    
1060
    // Test that the file saves when uploading a replacement file.
1061
    $edit = array();
1062
    $edit['files[replace_upload]'] = drupal_realpath($replacement->uri);
1063
    $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
1064
    $this->assertText(t('Document @file has been updated.', array('@file' => $file->filename)), 'File was updated with file upload.');
1065

    
1066
    // Re-load the file from the database.
1067
    $file = file_load($file->fid);
1068

    
1069
    // Test how file properties changed after the file has been replaced.
1070
    $this->assertEqual($file->filename, $original->filename, 'Updated file name did not change.');
1071
    $this->assertNotEqual($file->filesize, $original->filesize, 'Updated file size changed from previous file.');
1072
    $this->assertEqual($file->filesize, $replacement->filesize, 'Updated file size matches uploaded file.');
1073
    $this->assertEqual(file_get_contents($file->uri), file_get_contents($replacement->uri), 'Updated file contents matches uploaded file.');
1074
    $this->assertFalse(entity_load('file', FALSE, array('status' => 0)), 'Temporary file used for replacement was deleted.');
1075

    
1076
    // Get an image file.
1077
    $image = $this->getTestFile('image');
1078
    $edit['files[replace_upload]'] = drupal_realpath($image->uri);
1079

    
1080
    // Test that validation works by uploading a non-text file as a replacement.
1081
    $this->drupalPost('file/' . $file->fid . '/edit', $edit, t('Save'));
1082
    $this->assertRaw(t('The specified file %file could not be uploaded. Only files with the following extensions are allowed:', array('%file' => $image->filename)), 'File validation works, upload failed correctly.');
1083

    
1084
    // Create a non-local file record.
1085
    $file2 = new stdClass();
1086
    $file2->uri = 'oembed://' . $this->randomName();
1087
    $file2->filename = drupal_basename($file2->uri);
1088
    $file2->filemime = 'image/oembed';
1089
    $file2->type = 'image';
1090
    $file2->uid = 1;
1091
    $file2->timestamp = REQUEST_TIME;
1092
    $file2->filesize = 0;
1093
    $file2->status = 0;
1094
    // Write the record directly rather than calling file_save() so we don't
1095
    // invoke the hooks.
1096
    $this->assertTrue(drupal_write_record('file_managed', $file2), 'Non-local file was added to the database.');
1097

    
1098
    // Test that Upload widget does not appear for non-local file.
1099
    $this->drupalGet('file/' . $file2->fid . '/edit');
1100
    $this->assertNoFieldByName('files[replace_upload]');
1101
  }
1102
}
1103

    
1104
/**
1105
 * Tests file entity tokens.
1106
 */
1107
class FileEntityTokenTestCase extends FileEntityTestHelper {
1108
  public static function getInfo() {
1109
    return array(
1110
      'name' => 'File entity tokens',
1111
      'description' => 'Test the file entity tokens.',
1112
      'group' => 'File entity',
1113
    );
1114
  }
1115

    
1116
  function setUp() {
1117
    parent::setUp();
1118
  }
1119

    
1120
  function testFileEntityTokens() {
1121
    $file = $this->createFileEntity(array('type' => 'document'));
1122
    $tokens = array(
1123
      'type' => 'Document',
1124
      'type:name' => 'Document',
1125
      'type:machine-name' => 'document',
1126
      'type:count' => 1,
1127
    );
1128
    $this->assertTokens('file', array('file' => $file), $tokens);
1129

    
1130
    $file = $this->createFileEntity(array('type' => 'image'));
1131
    $tokens = array(
1132
      'type' => 'Image',
1133
      'type:name' => 'Image',
1134
      'type:machine-name' => 'image',
1135
      'type:count' => 1,
1136
    );
1137
    $this->assertTokens('file', array('file' => $file), $tokens);
1138
  }
1139

    
1140
  function assertTokens($type, array $data, array $tokens, array $options = array()) {
1141
    $token_input = drupal_map_assoc(array_keys($tokens));
1142
    $values = token_generate($type, $token_input, $data, $options);
1143
    foreach ($tokens as $token => $expected) {
1144
      if (!isset($expected)) {
1145
        $this->assertTrue(!isset($values[$token]), t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
1146
      }
1147
      elseif (!isset($values[$token])) {
1148
        $this->fail(t("Token value for [@type:@token] was not generated.", array('@type' => $type, '@token' => $token)));
1149
      }
1150
      elseif (!empty($options['regex'])) {
1151
        $this->assertTrue(preg_match('/^' . $expected . '$/', $values[$token]), t("Token value for [@type:@token] was '@actual', matching regular expression pattern '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
1152
      }
1153
      else {
1154
        $this->assertIdentical($values[$token], $expected, t("Token value for [@type:@token] was '@actual', expected value '@expected'.", array('@type' => $type, '@token' => $token, '@actual' => $values[$token], '@expected' => $expected)));
1155
      }
1156
    }
1157

    
1158
    return $values;
1159
  }
1160
}
1161

    
1162
/**
1163
 * Tests adding support for bundles to the core 'file' entity.
1164
 */
1165
class FileEntityTypeTestCase extends FileEntityTestHelper {
1166
  public static function getInfo() {
1167
    return array(
1168
      'name' => 'File entity types',
1169
      'description' => 'Test the file entity types.',
1170
      'group' => 'File entity',
1171
    );
1172
  }
1173

    
1174
  function setUp() {
1175
    parent::setUp();
1176
  }
1177

    
1178
  /**
1179
   * Test admin pages access and functionality.
1180
   */
1181
  function testAdminPages() {
1182
    // Create a user with file type administration access.
1183
    $user = $this->drupalCreateUser(array('administer file types'));
1184
    $this->drupalLogin($user);
1185

    
1186
    $this->drupalGet('admin/structure/file-types');
1187
    $this->assertResponse(200, 'File types admin page is accessible');
1188
  }
1189

    
1190
  /**
1191
   * Test creating a new type. Basic CRUD.
1192
   */
1193
  function testCreate() {
1194
    $type_machine_type = 'foo';
1195
    $type_machine_label = 'foobar';
1196
    $type = $this->createFileType(array('type' => $type_machine_type, 'label' => $type_machine_label));
1197
    $loaded_type = file_type_load($type_machine_type);
1198
    $this->assertEqual($loaded_type->label, $type_machine_label, "Was able to create a type and retrieve it.");
1199
  }
1200

    
1201
  /**
1202
   * Test file types CRUD UI.
1203
   */
1204
  function testTypesCrudUi() {
1205
    $this->drupalGet('admin/structure/file-types');
1206
    $this->assertResponse(403, 'File types UI page is not accessible to unauthorized users.');
1207

    
1208
    $user = $this->drupalCreateUser(array('administer file types', 'administer fields'));
1209
    $this->drupalLogin($user);
1210

    
1211
    $this->drupalGet('admin/structure/file-types');
1212
    $this->assertResponse(200, 'File types UI page is accessible to users with adequate permission.');
1213

    
1214
    // Create new file type.
1215
    $edit = array(
1216
      'label' => t('Test type'),
1217
      'type' => 'test_type',
1218
      'description' => t('This is dummy file type used just for testing.'),
1219
      'mimetypes' => 'image/png',
1220
    );
1221
    $this->drupalGet('admin/structure/file-types/add');
1222
    $this->drupalPost(NULL, $edit, t('Save'));
1223
    $this->assertText(t('The file type @type has been updated.', array('@type' => $edit['label'])), 'New file type successfully created.');
1224
    $this->assertText($edit['label'], 'New file type created: label found.');
1225
    $this->assertText($edit['description'], 'New file type created: description found.');
1226
    $this->assertFieldByXPath("//table//tr[1]//td[7]", t('Normal'), 'Newly created file type is stored in DB.');
1227
    $this->assertLink(t('disable'), 0, 'Able to disable newly created file type.');
1228
    $this->assertLink(t('delete'), 0, 'Able to delete newly created file type.');
1229
    $this->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/disable', 0, 'Disable link points to disable confirmation page.');
1230
    $this->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/delete', 0, 'Delete link points to delete confirmation page.');
1231

    
1232
    // Edit file type.
1233
    $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/edit');
1234
    $this->assertRaw(t('Save'), 'Save button found on edit page.');
1235
    $this->assertRaw(t('Delete'), 'Delete button found on edit page.');
1236
    $this->assertRaw($edit['label'], 'Label found on file type edit page');
1237
    $this->assertText($edit['description'], 'Description found on file type edit page');
1238
    $this->assertText($edit['mimetypes'], 'Mime-type configuration found on file type edit page');
1239
    $this->assertText(t('Mimetype List'), 'Mimetype list present on edit form.');
1240

    
1241
    // Modify file type.
1242
    $edit['label'] = t('New type label');
1243
    $this->drupalPost(NULL, array('label' => $edit['label']), t('Save'));
1244
    $this->assertText(t('The file type @type has been updated.', array('@type' => $edit['label'])), 'File type was modified.');
1245
    $this->assertText($edit['label'], 'Modified label found on file types list.');
1246

    
1247
    // Disable and re-enable file type.
1248
    $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/disable');
1249
    $this->assertText(t('Are you sure you want to disable the file type @type?', array('@type' => $edit['label'])), 'Disable confirmation page found.');
1250
    $this->drupalPost(NULL, array(), t('Disable'));
1251
    $this->assertText(t('The file type @type has been disabled.', array('@type' => $edit['label'])), 'Disable confirmation message found.');
1252
    $this->assertFieldByXPath("//table//tr[5]//td[1]", $edit['label'], 'Disabled type moved to the tail of the list.');
1253
    $this->assertLink(t('enable'), 0, 'Able to re-enable newly created file type.');
1254
    $this->assertLinkByHref('admin/structure/file-types/manage/' . $edit['type'] . '/enable', 0, 'Enable link points to enable confirmation page.');
1255
    $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/enable');
1256
    $this->assertText(t('Are you sure you want to enable the file type @type?', array('@type' => $edit['label'])), 'Enable confirmation page found.');
1257
    $this->drupalPost(NULL, array(), t('Enable'));
1258
    $this->assertText(t('The file type @type has been enabled.', array('@type' => $edit['label'])), 'Enable confirmation message found.');
1259
    $this->assertFieldByXPath("//table//tr[1]//td[1]", $edit['label'], 'Enabled type moved to the top of the list.');
1260

    
1261
    // Delete newly created type.
1262
    $this->drupalGet('admin/structure/file-types/manage/' . $edit['type'] . '/delete');
1263
    $this->assertText(t('Are you sure you want to delete the file type @type?', array('@type' => $edit['label'])), 'Delete confirmation page found.');
1264
    $this->drupalPost(NULL, array(), t('Delete'));
1265
    $this->assertText(t('The file type @type has been deleted.', array('@type' => $edit['label'])), 'Delete confirmation message found.');
1266
    $this->drupalGet('admin/structure/file-types');
1267
    $this->assertNoText($edit['label'], 'File type successfully deleted.');
1268

    
1269
    // Edit exported file type.
1270
    $this->drupalGet('admin/structure/file-types/manage/image/edit');
1271
    $this->assertRaw(t('Image'), 'Label found on file type edit page');
1272
    $this->assertText("image/*", 'Mime-type configuration found on file type edit page');
1273
    $this->drupalPost(NULL, array('label' => t('Funky images')), t('Save'));
1274
    $this->assertText(t('The file type @type has been updated.', array('@type' => t('Funky images'))), 'File type was modified.');
1275
    $this->assertText(t('Funky image'), 'Modified label found on file types list.');
1276
    $this->assertFieldByXPath("//table//tr[1]//td[7]", t('Overridden'), 'Modified type overrides configuration from code.');
1277
    $this->assertLink(t('revert'), 0, 'Able to revert overridden file type.');
1278
    $this->assertLinkByHref('admin/structure/file-types/manage/image/revert', 0, 'Revert link points to revert confirmation page.');
1279

    
1280
    // Revert file type.
1281
    $this->drupalGet('admin/structure/file-types/manage/image/revert');
1282
    $this->assertText(t('Are you sure you want to revert the file type @type?', array('@type' => t('Funky images'))), 'Revert confirmation page found.');
1283
    $this->drupalPost(NULL, array(), t('Revert'));
1284
    $this->assertText(t('The file type @type has been reverted.', array('@type' => t('Funky images'))), 'Revert confirmation message found.');
1285
    $this->assertText(t('Image'), 'Reverted file type found in list.');
1286
    $this->assertFieldByXPath("//table//tr[1]//td[7]", t('Default'), 'Reverted file type shows correct state.');
1287
  }
1288
}
1289

    
1290
/**
1291
 * Tests the file entity access API.
1292
 */
1293
class FileEntityAccessTestCase extends FileEntityTestHelper {
1294

    
1295
  public static function getInfo() {
1296
    return array(
1297
      'name' => 'File entity access',
1298
      'description' => 'Test the access aspects of file entity.',
1299
      'group' => 'File entity',
1300
    );
1301
  }
1302

    
1303
  function setUp() {
1304
    parent::setUp();
1305

    
1306
    // Remove the "view files" permission which is set by default for all users
1307
    // so we can test this permission correctly.
1308
    $roles = user_roles();
1309
    foreach ($roles as $rid => $role) {
1310
      user_role_revoke_permissions($rid, array('view files'));
1311
    }
1312
  }
1313

    
1314
  /**
1315
   * Runs basic tests for file_entity_access function.
1316
   */
1317
  function testFileEntityAccess() {
1318
    $file = $this->createFileEntity(array('type' => 'image'));
1319

    
1320
    // Ensures user with 'bypass file access' permission can do everything.
1321
    $web_user = $this->drupalCreateUser(array('bypass file access'));
1322
    $this->assertFileEntityAccess(array('create' => TRUE), NULL, $web_user);
1323
    $this->assertFileEntityAccess(array('view' => TRUE, 'download' => TRUE, 'update' => TRUE, 'delete' => TRUE), $file, $web_user);
1324

    
1325
    // A user with 'administer files' should not access CRUD operations.
1326
    $web_user = $this->drupalCreateUser(array('administer files'));
1327
    $this->assertFileEntityAccess(array('view' => FALSE, 'download' => FALSE, 'update' => FALSE, 'delete' => FALSE), $file, $web_user);
1328

    
1329
    // User cannot 'view files'.
1330
    $web_user = $this->drupalCreateUser(array('create files'));
1331
    $this->assertFileEntityAccess(array('view' => FALSE), $file, $web_user);
1332
    // But can upload new ones.
1333
    $this->assertFileEntityAccess(array('create' => TRUE), NULL, $web_user);
1334

    
1335
    // User can view own files but no other files.
1336
    $web_user = $this->drupalCreateUser(array('create files', 'view own files'));
1337
    $this->assertFileEntityAccess(array('view' => FALSE), $file, $web_user);
1338
    $file->uid = $web_user->uid;
1339
    $this->assertFileEntityAccess(array('view' => TRUE), $file, $web_user);
1340

    
1341
    // User can download own files but no other files.
1342
    $web_user = $this->drupalCreateUser(array('create files', 'download own image files'));
1343
    $this->assertFileEntityAccess(array('download' => FALSE), $file, $web_user);
1344
    $file->uid = $web_user->uid;
1345
    $this->assertFileEntityAccess(array('download' => TRUE), $file, $web_user);
1346

    
1347
    // User can update own files but no other files.
1348
    $web_user = $this->drupalCreateUser(array('create files', 'view own files', 'edit own image files'));
1349
    $this->assertFileEntityAccess(array('update' => FALSE), $file, $web_user);
1350
    $file->uid = $web_user->uid;
1351
    $this->assertFileEntityAccess(array('update' => TRUE), $file, $web_user);
1352

    
1353
    // User can delete own files but no other files.
1354
    $web_user = $this->drupalCreateUser(array('create files', 'view own files', 'edit own image files', 'delete own image files'));
1355
    $this->assertFileEntityAccess(array('delete' => FALSE), $file, $web_user);
1356
    $file->uid = $web_user->uid;
1357
    $this->assertFileEntityAccess(array('delete' => TRUE), $file, $web_user);
1358

    
1359
    // User can view any file.
1360
    $web_user = $this->drupalCreateUser(array('create files', 'view files'));
1361
    $this->assertFileEntityAccess(array('view' => TRUE), $file, $web_user);
1362

    
1363
    // User can download any file.
1364
    $web_user = $this->drupalCreateUser(array('create files', 'download any image files'));
1365
    $this->assertFileEntityAccess(array('download' => TRUE), $file, $web_user);
1366

    
1367
    // User can edit any file.
1368
    $web_user = $this->drupalCreateUser(array('create files', 'view files', 'edit any image files'));
1369
    $this->assertFileEntityAccess(array('update' => TRUE), $file, $web_user);
1370

    
1371
    // User can delete any file.
1372
    $web_user = $this->drupalCreateUser(array('create files', 'view files', 'edit any image files', 'delete any image files'));
1373
    $this->assertFileEntityAccess(array('delete' => TRUE), $file, $web_user);
1374
  }
1375

    
1376
  /**
1377
   * Tests page access.
1378
   *
1379
   * Verifies the privileges required to access the following pages:
1380
   *  file/add
1381
   *  file/%/view
1382
   *  file/%/download
1383
   *  file/%/edit
1384
   *  file/%/usage
1385
   *  file/%/delete
1386
   */
1387
  function testFileEntityPageAccess() {
1388
    // Test creating files without permission.
1389
    $web_user = $this->drupalCreateUser();
1390
    $this->drupalLogin($web_user);
1391
    $this->drupalGet('file/add');
1392
    $this->assertResponse(403, 'Users without access can not access the file add page');
1393

    
1394
    // Test creating files with permission.
1395
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1396
      'create files' => TRUE,
1397
    ));
1398
    $this->drupalGet('file/add');
1399
    $this->assertResponse(200, 'Users with access can access the file add page');
1400

    
1401
    $file = $this->createFileEntity(array('type' => 'document','uid' => $web_user->uid));
1402

    
1403
    // Test viewing own files without permission.
1404
    $this->drupalGet("file/{$file->fid}/view");
1405
    $this->assertResponse(403, 'Users without access can not view their own files');
1406

    
1407
    // Test viewing own files with permission.
1408
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1409
      'view own files' => TRUE,
1410
    ));
1411
    $this->drupalGet("file/{$file->fid}/view");
1412
    $this->assertResponse(200, 'Users with access can view their own files');
1413

    
1414
    // Test viewing any files without permission.
1415
    $file->uid = 1;
1416
    file_save($file);
1417
    $this->drupalGet("file/{$file->fid}/view");
1418
    $this->assertResponse(403, 'Users with access can not view any file');
1419

    
1420
    // Test viewing any files with permission.
1421
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1422
      'view files' => TRUE,
1423
    ));
1424
    $this->drupalGet("file/{$file->fid}/view");
1425
    $this->assertResponse(200, 'Users with access can view any file');
1426

    
1427
    // Test downloading own files without permission.
1428
    $file->uid = $web_user->uid;
1429
    file_save($file);
1430
    $url = "file/{$file->fid}/download";
1431
    $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
1432
    $this->assertResponse(403, 'Users without access can not download their own files');
1433

    
1434
    // Test downloading own files with permission.
1435
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1436
      'download own document files' => TRUE,
1437
    ));
1438
    $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
1439
    $this->assertResponse(200, 'Users with access can download their own files');
1440

    
1441
    // Test downloading any files without permission.
1442
    $file->uid = 1;
1443
    file_save($file);
1444
    $url = "file/{$file->fid}/download";
1445
    $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
1446
    $this->assertResponse(403, 'Users without access can not download any file');
1447

    
1448
    // Test downloading any files with permission.
1449
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1450
      'download any document files' => TRUE,
1451
    ));
1452
    $this->drupalGet($url, array('query' => array('token' => file_entity_get_download_token($file))));
1453
    $this->assertResponse(200, 'Users with access can download any file');
1454

    
1455
    // Test downloading files with an invalid token.
1456
    $this->drupalGet($url, array('query' => array('token' => 'invalid-token')));
1457
    $this->assertResponse(403, 'Cannot download file with an invalid token.');
1458

    
1459
    // Test downloading files without a token.
1460
    $this->drupalGet($url);
1461
    $this->assertResponse(403, 'Cannot download file without a token.');
1462
    variable_set('file_entity_allow_insecure_download', TRUE);
1463

    
1464
    // Test downloading files with permission but without a token when insecure
1465
    // downloads are enabled.
1466
    $this->drupalGet($url);
1467
    $this->assertResponse(200, 'Users with access can download the file without a token when file_entity_allow_insecure_download is set.');
1468

    
1469
    // Tests editing own files without permission.
1470
    $file->uid = $web_user->uid;
1471
    file_save($file);
1472
    $this->drupalGet("file/{$file->fid}/edit");
1473
    $this->assertResponse(403, 'Users without access can not edit own files');
1474

    
1475
    // Tests checking the usage of their own files without permission.
1476
    $this->drupalGet("file/{$file->fid}/usage");
1477
    $this->assertResponse(403, 'Users without access can not check the usage of their own files');
1478

    
1479
    // Tests editing own files with permission.
1480
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1481
      'edit own document files' => TRUE,
1482
    ));
1483
    $this->drupalGet("file/{$file->fid}/edit");
1484
    $this->assertResponse(200, 'Users with access can edit own files');
1485

    
1486
    // Tests checking the usage of their own files without permission.
1487
    $this->drupalGet("file/{$file->fid}/usage");
1488
    $this->assertResponse(200, 'Users with access can check the usage of their own files');
1489

    
1490
    // Tests editing any files without permission.
1491
    $file->uid = 1;
1492
    file_save($file);
1493
    $this->drupalGet("file/{$file->fid}/edit");
1494
    $this->assertResponse(403, 'Users without access can not edit any file');
1495

    
1496
    // Tests checking the usage of any files without permission.
1497
    $this->drupalGet("file/{$file->fid}/usage");
1498
    $this->assertResponse(403, 'Users without access can not check the usage of any file');
1499

    
1500
    // Tests editing any files with permission.
1501
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1502
      'edit any document files' => TRUE,
1503
    ));
1504
    $this->drupalGet("file/{$file->fid}/edit");
1505
    $this->assertResponse(200, 'Users with access can edit any file');
1506

    
1507
    // Tests checking the usage of any files with permission.
1508
    $this->drupalGet("file/{$file->fid}/usage");
1509
    $this->assertResponse(200, 'Users with access can check the usage of any file');
1510

    
1511
    // Tests deleting own files without permission.
1512
    $file->uid = $web_user->uid;
1513
    file_save($file);
1514
    $this->drupalGet("file/{$file->fid}/delete");
1515
    $this->assertResponse(403, 'Users without access can not delete their own files');
1516

    
1517
    // Tests deleting own files with permission.
1518
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1519
      'delete own document files' => TRUE,
1520
    ));
1521
    $this->drupalGet("file/{$file->fid}/delete");
1522
    $this->assertResponse(200, 'Users with access can delete their own files');
1523

    
1524
    // Tests deleting any files without permission.
1525
    $file->uid = 1;
1526
    file_save($file);
1527
    $this->drupalGet("file/{$file->fid}/delete");
1528
    $this->assertResponse(403, 'Users without access can not delete any file');
1529

    
1530
    // Tests deleting any files with permission.
1531
    user_role_change_permissions(DRUPAL_AUTHENTICATED_RID, array(
1532
      'delete any document files' => TRUE,
1533
    ));
1534
    $this->drupalGet("file/{$file->fid}/delete");
1535
    $this->assertResponse(200, 'Users with access can delete any file');
1536
  }
1537

    
1538
  /**
1539
   * Test to see if we have access to download private files when granted the permissions.
1540
   */
1541
  function testFileEntityPrivateDownloadAccess() {
1542
    foreach ($this->getPrivateDownloadAccessCases() as $case) {
1543
      // Create users and login only if non-anonymous.
1544
      $authenticated_user = !is_null($case['permissions']);
1545
      if ($authenticated_user) {
1546
        $account = $this->drupalCreateUser($case['permissions']);
1547
        $this->drupalLogin($account);
1548
      }
1549

    
1550
      // Create private, permanent files owned by this user only he's an owner.
1551
      if (!empty($case['owner'])) {
1552
        $file = $this->createFileEntity(array('type' => 'document', 'uid' => $account->uid, 'scheme' => 'private'));
1553

    
1554
        // Check if the physical file is there.
1555
        $arguments = array('%name' => $file->filename, '%username' => $account->name, '%uri' => $file->uri);
1556
        $this->assertTrue(is_file($file->uri), format_string('File %name owned by %username successfully created at %uri.', $arguments));
1557
        $url = file_create_url($file->uri);
1558
        $message_file_info = ' ' . format_string('File %uri was checked.', array('%uri' => $file->uri));
1559
      }
1560

    
1561
      // Try to download the file.
1562
      $this->drupalGet($url);
1563
      $this->assertResponse($case['expect'], $case['message'] . $message_file_info);
1564

    
1565
      // Logout authenticated users.
1566
      if ($authenticated_user) {
1567
        $this->drupalLogout();
1568
      }
1569
    }
1570
  }
1571

    
1572
  /**
1573
   * Asserts file_entity_access correctly grants or denies access.
1574
   */
1575
  function assertFileEntityAccess($ops, $file, $account) {
1576
    drupal_static_reset('file_entity_access');
1577
    foreach ($ops as $op => $result) {
1578
      $msg = t("file_entity_access returns @result with operation '@op'.", array('@result' => $result ? 'true' : 'false', '@op' => $op));
1579
      $this->assertEqual($result, file_entity_access($op, $file, $account), $msg);
1580
    }
1581
  }
1582

    
1583
  /**
1584
   * Helper for testFileEntityPrivateDownloadAccess() test.
1585
   *
1586
   * Defines several cases for accesing private files.
1587
   *
1588
   * @return array
1589
   *   Array of associative arrays, each one having the next keys:
1590
   *   - "message" string with the assertion message.
1591
   *   - "permissions" array of permissions or NULL for anonymous user.
1592
   *   - "expect" expected HTTP response code.
1593
   *   - "owner" Optional boolean indicating if the user is a file owner.
1594
   */
1595
  function getPrivateDownloadAccessCases() {
1596
    return array(
1597
      array(
1598
        'message' => "File owners cannot download their own files unless they are granted the 'view own private files' permission.",
1599
        'permissions' => array(),
1600
        'expect' => 403,
1601
        'owner' => TRUE,
1602
      ),
1603
      array(
1604
        'message' => "File owners can download their own files as they have been granted the 'view own private files' permission.",
1605
        'permissions' => array('view own private files'),
1606
        'expect' => 200,
1607
        'owner' => TRUE,
1608
      ),
1609
      array(
1610
        'message' => "Anonymous users cannot download private files.",
1611
        'permissions' => NULL,
1612
        'expect' => 403,
1613
      ),
1614
      array(
1615
        'message' => "Authenticated users cannot download each other's private files.",
1616
        'permissions' => array(),
1617
        'expect' => 403,
1618
      ),
1619
      array(
1620
        'message' => "Users who can view public files are not able to download private files.",
1621
        'permissions' => array('view files'),
1622
        'expect' => 403,
1623
      ),
1624
      array(
1625
        'message' => "Users who bypass file access can download any file.",
1626
        'permissions' => array('bypass file access'),
1627
        'expect' => 200,
1628
      ),
1629
    );
1630
  }
1631
}
1632

    
1633
/**
1634
 * Tests overriding file attributes.
1635
 */
1636
class FileEntityAttributeOverrideTestCase extends FileEntityTestHelper {
1637

    
1638
  public static function getInfo() {
1639
    return array(
1640
      'name' => 'File entity attribute override',
1641
      'description' => 'Test overriding file entity attributes.',
1642
      'group' => 'File entity',
1643
    );
1644
  }
1645

    
1646
  /**
1647
   * Test to see if file attributes can be overridden.
1648
   */
1649
  function testFileEntityFileAttributeOverrides() {
1650
    $overrides = array(
1651
      'width' => 40,
1652
      'height' => 20,
1653
      'alt' => $this->randomName(),
1654
      'title' => $this->randomName(),
1655

    
1656
    );
1657

    
1658
    // Create an image file entity for testing.
1659
    $file = $this->createFileEntity(array('type' => 'image'));
1660

    
1661
    // Override a variety of attributes.
1662
    foreach ($overrides as $override => $value) {
1663
      $file->override['attributes'][$override] = $value;
1664
    }
1665

    
1666
    // Build just the file portion of a file entity.
1667
    $build = file_view_file($file, 'full');
1668

    
1669
    // Verify that all of the overrides replaced the attributes.
1670
    foreach ($overrides as $attribute => $expected_value) {
1671
      $this->assertEqual($build['#file']->$attribute, $expected_value, format_string('The %attribute was overridden correctly.', array('%attribute' => $attribute)));
1672
    }
1673
  }
1674
}