Projet

Général

Profil

Paste
Télécharger (32 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / file_entity / file_entity.pages.inc @ c169e7c4

1
<?php
2

    
3
/**
4
 * @file
5
 * Supports file operations including View, Edit, and Delete.
6
 */
7

    
8
/**
9
 * Menu callback; view a single file entity.
10
 */
11
function file_entity_view_page($file) {
12
  drupal_set_title($file->filename);
13

    
14
  $uri = entity_uri('file', $file);
15
  // Set the file path as the canonical URL to prevent duplicate content.
16
  drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE);
17
  // Set the non-aliased path as a default shortlink.
18
  drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
19

    
20
  return file_view($file, 'full');
21
}
22

    
23
/**
24
 * Menu callback; download a single file entity.
25
 */
26
function file_entity_download_page($file) {
27
  // Ensure there is a valid token to download this file.
28
  if (!variable_get('file_entity_allow_insecure_download', FALSE)) {
29
    if (!isset($_GET['token']) || $_GET['token'] !== file_entity_get_download_token($file)) {
30
      return MENU_ACCESS_DENIED;
31
    }
32
  }
33

    
34
  // If the file does not exist it can cause problems with file_transfer().
35
  if (!is_file($file->uri)) {
36
    return MENU_NOT_FOUND;
37
  }
38

    
39
  $headers = array(
40
    'Content-Type' => 'force-download',
41
    'Content-Disposition' => 'attachment; filename="' . $file->filename . '"',
42
    'Content-Length' => $file->filesize,
43
    'Content-Transfer-Encoding' => 'binary',
44
    'Pragma' => 'no-cache',
45
    'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
46
    'Expires' => '0',
47
    'Accept-Ranges' => 'bytes',
48
  );
49

    
50
  // Let other modules alter the download headers.
51
  drupal_alter('file_download_headers', $headers, $file);
52

    
53
  file_transfer($file->uri, $headers);
54
}
55

    
56
/**
57
 * Form callback for adding a file via an upload form.
58
 *
59
 * This is a multi step form which has 1-3 pages:
60
 * - Upload file
61
 * - Choose filetype
62
 *   If there is only one candidate (based on mimetype) we will skip this step.
63
 * - Edit fields
64
 *   Skip this step if there are no fields on this entity type.
65
 */
66
function file_entity_add_upload($form, &$form_state, array $options = array()) {
67
  $step = (isset($form_state['step']) && in_array($form_state['step'], array(1, 2, 3, 4))) ? $form_state['step'] : 1;
68
  $form['#step'] = $step;
69
  switch ($step) {
70
    case 1:
71
      return file_entity_add_upload_step_upload($form, $form_state, $options);
72

    
73
    case 2:
74
      return file_entity_add_upload_step_filetype($form, $form_state, $options);
75

    
76
    case 3:
77
      return file_entity_add_upload_step_scheme($form, $form_state, $options);
78

    
79
    case 4:
80
      return file_entity_add_upload_step_fields($form, $form_state, $options);
81

    
82
  }
83
}
84

    
85
/**
86
 * Generate form fields for the first step in the add file wizard.
87
 */
88
function file_entity_add_upload_step_upload($form, &$form_state, array $options = array()) {
89
  $form['upload'] = array(
90
    '#type' => 'managed_file',
91
    '#title' => t('Upload a new file'),
92
    '#upload_location' => file_entity_upload_destination_uri($options),
93
    '#upload_validators' => file_entity_get_upload_validators($options),
94
    '#progress_indicator' => 'bar',
95
    '#required' => TRUE,
96
    '#pre_render' => array('file_managed_file_pre_render', 'file_entity_upload_validators_pre_render'),
97
    '#default_value' => isset($form_state['storage']['upload']) ? $form_state['storage']['upload'] : NULL,
98
  );
99

    
100
  $form['actions'] = array('#type' => 'actions');
101
  $form['actions']['next'] = array(
102
    '#type' => 'submit',
103
    '#value' => t('Next'),
104
  );
105

    
106
  form_load_include($form_state, 'inc', 'file_entity', 'file_entity.pages');
107

    
108
  return $form;
109
}
110

    
111
/**
112
 * Generate form fields for the second step in the add file wizard.
113
 */
114
function file_entity_add_upload_step_filetype($form, &$form_state, array $options = array()) {
115
  $file = file_load($form_state['storage']['upload']);
116

    
117
  $form['type'] = array(
118
    '#type' => 'radios',
119
    '#title' => t('File type'),
120
    '#options' => file_entity_get_filetype_candidates($file),
121
    '#default_value' => isset($form_state['storage']['type']) ? $form_state['storage']['type'] : NULL,
122
    '#required' => TRUE,
123
  );
124

    
125
  $form['actions'] = array('#type' => 'actions');
126
  $form['actions']['previous'] = array(
127
    '#type' => 'submit',
128
    '#value' => t('Previous'),
129
    '#limit_validation_errors' => array(),
130
    '#submit' => array('file_entity_add_upload_submit'),
131
  );
132
  $form['actions']['next'] = array(
133
    '#type' => 'submit',
134
    '#value' => t('Next'),
135
  );
136

    
137
  return $form;
138
}
139

    
140
/**
141
 * Generate form fields for the third step in the add file wizard.
142
 */
143
function file_entity_add_upload_step_scheme($form, &$form_state, array $options = array()) {
144
  $file = file_load($form_state['storage']['upload']);
145

    
146
  $options = array();
147
  foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
148
    $options[$scheme] = check_plain($info['description']);
149
  }
150

    
151
  $form['scheme'] = array(
152
    '#type' => 'radios',
153
    '#title' => t('Destination'),
154
    '#options' => $options,
155
    '#default_value' => isset($form_state['storage']['scheme']) ? $form_state['storage']['scheme'] : file_default_scheme(),
156
    '#required' => TRUE,
157
  );
158

    
159
  $form['actions'] = array('#type' => 'actions');
160
  $form['actions']['previous'] = array(
161
    '#type' => 'submit',
162
    '#value' => t('Previous'),
163
    '#limit_validation_errors' => array(),
164
    '#submit' => array('file_entity_add_upload_submit'),
165
  );
166
  $form['actions']['next'] = array(
167
    '#type' => 'submit',
168
    '#value' => t('Next'),
169
  );
170

    
171
  return $form;
172
}
173

    
174
/**
175
 * Generate form fields for the fourth step in the add file wizard.
176
 */
177
function file_entity_add_upload_step_fields($form, &$form_state, array $options = array()) {
178
  // Load the file and overwrite the filetype set on the previous screen.
179
  $file = file_load($form_state['storage']['upload']);
180
  $file->type = $form_state['storage']['type'];
181

    
182
  // Add fields.
183
  field_attach_form('file', $file, $form, $form_state);
184

    
185
  $form['actions'] = array('#type' => 'actions');
186
  $form['actions']['previous'] = array(
187
    '#type' => 'submit',
188
    '#value' => t('Previous'),
189
    '#limit_validation_errors' => array(),
190
    '#submit' => array('file_entity_add_upload_submit'),
191
  );
192
  $form['actions']['submit'] = array(
193
    '#type' => 'submit',
194
    '#value' => t('Save'),
195
  );
196

    
197
  return $form;
198
}
199

    
200
/**
201
 * Page callback to show file usage information.
202
 */
203
function file_entity_usage_page($file) {
204
  $rows = array();
205
  $occured_entities = array();
206

    
207
  foreach (file_usage_list($file) as $module => $usage) {
208
    $info = system_get_info('module', $module);
209

    
210
    // There are cases, where actual entitiy doesen't exist.
211
    // We have to handle this.
212
    foreach ($usage as $entity_type => $entity_ids) {
213
      $entity_info = entity_get_info($entity_type);
214
      $entities = empty($entity_info) ? NULL : entity_load($entity_type, array_keys($entity_ids));
215

    
216
      foreach ($entity_ids as $entity_id => $count) {
217
        // If some other module already added this entity just sum all counts.
218
        if (isset($occured_entities[$entity_type][$entity_id])) {
219
          $rows[$occured_entities[$entity_type][$entity_id]][2] += $count;
220
          continue;
221
        }
222

    
223
        $label = empty($entities[$entity_id]) ? $module : entity_label($entity_type, $entities[$entity_id]);
224
        $entity_uri = empty($entities[$entity_id]) ? NULL : entity_uri($entity_type, $entities[$entity_id]);
225

    
226
        // Some entities do not have URL.
227
        if (empty($entity_uri)) {
228
          $rows[] = array(check_plain($label), $entity_type, $module, $count);
229
        }
230
        else {
231
          $uri = $entity_uri['path'];
232
          $rows[] = array(l($label, $uri), $entity_type, $module, $count);
233
        }
234

    
235
        $occured_entities[$entity_type][$entity_id] = count($rows) - 1;
236
      }
237
    }
238
  }
239
  $header[] = array(
240
    'data' => t('Entity'),
241
  );
242
  $header[] = array(
243
    'data' => t('Entity type'),
244
  );
245
  $header[] = array(
246
    'data' => t('Registering module'),
247
  );
248
  $header[] = array(
249
    'data' => t('Use count'),
250
  );
251
  $build['usage_table'] = array(
252
    '#theme' => 'table',
253
    '#header' => $header,
254
    '#rows' => $rows,
255
    '#caption' => t('This table lists all of the places where @filename is used.',
256
    array('@filename' => $file->filename)),
257
    '#empty' => t('This file is not currently used.'),
258
  );
259
  return $build;
260
}
261

    
262
/**
263
 * Get the candidate filetypes for a given file.
264
 *
265
 * Only filetypes for which the user has access to create entities are returned.
266
 *
267
 * @param array $file
268
 *   An upload file array from form_state.
269
 *
270
 * @return array
271
 *   An array of file type bundles that support the file's mime type.
272
 */
