diff --git a/sites/all/modules/contrib/users/feedback/0001-patched-for-email-sending-on-each-feedback-creation-.patch b/sites/all/modules/contrib/users/feedback/0001-patched-for-email-sending-on-each-feedback-creation-.patch new file mode 100644 index 00000000..2f09078a --- /dev/null +++ b/sites/all/modules/contrib/users/feedback/0001-patched-for-email-sending-on-each-feedback-creation-.patch @@ -0,0 +1,1305 @@ +From 235e57d8e944175ddfd7907598ada29c5c2ebb3d Mon Sep 17 00:00:00 2001 +From: Bachir Soussi Chiadmi +Date: Sat, 12 Oct 2013 13:27:26 +0200 +Subject: [PATCH] patched for email sending on each feedback creation + https://drupal.org/node/353548#comment-7130746 + +--- + feedback-353548-45.patch | 338 +++++++++++++++++++++++++++ + feedback.module | 229 ++++++++++++++++++ + feedback.module.orig | 593 +++++++++++++++++++++++++++++++++++++++++++++++ + tests/feedback.test | 75 +++++- + 4 files changed, 1231 insertions(+), 4 deletions(-) + create mode 100644 feedback-353548-45.patch + mode change 100755 => 100644 feedback.module + create mode 100755 feedback.module.orig + mode change 100755 => 100644 tests/feedback.test + +diff --git a/feedback-353548-45.patch b/feedback-353548-45.patch +new file mode 100644 +index 0000000..999e88a +--- /dev/null ++++ b/feedback-353548-45.patch +@@ -0,0 +1,338 @@ ++diff --git a/feedback.module b/feedback.module ++index 9763575..ef5b24a 100644 ++--- a/feedback.module +++++ b/feedback.module ++@@ -534,6 +534,235 @@ function feedback_user_delete($account) { ++ } ++ ++ /** +++ * Implements hook_action_info(). +++ */ +++function feedback_action_info() { +++ return array( +++ 'feedback_process_action' => array( +++ 'label' => t('Process entry'), +++ 'type' => 'feedback', +++ 'configurable' => FALSE, +++ 'behavior' => array('changes_property'), +++ 'triggers' => array('feedback_insert', 'feedback_update'), +++ ), +++ 'feedback_open_action' => array( +++ 'label' => t('Open entry'), +++ 'type' => 'feedback', +++ 'configurable' => FALSE, +++ 'behavior' => array('changes_property'), +++ 'triggers' => array('feedback_insert', 'feedback_update'), +++ ), +++ 'feedback_delete_action' => array( +++ 'label' => t('Delete entry'), +++ 'type' => 'feedback', +++ 'configurable' => FALSE, +++ 'triggers' => array('feedback_insert', 'feedback_update'), +++ ), +++ 'feedback_send_email_action' => array( +++ 'label' => t('Send e-mail of feedback'), +++ 'type' => 'feedback', +++ 'configurable' => TRUE, +++ 'triggers' => array('feedback_insert', 'feedback_update'), +++ ), +++ ); +++} +++ +++/** +++* Implements hook_trigger_info(). +++*/ +++function feedback_trigger_info() { +++ return array( +++ 'feedback' => array( +++ 'feedback_insert' => array( +++ 'label' => t('New feedback is added.'), +++ ), +++ 'feedback_update' => array( +++ 'label' => t('Feedback is marked processed or open.'), +++ ), +++ ), +++ ); +++} +++ +++/** +++ * Implements hook_feedback_insert(). +++ */ +++function feedback_feedback_insert($entry) { +++ $aids = trigger_get_assigned_actions('feedback_insert'); +++ if (!$aids) { +++ return; +++ } +++ +++ $context = array( +++ 'group' => 'feedback', +++ 'hook' => 'feedback_insert', +++ ); +++ +++ foreach ($aids as $aid => $info) { +++ actions_do($aid, $entry, $context); +++ } +++} +++ +++/** +++ * Implements hook_feedback_update(). +++ */ +++function feedback_feedback_update($entry) { +++ $aids = trigger_get_assigned_actions('feedback_update'); +++ if (!$aids) { +++ return; +++ } +++ +++ $context = array( +++ 'group' => 'feedback', +++ 'hook' => 'feedback_update', +++ ); +++ +++ foreach ($aids as $aid => $info) { +++ actions_do($aid, $entry, $context); +++ } +++} +++ +++/** +++ * Sets the status of an entry to processed. +++ * +++ * @ingroup actions +++ */ +++function feedback_process_action($entry, $context) { +++ $entry->status = FEEDBACK_PROCESSED; +++ drupal_write_record('feedback', $entry, 'fid'); +++} +++ +++/** +++ * Sets the status of an entry to open. +++ * +++ * @ingroup actions +++ */ +++function feedback_open_action($entry, $context) { +++ $entry->status = FEEDBACK_OPEN; +++ drupal_write_record('feedback', $entry, 'fid'); +++} +++ +++/** +++ * Deletes a feedback entry. +++ * +++ * @ingroup actions +++ */ +++function feedback_delete_action($entry, $context) { +++ feedback_delete($entry->fid); +++} +++ +++/** +++ * Return a form definition so the Feedback send email action can be configured. +++ * +++ * @param $context +++ * Default values (if we are editing an existing action instance). +++ * @return +++ * Form definition. +++ */ +++function feedback_send_email_action_form($context = array()) { +++ // Set default values for form. +++ $context += array( +++ 'recipients' => '', +++ 'subject' => '', +++ 'message' => '', +++ ); +++ +++ $form['recipients'] = array( +++ '#type' => 'textarea', +++ '#title' => t('Recipients'), +++ '#default_value' => $context['recipients'], +++ '#description' => t("Example: 'webmaster@example.com' or 'dev@example.com,support@example.com'. To specify multiple recipients, separate each e-mail address with a comma."), +++ '#required' => TRUE, +++ ); +++ $form['subject'] = array( +++ '#type' => 'textfield', +++ '#title' => t('Subject'), +++ '#default_value' => $context['subject'], +++ '#maxlength' => '254', +++ '#description' => t('The subject of the message.'), +++ '#required' => TRUE, +++ ); +++ $form['message'] = array( +++ '#type' => 'textarea', +++ '#title' => t('Message'), +++ '#default_value' => $context['message'], +++ '#cols' => '80', +++ '#rows' => '20', +++ '#description' => t('The message that should be sent. You may include the following variables: !uid, !username, !usermail, !useragent (of the user who gave the feedback), !site_name, !status, !message, !url, !date.'), +++ '#required' => TRUE, +++ ); +++ return $form; +++} +++ +++/** +++ * Validate the send e-mail action form submission. +++ */ +++function feedback_send_email_action_validate($form, &$form_state) { +++ if (empty($form_state['values']['recipients'])) { +++ form_set_error('recipients', t('You must enter one or more recipients.')); +++ } +++ else { +++ $recipients = explode(',', $form_state['values']['recipients']); +++ foreach ($recipients as $recipient) { +++ if (!valid_email_address(trim($recipient))) { +++ form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient))); +++ } +++ } +++ } +++} +++ +++/** +++ * Process the send e-mail action form submission. +++ */ +++function feedback_send_email_action_submit($form, $form_state) { +++ // Process the HTML form to store configuration. The keyed array that +++ // we return will be serialized to the database. +++ $params = array( +++ 'recipients' => $form_state['values']['recipients'], +++ 'subject' => $form_state['values']['subject'], +++ 'message' => $form_state['values']['message'], +++ ); +++ return $params; +++} +++ +++/** +++ * Implements the feedback send e-mail action. +++ */ +++function feedback_send_email_action($entry, $context) { +++ $account = user_load($entry->uid); +++ $from = variable_get('site_name', 'Drupal') . ' <' . variable_get('site_mail', '') . '>'; +++ $params = array('entry' => $entry, 'account' => $account, 'context' => $context); +++ // Send the e-mail to the recipients using the site default language. +++ drupal_mail('feedback', 'send_email_action', $context['recipients'], language_default(), $params, $from); +++ watchdog('feedback', 'Feedback information sent to %recipients', array('%recipients' => $context['recipients'])); +++} +++ +++/** +++ * Implements hook_mail(). +++ */ +++function feedback_mail($key, &$message, $params) { +++ $language = $message['language']; +++ $entry = $params['entry']; +++ $account = $params['account']; +++ $context = $params['context']; +++ $variables = array( +++ '!site_name' => variable_get('site_name', 'Drupal'), +++ '!uid' => $account->uid, +++ '!username' => $account->name ? $account->name : t('Anonymous'), +++ '!usermail' => $account->mail ? $account->mail : t('unknown'), +++ '!status' => $entry->status ? t('Processed') : t('Open'), +++ '!message' => $entry->message, +++ '!url' => url($entry->location, array('absolute' => TRUE, 'language' => $language)), +++ '!useragent' => $entry->useragent, +++ '!date' => format_date($entry->timestamp, 'small', '', NULL, $language->language), +++ ); +++ $subject = strtr($context['subject'], $variables); +++ $body = strtr($context['message'], $variables); +++ $message['subject'] .= str_replace(array("\r", "\n"), '', $subject); +++ $message['body'][] = drupal_html_to_text($body); +++} +++ +++ +++/** ++ * Implements hook_mollom_form_list(). ++ */ ++ function feedback_mollom_form_list() { ++diff --git a/tests/feedback.test b/tests/feedback.test ++index 4d4244c..09ce922 100644 ++--- a/tests/feedback.test +++++ b/tests/feedback.test ++@@ -20,8 +20,7 @@ class FeedbackTestCase extends DrupalWebTestCase { ++ } ++ ++ function setUp() { ++- // @todo Remove soft-dependency on Block. ++- parent::setUp(array('block', 'feedback')); +++ parent::setUp(array('feedback', 'trigger')); ++ ++ $this->admin_user = $this->drupalCreateUser(array('access feedback form', 'view feedback messages', 'administer feedback')); ++ $this->web_user = $this->drupalCreateUser(array('access feedback form')); ++@@ -49,7 +48,7 @@ class FeedbackTestCase extends DrupalWebTestCase { ++ $edit = array( ++ 'feedback-messages[0][1]' => TRUE, ++ ); ++- $this->drupalPost(NULL, $edit, t('Submit')); +++ $this->drupalPost(NULL, $edit, t('Update')); ++ $this->assertFieldByName('feedback-messages[1][1]', 1, t('Processed message found.')); ++ } ++ ++@@ -89,4 +88,72 @@ class FeedbackTestCase extends DrupalWebTestCase { ++ $this->assertNoLinkByHref('admin/reports/feedback/1/delete'); ++ $this->assertNoRaw(check_plain($message), t('Message not found.')); ++ } ++-} +++ +++ /** +++ * Test the feedback triggers and actions. +++ */ +++ function testFeedbackEmailAction() { +++ $test_user = $this->drupalCreateUser(array('administer actions', 'administer feedback', 'access feedback form')); +++ $this->drupalLogin($test_user); +++ $this->assignFeedbackEmailAction('feedback_insert', $test_user->mail); +++ +++ // Insert a feedback entry. +++ $message = $this->randomString(); +++ $edit = array( +++ 'message' => $message, +++ ); +++ $this->drupalPost('node', $edit, t('Send feedback')); +++ $this->assertFeedbackEmailTokenReplacement($test_user->mail, $message); +++ +++ $this->assignFeedbackEmailAction('feedback_update', $test_user->mail); +++ +++ // Update a feedback entry. +++ $fid = db_query("SELECT fid FROM {feedback} LIMIT 0,1")->fetchField(); +++ $entry = feedback_load($fid); +++ feedback_save($entry); +++ $this->assertFeedbackEmailTokenReplacement($test_user->mail, $entry->message); +++ } +++ +++ /** +++ * Assigns a system_send_email_action to the passed-in trigger. +++ * +++ * @param $trigger +++ * For example, 'user_login' +++ */ +++ function assignFeedbackEmailAction($trigger, $mail) { +++ $form_name = "trigger_{$trigger}_assign_form"; +++ $form_html_id = strtr($form_name, '_', '-'); +++ +++ $edit = array( +++ 'actions_label' => $trigger . "_feedback_send_email_action", +++ 'recipients' => $mail, +++ 'subject' => $this->randomName(), +++ 'message' => '!message', +++ ); +++ +++ $hash = drupal_hash_base64('feedback_send_email_action'); +++ $this->drupalPost("admin/config/system/actions/configure/$hash", $edit, t('Save')); +++ $this->assertText(t('The action has been successfully saved.')); +++ +++ // Now we have to find out the action ID of what we created. +++ $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback AND label = :label', array(':callback' => 'feedback_send_email_action', ':label' => $edit['actions_label']))->fetchField(); +++ +++ $edit = array('aid' => drupal_hash_base64($aid)); +++ $this->drupalPost('admin/structure/trigger/feedback', $edit, t('Assign'), array(), array(), $form_html_id); +++ } +++ +++ +++ /** +++ * Asserts correct token replacement for the given trigger and account. +++ * +++ * @param $account +++ * The user account which triggered the action. +++ * @param $email_depth +++ * Number of emails to scan, starting with most recent. +++ */ +++ function assertFeedbackEmailTokenReplacement($mail, $message, $email_depth = 1) { +++ $this->verboseEmail($email_depth); +++ $this->assertMailString('body', $message, $email_depth); +++ $this->assertMail('to', $mail, t('Mail sent to correct destination')); +++ } +++} ++\ No newline at end of file +diff --git a/feedback.module b/feedback.module +old mode 100755 +new mode 100644 +index a4acfc0..fef1eda +--- a/feedback.module ++++ b/feedback.module +@@ -550,6 +550,235 @@ function feedback_user_delete($account) { + } + + /** ++ * Implements hook_action_info(). ++ */ ++function feedback_action_info() { ++ return array( ++ 'feedback_process_action' => array( ++ 'label' => t('Process entry'), ++ 'type' => 'feedback', ++ 'configurable' => FALSE, ++ 'behavior' => array('changes_property'), ++ 'triggers' => array('feedback_insert', 'feedback_update'), ++ ), ++ 'feedback_open_action' => array( ++ 'label' => t('Open entry'), ++ 'type' => 'feedback', ++ 'configurable' => FALSE, ++ 'behavior' => array('changes_property'), ++ 'triggers' => array('feedback_insert', 'feedback_update'), ++ ), ++ 'feedback_delete_action' => array( ++ 'label' => t('Delete entry'), ++ 'type' => 'feedback', ++ 'configurable' => FALSE, ++ 'triggers' => array('feedback_insert', 'feedback_update'), ++ ), ++ 'feedback_send_email_action' => array( ++ 'label' => t('Send e-mail of feedback'), ++ 'type' => 'feedback', ++ 'configurable' => TRUE, ++ 'triggers' => array('feedback_insert', 'feedback_update'), ++ ), ++ ); ++} ++ ++/** ++* Implements hook_trigger_info(). ++*/ ++function feedback_trigger_info() { ++ return array( ++ 'feedback' => array( ++ 'feedback_insert' => array( ++ 'label' => t('New feedback is added.'), ++ ), ++ 'feedback_update' => array( ++ 'label' => t('Feedback is marked processed or open.'), ++ ), ++ ), ++ ); ++} ++ ++/** ++ * Implements hook_feedback_insert(). ++ */ ++function feedback_feedback_insert($entry) { ++ $aids = trigger_get_assigned_actions('feedback_insert'); ++ if (!$aids) { ++ return; ++ } ++ ++ $context = array( ++ 'group' => 'feedback', ++ 'hook' => 'feedback_insert', ++ ); ++ ++ foreach ($aids as $aid => $info) { ++ actions_do($aid, $entry, $context); ++ } ++} ++ ++/** ++ * Implements hook_feedback_update(). ++ */ ++function feedback_feedback_update($entry) { ++ $aids = trigger_get_assigned_actions('feedback_update'); ++ if (!$aids) { ++ return; ++ } ++ ++ $context = array( ++ 'group' => 'feedback', ++ 'hook' => 'feedback_update', ++ ); ++ ++ foreach ($aids as $aid => $info) { ++ actions_do($aid, $entry, $context); ++ } ++} ++ ++/** ++ * Sets the status of an entry to processed. ++ * ++ * @ingroup actions ++ */ ++function feedback_process_action($entry, $context) { ++ $entry->status = FEEDBACK_PROCESSED; ++ drupal_write_record('feedback', $entry, 'fid'); ++} ++ ++/** ++ * Sets the status of an entry to open. ++ * ++ * @ingroup actions ++ */ ++function feedback_open_action($entry, $context) { ++ $entry->status = FEEDBACK_OPEN; ++ drupal_write_record('feedback', $entry, 'fid'); ++} ++ ++/** ++ * Deletes a feedback entry. ++ * ++ * @ingroup actions ++ */ ++function feedback_delete_action($entry, $context) { ++ feedback_delete($entry->fid); ++} ++ ++/** ++ * Return a form definition so the Feedback send email action can be configured. ++ * ++ * @param $context ++ * Default values (if we are editing an existing action instance). ++ * @return ++ * Form definition. ++ */ ++function feedback_send_email_action_form($context = array()) { ++ // Set default values for form. ++ $context += array( ++ 'recipients' => '', ++ 'subject' => '', ++ 'message' => '', ++ ); ++ ++ $form['recipients'] = array( ++ '#type' => 'textarea', ++ '#title' => t('Recipients'), ++ '#default_value' => $context['recipients'], ++ '#description' => t("Example: 'webmaster@example.com' or 'dev@example.com,support@example.com'. To specify multiple recipients, separate each e-mail address with a comma."), ++ '#required' => TRUE, ++ ); ++ $form['subject'] = array( ++ '#type' => 'textfield', ++ '#title' => t('Subject'), ++ '#default_value' => $context['subject'], ++ '#maxlength' => '254', ++ '#description' => t('The subject of the message.'), ++ '#required' => TRUE, ++ ); ++ $form['message'] = array( ++ '#type' => 'textarea', ++ '#title' => t('Message'), ++ '#default_value' => $context['message'], ++ '#cols' => '80', ++ '#rows' => '20', ++ '#description' => t('The message that should be sent. You may include the following variables: !uid, !username, !usermail, !useragent (of the user who gave the feedback), !site_name, !status, !message, !url, !date.'), ++ '#required' => TRUE, ++ ); ++ return $form; ++} ++ ++/** ++ * Validate the send e-mail action form submission. ++ */ ++function feedback_send_email_action_validate($form, &$form_state) { ++ if (empty($form_state['values']['recipients'])) { ++ form_set_error('recipients', t('You must enter one or more recipients.')); ++ } ++ else { ++ $recipients = explode(',', $form_state['values']['recipients']); ++ foreach ($recipients as $recipient) { ++ if (!valid_email_address(trim($recipient))) { ++ form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient))); ++ } ++ } ++ } ++} ++ ++/** ++ * Process the send e-mail action form submission. ++ */ ++function feedback_send_email_action_submit($form, $form_state) { ++ // Process the HTML form to store configuration. The keyed array that ++ // we return will be serialized to the database. ++ $params = array( ++ 'recipients' => $form_state['values']['recipients'], ++ 'subject' => $form_state['values']['subject'], ++ 'message' => $form_state['values']['message'], ++ ); ++ return $params; ++} ++ ++/** ++ * Implements the feedback send e-mail action. ++ */ ++function feedback_send_email_action($entry, $context) { ++ $account = user_load($entry->uid); ++ $from = variable_get('site_name', 'Drupal') . ' <' . variable_get('site_mail', '') . '>'; ++ $params = array('entry' => $entry, 'account' => $account, 'context' => $context); ++ // Send the e-mail to the recipients using the site default language. ++ drupal_mail('feedback', 'send_email_action', $context['recipients'], language_default(), $params, $from); ++ watchdog('feedback', 'Feedback information sent to %recipients', array('%recipients' => $context['recipients'])); ++} ++ ++/** ++ * Implements hook_mail(). ++ */ ++function feedback_mail($key, &$message, $params) { ++ $language = $message['language']; ++ $entry = $params['entry']; ++ $account = $params['account']; ++ $context = $params['context']; ++ $variables = array( ++ '!site_name' => variable_get('site_name', 'Drupal'), ++ '!uid' => $account->uid, ++ '!username' => $account->name ? $account->name : t('Anonymous'), ++ '!usermail' => $account->mail ? $account->mail : t('unknown'), ++ '!status' => $entry->status ? t('Processed') : t('Open'), ++ '!message' => $entry->message, ++ '!url' => url($entry->location, array('absolute' => TRUE, 'language' => $language)), ++ '!useragent' => $entry->useragent, ++ '!date' => format_date($entry->timestamp, 'small', '', NULL, $language->language), ++ ); ++ $subject = strtr($context['subject'], $variables); ++ $body = strtr($context['message'], $variables); ++ $message['subject'] .= str_replace(array("\r", "\n"), '', $subject); ++ $message['body'][] = drupal_html_to_text($body); ++} ++ ++ ++/** + * Implements hook_mollom_form_list(). + */ + function feedback_mollom_form_list() { +diff --git a/feedback.module.orig b/feedback.module.orig +new file mode 100755 +index 0000000..a4acfc0 +--- /dev/null ++++ b/feedback.module.orig +@@ -0,0 +1,593 @@ ++ array( ++ 'render element' => 'form', ++ ), ++ 'feedback_entry' => array( ++ 'render element' => 'elements', ++ 'template' => 'feedback-entry', ++ 'file' => 'feedback.admin.inc', ++ ), ++ 'feedback_form_display' => array( ++ 'template' => 'feedback-form-display', ++ 'variables' => array('title' => NULL, 'content' => NULL), ++ ), ++ ); ++} ++ ++/** ++ * Implements hook_entity_info(). ++ */ ++function feedback_entity_info() { ++ $return = array( ++ 'feedback' => array( ++ 'label' => t('Feedback'), ++ 'controller class' => 'FeedbackController', ++ 'base table' => 'feedback', ++ 'uri callback' => 'feedback_uri', ++ 'fieldable' => TRUE, ++ 'entity keys' => array( ++ 'id' => 'fid', ++ ), ++ 'bundles' => array( ++ 'feedback' => array( ++ 'label' => t('Feedback'), ++ 'admin' => array( ++ 'path' => 'admin/config/user-interface/feedback', ++ 'access arguments' => array('administer feedback'), ++ ), ++ ), ++ ), ++ 'view modes' => array( ++ 'full' => array( ++ 'label' => t('Full feedback entry'), ++ 'custom settings' => FALSE, ++ ), ++ 'teaser' => array( ++ 'label' => t('Teaser'), ++ 'custom settings' => FALSE, ++ ), ++ 'widget' => array( ++ 'label' => t('Widget'), ++ 'custom settings' => FALSE, ++ ), ++ ), ++ // Disable Metatags (metatag) module's entity form additions. ++ 'metatags' => FALSE, ++ ), ++ ); ++ ++ return $return; ++} ++ ++/** ++ * Implements hook_field_extra_fields(). ++ */ ++function feedback_field_extra_fields() { ++ $extras['feedback']['feedback']['form']['help'] = array( ++ 'label' => t('Help'), ++ 'description' => t('Feedback submission guidelines'), ++ 'weight' => -10, ++ ); ++ $extras['feedback']['feedback']['form']['messages'] = array( ++ 'label' => t('Entries'), ++ 'description' => t('Existing feedback entries for the current page'), ++ 'weight' => -5, ++ ); ++ $extras['feedback']['feedback']['form']['message'] = array( ++ 'label' => t('Message'), ++ 'description' => t('Feedback message form text field'), ++ 'weight' => 0, ++ ); ++ ++ $extras['feedback']['feedback']['display']['location'] = array( ++ 'label' => t('Location'), ++ 'description' => t('The URL of the page the message was submitted on'), ++ 'weight' => -15, ++ ); ++ $extras['feedback']['feedback']['display']['date'] = array( ++ 'label' => t('Date'), ++ 'description' => t('The submission date of the message'), ++ 'weight' => -10, ++ ); ++ $extras['feedback']['feedback']['display']['user'] = array( ++ 'label' => t('User'), ++ 'description' => t('The name of the user who submitted the message'), ++ 'weight' => -5, ++ ); ++ $extras['feedback']['feedback']['display']['message'] = array( ++ 'label' => t('Message'), ++ 'description' => t('The main feedback message'), ++ 'weight' => 0, ++ ); ++ return $extras; ++} ++ ++/** ++ * Entity uri callback. ++ */ ++function feedback_uri($entry) { ++ return array( ++ 'path' => 'admin/reports/feedback/' . $entry->fid, ++ ); ++} ++ ++/** ++ * Implements hook_permission(). ++ */ ++function feedback_permission() { ++ return array( ++ 'access feedback form' => array( ++ 'title' => t('Access feedback form'), ++ 'description' => t('Submit feedback messages.'), ++ ), ++ 'view feedback messages' => array( ++ 'title' => t('View feedback messages'), ++ 'description' => t('View, process, and delete submitted feedback messages.'), ++ ), ++ 'administer feedback' => array( ++ 'title' => t('Administer feedback settings'), ++ ), ++ ); ++} ++ ++/** ++ * Implements hook_menu(). ++ */ ++function feedback_menu() { ++ $items['admin/reports/feedback'] = array( ++ 'title' => 'Feedback messages', ++ 'description' => 'View feedback messages.', ++ 'page callback' => 'drupal_get_form', ++ 'page arguments' => array('feedback_admin_view_form'), ++ 'access arguments' => array('view feedback messages'), ++ 'file' => 'feedback.admin.inc', ++ ); ++ $items['admin/reports/feedback/%feedback'] = array( ++ 'title' => 'Feedback entry', ++ 'page callback' => 'feedback_view', ++ 'page arguments' => array(3), ++ 'access arguments' => array('view feedback messages'), ++ 'file' => 'feedback.admin.inc', ++ ); ++ $items['admin/reports/feedback/%feedback/view'] = array( ++ 'title' => 'View', ++ 'type' => MENU_DEFAULT_LOCAL_TASK, ++ 'weight' => -10, ++ ); ++ $items['admin/reports/feedback/%feedback/edit'] = array( ++ 'title' => 'Edit', ++ 'page callback' => 'drupal_get_form', ++ 'page arguments' => array('feedback_entry_form', 3), ++ 'access arguments' => array('view feedback messages'), ++ 'type' => MENU_LOCAL_TASK, ++ 'file' => 'feedback.admin.inc', ++ ); ++ $items['admin/reports/feedback/%feedback/delete'] = array( ++ 'title' => 'Delete feedback entry', ++ 'page callback' => 'drupal_get_form', ++ 'page arguments' => array('feedback_delete_confirm', 3), ++ 'access arguments' => array('view feedback messages'), ++ 'type' => MENU_CALLBACK, ++ 'file' => 'feedback.admin.inc', ++ ); ++ $items['admin/config/user-interface/feedback'] = array( ++ 'title' => 'Feedback', ++ 'description' => 'Administer feedback settings.', ++ 'page callback' => 'drupal_get_form', ++ 'page arguments' => array('feedback_admin_settings_form'), ++ 'access arguments' => array('administer feedback'), ++ 'file' => 'feedback.admin.inc', ++ ); ++ $items['admin/config/user-interface/feedback/settings'] = array( ++ 'title' => 'Settings', ++ 'type' => MENU_DEFAULT_LOCAL_TASK, ++ 'weight' => -10, ++ ); ++ ++ return $items; ++} ++ ++/** ++ * Implements hook_page_build(). ++ */ ++function feedback_page_build(&$page) { ++ if (user_access('access feedback form') && !feedback_match_path(variable_get('feedback_excluded_paths', 'admin/reports/feedback'))) { ++ $page['page_bottom']['feedback'] = array( ++ '#theme' => 'feedback_form_display', ++ '#title' => t('Feedback'), ++ '#content' => drupal_get_form('feedback_form'), ++ ); ++ $path = drupal_get_path('module', 'feedback'); ++ $page['page_bottom']['feedback']['#attached']['css'][] = $path . '/feedback.css'; ++ $page['page_bottom']['feedback']['#attached']['js'][] = $path . '/feedback.js'; ++ } ++} ++ ++/** ++ * Check if the current path matches any pattern in a set of patterns. ++ * ++ * @param $patterns ++ * String containing a set of patterns separated by \n, \r or \r\n. ++ * ++ * @return ++ * Boolean value: TRUE if the current path or alias matches a pattern. ++ */ ++function feedback_match_path($patterns) { ++ // Convert path to lowercase. This allows comparison of the same path ++ // with different case. Ex: /Page, /page, /PAGE. ++ $patterns = drupal_strtolower($patterns); ++ ++ // Convert the current path to lowercase. ++ $path = drupal_strtolower(drupal_get_path_alias($_GET['q'])); ++ ++ // Compare the lowercase internal and lowercase path alias (if any). ++ $page_match = drupal_match_path($path, $patterns); ++ if ($path != $_GET['q']) { ++ $page_match = $page_match || drupal_match_path($_GET['q'], $patterns); ++ } ++ ++ return $page_match; ++} ++ ++/** ++ * Form constructor for the feedback form. ++ * ++ * @see feedback_form_submit() ++ * @ingroup forms ++ */ ++function feedback_form($form, &$form_state) { ++ $form['#attributes']['class'] = array('feedback-form'); ++ ++ // Store the path on which this form is displayed. ++ if (!isset($form_state['inline']['location'])) { ++ $form_state['inline']['location'] = $_GET['q']; ++ } ++ $form['location'] = array( ++ '#type' => 'value', ++ '#value' => $form_state['inline']['location'], ++ ); ++ ++ $form['help'] = array( ++ '#prefix' => '
', ++ '#markup' => t('If you experience a bug or would like to see an addition on the current page, feel free to leave us a message.'), ++ '#suffix' => '
', ++ ); ++ if (user_access('view feedback messages')) { ++ if (arg(0) != 'node') { ++ $feedbacks = feedback_load_multiple(array(), array('status' => FEEDBACK_OPEN, 'location_masked' => feedback_mask_path($_GET['q']))); ++ } ++ else { ++ $feedbacks = feedback_load_multiple(array(), array('status' => FEEDBACK_OPEN, 'location' => $_GET['q'])); ++ } ++ if ($feedbacks) { ++ form_load_include($form_state, 'inc', 'feedback', 'feedback.admin'); ++ $form['messages'] = array( ++ '#prefix' => '
', ++ '#suffix' => '
', ++ ); ++ foreach ($feedbacks as $fid => $feedback) { ++ $form['messages'][$fid]['#feedback'] = $feedback; ++ $form['messages'][$fid]['submitted'] = array('#markup' => t('@feedback-author !feedback-date:', array('@feedback-author' => format_username($feedback), '!feedback-date' => format_date($feedback->timestamp, 'small')))); ++ $form['messages'][$fid]['submitted']['#prefix'] = '
'; ++ $form['messages'][$fid]['submitted']['#suffix'] = '
'; ++ $form['messages'][$fid]['body'] = feedback_build_content($feedback, 'widget'); ++ $form['messages'][$fid]['body']['#prefix'] = '
'; ++ $form['messages'][$fid]['body']['#suffix'] = '
'; ++ } ++ } ++ } ++ $form['message'] = array( ++ '#type' => 'textarea', ++ '#attributes' => array('class' => array('feedback-message')), ++ '#cols' => 20, ++ '#title' => t('Message'), ++ '#required' => TRUE, ++ '#wysiwyg' => FALSE, ++ ); ++ ++ $entry = new stdClass(); ++ field_attach_form('feedback', $entry, $form, $form_state); ++ ++ $form['actions'] = array( ++ '#type' => 'actions', ++ // Without clearfix, the AJAX throbber wraps in an ugly way. ++ // @todo Patch #type actions in core? ++ '#attributes' => array('class' => array('clearfix')), ++ ); ++ $form['actions']['submit'] = array( ++ '#type' => 'submit', ++ '#value' => t('Send feedback'), ++ '#id' => 'feedback-submit', ++ '#ajax' => array( ++ 'wrapper' => 'feedback-form', ++ 'callback' => 'feedback_form_ajax_callback', ++ 'progress' => array( ++ 'type' => 'throbber', ++ 'message' => '', ++ ), ++ ), ++ ); ++ ++ return $form; ++} ++ ++/** ++ * Form submission handler for feedback_form(). ++ */ ++function feedback_form_submit($form, &$form_state) { ++ $entry = new stdClass(); ++ entity_form_submit_build_entity('feedback', $entry, $form, $form_state); ++ $entry->message = $form_state['values']['message']; ++ $entry->location = $form_state['values']['location']; ++ feedback_save($entry); ++ ++ drupal_set_message(t('Thanks for your feedback!')); ++} ++ ++/** ++ * AJAX callback for feedback_form() submissions. ++ */ ++function feedback_form_ajax_callback($form, &$form_state) { ++ // If there was a form validation error, re-render the entire form. ++ if (!$form_state['executed']) { ++ return $form; ++ } ++ ++ // Otherwise, return a fresh copy of the form, so the user may post additional ++ // feedback. ++ // Reset the static cache of drupal_html_id(). ++ // @see drupal_process_form() ++ // @see drupal_html_id() ++ $seen_ids = &drupal_static('drupal_html_id'); ++ $seen_ids = array(); ++ ++ // Prevent the form from being processed again. ++ // @see drupal_build_form() ++ list($form, $new_form_state) = ajax_get_form(); ++ $new_form_state['input'] = array(); ++ drupal_process_form($form['#form_id'], $form, $new_form_state); ++ ++ // Return AJAX commands in order to output the special success message. ++ // @see ajax_deliver() ++ $build = array('#type' => 'ajax'); ++ $html = drupal_render($form); ++ $build['#commands'][] = ajax_command_insert(NULL, $html); ++ ++ // A successful form submission normally means that there were no errors, so ++ // we only render status messages. ++ $messages = drupal_get_messages(); ++ $messages += array('status' => array()); ++ $messages = implode('
', $messages['status']); ++ $html = '
' . $messages . '
'; ++ $build['#commands'][] = ajax_command_append('#block-feedback-form', $html); ++ return $build; ++} ++ ++/** ++ * Loads a feedback entry from the database. ++ * ++ * @param $fid ++ * Integer specifying the feedback ID to load. ++ * ++ * @return ++ * A loaded feedback entry object upon successful load, or FALSE if the entry ++ * cannot be loaded. ++ * ++ * @see feedback_load_multiple() ++ */ ++function feedback_load($fid) { ++ $entries = feedback_load_multiple(array($fid)); ++ return (isset($entries[$fid]) ? $entries[$fid] : FALSE); ++} ++ ++/** ++ * Loads feedback entries from the database. ++ * ++ * @param $fids ++ * An array of feedback entry IDs. ++ * @param $conditions ++ * An associative array of conditions on the {feedback} table, where the keys ++ * are the database fields and the values are the values those fields ++ * must have. ++ * ++ * @return ++ * An array of feedback entry objects indexed by fid. ++ * ++ * @see hook_feedback_load() ++ * @see feedback_load() ++ * @see entity_load() ++ * @see EntityFieldQuery ++ */ ++function feedback_load_multiple($fids = array(), $conditions = array()) { ++ return entity_load('feedback', $fids, $conditions); ++} ++ ++/** ++ * Saves changes to a feedback entry or adds a new feedback entry. ++ * ++ * @param $entry ++ * The feedback entry object to modify or add. If $entry->fid is omitted, a ++ * new entry will be added. ++ * ++ * @see hook_feedback_insert() ++ * @see hook_feedback_update() ++ */ ++function feedback_save($entry) { ++ global $user; ++ ++ // Load the stored entity, if any. ++ if (!empty($entry->fid) && !isset($entry->original)) { ++ $entry->original = entity_load_unchanged('feedback', $entry->fid); ++ } ++ ++ field_attach_presave('feedback', $entry); ++ ++ // Allow modules to alter the feedback entry before saving. ++ module_invoke_all('feedback_presave', $entry); ++ module_invoke_all('entity_presave', $entry, 'feedback'); ++ ++ if (empty($entry->fid)) { ++ $entry->message = trim($entry->message); ++ ++ $defaults = array( ++ 'uid' => $user->uid, ++ 'location_masked' => feedback_mask_path($entry->location), ++ 'url' => url($entry->location, array('absolute' => TRUE)), ++ 'timestamp' => REQUEST_TIME, ++ 'useragent' => $_SERVER['HTTP_USER_AGENT'], ++ ); ++ foreach ($defaults as $key => $default) { ++ if (!isset($entry->$key)) { ++ $entry->$key = $default; ++ } ++ } ++ ++ $status = drupal_write_record('feedback', $entry); ++ field_attach_insert('feedback', $entry); ++ module_invoke_all('feedback_insert', $entry); ++ module_invoke_all('entity_insert', $entry, 'feedback'); ++ } ++ else { ++ $status = drupal_write_record('feedback', $entry, 'fid'); ++ ++ field_attach_update('feedback', $entry); ++ module_invoke_all('feedback_update', $entry); ++ module_invoke_all('entity_update', $entry, 'feedback'); ++ } ++ unset($entry->original); ++ ++ return $status; ++} ++ ++/** ++ * Deletes a feedback entry. ++ * ++ * @param $fid ++ * A feedback entry ID. ++ */ ++function feedback_delete($fid) { ++ feedback_delete_multiple(array($fid)); ++} ++ ++/** ++ * Deletes multiple feedback entries. ++ * ++ * @param $fids ++ * An array of feedback entry IDs. ++ */ ++function feedback_delete_multiple($fids) { ++ if (!empty($fids)) { ++ $entries = feedback_load_multiple($fids); ++ foreach ($entries as $fid => $entry) { ++ field_attach_delete('feedback', $entry); ++ module_invoke_all('feedback_delete', $entry); ++ module_invoke_all('entity_delete', $entry, 'feedback'); ++ } ++ db_delete('feedback') ++ ->condition('fid', $fids, 'IN') ++ ->execute(); ++ } ++} ++ ++/** ++ * 'Mask' a path, i.e. replace all numeric arguments in a path with '%' placeholders. ++ * ++ * Please note that only numeric arguments with a preceding slash will be ++ * replaced. ++ * ++ * @param $path ++ * An internal Drupal path, f.e. 'user/123/edit'. ++ * @return ++ * A 'masked' path, for above example 'user/%/edit'. ++ * ++ * @todo Use the untranslated patch of menu_get_item() instead. ++ */ ++function feedback_mask_path($path) { ++ return preg_replace('@/\d+@', '/%', $path); ++} ++ ++/** ++ * Implements hook_user_cancel(). ++ */ ++function feedback_user_cancel($edit, $account, $method) { ++ switch ($method) { ++ case 'user_cancel_reassign': ++ db_update('feedback') ++ ->fields(array('uid' => 0)) ++ ->condition('uid', $account->uid) ++ ->execute(); ++ break; ++ } ++} ++ ++/** ++ * Implements hook_user_delete(). ++ */ ++function feedback_user_delete($account) { ++ $fids = db_query('SELECT fid FROM {feedback} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol(); ++ feedback_delete_multiple($fids); ++} ++ ++/** ++ * Implements hook_mollom_form_list(). ++ */ ++function feedback_mollom_form_list() { ++ $forms['feedback_form'] = array( ++ 'title' => t('Feedback form'), ++ 'entity' => 'feedback', ++ 'bundle' => 'feedback', ++ 'entity delete multiple callback' => 'feedback_delete_multiple', ++ 'delete form' => 'feedback_delete_confirm', ++ 'delete form file' => array( ++ 'name' => 'feedback.admin', ++ ), ++ 'report access' => array('view feedback messages'), ++ ); ++ return $forms; ++} ++ ++/** ++ * Implements hook_mollom_form_info(). ++ */ ++function feedback_mollom_form_info($form_id) { ++ $form_info = array( ++ 'mode' => MOLLOM_MODE_ANALYSIS, ++ 'bypass access' => array('administer feedback'), ++ 'elements' => array( ++ 'message' => t('Message'), ++ ), ++ ); ++ mollom_form_info_add_fields($form_info, 'feedback', 'feedback'); ++ return $form_info; ++} ++ ++/** ++ * Implements hook_views_api(); ++ */ ++function feedback_views_api() { ++ return array( ++ 'api' => 3.0, ++ 'path' => drupal_get_path('module', 'feedback') . '/views', ++ ); ++} +diff --git a/tests/feedback.test b/tests/feedback.test +old mode 100755 +new mode 100644 +index 4d4244c..09ce922 +--- a/tests/feedback.test ++++ b/tests/feedback.test +@@ -20,8 +20,7 @@ class FeedbackTestCase extends DrupalWebTestCase { + } + + function setUp() { +- // @todo Remove soft-dependency on Block. +- parent::setUp(array('block', 'feedback')); ++ parent::setUp(array('feedback', 'trigger')); + + $this->admin_user = $this->drupalCreateUser(array('access feedback form', 'view feedback messages', 'administer feedback')); + $this->web_user = $this->drupalCreateUser(array('access feedback form')); +@@ -49,7 +48,7 @@ class FeedbackTestCase extends DrupalWebTestCase { + $edit = array( + 'feedback-messages[0][1]' => TRUE, + ); +- $this->drupalPost(NULL, $edit, t('Submit')); ++ $this->drupalPost(NULL, $edit, t('Update')); + $this->assertFieldByName('feedback-messages[1][1]', 1, t('Processed message found.')); + } + +@@ -89,4 +88,72 @@ class FeedbackTestCase extends DrupalWebTestCase { + $this->assertNoLinkByHref('admin/reports/feedback/1/delete'); + $this->assertNoRaw(check_plain($message), t('Message not found.')); + } +-} ++ ++ /** ++ * Test the feedback triggers and actions. ++ */ ++ function testFeedbackEmailAction() { ++ $test_user = $this->drupalCreateUser(array('administer actions', 'administer feedback', 'access feedback form')); ++ $this->drupalLogin($test_user); ++ $this->assignFeedbackEmailAction('feedback_insert', $test_user->mail); ++ ++ // Insert a feedback entry. ++ $message = $this->randomString(); ++ $edit = array( ++ 'message' => $message, ++ ); ++ $this->drupalPost('node', $edit, t('Send feedback')); ++ $this->assertFeedbackEmailTokenReplacement($test_user->mail, $message); ++ ++ $this->assignFeedbackEmailAction('feedback_update', $test_user->mail); ++ ++ // Update a feedback entry. ++ $fid = db_query("SELECT fid FROM {feedback} LIMIT 0,1")->fetchField(); ++ $entry = feedback_load($fid); ++ feedback_save($entry); ++ $this->assertFeedbackEmailTokenReplacement($test_user->mail, $entry->message); ++ } ++ ++ /** ++ * Assigns a system_send_email_action to the passed-in trigger. ++ * ++ * @param $trigger ++ * For example, 'user_login' ++ */ ++ function assignFeedbackEmailAction($trigger, $mail) { ++ $form_name = "trigger_{$trigger}_assign_form"; ++ $form_html_id = strtr($form_name, '_', '-'); ++ ++ $edit = array( ++ 'actions_label' => $trigger . "_feedback_send_email_action", ++ 'recipients' => $mail, ++ 'subject' => $this->randomName(), ++ 'message' => '!message', ++ ); ++ ++ $hash = drupal_hash_base64('feedback_send_email_action'); ++ $this->drupalPost("admin/config/system/actions/configure/$hash", $edit, t('Save')); ++ $this->assertText(t('The action has been successfully saved.')); ++ ++ // Now we have to find out the action ID of what we created. ++ $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback AND label = :label', array(':callback' => 'feedback_send_email_action', ':label' => $edit['actions_label']))->fetchField(); ++ ++ $edit = array('aid' => drupal_hash_base64($aid)); ++ $this->drupalPost('admin/structure/trigger/feedback', $edit, t('Assign'), array(), array(), $form_html_id); ++ } ++ ++ ++ /** ++ * Asserts correct token replacement for the given trigger and account. ++ * ++ * @param $account ++ * The user account which triggered the action. ++ * @param $email_depth ++ * Number of emails to scan, starting with most recent. ++ */ ++ function assertFeedbackEmailTokenReplacement($mail, $message, $email_depth = 1) { ++ $this->verboseEmail($email_depth); ++ $this->assertMailString('body', $message, $email_depth); ++ $this->assertMail('to', $mail, t('Mail sent to correct destination')); ++ } ++} +\ No newline at end of file +-- +2.3.5 + diff --git a/sites/all/modules/contrib/users/feedback/feedback-353548-45.patch b/sites/all/modules/contrib/users/feedback/feedback-353548-45.patch deleted file mode 100644 index 999e88a8..00000000 --- a/sites/all/modules/contrib/users/feedback/feedback-353548-45.patch +++ /dev/null @@ -1,338 +0,0 @@ -diff --git a/feedback.module b/feedback.module -index 9763575..ef5b24a 100644 ---- a/feedback.module -+++ b/feedback.module -@@ -534,6 +534,235 @@ function feedback_user_delete($account) { - } - - /** -+ * Implements hook_action_info(). -+ */ -+function feedback_action_info() { -+ return array( -+ 'feedback_process_action' => array( -+ 'label' => t('Process entry'), -+ 'type' => 'feedback', -+ 'configurable' => FALSE, -+ 'behavior' => array('changes_property'), -+ 'triggers' => array('feedback_insert', 'feedback_update'), -+ ), -+ 'feedback_open_action' => array( -+ 'label' => t('Open entry'), -+ 'type' => 'feedback', -+ 'configurable' => FALSE, -+ 'behavior' => array('changes_property'), -+ 'triggers' => array('feedback_insert', 'feedback_update'), -+ ), -+ 'feedback_delete_action' => array( -+ 'label' => t('Delete entry'), -+ 'type' => 'feedback', -+ 'configurable' => FALSE, -+ 'triggers' => array('feedback_insert', 'feedback_update'), -+ ), -+ 'feedback_send_email_action' => array( -+ 'label' => t('Send e-mail of feedback'), -+ 'type' => 'feedback', -+ 'configurable' => TRUE, -+ 'triggers' => array('feedback_insert', 'feedback_update'), -+ ), -+ ); -+} -+ -+/** -+* Implements hook_trigger_info(). -+*/ -+function feedback_trigger_info() { -+ return array( -+ 'feedback' => array( -+ 'feedback_insert' => array( -+ 'label' => t('New feedback is added.'), -+ ), -+ 'feedback_update' => array( -+ 'label' => t('Feedback is marked processed or open.'), -+ ), -+ ), -+ ); -+} -+ -+/** -+ * Implements hook_feedback_insert(). -+ */ -+function feedback_feedback_insert($entry) { -+ $aids = trigger_get_assigned_actions('feedback_insert'); -+ if (!$aids) { -+ return; -+ } -+ -+ $context = array( -+ 'group' => 'feedback', -+ 'hook' => 'feedback_insert', -+ ); -+ -+ foreach ($aids as $aid => $info) { -+ actions_do($aid, $entry, $context); -+ } -+} -+ -+/** -+ * Implements hook_feedback_update(). -+ */ -+function feedback_feedback_update($entry) { -+ $aids = trigger_get_assigned_actions('feedback_update'); -+ if (!$aids) { -+ return; -+ } -+ -+ $context = array( -+ 'group' => 'feedback', -+ 'hook' => 'feedback_update', -+ ); -+ -+ foreach ($aids as $aid => $info) { -+ actions_do($aid, $entry, $context); -+ } -+} -+ -+/** -+ * Sets the status of an entry to processed. -+ * -+ * @ingroup actions -+ */ -+function feedback_process_action($entry, $context) { -+ $entry->status = FEEDBACK_PROCESSED; -+ drupal_write_record('feedback', $entry, 'fid'); -+} -+ -+/** -+ * Sets the status of an entry to open. -+ * -+ * @ingroup actions -+ */ -+function feedback_open_action($entry, $context) { -+ $entry->status = FEEDBACK_OPEN; -+ drupal_write_record('feedback', $entry, 'fid'); -+} -+ -+/** -+ * Deletes a feedback entry. -+ * -+ * @ingroup actions -+ */ -+function feedback_delete_action($entry, $context) { -+ feedback_delete($entry->fid); -+} -+ -+/** -+ * Return a form definition so the Feedback send email action can be configured. -+ * -+ * @param $context -+ * Default values (if we are editing an existing action instance). -+ * @return -+ * Form definition. -+ */ -+function feedback_send_email_action_form($context = array()) { -+ // Set default values for form. -+ $context += array( -+ 'recipients' => '', -+ 'subject' => '', -+ 'message' => '', -+ ); -+ -+ $form['recipients'] = array( -+ '#type' => 'textarea', -+ '#title' => t('Recipients'), -+ '#default_value' => $context['recipients'], -+ '#description' => t("Example: 'webmaster@example.com' or 'dev@example.com,support@example.com'. To specify multiple recipients, separate each e-mail address with a comma."), -+ '#required' => TRUE, -+ ); -+ $form['subject'] = array( -+ '#type' => 'textfield', -+ '#title' => t('Subject'), -+ '#default_value' => $context['subject'], -+ '#maxlength' => '254', -+ '#description' => t('The subject of the message.'), -+ '#required' => TRUE, -+ ); -+ $form['message'] = array( -+ '#type' => 'textarea', -+ '#title' => t('Message'), -+ '#default_value' => $context['message'], -+ '#cols' => '80', -+ '#rows' => '20', -+ '#description' => t('The message that should be sent. You may include the following variables: !uid, !username, !usermail, !useragent (of the user who gave the feedback), !site_name, !status, !message, !url, !date.'), -+ '#required' => TRUE, -+ ); -+ return $form; -+} -+ -+/** -+ * Validate the send e-mail action form submission. -+ */ -+function feedback_send_email_action_validate($form, &$form_state) { -+ if (empty($form_state['values']['recipients'])) { -+ form_set_error('recipients', t('You must enter one or more recipients.')); -+ } -+ else { -+ $recipients = explode(',', $form_state['values']['recipients']); -+ foreach ($recipients as $recipient) { -+ if (!valid_email_address(trim($recipient))) { -+ form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient))); -+ } -+ } -+ } -+} -+ -+/** -+ * Process the send e-mail action form submission. -+ */ -+function feedback_send_email_action_submit($form, $form_state) { -+ // Process the HTML form to store configuration. The keyed array that -+ // we return will be serialized to the database. -+ $params = array( -+ 'recipients' => $form_state['values']['recipients'], -+ 'subject' => $form_state['values']['subject'], -+ 'message' => $form_state['values']['message'], -+ ); -+ return $params; -+} -+ -+/** -+ * Implements the feedback send e-mail action. -+ */ -+function feedback_send_email_action($entry, $context) { -+ $account = user_load($entry->uid); -+ $from = variable_get('site_name', 'Drupal') . ' <' . variable_get('site_mail', '') . '>'; -+ $params = array('entry' => $entry, 'account' => $account, 'context' => $context); -+ // Send the e-mail to the recipients using the site default language. -+ drupal_mail('feedback', 'send_email_action', $context['recipients'], language_default(), $params, $from); -+ watchdog('feedback', 'Feedback information sent to %recipients', array('%recipients' => $context['recipients'])); -+} -+ -+/** -+ * Implements hook_mail(). -+ */ -+function feedback_mail($key, &$message, $params) { -+ $language = $message['language']; -+ $entry = $params['entry']; -+ $account = $params['account']; -+ $context = $params['context']; -+ $variables = array( -+ '!site_name' => variable_get('site_name', 'Drupal'), -+ '!uid' => $account->uid, -+ '!username' => $account->name ? $account->name : t('Anonymous'), -+ '!usermail' => $account->mail ? $account->mail : t('unknown'), -+ '!status' => $entry->status ? t('Processed') : t('Open'), -+ '!message' => $entry->message, -+ '!url' => url($entry->location, array('absolute' => TRUE, 'language' => $language)), -+ '!useragent' => $entry->useragent, -+ '!date' => format_date($entry->timestamp, 'small', '', NULL, $language->language), -+ ); -+ $subject = strtr($context['subject'], $variables); -+ $body = strtr($context['message'], $variables); -+ $message['subject'] .= str_replace(array("\r", "\n"), '', $subject); -+ $message['body'][] = drupal_html_to_text($body); -+} -+ -+ -+/** - * Implements hook_mollom_form_list(). - */ - function feedback_mollom_form_list() { -diff --git a/tests/feedback.test b/tests/feedback.test -index 4d4244c..09ce922 100644 ---- a/tests/feedback.test -+++ b/tests/feedback.test -@@ -20,8 +20,7 @@ class FeedbackTestCase extends DrupalWebTestCase { - } - - function setUp() { -- // @todo Remove soft-dependency on Block. -- parent::setUp(array('block', 'feedback')); -+ parent::setUp(array('feedback', 'trigger')); - - $this->admin_user = $this->drupalCreateUser(array('access feedback form', 'view feedback messages', 'administer feedback')); - $this->web_user = $this->drupalCreateUser(array('access feedback form')); -@@ -49,7 +48,7 @@ class FeedbackTestCase extends DrupalWebTestCase { - $edit = array( - 'feedback-messages[0][1]' => TRUE, - ); -- $this->drupalPost(NULL, $edit, t('Submit')); -+ $this->drupalPost(NULL, $edit, t('Update')); - $this->assertFieldByName('feedback-messages[1][1]', 1, t('Processed message found.')); - } - -@@ -89,4 +88,72 @@ class FeedbackTestCase extends DrupalWebTestCase { - $this->assertNoLinkByHref('admin/reports/feedback/1/delete'); - $this->assertNoRaw(check_plain($message), t('Message not found.')); - } --} -+ -+ /** -+ * Test the feedback triggers and actions. -+ */ -+ function testFeedbackEmailAction() { -+ $test_user = $this->drupalCreateUser(array('administer actions', 'administer feedback', 'access feedback form')); -+ $this->drupalLogin($test_user); -+ $this->assignFeedbackEmailAction('feedback_insert', $test_user->mail); -+ -+ // Insert a feedback entry. -+ $message = $this->randomString(); -+ $edit = array( -+ 'message' => $message, -+ ); -+ $this->drupalPost('node', $edit, t('Send feedback')); -+ $this->assertFeedbackEmailTokenReplacement($test_user->mail, $message); -+ -+ $this->assignFeedbackEmailAction('feedback_update', $test_user->mail); -+ -+ // Update a feedback entry. -+ $fid = db_query("SELECT fid FROM {feedback} LIMIT 0,1")->fetchField(); -+ $entry = feedback_load($fid); -+ feedback_save($entry); -+ $this->assertFeedbackEmailTokenReplacement($test_user->mail, $entry->message); -+ } -+ -+ /** -+ * Assigns a system_send_email_action to the passed-in trigger. -+ * -+ * @param $trigger -+ * For example, 'user_login' -+ */ -+ function assignFeedbackEmailAction($trigger, $mail) { -+ $form_name = "trigger_{$trigger}_assign_form"; -+ $form_html_id = strtr($form_name, '_', '-'); -+ -+ $edit = array( -+ 'actions_label' => $trigger . "_feedback_send_email_action", -+ 'recipients' => $mail, -+ 'subject' => $this->randomName(), -+ 'message' => '!message', -+ ); -+ -+ $hash = drupal_hash_base64('feedback_send_email_action'); -+ $this->drupalPost("admin/config/system/actions/configure/$hash", $edit, t('Save')); -+ $this->assertText(t('The action has been successfully saved.')); -+ -+ // Now we have to find out the action ID of what we created. -+ $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback AND label = :label', array(':callback' => 'feedback_send_email_action', ':label' => $edit['actions_label']))->fetchField(); -+ -+ $edit = array('aid' => drupal_hash_base64($aid)); -+ $this->drupalPost('admin/structure/trigger/feedback', $edit, t('Assign'), array(), array(), $form_html_id); -+ } -+ -+ -+ /** -+ * Asserts correct token replacement for the given trigger and account. -+ * -+ * @param $account -+ * The user account which triggered the action. -+ * @param $email_depth -+ * Number of emails to scan, starting with most recent. -+ */ -+ function assertFeedbackEmailTokenReplacement($mail, $message, $email_depth = 1) { -+ $this->verboseEmail($email_depth); -+ $this->assertMailString('body', $message, $email_depth); -+ $this->assertMail('to', $mail, t('Mail sent to correct destination')); -+ } -+} -\ No newline at end of file diff --git a/sites/all/modules/contrib/users/feedback/feedback.admin.inc b/sites/all/modules/contrib/users/feedback/feedback.admin.inc index f6424ce4..425df522 100755 --- a/sites/all/modules/contrib/users/feedback/feedback.admin.inc +++ b/sites/all/modules/contrib/users/feedback/feedback.admin.inc @@ -56,10 +56,20 @@ function feedback_admin_view_form($form, &$form_state) { '#return_value' => FEEDBACK_PROCESSED, '#default_value' => FALSE, ); - $form['feedback-messages'][$status][$fid]['location'] = array('#markup' => l(truncate_utf8($entry->location, 32, FALSE, TRUE), $entry->url)); - $form['feedback-messages'][$status][$fid]['date'] = array('#markup' => format_date($entry->timestamp, 'small')); - $form['feedback-messages'][$status][$fid]['user'] = array('#markup' => check_plain(format_username($entry))); - $form['feedback-messages'][$status][$fid]['message'] = feedback_build_content($entry, 'teaser'); + $form['feedback-messages'][$status][$fid]['location'] = array( + '#markup' => l(truncate_utf8($entry->location, 32, FALSE, TRUE), $entry->url), + ); + $form['feedback-messages'][$status][$fid]['date'] = array( + '#markup' => format_date($entry->timestamp, 'small'), + ); + $form['feedback-messages'][$status][$fid]['user'] = array( + '#markup' => check_plain(format_username($entry)), + ); + + feedback_build_content($entry, 'teaser'); + $form['feedback-messages'][$status][$fid]['message'] = $entry->content; + unset($entry->content); + $form['feedback-messages'][$status][$fid]['operations'] = array( '#theme' => 'links', '#links' => array( diff --git a/sites/all/modules/contrib/users/feedback/feedback.css b/sites/all/modules/contrib/users/feedback/feedback.css index 2185691d..93bb5a0c 100755 --- a/sites/all/modules/contrib/users/feedback/feedback.css +++ b/sites/all/modules/contrib/users/feedback/feedback.css @@ -54,6 +54,18 @@ font-size: 10px; line-height: normal; } +#block-feedback-form input[type="text"] { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + max-width: 100%; +} +#block-feedback-form .form-actions { + margin: 1em 0 0; + padding: 0; +} + +/* Ajax interaction styles */ #block-feedback-form .feedback-message { height: 10ex; } @@ -66,7 +78,14 @@ /** * Styles for existing feedback messages. */ -#block-feedback-form .feedback-submitted { - margin-top: 0.2em; - font-size: 10px; +#block-feedback-form .feedback-entry { + font-size: 80%; +} +.feedback-entry .feedback-submitted { + margin-top: 0.2em; + font-size: 90%; +} +.feedback-entry .browserinfo { + color: #666; + font-size: 80%; } diff --git a/sites/all/modules/contrib/users/feedback/feedback.info b/sites/all/modules/contrib/users/feedback/feedback.info index 2edfa5b3..8891affd 100755 --- a/sites/all/modules/contrib/users/feedback/feedback.info +++ b/sites/all/modules/contrib/users/feedback/feedback.info @@ -9,9 +9,9 @@ files[] = views/feedback_handler_field_feedback_link_delete.inc files[] = views/feedback_handler_field_feedback_link_edit.inc files[] = tests/feedback.test -; Information added by drupal.org packaging script on 2013-03-04 +; Information added by Drupal.org packaging script on 2015-02-11 version = "7.x-2.x-dev" core = "7.x" project = "feedback" -datestamp = "1362358407" +datestamp = "1423690684" diff --git a/sites/all/modules/contrib/users/feedback/feedback.module b/sites/all/modules/contrib/users/feedback/feedback.module index fef1edab..1572020d 100644 --- a/sites/all/modules/contrib/users/feedback/feedback.module +++ b/sites/all/modules/contrib/users/feedback/feedback.module @@ -80,6 +80,51 @@ function feedback_entity_info() { return $return; } +/** + * Implements hook_entity_property_info(). + */ +function feedback_entity_property_info() { + $info = array(); + $properties = &$info['feedback']['properties']; + + $properties['fid'] = array( + 'label' => t('Feedback ID'), + 'type' => 'integer', + 'description' => t('The Feedback ID'), + 'schema field' => 'fid', + ); + $properties['status'] = array( + 'label' => t("Status"), + 'type' => 'integer', + 'description' => t("0 for new, 1 for processed"), + 'schema field' => 'status', + ); + $properties['author'] = array( + 'label' => t("Author"), + 'type' => 'user', + 'description' => t("The author of the feedback."), + 'setter callback' => 'entity_property_verbatim_set', + 'required' => TRUE, + 'schema field' => 'uid', + ); + $properties['message'] = array( + 'label' => t("Title"), + 'description' => t("The feedback message."), + 'setter callback' => 'entity_property_verbatim_set', + 'schema field' => 'message', + 'required' => TRUE, + ); + $properties['timestamp'] = array( + 'label' => t("Date created"), + 'type' => 'date', + 'schema field' => 'timestamp', + 'description' => t("The date the feedback was created."), + ); + + return $info; +} + + /** * Implements hook_field_extra_fields(). */ @@ -287,11 +332,22 @@ function feedback_form($form, &$form_state) { '#suffix' => '', ); foreach ($feedbacks as $fid => $feedback) { - $form['messages'][$fid]['#feedback'] = $feedback; - $form['messages'][$fid]['submitted'] = array('#markup' => t('@feedback-author !feedback-date:', array('@feedback-author' => format_username($feedback), '!feedback-date' => format_date($feedback->timestamp, 'small')))); + $form['messages'][$fid] = array( + '#type' => 'container', + '#attributes' => array('class' => array('feedback-entry')), + '#feedback' => $feedback, + ); + $form['messages'][$fid]['submitted'] = array( + '#markup' => t('@feedback-author !feedback-date:', array( + '@feedback-author' => format_username($feedback), + '!feedback-date' => format_date($feedback->timestamp, 'small'), + )), + ); $form['messages'][$fid]['submitted']['#prefix'] = '
'; $form['messages'][$fid]['submitted']['#suffix'] = '
'; - $form['messages'][$fid]['body'] = feedback_build_content($feedback, 'widget'); + feedback_build_content($feedback, 'widget'); + $form['messages'][$fid]['body'] = $feedback->content; + unset($feedback->content); $form['messages'][$fid]['body']['#prefix'] = '
'; $form['messages'][$fid]['body']['#suffix'] = '
'; } @@ -549,235 +605,6 @@ function feedback_user_delete($account) { feedback_delete_multiple($fids); } -/** - * Implements hook_action_info(). - */ -function feedback_action_info() { - return array( - 'feedback_process_action' => array( - 'label' => t('Process entry'), - 'type' => 'feedback', - 'configurable' => FALSE, - 'behavior' => array('changes_property'), - 'triggers' => array('feedback_insert', 'feedback_update'), - ), - 'feedback_open_action' => array( - 'label' => t('Open entry'), - 'type' => 'feedback', - 'configurable' => FALSE, - 'behavior' => array('changes_property'), - 'triggers' => array('feedback_insert', 'feedback_update'), - ), - 'feedback_delete_action' => array( - 'label' => t('Delete entry'), - 'type' => 'feedback', - 'configurable' => FALSE, - 'triggers' => array('feedback_insert', 'feedback_update'), - ), - 'feedback_send_email_action' => array( - 'label' => t('Send e-mail of feedback'), - 'type' => 'feedback', - 'configurable' => TRUE, - 'triggers' => array('feedback_insert', 'feedback_update'), - ), - ); -} - -/** -* Implements hook_trigger_info(). -*/ -function feedback_trigger_info() { - return array( - 'feedback' => array( - 'feedback_insert' => array( - 'label' => t('New feedback is added.'), - ), - 'feedback_update' => array( - 'label' => t('Feedback is marked processed or open.'), - ), - ), - ); -} - -/** - * Implements hook_feedback_insert(). - */ -function feedback_feedback_insert($entry) { - $aids = trigger_get_assigned_actions('feedback_insert'); - if (!$aids) { - return; - } - - $context = array( - 'group' => 'feedback', - 'hook' => 'feedback_insert', - ); - - foreach ($aids as $aid => $info) { - actions_do($aid, $entry, $context); - } -} - -/** - * Implements hook_feedback_update(). - */ -function feedback_feedback_update($entry) { - $aids = trigger_get_assigned_actions('feedback_update'); - if (!$aids) { - return; - } - - $context = array( - 'group' => 'feedback', - 'hook' => 'feedback_update', - ); - - foreach ($aids as $aid => $info) { - actions_do($aid, $entry, $context); - } -} - -/** - * Sets the status of an entry to processed. - * - * @ingroup actions - */ -function feedback_process_action($entry, $context) { - $entry->status = FEEDBACK_PROCESSED; - drupal_write_record('feedback', $entry, 'fid'); -} - -/** - * Sets the status of an entry to open. - * - * @ingroup actions - */ -function feedback_open_action($entry, $context) { - $entry->status = FEEDBACK_OPEN; - drupal_write_record('feedback', $entry, 'fid'); -} - -/** - * Deletes a feedback entry. - * - * @ingroup actions - */ -function feedback_delete_action($entry, $context) { - feedback_delete($entry->fid); -} - -/** - * Return a form definition so the Feedback send email action can be configured. - * - * @param $context - * Default values (if we are editing an existing action instance). - * @return - * Form definition. - */ -function feedback_send_email_action_form($context = array()) { - // Set default values for form. - $context += array( - 'recipients' => '', - 'subject' => '', - 'message' => '', - ); - - $form['recipients'] = array( - '#type' => 'textarea', - '#title' => t('Recipients'), - '#default_value' => $context['recipients'], - '#description' => t("Example: 'webmaster@example.com' or 'dev@example.com,support@example.com'. To specify multiple recipients, separate each e-mail address with a comma."), - '#required' => TRUE, - ); - $form['subject'] = array( - '#type' => 'textfield', - '#title' => t('Subject'), - '#default_value' => $context['subject'], - '#maxlength' => '254', - '#description' => t('The subject of the message.'), - '#required' => TRUE, - ); - $form['message'] = array( - '#type' => 'textarea', - '#title' => t('Message'), - '#default_value' => $context['message'], - '#cols' => '80', - '#rows' => '20', - '#description' => t('The message that should be sent. You may include the following variables: !uid, !username, !usermail, !useragent (of the user who gave the feedback), !site_name, !status, !message, !url, !date.'), - '#required' => TRUE, - ); - return $form; -} - -/** - * Validate the send e-mail action form submission. - */ -function feedback_send_email_action_validate($form, &$form_state) { - if (empty($form_state['values']['recipients'])) { - form_set_error('recipients', t('You must enter one or more recipients.')); - } - else { - $recipients = explode(',', $form_state['values']['recipients']); - foreach ($recipients as $recipient) { - if (!valid_email_address(trim($recipient))) { - form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient))); - } - } - } -} - -/** - * Process the send e-mail action form submission. - */ -function feedback_send_email_action_submit($form, $form_state) { - // Process the HTML form to store configuration. The keyed array that - // we return will be serialized to the database. - $params = array( - 'recipients' => $form_state['values']['recipients'], - 'subject' => $form_state['values']['subject'], - 'message' => $form_state['values']['message'], - ); - return $params; -} - -/** - * Implements the feedback send e-mail action. - */ -function feedback_send_email_action($entry, $context) { - $account = user_load($entry->uid); - $from = variable_get('site_name', 'Drupal') . ' <' . variable_get('site_mail', '') . '>'; - $params = array('entry' => $entry, 'account' => $account, 'context' => $context); - // Send the e-mail to the recipients using the site default language. - drupal_mail('feedback', 'send_email_action', $context['recipients'], language_default(), $params, $from); - watchdog('feedback', 'Feedback information sent to %recipients', array('%recipients' => $context['recipients'])); -} - -/** - * Implements hook_mail(). - */ -function feedback_mail($key, &$message, $params) { - $language = $message['language']; - $entry = $params['entry']; - $account = $params['account']; - $context = $params['context']; - $variables = array( - '!site_name' => variable_get('site_name', 'Drupal'), - '!uid' => $account->uid, - '!username' => $account->name ? $account->name : t('Anonymous'), - '!usermail' => $account->mail ? $account->mail : t('unknown'), - '!status' => $entry->status ? t('Processed') : t('Open'), - '!message' => $entry->message, - '!url' => url($entry->location, array('absolute' => TRUE, 'language' => $language)), - '!useragent' => $entry->useragent, - '!date' => format_date($entry->timestamp, 'small', '', NULL, $language->language), - ); - $subject = strtr($context['subject'], $variables); - $body = strtr($context['message'], $variables); - $message['subject'] .= str_replace(array("\r", "\n"), '', $subject); - $message['body'][] = drupal_html_to_text($body); -} - - /** * Implements hook_mollom_form_list(). */ @@ -820,3 +647,23 @@ function feedback_views_api() { 'path' => drupal_get_path('module', 'feedback') . '/views', ); } + +/** + * Implements hook_feedback_insert(). + */ +function feedback_feedback_insert($entry) { + // Trigger rule if Rules is enabled + if (module_exists('rules')) { + rules_invoke_event('feedback_insert', $entry); + } +} + +/** + * Implements hook_feedback_update(). + */ +function feedback_feedback_update($entry) { + // Trigger rule if Rules is enabled + if (module_exists('rules')) { + rules_invoke_event('feedback_update', $entry); + } +} diff --git a/sites/all/modules/contrib/users/feedback/feedback.module.orig b/sites/all/modules/contrib/users/feedback/feedback.module.orig deleted file mode 100755 index a4acfc09..00000000 --- a/sites/all/modules/contrib/users/feedback/feedback.module.orig +++ /dev/null @@ -1,593 +0,0 @@ - array( - 'render element' => 'form', - ), - 'feedback_entry' => array( - 'render element' => 'elements', - 'template' => 'feedback-entry', - 'file' => 'feedback.admin.inc', - ), - 'feedback_form_display' => array( - 'template' => 'feedback-form-display', - 'variables' => array('title' => NULL, 'content' => NULL), - ), - ); -} - -/** - * Implements hook_entity_info(). - */ -function feedback_entity_info() { - $return = array( - 'feedback' => array( - 'label' => t('Feedback'), - 'controller class' => 'FeedbackController', - 'base table' => 'feedback', - 'uri callback' => 'feedback_uri', - 'fieldable' => TRUE, - 'entity keys' => array( - 'id' => 'fid', - ), - 'bundles' => array( - 'feedback' => array( - 'label' => t('Feedback'), - 'admin' => array( - 'path' => 'admin/config/user-interface/feedback', - 'access arguments' => array('administer feedback'), - ), - ), - ), - 'view modes' => array( - 'full' => array( - 'label' => t('Full feedback entry'), - 'custom settings' => FALSE, - ), - 'teaser' => array( - 'label' => t('Teaser'), - 'custom settings' => FALSE, - ), - 'widget' => array( - 'label' => t('Widget'), - 'custom settings' => FALSE, - ), - ), - // Disable Metatags (metatag) module's entity form additions. - 'metatags' => FALSE, - ), - ); - - return $return; -} - -/** - * Implements hook_field_extra_fields(). - */ -function feedback_field_extra_fields() { - $extras['feedback']['feedback']['form']['help'] = array( - 'label' => t('Help'), - 'description' => t('Feedback submission guidelines'), - 'weight' => -10, - ); - $extras['feedback']['feedback']['form']['messages'] = array( - 'label' => t('Entries'), - 'description' => t('Existing feedback entries for the current page'), - 'weight' => -5, - ); - $extras['feedback']['feedback']['form']['message'] = array( - 'label' => t('Message'), - 'description' => t('Feedback message form text field'), - 'weight' => 0, - ); - - $extras['feedback']['feedback']['display']['location'] = array( - 'label' => t('Location'), - 'description' => t('The URL of the page the message was submitted on'), - 'weight' => -15, - ); - $extras['feedback']['feedback']['display']['date'] = array( - 'label' => t('Date'), - 'description' => t('The submission date of the message'), - 'weight' => -10, - ); - $extras['feedback']['feedback']['display']['user'] = array( - 'label' => t('User'), - 'description' => t('The name of the user who submitted the message'), - 'weight' => -5, - ); - $extras['feedback']['feedback']['display']['message'] = array( - 'label' => t('Message'), - 'description' => t('The main feedback message'), - 'weight' => 0, - ); - return $extras; -} - -/** - * Entity uri callback. - */ -function feedback_uri($entry) { - return array( - 'path' => 'admin/reports/feedback/' . $entry->fid, - ); -} - -/** - * Implements hook_permission(). - */ -function feedback_permission() { - return array( - 'access feedback form' => array( - 'title' => t('Access feedback form'), - 'description' => t('Submit feedback messages.'), - ), - 'view feedback messages' => array( - 'title' => t('View feedback messages'), - 'description' => t('View, process, and delete submitted feedback messages.'), - ), - 'administer feedback' => array( - 'title' => t('Administer feedback settings'), - ), - ); -} - -/** - * Implements hook_menu(). - */ -function feedback_menu() { - $items['admin/reports/feedback'] = array( - 'title' => 'Feedback messages', - 'description' => 'View feedback messages.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('feedback_admin_view_form'), - 'access arguments' => array('view feedback messages'), - 'file' => 'feedback.admin.inc', - ); - $items['admin/reports/feedback/%feedback'] = array( - 'title' => 'Feedback entry', - 'page callback' => 'feedback_view', - 'page arguments' => array(3), - 'access arguments' => array('view feedback messages'), - 'file' => 'feedback.admin.inc', - ); - $items['admin/reports/feedback/%feedback/view'] = array( - 'title' => 'View', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - $items['admin/reports/feedback/%feedback/edit'] = array( - 'title' => 'Edit', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('feedback_entry_form', 3), - 'access arguments' => array('view feedback messages'), - 'type' => MENU_LOCAL_TASK, - 'file' => 'feedback.admin.inc', - ); - $items['admin/reports/feedback/%feedback/delete'] = array( - 'title' => 'Delete feedback entry', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('feedback_delete_confirm', 3), - 'access arguments' => array('view feedback messages'), - 'type' => MENU_CALLBACK, - 'file' => 'feedback.admin.inc', - ); - $items['admin/config/user-interface/feedback'] = array( - 'title' => 'Feedback', - 'description' => 'Administer feedback settings.', - 'page callback' => 'drupal_get_form', - 'page arguments' => array('feedback_admin_settings_form'), - 'access arguments' => array('administer feedback'), - 'file' => 'feedback.admin.inc', - ); - $items['admin/config/user-interface/feedback/settings'] = array( - 'title' => 'Settings', - 'type' => MENU_DEFAULT_LOCAL_TASK, - 'weight' => -10, - ); - - return $items; -} - -/** - * Implements hook_page_build(). - */ -function feedback_page_build(&$page) { - if (user_access('access feedback form') && !feedback_match_path(variable_get('feedback_excluded_paths', 'admin/reports/feedback'))) { - $page['page_bottom']['feedback'] = array( - '#theme' => 'feedback_form_display', - '#title' => t('Feedback'), - '#content' => drupal_get_form('feedback_form'), - ); - $path = drupal_get_path('module', 'feedback'); - $page['page_bottom']['feedback']['#attached']['css'][] = $path . '/feedback.css'; - $page['page_bottom']['feedback']['#attached']['js'][] = $path . '/feedback.js'; - } -} - -/** - * Check if the current path matches any pattern in a set of patterns. - * - * @param $patterns - * String containing a set of patterns separated by \n, \r or \r\n. - * - * @return - * Boolean value: TRUE if the current path or alias matches a pattern. - */ -function feedback_match_path($patterns) { - // Convert path to lowercase. This allows comparison of the same path - // with different case. Ex: /Page, /page, /PAGE. - $patterns = drupal_strtolower($patterns); - - // Convert the current path to lowercase. - $path = drupal_strtolower(drupal_get_path_alias($_GET['q'])); - - // Compare the lowercase internal and lowercase path alias (if any). - $page_match = drupal_match_path($path, $patterns); - if ($path != $_GET['q']) { - $page_match = $page_match || drupal_match_path($_GET['q'], $patterns); - } - - return $page_match; -} - -/** - * Form constructor for the feedback form. - * - * @see feedback_form_submit() - * @ingroup forms - */ -function feedback_form($form, &$form_state) { - $form['#attributes']['class'] = array('feedback-form'); - - // Store the path on which this form is displayed. - if (!isset($form_state['inline']['location'])) { - $form_state['inline']['location'] = $_GET['q']; - } - $form['location'] = array( - '#type' => 'value', - '#value' => $form_state['inline']['location'], - ); - - $form['help'] = array( - '#prefix' => '
', - '#markup' => t('If you experience a bug or would like to see an addition on the current page, feel free to leave us a message.'), - '#suffix' => '
', - ); - if (user_access('view feedback messages')) { - if (arg(0) != 'node') { - $feedbacks = feedback_load_multiple(array(), array('status' => FEEDBACK_OPEN, 'location_masked' => feedback_mask_path($_GET['q']))); - } - else { - $feedbacks = feedback_load_multiple(array(), array('status' => FEEDBACK_OPEN, 'location' => $_GET['q'])); - } - if ($feedbacks) { - form_load_include($form_state, 'inc', 'feedback', 'feedback.admin'); - $form['messages'] = array( - '#prefix' => '
', - '#suffix' => '
', - ); - foreach ($feedbacks as $fid => $feedback) { - $form['messages'][$fid]['#feedback'] = $feedback; - $form['messages'][$fid]['submitted'] = array('#markup' => t('@feedback-author !feedback-date:', array('@feedback-author' => format_username($feedback), '!feedback-date' => format_date($feedback->timestamp, 'small')))); - $form['messages'][$fid]['submitted']['#prefix'] = '
'; - $form['messages'][$fid]['submitted']['#suffix'] = '
'; - $form['messages'][$fid]['body'] = feedback_build_content($feedback, 'widget'); - $form['messages'][$fid]['body']['#prefix'] = '
'; - $form['messages'][$fid]['body']['#suffix'] = '
'; - } - } - } - $form['message'] = array( - '#type' => 'textarea', - '#attributes' => array('class' => array('feedback-message')), - '#cols' => 20, - '#title' => t('Message'), - '#required' => TRUE, - '#wysiwyg' => FALSE, - ); - - $entry = new stdClass(); - field_attach_form('feedback', $entry, $form, $form_state); - - $form['actions'] = array( - '#type' => 'actions', - // Without clearfix, the AJAX throbber wraps in an ugly way. - // @todo Patch #type actions in core? - '#attributes' => array('class' => array('clearfix')), - ); - $form['actions']['submit'] = array( - '#type' => 'submit', - '#value' => t('Send feedback'), - '#id' => 'feedback-submit', - '#ajax' => array( - 'wrapper' => 'feedback-form', - 'callback' => 'feedback_form_ajax_callback', - 'progress' => array( - 'type' => 'throbber', - 'message' => '', - ), - ), - ); - - return $form; -} - -/** - * Form submission handler for feedback_form(). - */ -function feedback_form_submit($form, &$form_state) { - $entry = new stdClass(); - entity_form_submit_build_entity('feedback', $entry, $form, $form_state); - $entry->message = $form_state['values']['message']; - $entry->location = $form_state['values']['location']; - feedback_save($entry); - - drupal_set_message(t('Thanks for your feedback!')); -} - -/** - * AJAX callback for feedback_form() submissions. - */ -function feedback_form_ajax_callback($form, &$form_state) { - // If there was a form validation error, re-render the entire form. - if (!$form_state['executed']) { - return $form; - } - - // Otherwise, return a fresh copy of the form, so the user may post additional - // feedback. - // Reset the static cache of drupal_html_id(). - // @see drupal_process_form() - // @see drupal_html_id() - $seen_ids = &drupal_static('drupal_html_id'); - $seen_ids = array(); - - // Prevent the form from being processed again. - // @see drupal_build_form() - list($form, $new_form_state) = ajax_get_form(); - $new_form_state['input'] = array(); - drupal_process_form($form['#form_id'], $form, $new_form_state); - - // Return AJAX commands in order to output the special success message. - // @see ajax_deliver() - $build = array('#type' => 'ajax'); - $html = drupal_render($form); - $build['#commands'][] = ajax_command_insert(NULL, $html); - - // A successful form submission normally means that there were no errors, so - // we only render status messages. - $messages = drupal_get_messages(); - $messages += array('status' => array()); - $messages = implode('
', $messages['status']); - $html = '
' . $messages . '
'; - $build['#commands'][] = ajax_command_append('#block-feedback-form', $html); - return $build; -} - -/** - * Loads a feedback entry from the database. - * - * @param $fid - * Integer specifying the feedback ID to load. - * - * @return - * A loaded feedback entry object upon successful load, or FALSE if the entry - * cannot be loaded. - * - * @see feedback_load_multiple() - */ -function feedback_load($fid) { - $entries = feedback_load_multiple(array($fid)); - return (isset($entries[$fid]) ? $entries[$fid] : FALSE); -} - -/** - * Loads feedback entries from the database. - * - * @param $fids - * An array of feedback entry IDs. - * @param $conditions - * An associative array of conditions on the {feedback} table, where the keys - * are the database fields and the values are the values those fields - * must have. - * - * @return - * An array of feedback entry objects indexed by fid. - * - * @see hook_feedback_load() - * @see feedback_load() - * @see entity_load() - * @see EntityFieldQuery - */ -function feedback_load_multiple($fids = array(), $conditions = array()) { - return entity_load('feedback', $fids, $conditions); -} - -/** - * Saves changes to a feedback entry or adds a new feedback entry. - * - * @param $entry - * The feedback entry object to modify or add. If $entry->fid is omitted, a - * new entry will be added. - * - * @see hook_feedback_insert() - * @see hook_feedback_update() - */ -function feedback_save($entry) { - global $user; - - // Load the stored entity, if any. - if (!empty($entry->fid) && !isset($entry->original)) { - $entry->original = entity_load_unchanged('feedback', $entry->fid); - } - - field_attach_presave('feedback', $entry); - - // Allow modules to alter the feedback entry before saving. - module_invoke_all('feedback_presave', $entry); - module_invoke_all('entity_presave', $entry, 'feedback'); - - if (empty($entry->fid)) { - $entry->message = trim($entry->message); - - $defaults = array( - 'uid' => $user->uid, - 'location_masked' => feedback_mask_path($entry->location), - 'url' => url($entry->location, array('absolute' => TRUE)), - 'timestamp' => REQUEST_TIME, - 'useragent' => $_SERVER['HTTP_USER_AGENT'], - ); - foreach ($defaults as $key => $default) { - if (!isset($entry->$key)) { - $entry->$key = $default; - } - } - - $status = drupal_write_record('feedback', $entry); - field_attach_insert('feedback', $entry); - module_invoke_all('feedback_insert', $entry); - module_invoke_all('entity_insert', $entry, 'feedback'); - } - else { - $status = drupal_write_record('feedback', $entry, 'fid'); - - field_attach_update('feedback', $entry); - module_invoke_all('feedback_update', $entry); - module_invoke_all('entity_update', $entry, 'feedback'); - } - unset($entry->original); - - return $status; -} - -/** - * Deletes a feedback entry. - * - * @param $fid - * A feedback entry ID. - */ -function feedback_delete($fid) { - feedback_delete_multiple(array($fid)); -} - -/** - * Deletes multiple feedback entries. - * - * @param $fids - * An array of feedback entry IDs. - */ -function feedback_delete_multiple($fids) { - if (!empty($fids)) { - $entries = feedback_load_multiple($fids); - foreach ($entries as $fid => $entry) { - field_attach_delete('feedback', $entry); - module_invoke_all('feedback_delete', $entry); - module_invoke_all('entity_delete', $entry, 'feedback'); - } - db_delete('feedback') - ->condition('fid', $fids, 'IN') - ->execute(); - } -} - -/** - * 'Mask' a path, i.e. replace all numeric arguments in a path with '%' placeholders. - * - * Please note that only numeric arguments with a preceding slash will be - * replaced. - * - * @param $path - * An internal Drupal path, f.e. 'user/123/edit'. - * @return - * A 'masked' path, for above example 'user/%/edit'. - * - * @todo Use the untranslated patch of menu_get_item() instead. - */ -function feedback_mask_path($path) { - return preg_replace('@/\d+@', '/%', $path); -} - -/** - * Implements hook_user_cancel(). - */ -function feedback_user_cancel($edit, $account, $method) { - switch ($method) { - case 'user_cancel_reassign': - db_update('feedback') - ->fields(array('uid' => 0)) - ->condition('uid', $account->uid) - ->execute(); - break; - } -} - -/** - * Implements hook_user_delete(). - */ -function feedback_user_delete($account) { - $fids = db_query('SELECT fid FROM {feedback} WHERE uid = :uid', array(':uid' => $account->uid))->fetchCol(); - feedback_delete_multiple($fids); -} - -/** - * Implements hook_mollom_form_list(). - */ -function feedback_mollom_form_list() { - $forms['feedback_form'] = array( - 'title' => t('Feedback form'), - 'entity' => 'feedback', - 'bundle' => 'feedback', - 'entity delete multiple callback' => 'feedback_delete_multiple', - 'delete form' => 'feedback_delete_confirm', - 'delete form file' => array( - 'name' => 'feedback.admin', - ), - 'report access' => array('view feedback messages'), - ); - return $forms; -} - -/** - * Implements hook_mollom_form_info(). - */ -function feedback_mollom_form_info($form_id) { - $form_info = array( - 'mode' => MOLLOM_MODE_ANALYSIS, - 'bypass access' => array('administer feedback'), - 'elements' => array( - 'message' => t('Message'), - ), - ); - mollom_form_info_add_fields($form_info, 'feedback', 'feedback'); - return $form_info; -} - -/** - * Implements hook_views_api(); - */ -function feedback_views_api() { - return array( - 'api' => 3.0, - 'path' => drupal_get_path('module', 'feedback') . '/views', - ); -} diff --git a/sites/all/modules/contrib/users/feedback/feedback.rules.inc b/sites/all/modules/contrib/users/feedback/feedback.rules.inc new file mode 100644 index 00000000..829a84ba --- /dev/null +++ b/sites/all/modules/contrib/users/feedback/feedback.rules.inc @@ -0,0 +1,55 @@ + t('Feedback'), + 'module' => 'feedback', + 'access callback' => 'feedback_rules_integration_access', + ); + return array( + 'feedback_insert' => $defaults + array( + 'label' => t('After saving new feedback'), + 'variables' => array( + 'feedback' => array('type' => 'feedback', 'label' => t('Feedback message')), + ), + ), + 'feedback_update' => $defaults + array( + 'label' => t('After saving existing feedback'), + 'variables' => array( + 'feedback' => array( + 'type' => 'feedback', + 'label' => t('Feedback message'), + ), + 'feedback_unchanged' => array( + 'type' => 'feedback', + 'label' => t('unchanged feedback entity'), + 'handler' => 'rules_events_entity_unchanged', + ), + ), + ), + ); +} + +/** + * Rules integration access callback. + */ +function feedback_rules_integration_access($type, $name) { + if ($type == 'event' || $type == 'condition') { + return entity_access('view', 'feedback'); + } +} + +/** + * @} + */ diff --git a/sites/all/modules/contrib/users/feedback/tests/feedback.test b/sites/all/modules/contrib/users/feedback/tests/feedback.test index 09ce922d..4d4244ca 100644 --- a/sites/all/modules/contrib/users/feedback/tests/feedback.test +++ b/sites/all/modules/contrib/users/feedback/tests/feedback.test @@ -20,7 +20,8 @@ class FeedbackTestCase extends DrupalWebTestCase { } function setUp() { - parent::setUp(array('feedback', 'trigger')); + // @todo Remove soft-dependency on Block. + parent::setUp(array('block', 'feedback')); $this->admin_user = $this->drupalCreateUser(array('access feedback form', 'view feedback messages', 'administer feedback')); $this->web_user = $this->drupalCreateUser(array('access feedback form')); @@ -48,7 +49,7 @@ class FeedbackTestCase extends DrupalWebTestCase { $edit = array( 'feedback-messages[0][1]' => TRUE, ); - $this->drupalPost(NULL, $edit, t('Update')); + $this->drupalPost(NULL, $edit, t('Submit')); $this->assertFieldByName('feedback-messages[1][1]', 1, t('Processed message found.')); } @@ -88,72 +89,4 @@ class FeedbackTestCase extends DrupalWebTestCase { $this->assertNoLinkByHref('admin/reports/feedback/1/delete'); $this->assertNoRaw(check_plain($message), t('Message not found.')); } - - /** - * Test the feedback triggers and actions. - */ - function testFeedbackEmailAction() { - $test_user = $this->drupalCreateUser(array('administer actions', 'administer feedback', 'access feedback form')); - $this->drupalLogin($test_user); - $this->assignFeedbackEmailAction('feedback_insert', $test_user->mail); - - // Insert a feedback entry. - $message = $this->randomString(); - $edit = array( - 'message' => $message, - ); - $this->drupalPost('node', $edit, t('Send feedback')); - $this->assertFeedbackEmailTokenReplacement($test_user->mail, $message); - - $this->assignFeedbackEmailAction('feedback_update', $test_user->mail); - - // Update a feedback entry. - $fid = db_query("SELECT fid FROM {feedback} LIMIT 0,1")->fetchField(); - $entry = feedback_load($fid); - feedback_save($entry); - $this->assertFeedbackEmailTokenReplacement($test_user->mail, $entry->message); - } - - /** - * Assigns a system_send_email_action to the passed-in trigger. - * - * @param $trigger - * For example, 'user_login' - */ - function assignFeedbackEmailAction($trigger, $mail) { - $form_name = "trigger_{$trigger}_assign_form"; - $form_html_id = strtr($form_name, '_', '-'); - - $edit = array( - 'actions_label' => $trigger . "_feedback_send_email_action", - 'recipients' => $mail, - 'subject' => $this->randomName(), - 'message' => '!message', - ); - - $hash = drupal_hash_base64('feedback_send_email_action'); - $this->drupalPost("admin/config/system/actions/configure/$hash", $edit, t('Save')); - $this->assertText(t('The action has been successfully saved.')); - - // Now we have to find out the action ID of what we created. - $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback AND label = :label', array(':callback' => 'feedback_send_email_action', ':label' => $edit['actions_label']))->fetchField(); - - $edit = array('aid' => drupal_hash_base64($aid)); - $this->drupalPost('admin/structure/trigger/feedback', $edit, t('Assign'), array(), array(), $form_html_id); - } - - - /** - * Asserts correct token replacement for the given trigger and account. - * - * @param $account - * The user account which triggered the action. - * @param $email_depth - * Number of emails to scan, starting with most recent. - */ - function assertFeedbackEmailTokenReplacement($mail, $message, $email_depth = 1) { - $this->verboseEmail($email_depth); - $this->assertMailString('body', $message, $email_depth); - $this->assertMail('to', $mail, t('Mail sent to correct destination')); - } -} \ No newline at end of file +}