diff --git a/ContributionPlugin.php b/ContributionPlugin.php index 4afff01e..8437dde4 100644 --- a/ContributionPlugin.php +++ b/ContributionPlugin.php @@ -112,6 +112,7 @@ public function hookInstall() `item_type_id` INT UNSIGNED NOT NULL, `display_name` VARCHAR(255) NOT NULL, `file_permissions` ENUM('Disallowed', 'Allowed', 'Required') NOT NULL DEFAULT 'Disallowed', + `multiple_files` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', PRIMARY KEY (`id`), UNIQUE KEY `item_type_id` (`item_type_id`) ) ENGINE=MyISAM;"; @@ -259,6 +260,12 @@ public function hookUpgrade($args) set_option('contribution_open', get_option('contribution_simple')); delete_option('contribution_simple'); } + + if (version_compare($oldVersion, '3.1.1', '<')) { + $db = $this->_db; + $sql = "ALTER TABLE `$db->ContributionType` ADD COLUMN `multiple_files` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0'"; + $db->query($sql); + } } public function hookUninstallMessage() diff --git a/controllers/ContributionController.php b/controllers/ContributionController.php index 96e931c1..fe6e5e16 100644 --- a/controllers/ContributionController.php +++ b/controllers/ContributionController.php @@ -159,7 +159,7 @@ public function _setupContributeSubmit($typeId) /** * Creates the reCAPTCHA object and returns it. - * + * * @return Zend_Captcha_Recaptcha|null */ protected function _setupCaptcha() @@ -244,7 +244,8 @@ protected function _processForm($post) $itemMetadata['collection_id'] = (int) $collectionId; } - $fileMetadata = $this->_processFileUpload($contributionType); + // TODO Check if there is at least one file if one file or more is required and remove the catch below. + $fileMetadata = $this->_processFilesUpload($contributionType); // This is a hack to allow the file upload job to succeed // even with the synchronous job dispatcher. @@ -263,8 +264,13 @@ protected function _processForm($post) return false; } catch (Omeka_File_Ingest_InvalidException $e) { // Copying this cruddy hack - if (strstr($e->getMessage(), "'contributed_file'")) { + if (strstr($e->getMessage(), "'file'")) { $this->_helper->flashMessenger("You must upload a file when making a {$contributionType->display_name} contribution.", 'error'); + } + // Check multiple files. + elseif (strstr($e->getMessage(), "file_")) { + $this->_helper->flashMessenger(__('One or more files have not been uploaded.') + . ' ' . __('You must upload a file when making a %s contribution.', $contributionType->display_name), 'error'); } else { $this->_helper->flashMessenger($e->getMessage()); } @@ -273,6 +279,7 @@ protected function _processForm($post) $this->_helper->flashMessenger($e->getMessage()); return false; } + $this->_addElementTextsToItem($item, $post['Elements']); // Allow plugins to deal with the inputs they may have added to the form. fire_plugin_hook('contribution_save_form', array('contributionType'=>$contributionType,'record'=>$item, 'post'=>$post)); @@ -310,21 +317,21 @@ protected function _processUserProfile($post, $user) /** * Deals with files specified on the contribution form. * + * @todo Check if multiple files are allowed. + * @todo Error when option is required and when multiple files are allowed: an empty contributed_file input generate an error. + * * @param ContributionType $contributionType Type of contribution. - * @return array File upload array. + * @return array Files upload array. */ - protected function _processFileUpload($contributionType) { + protected function _processFilesUpload($contributionType) + { if ($contributionType->isFileAllowed()) { $options = array(); - if ($contributionType->isFileRequired()) { - $options['ignoreNoFile'] = false; - } else { - $options['ignoreNoFile'] = true; - } + $options['ignoreNoFile'] = !$contributionType->isFileRequired(); $fileMetadata = array( 'file_transfer_type' => 'Upload', - 'files' => 'contributed_file', + 'files' => 'file', 'file_ingest_options' => $options ); @@ -385,13 +392,13 @@ protected function _addElementTextsToItem($item, $elements) */ protected function _validateContribution($post) { - + // ReCaptcha ignores the first argument. if ($this->_captcha and !$this->_captcha->isValid(null, $_POST)) { $this->_helper->flashMessenger(__('Your CAPTCHA submission was invalid, please try again.'), 'error'); return false; } - + if ($post['terms-agree'] == 0) { $this->_helper->flashMessenger(__('You must agree to the Terms and Conditions.'), 'error'); return false; diff --git a/models/ContributionType.php b/models/ContributionType.php index adfbaafb..b532534e 100644 --- a/models/ContributionType.php +++ b/models/ContributionType.php @@ -22,9 +22,12 @@ class ContributionType extends Omeka_Record_AbstractRecord public $item_type_id; public $display_name; public $file_permissions = 'Disallowed'; - - protected $_related = array('ContributionTypeElements' => 'getTypeElements', - 'ItemType' => 'getItemType'); + public $multiple_files = 0; + + protected $_related = array( + 'ContributionTypeElements' => 'getTypeElements', + 'ItemType' => 'getItemType', + ); protected function filterPostData($post) { @@ -34,7 +37,7 @@ protected function filterPostData($post) } return $post; } - + protected function _validate() { if(empty($this->item_type_id)) { @@ -47,7 +50,7 @@ protected function _initializeMixins() $this->_mixins[] = new Mixin_ContributionOrder($this, 'ContributionTypeElement', 'type_id', 'Elements'); } - + /** * Get the type elements associated with this type. * @@ -57,7 +60,7 @@ public function getTypeElements() { return $this->_db->getTable('ContributionTypeElement')->findByType($this); } - + /** * Get the item type associated with this type. * @@ -173,7 +176,7 @@ public function getPossibleTypeElements() } return $options; } - + public function getRecordUrl($action = 'show') { return url("contribution/types/$action/id/{$this->id}"); diff --git a/plugin.ini b/plugin.ini index b9dfbc78..6b839bfc 100644 --- a/plugin.ini +++ b/plugin.ini @@ -6,7 +6,7 @@ link="http://omeka.org/codex/Plugins/Contribution_2.0" support_link="http://omeka.org/forums/forum/plugins" omeka_minimum_version="2.3" omeka_target_version="2.3" -version="3.1.0" +version="3.1.1" tags="social, items" license="GPLv3" required_plugins="GuestUser" diff --git a/views/admin/types/form.php b/views/admin/types/form.php index 3cdd85b0..40e1e79b 100644 --- a/views/admin/types/form.php +++ b/views/admin/types/form.php @@ -1,8 +1,8 @@ -getTable('ContributionType')->getPossibleItemTypes(); $itemTypeOptions = array('' => 'Select an Item Type') + $itemTypeOptions; ?> -
+
@@ -42,17 +42,27 @@ formSelect('file_permissions', $contribution_type->file_permissions, array(), ContributionType::getPossibleFilePermissions()); ?>
- - + + +
+
+ +
+
+