273
function file_entity_get_filetype_candidates($file) {
274
  $types = module_invoke_all('file_type', $file);
275
  drupal_alter('file_type', $types, $file);
276
  $candidates = array();
277
  foreach ($types as $type) {
278
    $file->type = $type;
279
    if (file_entity_access('create', $file)) {
280
      $candidates[$type] = file_entity_type_get_name($file);
281
    }
282
  }
283
  return $candidates;
284
}
285

    
286
/**
287
 * Submit handler for the add file form.
288
 */
289
function file_entity_add_upload_submit($form, &$form_state) {
290
  $form_state['storage'] = isset($form_state['storage']) ? $form_state['storage'] : array();
291
  $form_state['storage'] = array_merge($form_state['storage'], $form_state['values']);
292

    
293
  // This var is set to TRUE when we are ready to save the file.
294
  $save = FALSE;
295
  $trigger = $form_state['triggering_element']['#id'];
296

    
297
  $steps_to_check = array(2, 3);
298
  if ($trigger == 'edit-previous') {
299
    // If the previous button was hit,
300
    // the step checking order should be reversed 3, 2.
301
    $steps_to_check = array_reverse($steps_to_check);
302
  }
303

    
304
  foreach ($steps_to_check as $step) {
305
    // Check if we can skip step 2 and 3.
306
    if (($form['#step'] == $step - 1 && $trigger == 'edit-next') || ($form['#step'] == $step + 1 && $trigger == 'edit-previous')) {
307
      $file = file_load($form_state['storage']['upload']);
308
      if ($step == 2) {
309
        // Check if we can skip step 2.
310
        $candidates = file_entity_get_filetype_candidates($file);
311
        if (count($candidates) == 1) {
312
          $candidates_keys = array_keys($candidates);
313
          // There is only one possible filetype for this file.
314
          // Skip the second page.
315
          $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
316
          $form_state['storage']['type'] = reset($candidates_keys);
317
        }
318
        elseif (variable_get('file_entity_file_upload_wizard_skip_file_type', FALSE)) {
319
          // Do not assign the file a file type.
320
          $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
321
          $form_state['storage']['type'] = FILE_TYPE_NONE;
322
        }
323
      }
324
      else {
325
        // Check if we can skip step 3.
326
        $schemes = file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE);
327
        if (count($schemes) == 1) {
328
          // There is only one possible stream wrapper for this file.
329
          // Skip the third page.
330
          $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
331
          $form_state['storage']['scheme'] = key($schemes);
332
        }
333
        elseif (variable_get('file_entity_file_upload_wizard_skip_scheme', FALSE)) {
334
          // Assign the file the default scheme.
335
          $form['#step'] += ($trigger == 'edit-previous') ? -1 : 1;
336
          $form_state['storage']['scheme'] = file_default_scheme();
337
        }
338
      }
339
    }
340
  }
341

    
342
  // We have the filetype, check if we can skip step 4.
343
  if (($form['#step'] == 3 && $trigger == 'edit-next')) {
344
    $file = file_load($form_state['storage']['upload']);
345
    if (!field_info_instances('file', $form_state['storage']['type'])) {
346
      // This filetype doesn't have fields, save the file.
347
      $save = TRUE;
348
    }
349
    elseif (variable_get('file_entity_file_upload_wizard_skip_fields', FALSE)) {
350
      // Save the file with blanks fields.
351
      $save = TRUE;
352
    }
353
  }
354

    
355
  // Form id's can vary depending on how many other forms are displayed, so we
356
  // need to do string comparissons. e.g edit-submit--2.
357
  if (strpos($trigger, 'edit-next') !== FALSE) {
358
    $form_state['step'] = $form['#step'] + 1;
359
  }
360
  elseif (strpos($trigger, 'edit-previous') !== FALSE) {
361
    $form_state['step'] = $form['#step'] - 1;
362
  }
363
  elseif (strpos($trigger, 'edit-submit') !== FALSE) {
364
    $save = TRUE;
365
  }
