/[drupal]/contributions/modules/simplenews/simplenews.admin.inc
ViewVC logotype

Contents of /contributions/modules/simplenews/simplenews.admin.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.59 - (show annotations) (download) (as text)
Wed Sep 30 14:10:20 2009 UTC (8 weeks, 3 days ago) by sutharsan
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-6--2
Changes since 1.58: +2 -3 lines
File MIME type: text/x-php
#183120 by Sutharsan, miro_dietiker: Added token support to Simplenews. Simplenews is now depending on Token.
1 <?php
2 // $Id: simplenews.admin.inc,v 1.58 2009/07/30 19:56:47 sutharsan Exp $
3
4 /**
5 * @file
6 * Newsletter admin, subscription admin, simplenews settings
7 *
8 * @ingroup simplenews
9 */
10
11 /**
12 * Menu callback: Admin form for sent and draft newsletters.
13 *
14 * @see simplenews_admin_news_submit()
15 */
16 function simplenews_admin_news(&$form_state, $action = 'sent') {
17 $vid = variable_get('simplenews_vid', '');
18 $form = array();
19 $form['simplenews_issue_filter'] = array(
20 '#type' => 'fieldset',
21 '#title' => t('Show issues from'),
22 '#collapsible' => FALSE,
23 '#prefix' => '<div class="container-inline">',
24 '#suffix' => '</div>',
25 );
26
27 if (variable_get('simplenews_last_cron', '')) {
28 $form['last_sent'] = array('#value' => '<p>'. format_plural(variable_get('simplenews_last_sent', 0), 'Last batch: 1 mail sent at !time.', 'Last batch: !count mails sent at !time.', array('!time' => format_date(variable_get('simplenews_last_cron', ''), 'small'), '!count' => variable_get('simplenews_last_sent', 0))) ."</p>\n");
29 }
30
31 $header = array(t('Title'), t('Newsletter'), t('Date created'), t('Published'), t('Sent'), t('Subscribers'), t('Operations'));
32 list($names, $queries) = array_values(simplenews_get_filter('simplenews_newsletters_filter'));
33 $filter = isset($_SESSION['simplenews_newsletters_filter']) ? $_SESSION['simplenews_newsletters_filter'] : '';
34 $form['simplenews_issue_filter']['filter'] = array(
35 '#type' => 'select',
36 '#options' => $names,
37 '#default_value' => $filter,
38 );
39 $where_condition = isset($queries[$filter]) && !empty($queries[$filter]) ? 'WHERE '. $queries[$filter] : '';
40 $query = "SELECT DISTINCT n.*, s.s_status, s.tid FROM {node} n INNER JOIN {simplenews_newsletters} s ON n.nid = s.nid ". $where_condition ." ORDER BY n.created DESC";
41 $count_query = "SELECT COUNT(n.nid) FROM {node} n INNER JOIN {simplenews_newsletters} s ON n.nid = s.nid ". $where_condition;
42 $result = pager_query(db_rewrite_sql($query, 'n', 'nid'), 10, 0, db_rewrite_sql($count_query, 'n', 'nid'), 0);
43
44 $rows = array();
45 while ($node = db_fetch_object($result)) {
46 $row = array();
47 $operation = array();
48 $terms = array_keys(taxonomy_node_get_terms_by_vocabulary($node, $vid, 'name'));
49 $subscriber_count = simplenews_count_subscriptions($node->tid);
50 $pending_count = simplenews_count_spool($node->nid, $node->vid);
51 $send_status = $node->s_status == SIMPLENEWS_STATUS_SEND_PENDING ? $subscriber_count - $pending_count : theme('simplenews_status', $node->s_status, 'sent');
52 $operation[] = l(t('edit'), 'node/'. $node->nid .'/edit', array('query' => drupal_get_destination()));
53
54 $row[] = l($node->title, 'node/'. $node->nid);
55 $row[] = isset($terms[0]) ? $terms[0] : t('n/a');
56 $row[] = format_date($node->created, 'small');
57 $row[] = theme('simplenews_status', $node->status, 'published');
58 $row[] = $send_status;
59 $row[] = $subscriber_count;
60 $row[] = implode(' ', $operation);
61 $rows[] = $row;
62 }
63 if ($pager = theme('pager', NULL, 10, 0)) {
64 $rows[] = array(array('data' => $pager, 'colspan' => '8'));
65 }
66 if (!$rows) {
67 $rows[] = array(array('data' => t('No newsletters available.'), 'colspan' => '8'));
68 }
69 $form['simplenews_issue_filter']['submit'] = array(
70 '#type' => 'submit',
71 '#value' => t('Filter'),
72 );
73
74 $table = theme('table', $header, $rows);
75
76 $form['table'] = array('#value' => $table);
77 return $form;
78 }
79
80 function simplenews_admin_news_submit($form, &$form_state) {
81 _simplenews_set_filter('simplenews_newsletters_filter', $form_state['values']);
82 }
83
84 /**
85 * Store filter values in session var
86 *
87 * @param $type identification string
88 * @param $form_values array of values to be stored
89 */
90 function _simplenews_set_filter($type, $values) {
91 if (empty($_SESSION[$type])) {
92 $_SESSION[$type] = 'all';
93 }
94 $op = $values['op'];
95 if ($op == t('Filter') && isset($values['filter'])) {
96 $_SESSION[$type] = $values['filter'];
97 }
98 }
99
100 /**
101 * Menu callback: newsletter admin form with list of available newsletter series.
102 */
103 function simplenews_types_overview() {
104 $rows = array();
105 $header = array(t('Newsletter name'), t('Subscribers'), t('Operations'));
106
107 foreach (taxonomy_get_tree(variable_get('simplenews_vid', '')) as $term) {
108 $count = simplenews_count_subscriptions($term->tid);
109 $rows[] = array(check_plain($term->name), $count, l(t('edit newsletter'), 'admin/content/simplenews/types/edit/'. $term->tid));
110 }
111
112 if (count($rows) == 0) {
113 $rows[] = array(array('data' => t('There are currently no newsletter series.'), 'colspan' => count($header)));
114 }
115 return theme('table', $header, $rows);
116 }
117
118 /**
119 * Menu callback: newsletter admin form for newsletter add/edit.
120 *
121 * @see simplenews_admin_types_form_validate()
122 * @see simplenews_admin_types_form_submit()
123 */
124 function simplenews_admin_types_form(&$form_state, $tid = NULL) {
125 if (isset($tid)) {
126 // We are editing an existing newsletter.
127 $term = taxonomy_get_term($tid);
128
129 // If the given term is not a newsletter, don't allow editing.
130 if (variable_get('simplenews_vid', '') != $term->vid) {
131 drupal_not_found();
132 return;
133 }
134
135 // Redirect on a delete operation for posterity's sake.
136 if (isset($form_state['post']['op']) && $form_state['post']['op'] == t('Delete')) {
137 drupal_goto('admin/content/simplenews/types/delete/'. $term->tid);
138 }
139
140 }
141 else {
142 // We will create a new newsletter.
143 // Provide vocabulary id for the newsletter to be added to.
144 $term = (object)array('vid' => variable_get('simplenews_vid', ''));
145 }
146
147 $form['name'] = array(
148 '#type' => 'textfield',
149 '#title' => t('Newsletter name'),
150 '#size' => 50,
151 '#maxlength' => 128,
152 '#description' => t('This name of this newsletter.'),
153 '#required' => TRUE,
154 '#default_value' => isset($term->name) ? $term->name : '',
155 );
156 $form['description'] = array(
157 '#type' => 'textarea',
158 '#title' => t('Description'),
159 '#cols' => 60,
160 '#rows' => 5,
161 '#description' => t('A description of the newsletter. To be displayed on taxonomy/term pages and RSS feeds.'),
162 '#default_value' => isset($term->description) ? $term->description : '',
163 );
164 $form['weight'] = array(
165 '#type' => 'weight',
166 '#title' => t('Weight'),
167 '#delta' => 10,
168 '#description' => t('Newsletters are displayed in ascending order by weight.'),
169 '#required' => TRUE,
170 '#default_value' => isset($term->weight) ? $term->weight : 0,
171 );
172
173 $form['simplenews_sender_information'] = array(
174 '#type' => 'fieldset',
175 '#title' => t('Sender information'),
176 '#collapsible' => FALSE,
177 );
178 $form['simplenews_sender_information']['simplenews_from_name_'. $term->tid] = array(
179 '#type' => 'textfield',
180 '#title' => t('From name'),
181 '#size' => 60,
182 '#maxlength' => 128,
183 '#default_value' => variable_get('simplenews_from_name_'. $term->tid, variable_get('simplenews_from_name', variable_get('site_name', 'Drupal'))),
184 );
185 $form['simplenews_sender_information']['simplenews_from_address_'. $term->tid] = array(
186 '#type' => 'textfield',
187 '#title' => t('From email address'),
188 '#size' => 60,
189 '#maxlength' => 128,
190 '#required' => TRUE,
191 '#default_value' => variable_get('simplenews_from_address_'. $term->tid, variable_get('simplenews_from_address', variable_get('site_mail', ini_get('sendmail_from')))),
192 );
193 $form['simplenews_hyperlinks'] = array('#type' => 'fieldset',
194 '#title' => t('HTML to text conversion'),
195 '#collapsible' => FALSE,
196 '#description' => t('When your newsletter is sent as plain text, these options will determine how the conversion to text is performed.'),
197 );
198 $form['simplenews_hyperlinks']['simplenews_hyperlinks_'. $term->tid] = array(
199 '#type' => 'radios',
200 '#title' => t('Hyperlink conversion'),
201 '#options' => array(
202 t('Append hyperlinks as a numbered reference list'),
203 t('Display hyperlinks inline with the text')
204 ),
205 '#default_value' => variable_get('simplenews_hyperlinks_'. $term->tid, 1),
206 );
207 $form['submit'] = array(
208 '#type' => 'submit',
209 '#value' => t('Save'),
210 '#weight' => 25,
211 );
212 $form['vid'] = array(
213 '#type' => 'hidden',
214 '#value' => isset($term->vid) ? $term->vid : variable_get('simplenews_vid', ''),
215 );
216
217 // If we are editing a newsletter term, show delete option and store tid.
218 // tid is used in validation and submission functions to differentiate
219 // between form actions of creating a new or editing an existing term.
220 if (isset($term->tid)) {
221 $form['delete'] = array(
222 '#type' => 'submit',
223 '#value' => t('Delete'),
224 '#weight' => 30,
225 );
226 $form['tid'] = array(
227 '#type' => 'value',
228 '#value' => $term->tid,
229 );
230 }
231
232 // Return to Newsletter list page after submit
233 $form['#redirect'] = 'admin/content/simplenews/types';
234
235 return $form;
236 }
237
238 function simplenews_admin_types_form_validate($form, &$form_state) {
239 $tid = $form_state['values']['tid'];
240 $field_name = 'simplenews_from_address_'. $tid;
241
242 if (!valid_email_address($form_state['values'][$field_name])) {
243 form_set_error($field_name, t("The sender's email address you supplied is not valid."));
244 }
245 }
246
247 function simplenews_admin_types_form_submit($form, &$form_state) {
248 // Redirect on a delete operation for posterity's sake.
249 if (isset($form_state['post']['op']) && $form_state['post']['op'] == t('Delete')) {
250 drupal_goto('admin/content/simplenews/types/delete/'. $term->tid);
251 }
252
253 // Create or update taxonomy term for this newsletter.
254 // When creating a term $form_state['values']['tid'] is NULL.
255 if (isset($form_state['values']['tid'])) {
256 $termdata = (array)taxonomy_get_term($form_state['values']['tid']);
257 }
258 $termdata['tid'] = $form_state['values']['tid'];
259 $termdata['vid'] = $form_state['values']['vid'];
260 $termdata['name'] = $form_state['values']['name'];
261 $termdata['description'] = $form_state['values']['description'];
262 $termdata['weight'] = $form_state['values']['weight'];
263 switch (taxonomy_save_term($termdata)) {
264 case SAVED_NEW:
265 drupal_set_message(t('Created new term %name.', array('%name' => $form_state['values']['name'])));
266 break;
267 case SAVED_UPDATED:
268 drupal_set_message(t('Updated term %name.', array('%name' => $form_state['values']['name'])));
269 break;
270 }
271
272 // Store newsletter specific settings.
273 // When editing a newsletter fieldnames have $tid suffix.
274 // When creating a new newsletter field names have no suffix
275 // and $form_state['values']['tid'] is NULL.
276 if (isset($form_state['values']['tid'])) {
277 $tid = $suffix = $form_state['values']['tid'];
278 }
279 else {
280 // Get the tid from the database based on the form values used above to
281 // create a new term.
282 $tid = db_result(db_query("SELECT t.tid FROM {term_data} t WHERE t.vid = %d AND t.name = '%s' ORDER BY t.tid DESC", $form_state['values']['vid'], $form_state['values']['name']));
283 $suffix = '';
284 }
285 variable_set('simplenews_from_name_'. $tid, $form_state['values']['simplenews_from_name_'. $suffix]);
286 variable_set('simplenews_from_address_'. $tid, $form_state['values']['simplenews_from_address_'. $suffix]);
287 variable_set('simplenews_hyperlinks_'. $tid, $form_state['values']['simplenews_hyperlinks_'. $suffix]);
288 }
289
290 /**
291 * Menu callback: Delete newsletter series.
292 *
293 * @see simplenews_admin_types_delete_submit()
294 */
295 function simplenews_admin_types_delete(&$form_state, $tid = NULL) {
296 if (!isset($tid)) {
297 drupal_not_found();
298 return;
299 }
300 $term = taxonomy_get_term($tid);
301 $form = array();
302 $form['tid'] = array(
303 '#type' => 'value',
304 '#value' => $tid,
305 );
306 $form['notice'] = array(
307 '#value' => '<p><strong>'. t('Note: All subscriptions associated with this newsletter will be lost.') .'</strong></p>',
308 );
309 $form['#redirect'] = 'admin/content/simplenews/types';
310
311 return confirm_form($form,
312 t('Are you sure you want to delete %title?', array('%title' => $term->name)),
313 'admin/content/simplenews/types',
314 t('This action cannot be undone.'),
315 t('Delete'),
316 t('Cancel')
317 );
318 }
319
320 function simplenews_admin_types_delete_submit($form, &$form_state) {
321 if ($form_state['values']['confirm']) {
322 $tid = $form_state['values']['tid'];
323 $term = taxonomy_get_term($tid);
324 taxonomy_del_term($tid);
325 variable_del('simplenews_from_name_'. $tid);
326 variable_del('simplenews_from_address_'. $tid);
327 drupal_set_message(t('Newsletter %title has been deleted.', array('%title' => $term->name)));
328 }
329 }
330
331 /**
332 * Menu callback: Delete multiple subscriptions.
333 *
334 * @see simplenews_subscription_multiple_delete_confirm_submit()
335 */
336 function simplenews_subscription_multiple_delete_confirm() {
337 // Subscriptions to be deleted are passed via session var.
338 $snids = $_SESSION['simplenews_subscriptions_delete'];
339
340 $form['snids'] = array('#prefix' => '<ul>', '#suffix' => '</ul>', '#tree' => TRUE);
341 // array_filter returns only elements with TRUE values
342 foreach (array_filter($snids) as $snid => $value) {
343 $mail = db_result(db_query('SELECT mail FROM {simplenews_subscriptions} WHERE snid = %d', $snid));
344 $form['snids'][$snid] = array(
345 '#type' => 'hidden',
346 '#value' => $snid,
347 '#prefix' => '<li>',
348 '#suffix' => check_plain($mail) ."</li>\n"
349 );
350 }
351
352 $form['operation'] = array(
353 '#type' => 'hidden',
354 '#value' => 'delete',
355 );
356 $form['#submit'][] = 'simplenews_subscription_multiple_delete_confirm_submit';
357
358 return confirm_form($form,
359 t('Are you sure you want to delete these subscriptions?'),
360 'admin/content/simplenews/users',
361 t('This action cannot be undone.'),
362 t('Delete all'),
363 t('Cancel')
364 );
365 }
366
367 function simplenews_subscription_multiple_delete_confirm_submit($form, &$form_state) {
368 if ($form_state['values']['confirm']) {
369 foreach ($form_state['values']['snids'] as $snid => $value) {
370 simplenews_delete_subscription($snid);
371 }
372 drupal_set_message(t('The subscriptions have been deleted.'));
373 }
374 return '';
375 }
376
377 /**
378 * Menu callback: Mass subscribe to newsletters.
379 *
380 * @see simplenews_subscription_list_add_submit()
381 * @todo Add 32char description field as subsription source
382 */
383 function simplenews_subscription_list_add() {
384 global $language;
385
386 $form['emails'] = array(
387 '#type' => 'textarea',
388 '#title' => t('Email addresses'),
389 '#cols' => 60,
390 '#rows' => 5,
391 '#description' => t('Email addresses must be separated by comma, space or newline.'),
392 );
393 $newsletters = array();
394 foreach (taxonomy_get_tree(variable_get('simplenews_vid', '')) as $newsletter) {
395 $newsletters[$newsletter->tid] = check_plain($newsletter->name);
396 }
397 $form['newsletters'] = array(
398 '#type' => 'checkboxes',
399 '#title' => t('Subscribe to'),
400 '#options' => $newsletters,
401 '#required' => TRUE,
402 );
403
404 // Include language selection when the site is multilingual.
405 // Default value is the empty string which will result in receiving emails
406 // in the site's default language.
407 if (variable_get('language_count', 1) > 1) {
408 $options[''] = t('Site default language');
409 $languages = language_list('enabled');
410 foreach ($languages[1] as $langcode => $item) {
411 $name = t($item->name);
412 $options[$langcode] = $name . ($item->native != $name ? ' ('. $item->native .')' : '');
413 }
414 $form['language'] = array(
415 '#type' => 'radios',
416 '#title' => t('Anonymous user preferred language'),
417 '#default_value' => '',
418 '#options' => $options,
419 '#description' => t('Anonymous users will be subscribed with the selected preferred language. They will receive newsletters in this language if available. Registered users will be subscribed with their preferred language as set on their account page.'),
420 );
421 }
422 else {
423 $form['language'] = array('#type' => 'value', '#value' => '');
424 }
425
426 $form['submit'] = array(
427 '#type' => 'submit',
428 '#value' => t('Subscribe'),
429 );
430 return $form;
431 }
432
433 function simplenews_subscription_list_add_submit($form, &$form_state) {
434 $tree = taxonomy_get_tree(variable_get('simplenews_vid', ''));
435 $added = array();
436 $invalid = array();
437 $checked_newsletters = array_filter($form_state['values']['newsletters']);
438 $langcode = $form_state['values']['language'];
439
440 $emails = preg_split("/[\s,]+/", $form_state['values']['emails']);
441 foreach ($emails as $email) {
442 $email = trim($email);
443 if (valid_email_address($email)) {
444 foreach ($checked_newsletters as $tid) {
445 $newsletter = taxonomy_get_term($tid);
446 simplenews_subscribe_user($email, $newsletter->tid, FALSE, 'mass subscribe', $langcode);
447 $added[] = $email;
448 }
449 }
450 else {
451 $invalid[] = $email;
452 }
453 }
454 if ($added) {
455 $added = implode(", ", $added);
456 drupal_set_message(t('The following addresses were added or updated: %added.', array('%added' => $added)));
457
458 $newsletter_names = array();
459 foreach ($checked_newsletters as $tid) {
460 $newsletter = taxonomy_get_term($tid);
461 $newsletter_names[] = $newsletter->name;
462 }
463 drupal_set_message(t('The addresses were subscribed to the following newsletters: %newsletters.', array('%newsletters' => implode(', ', $newsletter_names))));
464 }
465 else {
466 drupal_set_message(t('No addresses were added.'));
467 }
468 if ($invalid) {
469 $invalid = implode(", ", $invalid);
470 drupal_set_message(t('The following addresses were invalid: %invalid.', array('%invalid' => $invalid)), 'error');
471 }
472 }
473
474 /**
475 * Menu callback: Export email address of subscriptions.
476 *
477 * @see simplenews_admin_export_after_build()
478 * @todo Add checkboxes for subscribed and unsubscribed selection.
479 */
480 function simplenews_subscription_list_export() {
481 $form['states'] = array(
482 '#type' => 'checkboxes',
483 '#title' => t('Status'),
484 '#options' => array('active' => t('Active users'), 'inactive' => t('Inactive users')),
485 '#description' => t('Subscriptions matching the selected states will be exported.'),
486 '#required' => TRUE,
487 );
488 $newsletters = array();
489 foreach (taxonomy_get_tree(variable_get('simplenews_vid', '')) as $newsletter) {
490 $newsletters[$newsletter->tid] = check_plain($newsletter->name);
491 }
492 $form['newsletters'] = array(
493 '#type' => 'checkboxes',
494 '#title' => t('Subscribed to'),
495 '#options' => $newsletters,
496 '#description' => t('Subscriptions matching the selected newsletters will be exported.'),
497 '#required' => TRUE,
498 );
499
500 // Emails item is initially empty. It serves as place holder. Data is added by
501 // simplenews_admin_export_after_build().
502 $form['emails'] = array();
503 $form['submit'] = array(
504 '#type' => 'submit',
505 '#value' => t('Export'),
506 );
507 $form['#after_build'] = array('simplenews_admin_export_after_build');
508 $form['#redirect'] = FALSE;
509 return $form;
510 }
511
512 function simplenews_admin_export_after_build($form, $form_element) {
513 //TODO: Add (un)subscribed as filter to form.
514 if (isset($form_element['values']['op']) && $form_element['values']['op'] == t('Export')) {
515 $states = array_filter($form_element['values']['states']);
516 $newsletters = array_filter($form_element['values']['newsletters']);
517
518 // Build where clause for active/inactive state and newsletter selection.
519 if (isset($states['active'])) {
520 $where[] = 's.activated = 1';
521 }
522 if (isset($states['inactive'])) {
523 $where[] = 's.activated = 0';
524 }
525 $where = isset($where) ? implode(' OR ', $where) : NULL;
526 if ($tree = taxonomy_get_tree(variable_get('simplenews_vid', ''))) {
527 foreach ($tree as $newsletter) {
528 if (isset($newsletters[$newsletter->tid])) {
529 $where_tid[] = 't.tid = '. $newsletter->tid;
530 }
531 }
532 }
533 $where_tid = isset($where_tid) ? implode(' OR ', $where_tid) : NULL;
534
535 // Get subscription data
536 if (isset($where) && isset($where_tid)) {
537 $query = 'SELECT DISTINCT s.mail FROM {simplenews_subscriptions} s INNER JOIN {simplenews_snid_tid} t ON s.snid = t.snid WHERE ('. $where .') AND ('. $where_tid .')';
538 $result = db_query($query);
539 while ($mail = db_fetch_object($result)) {
540 $mails[] = $mail->mail;
541 }
542 }
543
544 // Build form field containing exported emails.
545 // The field will be included in the form where at the ['emails'] place holder.
546 if (isset($mails)) {
547 $exported_mails = implode(", ", $mails);
548 }
549 else {
550 $exported_mails = t('No addresses were found.');
551 }
552 $form['emails'] = array(
553 '#type' => 'textarea',
554 '#title' => t('Export results'),
555 '#cols' => 60,
556 '#rows' => 5,
557 '#value' => $exported_mails,
558 );
559 }
560 return $form;
561 }
562
563 /**
564 * Menu callback: Mass subscribe to newsletters.
565 *
566 * @see simplenews_subscription_list_remove_submit()
567 * @todo Add 32char description field as unsubsription source
568 */
569 function simplenews_subscription_list_remove() {
570 $form['emails'] = array(
571 '#type' => 'textarea',
572 '#title' => t('Email addresses'),
573 '#cols' => 60,
574 '#rows' => 5,
575 '#description' => t('Email addresses must be separated by comma, space or newline.'),
576 );
577 $newsletters = array();
578 foreach (taxonomy_get_tree(variable_get('simplenews_vid', '')) as $newsletter) {
579 $newsletters[$newsletter->tid] = check_plain($newsletter->name);
580 }
581 $form['newsletters'] = array(
582 '#type' => 'checkboxes',
583 '#title' => t('Unsubscribe from'),
584 '#options' => $newsletters,
585 '#required' => TRUE,
586 );
587 $form['submit'] = array(
588 '#type' => 'submit',
589 '#value' => t('Unsubscribe'),
590 );
591 return $form;
592 }
593
594 function simplenews_subscription_list_remove_submit($form, &$form_state) {
595 $tree = taxonomy_get_tree(variable_get('simplenews_vid', ''));
596 $removed = array();
597 $invalid = array();
598 $checked_newsletters = array_filter($form_state['values']['newsletters']);
599
600 $emails = preg_split("/[\s,]+/", $form_state['values']['emails']);
601 foreach ($emails as $email) {
602 $email = trim($email);
603 if (valid_email_address($email)) {
604 foreach ($checked_newsletters as $tid) {
605 $newsletter = taxonomy_get_term($tid);
606 simplenews_unsubscribe_user($email, $newsletter->tid, FALSE, 'mass unsubscribe');
607 $removed[] = $email;
608 }
609 }
610 else {
611 $invalid[] = $email;
612 }
613 }
614 if ($removed) {
615 $removed = implode(", ", $removed);
616 drupal_set_message(t('The following addresses were unsubscribed: %removed.', array('%removed' => $removed)));
617
618 $newsletter_names = array();
619 foreach ($checked_newsletters as $tid) {
620 $newsletter = taxonomy_get_term($tid);
621 $newsletter_names[] = $newsletter->name;
622 }
623 drupal_set_message(t('The addresses were unsubscribed from the following newsletters: %newsletters.', array('%newsletters' => implode(', ', $newsletter_names))));
624 }
625 else {
626 drupal_set_message(t('No addresses were removed.'));
627 }
628 if ($invalid) {
629 $invalid = implode(", ", $invalid);
630 drupal_set_message(t('The following addresses were invalid: %invalid.', array('%invalid' => $invalid)), 'error');
631 }
632 }
633
634 /**
635 * Menu callback: subscription administration.
636 */
637 function simplenews_subscription_admin($form_state) {
638 // Delete subscriptions requires delete confirmation. This is handled with a different form
639 if (isset($form_state['post']['operation']) && $form_state['post']['operation'] == 'delete' && isset($form_state['post']['snids'])) {
640 $destination = drupal_get_destination();
641 $_SESSION['simplenews_subscriptions_delete'] = $form_state['post']['snids'];
642 // Note: we redirect from admin/content/simplenews/users to admin/content/simplenews/subscriptions/delete to make the tabs disappear.
643 drupal_goto("admin/content/simplenews/subscriptions/delete", $destination);
644 }
645
646 $form = simplenews_subscription_filter_form();
647 $form['admin'] = simplenews_subscription_list_form();
648
649 return $form;
650 }
651
652 /**
653 * Build the form for admin subscription.
654 *
655 * Form consists of a filter fieldset, an operation fieldset and a list of
656 * subscriptions maching the filter criteria.
657 *
658 * @see simplenews_subscription_list_form_validate()
659 * @see simplenews_subscription_list_form_submit()
660 */
661 function simplenews_subscription_list_form() {
662 //TODO: Subscriber maintanance needs overhaul now we have more data availabale.
663
664 // Table header. Used as tablesort default
665 $header = array(
666 array('data' => t('Email'), 'field' => 'ss.mail', 'sort' => 'asc'),
667 array('data' => t('Username'), 'field' => 'u.name'),
668 array('data' => t('Status'), 'field' => 'ss.activated'),
669 t('Operations')
670 );
671
672 // Data collection with filter and sorting applied
673 $filter = simplenews_build_subscription_filter_query();
674 $query = 'SELECT DISTINCT ss.*, u.name FROM {simplenews_subscriptions} ss LEFT JOIN {users} u ON ss.uid = u.uid INNER JOIN {simplenews_snid_tid} s ON ss.snid = s.snid'. $filter['where'];
675
676 // $count_query used to count distinct records only
677 $count_query = preg_replace('/SELECT.*FROM /', 'SELECT COUNT(DISTINCT ss.mail) FROM ', $query);
678 $query .= tablesort_sql($header);
679 $result = pager_query($query, 30, 0, $count_query);
680
681 // Update options
682 $form['options'] = array(
683 '#type' => 'fieldset',
684 '#title' => t('Update options'),
685 '#prefix' => '<div class="container-inline">',
686 '#suffix' => '</div>',
687 );
688 $form['options']['operation'] = array(
689 '#type' => 'select',
690 '#options' => array(
691 'activate' => t('Activate'),
692 'inactivate' => t('Inactivate'),
693 'delete' => t('Delete'),
694 ),
695 '#default_value' => 'activate');
696 $form['options']['submit'] = array(
697 '#type' => 'submit',
698 '#value' => t('Update'),
699 '#submit' => array('simplenews_subscription_list_form_submit'),
700 '#validate' => array('simplenews_subscription_list_form_validate'),
701 );
702
703 $snids = array();
704 // Subscription table and table pager
705 while ($subscription = db_fetch_object($result)) {
706 $snids[$subscription->snid] = '';
707 $form['mail'][$subscription->snid] = array('#value' => $subscription->mail);
708 $form['name'][$subscription->snid] = array('#value' => isset($subscription->uid) ? l($subscription->name, 'user/'. $subscription->uid) : $subscription->name);
709 $form['status'][$subscription->snid] = array('#value' => theme('simplenews_status', $subscription->activated, 'activated'));
710 $form['operations'][$subscription->snid] = array('#value' => l(t('edit'), 'admin/content/simplenews/users/edit/'. $subscription->snid, array(), drupal_get_destination()));
711 }
712 $form['snids'] = array('#type' => 'checkboxes', '#options' => $snids);
713 $form['pager'] = array('#value' => theme('pager', NULL, 30, 0));
714 $form['#theme'] = 'simplenews_subscription_list';
715 return $form;
716 }
717
718 function simplenews_subscription_list_form_validate($form, &$form_state) {
719 if (isset($form_state['values']['operation'])) {
720 $snids = array_filter($form_state['values']['snids']);
721 if (empty($snids)) {
722 form_set_error('', t('No items selected.'));
723 }
724 }
725 }
726
727 function simplenews_subscription_list_form_submit($form, &$form_state) {
728 if (isset($form_state['values']['operation'])) {
729 $snids = array_filter($form_state['values']['snids']);
730 $args = array($snids);
731 switch ($form_state['values']['operation']) {
732 case 'activate':
733 call_user_func_array('simplenews_activate_subscription', $args);
734 drupal_set_message(t('The update has been performed.'));
735 break;
736 case 'inactivate':
737 call_user_func_array('simplenews_inactivate_subscription', $args);
738 drupal_set_message(t('The update has been performed.'));
739 break;
740 }
741 }
742 }
743
744 /**
745 * Menu callback: Simplenews admin settings - General.
746 */
747 function simplenews_admin_settings(&$form_state) {
748 $vid = variable_get('simplenews_vid', '');
749 $address_default = variable_get('site_mail', ini_get('sendmail_from'));
750 $form = array();
751
752 $form['simplenews_general_settings']['simplenews_content_types'] = array(
753 '#type' => 'checkboxes',
754 '#title' => t('Content types'),
755 '#required' => TRUE,
756 '#options' => array_map('check_plain', node_get_types('names')),
757 '#default_value' => variable_get('simplenews_content_types', array('simplenews' => 'simplenews')),
758 '#description' => t('Content types to be used as newsletter.'),
759 );
760
761 $vocabulary_options = array('' => t('<select>'));
762 if ($vocabularies = taxonomy_get_vocabularies()) {
763 foreach ($vocabularies as $key => $object) {
764 $vocabulary_options[$key] = $object->name;
765 }
766 }
767 $form['simplenews_general_settings']['simplenews_vid'] = array(
768 '#type' => 'select',
769 '#title' => t('Newsletter vocabulary'),
770 '#options' => $vocabulary_options,
771 '#required' => TRUE,
772 '#description' => t('This vocabulary identifies newsletter series. Note that changing this vocabulary will require existing newsletters to be re-tagged and activated newsletter blocks to be re-activated.'),
773 '#default_value' => variable_get('simplenews_vid', ''),
774 );
775
776 // Node type settings require pre-processing.
777 // simplenews_admin_settings_submit() is called before system_settings_form_submit().
778 $form['#submit'][] = 'simplenews_admin_settings_submit';
779 return system_settings_form($form);
780 }
781
782 function simplenews_admin_settings_submit($form, &$form_state) {
783 // Newsletter vocabulary is updated using node type settings.
784 $vocabulary = (array)taxonomy_vocabulary_load($form_state['values']['simplenews_vid']);
785 $form_state['values']['simplenews_content_types'] = array_filter($form_state['values']['simplenews_content_types']);
786 $vocabulary['nodes'] = $form_state['values']['simplenews_content_types'];
787
788 // Set vocabulary required values
789 $vocabulary['multiple'] = FALSE;
790 $vocabulary['required'] = TRUE;
791 $vocabulary['tags'] = FALSE;
792
793 taxonomy_save_vocabulary($vocabulary);
794 variable_set('simplenews_content_types', $form_state['values']['simplenews_content_types']);
795
796 // We do not need a simplenews_content_types variable.
797 unset($form_state['values']['simplenews_content_types']);
798
799 drupal_set_message(t('Updated vocabulary %name.', array('%name' => $vocabulary['name'])));
800 watchdog('simplenews', 'Updated vocabulary %name.', array('%name' => $vocabulary['name']), WATCHDOG_NOTICE, l(t('edit'), 'admin/content/taxonomy/edit/vocabulary/'. $form_state['values']['vid']));
801 }
802
803 /**
804 * Menu callback: Simplenews admin settings - Newsletter.
805 */
806 function simplenews_admin_settings_newsletter(&$form_state) {
807 $vid = variable_get('simplenews_vid', '');
808 $address_default = variable_get('site_mail', ini_get('sendmail_from'));
809 $form = array();
810
811 $form['simplenews_default_options'] = array(
812 '#type' => 'fieldset',
813 '#title' => t('Default newsletter options'),
814 '#collapsible' => FALSE,
815 '#description' => t('These options will be the defaults for new newsletters, but can be overridden in the newsletter editing form.'),
816 );
817 $description = t('Default newsletter format.');
818 if (!module_exists('mimemail')) {
819 $description .= ' '. t('Install <a href="@mime_mail_url">Mime Mail</a> module to send newsletters in HTML format.', array('@mime_mail_url' => 'http://drupal.org/project/mimemail'));
820 }
821 $form['simplenews_default_options']['simplenews_format'] = array(
822 '#type' => 'select',
823 '#title' => t('Format'),
824 '#options' => _simplenews_format_options(),
825 '#description' => $description,
826 '#default_value' => variable_get('simplenews_format', 'plain'),
827 );
828 $form['simplenews_default_options']['simplenews_priority'] = array(
829 '#type' => 'select',
830 '#title' => t('Priority'),
831 '#options' => array(0 => t('none'), 1 => t('highest'), 2 => t('high'), 3 => t('normal'), 4 => t('low'), 5 => t('lowest')),
832 '#description' => t('Note that email priority is ignored by a lot of email programs.'),
833 '#default_value' => variable_get('simplenews_priority', 0),
834 );
835 $form['simplenews_default_options']['simplenews_receipt'] = array(
836 '#type' => 'checkbox',
837 '#title' => t('Request receipt'),
838 '#default_value' => variable_get('simplenews_receipt', 0),
839 '#description' => t('Request a Read Receipt from your newsletters. A lot of email programs ignore these so it is not a definitive indication of how many people have read your newsletter.'),
840 );
841 $form['simplenews_default_options']['simplenews_send'] = array(
842 '#type' => 'radios',
843 '#title' => t('Default send action'),
844 '#options' => array(0 => t("Don't send now"), 2 => t('Send one test newsletter to the test address'), 1 => t('Send newsletter')),
845 '#default_value' => variable_get('simplenews_send', 0),
846 );
847 $form['simplenews_test_address'] = array(
848 '#type' => 'fieldset',
849 '#title' => t('Test addresses'),
850 '#collapsible' => FALSE,
851 '#description' => t('Supply a comma-separated list of email addresses to be used as test addresses. The override function allows to override these addresses in the newsletter editing form.'),
852 );
853 $form['simplenews_test_address']['simplenews_test_address'] = array(
854 '#type' => 'textfield',
855 '#title' => t('Email address'),
856 '#size' => 60,
857 '#maxlength' => 128,
858 '#default_value' => variable_get('simplenews_test_address', $address_default),
859 );
860 $form['simplenews_test_address']['simplenews_test_address_override'] = array(
861 '#type' => 'checkbox',
862 '#title' => t('Allow test address override'),
863 '#default_value' => variable_get('simplenews_test_address_override', 0),
864 );
865 $form['simplenews_sender_info'] = array(
866 '#type' => 'fieldset',
867 '#title' => t('Sender information'),
868 '#collapsible' => FALSE,
869 '#description' => t('Default sender address that will only be used for confirmation emails. You can specify sender information for each newsletter separately on the newsletter\'s settings page.'),
870 );
871 $form['simplenews_sender_info']['simplenews_from_name'] = array(
872 '#type' => 'textfield',
873 '#title' => t('From name'),
874 '#size' => 60,
875 '#maxlength' => 128,
876 '#default_value' => variable_get('simplenews_from_name', variable_get('site_name', 'Drupal')),
877 );
878 $form['simplenews_sender_info']['simplenews_from_address'] = array(
879 '#type' => 'textfield',
880 '#title' => t('From email address'),
881 '#size' => 60,
882 '#maxlength' => 128,
883 '#required' => TRUE,
884 '#default_value' => variable_get('simplenews_from_address', $address_default),
885 );
886
887 return system_settings_form($form);
888 }
889
890 function simplenews_admin_settings_newsletter_validate($form, &$form_state) {
891 if (!valid_email_address($form_state['values']['simplenews_from_address'])) {
892 form_set_error($field_name, t("The sender's email address you supplied is not valid."));
893 }
894 }
895
896 /**
897 * Menu callback: Simplenews admin settings - Email.
898 */
899 function simplenews_admin_settings_mail(&$form_state) {
900 $vid = variable_get('simplenews_vid', '');
901 $address_default = variable_get('site_mail', ini_get('sendmail_from'));
902 $form = array();
903
904 $form['simplenews_mail_backend']['simplenews_use_cron'] = array(
905 '#type' => 'checkbox',
906 '#title' => t('Use cron to send newsletters'),
907 '#default_value' => variable_get('simplenews_use_cron', TRUE),
908 '#description' => t('When checked cron will be used to send newsletters (recommended). Test newsletters and confirmation emails will be send immediately. Leave unchecked for testing purposes.'),
909 );
910 $throttle = drupal_map_assoc(array(1, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000));
911 $throttle[999999] = t('Unlimited');
912 if (function_exists('getrusage')) {
913 $description_extra = '<br />'. t('Cron execution must not exceed the PHP maximum execution time of %max seconds. You find the time spend to send emails in the <a href="/admin/reports/dblog">Recent log entries</a>.', array('%max' => ini_get('max_execution_time')));
914 }
915 else {
916 $description_extra = '<br />'. t('Cron execution must not exceed the PHP maximum execution time of %max seconds.', array('%max' => ini_get('max_execution_time')));
917 }
918 $form['simplenews_mail_backend']['simplenews_throttle'] = array(
919 '#type' => 'select',
920 '#title' => t('Cron throttle'),
921 '#options' => $throttle,
922 '#default_value' => variable_get('simplenews_throttle', 20),
923 '#description' => t('Sets the numbers of newsletters sent per cron run. Failure to send will also be counted.') . $description_extra,
924 );
925 $form['simplenews_mail_backend']['simplenews_spool_expire'] = array(
926 '#type' => 'select',
927 '#title' => t('Mail spool expiration'),
928 '#options' => array(0 => t('Immediate'), 1 => t('1 day'), 7 => t('1 week'), 14 => t('2 weeks')),
929 '#default_value' => variable_get('simplenews_spool_expire', 0),
930 '#description' => t('Newsletter mails are spooled. How long must messages be retained in the spool after successfull sending. Keeping the message in the spool allows mail statistics (which is not yet implemented). If cron is not used, immediate expiration is advised.'),
931 );
932 $form['simplenews_mail_backend']['simplenews_debug'] = array(
933 '#type' => 'checkbox',
934 '#title' => t('Log emails'),
935 '#default_value' => variable_get('simplenews_debug', FALSE),
936 '#description' => t('When checked all outgoing simplenews emails are logged in the system log. A logged email does not guarantee that it is send or will be delivered. It only indicates that a message is send to the PHP mail() function. No status information is available of delivery by the PHP mail() function.'),
937 );
938
939 return system_settings_form($form);
940 }
941
942 /**
943 * Menu callback: Simplenews admin settings - Subscription.
944 */
945 function simplenews_admin_settings_subscription(&$form_state) {
946 $vid = variable_get('simplenews_vid', '');
947 $address_default = variable_get('site_mail', ini_get('sendmail_from'));
948 $form = array();
949
950 $form['simplenews_subscription']['account'] = array(
951 '#type' => 'fieldset',
952 '#title' => t('User account'),
953 '#collapsible' => FALSE,
954 );
955 $form['simplenews_subscription']['account']['simplenews_sync_account'] = array(
956 '#type' => 'checkbox',
957 '#title' => t('Synchronize with account'),
958 '#default_value' => variable_get('simplenews_sync_account', TRUE),
959 '#description' => t('When checked subscriptions will be synchronized with site accounts. When accounts are deleted, subscriptions with the same email address will be removed. When site accounts are blocked/unblocked, subscriptions will be deactivated/activated. When not checked subscriptions will be unchanged when associated accounts are deleted or blocked.'),
960 );
961
962 // These email tokens are shared for all settings, so just define
963 // the list once to help ensure they stay in sync.
964
965 $form['simplenews_subscription']['subscription_mail'] = array(
966 '#type' => 'fieldset',
967 '#title' => t('Confirmation emails'),
968 '#collapsible' => FALSE,
969 );
970
971 $form['simplenews_subscription']['subscription_mail']['token_help'] = array(
972 '#title' => t('Replacement patterns'),
973 '#type' => 'fieldset',
974 '#collapsible' => TRUE,
975 '#collapsed' => TRUE,
976 );
977 $form['simplenews_subscription']['subscription_mail']['token_help']['help'] = array(
978 '#value' => theme('token_help', 'simplenews'),
979 );
980
981 $form['simplenews_subscription']['subscription_mail']['simplenews_confirm_subscribe_subject'] = array(
982 '#type' => 'textfield',
983 '#title' => t('Subject'),
984 '#default_value' => _simplenews_subscription_confirmation_text('subscribe_subject'),
985 '#maxlength' => 180,
986 );
987 $form['simplenews_subscription']['subscription_mail']['simplenews_confirm_subscribe_unsubscribed'] = array(
988 '#type' => 'textarea',
989 '#title' => t('Body text of subscribe email'),
990 '#default_value' => _simplenews_subscription_confirmation_text('subscribe_unsubscribed'),
991 '#rows' => 5,
992 );
993 $form['simplenews_subscription']['subscription_mail']['simplenews_confirm_subscribe_subscribed'] = array(
994 '#type' => 'textarea',
995 '#title' => t('Body text for already subscribed visitor'),
996 '#default_value' => _simplenews_subscription_confirmation_text('subscribe_subscribed'),
997 '#rows' => 5,
998 );
999 $form['simplenews_subscription']['subscription_mail']['simplenews_confirm_unsubscribe_subscribed'] = array(
1000 '#type' => 'textarea',
1001 '#title' => t('Body text of unsubscribe email'),
1002 '#default_value' => _simplenews_subscription_confirmation_text('unsubscribe_subscribed'),
1003 '#rows' => 5,
1004 );
1005 $form['simplenews_subscription']['subscription_mail']['simplenews_confirm_unsubscribe_unsubscribed'] = array(
1006 '#type' => 'textarea',
1007 '#title' => t('Body text for not yet subscribed visitor'),
1008 '#default_value' => _simplenews_subscription_confirmation_text('unsubscribe_unsubscribed'),
1009 '#rows' => 5,
1010 );
1011
1012 return system_settings_form($form);
1013 }
1014
1015 /**
1016 * Callback function to activate the specified subscriptions.
1017 *
1018 * @param $snid array of snid's
1019 */
1020 function simplenews_activate_subscription($snid) {
1021 db_query('UPDATE {simplenews_subscriptions} SET activated = %d WHERE snid IN('. db_placeholders($snid, 'int') .')', array_merge(array('1'), $snid));
1022 }
1023