+
+ formCheckbox("multiple_files", null, array('checked' => $contribution_type->multiple_files)); ?> +
+
+
-
    - +
  • Element->name); ?> @@ -65,7 +75,7 @@
    - +
    Element->description); ?>
    @@ -96,7 +106,7 @@ ?> - +
  • @@ -112,7 +122,7 @@
    - + exists()): ?> 'big red button delete-confirm')); ?> diff --git a/views/public/contribution/contribute.php b/views/public/contribution/contribute.php index 30bc025d..7065e6f3 100644 --- a/views/public/contribution/contribute.php +++ b/views/public/contribution/contribute.php @@ -6,13 +6,13 @@ * @package Contribution */ -queue_js_file('contribution-public-form'); $contributionPath = get_option('contribution_page_path'); if(!$contributionPath) { $contributionPath = 'contribution'; } queue_css_file('form'); +queue_js_file('contribution-public-form'); //load user profiles js and css if needed if(get_option('contribution_user_profile_type') && plugin_is_active('UserProfiles') ) { queue_js_file('admin-globals'); @@ -32,7 +32,7 @@
    - +

    redirect = absolute_url(); ?> -

    You must '>create an account or '>log in before contributing. You can still leave your identity to site visitors anonymous.

    +

    You must '>create an account or '>log in before contributing. You can still leave your identity to site visitors anonymous.

    @@ -54,7 +54,19 @@
    - + partial('contribution/type-form.php', $partialOptions); + }?>
    diff --git a/views/public/contribution/type-form.php b/views/public/contribution/type-form.php index 9512c838..547030eb 100644 --- a/views/public/contribution/type-form.php +++ b/views/public/contribution/type-form.php @@ -1,23 +1,26 @@ -

    - +isFileRequired(); +$isAllowed = $type->isFileAllowed(); +$allowMultipleFiles = $isAllowed && $type->multiple_files; +?>

    display_name); ?>

    isFileRequired()): - $required = true; -?> - -
    +// When a file is required, the upload element is displayed before other ones. +if ($isRequired): ?> +
    - formLabel('contributed_file', __('Upload a file')); ?> + formLabel('file', __('Upload a file')); ?>
    -
    - formFile('contributed_file', array('class' => 'fileinput')); ?> +
    +
    + formFile($allowMultipleFiles ? 'file[0]' : 'file', array('class' => 'fileinput button')); ?> +

    +
    - -isFileAllowed()): -?> -
    -
    - formLabel('contributed_file', __('Upload a file (Optional)')); ?> -
    -
    - formFile('contributed_file', array('class' => 'fileinput')); ?> + +
    +
    + formLabel('file', __('Upload a file (Optional)')); ?> +
    +
    +
    + formFile($allowMultipleFiles ? 'file[0]' : 'file', array('class' => 'fileinput button')); ?> +

    +
    + + + +
    formLabel('contribution_email', __('Email (Optional)')); + echo $this->formLabel('contribution_email', __('Email (Optional)')); } else { echo $this->formLabel('contribution_email', __('Email (Required)')); } @@ -90,7 +106,7 @@

    description; ?>

    - Elements as $element) { echo $this->profileElementForm($element, $profile); } @@ -104,4 +120,4 @@ // on a type-by-type basis). fire_plugin_hook('contribution_type_form', array('type'=>$type, 'view'=>$this)); ?> - +' + label + ''); + link.click(function (event) { + event.preventDefault(); + var inputs = filesDiv.find('input'); + var inputCount = inputs.length; + var fileHtml = '
    '; + $(fileHtml).insertAfter(inputs.last()).hide().slideDown(200, function () { + // Extra show fixes IE bug. + $(this).show(); + }); + }); + + $('#upload-files').after(link); + }; +})(jQuery); function toggleProfileEdit() { jQuery('div.contribution-userprofile').toggle(); @@ -26,7 +86,7 @@ function enableContributionAjaxForm(url) { form.empty(); if (value != "") { jQuery.post(url, {contribution_type: value}, function(data) { - form.append(data); + form.append(data); form.show(duration, function() { form.trigger('contribution-form-shown'); form.trigger('omeka:tabselected');