Commit ac30bf8a authored by Dries's avatar Dries

- Patch #391330 by quicksketch, drewish et al: file module to core. Yaaa-a-a-y!

parent ab53f11f
/* $Id$ */
/**
* Managed file element styles.
*/
.form-managed-file .form-file,
.form-managed-file .form-submit {
margin: 0;
}
.form-managed-file input.progress-disabled {
float: none;
display: inline;
}
.form-managed-file div.ajax-progress,
.form-managed-file div.throbber {
display: inline;
float: none;
padding: 1px 5px 2px 5px;
}
.form-managed-file div.ajax-progress div {
display: inline;
}
.form-managed-file div.ajax-progress-bar {
display: none;
margin-top: 4px;
width: 28em;
padding: 0;
}
.form-managed-file div.ajax-progress-bar div.bar {
margin: 0;
}
This diff is collapsed.
; $Id$
name = File
description = Defines a file field type.
package = Core
version = VERSION
core = 7.x
files[] = file.module
files[] = file.field.inc
files[] = file.install
files[] = tests/file.test
<?php
// $Id$
/**
* @file
* Install, update and uninstall functions for File module.
*/
/**
* Implement hook_requirements().
*
* Display information about getting upload progress bars working.
*/
function file_requirements($phase) {
$requirements = array();
// Check the server's ability to indicate upload progress.
if ($phase == 'runtime') {
$implementation = file_progress_implementation();
$apache = strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== FALSE;
$fastcgi = strpos($_SERVER['SERVER_SOFTWARE'], 'mod_fastcgi') !== FALSE || strpos($_SERVER["SERVER_SOFTWARE"], 'mod_fcgi') !== FALSE;
$description = NULL;
if (!$apache) {
$value = t('Not enabled');
$description = t('Your server is not capable of displaying file upload progress. File upload progress requires an Apache server running PHP with mod_php.');
$severity = REQUIREMENT_INFO;
}
elseif ($fastcgi) {
$value = t('Not enabled');
$description = t('Your server is not capable of displaying file upload progress. File upload progress requires PHP be run with mod_php and not as FastCGI.');
$severity = REQUIREMENT_INFO;
}
elseif (!$implementation && extension_loaded('apc')) {
$value = t('Not enabled');
$description = t('Your server is capable of displaying file upload progress through APC, but it is not enabled. Add <code>apc.rfc1867 = 1</code> to your php.ini configuration. Alternatively, it is recommended to use <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>, which supports more than one simultaneous upload.');
$severity = REQUIREMENT_INFO;
}
elseif (!$implementation) {
$value = t('Not enabled');
$description = t('Your server is capable of displaying file upload progress, but does not have the required libraries. It is recommended to install the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a> (preferred) or to install <a href="http://us2.php.net/apc">APC</a>.');
$severity = REQUIREMENT_INFO;
}
elseif ($implementation == 'apc') {
$value = t('Enabled (<a href="http://php.net/manual/en/apc.configuration.php#ini.apc.rfc1867">APC RFC1867</a>)');
$description = t('Your server is capable of displaying file upload progress using APC RFC1867. Note that only one upload at a time is supported. It is recommended to use the <a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress library</a> if possible.');
$severity = REQUIREMENT_OK;
}
elseif ($implementation == 'uploadprogress') {
$value = t('Enabled (<a href="http://pecl.php.net/package/uploadprogress">PECL uploadprogress</a>)');
$severity = REQUIREMENT_OK;
}
$requirements['file_progress'] = array(
'title' => t('Upload progress'),
'value' => $value,
'severity' => $severity,
'description' => $description,
);
}
return $requirements;
}
// $Id$
/**
* @file
* Provides JavaScript additions to the managed file field type.
*
* This file provides progress bar support (if available), popup windows for
* file previews, and disabling of other file fields during AJAX uploads (which
* prevents separate file fields from accidentally uploading files).
*/
(function($) {
/**
* Attach behaviors to managed file element upload fields.
*/
Drupal.behaviors.fileValidateAutoAttach = {
attach: function(context) {
$('div.form-managed-file input.form-file[accept]', context).bind('change', Drupal.file.validateExtension);
},
detach: function(context) {
$('div.form-managed-file input.form-file[accept]', context).unbind('change', Drupal.file.validateExtension);
}
};
/**
* Attach behaviors to the file upload and remove buttons.
*/
Drupal.behaviors.fileButtons = {
attach: function(context) {
$('input.form-submit', context).bind('mousedown', Drupal.file.disableFields);
$('div.form-managed-file input.form-submit', context).bind('mousedown', Drupal.file.progressBar);
},
unattach: function(context) {
$('input.form-submit', context).unbind('mousedown', Drupal.file.disableFields);
$('div.form-managed-file input.form-submit', context).unbind('mousedown', Drupal.file.progressBar);
}
};
/**
* Attach behaviors to links within managed file elements.
*/
Drupal.behaviors.filePreviewLinks = {
attach: function(context) {
$('div.form-managed-file .file a, .file-widget .file a', context).bind('click',Drupal.file.openInNewWindow);
},
detach: function(context){
$('div.form-managed-file .file a, .file-widget .file a', context).unbind('click', Drupal.file.openInNewWindow);
}
};
/**
* File upload utility functions.
*/
Drupal.file = Drupal.file || {
/**
* Client-side file input validation based on the HTML "accept" attribute.
*/
validateExtension: function(event) {
// Remove any previous errors.
$('.file-upload-js-error').remove();
// Add client side validation for the input[type=file] accept attribute.
var accept = this.accept.replace(/,\s*/g, '|');
if (accept.length > 1 && this.value.length > 0) {
var acceptableMatch = new RegExp('\\.(' + accept + ')$', 'gi');
if (!acceptableMatch.test(this.value)) {
var error = Drupal.t("The selected file %filename cannot not be uploaded. Only files with the following extensions are allowed: %extensions.", {
'%filename': this.value,
'%extensions': accept.replace(/\|/g, ', ')
});
$(this).parents('div.form-managed-file').prepend('<div class="messages error file-upload-js-error">' + error + '</div>');
this.value = '';
return false;
}
}
},
/**
* Prevent file uploads when using buttons not intended to upload.
*/
disableFields: function(event){
var clickedButton = this;
// Only disable upload fields for AJAX buttons.
if (!$(clickedButton).hasClass('ajax-processed')) {
return;
}
// Check if we're working with an "Upload" button.
var $enabledFields = [];
if ($(this).parents('div.form-managed-file').size() > 0) {
$enabledFields = $(this).parents('div.form-managed-file').find('input.form-file');
}
var $disabledFields = $('div.form-managed-file input.form-file').not($enabledFields);
// Disable upload fields other than the one we're currently working with.
$disabledFields.attr('disabled', 'disabled');
// All the other mousedown handlers (like Drupal's AJAX behaviors) are
// excuted before any timeout functions will be called, so this effectively
// re-enables the file fields after other processing is complete even though
// it is only a 1 second timeout.
setTimeout(function(){
$disabledFields.attr('disabled', '');
}, 1000);
},
/**
* Add progress bar support if possible.
*/
progressBar: function(event) {
var clickedButton = this;
var $progressId = $(clickedButton).parents('div.form-managed-file').find('input.file-progress');
if ($progressId.size()) {
var originalName = $progressId.attr('name');
// Replace the name with the required identifier.
$progressId.attr('name', originalName.match(/APC_UPLOAD_PROGRESS|UPLOAD_IDENTIFIER/)[0]);
// Restore the original name after the upload begins.
setTimeout(function() {
$progressId.attr('name', originalName);
}, 1000);
}
// Show the progress bar if the upload takes longer than half a second.
setTimeout(function() {
$(clickedButton).parents('div.form-managed-file').find('div.ajax-progress-bar').slideDown();
}, 500);
},
/**
* Open links to files within forms in a new window.
*/
openInNewWindow: function(event) {
$(this).attr('target', '_blank');
window.open(this.href, 'filePreview', 'toolbar=0,scrollbars=1,location=1,statusbar=1,menubar=0,resizable=1,width=500,height=550');
return false;
}
};
})(jQuery);
This diff is collapsed.
This diff is collapsed.
; $Id$
name = File test
description = Provides hooks for testing File module functionality.
package = Core
version = VERSION
core = 7.x
files[] = file_module_test.module
hidden = TRUE
<?php
// $Id$
/**
* @file
* Provides File module pages for testing purposes.
*/
/**
* Implement hook_menu().
*/
function file_module_test_menu() {
$items = array();
$items['file/test'] = array(
'title' => 'Managed file test',
'page callback' => 'drupal_get_form',
'page arguments' => array('file_module_test_form'),
'access arguments' => array('access content'),
);
return $items;
}
function file_module_test_form($form_state) {
$form = array(
'#tree' => TRUE,
);
$form['file'] = array(
'#type' => 'managed_file',
'#title' => t('Managed file'),
'#upload_location' => 'public://test',
'#progress_message' => t('Please wait...'),
);
$form['textfield'] = array(
'#type' => 'textfield',
'#title' => t('Type a value and ensure it stays'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
......@@ -280,7 +280,7 @@ class FileSpaceUsedTest extends FileTestCase {
return array(
'name' => 'File space used tests',
'description' => 'Tests the file_space_used() function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -340,7 +340,7 @@ class FileValidatorTest extends DrupalWebTestCase {
return array(
'name' => 'File validator tests',
'description' => 'Tests the functions used to validate uploaded files.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -498,7 +498,7 @@ class FileUnmanagedSaveDataTest extends FileTestCase {
return array(
'name' => 'Unmanaged file save data',
'description' => 'Tests the unmanaged file save data function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -542,7 +542,7 @@ class FileSaveUploadTest extends FileHookTestCase {
return array(
'name' => 'File uploading',
'description' => 'Tests the file uploading functions.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -685,7 +685,7 @@ class FileDirectoryTest extends FileTestCase {
return array(
'name' => 'File paths and directories',
'description' => 'Tests operations dealing with directories.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -810,7 +810,7 @@ class FileScanDirectoryTest extends FileTestCase {
return array(
'name' => 'File scan directory',
'description' => 'Tests the file_scan_directory() function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -940,7 +940,7 @@ class FileUnmanagedDeleteTest extends FileTestCase {
return array(
'name' => 'Unmanaged file delete',
'description' => 'Tests the unmanaged file delete function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -986,7 +986,7 @@ class FileUnmanagedDeleteRecursiveTest extends FileTestCase {
return array(
'name' => 'Unmanaged recursive file delete',
'description' => 'Tests the unmanaged file delete recursive function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1063,7 +1063,7 @@ class FileUnmanagedMoveTest extends FileTestCase {
return array(
'name' => 'Unmanaged file moving',
'description' => 'Tests the unmanaged file move function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1136,7 +1136,7 @@ class FileUnmanagedCopyTest extends FileTestCase {
return array(
'name' => 'Unmanaged file copying',
'description' => 'Tests the unmanaged file copy function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1224,7 +1224,7 @@ class FileDeleteTest extends FileHookTestCase {
return array(
'name' => 'File delete',
'description' => 'Tests the file delete function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1255,7 +1255,7 @@ class FileMoveTest extends FileHookTestCase {
return array(
'name' => 'File moving',
'description' => 'Tests the file move function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1416,7 +1416,7 @@ class FileCopyTest extends FileHookTestCase {
return array(
'name' => 'File copying',
'description' => 'Tests the file copy function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1562,7 +1562,7 @@ class FileLoadTest extends FileHookTestCase {
return array(
'name' => 'File loading',
'description' => 'Tests the file_load() function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1643,7 +1643,7 @@ class FileSaveTest extends FileHookTestCase {
return array(
'name' => 'File saving',
'description' => 'Tests the file_save() function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1700,7 +1700,7 @@ class FileValidateTest extends FileHookTestCase {
return array(
'name' => 'File validate',
'description' => 'Tests the file_validate() function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1739,7 +1739,7 @@ class FileSaveDataTest extends FileHookTestCase {
return array(
'name' => 'File save data',
'description' => 'Tests the file save data function.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1870,7 +1870,7 @@ class FileDownloadTest extends FileTestCase {
return array(
'name' => 'File download',
'description' => 'Tests for file download/transfer functions.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -1977,7 +1977,7 @@ class FileNameMungingTest extends FileTestCase {
return array(
'name' => 'File naming',
'description' => 'Test filename munging and unmunging.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -2038,7 +2038,7 @@ class FileMimeTypeTest extends DrupalWebTestCase {
return array(
'name' => 'File mimetypes',
'description' => 'Test filename mimetype detection.',
'group' => 'File',
'group' => 'File API',
);
}
......@@ -2124,7 +2124,7 @@ class StreamWrapperRegistryTest extends DrupalWebTestCase {
return array(
'name' => 'Stream Wrapper Registry',
'description' => 'Tests stream wrapper registry.',
'group' => 'File',
'group' => 'File API',
);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment