Projet

Général

Profil

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

root / drupal7 / sites / all / modules / file_entity / file_entity.admin.inc @ 87dbc3bf

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
  $query->addExpression('SUM(fu.count)', 'total_count');
335
  file_entity_build_filter_query($query);
336
337
  $result = $query
338
    ->fields('fm', array('fid', 'uid'))
339
    ->limit(50)
340
    ->orderByHeader($header)
341
    ->addTag('file_access')
342
    ->execute()
343
    ->fetchAllAssoc('fid');
344
  $files = file_load_multiple(array_keys($result));
345
346
  $uids = array();
347
  foreach ($files as $file) {
348
    $uids[] = $file->uid;
349
  }
350
  $accounts = !empty($uids) ? user_load_multiple(array_unique($uids)) : array();
351
352
  // Prepare the list of files.
353
  $destination = drupal_get_destination();
354
  $options = array();
355
  foreach ($files as $file) {
356
    $file_type = file_type_load($file->type);
357
    $options[$file->fid] = array(
358
      'title' => array(
359
        'data' => array(
360
          '#type' => 'link',
361
          '#title' => $file->filename,
362
          '#href' => 'file/' . $file->fid,
363
        ),
364
      ),
365
      'type' => $file_type ? check_plain($file_type->label) : FILE_TYPE_NONE,
366
      'size' => format_size($file->filesize),
367
      'author' => theme('username', array('account' => $accounts[$file->uid])),
368
      'timestamp' => format_date($file->timestamp, 'short'),
369
      'usage' => format_plural((int) $result[$file->fid]->total_count, '1 place', '@count places'),
370
    );
371
372
    // Show a warning for files that do not exist.
373
    if (@!is_file($file->uri)) {
374
      $options[$file->fid]['#attributes']['class'][] = 'error';
375
      if (!file_stream_wrapper_get_instance_by_uri($file->uri)) {
376
        $options[$file->fid]['#attributes']['title'] = t('The stream wrapper for @scheme files is missing.', array('@scheme' => file_uri_scheme($file->uri)));
377
      }
378
      else {
379
        $options[$file->fid]['#attributes']['title'] = t('The file does not exist.');
380
      }
381
    }
382
383
    // Build a list of all the accessible operations for the current file.
384
    $operations = array();
385
    if (file_entity_access('update', $file)) {
386
      // Convert the usage count to a link.
387
      $options[$file->fid]['usage'] = l($options[$file->fid]['usage'], 'file/' . $file->fid . '/usage');
388
      $operations['edit'] = array(
389
        'title' => t('Edit'),
390
        'href' => 'file/' . $file->fid . '/edit',
391
        'query' => $destination,
392
      );
393
    }
394
    if (file_entity_access('delete', $file)) {
395
      $operations['delete'] = array(
396
        'title' => t('Delete'),
397
        'href' => 'file/' . $file->fid . '/delete',
398
        'query' => $destination,
399
      );
400
    }
401
    $options[$file->fid]['operations'] = array();
402
    if (count($operations) > 1) {
403
      // Render an unordered list of operations links.
404
      $options[$file->fid]['operations'] = array(
405
        'data' => array(
406
          '#theme' => 'links__file_entity_operations',
407
          '#links' => $operations,
408
          '#attributes' => array('class' => array('links', 'inline')),
409
        ),
410
      );
411
    }
412
    elseif (!empty($operations)) {
413
      // Render the first and only operation as a link.
414
      $link = reset($operations);
415
      $options[$file->fid]['operations'] = array(
416
        'data' => array(
417
          '#type' => 'link',
418
          '#title' => $link['title'],
419
          '#href' => $link['href'],
420
          '#options' => array('query' => $link['query']),
421
        ),
422
      );
423
    }
424
  }
425
426
  // Only use a tableselect when the current user is able to perform any
427
  // operations.
