Fixing spelling of "recommended".
[project/filefield.git] / filefield_widget.inc
CommitLineData
9412a7cc
JP
1<?php
2// $Id$
a679aaae 3
9412a7cc
JP
4/**
5 * @file
90a92972 6 * This file contains CCK widget related functionality.
9412a7cc
JP
7 *
8 * Uses content.module to store the fid and field specific metadata,
90a92972 9 * and Drupal's files table to store the actual file data.
9412a7cc
JP
10 */
11
22e736e6 12/**
87d3e491 13 * Implementation of CCK's hook_widget_settings($op == 'form').
22e736e6 14 */
22e736e6
DP
15function filefield_widget_settings_form($widget) {
16 $form = array();
17 $form['file_extensions'] = array(
18 '#type' => 'textfield',
19 '#title' => t('Permitted upload file extensions'),
20 '#default_value' => is_string($widget['file_extensions']) ? $widget['file_extensions'] : 'txt',
21 '#size' => 64,
22 '#description' => t('Extensions a user can upload to this field. Separate extensions with a space and do not include the leading dot. Leaving this blank will allow users to upload a file with any extension.'),
23 '#weight' => 1,
24 );
87d3e491 25
70785e17
NH
26 $form['progress_indicator'] = array(
27 '#type' => 'radios',
28 '#title' => t('Progress indicator'),
29 '#options' => array(
30 'bar' => t('Bar with progress meter'),
31 'throbber' => t('Throbber'),
32 ),
33 '#default_value' => empty($widget['progress_indicator']) ? 'bar' : $widget['progress_indicator'],
34 '#description' => t('Your server supports upload progress capabilities. The "throbber" display does not indicate progress but takes up less room on the form, you may want to use it if you\'ll only be uploading small files or if experiencing problems with the progress bar.'),
35 '#weight' => 5,
36 '#access' => filefield_progress_implementation(),
37 );
38
22e736e6
DP
39 $form['path_settings'] = array(
40 '#type' => 'fieldset',
41 '#title' => t('Path settings'),
e76d77f0
NH
42 '#collapsible' => TRUE,
43 '#collapsed' => TRUE,
22e736e6
DP
44 '#weight' => 6,
45 );
22e736e6
DP
46 $form['path_settings']['file_path'] = array(
47 '#type' => 'textfield',
48 '#title' => t('File path'),
49 '#default_value' => is_string($widget['file_path']) ? $widget['file_path'] : '',
af2b0845 50 '#description' => t('Optional subdirectory within the "%directory" directory where files will be stored. Do not include preceding or trailing slashes.', array('%directory' => variable_get('file_directory_path', 'files') . '/')),
22e736e6
DP
51 '#element_validate' => array('_filefield_widget_settings_file_path_validate'),
52 '#suffix' => theme('token_help', 'user'),
53 );
54
55 $form['max_filesize'] = array(
56 '#type' => 'fieldset',
57 '#title' => t('File size restrictions'),
58 '#description' => t('Limits for the size of files that a user can upload. Note that these settings only apply to newly uploaded files, whereas existing files are not affected.'),
59 '#weight' => 6,
60 '#collapsible' => TRUE,
61 '#collapsed' => TRUE,
62 );
63 $form['max_filesize']['max_filesize_per_file'] = array(
64 '#type' => 'textfield',
65 '#title' => t('Maximum upload size per file'),
66 '#default_value' => is_string($widget['max_filesize_per_file'])
67 ? $widget['max_filesize_per_file']
68 : '',
a2db4a45 69 '#description' => t('Specify the size limit that applies to each file separately. Enter a value like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes) in order to restrict the allowed file size. If you leave this this empty the file sizes will be limited only by PHP\'s maximum post and file upload sizes (current limit <strong>%limit</strong>).', array('%limit' => format_size(file_upload_max_size()))),
22e736e6
DP
70 '#element_validate' => array('_filefield_widget_settings_max_filesize_per_file_validate'),
71 );
72 $form['max_filesize']['max_filesize_per_node'] = array(
73 '#type' => 'textfield',
74 '#title' => t('Maximum upload size per node'),
75 '#default_value' => is_string($widget['max_filesize_per_node'])
76 ? $widget['max_filesize_per_node']
77 : '',
78 '#description' => t('Specify the total size limit for all files in field on a given node. Enter a value like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes) in order to restrict the total size of a node. Leave this empty if there should be no size restriction.'),
79 '#element_validate' => array('_filefield_widget_settings_max_filesize_per_node_validate'),
80 );
87d3e491 81
22e736e6
DP
82 return $form;
83}
84
87d3e491
NH
85/**
86 * Implementation of CCK's hook_widget_settings($op == 'save').
87 */
22e736e6 88function filefield_widget_settings_save($widget) {
70785e17 89 return array('file_extensions', 'file_path', 'progress_indicator', 'max_filesize_per_file', 'max_filesize_per_node');
22e736e6
DP
90}
91
92function _filefield_widget_settings_file_path_validate($element, &$form_state) {
93 // Strip slashes from the beginning and end of $widget['file_path']
94 $form_state['values']['file_path'] = trim($form_state['values']['file_path'], '\\/');
5322fc46
NH
95
96 // Do not allow the file path to be the same as the file_directory_path().
97 // This causes all sorts of problems with things like file_create_url().
98 if (strpos($form_state['values']['file_path'], file_directory_path()) === 0) {
99 form_error($element, t('The file path (@file_path) cannot start with the system files directory (@files_directory), as this may cause conflicts when building file URLs.', array('@file_path' => $form_state['values']['file_path'], '@files_directory' => file_directory_path())));
100 }
22e736e6
DP
101}
102
103function _filefield_widget_settings_max_filesize_per_file_validate($element, &$form_state) {
104 if (empty($form_state['values']['max_filesize_per_file'])) {
105 return; // Empty means no size restrictions, so don't throw an error.
106 }
87d3e491
NH
107 elseif (!is_numeric(parse_size($form_state['values']['max_filesize_per_file']))) {
108 form_error($element, t('The "@field" option must contain a valid value. You can either leave the text field empty or enter a string like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes).', array('@field' => t('Maximum upload size per file'))));
22e736e6
DP
109 }
110}
111
112function _filefield_widget_settings_max_filesize_per_node_validate($element, &$form_state) {
113 if (empty($form_state['values']['max_filesize_per_node'])) {
114 return; // Empty means no size restrictions, so don't throw an error.
115 }
87d3e491
NH
116 elseif (!is_numeric(parse_size($form_state['values']['max_filesize_per_node']))) {
117 form_error($element, t('The "@field" option must contain a valid value. You can either leave the text field empty or enter a string like "512" (bytes), "80K" (kilobytes) or "50M" (megabytes).', array('@field' => t('Maximum upload size per node'))));
22e736e6
DP
118 }
119}
120
bf602673 121/**
122 * Determine the widget's files directory
123 *
87d3e491
NH
124 * @param $field
125 * A CCK field array.
25f2014e
NH
126 * @param $account
127 * The user account object to calculate the file path for.
87d3e491
NH
128 * @return
129 * The files directory path, with any tokens replaced.
bf602673 130 */
25f2014e
NH
131function filefield_widget_file_path($field, $account = NULL) {
132 $account = isset($account) ? $account : $GLOBALS['user'];
133 $dest = $field['widget']['file_path'];
14907c69
NH
134 // Replace user level tokens.
135 // Node level tokens require a lot of complexity like temporary storage
136 // locations when values don't exist. See the filefield_paths module.
bf602673 137 if (module_exists('token')) {
25f2014e 138 $dest = token_replace($dest, 'user', $account);
bf602673 139 }
14907c69
NH
140 // Replace nasty characters in the path if possible.
141 if (module_exists('transliteration')) {
f21581e9 142 module_load_include('inc', 'transliteration');
14907c69
NH
143 $dest_array = array_filter(explode('/', $dest));
144 foreach ($dest_array as $key => $directory) {
145 $dest_array[$key] = transliteration_clean_filename($directory);
146 }
147 $dest = implode('/', $dest_array);
148 }
bf602673 149
150 return file_directory_path() .'/'. $dest;
151}
152
87d3e491
NH
153/**
154 * Given a FAPI element, save any files that may have been uploaded into it.
155 *
156 * This function should only be called during validate, submit, or
157 * value_callback functions.
158 *
159 * @param $element
160 * The FAPI element whose values are being saved.
161 */
8ffd8e3d
DP
162function filefield_save_upload($element) {
163 $upload_name = $element['#field_name'] .'_'. $element['#delta'];
25f2014e 164 $field = content_fields($element['#field_name'], $element['#type_name']);
8ffd8e3d
DP
165
166 if (empty($_FILES['files']['name'][$upload_name])) {
167 return 0;
168 }
169
25f2014e 170 $dest = filefield_widget_file_path($field);
8ffd8e3d 171 if (!field_file_check_directory($dest, FILE_CREATE_DIRECTORY)) {
32984cd2 172 watchdog('filefield', 'The upload directory %directory for the file field %field (content type %type) could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was canceled.', array('%directory' => $dest, '%field' => $element['#field_name'], '%type' => $element['#type_name']));
8ffd8e3d
DP
173 form_set_error($upload_name, t('The file could not be uploaded.'));
174 return 0;
175 }
176
177 if (!$file = field_file_save_upload($upload_name, $element['#upload_validators'], $dest)) {
32984cd2 178 watchdog('filefield', 'The file upload failed. %upload', array('%upload' => $upload_name));
29194778 179 form_set_error($upload_name, t('The file in the @field field was unable to be uploaded.', array('@field' => $element['#title'])));
8ffd8e3d
DP
180 return 0;
181 }
182 return $file['fid'];
183}
184
22e736e6 185/**
87d3e491 186 * The #value_callback for the filefield_widget type element.
22e736e6 187 */
d2f124d5 188function filefield_widget_value($element, $edit = FALSE) {
7e784adc 189 if (!$edit) {
692a0c14 190 $file = field_file_load($element['#default_value']['fid']);
d2f124d5
DP
191 $item = $element['#default_value'];
192 }
193 else {
9811a70a 194 $item = array_merge($element['#default_value'], $edit);
692a0c14
NH
195 $field = content_fields($element['#field_name'], $element['#type_name']);
196
197 // Uploads take priority over value of fid text field.
8ffd8e3d 198 if ($fid = filefield_save_upload($element)) {
9811a70a 199 $item['fid'] = $fid;
7e784adc 200 }
01c15c1d
NH
201 // Check for #filefield_value_callback values.
202 // Because FAPI does not allow multiple #value_callback values like it does
203 // for #element_validate and #process, this fills the missing functionality
204 // to allow FileField to be extended purely through FAPI.
205 elseif (isset($element['#filefield_value_callback'])) {
206 foreach ($element['#filefield_value_callback'] as $callback) {
207 $callback($element, $item);
208 }
209 }
5322fc46 210
692a0c14 211 // Load file if the FID has changed so that it can be saved by CCK.
9811a70a 212 $file = field_file_load($item['fid']);
692a0c14 213
3ecf9d5c
NH
214 // If the file entry doesn't exist, don't save anything.
215 if (empty($file)) {
216 $item = array();
217 }
218
692a0c14
NH
219 // Checkboxes loose their value when empty.
220 // If the list field is present make sure its unchecked value is saved.
4a03547e 221 if (!empty($field['list_field']) && empty($edit['list'])) {
692a0c14
NH
222 $item['list'] = 0;
223 }
d2f124d5 224 }
692a0c14 225 // Merge file and item data so it is available to all widgets.
6e7782b4 226 $item = array_merge($item, $file);
1bffec9e 227
6e7782b4 228 return $item;
d2f124d5
DP
229}
230
87d3e491
NH
231/**
232 * An element #process callback for the filefield_widget field type.
233 *
234 * Expands the filefield_widget type to include the upload field, upload and
235 * remove buttons, and the description field.
236 */
d2f124d5 237function filefield_widget_process($element, $edit, &$form_state, $form) {
9c0b75b0 238 // The widget is being presented, so apply the JavaScript.
239 drupal_add_js(drupal_get_path('module', 'filefield') .'/filefield.js');
7e784adc 240
8ffd8e3d
DP
241 $item = $element['#value'];
242 $field_name = $element['#field_name'];
243 $delta = $element['#delta'];
3897ed27 244 $element['#theme'] = 'filefield_widget_item';
8ffd8e3d 245
ad6c5ff0
DP
246 $field = content_fields($element['#field_name'], $element['#type_name']);
247
3897ed27
NH
248 // Title is not necessary for each individual field.
249 if ($field['multiple'] > 0) {
250 unset($element['#title']);
251 }
252
4b58ccde
NH
253 // Set up the buttons first since we need to check if they were clicked.
254 $element['filefield_upload'] = array(
255 '#type' => 'submit',
256 '#value' => t('Upload'),
257 '#process' => array('form_expand_ahah'),
258 '#submit' => array('node_form_submit_build_node'),
259 '#ahah' => array( // with JavaScript
260 'path' => 'filefield/ahah/'. $element['#type_name'] .'/'. $element['#field_name'] .'/'. $element['#delta'],
261 'wrapper' => $element['#id'] .'-ahah-wrapper',
262 'method' => 'replace',
263 'effect' => 'fade',
264 ),
265 '#field_name' => $element['#field_name'],
266 '#delta' => $element['#delta'],
267 '#type_name' => $element['#type_name'],
268 '#upload_validators' => $element['#upload_validators'],
269 '#weight' => 100,
270 '#post' => $element['#post'],
271 );
272 $element['filefield_remove'] = array(
273 '#name' => $element['#field_name'] .'_'. $element['#delta'] .'_filefield_remove',
274 '#type' => 'submit',
275 '#value' => t('Remove'),
276 '#process' => array('form_expand_ahah'),
277 '#submit' => array('node_form_submit_build_node'),
278 '#ahah' => array( // with JavaScript
279 'path' => 'filefield/ahah/'. $element['#type_name'] .'/'. $element['#field_name'] .'/'. $element['#delta'],
280 'wrapper' => $element['#id'] .'-ahah-wrapper',
281 'method' => 'replace',
282 'effect' => 'fade',
283 ),
284 '#field_name' => $element['#field_name'],
285 '#delta' => $element['#delta'],
286 '#weight' => 101,
287 '#post' => $element['#post'],
288 );
289
290 // Because the output of this field changes depending on the button clicked,
291 // we need to ask FAPI immediately if the remove button was clicked.
292 // It's not good that we call this private function, but
293 // $form_state['clicked_button'] is only available after this #process
294 // callback is finished.
295 if (_form_button_was_clicked($element['filefield_remove'])) {
319a4dc5
NH
296 // Delete the file if it is currently unused. Note that field_file_delete()
297 // does a reference check in addition to our basic status check.
298 if (isset($edit['fid'])) {
299 $removed_file = field_file_load($edit['fid']);
300 if ($removed_file['status'] == 0) {
301 field_file_delete($removed_file);
302 }
303 }
3a35dc81 304 $item = array('fid' => 0, 'list' => $field['list_default'], 'data' => array('description' => ''));
8ffd8e3d 305 }
7e784adc 306
4b58ccde
NH
307 // Set access on the buttons.
308 $element['filefield_upload']['#access'] = empty($item['fid']);
309 $element['filefield_remove']['#access'] = !empty($item['fid']);
310
e3623331 311 // Add progress bar support to the upload if possible.
70785e17
NH
312 $progress_indicator = isset($field['widget']['progress_indicator']) ? $field['widget']['progress_indicator'] : 'bar';
313 if ($progress_indicator != 'throbber' && $implementation = filefield_progress_implementation()) {
e3623331
NH
314 $upload_progress_key = md5(mt_rand());
315
316 if ($implementation == 'uploadprogress') {
317 $element['UPLOAD_IDENTIFIER'] = array(
318 '#type' => 'hidden',
319 '#value' => $upload_progress_key,
320 '#attributes' => array('class' => 'filefield-progress'),
321 );
322 }
323 elseif ($implementation == 'apc') {
324 $element['APC_UPLOAD_PROGRESS'] = array(
325 '#type' => 'hidden',
326 '#value' => $upload_progress_key,
327 '#attributes' => array('class' => 'filefield-progress'),
328 );
329 }
330
331 // Add the upload progress callback.
332 $element['filefield_upload']['#ahah']['progress']['type'] = 'bar';
333 $element['filefield_upload']['#ahah']['progress']['path'] = 'filefield/progress/' . $upload_progress_key;
334 }
335
123172a6
NH
336 // Set the FID.
337 $element['fid'] = array(
338 '#type' => 'hidden',
339 '#value' => $item['fid'],
340 );
d2f124d5 341
6e7782b4 342 if ($item['fid'] != 0) {
e49d0f07
NH
343 $element['preview'] = array(
344 '#type' => 'markup',
345 '#value' => theme('filefield_widget_preview', $item),
346 );
d2f124d5 347 }
28b1c58e
DP
348
349 // placeholder.. will be serialized into the data column. this is a place for widgets
350 // to put additional data.
a679aaae
NH
351 $element['data'] = array(
352 '#tree' => 'true',
353 '#access' => !empty($item['fid']),
354 );
2635f5af 355
4a03547e 356 if (!empty($field['description_field'])) {
2635f5af 357 $element['data']['description'] = array(
358 '#type' => 'textfield',
359 '#title' => t('Description'),
360 '#value' => isset($item['data']['description']) ? $item['data']['description'] : '',
994c57b0 361 '#type' => variable_get('filefield_description_type', 'textfield'),
f56c699b 362 '#maxlength' => variable_get('filefield_description_length', 128),
2635f5af 363 );
364 }
28b1c58e 365
4a03547e 366 if (!empty($field['list_field'])) {
28b1c58e 367 $element['list'] = array(
f24fc10c 368 '#type' => empty($item['fid']) ? 'hidden' : 'checkbox',
28b1c58e 369 '#title' => t('List'),
8ffd8e3d 370 '#value' => isset($item['list']) ? $item['list'] : $field['list_default'],
28b1c58e
DP
371 '#attributes' => array('class' => 'filefield-list'),
372 );
373 }
35873ed9
NH
374 else {
375 $element['list'] = array(
376 '#type' => 'hidden',
377 '#value' => '1',
378 );
379 }
d2f124d5 380
8ffd8e3d
DP
381 foreach ($element['#upload_validators'] as $callback => $arguments) {
382 $help_func = $callback .'_help';
ad6bb31f
DP
383 if (function_exists($help_func)) {
384 $desc[] = call_user_func_array($help_func, $arguments);
385 }
8ffd8e3d
DP
386 }
387 $element['upload'] = array(
388 '#name' => 'files['. $element['#field_name'] .'_'. $element['#delta'] .']',
389 '#type' => 'file',
8ffd8e3d 390 '#description' => implode('<br />', $desc),
3897ed27 391 '#size' => 22,
8ffd8e3d 392 '#attributes' => array(
f976317f 393 'accept' => implode(',', array_filter(explode(' ', $field['widget']['file_extensions']))),
3897ed27
NH
394 ),
395 '#access' => empty($item['fid']),
8ffd8e3d
DP
396 );
397
f613b75e 398 $element['#attributes']['id'] = $element['#id'] .'-ahah-wrapper';
f613b75e 399 $element['#prefix'] = '<div '. drupal_attributes($element['#attributes']) .'>';
aa3a8ca0 400 $element['#suffix'] = '</div>';
d2f124d5 401
d2f124d5
DP
402 return $element;
403}
404
87d3e491
NH
405/**
406 * An #element_validate callback for the filefield_widget field.
407 */
123172a6
NH
408function filefield_widget_validate(&$element, &$form_state) {
409 // If referencing an existing file, only allow if there are existing
410 // references. This prevents unmanaged files (outside of FileField) from
411 // being deleted if this node were to be deleted.
412 if (!empty($element['fid']['#value'])) {
413 $field = content_fields($element['#field_name'], $element['#type_name']);
414 if ($file = field_file_load($element['fid']['#value'])) {
415 $file = (object) $file;
ab6a2015
NH
416 if ($file->status == FILE_STATUS_PERMANENT) {
417 // TODO: We could use field_file_references() here to reference any file
418 // but hook_file_delete() needs to be implemented first.
419 $references = module_invoke('filefield', 'file_references', $file);
420 if ($references['filefield'] == 0) {
72b7664c 421 form_error($element, t('Referencing to the file used in the %field field is not allowed.', array('%field' => $element['#title'])));
ab6a2015 422 }
123172a6
NH
423 }
424 }
425 else {
426 form_error($element, t('The file referenced by the %field field does not exist.', array('%field' => $element['#title'])));
427 }
428 }
d2f124d5
DP
429}
430
d2f124d5
DP
431/**
432 * FormAPI theme function. Theme the output of an image field.
433 */
bad2b17f 434function theme_filefield_widget($element) {
c6e8be79 435 return theme('form_element', $element, $element['#children']);
d2f124d5
DP
436}
437
22e736e6 438function theme_filefield_widget_preview($item) {
96f6f7a9
NH
439 // Remove the current description so that we get the filename as the link.
440 if (isset($item['data']['description'])) {
441 unset($item['data']['description']);
442 }
443
839679c0
NH
444 return '<div class="filefield-file-info">'.
445 '<div class="filename">'. theme('filefield_file', $item) .'</div>'.
446 '<div class="filesize">'. format_size($item['filesize']) .'</div>'.
447 '<div class="filemime">'. $item['filemime'] .'</div>'.
448 '</div>';
22e736e6
DP
449}
450
451function theme_filefield_widget_item($element) {
3897ed27 452 // Put the upload button directly after the upload field.
ad98c19d 453 $element['upload']['#field_suffix'] = drupal_render($element['filefield_upload']);
3897ed27
NH
454 $element['upload']['#theme'] = 'filefield_widget_file';
455
456 $output = '';
457 $output .= '<div class="filefield-element clear-block">';
458
459 if ($element['fid']['#value'] != 0) {
839679c0 460 $output .= '<div class="widget-preview">';
3897ed27
NH
461 $output .= drupal_render($element['preview']);
462 $output .= '</div>';
463 }
464
839679c0 465 $output .= '<div class="widget-edit">';
3897ed27
NH
466 $output .= drupal_render($element);
467 $output .= '</div>';
468 $output .= '</div>';
469
470 return $output;
471}
472
473/**
ab322a18
NH
474 * Custom theme function for FileField upload elements.
475 *
476 * This function allows us to put the "Upload" button immediately after the
477 * file upload field by respecting the #field_suffix property.
3897ed27
NH
478 */
479function theme_filefield_widget_file($element) {
480 $output = '';
481
482 $output .= '<div class="filefield-upload clear-block">';
483
484 if (isset($element['#field_prefix'])) {
485 $output .= $element['#field_prefix'];
486 }
487
488 _form_set_class($element, array('form-file'));
489 $output .= '<input type="file" name="'. $element['#name'] .'"'. ($element['#attributes'] ? ' '. drupal_attributes($element['#attributes']) : '') .' id="'. $element['#id'] .'" size="'. $element['#size'] ."\" />\n";
490
491 if (isset($element['#field_suffix'])) {
492 $output .= $element['#field_suffix'];
493 }
494
495 $output .= '</div>';
496
497 return theme('form_element', $element, $output);
bad2b17f 498}
d2f124d5 499
2be7e4b0 500/**
87d3e491
NH
501 * Additional #validate handler for the node form.
502 *
503 * This function checks the #required properties on file fields and calculates
504 * node upload totals for all file fields. The #required property is not
505 * properly supported on file fields by Drupal core, so we do this manually.
2be7e4b0 506 */
2be7e4b0 507function filefield_node_form_validate($form, &$form_state) {
2be7e4b0
DP
508 $type = content_types($form['type']['#value']);
509 foreach ($type['fields'] as $field_name => $field) {
b6644f47 510 if (!(in_array($field['module'], array('imagefield', 'filefield')))) continue;
2be7e4b0 511 $empty = $field['module'] .'_content_is_empty';
e76d77f0 512 $valid = FALSE;
f92ea317 513 $total_filesize = 0;
9b86f834 514 if (!empty($form_state['values'][$field_name])) {
e76d77f0 515 foreach ($form_state['values'][$field_name] as $delta => $item) {
9b86f834
NH
516 if ($empty($item, $field)) continue;
517 $valid = TRUE;
518 $total_filesize += (int)$item['filesize'];
519 }
2be7e4b0 520 }
9412a7cc 521
b6644f47 522 if (!$valid && $field['required']) {
f92ea317
DP
523 form_set_error($field_name, t('%title field is required.', array('%title' => $field['widget']['label'])));
524 }
525 $max_filesize = parse_size($field['widget']['max_filesize_per_node']);
5af49125 526 if ($max_filesize && $total_filesize > $max_filesize) {
7e784adc 527 form_set_error($field_name, t('Total filesize for %title, %tsize, exceeds field settings of %msize.',
f92ea317 528 array(
7e784adc 529 '%title' => $field['widget']['label'],
530 '%tsize' => format_size($total_filesize),
f92ea317
DP
531 '%msize' => format_size($max_filesize)
532 )
533 ));
534 }
2be7e4b0
DP
535 }
536}