Projet

Général

Profil

Paste
Télécharger (38,9 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / file_entity / file_entity.admin.inc @ 2b3c8cc1

1 85ad3d82 Assos Assos
<?php
2
/**
3
 * @file
4
 * File administration and module settings UI.
5
 */
6
7
require_once dirname(__FILE__) . '/file_entity.pages.inc';
8
9
/**
10
 * List file administration filters that can be applied.
11
 */
12
function file_filters() {
13
  $visible_steam_wrappers = file_get_stream_wrappers(STREAM_WRAPPERS_VISIBLE);
14
  $options = array();
15
  foreach ($visible_steam_wrappers as $scheme => $information) {
16
    $options[$scheme] = check_plain($information['name']);
17
  }
18
  $filters['uri'] = array(
19
    'title' => t('scheme'),
20
    'options' => array(
21
      '[any]' => t('any'),
22
    ) + $options,
23
  );
24
  $filters['type'] = array(
25
    'title' => t('type'),
26
    'options' => array(
27
      '[any]' => t('any'),
28
    ) + file_entity_type_get_names(),
29
  );
30
  return $filters;
31
}
32
33
/**
34
 * Apply filters for file administration filters based on session.
35
 *
36
 * @param object $query
37
 *   A SelectQuery to which the filters should be applied.
38
 */
39
function file_entity_build_filter_query(SelectQueryInterface $query) {
40
  // Build query.
41
  $filter_data = isset($_SESSION['file_entity_overview_filter']) ? $_SESSION['file_entity_overview_filter'] : array();
42
  foreach ($filter_data as $index => $filter) {
43
    list($key, $value) = $filter;
44
    switch ($key) {
45
      case 'uri':
46
        $query->condition('fm.' . $key, $value . '%', 'LIKE');
47
        break;
48
49
      case 'type':
50
        $query->condition('fm.' . $key, $value);
51
        break;
52
53
    }
54
  }
55
}
56
57
/**
58
 * Return form for file administration filters.
59
 */
60
function file_entity_filter_form() {
61
  $session = isset($_SESSION['file_entity_overview_filter']) ? $_SESSION['file_entity_overview_filter'] : array();
62
  $filters = file_filters();
63
64
  $i = 0;
65
  $form['filters'] = array(
66
    '#type' => 'fieldset',
67
    '#title' => t('Show only items where'),
68
    '#theme' => 'exposed_filters__file_entity',
69
  );
70
  foreach ($session as $filter) {
71
    list($type, $value) = $filter;
72
    if ($type == 'term') {
73
      // Load term name from DB rather than search and parse options array.
74
      $value = module_invoke('taxonomy', 'term_load', $value);
75
      $value = $value->name;
76
    }
77
    else {
78
      $value = $filters[$type]['options'][$value];
79
    }
80
    $t_args = array('%property' => $filters[$type]['title'], '%value' => $value);
81
    if ($i++) {
82
      $form['filters']['current'][] = array('#markup' => t('and where %property is %value', $t_args));
83
    }
84
    else {
85
      $form['filters']['current'][] = array('#markup' => t('where %property is %value', $t_args));
86
    }
87
    if (in_array($type, array('type', 'uri'))) {
88
      // Remove the option if it is already being filtered on.
89
      unset($filters[$type]);
90
    }
91
  }
92
93
  $form['filters']['status'] = array(
94
    '#type' => 'container',
95
    '#attributes' => array('class' => array('clearfix')),
96
    '#prefix' => ($i ? '<div class="additional-filters">' . t('and where') . '</div>' : ''),
97
  );
98
  $form['filters']['status']['filters'] = array(
99
    '#type' => 'container',
100
    '#attributes' => array('class' => array('filters')),
101
  );
102
  foreach ($filters as $key => $filter) {
103
    $form['filters']['status']['filters'][$key] = array(
104
      '#type' => 'select',
105
      '#options' => $filter['options'],
106
      '#title' => $filter['title'],
107
      '#default_value' => '[any]',
108
    );
109
  }
110
111
  $form['filters']['status']['actions'] = array(
112
    '#type' => 'actions',
113
    '#attributes' => array('class' => array('container-inline')),
114
  );
115
  if (count($filters)) {
116
    $form['filters']['status']['actions']['submit'] = array(
117
      '#type' => 'submit',
118
      '#value' => count($session) ? t('Refine') : t('Filter'),
119
    );
120
  }
121
  if (count($session)) {
122
    $form['filters']['status']['actions']['undo'] = array('#type' => 'submit', '#value' => t('Undo'));
123
    $form['filters']['status']['actions']['reset'] = array('#type' => 'submit', '#value' => t('Reset'));
124
  }
125
126
  drupal_add_js('misc/form.js');
127
128
  return $form;
129
}
130
131
/**
132
 * Process result from file administration filter form.
133
 */
134
function file_entity_filter_form_submit($form, &$form_state) {
135
  $filters = file_filters();
136
  switch ($form_state['values']['op']) {
137
    case t('Filter'):
138
    case t('Refine'):
139
      // Apply every filter that has a choice selected other than 'any'.
140
      foreach ($filters as $filter => $options) {
141
        if (isset($form_state['values'][$filter]) && $form_state['values'][$filter] != '[any]') {
142
          // Flatten the options array to accommodate hierarchical/nested
143
          // options.
144
          $flat_options = form_options_flatten($filters[$filter]['options']);
145
          // Only accept valid selections offered on the dropdown, block bad
146
          // input.
147
          if (isset($flat_options[$form_state['values'][$filter]])) {
148
            $_SESSION['file_entity_overview_filter'][] = array($filter, $form_state['values'][$filter]);
149
          }
150
        }
151
      }
152
      break;
153
154
    case t('Undo'):
155
      array_pop($_SESSION['file_entity_overview_filter']);
156
      break;
157
158
    case t('Reset'):
159
      $_SESSION['file_entity_overview_filter'] = array();
160
      break;
161
162
  }
163
}
164
165
/**
166
 * Make mass update of files.
167
 *
168
 * Change all files in the $files array to update them with the field values in
169
 * $updates.
170
 *
171
 * IMPORTANT NOTE: This function is intended to work when called
172
 * from a form submit handler. Calling it outside of the form submission
173
 * process may not work correctly.
174
 *
175
 * @param array $files
176
 *   Array of file fids to update.
177
 * @param array $updates
178
 *   Array of key/value pairs with file field names and the
179
 *   value to update that field to.
180
 */
181
function file_entity_mass_update($files, $updates) {
182
  // We use batch processing to prevent timeout when updating a large number
183
  // of files.
184
  if (count($files) > 10) {
185
    $batch = array(
186
      'operations' => array(
187
        array(
188
          '_file_entity_mass_update_batch_process',
189
          array($files, $updates),
190
        ),
191
      ),
192
      'finished' => '_file_entity_mass_update_batch_finished',
193
      'title' => t('Processing'),
194
      // We use a single multi-pass operation, so the default
195
      // 'Remaining x of y operations' message will be confusing here.
196
      'progress_message' => '',
197
      'error_message' => t('The update has encountered an error.'),
198
      // The operations do not live in the .module file, so we need to
199
      // tell the batch engine which file to load before calling them.
200
      'file' => drupal_get_path('module', 'file_entity') . '/file_entity.admin.inc',
201
    );
202
    batch_set($batch);
203
  }
204
  else {
205
    foreach ($files as $fid) {
206
      _file_entity_mass_update_helper($fid, $updates);
207
    }
208
    drupal_set_message(t('The update has been performed.'));
209
  }
210
}
211
212
/**
213
 * File Mass Update - helper function.
214
 */
215
function _file_entity_mass_update_helper($fid, $updates) {
216
  $file = file_load($fid);
217
  // For efficiency manually save the original file before applying any changes.
218
  $file->original = clone $file;
219
  foreach ($updates as $name => $value) {
220
    $file->$name = $value;
221
  }
222
  file_save($file);
223
  return $file;
224
}
225
226
/**
227
 * File Mass Update Batch operation.
228
 */
229
function _file_entity_mass_update_batch_process($files, $updates, &$context) {
230
  if (!isset($context['sandbox']['progress'])) {
231
    $context['sandbox']['progress'] = 0;
232
    $context['sandbox']['max'] = count($files);
233
    $context['sandbox']['files'] = $files;
234
  }
235
236
  // Process files by groups of 5.
237
  $count = min(5, count($context['sandbox']['files']));
238
  for ($i = 1; $i <= $count; $i++) {
239
    // For each fid, load the file, reset the values, and save it.
240
    $fid = array_shift($context['sandbox']['files']);
241
    $file = _file_entity_mass_update_helper($fid, $updates);
242
243
    // Store result for post-processing in the finished callback.
244
    $context['results'][] = l($file->filename, 'file/' . $file->fid);
245
246
    // Update our progress information.
247
    $context['sandbox']['progress']++;
248
  }
249
250
  // Inform the batch engine that we are not finished,
251
  // and provide an estimation of the completion level we reached.
252
  if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
253
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
254
  }
255
}
256
257
/**
258
 * File Mass Update Batch 'finished' callback.
259
 */