428
  if ($admin_access) {
429
    $form['files'] = array(
430
      '#type' => 'tableselect',
431
      '#header' => $header,
432
      '#options' => $options,
433
      '#empty' => t('No files available.'),
434
    );
435
  }
436
  // Otherwise, use a simple table.
437
  else {
438
    $form['files'] = array(
439
      '#theme' => 'table',
440
      '#header' => $header,
441
      '#rows' => $options,
442
      '#empty' => t('No files available.'),
443
    );
444
  }
445
446
  $form['pager'] = array('#markup' => theme('pager'));
447
  return $form;
448
}
449
450
/**
451
 * Validate file_entity_admin_files form submissions.
452
 *
453
 * Check if any files have been selected to perform the chosen
454
 * 'Update option' on.
455
 */
456
function file_entity_admin_files_validate($form, &$form_state) {
457
  // Error if there are no items to select.
458
  if (!is_array($form_state['values']['files']) || !count(array_filter($form_state['values']['files']))) {
459
    form_set_error('', t('No items selected.'));
460
  }
461
}
462
463
/**
464
 * Process file_entity_admin_files form submissions.
465
 *
466
 * Execute the chosen 'Update option' on the selected files.
467
 */
468
function file_entity_admin_files_submit($form, &$form_state) {
469
  $operations = module_invoke_all('file_operations');
470
  $operation = $operations[$form_state['values']['operation']];
471
  // Filter out unchecked files.
472
  $files = array_filter($form_state['values']['files']);
473
  if ($function = $operation['callback']) {
474
    // Add in callback arguments if present.
475
    if (isset($operation['callback arguments'])) {
476
      $args = array_merge(array($files), $operation['callback arguments']);
477
    }
478
    else {
479
      $args = array($files);
480
    }
481
    call_user_func_array($function, $args);
482
483
    cache_clear_all();
484
  }
485
  else {
486
    // We need to rebuild the form to go to a second step. For example, to
487
    // show the confirmation form for the deletion of files.
488
    $form_state['rebuild'] = TRUE;
489
  }
490
}
491
492
/**
493
 * File entity delete confirmation.
494
 */
495
function file_entity_multiple_delete_confirm($form, &$form_state, $files) {
496
  $form['files'] = array(
497
    '#prefix' => '<ul>',
498
    '#suffix' => '</ul>',
499
    '#tree' => TRUE,
500
  );
501
  // array_filter returns only elements with TRUE values.
502
  foreach ($files as $fid => $value) {
503
    $filename = db_query('SELECT filename FROM {file_managed} WHERE fid = :fid', array(':fid' => $fid))->fetchField();
504
    $form['files'][$fid] = array(
505
      '#type' => 'hidden',
506
      '#value' => $fid,
507
      '#prefix' => '<li>',
508
      '#suffix' => check_plain($filename) . "</li>\n",
509
    );
510
  }
511
  $form['operation'] = array('#type' => 'hidden', '#value' => 'delete');
512
  $form['#submit'][] = 'file_entity_multiple_delete_confirm_submit';
513
  $confirm_question = format_plural(count($files),
514
                                  'Are you sure you want to delete this item?',
515
                                  'Are you sure you want to delete these items?');
516
  return confirm_form($form,
517
                    $confirm_question,
518
                    'admin/content/file', t('This action cannot be undone.'),
519
                    t('Delete'), t('Cancel'));
520
}
521
522
/**
523
 * Submit handler for delete confirmation.
524
 */
525
function file_entity_multiple_delete_confirm_submit($form, &$form_state) {
526
  if ($form_state['values']['confirm']) {
527
    file_delete_multiple(array_keys($form_state['values']['files']));
528
    $count = count($form_state['values']['files']);
529
    watchdog('file_entity', 'Deleted @count files.', array('@count' => $count));
530
    drupal_set_message(format_plural($count, 'Deleted 1 file.', 'Deleted @count files.'));
531
  }
532
  $form_state['redirect'] = 'admin/content/file';
533
}
534
535
/**
536
 * Displays the file type admin overview page.
537
 */
