FileListingTest.php 7.45 KB
Newer Older
1 2
<?php

3
namespace Drupal\Tests\file\Functional;
4

5
use Drupal\node\Entity\Node;
6
use Drupal\file\Entity\File;
7
use Drupal\entity_test\Entity\EntityTestConstraints;
8

9 10
/**
 * Tests file listing page functionality.
11 12
 *
 * @group file
13 14 15 16 17 18 19 20
 */
class FileListingTest extends FileFieldTestBase {

  /**
   * Modules to enable.
   *
   * @var array
   */
21
  protected static $modules = ['views', 'file', 'image', 'entity_test'];
22

23 24 25
  /**
   * {@inheritdoc}
   */
xjm's avatar
Issue  
xjm committed
26
  protected $defaultTheme = 'classy';
27

28 29 30 31 32 33 34
  /**
   * An authenticated user.
   *
   * @var \Drupal\user\UserInterface
   */
  protected $baseUser;

35
  protected function setUp(): void {
36 37
    parent::setUp();

38 39 40 41 42
    // This test expects unused managed files to be marked as a temporary file.
    $this->config('file.settings')
      ->set('make_unused_managed_files_temporary', TRUE)
      ->save();

43
    $this->adminUser = $this->drupalCreateUser(['access files overview', 'bypass node access']);
44
    $this->baseUser = $this->drupalCreateUser();
45
    $this->createFileField('file', 'node', 'article', [], ['file_extensions' => 'txt png']);
46 47 48 49 50 51 52
  }

  /**
   * Calculates total count of usages for a file.
   *
   * @param $usage array
   *   Array of file usage information as returned from file_usage subsystem.
53
   *
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
   * @return int
   *   Total usage count.
   */
  protected function sumUsages($usage) {
    $count = 0;
    foreach ($usage as $module) {
      foreach ($module as $entity_type) {
        foreach ($entity_type as $entity) {
          $count += $entity;
        }
      }
    }

    return $count;
  }