260
function _file_entity_mass_update_batch_finished($success, $results, $operations) {
261
  if ($success) {
262
    drupal_set_message(t('The update has been performed.'));
263
  }
264
  else {
265
    drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
266
    $message = format_plural(count($results), '1 item successfully processed:', '@count items successfully processed:');
267
    $message .= theme('item_list', array('items' => $results));
268
    drupal_set_message($message);
269
  }
270
}
271
272
/**
273
 * Menu callback: file administration.
274
 */
275
function file_entity_admin_file($form, $form_state) {
276
  if (isset($form_state['values']['operation']) && $form_state['values']['operation'] == 'delete') {
277
    return file_entity_multiple_delete_confirm($form, $form_state, array_filter($form_state['values']['files']));
278
  }
279
  $form['filter'] = file_entity_filter_form();
280
  $form['#submit'][] = 'file_entity_filter_form_submit';
281
  $form['admin'] = file_entity_admin_files();
282
283
  return $form;
284
}
285
286
/**
287
 * Form builder: Builds the file administration overview.
288
 */
289
function file_entity_admin_files() {
290
  $admin_access = user_access('administer files');
291
292
  // Build the 'Update options' form.
293
  $form['options'] = array(
294
    '#type' => 'fieldset',
295
    '#title' => t('Update options'),
296
    '#attributes' => array('class' => array('container-inline')),
297
    '#access' => $admin_access,
298
  );
299
  $options = array();
300
  foreach (module_invoke_all('file_operations') as $operation => $array) {
301
    $options[$operation] = $array['label'];
302
  }
303
  $form['options']['operation'] = array(
304
    '#type' => 'select',
305
    '#title' => t('Operation'),
306
    '#title_display' => 'invisible',
307
    '#options' => $options,
308
    '#default_value' => 'approve',
309
  );
310
  $form['options']['submit'] = array(
311
    '#type' => 'submit',
312
    '#value' => t('Update'),
313
    '#validate' => array('file_entity_admin_files_validate'),
314
    '#submit' => array('file_entity_admin_files_submit'),
315
  );
316
317
  // Build the sortable table header.
318
  $header = array(
319
    'title' => array('data' => t('Title'), 'field' => 'fm.filename'),
320
    'type' => array('data' => t('Type'), 'field' => 'fm.type'),
321
    'size' => array('data' => t('Size'), 'field' => 'fm.filesize'),
322
    'author' => t('Author'),
323
    'timestamp' => array(
324
      'data' => t('Updated'),
325
      'field' => 'fm.timestamp',
326
      'sort' => 'desc'),
327
    'usage' => array('data' => t('Used in'), 'field' => 'total_count'),
328
    'operations' => array('data' => t('Operations')),
329
  );
330
331
  $query = db_select('file_managed', 'fm')->extend('PagerDefault')->extend('TableSort');
332
  $query->leftJoin('file_usage', 'fu', 'fm.fid = fu.fid');
333
  $query->groupBy('fm.fid');
334 2b3c8cc1 Assos Assos
  $query->groupBy('fm.uid');
335
  $query->groupBy('fm.timestamp');
336 85ad3d82 Assos Assos
  $query->addExpression('SUM(fu.count)', 'total_count');
337
  file_entity_build_filter_query($query);
338
339
  $result = $query
340
    ->fields('fm', array('fid', 'uid'))
341
    ->limit(50)
342
    ->orderByHeader($header)
343
    ->addTag('file_access')
344
    ->execute()
345
    ->fetchAllAssoc('fid');
346
  $files = file_load_multiple(array_keys($result));
347
348
  $uids = array();
349
  foreach ($files as $file) {
350
    $uids[] = $file->uid;
351
  }
352
  $accounts = !empty($uids) ? user_load_multiple(array_unique($uids)) : array();
353
354
  // Prepare the list of files.
355
  $destination = drupal_get_destination();
356
  $options = array();
357
  foreach ($files as $file) {
358
    $file_type = file_type_load($file->type);
359 2b3c8cc1 Assos Assos
    $account = isset($accounts[$file->uid]) ? $accounts[$file->uid] : NULL;
360 85ad3d82 Assos Assos
    $options[$file->fid] = array(
361
      'title' => array(
362
        'data' => array(
363
          '#type' => 'link',
364
          '#title' => $file->filename,
365
          '#href' => 'file/' . $file->fid,
366
        ),
367
      ),
368
      'type' => $file_type ? check_plain($file_type->label) : FILE_TYPE_NONE,
369
      'size' => format_size($file->filesize),
370 2b3c8cc1 Assos Assos
      'author' => theme('username', array('account' => $account)),
371 85ad3d82 Assos Assos
      'timestamp' => format_date($file->timestamp, 'short'),
372
      'usage' => format_plural((int) $result[$file->fid]->total_count, '1 place', '@count places'),
373
    );
374
375
    // Show a warning for files that do not exist.
376
    if (@!is_file($file->uri)) {
377
      $options[$file->fid]['#attributes']['class'][] = 'error';
378
      if (!file_stream_wrapper_get_instance_by_uri($file->uri)) {
379
        $options[$file->fid]['#attributes']['title'] = t('The stream wrapper for @scheme files is missing.', array('@scheme' => file_uri_scheme($file->uri)));
380
      }
381
      else {
382
        $options[$file->fid]['#attributes']['title'] = t('The file does not exist.');
383
      }
384
    }
385
386
    // Build a list of all the accessible operations for the current file.
387
    $operations = array();
388
    if (file_entity_access('update', $file)) {
389
      // Convert the usage count to a link.
390
      $options[$file->fid]['usage'] = l($options[$file->fid]['usage'], 'file/' . $file->fid . '/usage');
391
      $operations['edit'] = array(
392
        'title' => t('Edit'),
393
        'href' => 'file/' . $file->fid . '/edit',
394
        'query' => $destination,
395
      );
396
    }
397
    if (file_entity_access('delete', $file)) {
398
      $operations['delete'] = array(
399
        'title' => t('Delete'),
400
        'href' => 'file/' . $file->fid . '/delete',
401
        'query' => $destination,
402
      );
403
    }
404
    $options[$file->fid]['operations'] = array();
405
    if (count($operations) > 1) {
406
      // Render an unordered list of operations links.
407
      $options[$file->fid]['operations'] = array(
408
        'data' => array(
409
          '#theme' => 'links__file_entity_operations',
410
          '#links' => $operations,
411
          '#attributes' => array('class' => array('links', 'inline')),
412
        ),
413
      );
414
    }
415
    elseif (!empty($operations)) {
416
      // Render the first and only operation as a link.
417
      $link = reset($operations);
418
      $options[$file->fid]['operations'] = array(
419
        'data' => array(
420
          '#type' => 'link',
421
          '#title' => $link['title'],
422
          '#href' => $link['href'],
423
          '#options' => array('query' => $link['query']),
424
        ),
425
      );
426
    }
427
  }
428
429
  // Only use a tableselect when the current user is able to perform any
430
  // operations.
431
  if ($admin_access) {
432
    $form['files'] = array(
433
      '#type' => 'tableselect',
434
      '#header' => $header,
435
      '#options' => $options,
436
      '#empty' => t('No files available.'),
437
    );
438
  }
439
  // Otherwise, use a simple table.
440
  else {
441
    $form['files'] = array(
442
      '#theme' => 'table',
443
      '#header' => $header,
444
      '#rows' => $options,
445
      '#empty' => t('No files available.'),
446
    );
447
  }
448
449
  $form['pager'] = array('#markup' => theme('pager'));
450
  return $form;
451
}
452
453
/**
454
 * Validate file_entity_admin_files form submissions.
455
 *
456
 * Check if any files have been selected to perform the chosen
457
 * 'Update option' on.
458
 */