538
function file_entity_list_types_page() {
539
  $file_entity_info = entity_get_info('file');
540
  $field_ui = module_exists('field_ui');
541
  $colspan = $field_ui ? 5 : 3;
542
  $header = array(
543
    array('data' => t('Name')),
544
    array('data' => t('Operations'), 'colspan' => $colspan),
545
    array('data' => t('Status')),
546
  );
547
  $rows = array();
548
  $weight = 0;
549
  $types = file_type_load_all(TRUE);
550
  $count = count($types);
551
  foreach ($types as $type) {
552
    $weight++;
553
    $row = array(
554
      array(
555
        'data' => theme('file_entity_file_type_overview',
556
          array(
557
            'label' => $type->label,
558
            'description' => $type->description,
559
          )
560
        ),
561
      ),
562
    );
563
    $path = isset($file_entity_info['bundles'][$type->type]['admin']['real path']) ? $file_entity_info['bundles'][$type->type]['admin']['real path'] : NULL;
564
565
    if (empty($type->disabled) && isset($path)) {
566
      $row[] = array('data' => l(t('edit file type'), $path . '/edit'));
567
      if ($field_ui) {
568
        $row[] = array('data' => l(t('manage fields'), $path . '/fields'));
569
        $row[] = array('data' => l(t('manage display'), $path . '/display'));
570
      }
571
      $row[] = array('data' => l(t('manage file display'), $path . '/file-display'));
572
    }
573
    else {
574
      $row += array_fill(1, $colspan - 1, '');
575
    }
576
577
    $admin_path = 'admin/structure/file-types/manage/' . $type->type;
578
    switch ($type->ctools_type) {
579
      // Configuration is in code.
580
      case 'Default':
581
        if (!empty($type->disabled)) {
582
          $row[] = l(t('enable'), $admin_path . '/enable');
583
        }
584
        else {
585
          $row[] = l(t('disable'), $admin_path . '/disable');
586
        }
587
        break;
588
589
      // Configuration is in DB.
590
      case 'Normal':
591
        if (!empty($type->disabled)) {
592
          $status = l(t('enable'), $admin_path . '/enable');
593
        }
594
        else {
595
          $status = l(t('disable'), $admin_path . '/disable');
596
        }
597
        $row[] = $status . ' | ' . l(t('delete'), $admin_path . '/delete');
598
        break;
599
600
      // Configuration is in code, but overridden in DB.
601
      case 'Overridden':
602
        if (!empty($type->disabled)) {
603
          $row[] = l(t('enable'), $admin_path . '/enable');
604
        }
605
        else {
606
          $row[] = l(t('disable'), $admin_path . '/disable') . ' | ' . l(t('revert'), $admin_path . '/revert');
607
        }
608
        break;
609
    }
610
611
    if (!empty($type->disabled)) {
612
      $row[] = t('Disabled');
613
      $rows[$weight + $count] = array('data' => $row, 'class' => array('ctools-export-ui-disabled'));
614
    }
615
    else {
616
      $row[] = $type->ctools_type;
617
      $rows[$weight] = array('data' => $row);
618
    }
619
  }
620
621
  // Move disabled items to the bottom.
622
  ksort($rows);
623
624
  $build['file_type_table'] = array(
625
    '#theme' => 'table',
626
    '#header' => $header,
627
    '#rows' => $rows,
628
    '#empty' => t('No file types available.'),
629
    '#attached' => array(
630
      'css' => array(drupal_get_path('module', 'ctools') . '/css/export-ui-list.css'),
631
    ),
632
  );
633
634
  return $build;
635
}
636
637
/**
638
 * Form callback; presents file display settings for a given view mode.
639
 */