366

    
367
  if ($save) {
368
    $file = file_load($form_state['storage']['upload']);
369
    if ($file) {
370
      if (file_uri_scheme($file->uri) != $form_state['storage']['scheme']) {
371
        if ($moved_file = file_move($file, $form_state['storage']['scheme'] . '://' . file_uri_target($file->uri), FILE_EXISTS_RENAME)) {
372
          // Only re-assign the file object if file_move() did not fail.
373
          $file = $moved_file;
374
        }
375
      }
376
      $file->type = $form_state['storage']['type'];
377
      $file->display = TRUE;
378

    
379
      // Change the file from temporary to permanent.
380
      $file->status = FILE_STATUS_PERMANENT;
381

    
382
      // Save the form fields.
383
      // Keep in mind that the values for the Field API fields must be in
384
      // $form_state['values'] and not in ['storage']. This is true as long as
385
      // the fields are on the last page of the multi step form.
386
      entity_form_submit_build_entity('file', $file, $form, $form_state);
387

    
388
      file_save($file);
389
      $form_state['file'] = $file;
390
      drupal_set_message(t('@type %name was uploaded.', array('@type' => file_entity_type_get_name($file), '%name' => $file->filename)));
391
    }
392
    else {
393
      drupal_set_message(t('An error occurred and no file was uploaded.'), 'error');
394
      return;
395
    }
396

    
397
    // Figure out destination.
398
    if (isset($_GET['destination'])) {
399
      $destination = drupal_get_destination();
400
      unset($_GET['destination']);
401
    }
402
    elseif (user_access('administer files')) {
403
      $destination = array('destination' => 'admin/content/file');
404
    }
405
    else {
406
      $destination = array('destination' => 'file/' . $file->fid);
407
    }
408
    $form_state['redirect'] = $destination['destination'];
409
  }
410
  else {
411
    $form_state['rebuild'] = TRUE;
412
  }
413

    
414
  // Clear the page and block caches.
415
  cache_clear_all();
416
}
417

    
418
/**
419
 * Determines the upload location for the file add upload form.
420
 *
421
 * @param array $params
422
 *   An array of parameters from the media browser.
423
 * @param array $data
424
 *   (optional) An array of token objects to pass to token_replace().
425
 *
426
 * @return string
427
 *   A file directory URI with tokens replaced.
428
 *
429
 * @see token_replace()
430
 */
431
function file_entity_upload_destination_uri(array $params, array $data = array()) {
432
  $params += array(
433
    'uri_scheme' => file_default_scheme(),
434
    'file_directory' => '',
435
  );
436

    
437
  $destination = trim($params['file_directory'], '/');
438

    
439
  // Replace tokens.
440
  $destination = token_replace($destination, $data);
441

    
442
  return $params['uri_scheme'] . '://' . $destination;
443
}
444

    
445
/**
446
 * Form for uploading multiple files.
447
 */
448
function file_entity_add_upload_multiple($form, &$form_state, $params = array()) {
449
  $form = file_entity_add_upload($form, $form_state, $params);
450
  unset($form['upload']['#title']);
451
  // The validators will be set from plupload anyway. This isn't pretty,
452
  // but don't allow it to show up twice.
453
  unset($form['upload']['#description']);
454

    
455
  $form['upload']['#type'] = 'plupload';
456

    
457
  // Ensure that we call the plupload_element_pre_render function.
458
  // If it isn't called, it doesn't set the JS settings that transfers the
459
  // list of allowed file extentions to the PLUpload widget.
460
  // We override the 'file_entity_upload_validators_pre_render' setting if it
461
  // exists, because both pre-render hooks adds the upload-help with list of
462
  // allowed file extensions.
463
  $index = array_search('file_entity_upload_validators_pre_render', $form['upload']['#pre_render']);
464
  if ($index !== FALSE) {
465
    $form['upload']['#pre_render'][$index] = 'plupload_element_pre_render';
466
  }
467
  else {
468
    $form['upload']['#pre_render'][] = 'plupload_element_pre_render';
469
  }
470

    
471
  $form['submit']['#value'] = t('Start upload');
472
  return $form;
473
}
474

    
475
/**
476
 * Submit handler for the multiple upload form.
477
 */