459
function file_entity_admin_files_validate($form, &$form_state) {
460
  // Error if there are no items to select.
461
  if (!is_array($form_state['values']['files']) || !count(array_filter($form_state['values']['files']))) {
462
    form_set_error('', t('No items selected.'));
463
  }
464
}
465
466
/**
467
 * Process file_entity_admin_files form submissions.
468
 *
469
 * Execute the chosen 'Update option' on the selected files.
470
 */
471
function file_entity_admin_files_submit($form, &$form_state) {
472
  $operations = module_invoke_all('file_operations');
473
  $operation = $operations[$form_state['values']['operation']];
474
  // Filter out unchecked files.
475
  $files = array_filter($form_state['values']['files']);
476
  if ($function = $operation['callback']) {
477
    // Add in callback arguments if present.
478
    if (isset($operation['callback arguments'])) {
479
      $args = array_merge(array($files), $operation['callback arguments']);
480
    }
481
    else {
482
      $args = array($files);
483
    }
484
    call_user_func_array($function, $args);
485
486
    cache_clear_all();
487
  }
488
  else {
489
    // We need to rebuild the form to go to a second step. For example, to
490
    // show the confirmation form for the deletion of files.
491
    $form_state['rebuild'] = TRUE;
492
  }
493
}
494
495
/**
496
 * File entity delete confirmation.
497
 */