640
function file_entity_file_display_form($form, &$form_state, $file_type, $view_mode) {
641
  $form['#file_type'] = $file_type->type;
642
  $form['#view_mode'] = $view_mode;
643
  $form['#tree'] = TRUE;
644
  $form['#attached']['js'][] = drupal_get_path('module', 'file_entity') . '/file_entity.admin.js';
645
646
  // Retrieve available formatters for this file type and load all configured
647
  // filters for existing text formats.
648
  $formatters = file_info_formatter_types();
649
  foreach ($formatters as $name => $formatter) {
650
    if (!empty($formatter['hidden'])) {
651
      unset($formatters[$name]);
652
    }
653
    if (isset($formatter['mime types'])) {
654
      if (file_entity_match_mimetypes($formatter['mime types'], $file_type->mimetypes)) {
655
        continue;
656
      }
657
      unset($formatters[$name]);
658
    }
659
  }
660
  $current_displays = file_displays_load($file_type->type, $view_mode, TRUE);
661
  foreach ($current_displays as $name => $display) {
662
    $current_displays[$name] = (array) $display;
663
  }
664
665
  // Formatter status.
666
  $form['displays']['status'] = array(
667
    '#type' => 'item',
668
    '#title' => t('Enabled displays'),
669
    '#prefix' => '<div id="file-displays-status-wrapper">',
670
    '#suffix' => '</div>',
671
  );
672
  $i = 0;
673
  foreach ($formatters as $name => $formatter) {
674
    $form['displays']['status'][$name] = array(
675
      '#type' => 'checkbox',
676
      '#title' => check_plain($formatter['label']),
677
      '#default_value' => !empty($current_displays[$name]['status']),
678
      '#description' => isset($formatter['description']) ? filter_xss($formatter['description']) : NULL,
679
      '#parents' => array('displays', $name, 'status'),
680
      '#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
681
    );
682
    $i++;
683
  }
684
685
  // Formatter order (tabledrag).
686
  $form['displays']['order'] = array(
687
    '#type' => 'item',
688
    '#title' => t('Display precedence order'),
689
    '#theme' => 'file_entity_file_display_order',
690
  );
691
  foreach ($formatters as $name => $formatter) {
692
    $form['displays']['order'][$name]['label'] = array(
693
      '#markup' => check_plain($formatter['label']),
694
    );
695
    $form['displays']['order'][$name]['weight'] = array(
696
      '#type' => 'weight',
697
      '#title' => t('Weight for @title', array('@title' => $formatter['label'])),
698
      '#title_display' => 'invisible',
699
      '#delta' => 50,
700
      '#default_value' => isset($current_displays[$name]['weight']) ? $current_displays[$name]['weight'] : 0,
701
      '#parents' => array('displays', $name, 'weight'),
702
    );
703
    $form['displays']['order'][$name]['#weight'] = $form['displays']['order'][$name]['weight']['#default_value'];
704
  }
705
706
  // Formatter settings.
707
  $form['display_settings_title'] = array(
708
    '#type' => 'item',
709
    '#title' => t('Display settings'),
710
  );
711
  $form['display_settings'] = array(
712
    '#type' => 'vertical_tabs',
713
  );
714
  $i = 0;
715
  foreach ($formatters as $name => $formatter) {
716
    if (isset($formatter['settings callback']) && ($function = $formatter['settings callback']) && function_exists($function)) {
717
      $defaults = !empty($formatter['default settings']) ? $formatter['default settings'] : array();
718
      $settings = !empty($current_displays[$name]['settings']) ? $current_displays[$name]['settings'] : array();
719
      $settings += $defaults;
720
      $settings_form = $function($form, $form_state, $settings, $name, $file_type->type, $view_mode);
721
      if (!empty($settings_form)) {
722
        $form['displays']['settings'][$name] = array(
723
          '#type' => 'fieldset',
724
          '#title' => check_plain($formatter['label']),
725
          '#parents' => array('displays', $name, 'settings'),
726
          '#group' => 'display_settings',
727
          '#weight' => (isset($formatter['weight']) ? $formatter['weight'] : 0) + ($i / 1000),
728
        ) + $settings_form;
729
      }
730
    }
731
    $i++;
732
  }
733
734
  $form['actions'] = array('#type' => 'actions');
735
  $form['actions']['submit'] = array(
736
    '#type' => 'submit',
737
    '#value' => t('Save configuration'),
738
  );
739
740
  return $form;
741
}
742
743
/**
744
 * Process file display settings form submissions.
745
 */
