feedback-353548-45.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. diff --git a/feedback.module b/feedback.module
  2. index 9763575..ef5b24a 100644
  3. --- a/feedback.module
  4. +++ b/feedback.module
  5. @@ -534,6 +534,235 @@ function feedback_user_delete($account) {
  6. }
  7. /**
  8. + * Implements hook_action_info().
  9. + */
  10. +function feedback_action_info() {
  11. + return array(
  12. + 'feedback_process_action' => array(
  13. + 'label' => t('Process entry'),
  14. + 'type' => 'feedback',
  15. + 'configurable' => FALSE,
  16. + 'behavior' => array('changes_property'),
  17. + 'triggers' => array('feedback_insert', 'feedback_update'),
  18. + ),
  19. + 'feedback_open_action' => array(
  20. + 'label' => t('Open entry'),
  21. + 'type' => 'feedback',
  22. + 'configurable' => FALSE,
  23. + 'behavior' => array('changes_property'),
  24. + 'triggers' => array('feedback_insert', 'feedback_update'),
  25. + ),
  26. + 'feedback_delete_action' => array(
  27. + 'label' => t('Delete entry'),
  28. + 'type' => 'feedback',
  29. + 'configurable' => FALSE,
  30. + 'triggers' => array('feedback_insert', 'feedback_update'),
  31. + ),
  32. + 'feedback_send_email_action' => array(
  33. + 'label' => t('Send e-mail of feedback'),
  34. + 'type' => 'feedback',
  35. + 'configurable' => TRUE,
  36. + 'triggers' => array('feedback_insert', 'feedback_update'),
  37. + ),
  38. + );
  39. +}
  40. +
  41. +/**
  42. +* Implements hook_trigger_info().
  43. +*/
  44. +function feedback_trigger_info() {
  45. + return array(
  46. + 'feedback' => array(
  47. + 'feedback_insert' => array(
  48. + 'label' => t('New feedback is added.'),
  49. + ),
  50. + 'feedback_update' => array(
  51. + 'label' => t('Feedback is marked processed or open.'),
  52. + ),
  53. + ),
  54. + );
  55. +}
  56. +
  57. +/**
  58. + * Implements hook_feedback_insert().
  59. + */
  60. +function feedback_feedback_insert($entry) {
  61. + $aids = trigger_get_assigned_actions('feedback_insert');
  62. + if (!$aids) {
  63. + return;
  64. + }
  65. +
  66. + $context = array(
  67. + 'group' => 'feedback',
  68. + 'hook' => 'feedback_insert',
  69. + );
  70. +
  71. + foreach ($aids as $aid => $info) {
  72. + actions_do($aid, $entry, $context);
  73. + }
  74. +}
  75. +
  76. +/**
  77. + * Implements hook_feedback_update().
  78. + */
  79. +function feedback_feedback_update($entry) {
  80. + $aids = trigger_get_assigned_actions('feedback_update');
  81. + if (!$aids) {
  82. + return;
  83. + }
  84. +
  85. + $context = array(
  86. + 'group' => 'feedback',
  87. + 'hook' => 'feedback_update',
  88. + );
  89. +
  90. + foreach ($aids as $aid => $info) {
  91. + actions_do($aid, $entry, $context);
  92. + }
  93. +}
  94. +
  95. +/**
  96. + * Sets the status of an entry to processed.
  97. + *
  98. + * @ingroup actions
  99. + */
  100. +function feedback_process_action($entry, $context) {
  101. + $entry->status = FEEDBACK_PROCESSED;
  102. + drupal_write_record('feedback', $entry, 'fid');
  103. +}
  104. +
  105. +/**
  106. + * Sets the status of an entry to open.
  107. + *
  108. + * @ingroup actions
  109. + */
  110. +function feedback_open_action($entry, $context) {
  111. + $entry->status = FEEDBACK_OPEN;
  112. + drupal_write_record('feedback', $entry, 'fid');
  113. +}
  114. +
  115. +/**
  116. + * Deletes a feedback entry.
  117. + *
  118. + * @ingroup actions
  119. + */
  120. +function feedback_delete_action($entry, $context) {
  121. + feedback_delete($entry->fid);
  122. +}
  123. +
  124. +/**
  125. + * Return a form definition so the Feedback send email action can be configured.
  126. + *
  127. + * @param $context
  128. + * Default values (if we are editing an existing action instance).
  129. + * @return
  130. + * Form definition.
  131. + */
  132. +function feedback_send_email_action_form($context = array()) {
  133. + // Set default values for form.
  134. + $context += array(
  135. + 'recipients' => '',
  136. + 'subject' => '',
  137. + 'message' => '',
  138. + );
  139. +
  140. + $form['recipients'] = array(
  141. + '#type' => 'textarea',
  142. + '#title' => t('Recipients'),
  143. + '#default_value' => $context['recipients'],
  144. + '#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."),
  145. + '#required' => TRUE,
  146. + );
  147. + $form['subject'] = array(
  148. + '#type' => 'textfield',
  149. + '#title' => t('Subject'),
  150. + '#default_value' => $context['subject'],
  151. + '#maxlength' => '254',
  152. + '#description' => t('The subject of the message.'),
  153. + '#required' => TRUE,
  154. + );
  155. + $form['message'] = array(
  156. + '#type' => 'textarea',
  157. + '#title' => t('Message'),
  158. + '#default_value' => $context['message'],
  159. + '#cols' => '80',
  160. + '#rows' => '20',
  161. + '#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.'),
  162. + '#required' => TRUE,
  163. + );
  164. + return $form;
  165. +}
  166. +
  167. +/**
  168. + * Validate the send e-mail action form submission.
  169. + */
  170. +function feedback_send_email_action_validate($form, &$form_state) {
  171. + if (empty($form_state['values']['recipients'])) {
  172. + form_set_error('recipients', t('You must enter one or more recipients.'));
  173. + }
  174. + else {
  175. + $recipients = explode(',', $form_state['values']['recipients']);
  176. + foreach ($recipients as $recipient) {
  177. + if (!valid_email_address(trim($recipient))) {
  178. + form_set_error('recipients', t('%recipient is an invalid e-mail address.', array('%recipient' => $recipient)));
  179. + }
  180. + }
  181. + }
  182. +}
  183. +
  184. +/**
  185. + * Process the send e-mail action form submission.
  186. + */
  187. +function feedback_send_email_action_submit($form, $form_state) {
  188. + // Process the HTML form to store configuration. The keyed array that
  189. + // we return will be serialized to the database.
  190. + $params = array(
  191. + 'recipients' => $form_state['values']['recipients'],
  192. + 'subject' => $form_state['values']['subject'],
  193. + 'message' => $form_state['values']['message'],
  194. + );
  195. + return $params;
  196. +}
  197. +
  198. +/**
  199. + * Implements the feedback send e-mail action.
  200. + */
  201. +function feedback_send_email_action($entry, $context) {
  202. + $account = user_load($entry->uid);
  203. + $from = variable_get('site_name', 'Drupal') . ' <' . variable_get('site_mail', '') . '>';
  204. + $params = array('entry' => $entry, 'account' => $account, 'context' => $context);
  205. + // Send the e-mail to the recipients using the site default language.
  206. + drupal_mail('feedback', 'send_email_action', $context['recipients'], language_default(), $params, $from);
  207. + watchdog('feedback', 'Feedback information sent to %recipients', array('%recipients' => $context['recipients']));
  208. +}
  209. +
  210. +/**
  211. + * Implements hook_mail().
  212. + */
  213. +function feedback_mail($key, &$message, $params) {
  214. + $language = $message['language'];
  215. + $entry = $params['entry'];
  216. + $account = $params['account'];
  217. + $context = $params['context'];
  218. + $variables = array(
  219. + '!site_name' => variable_get('site_name', 'Drupal'),
  220. + '!uid' => $account->uid,
  221. + '!username' => $account->name ? $account->name : t('Anonymous'),
  222. + '!usermail' => $account->mail ? $account->mail : t('unknown'),
  223. + '!status' => $entry->status ? t('Processed') : t('Open'),
  224. + '!message' => $entry->message,
  225. + '!url' => url($entry->location, array('absolute' => TRUE, 'language' => $language)),
  226. + '!useragent' => $entry->useragent,
  227. + '!date' => format_date($entry->timestamp, 'small', '', NULL, $language->language),
  228. + );
  229. + $subject = strtr($context['subject'], $variables);
  230. + $body = strtr($context['message'], $variables);
  231. + $message['subject'] .= str_replace(array("\r", "\n"), '', $subject);
  232. + $message['body'][] = drupal_html_to_text($body);
  233. +}
  234. +
  235. +
  236. +/**
  237. * Implements hook_mollom_form_list().
  238. */
  239. function feedback_mollom_form_list() {
  240. diff --git a/tests/feedback.test b/tests/feedback.test
  241. index 4d4244c..09ce922 100644
  242. --- a/tests/feedback.test
  243. +++ b/tests/feedback.test
  244. @@ -20,8 +20,7 @@ class FeedbackTestCase extends DrupalWebTestCase {
  245. }
  246. function setUp() {
  247. - // @todo Remove soft-dependency on Block.
  248. - parent::setUp(array('block', 'feedback'));
  249. + parent::setUp(array('feedback', 'trigger'));
  250. $this->admin_user = $this->drupalCreateUser(array('access feedback form', 'view feedback messages', 'administer feedback'));
  251. $this->web_user = $this->drupalCreateUser(array('access feedback form'));
  252. @@ -49,7 +48,7 @@ class FeedbackTestCase extends DrupalWebTestCase {
  253. $edit = array(
  254. 'feedback-messages[0][1]' => TRUE,
  255. );
  256. - $this->drupalPost(NULL, $edit, t('Submit'));
  257. + $this->drupalPost(NULL, $edit, t('Update'));
  258. $this->assertFieldByName('feedback-messages[1][1]', 1, t('Processed message found.'));
  259. }
  260. @@ -89,4 +88,72 @@ class FeedbackTestCase extends DrupalWebTestCase {
  261. $this->assertNoLinkByHref('admin/reports/feedback/1/delete');
  262. $this->assertNoRaw(check_plain($message), t('Message not found.'));
  263. }
  264. -}
  265. +
  266. + /**
  267. + * Test the feedback triggers and actions.
  268. + */
  269. + function testFeedbackEmailAction() {
  270. + $test_user = $this->drupalCreateUser(array('administer actions', 'administer feedback', 'access feedback form'));
  271. + $this->drupalLogin($test_user);
  272. + $this->assignFeedbackEmailAction('feedback_insert', $test_user->mail);
  273. +
  274. + // Insert a feedback entry.
  275. + $message = $this->randomString();
  276. + $edit = array(
  277. + 'message' => $message,
  278. + );
  279. + $this->drupalPost('node', $edit, t('Send feedback'));
  280. + $this->assertFeedbackEmailTokenReplacement($test_user->mail, $message);
  281. +
  282. + $this->assignFeedbackEmailAction('feedback_update', $test_user->mail);
  283. +
  284. + // Update a feedback entry.
  285. + $fid = db_query("SELECT fid FROM {feedback} LIMIT 0,1")->fetchField();
  286. + $entry = feedback_load($fid);
  287. + feedback_save($entry);
  288. + $this->assertFeedbackEmailTokenReplacement($test_user->mail, $entry->message);
  289. + }
  290. +
  291. + /**
  292. + * Assigns a system_send_email_action to the passed-in trigger.
  293. + *
  294. + * @param $trigger
  295. + * For example, 'user_login'
  296. + */
  297. + function assignFeedbackEmailAction($trigger, $mail) {
  298. + $form_name = "trigger_{$trigger}_assign_form";
  299. + $form_html_id = strtr($form_name, '_', '-');
  300. +
  301. + $edit = array(
  302. + 'actions_label' => $trigger . "_feedback_send_email_action",
  303. + 'recipients' => $mail,
  304. + 'subject' => $this->randomName(),
  305. + 'message' => '!message',
  306. + );
  307. +
  308. + $hash = drupal_hash_base64('feedback_send_email_action');
  309. + $this->drupalPost("admin/config/system/actions/configure/$hash", $edit, t('Save'));
  310. + $this->assertText(t('The action has been successfully saved.'));
  311. +
  312. + // Now we have to find out the action ID of what we created.
  313. + $aid = db_query('SELECT aid FROM {actions} WHERE callback = :callback AND label = :label', array(':callback' => 'feedback_send_email_action', ':label' => $edit['actions_label']))->fetchField();
  314. +
  315. + $edit = array('aid' => drupal_hash_base64($aid));
  316. + $this->drupalPost('admin/structure/trigger/feedback', $edit, t('Assign'), array(), array(), $form_html_id);
  317. + }
  318. +
  319. +
  320. + /**
  321. + * Asserts correct token replacement for the given trigger and account.
  322. + *
  323. + * @param $account
  324. + * The user account which triggered the action.
  325. + * @param $email_depth
  326. + * Number of emails to scan, starting with most recent.
  327. + */
  328. + function assertFeedbackEmailTokenReplacement($mail, $message, $email_depth = 1) {
  329. + $this->verboseEmail($email_depth);
  330. + $this->assertMailString('body', $message, $email_depth);
  331. + $this->assertMail('to', $mail, t('Mail sent to correct destination'));
  332. + }
  333. +}
  334. \ No newline at end of file