498
function file_entity_multiple_delete_confirm($form, &$form_state, $files) {
499
  $form['files'] = array(
500
    '#prefix' => '<ul>',
501
    '#suffix' => '</ul>',
502
    '#tree' => TRUE,
503
  );
504
  // array_filter returns only elements with TRUE values.
505
  foreach ($files as $fid => $value) {
506
    $filename = db_query('SELECT filename FROM {file_managed} WHERE fid = :fid', array(':fid' => $fid))->fetchField();
507
    $form['files'][$fid] = array(
508
      '#type' => 'hidden',
509
      '#value' => $fid,
510
      '#prefix' => '<li>',
511
      '#suffix' => check_plain($filename) . "</li>\n",
512
    );
513
  }
514
  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
515
  $form['#submit'][] = 'file_entity_multiple_delete_confirm_submit';
516
  $confirm_question = format_plural(count($files),
517
                                  'Are you sure you want to delete this item?',
518
                                  'Are you sure you want to delete these items?');
519
  return confirm_form($form,
520
                    $confirm_question,
521
                    'admin/content/file', t('This action cannot be undone.'),
522
                    t('Delete'), t('Cancel'));
523
}
524
525
/**
526
 * Submit handler for delete confirmation.
527
 */
528
function file_entity_multiple_delete_confirm_submit($form, &$form_state) {
529
  if ($form_state['values']['confirm']) {
530
    file_delete_multiple(array_keys($form_state['values']['files']));
531
    $count = count($form_state['values']['files']);
532
    watchdog('file_entity', 'Deleted @count files.', array('@count' => $count));
533
    drupal_set_message(format_plural($count, 'Deleted 1 file.', 'Deleted @count files.'));
534
  }
535
  $form_state['redirect'] = 'admin/content/file';
536
}
537
538
/**
539
 * Displays the file type admin overview page.
540
 */
541
function file_entity_list_types_page() {
542
  $file_entity_info = entity_get_info('file');
543
  $field_ui = module_exists('field_ui');
544
  $colspan = $field_ui ? 5 : 3;
545
  $header = array(
546
    array('data' => t('Name')),
547
    array('data' => t('Operations'), 'colspan' => $colspan),
548
    array('data' => t('Status')),
549
  );
550
  $rows = array();
551
  $weight = 0;
552
  $types = file_type_load_all(TRUE);
553
  $count = count($types);
554
  foreach ($types as $type) {
555
    $weight++;
556
    $row = array(
557
      array(
558
        'data' => theme('file_entity_file_type_overview',
559
          array(
560
            'label' => $type->label,
561
            'description' => $type->description,
562
          )
563
        ),
564
      ),
565
    );
566
    $path = isset($file_entity_info['bundles'][$type->type]['admin']['real path']) ? $file_entity_info['bundles'][$type->type]['admin']['real path'] : NULL;
567
568
    if (empty($type->disabled) && isset($path)) {
569
      $row[] = array('data' => l(t('edit file type'), $path . '/edit'));
570
      if ($field_ui) {
571
        $row[] = array('data' => l(t('manage fields'), $path . '/fields'));
572
        $row[] = array('data' => l(t('manage display'), $path . '/display'));
573
      }
574
      $row[] = array('data' => l(t('manage file display'), $path . '/file-display'));
575
    }
576
    else {
577
      $row += array_fill(1, $colspan - 1, '');
578
    }
579
580
    $admin_path = 'admin/structure/file-types/manage/' . $type->type;
581
    switch ($type->ctools_type) {
582
      // Configuration is in code.
583
      case 'Default':
584
        if (!empty($type->disabled)) {
585
          $row[] = l(t('enable'), $admin_path . '/enable');
586
        }
587
        else {
588
          $row[] = l(t('disable'), $admin_path . '/disable');
589
        }
590
        break;
591
592
      // Configuration is in DB.
593
      case 'Normal':
594
        if (!empty($type->disabled)) {
595
          $status = l(t('enable'), $admin_path . '/enable');
596
        }
597
        else {
598
          $status = l(t('disable'), $admin_path . '/disable');
599
        }
600
        $row[] = $status . ' | ' . l(t('delete'), $admin_path . '/delete');
601
        break;
602
603
      // Configuration is in code, but overridden in DB.
604
      case 'Overridden':
605
        if (!empty($type->disabled)) {
606
          $row[] = l(t('enable'), $admin_path . '/enable');
607
        }
608
        else {
609
          $row[] = l(t('disable'), $admin_path . '/disable') . ' | ' . l(t('revert'), $admin_path . '/revert');
610
        }
611
        break;
612
    }
613
614
    if (!empty($type->disabled)) {
615
      $row[] = t('Disabled');
616
      $rows[$weight + $count] = array('data' => $row, 'class' => array('ctools-export-ui-disabled'));
617
    }
618
    else {
619
      $row[] = $type->ctools_type;
620
      $rows[$weight] = array('data' => $row);
621
    }
622
  }
623
624
  // Move disabled items to the bottom.
625
  ksort($rows);
626
627
  $build['file_type_table'] = array(
628
    '#theme' => 'table',
629
    '#header' => $header,
630
    '#rows' => $rows,
631
    '#empty' => t('No file types available.'),
632
    '#attached' => array(
633
      'css' => array(drupal_get_path('module', 'ctools') . '/css/export-ui-list.css'),
634
    ),
635
  );
636
637
  return $build;
638
}
639
640
/**
641
 * Form callback; presents file display settings for a given view mode.
642
 */