746
function file_entity_file_display_form_submit($form, &$form_state) {
747
  $file_type = $form['#file_type'];
748
  $view_mode = $form['#view_mode'];
749
  $displays = isset($form_state['values']['displays']) ? $form_state['values']['displays'] : array();
750
  $displays_original = file_displays_load($file_type, $view_mode, TRUE);
751
  foreach ($displays as $formatter_name => $display) {
752
    $display_original = isset($displays_original[$formatter_name]) ? $displays_original[$formatter_name] : file_display_new($file_type, $view_mode, $formatter_name);
753
    $display += (array) $display_original;
754
    file_display_save((object) $display);
755
  }
756
  drupal_set_message(t('Your settings have been saved.'));
757
}
758
759
/**
760
 * Returns HTML for the file type overview page.
761
 *
762
 * Specifically, this returns HTML for a file type label and description.
763
 */
764
function theme_file_entity_file_type_overview($variables) {
765
  return check_plain($variables['label']) . '<div class="description">' . $variables['description'] . '</div>';
766
}
767
768
/**
769
 * Returns HTML for a file display's display order table.
770
 */
771
function theme_file_entity_file_display_order($variables) {
772
  $element = $variables['element'];
773
774
  $rows = array();
775
  foreach (element_children($element, TRUE) as $name) {
776
    $element[$name]['weight']['#attributes']['class'][] = 'file-display-order-weight';
777
    $rows[] = array(
778
      'data' => array(
779
        drupal_render($element[$name]['label']),
780
        drupal_render($element[$name]['weight']),
781
      ),
782
      'class' => array('draggable'),
783
    );
784
  }
785
  $output = drupal_render_children($element);
786
  $output .= theme('table', array('rows' => $rows, 'attributes' => array('id' => 'file-displays-order')));
787
  drupal_add_tabledrag('file-displays-order', 'order', 'sibling', 'file-display-order-weight', NULL, NULL, TRUE);
788
789
  return $output;
790
}
791
792
/**
793
 * Form constructor for the file type settings form.
794
 *
795
 * @param object $type
796
 *   The file type.
797
 *
798
 * @see file_entity_file_type_form_validate()
799
 * @see file_entity_file_type_form_submit()
800
 */
801
function file_entity_file_type_form($form, &$form_state, $type = NULL) {
802
  if (!isset($type->type)) {
803
    // This is a new type.
804
    $type = (object) array(
805
      'type' => '',
806
      'label' => '',
807
      'description' => '',
808
      'mimetypes' => array(),
809
    );
810
  }
811
  $form['#file_type'] = $type;
812
813
  $form['label'] = array(
814
    '#type' => 'textfield',
815
    '#title' => t('Name'),
816
    '#description' => t('This is the human readable name of the file type.'),
817
    '#required' => TRUE,
818
    '#default_value' => $type->label,
819
  );
820
821
  $form['type'] = array(
822
    '#type' => 'machine_name',
823
    '#default_value' => $type->type,
824
    '#maxlength' => 255,
825
    '#disabled' => (bool) $type->type,
826
    '#machine_name' => array(
827
      'exists' => 'file_type_load',
828
      'source' => array('label'),
829
    ),
830
    '#description' => t('A unique machine-readable name for this file type. It must only contain lowercase letters, numbers, and underscores.'),
831
  );
832
833
  $form['description'] = array(
834
    '#type' => 'textarea',
835
    '#title' => t('Description'),
836
    '#description' => t('This is the description of the file type.'),
837
    '#default_value' => $type->description,
838
  );
839
840
  $form['mimetypes'] = array(
841
    '#type' => 'textarea',
842
    '#title' => t('Mimetypes'),
843
    '#description' => t('Enter one mimetype per line.'),
844
    '#default_value' => implode("\n", $type->mimetypes),
845
  );
846
847
  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
848
  $mimetypes = file_mimetype_mapping();
849
850
  $form['mimetype_mapping'] = array(
851
    '#type' => 'fieldset',
852
    '#title' => t('Mimetype List'),
853
    '#collapsible' => TRUE,
854
    '#collapsed' => TRUE,
855
  );
856
  $form['mimetype_mapping']['mapping'] = array(
857
    '#theme' => 'item_list',
858
    '#items' => $mimetypes['mimetypes'],
859
  );
860
861
  $form['actions'] = array('#type' => 'actions');
862
863
  $form['actions']['submit'] = array(
864
    '#type' => 'submit',
865
    '#value' => t('Save'),
866
  );
867
  if (!empty($type->type)) {
868
    $form['actions']['delete'] = array(
869
      '#type' => 'submit',
870
      '#value' => t('Delete'),
871
    );
872
  }
873
874
  return $form;
875
}
876
877
/**
878
 * Form validation handler for file_entity_file_type_form().
879
 *
880
 * @see file_entity_file_type_form_submit()
881
 */