478
function file_entity_add_upload_multiple_submit($form, &$form_state) {
479
  $upload_location = !empty($form['upload']['#upload_location']) ?
480
    $form['upload']['#upload_location'] . '/' :
481
    variable_get('file_default_scheme', 'public') . '://';
482

    
483
  // We can't use file_save_upload() because of
484
  // http://www.jacobsingh.name/content/tight-coupling-no-not.
485
  foreach ($form_state['values']['upload'] as $uploaded_file) {
486
    if ($uploaded_file['status'] == 'done') {
487
      $source = $uploaded_file['tmppath'];
488
      $destination = file_stream_wrapper_uri_normalize($upload_location . $uploaded_file['name']);
489
      // Rename it to its original name, and put it in its final home.
490
      // Note - not using file_move here because if we call file_get_mime
491
      // (in file_uri_to_object) while it has a .tmp extension, it horks.
492
      $destination = file_unmanaged_move($source, $destination, FILE_EXISTS_RENAME);
493

    
494
      $file = file_uri_to_object($destination);
495
      $file->status = FILE_STATUS_PERMANENT;
496
      file_save($file);
497

    
498
      $saved_files[] = $file;
499
      $form_state['files'][$file->fid] = $file;
500
    }
501
    else {
502
      // @todo: move this to element validate or something.
503
      form_set_error('pud', t('The specified file %name could not be uploaded.', array('%name' => $uploaded_file['name'])));
504
    }
505
  }
506

    
507
  // Redirect to the file edit page.
508
  if (file_entity_access('update', $file) && module_exists('multiform') && module_exists('media')) {
509
    $destination = array();
510
    if (isset($_GET['destination'])) {
511
      $destination = drupal_get_destination();
512
      unset($_GET['destination']);
513
    }
514
    elseif (user_access('administer files')) {
515
      $destination = array('destination' => 'admin/content/file');
516
    }
517
    $form_state['redirect'] = array('admin/content/file/edit-multiple/' . implode(' ', array_keys($form_state['files'])), array('query' => $destination));
518
  }
519
  else {
520
    $form_state['redirect'] = user_access('administer files') ? 'admin/content/file' : '<front>';
521
  }
522

    
523
  // Clear the page and block caches.
524
  cache_clear_all();
525
}
526

    
527
/**
528
 * Page callback: Form constructor for the file edit form.
529
 *
530
 * Path: file/%file/edit
531
 *
532
 * @param object $file
533
 *   A file object from file_load().
534
 *
535
 * @see file_entity_menu()
536
 *
537
 * @todo Rename this form to file_edit_form to ease into core.
538
 */
539
function file_entity_edit($form, &$form_state, $file) {
540
  drupal_set_title(t('<em>Edit @type</em> @title', array('@type' => $file->type, '@title' => $file->filename)), PASS_THROUGH);
541

    
542
  $form_state['file'] = $file;
543

    
544
  $form['#attributes']['class'][] = 'file-form';
545
  if (!empty($file->type)) {
546
    $form['#attributes']['class'][] = 'file-' . $file->type . '-form';
547
  }
548

    
549
  // Basic file information.
550
  // These elements are just values so they are not even sent to the client.
551
  foreach (array('fid', 'type', 'uid', 'timestamp') as $key) {
552
    $form[$key] = array(
553
      '#type' => 'value',
554
      '#value' => isset($file->$key) ? $file->$key : NULL,
555
    );
556
  }
557

    
558
  $form['filename'] = array(
559
    '#type' => 'textfield',
560
    '#title' => t('Name'),
561
    '#default_value' => $file->filename,
562
    '#required' => TRUE,
563
    '#maxlength' => 255,
564
    '#weight' => -10,
565
  );
566

    
567
  // Add a 'replace this file' upload field if the file is writeable.
568
  if (file_entity_file_is_writeable($file)) {
569
    // Set up replacement file validation.
570
    $replacement_options = array();
571
    // The replacement file must have the same extension as the original file.
572
    $replacement_options['file_extensions'] = pathinfo($file->uri, PATHINFO_EXTENSION);
573

    
574
    $form['replace_upload'] = array(
575
      '#type' => 'file',
576
      '#title' => t('Replace file'),
577
      '#description' => t('This file will replace the existing file. This action cannot be undone.'),
578
      '#upload_validators' => file_entity_get_upload_validators($replacement_options),
579
      '#pre_render' => array('file_entity_upload_validators_pre_render'),
580
    );
581
  }
582

    
583
  $form['preview'] = file_view_file($file, 'preview');
584

    
585
  $form['additional_settings'] = array(
586
    '#type' => 'vertical_tabs',
587
    '#weight' => 99,
588
  );
589

    
590
  // File destination information for administrators.
591
  $form['destination'] = array(
592
    '#type' => 'fieldset',
593
    '#access' => user_access('administer files') && file_entity_file_is_writeable($file),
594
    '#title' => t('Destination'),
595
    '#collapsible' => TRUE,
596
    '#collapsed' => TRUE,
597
    '#group' => 'additional_settings',
598
    '#attributes' => array(
599
      'class' => array('file-form-destination'),
600
    ),
601
    '#attached' => array(
602
      'js' => array(
603
        drupal_get_path('module', 'file_entity') . '/file_entity.js',
604
      ),
605
    ),
606
  );
607

    
608
  $options = array();
609
  foreach (file_get_stream_wrappers(STREAM_WRAPPERS_WRITE_VISIBLE) as $scheme => $info) {
610
    $options[$scheme] = check_plain($info['name']);
611
  }
612

    
613
  $form['destination']['scheme'] = array(
614
    '#type' => 'radios',
615
    '#title' => t('Destination'),
616
    '#options' => $options,
617
    '#default_value' => file_uri_scheme($file->uri),
618
  );
619

    
620
  // File user information for administrators.
621
  $form['user'] = array(
622
    '#type' => 'fieldset',
623
    '#access' => user_access('administer files'),
624
    '#title' => t('User information'),
625
    '#collapsible' => TRUE,
626
    '#collapsed' => TRUE,
627
    '#group' => 'additional_settings',
628
    '#attributes' => array(
629
      'class' => array('file-form-user'),
630
    ),
631
    '#attached' => array(
632
      'js' => array(
633
        drupal_get_path('module', 'file_entity') . '/file_entity.js',
634
        array(
635
          'type' => 'setting',
636
          'data' => array('anonymous' => variable_get('anonymous', t('Anonymous'))),
637
        ),
638
      ),
639
    ),
640
    '#weight' => 90,
641
  );
642
  $form['user']['name'] = array(
643
    '#type' => 'textfield',
644
    '#title' => t('Associated with'),
645
    '#maxlength' => 60,
646
    '#autocomplete_path' => 'user/autocomplete',
647
    '#default_value' => !empty($file->uid) ? user_load($file->uid)->name : '',
648
    '#weight' => -1,
649
    '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', t('Anonymous')))),
