Contribution error

I have a customized Contribution plugin form that works on my current production server but on our new development server is throwing the following error when the form is submitted. I'm not quite sure what to make of it. The new item is created, including any files, but all the metadata fields are empty. Any ideas? -- E

2014-07-15T14:58:24-04:00 ERR (3): exception 'Zend_Db_Statement_Mysqli_Exception' with message 'Mysqli statement execute error : No data supplied for parameters in prepared statement' in /oss/community-gardens.sg/htdocs/application/libraries/Zend/Db/Statement/Mysqli.php:214
Stack trace:
#0 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Db/Statement.php(303): Zend_Db_Statement_Mysqli->_execute(Array)
#1 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Db/Adapter/Abstract.php(480): Zend_Db_Statement->execute(Array)
#2 [internal function]: Zend_Db_Adapter_Abstract->query(Object(Omeka_Db_Select), Array)
#3 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Db.php(79): call_user_func_array(Array, Array)
#4 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Db/Table.php(597): Omeka_Db->__call('query', Array)
#5 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Db/Table.php(597): Omeka_Db->query(Object(Omeka_Db_Select), Array)
#6 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Db/Table.php(281): Omeka_Db_Table->fetchObjects(Object(Omeka_Db_Select))
#7 /oss/community-gardens.sg/htdocs/plugins/Geolocation/models/Location.php(30): Omeka_Db_Table->findBy(Array)
#8 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Record/AbstractRecord.php(383): Location->_validate()
#9 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Record/AbstractRecord.php(533): Omeka_Record_AbstractRecord->isValid()
#10 /oss/community-gardens.sg/htdocs/plugins/Geolocation/GeolocationPlugin.php(196): Omeka_Record_AbstractRecord->save()
#11 /oss/community-gardens.sg/htdocs/plugins/Geolocation/GeolocationPlugin.php(426): GeolocationPlugin->hookAfterSaveItem(Array)
#12 [internal function]: GeolocationPlugin->hookContributionSaveForm(Array)
#13 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Plugin/Broker.php(157): call_user_func(Array, Array)
#14 /oss/community-gardens.sg/htdocs/application/libraries/globals.php(188): Omeka_Plugin_Broker->callHook('contribution_sa...', Array)
#15 /oss/community-gardens.sg/htdocs/plugins/Contribution/controllers/ContributionController.php(231): fire_plugin_hook('contribution_sa...', Array)
#16 /oss/community-gardens.sg/htdocs/plugins/Contribution/controllers/ContributionController.php(63): Contribution_ContributionController->_processForm(Array)
#17 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Controller/Action.php(516): Contribution_ContributionController->contributeAction()
#18 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Controller/Dispatcher/Standard.php(308): Zend_Controller_Action->dispatch('contributeActio...')
#19 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Controller/Front.php(954): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#20 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Application/Bootstrap/Bootstrap.php(97): Zend_Controller_Front->dispatch()
#21 /oss/community-gardens.sg/htdocs/application/libraries/Zend/Application.php(366): Zend_Application_Bootstrap_Bootstrap->run()
#22 /oss/community-gardens.sg/htdocs/application/libraries/Omeka/Application.php(79): Zend_Application->run()
#23 /oss/community-gardens.sg/htdocs/index.php(23): Omeka_Application->run()
#24 {main}

First guess is that I see something from Geolocation in there. If you deactivate Geolocation, does it work again?

It does work without the Geolocation map, but only if I manually remove the fire_plugin_hook('contribution_type_form', array('type'=>$type, 'view'=>$this)); line from the custom type form.