  /**
   * Tests file overview with different user permissions.
   */
73
  public function testFileListingPages() {
74 75
    $file_usage = $this->container->get('file.usage');
    // Users without sufficient permissions should not see file listing.
76
    $this->drupalLogin($this->baseUser);
77
    $this->drupalGet('admin/content/files');
78
    $this->assertSession()->statusCodeEquals(403);
79

80
    // Log in with user with right permissions and test listing.
81
    $this->drupalLogin($this->adminUser);
82 83

    for ($i = 0; $i < 5; $i++) {
84
      $nodes[] = $this->drupalCreateNode(['type' => 'article']);
85 86
    }

87
    $this->drupalGet('admin/content/files');
88
    $this->assertSession()->statusCodeEquals(200);
89 90
    $this->assertText('No files available.');
    $this->drupalGet('admin/content/files');
91
    $this->assertSession()->statusCodeEquals(200);
92 93 94 95 96

    // Create a file with no usage.
    $file = $this->createFile();

    $this->drupalGet('admin/content/files/usage/' . $file->id());
97
    $this->assertSession()->statusCodeEquals(200);
98
    $this->assertTitle('File usage information for ' . $file->getFilename() . ' | Drupal');
99

100
    foreach ($nodes as &$node) {
101
      $this->drupalGet('node/' . $node->id() . '/edit');
102 103
      $file = $this->getTestFile('image');

104
      $edit = [
105
        'files[file_0]' => \Drupal::service('file_system')->realpath($file->getFileUri()),
106
      ];
107
      $this->drupalPostForm(NULL, $edit, t('Save'));
108
      $node = Node::load($node->id());
109 110 111 112 113
    }

    $this->drupalGet('admin/content/files');

    foreach ($nodes as $node) {
114
      $file = File::load($node->file->target_id);
115 116 117 118
      $this->assertText($file->getFilename());
      $this->assertLinkByHref(file_create_url($file->getFileUri()));
      $this->assertLinkByHref('admin/content/files/usage/' . $file->id());
    }
119 120
    $this->assertSession()->elementTextNotContains('css', 'table.views-table', 'Temporary');
    $this->assertSession()->elementTextContains('css', 'table.views-table', 'Permanent');
121 122 123 124 125 126 127 128

    // Use one file two times and check usage information.
    $orphaned_file = $nodes[1]->file->target_id;
    $used_file = $nodes[0]->file->target_id;
    $nodes[1]->file->target_id = $used_file;
    $nodes[1]->save();

    $this->drupalGet('admin/content/files');
129
    $file = File::load($orphaned_file);
130
    $usage = $this->sumUsages($file_usage->listUsage($file));
131 132
    $this->assertRaw('admin/content/files/usage/' . $file->id() . '">' . $usage);

133
    $file = File::load($used_file);
134
    $usage = $this->sumUsages($file_usage->listUsage($file));
135 136
    $this->assertRaw('admin/content/files/usage/' . $file->id() . '">' . $usage);

137
    $result = $this->xpath("//td[contains(@class, 'views-field-status') and contains(text(), :value)]", [':value' => 'Temporary']);
138
    $this->assertCount(1, $result, 'Unused file marked as temporary.');
139 140 141

    // Test file usage page.
    foreach ($nodes as $node) {
142
      $file = File::load($node->file->target_id);
143
      $usage = $file_usage->listUsage($file);
144
      $this->drupalGet('admin/content/files/usage/' . $file->id());
145
      $this->assertSession()->statusCodeEquals(200);
146 147 148 149 150 151 152 153 154 155 156 157
      $this->assertText($node->getTitle(), 'Node title found on usage page.');
      $this->assertText('node', 'Registering entity type found on usage page.');
      $this->assertText('file', 'Registering module found on usage page.');
      foreach ($usage as $module) {
        foreach ($module as $entity_type) {
          foreach ($entity_type as $entity) {
            $this->assertText($entity, 'Usage count found on usage page.');
          }
        }
      }
      $this->assertLinkByHref('node/' . $node->id(), 0, 'Link to registering entity found on usage page.');
    }
158
  }
159

160 161 162
  /**
   * Tests file listing usage page for entities with no canonical link template.
   */
163
  public function testFileListingUsageNoLink() {
164 165 166 167 168 169
    // Login with user with right permissions and test listing.
    $this->drupalLogin($this->adminUser);

    // Create a bundle and attach a File field to the bundle.
    $bundle = $this->randomMachineName();
    entity_test_create_bundle($bundle, NULL, 'entity_test_constraints');
170
    $this->createFileField('field_test_file', 'entity_test_constraints', $bundle, [], ['file_extensions' => 'txt png']);
171 172 173 174 175 176 177 178 179 180 181 182 183

    // Create file to attach to entity.
    $file = File::create([
      'filename' => 'druplicon.txt',
      'uri' => 'public://druplicon.txt',
      'filemime' => 'text/plain',
    ]);
    $file->setPermanent();
    file_put_contents($file->getFileUri(), 'hello world');
    $file->save();

    // Create entity and attach the created file.
    $entity_name = $this->randomMachineName();
184
    $entity = EntityTestConstraints::create([
185 186 187
      'uid' => 1,
      'name' => $entity_name,
      'type' => $bundle,
188
      'field_test_file' => [
189
        'target_id' => $file->id(),
190 191
      ],
    ]);
192 193 194
    $entity->save();

    // Create node entity and attach the created file.
195
    $node = $this->drupalCreateNode(['type' => 'article', 'file' => $file]);
196 197 198 199 200
    $node->save();

    // Load the file usage page for the created and attached file.
    $this->drupalGet('admin/content/files/usage/' . $file->id());

201
    $this->assertSession()->statusCodeEquals(200);
202 203 204 205 206 207 208
    // Entity name should be displayed, but not linked if Entity::toUrl
    // throws an exception
    $this->assertText($entity_name, 'Entity name is added to file usage listing.');
    $this->assertNoLink($entity_name, 'Linked entity name not added to file usage listing.');
    $this->assertLink($node->getTitle());
  }

209 210 211 212
  /**
   * Creates and saves a test file.
   *
   * @return \Drupal\Core\Entity\EntityInterface
213
   *   A file entity.
214 215 216
   */
  protected function createFile() {
    // Create a new file entity.
217
    $file = File::create([
218 219 220 221
      'uid' => 1,
      'filename' => 'druplicon.txt',
      'uri' => 'public://druplicon.txt',
      'filemime' => 'text/plain',
222 223
      'created' => 1,
      'changed' => 1,
224
      'status' => FILE_STATUS_PERMANENT,
225
    ]);
226 227 228 229 230 231 232 233
    file_put_contents($file->getFileUri(), 'hello world');

    // Save it, inserting a new record.
    $file->save();

    return $file;
  }

234
}