650
  );
651

    
652
  // Add the buttons.
653
  $form['actions'] = array('#type' => 'actions');
654
  $form['actions']['submit'] = array(
655
    '#type' => 'submit',
656
    '#value' => t('Save'),
657
    '#weight' => 5,
658
    '#submit' => array('file_entity_edit_submit'),
659
  );
660
  $form['actions']['delete'] = array(
661
    '#type' => 'submit',
662
    '#value' => t('Delete'),
663
    '#weight' => 10,
664
    '#submit' => array('file_entity_edit_delete_submit'),
665
    '#access' => file_entity_access('delete', $file),
666
  );
667

    
668
  // Build the URL for the cancel button taking into account that there might be
669
  // a "destination" that includes query string variables.
670
  $parameters = drupal_get_query_parameters();
671
  $destination = isset($parameters['destination']) ? $parameters['destination'] : 'file/' . $file->fid;
672
  $url = drupal_parse_url($destination);
673

    
674
  $form['actions']['cancel'] = array(
675
    '#type' => 'link',
676
    '#title' => t('Cancel'),
677
    '#href' => $url['path'],
678
    '#options' => array('query' => $url['query']),
679
    '#weight' => 15,
680
  );
681

    
682
  $langcode = function_exists('entity_language') ? entity_language('file', $file) : NULL;
683
  field_attach_form('file', $file, $form, $form_state, $langcode);
684

    
685
  return $form;
686
}
687

    
688
/**
689
 * Form validation handler for file_entity_edit().
690
 */
691
function file_entity_edit_validate($form, &$form_state) {
692
  $file = (object) $form_state['values'];
693

    
694
  // Validate the "associated user" field.
695
  if (!empty($file->name) && !($account = user_load_by_name($file->name))) {
696
    // The use of empty() is mandatory in the context of usernames
697
    // as the empty string denotes the anonymous user. In case we
698
    // are dealing with an anonymous user we set the user ID to 0.
699
    form_set_error('name', t('The username %name does not exist.', array('%name' => $file->name)));
700
  }
701

    
702
  // Handle the replacement file if uploaded.
703
  if (isset($form_state['values']['replace_upload'])) {
704
    // Save the file as a temporary file.
705
    $file = file_save_upload('replace_upload', $form['replace_upload']['#upload_validators']);
706
    if (!empty($file)) {
707
      // Put the temporary file in form_values so we can save it on submit.
708
      $form_state['values']['replace_upload'] = $file;
709
    }
710
    elseif ($file === FALSE) {
711
      // File uploaded failed.
712
      form_set_error('replace_upload', t('The replacement file could not be uploaded.'));
713
    }
714
  }
715

    
716
  // Run entity form validation.
717
  entity_form_field_validate('file', $form, $form_state);
718
}
719

    
720
/**
721
 * Form submission handler for the 'Save' button for file_entity_edit().
722
 */