882
function file_entity_file_type_form_validate($form, &$form_state) {
883
  include_once DRUPAL_ROOT . '/includes/file.mimetypes.inc';
884
  $mimetype_mapping = file_mimetype_mapping();
885
886
  $valid_mimetypes = $mimetype_mapping['mimetypes'];
887
  $submitted_mimetypes = array_filter(array_map('trim', explode("\n", $form_state['values']['mimetypes'])));
888
889
  $invalid_mimetypes = array();
890
  foreach ($submitted_mimetypes as $mimetype) {
891
    if (!file_entity_match_mimetypes($mimetype, $valid_mimetypes)) {
892
      $invalid_mimetypes[] = $mimetype;
893
    }
894
  }
895
896
  foreach ($invalid_mimetypes as $mimetype) {
897
    form_set_error('mimetypes', t('The mimetype %mimetype is not a valid mimetype.', array('%mimetype' => $mimetype)));
898
  }
899
}
900
901
/**
902
 * Form submission handler for file_entity_file_type_form().
903
 *
904
 * @see file_entity_file_type_form_validate()
905
 */
906
function file_entity_file_type_form_submit($form, &$form_state) {
907
  if (!empty($form['#file_type']->type)) {
908
    $type = file_type_load($form['#file_type']->type);
909
  }
910
  else {
911
    $type = (object) array(
912
      'type' => $form_state['values']['type'],
913
    );
914
  }
915
  if ($form_state['values']['op'] == t('Delete')) {
916
    $form_state['redirect'] = 'admin/structure/file-types/manage/' . $type->type . '/delete';
917
    return;
918
  }
919
  $type->label = $form_state['values']['label'];
920
  $type->description = $form_state['values']['description'];
921
  $type->mimetypes = array_filter(array_map('trim', explode("\n", $form_state['values']['mimetypes'])));
922
923
  file_type_save($type);
924
925
  drupal_set_message(t('The file type %type has been updated.', array('%type' => $type->label)));
926
  $form_state['redirect'] = 'admin/structure/file-types';
927
}
928
929
930
/**
931
 * Menu callback; disable a single file type.
932
 */
933
function file_entity_type_enable_confirm($form, &$form_state, $type) {
934
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
935
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
936
  $message = t('Are you sure you want to enable the file type %type?', array('%type' => $type->label));
937
  return confirm_form($form, $message, 'admin/structure/file-types', '', t('Enable'));
938
}
939
940
941
/**
942
 * Process file type disable confirm submissions.
943
 */