Disabling the "add to contribution form" option in the Geolocation plugin settings results in the form not loading at all (i.e. the type-form doesn't load after choosing the contribution-type). So there might be something going on there, I'm not sure.

But the answer is yes, the form works as expected when the Geolocation plugin is removed from the equation.

EDIT: By the way, we're using Omeka 2.1.4, Geolocation 2.1, Guest User 1.0.1, and Contribution 3.0 (with some view customizations).

Well, the disabling in the settings not actually disabling looks like an oversight on our part. I'll experiment around a bit to try to reproduce what you are getting.

The combination of no metadata being save with the error from Geolocation makes me think that something is causing the $_POST data to not arrive, or not arrive in the structure expected. Could you post up an example of the view customizations?

I just pushed up a fix to the problem with the checkbox in the Geolocation settings.

The main change was the addition of multiple file uploads, which we accomplished by editing the plugin directly.

In ContributionController.php, line 272:

protected function _processFileUpload($contributionType) {
    if ($contributionType->isFileAllowed()) {
        $options = array();
        if ($contributionType->isFileRequired()) {
            $options['ignoreNoFile'] = false;
        } else {
            $options['ignoreNoFile'] = true;
        }

        $fileMetadata = array(
            'file_transfer_type' => 'Upload',
            //'files' => 'contributed_file', <-- original
            'files' => array('contributed_file_01','contributed_file_02','contributed_file_03','contributed_file_04','contributed_file_05','contributed_file_06','contributed_file_07','contributed_file_08','contributed_file_09','contributed_file_10'),
            'file_ingest_options' => $options
        );

        // Add the whitelists for uploaded files
        $fileValidation = new ContributionFileValidation;
        $fileValidation->enableFilter();

        return $fileMetadata;
    }
    return array();
}

... Then in our theme, we added the matching post data structures and made some other (mostly superficial) changes to the type-form.php file:

<?php if (!$type): ?>
<p>You must choose a contribution type to continue.</p>
<?php else: ?>

<?php
if ($type->isFileRequired()):
    $required = true;
?>

<div class="field">
        <?php echo $this->formLabel('contributed_file', 'Upload a file'); ?>
        <?php echo $this->formFile('contributed_file', array('class' => 'fileinput')); ?>
</div>

<?php endif; ?>

<fieldset>
<h3>Your Story</h3>
<?php
foreach ($type->getTypeElements() as $contributionTypeElement) {
    echo html_entity_decode($this->elementForm($contributionTypeElement->Element, $item, array('contributionTypeElement'=>$contributionTypeElement)));
}
?>
</fieldset>

<?php
if (!isset($required) && $type->isFileAllowed()):
?>
<!-- Adding a altenate/additional file input form requires adding the field name (eg contributed_file_02) to the array in plugins/Contribution/controllers/ContributionController.php on line 204 -->
<fieldset>
<h3>Upload Files</h3>
<span id="upload">Please upload any files that illustrate your story. You can upload up to ten photo or audio files. The maximum file size is 7 MB. If you would like to share a video, or larger audio files, please email it directly to <a href="mailto:communityofgardens@si.edu" target="_blank">communityofgardens@si.edu</a> with the name of the garden in the subject line. </span>
<div class="field">
        <?php echo $this->formLabel('contributed_file_01', 'Upload a file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_01', array('class' => 'fileinput')); ?>
</div>
<div class="upload-hidden">
<div class="field">
<?php echo $this->formLabel('contributed_file_02', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_02', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_03', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_03', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_04', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_04', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_05', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_05', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_06', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_06', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_07', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_07', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_08', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_08', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_09', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_09', array('class' => 'fileinput')); ?>
</div>
<div class="field">
<?php echo $this->formLabel('contributed_file_10', 'Upload another file (Optional)'); ?>
<?php echo $this->formFile('contributed_file_10', array('class' => 'fileinput')); ?>
</div>
</div>
<div class="upload-more"><a style="cursor:pointer">Upload Additional Files +</a></div>
</fieldset>

<?php endif; ?>

<fieldset>
<h3>About You</h3>
<?php $user = current_user(); ?>
<?php if(get_option('contribution_simple') && !$user) : ?>

<div class="field">
    <?php echo html_entity_decode($this->formLabel('contribution_simple_email', __('Email Address <span>The Smithsonian will not disclose your email address on the website, share it with third parties, or use it to contact you about anything other than your submission. We will contact you if we need clarification about your story.</span>'))); ?>
    <?php echo $this->formText('contribution_simple_email'); ?>
</div>

<?php else: ?>

    <?php echo __('You are logged in as: <a href="/guest-user/user/me/">%s</a>', metadata($user, 'name')); ?>

    <?php
    //pull in the user profile form if it is set
    if( isset($profileType) ): ?>

    <script type="text/javascript" charset="utf-8">
    //<![CDATA[
    jQuery(document).bind('omeka:elementformload', function (event) {
         Omeka.Elements.makeElementControls(event.target, <?php echo js_escape(url('user-profiles/profiles/element-form')); ?>,'UserProfilesProfile'<?php if ($id = metadata($profile, 'id')) echo ', '.$id; ?>);
         Omeka.Elements.enableWysiwyg(event.target);
    });
    //]]>
    </script>

        <h2 class='contribution-userprofile <?php echo $profile->exists() ? "exists" : ""  ?>'><?php echo  __('Your %s profile', $profileType->label); ?></h2>
        <p id='contribution-userprofile-visibility'>
        <?php if ($profile->exists()) :?>
            <span class='contribution-userprofile-visibility'>Show</span><span class='contribution-userprofile-visibility' style='display:none'>Hide</span>
            <?php else: ?>
            <span class='contribution-userprofile-visibility' style='display:none'>Show</span><span class='contribution-userprofile-visibility'>Hide</span>
        <?php endif; ?>
        </p>
        <div class='contribution-userprofile <?php echo $profile->exists() ? "exists" : ""  ?>'>
        <p class="user-profiles-profile-description"><?php echo $profileType->description; ?></p>
        <fieldset name="user-profiles">
        <?php
        foreach($profileType->Elements as $element) {
            echo $this->profileElementForm($element, $profile);
        }
        ?>
        </fieldset>
        </div>
        <?php endif; ?>

<?php endif; ?>

         <div class="inputs">
            <?php $anonymous = isset($_POST['contribution-anonymous']) ? $_POST['contribution-anonymous'] : 0; ?>
            <?php echo $this->formCheckbox('contribution-anonymous', $anonymous, null, array(1, 0)); ?>
            <?php echo $this->formLabel('contribution-anonymous', __("Contribute anonymously.")); ?>
        </div>
</fieldset> 

<fieldset>
<h3>Garden Location</h3>
<span id="location">If your story is about a publicly-accessible garden, please enter the full street address.<br><br><strong>Note for Private Gardens</strong>: If your story is about a private garden, please enter only the neighborhood, city, and state. For example, “Woodley Park, Washington, D.C.” Or, if you do not feel comfortable including the neighborhood, just the city and state. Do not include the street address. On the Community of Gardens map, private gardens are protected by the “zoom” function. At the city level, the residential garden pins will ‘disappear,’ only leaving the public gardens identified at the street level. </span>
<?php
// Allow other plugins to append to the form (pass the type to allow decisions
// on a type-by-type basis). Used on this site only for Geolocation.
fire_plugin_hook('contribution_type_form', array('type'=>$type, 'view'=>$this));
?>
</fieldset>
<script type="text/javascript">

    jQuery(document).ready(function() {
	    //Reveal more file uploads
	    jQuery('.upload-more a').click(function(event){
	            event.preventDefault();
	            jQuery('.contribution article form .upload-hidden').slideDown();
	            jQuery(this).hide();
	    });
		//Edit the map button text
		jQuery(".contribution article form button#geolocation_find_location_by_address").text("Click to Confirm Location");
    });

</script>

<?php endif; ?>

The strange thing is that this works on one server but not another (currently accessible only via VPN, so maybe that's a factor?).