643
function file_entity_file_display_form($form, &$form_state, $file_type, $view_mode) {
644
  $form['#file_type'] = $file_type->type;
645
  $form['#view_mode'] = $view_mode;
646
  $form['#tree'] = TRUE;
647
  $form['#attached']['js'][] = drupal_get_path('module', 'file_entity') . '/file_entity.admin.js';
648
649
  // Retrieve available formatters for this file type and load all configured
650
  // filters for existing text formats.
651
  $formatters = file_info_formatter_types();
652
  foreach ($formatters as $name => $formatter) {
653
    if (!empty($formatter['hidden'])) {
654
      unset($formatters[$name]);
655
    }
656
    if (isset($formatter['mime types'])) {
657
      if (file_entity_match_mimetypes($formatter['mime types'], $file_type->mimetypes)) {
658
        continue;
659
      }
660
      unset($formatters[$name]);
661
    }
662
  }
663
  $current_displays = file_displays_load($file_type->type, $view_mode, TRUE);
664
  foreach ($current_displays as $name => $display) {
665
    $current_displays[$name] = (array) $display;
666
  }
667
668
  // Formatter status.
669
  $form['displays']['status'] = array(
670
    '#type' => 'item',
671
    '#title' => t('Enabled displays'),
672
    '#prefix' => '<div id="file-displays-status-wrapper">',
673
    '#suffix' => '</div>',
674
  );
675
  $i = 0;
676
  foreach ($formatters as $name => $formatter) {
677
    $form['displays']['status'][$name] = array(
678
      '#type' => 'checkbox',
679
      '#title' => check_plain($formatter['label']),
680
      '#default_value' => !empty($current_displays[$name]['status']),
681
      '#description' => isset($formatter['description']) ? filter_xss($formatter['description']) : NULL,
682
      '#parents' => array('displays', $name, 'status'),
683
      '#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
684
    );
685
    $i++;
686
  }
687
688
  // Formatter order (tabledrag).
689
  $form['displays']['order'] = array(
690
    '#type' => 'item',
691
    '#title' => t('Display precedence order'),
692
    '#theme' => 'file_entity_file_display_order',
693
  );
694
  foreach ($formatters as $name => $formatter) {
695
    $form['displays']['order'][$name]['label'] = array(
696
      '#markup' => check_plain($formatter['label']),
697
    );
698
    $form['displays']['order'][$name]['weight'] = array(
699
      '#type' => 'weight',
700
      '#title' => t('Weight for @title', array('@title' => $formatter['label'])),
701
      '#title_display' => 'invisible',
702
      '#delta' => 50,
703
      '#default_value' => isset($current_displays[$name]['weight']) ? $current_displays[$name]['weight'] : 0,
704
      '#parents' => array('displays', $name, 'weight'),
705
    );
706
    $form['displays']['order'][$name]['#weight'] = $form['displays']['order'][$name]['weight']['#default_value'];
707
  }
708
709
  // Formatter settings.
710
  $form['display_settings_title'] = array(
711
    '#type' => 'item',
712
    '#title' => t('Display settings'),
713
  );
714
  $form['display_settings'] = array(
715
    '#type' => 'vertical_tabs',
716
  );
717
  $i = 0;
718
  foreach ($formatters as $name => $formatter) {
719
    if (isset($formatter['settings callback']) && ($function = $formatter['settings callback']) && function_exists($function)) {
720
      $defaults = !empty($formatter['default settings']) ? $formatter['default settings'] : array();
721
      $settings = !empty($current_displays[$name]['settings']) ? $current_displays[$name]['settings'] : array();
722
      $settings += $defaults;
723
      $settings_form = $function($form, $form_state, $settings, $name, $file_type->type, $view_mode);
724
      if (!empty($settings_form)) {
725
        $form['displays']['settings'][$name] = array(
726
          '#type' => 'fieldset',
727
          '#title' => check_plain($formatter['label']),
728
          '#parents' => array('displays', $name, 'settings'),
729
          '#group' => 'display_settings',
730
          '#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
731
        ) + $settings_form;
732
      }
733
    }
734
    $i++;
735
  }
736
737
  $form['actions'] = array('#type' => 'actions');
738
  $form['actions']['submit'] = array(
739
    '#type' => 'submit',
740
    '#value' => t('Save configuration'),
741
  );
742
743
  return $form;
744
}
745
746
/**
747
 * Process file display settings form submissions.
748
 */
