123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305 |
- From 235e57d8e944175ddfd7907598ada29c5c2ebb3d Mon Sep 17 00:00:00 2001
- From: Bachir Soussi Chiadmi <bachir@g-u-i.net>
- 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 @@
- +<?php
- +
- +/**
- + * @file
- + * Allows site visitors and users to report issues about this site.
- + */
- +
- +/**
- + * Open state (unprocessed) for feedback entries.
- + */
- +define('FEEDBACK_OPEN', 0);
- +
- +/**
- + * Processed state for feedback entries.
- + */
- +define('FEEDBACK_PROCESSED', 1);
- +
- +/**
- + * Implements hook_theme().
- + */
- +function feedback_theme() {
- + return array(
- + 'feedback_admin_view_form' => 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' => '<div class="feedback-help">',
- + '#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' => '</div>',
- + );
- + 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' => '<div class="feedback-messages">',
- + '#suffix' => '</div>',
- + );
- + 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'] = '<div class="feedback-submitted">';
- + $form['messages'][$fid]['submitted']['#suffix'] = '</div>';
- + $form['messages'][$fid]['body'] = feedback_build_content($feedback, 'widget');
- + $form['messages'][$fid]['body']['#prefix'] = '<div class="feedback-body">';
- + $form['messages'][$fid]['body']['#suffix'] = '</div>';
- + }
- + }
- + }
- + $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('<br />', $messages['status']);
- + $html = '<div id="feedback-status-message">' . $messages . '</div>';
- + $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
|