944
function file_entity_type_enable_confirm_submit($form, &$form_state) {
945
  file_type_enable($form_state['values']['type']);
946
  $t_args = array('%label' => $form_state['values']['label']);
947
  drupal_set_message(t('The file type %label has been enabled.', $t_args));
948
  watchdog('file_entity', 'Enabled file type %label.', $t_args, WATCHDOG_NOTICE);
949
  $form_state['redirect'] = 'admin/structure/file-types';
950
  return;
951
}
952
953
954
/**
955
 * Menu callback; disable a single file type.
956
 */
957
function file_entity_type_disable_confirm($form, &$form_state, $type) {
958
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
959
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
960
961
  $message = t('Are you sure you want to disable the file type %type?', array('%type' => $type->label));
962
  $caption = '';
963
964
  $num_files = db_query("SELECT COUNT(*) FROM {file_managed} WHERE type = :type", array(':type' => $type->type))->fetchField();
965
  if ($num_files) {
966
    $caption .= '<p>' . format_plural($num_files, '%type is used by 1 file on
967
      your site. If you disable this file type, you will not be able to edit
968
      the %type file and it may not display correctly.', '%type is used by
969
      @count files on your site. If you remove %type, you will not be able to
970
      edit the %type file and it may not display correctly.',
971
    array('%type' => $type->label)) . '</p>';
972
  }
973
974
  return confirm_form($form, $message, 'admin/structure/file-types', $caption, t('Disable'));
975
}
976
977
978
/**
979
 * Process file type disable confirm submissions.
980
 */
981
function file_entity_type_disable_confirm_submit($form, &$form_state) {
982
  file_type_disable($form_state['values']['type']);
983
  $t_args = array('%label' => $form_state['values']['label']);
984
  drupal_set_message(t('The file type %label has been disabled.', $t_args));
985
  watchdog('file_entity', 'Disabled file type %label.', $t_args, WATCHDOG_NOTICE);
986
  $form_state['redirect'] = 'admin/structure/file-types';
987
  return;
988
}
989
990
991
/**
992
 * Menu callback; revert a single file type.
993
 */
994
function file_entity_type_revert_confirm($form, &$form_state, $type) {
995
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
996
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
997
  $message = t('Are you sure you want to revert the file type %type?', array('%type' => $type->label));
998
  return confirm_form($form, $message, 'admin/structure/file-types', '', t('Revert'));
999
}
1000
1001
1002
/**
1003
 * Process file type delete confirm submissions.
1004
 */
1005
function file_entity_type_revert_confirm_submit($form, &$form_state) {
1006
  // @NOTE deleting the file_type from the DB actually reverts it to code.
1007
  file_type_delete($form_state['values']['type']);
1008
  $t_args = array('%label' => $form_state['values']['label']);
1009
  drupal_set_message(t('The file type %label has been reverted.', $t_args));
1010
  watchdog('file_entity', 'Reverted file type %label.', $t_args, WATCHDOG_NOTICE);
1011
  $form_state['redirect'] = 'admin/structure/file-types';
1012
  return;
1013
}
1014
1015
1016
/**
1017
 * Menu callback; delete a single file type.
1018
 */
1019
function file_entity_type_delete_confirm($form, &$form_state, $type) {
1020
  $form['type'] = array('#type' => 'value', '#value' => $type->type);
1021
  $form['label'] = array('#type' => 'value', '#value' => $type->label);
1022
1023
  $message = t('Are you sure you want to delete the file type %type?', array('%type' => $type->label));
1024
  $caption = '';
1025
1026
  $num_files = db_query("SELECT COUNT(*) FROM {file_managed} WHERE type = :type", array(':type' => $type->type))->fetchField();
1027
  if ($num_files) {
1028
    $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>';
1029
  }
1030
1031
  $caption .= '<p>' . t('This action cannot be undone.') . '</p>';
1032
1033
  return confirm_form($form, $message, 'admin/structure/file-types', $caption, t('Delete'));
1034
}
1035
1036
/**
1037
 * Process file type delete confirm submissions.
1038
 */