749
function file_entity_file_display_form_submit($form, &$form_state) {
750
  $file_type = $form['#file_type'];
751
  $view_mode = $form['#view_mode'];
752
  $displays = isset($form_state['values']['displays']) ? $form_state['values']['displays'] : array();
753
  $displays_original = file_displays_load($file_type, $view_mode, TRUE);
754
  foreach ($displays as $formatter_name => $display) {
755
    $display_original = isset($displays_original[$formatter_name]) ? $displays_original[$formatter_name] : file_display_new($file_type, $view_mode, $formatter_name);
756
    $display += (array) $display_original;
757
    file_display_save((object) $display);
758
  }
759
  drupal_set_message(t('Your settings have been saved.'));
760
}
761
762
/**
763
 * Returns HTML for the file type overview page.
764
 *
765
 * Specifically, this returns HTML for a file type label and description.
766
 */
767
function theme_file_entity_file_type_overview($variables) {
768
  return check_plain($variables['label']) . '<div class="description">' . $variables['description'] . '</div>';
769
}
770
771
/**
772
 * Returns HTML for a file display's display order table.
773
 */
774
function theme_file_entity_file_display_order($variables) {
775
  $element = $variables['element'];
776
777
  $rows = array();
778
  foreach (element_children($element, TRUE) as $name) {
779
    $element[$name]['weight']['#attributes']['class'][] = 'file-display-order-weight';
780
    $rows[] = array(
781
      'data' => array(
782
        drupal_render($element[$name]['label']),
783
        drupal_render($element[$name]['weight']),
784
      ),
785
      'class' => array('draggable'),
786
    );
787
  }
788
  $output = drupal_render_children($element);
789
  $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'file-displays-order')));
790
  drupal_add_tabledrag('file-displays-order', 'order', 'sibling', 'file-display-order-weight', NULL, NULL, TRUE);
791
792
  return $output;
793
}
794
795
/**
796
 * Form constructor for the file type settings form.
797
 *
798
 * @param object $type
799
 *   The file type.
800
 *
801
 * @see file_entity_file_type_form_validate()
802
 * @see file_entity_file_type_form_submit()
803
 */
804
function file_entity_file_type_form($form, &$form_state, $type = NULL) {
805
  if (!isset($type->type)) {
806
    // This is a new type.
807
    $type = (object) array(
808
      'type' => '',
809
      'label' => '',
810
      'description' => '',
811
      'mimetypes' => array(),
812
    );
813
  }
814
  $form['#file_type'] = $type;
815
816
  $form['label'] = array(
817
    '#type' => 'textfield',
818
    '#title' => t('Name'),
819
    '#description' => t('This is the human readable name of the file type.'),
820
    '#required' => TRUE,
821
    '#default_value' => $type->label,
822
  );
823
824
  $form['type'] = array(
825
    '#type' => 'machine_name',
826
    '#default_value' => $type->type,
827
    '#maxlength' => 255,
828
    '#disabled' => (bool) $type->type,
829
    '#machine_name' => array(
830
      'exists' => 'file_type_load',
831
      'source' => array('label'),
832
    ),
833
    '#description' => t('A unique machine-readable name for this file type. It must only contain lowercase letters, numbers, and underscores.'),
834
  );
835
836
  $form['description'] = array(
837
    '#type' => 'textarea',
838
    '#title' => t('Description'),
839
    '#description' => t('This is the description of the file type.'),
840
    '#default_value' => $type->description,
841
  );
842
843
  $form['mimetypes'] = array(
844
    '#type' => 'textarea',
845
    '#title' => t('Mimetypes'),
846
    '#description' => t('Enter one mimetype per line.'),
847
    '#default_value' => implode("\n", $type->mimetypes),
848
  );
849
850
  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
851
  $mimetypes = file_mimetype_mapping();
852
853
  $form['mimetype_mapping'] = array(
854
    '#type' => 'fieldset',
855
    '#title' => t('Mimetype List'),
856
    '#collapsible' => TRUE,
857
    '#collapsed' => TRUE,
858
  );
859
  $form['mimetype_mapping']['mapping'] = array(
860
    '#theme' => 'item_list',
861
    '#items' => $mimetypes['mimetypes'],
862
  );
863
864
  $form['actions'] = array('#type' => 'actions');
865
866
  $form['actions']['submit'] = array(
867
    '#type' => 'submit',
868
    '#value' => t('Save'),
869
  );
870
  if (!empty($type->type)) {
871
    $form['actions']['delete'] = array(
872
      '#type' => 'submit',
873
      '#value' => t('Delete'),
874
    );
875
  }
876
877
  return $form;
878
}
879
880
/**
881
 * Form validation handler for file_entity_file_type_form().
882
 *
883
 * @see file_entity_file_type_form_submit()
884
 */