723
function file_entity_edit_submit($form, &$form_state) {
724
  $file = $form_state['file'];
725

    
726
  // Check if a replacement file has been uploaded.
727
  if (!empty($form_state['values']['replace_upload'])) {
728
    $replacement = $form_state['values']['replace_upload'];
729
    // Move file from temp to permanent home.
730
    file_unmanaged_copy($replacement->uri, $file->uri, FILE_EXISTS_REPLACE);
731
  }
732

    
733
  // Run entity form submit handling and save the file.
734
  entity_form_submit_build_entity('file', $file, $form, $form_state);
735

    
736
  // A user might assign the associated user by entering a user name in the file
737
  // edit form, which we then need to translate to a user ID.
738
  if (isset($file->name)) {
739
    // The use of isset() is mandatory in the context of user IDs, because
740
    // user ID 0 denotes the anonymous user.
741
    if ($user = user_load_by_name($file->name)) {
742
      $file->uid = $user->uid;
743
    }
744
    else {
745
      // Anonymous user.
746
      $file->uid = 0;
747
    }
748
  }
749
  elseif ($file->uid) {
750
    $user = user_load($file->uid);
751
    $file->name = $user->name;
752
  }
753

    
754
  if (file_uri_scheme($file->uri) != $form_state['values']['scheme']) {
755
    if ($moved_file = file_move($file, $form_state['values']['scheme'] . '://' . file_uri_target($file->uri), FILE_EXISTS_RENAME)) {
756
      // Only re-assign the file object if file_move() did not fail.
757
      $file = $moved_file;
758
    }
759
  }
760

    
761
  file_save($file);
762

    
763
  $args = array(
764
    '@type' => file_entity_type_get_name($file),
765
    '%title' => entity_label('file', $file),
766
  );
767
  watchdog('file', '@type: updated %title.', $args);
768
  drupal_set_message(t('@type %title has been updated.', $args));
769

    
770
  $form_state['redirect'] = 'file/' . $file->fid;
771

    
772
  // Clear the page and block caches.
773
  cache_clear_all();
774
}
775

    
776
/**
777
 * Form submission handler for the 'Delete' button for file_entity_edit().
778
 */
779
function file_entity_edit_delete_submit($form, &$form_state) {
780
  $fid = $form_state['values']['fid'];
781
  $destination = array();
782
  if (isset($_GET['destination'])) {
783
    $destination = drupal_get_destination();
784
    unset($_GET['destination']);
785
  }
786
  $form_state['redirect'] = array('file/' . $fid . '/delete', array('query' => $destination));
787

    
788
  // Clear the page and block caches.
789
  cache_clear_all();
790
}
791

    
792
/**
793
 * Page callback: Form constructor for the file deletion confirmation form.
794
 *
795
 * Path: file/%file/delete
796
 *
797
 * @param object $file
798
 *   A file object from file_load().
799
 *
800
 * @see file_entity_menu()
801
 */
802
function file_entity_delete_form($form, &$form_state, $file) {
803
  $form_state['file'] = $file;
804

    
805
  $form['fid'] = array(
806
    '#type' => 'value',
807
    '#value' => $file->fid,
808
  );
809

    
810
  $description = t('This action cannot be undone.');
811
  if ($references = file_usage_list($file)) {
812
    $description .= ' ' . t('This file is currently in use and may cause problems if deleted.');
813
  }
814

    
815
  return confirm_form($form,
816
    t('Are you sure you want to delete the file %title?', array(
817
      '%title' => entity_label('file', $file),
818
    )),
819
    'file/' . $file->fid,
820
    $description,
821
    t('Delete')
822
  );
823
}
824

    
825
/**
826
 * Form submission handler for file_entity_delete_form().
827
 */
828
function file_entity_delete_form_submit($form, &$form_state) {
829
  if ($form_state['values']['confirm'] && $file = file_load($form_state['values']['fid'])) {
830
    // Use file_delete_multiple() rather than file_delete() since we want to
831
    // avoid unwanted validation and usage checking.
832
    file_delete_multiple(array($file->fid));
833

    
834
    $args = array(
835
      '@type' => file_entity_type_get_name($file),
836
      '%title' => entity_label('file', $file),
837
    );
838
    watchdog('file', '@type: deleted %title.', $args);
839
    drupal_set_message(t('@type %title has been deleted.', $args));
840
  }
841

    
842
  $form_state['redirect'] = '<front>';
843

    
844
  // Clear the page and block caches.
845
  cache_clear_all();
846
}
847

    
848
/**
849
 * Form constructor for file deletion confirmation form.
850
 *
851
 * @param array $files
852
 *   An array of file objects.
853
 */
