diff --git a/includes/redhen_donation.forms.inc b/includes/redhen_donation.forms.inc index af3b6a7..98f8d37 100644 --- a/includes/redhen_donation.forms.inc +++ b/includes/redhen_donation.forms.inc @@ -270,6 +270,69 @@ function redhen_donation_entity_settings_form($form, &$form_state, $settings, $e ), ); + $form['settings']['suggestion'] = array( + '#type' => 'fieldset', + '#title' => t('Personalize Donation Suggestions'), + '#description' => t('Suggest a donation amount based on prior donations.'), + '#collapsible' => FALSE, + '#tree' => TRUE, + '#states' => array( + 'invisible' => array( + ':input[name="settings[donation_entry]"]' => array('value' => 'custom'), + ), + ), + ); + $form['settings']['suggestion']['donation_suggestion'] = array( + '#type' => 'select', + '#title' => t('Donation suggestion basis'), + '#default_value' => isset($settings['settings']['suggestion']['donation_suggestion']) ? $settings['settings']['suggestion']['donation_suggestion'] : '', + '#options' => array( + '' => t('-- Disabled --'), + 'largest' => "Largest Donation Amount", + ), + ); + $form['settings']['suggestion']['suggestion_minimum'] = array( + '#type' => 'textfield', + '#title' => t('Suggestion Minimum'), + '#default_value' => isset($settings['settings']['suggestion']['suggestion_minimum']) ? $settings['settings']['suggestion']['suggestion_minimum'] : 0, + '#description' => t('The smallest prior donation amount on which to base donations (useful to avoid extremely small donation suggestions if you have very small-value donors.)'), + '#size' => 10, + '#element_validate' => array('element_validate_number'), + '#states' => array( + 'invisible' => array( + ':input[name="settings[suggestion][donation_suggestion]"]' => array('value' => ''), + ), + ), + ); + $form['settings']['suggestion']['suggestion_increment'] = array( + '#type' => 'textfield', + '#title' => t('Suggestion multiplier'), + '#default_value' => isset($settings['settings']['suggestion']['suggestion_increment']) ? $settings['settings']['suggestion']['suggestion_increment'] : '1.3', + '#element_validate' => array('element_validate_number'), + '#description' => t('When suggesting donation amounts, what should each amount be generated by to generate the next suggestion?'), + '#size' => 10, + '#states' => array( + 'invisible' => array( + ':input[name="settings[suggestion][donation_suggestion]"]' => array('value' => ''), + ), + ), + ); + $form['settings']['suggestion']['suggestion_sort'] = array( + '#type' => 'select', + '#title' => t('Suggestion sort order'), + '#default_value' => isset($settings['settings']['suggestion']['suggestion_sort']) ? $settings['settings']['suggestion']['suggestion_sort'] : '', + '#options' => array( + '' => t('- None -'), + 'asc' => t('Sort ascending'), + 'desc' => t('Sort descending'), + ), + '#states' => array( + 'invisible' => array( + ':input[name="settings[suggestion][donation_suggestion]"]' => array('value' => ''), + ), + ), + ); + $form['settings']['submit_label'] = array( '#type' => 'textfield', '#title' => t('Submit button'), @@ -613,7 +676,8 @@ function redhen_donation_form($form, &$form_state, RedhenDonation $donation, $us else { $default_product = reset($products); } - if (commerce_recurring_product_is_recurring($default_product) && !empty($settings['settings']['recurring_donation_amounts'])) { + $recurring_default = commerce_recurring_product_is_recurring($default_product); + if ($recurring_default && !empty($settings['settings']['recurring_donation_amounts'])) { $amount_options = $settings['settings']['recurring_donation_amounts']; } else { @@ -628,6 +692,16 @@ function redhen_donation_form($form, &$form_state, RedhenDonation $donation, $us $donation_amounts_default = !empty($settings['settings']['donation_amounts_default']) ? $settings['settings']['donation_amounts_default'] : NULL; $amount_label = isset($settings['settings']['donation_amounts_label']) ? $settings['settings']['donation_amounts_label'] : 'Donation Amount (@cur)'; $amount_title = format_string($amount_label, array('@cur' => $cur)); + if (!empty($settings['settings']['suggestion']['donation_suggestion']) && $contact_wrapper->getIdentifier() && !$recurring_default) { + $suggestion_config = array( + 'style' => $settings['settings']['suggestion']['donation_suggestion'], + 'currency' => $cur, + 'minimum' => $settings['settings']['suggestion']['suggestion_minimum'], + 'increment' => $settings['settings']['suggestion']['suggestion_increment'], + 'sort' => $settings['settings']['suggestion']['suggestion_sort'], + ); + _redhen_donation_suggest_donation($donation_amounts, $suggestion_config, $contact_wrapper); + } switch ($settings['settings']['donation_entry']) { case 'select': case 'radios': @@ -650,9 +724,12 @@ function redhen_donation_form($form, &$form_state, RedhenDonation $donation, $us '#default_value' => $donation_amounts_default, '#other' => isset($settings['settings']['other_label']) ? $settings['settings']['other_label'] : t('Other'), '#other_description' => t('Please enter an amount.'), + '#other_size' => 5, '#other_unknown_defaults' => 'other', '#other_delimiter' => ', ', '#select_type' => $settings['settings']['donation_entry'] == 'select_other' ? 'select' : 'radios', + '#field_widget' => 'select_or_other_buttons', + '#maxlength' => 30, ); break; @@ -756,6 +833,73 @@ function redhen_donation_amount_options_callback($form, $form_state) { return $form['donation']; } +/** + * Helper function to generate custom donation amount options for a Contact. + * NOTE: intended for one-off donations, not recurring ones. + * + * @array $donation_amounts + * Reference to the Options array for use in a select or radio field. + * @array $config + * Relevant configuration information. + * @entityMetadataWrapper $contact_wrapper + * Redhen Contact Wrapper: the Contact to suggest amounts for. + */ +function _redhen_donation_suggest_donation(&$donation_amounts, $config, $contact_wrapper) { + drupal_alter('redhen_donation_suggestion_config', $config, $contact_wrapper); + + $lower_bound = !empty($config['minimum']) ? $config['minimum'] : min(array_keys($donation_amounts)); + $contact_id = $contact_wrapper->getIdentifier(); + + $historical_donation_amounts = array(); + + if ($contact_id) { + // Find historical one-off donations. + $query = new EntityFieldQuery(); + $query->entityCondition('entity_type', 'redhen_donation') + ->propertyCondition('contact_id', $contact_id, '=') + ->propertyCondition('transaction_entity_type', 'commerce_order', '=') + ->propertyCondition('received', 100 * $lower_bound, '>=') + ->propertyOrderBy('received', 'DESC'); + $result = $query->execute(); + + if (!empty($result['redhen_donation'])) { + foreach($result['redhen_donation'] as $donation_result) { + $donation = redhen_donation_load($donation_result->donation_id); + $historical_donation_amounts[] = $donation->received / 100; + } + } + } + + drupal_alter('redhen_donation_historical_donation_amounts', $historical_donation_amounts, $config, $contact_wrapper); + + if ($historical_donation_amounts) { + switch ($config['style']) { + case "largest": + // Find a donation, build new amounts array: + $largest_donation = max($historical_donation_amounts); + if ($largest_donation && $largest_donation >= $lower_bound) { + // Round past maximum to nearest $5 for new suggestion. + $amount = 5 * round($largest_donation / 5); + $new_amounts = array(); + while (count($donation_amounts) > count($new_amounts)) { + $new_amounts[$amount] = $config['currency'] . $amount; + // Increase amount for next loop, round to nearest $10: + $amount = 10 * round($amount * $config['increment'] / 10); + } + $donation_amounts = $new_amounts; + } + break; + } + + if (!empty($config['sort'])) { + ksort($donation_amounts); + if ($config['sort'] === 'desc') { + $donation_amounts = array_reverse($donation_amounts, TRUE); + } + } + } +} + /** * Set defaults based on URL query parameters. *