885
function file_entity_file_type_form_validate($form, &$form_state) {
886
  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
887
  $mimetype_mapping = file_mimetype_mapping();
888
889
  $valid_mimetypes = $mimetype_mapping['mimetypes'];
890
  $submitted_mimetypes = array_filter(array_map('trim', explode("\n", $form_state['values']['mimetypes'])));
891
892
  $invalid_mimetypes = array();
893
  foreach ($submitted_mimetypes as $mimetype) {
894
    if (!file_entity_match_mimetypes($mimetype, $valid_mimetypes)) {
895
      $invalid_mimetypes[] = $mimetype;
896
    }
897
  }
898
899
  foreach ($invalid_mimetypes as $mimetype) {
900
    form_set_error('mimetypes', t('The mimetype %mimetype is not a valid mimetype.', array('%mimetype' => $mimetype)));
901
  }
902
}
903
904
/**
905
 * Form submission handler for file_entity_file_type_form().
906
 *
907
 * @see file_entity_file_type_form_validate()
908
 */
909
function file_entity_file_type_form_submit($form, &$form_state) {
910
  if (!empty($form['#file_type']->type)) {
911
    $type = file_type_load($form['#file_type']->type);
912
  }
913
  else {
914
    $type = (object) array(
915
      'type' => $form_state['values']['type'],
916
    );
917
  }
918
  if ($form_state['values']['op'] == t('Delete')) {
919
    $form_state['redirect'] = 'admin/structure/file-types/manage/' . $type->type . '/delete';
920
    return;
921
  }
922
  $type->label = $form_state['values']['label'];
923
  $type->description = $form_state['values']['description'];
924
  $type->mimetypes = array_filter(array_map('trim', explode("\n", $form_state['values']['mimetypes'])));
925
926
  file_type_save($type);
927
928
  drupal_set_message(t('The file type %type has been updated.', array('%type' => $type->label)));
929
  $form_state['redirect'] = 'admin/structure/file-types';
930
}
931
932
933
/**
934
 * Menu callback; disable a single file type.
935
 */
936
function file_entity_type_enable_confirm($form, &$form_state, $type) {
937
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
938
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
939
  $message = t('Are you sure you want to enable the file type %type?', array('%type' => $type->label));
940
  return confirm_form($form, $message, 'admin/structure/file-types', '', t('Enable'));
941
}
942
943
944
/**
945
 * Process file type disable confirm submissions.
946
 */
947
function file_entity_type_enable_confirm_submit($form, &$form_state) {
948
  file_type_enable($form_state['values']['type']);
949
  $t_args = array('%label' => $form_state['values']['label']);
950
  drupal_set_message(t('The file type %label has been enabled.', $t_args));
951
  watchdog('file_entity', 'Enabled file type %label.', $t_args, WATCHDOG_NOTICE);
952
  $form_state['redirect'] = 'admin/structure/file-types';
953
  return;
954
}
955
956
957
/**
958
 * Menu callback; disable a single file type.
959
 */
960
function file_entity_type_disable_confirm($form, &$form_state, $type) {
961
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
962
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
963
964
  $message = t('Are you sure you want to disable the file type %type?', array('%type' => $type->label));
965
  $caption = '';
966
967
  $num_files = db_query("SELECT COUNT(*) FROM {file_managed} WHERE type = :type", array(':type' => $type->type))->fetchField();
968
  if ($num_files) {
969
    $caption .= '<p>' . format_plural($num_files, '%type is used by 1 file on
970
      your site. If you disable this file type, you will not be able to edit
971
      the %type file and it may not display correctly.', '%type is used by
972
      @count files on your site. If you remove %type, you will not be able to
973
      edit the %type file and it may not display correctly.',
974
    array('%type' => $type->label)) . '</p>';
975
  }
976
977
  return confirm_form($form, $message, 'admin/structure/file-types', $caption, t('Disable'));
978
}
979
980
981
/**
982
 * Process file type disable confirm submissions.
983
 */
984
function file_entity_type_disable_confirm_submit($form, &$form_state) {
985
  file_type_disable($form_state['values']['type']);
986
  $t_args = array('%label' => $form_state['values']['label']);
987
  drupal_set_message(t('The file type %label has been disabled.', $t_args));
988
  watchdog('file_entity', 'Disabled file type %label.', $t_args, WATCHDOG_NOTICE);
989
  $form_state['redirect'] = 'admin/structure/file-types';
990
  return;
991
}
992
993
994
/**
995
 * Menu callback; revert a single file type.
996
 */
997
function file_entity_type_revert_confirm($form, &$form_state, $type) {
998
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
999
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
1000
  $message = t('Are you sure you want to revert the file type %type?', array('%type' => $type->label));
1001
  return confirm_form($form, $message, 'admin/structure/file-types', '', t('Revert'));
1002
}
1003
1004
1005
/**
1006
 * Process file type delete confirm submissions.
1007
 */
1008
function file_entity_type_revert_confirm_submit($form, &$form_state) {
1009
  // @NOTE deleting the file_type from the DB actually reverts it to code.
1010
  file_type_delete($form_state['values']['type']);
1011
  $t_args = array('%label' => $form_state['values']['label']);
1012
  drupal_set_message(t('The file type %label has been reverted.', $t_args));
1013
  watchdog('file_entity', 'Reverted file type %label.', $t_args, WATCHDOG_NOTICE);
1014
  $form_state['redirect'] = 'admin/structure/file-types';
1015
  return;
1016
}
1017
1018
1019
/**
1020
 * Menu callback; delete a single file type.
1021
 */