854
function file_entity_multiple_delete_form($form, &$form_state, array $files) {
855
  $form['files'] = array(
856
    '#prefix' => '<ul>',
857
    '#suffix' => '</ul>',
858
    '#tree' => TRUE,
859
  );
860

    
861
  $files_have_usage = FALSE;
862
  foreach ($files as $fid => $file) {
863
    $title = entity_label('file', $file);
864
    $usage = file_usage_list($file);
865
    if (!empty($usage)) {
866
      $files_have_usage = TRUE;
867
      $title = t('@title (in use)', array('@title' => $title));
868
    }
869
    else {
870
      $title = check_plain($title);
871
    }
872
    $form['files'][$fid] = array(
873
      '#type' => 'hidden',
874
      '#value' => $fid,
875
      '#prefix' => '<li>',
876
      '#suffix' => $title . "</li>\n",
877
    );
878
  }
879

    
880
  $form['operation'] = array(
881
    '#type' => 'hidden',
882
    '#value' => 'delete',
883
  );
884

    
885
  $description = t('This action cannot be undone.');
886
  if ($files_have_usage) {
887
    $description .= ' ' . t('Some of the files are currently in use and may cause problems if deleted.');
888
  }
889

    
890
  return confirm_form(
891
    $form,
892
    format_plural(count($files), 'Are you sure you want to delete this file?', 'Are you sure you want to delete these files?'),
893
    'admin/content/file',
894
    $description,
895
    t('Delete')
896
  );
897
}
898

    
899
/**
900
 * Form submission handler for file_entity_multiple_delete_form().
901
 */
902
function file_entity_multiple_delete_form_submit($form, &$form_state) {
903
  if ($form_state['values']['confirm'] && $fids = array_keys($form_state['values']['files'])) {
904
    file_delete_multiple($fids);
905
    $count = count($fids);
906
    watchdog('file', 'Deleted @count files.', array('@count' => $count));
907
    drupal_set_message(format_plural($count, 'Deleted one file.', 'Deleted @count files.'));
908
  }
909
  $form_state['redirect'] = 'admin/content/file';
910

    
911
  // Clear the page and block caches.
912
  cache_clear_all();
913
}
914

    
915
/**
916
 * Page callback for the file edit form.
917
 *
918
 * @deprecated
919
 *   Use drupal_get_form('file_entity_edit')
920
 */
921
function file_entity_page_edit($file) {
922
  return drupal_get_form('file_entity_edit', $file);
923
}
924

    
925
/**
926
 * Page callback for the file deletion confirmation form.
927
 *
928
 * @deprecated
929
 *   Use drupal_get_form('file_entity_delete_form')
930
 */
931
function file_entity_page_delete($file) {
932
  return drupal_get_form('file_entity_delete_form');
933
}
934

    
935
/**
936
 * Retrieves the upload validators for a file.
937
 *
938
 * @param array $options
939
 *   (optional) An array of options for file validation.
940
 *
941
 * @return array
942
 *   An array suitable for passing to file_save_upload() or for a managed_file
943
 *   or upload element's '#upload_validators' property.
944
 */
945
function file_entity_get_upload_validators(array $options = array()) {
946
  // Set up file upload validators.
947
  $validators = array();
948

    
949
  // Validate file extensions. If there are no file extensions in $params and
950
  // there are no Media defaults, there is no file extension validation.
951
  if (!empty($options['file_extensions'])) {
952
    $validators['file_validate_extensions'] = array($options['file_extensions']);
953
  }
954
  else {
955
    $validators['file_validate_extensions'] = array(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'));
956
  }
957

    
958
  // Cap the upload size according to the system or user defined limit.
959
  $max_filesize = parse_size(file_upload_max_size());
960
  $file_entity_max_filesize = parse_size(variable_get('file_entity_max_filesize', ''));
961

    
962
  // If the user defined a size limit, use the smaller of the two.
963
  if (!empty($file_entity_max_filesize)) {
964
    $max_filesize = min($max_filesize, $file_entity_max_filesize);
965
  }
966

    
967
  if (!empty($options['max_filesize']) && $options['max_filesize'] < $max_filesize) {
968
    $max_filesize = parse_size($options['max_filesize']);
969
  }
970

    
971
  // There is always a file size limit due to the PHP server limit.
972
  $validators['file_validate_size'] = array($max_filesize);
973

    
974
  // Add image validators.
975
  $options += array('min_resolution' => 0, 'max_resolution' => 0);
976
  if ($options['min_resolution'] || $options['max_resolution']) {
977
    $validators['file_validate_image_resolution'] = array($options['max_resolution'], $options['min_resolution']);
978
  }
979

    
980
  // Add other custom upload validators from options.
981
  if (!empty($options['upload_validators'])) {
982
    $validators += $options['upload_validators'];
983
  }
984

    
985
  return $validators;
986
}