1039
function file_entity_type_delete_confirm_submit($form, &$form_state) {
1040
  file_type_delete($form_state['values']['type']);
1041
1042
  $t_args = array('%label' => $form_state['values']['label']);
1043
  drupal_set_message(t('The file type %label has been deleted.', $t_args));
1044
  watchdog('file_entity', 'Deleted file type %label.', $t_args, WATCHDOG_NOTICE);
1045
1046
  $form_state['redirect'] = 'admin/structure/file-types';
1047
  return;
1048
}
1049
1050
/**
1051
 * Form callback for file_entity settings.
1052
 */
1053
function file_entity_settings_form($form, &$form_state) {
1054
  $form['file_entity_max_filesize'] = array(
1055
    '#type' => 'textfield',
1056
    '#title' => t('Maximum upload size'),
1057
    '#default_value' => variable_get('file_entity_max_filesize', ''),
1058
    '#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()))),
1059
    '#size' => 10,
1060
    '#element_validate' => array('_file_generic_settings_max_filesize'),
1061
  );
1062
1063
  $form['file_entity_default_allowed_extensions'] = array(
1064
    '#type' => 'textfield',
1065
    '#title' => t('Default allowed file extensions'),
1066
    '#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'),
1067
    '#description' => t('Separate extensions with a space or comma and do not include the leading dot.'),
1068 ca0757b9 Assos Assos
    '#maxlength' => NULL,
1069 85ad3d82 Assos Assos
  );
1070
1071
  $form['file_entity_alt'] = array(
1072
    '#type' => 'textfield',
1073
    '#title' => t('Alt attribute'),
1074
    '#description' => t('The text to use as value for the <em>img</em> tag <em>alt</em> attribute.'),
1075
    '#default_value' => variable_get('file_entity_alt', '[file:field_file_image_alt_text]'),
1076
  );
1077
  $form['file_entity_title'] = array(
1078
    '#type' => 'textfield',
1079
    '#title' => t('Title attribute'),
1080
    '#description' => t('The text to use as value for the <em>img</em> tag <em>title</em> attribute.'),
1081
    '#default_value' => variable_get('file_entity_title', '[file:field_file_image_title_text]'),
1082
  );
1083
1084
  // Provide default token values.
1085
  if (module_exists('token')) {
1086
    $form['token_help'] = array(
1087
      '#theme' => 'token_tree',
1088
      '#token_types' => array('file'),
1089
      '#dialog' => TRUE,
1090
    );
1091
    $form['file_entity_alt']['#description'] .= t('This field supports tokens.');
1092
    $form['file_entity_title']['#description'] .= t('This field supports tokens.');
1093
  }
1094
  $form['file_upload_wizard'] = array(
1095
    '#type' => 'fieldset',
1096
    '#title' => t('File upload wizard'),
1097
    '#collapsible' => TRUE,
1098
    '#collapsed' => FALSE,
1099
    '#description' => t('Configure the steps available when uploading a new file.'),
1100
  );
1101
  $form['file_upload_wizard']['file_entity_file_upload_wizard_skip_file_type'] = array(
1102
    '#type' => 'checkbox',
1103
    '#title' => t('Skip filetype selection.'),
1104
    '#default_value' => variable_get('file_entity_file_upload_wizard_skip_file_type', FALSE),
1105
    '#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.'),
1106
  );
1107
  $form['file_upload_wizard']['file_entity_file_upload_wizard_skip_scheme'] = array(
1108
    '#type' => 'checkbox',
1109
    '#title' => t('Skip scheme selection.'),
1110
    '#default_value' => variable_get('file_entity_file_upload_wizard_skip_scheme', FALSE),
1111
    '#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.'),
1112
  );
1113
  $form['file_upload_wizard']['file_entity_file_upload_wizard_skip_fields'] = array(
1114
    '#type' => 'checkbox',
1115
    '#title' => t('Skip available fields.'),
1116
    '#default_value' => variable_get('file_entity_file_upload_wizard_skip_fields', FALSE),
1117
    '#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.'),
1118
  );
1119
1120
  return system_settings_form($form);
1121
}