1022
function file_entity_type_delete_confirm($form, &$form_state, $type) {
1023
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
1024
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
1025
1026
  $message = t('Are you sure you want to delete the file type %type?', array('%type' => $type->label));
1027
  $caption = '';
1028
1029
  $num_files = db_query("SELECT COUNT(*) FROM {file_managed} WHERE type = :type", array(':type' => $type->type))->fetchField();
1030
  if ($num_files) {
1031
    $caption .= '<p>' . format_plural($num_files, '%type is used by 1 file on your site. If you remove this file type, you will not be able to edit the %type file and it may not display correctly.', '%type is used by @count pieces of file on your site. If you remove %type, you will not be able to edit the %type file and it may not display correctly.', array('%type' => $type->label)) . '</p>';
1032
  }
1033
1034
  $caption .= '<p>' . t('This action cannot be undone.') . '</p>';
1035
1036
  return confirm_form($form, $message, 'admin/structure/file-types', $caption, t('Delete'));
1037
}
1038
1039
/**
1040
 * Process file type delete confirm submissions.
1041
 */
1042
function file_entity_type_delete_confirm_submit($form, &$form_state) {
1043
  file_type_delete($form_state['values']['type']);
1044
1045
  $t_args = array('%label' => $form_state['values']['label']);
1046
  drupal_set_message(t('The file type %label has been deleted.', $t_args));
1047
  watchdog('file_entity', 'Deleted file type %label.', $t_args, WATCHDOG_NOTICE);
1048
1049
  $form_state['redirect'] = 'admin/structure/file-types';
1050
  return;
1051
}
1052
1053
/**
1054
 * Form callback for file_entity settings.
1055
 */
1056
function file_entity_settings_form($form, &$form_state) {
1057
  $form['file_entity_max_filesize'] = array(
1058
    '#type' => 'textfield',
1059
    '#title' => t('Maximum upload size'),
1060
    '#default_value' => variable_get('file_entity_max_filesize', ''),
1061
    '#description' => t('Enter a value like "512" (bytes), "80 KB" (kilobytes) or "50 MB" (megabytes) in order to restrict the allowed file size. If left empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current max limit <strong>%limit</strong>).', array('%limit' => format_size(file_upload_max_size()))),
1062
    '#size' => 10,
1063
    '#element_validate' => array('_file_generic_settings_max_filesize'),
1064
  );
1065
1066
  $form['file_entity_default_allowed_extensions'] = array(
1067
    '#type' => 'textfield',
1068
    '#title' => t('Default allowed file extensions'),
1069
    '#default_value' => variable_get('file_entity_default_allowed_extensions', 'jpg jpeg gif png txt doc docx xls xlsx pdf ppt pptx pps ppsx odt ods odp mp3 mov mp4 m4a m4v mpeg avi ogg oga ogv weba webp webm'),
1070
    '#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
1071 ca0757b9 Assos Assos
    '#maxlength' => NULL,
1072 85ad3d82 Assos Assos
  );
1073
1074
  $form['file_entity_alt'] = array(
1075
    '#type' => 'textfield',
1076
    '#title' => t('Alt attribute'),
1077
    '#description' => t('The text to use as value for the <em>img</em> tag <em>alt</em> attribute.'),
1078
    '#default_value' => variable_get('file_entity_alt', '[file:field_file_image_alt_text]'),
1079
  );
1080
  $form['file_entity_title'] = array(
1081
    '#type' => 'textfield',
1082
    '#title' => t('Title attribute'),
1083
    '#description' => t('The text to use as value for the <em>img</em> tag <em>title</em> attribute.'),
1084
    '#default_value' => variable_get('file_entity_title', '[file:field_file_image_title_text]'),
1085
  );
1086
1087
  // Provide default token values.
1088
  if (module_exists('token')) {
1089
    $form['token_help'] = array(
1090
      '#theme' => 'token_tree',
1091
      '#token_types' => array('file'),
1092
      '#dialog' => TRUE,
1093
    );
1094
    $form['file_entity_alt']['#description'] .= t('This field supports tokens.');
1095
    $form['file_entity_title']['#description'] .= t('This field supports tokens.');
1096
  }
1097
  $form['file_upload_wizard'] = array(
1098
    '#type' => 'fieldset',
1099
    '#title' => t('File upload wizard'),
1100
    '#collapsible' => TRUE,
1101
    '#collapsed' => FALSE,
1102
    '#description' => t('Configure the steps available when uploading a new file.'),
1103
  );
1104
  $form['file_upload_wizard']['file_entity_file_upload_wizard_skip_file_type'] = array(
1105
    '#type' => 'checkbox',
1106
    '#title' => t('Skip filetype selection.'),
1107
    '#default_value' => variable_get('file_entity_file_upload_wizard_skip_file_type', FALSE),
1108
    '#description' => t('The file type selection step is only available if the uploaded file falls into two or more file types. If this step is skipped, files with no available file type or two or more file types will not be assigned a file type.'),
1109
  );
1110
  $form['file_upload_wizard']['file_entity_file_upload_wizard_skip_scheme'] = array(
1111
    '#type' => 'checkbox',
1112
    '#title' => t('Skip scheme selection.'),
1113
    '#default_value' => variable_get('file_entity_file_upload_wizard_skip_scheme', FALSE),
1114
    '#description' => t('The scheme selection step is only available if two or more file destinations, such as public local files served by the webserver and private local files served by Drupal, are available. If this step is skipped, files will automatically be saved using the default download method.'),
1115
  );
1116
  $form['file_upload_wizard']['file_entity_file_upload_wizard_skip_fields'] = array(
1117
    '#type' => 'checkbox',
1118
    '#title' => t('Skip available fields.'),
1119
    '#default_value' => variable_get('file_entity_file_upload_wizard_skip_fields', FALSE),
1120
    '#description' => t('The field selection step is only available if the file type the file belongs to has any available fields. If this step is skipped, any fields on the file will be left blank.'),
1121
  );
1122
1123
  return system_settings_form($form);
1124
}