/** * {@inheritdoc} */ public function nextMail() { // Get the current mail spool row and update the internal pointer to the // next row. $return = each($this->mails); // If we're done, return false. if (!$return) { return FALSE; } $spool_data = $return['value']; // Store this spool row as processed. $this->processed[$spool_data->msid] = $spool_data; $entity = entity_load($spool_data->entity_type, $spool_data->entity_id); if (!$entity) { // If the entity load failed, set the processed status done and proceed with // the next mail. $this->processed[$spool_data->msid]->result = array('status' => SpoolStorageInterface::STATUS_DONE, 'error' => TRUE); return $this->nextMail(); } if ($spool_data->data) { $subscriber = $spool_data->data; } else { $subscriber = simplenews_subscriber_load_by_mail($spool_data->mail); } if (!$subscriber) { // If loading the subscriber failed, set the processed status done and // proceed with the next mail. $this->processed[$spool_data->msid]->result = array('status' => SpoolStorageInterface::STATUS_DONE, 'error' => TRUE); return $this->nextMail(); } $mail = new MailEntity($entity, $subscriber, \Drupal::service('simplenews.mail_cache')); // Set the langcode langcode. $this->processed[$spool_data->msid]->langcode = $mail->getEntity()->language()->getId(); return $mail; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $added = array(); $invalid = array(); $unsubscribed = array(); $checked_newsletters = array_keys(array_filter($form_state->getValue('newsletters'))); $langcode = $form_state->getValue('language'); $emails = preg_split("/[\\s,]+/", $form_state->getValue('emails')); foreach ($emails as $email) { $email = trim($email); if ($email == '') { continue; } if (valid_email_address($email)) { $subscriber = simplenews_subscriber_load_by_mail($email); /** @var \Drupal\simplenews\Subscription\SubscriptionManagerInterface $subscription_manager */ $subscription_manager = \Drupal::service('simplenews.subscription_manager'); foreach (simplenews_newsletter_load_multiple($checked_newsletters) as $newsletter) { // If there is a valid subscriber, check if there is a subscription for // the current newsletter and if this subscription has the status // unsubscribed. $is_unsubscribed = $subscriber ? $subscriber->isUnsubscribed($newsletter->id()) : FALSE; if (!$is_unsubscribed || $form_state->getValue('resubscribe') == TRUE) { $subscription_manager->subscribe($email, $newsletter->id(), FALSE, 'mass subscribe', $langcode); $added[] = $email; } else { $unsubscribed[$newsletter->label()][] = $email; } } } else { $invalid[] = $email; } } if ($added) { $added = implode(", ", $added); drupal_set_message(t('The following addresses were added or updated: %added.', array('%added' => $added))); $list_names = array(); foreach (simplenews_newsletter_load_multiple($checked_newsletters) as $newsletter) { $list_names[] = $newsletter->label(); } drupal_set_message(t('The addresses were subscribed to the following newsletters: %newsletters.', array('%newsletters' => implode(', ', $list_names)))); } else { drupal_set_message(t('No addresses were added.')); } if ($invalid) { $invalid = implode(", ", $invalid); drupal_set_message(t('The following addresses were invalid: %invalid.', array('%invalid' => $invalid)), 'error'); } foreach ($unsubscribed as $name => $subscribers) { $subscribers = implode(", ", $subscribers); drupal_set_message(t('The following addresses were skipped because they have previously unsubscribed from %name: %unsubscribed.', array('%name' => $name, '%unsubscribed' => $subscribers)), 'warning'); } if (!empty($unsubscribed)) { drupal_set_message(t("If you would like to resubscribe them, use the 'Force resubscription' option."), 'warning'); } // Return to the parent page. $form_state->setRedirect('view.simplenews_subscribers.page_1'); }
/** * {@inheritdoc} */ public function getMails($limit = self::UNLIMITED, $conditions = array()) { $messages = array(); // Continue to support 'nid' as a condition. if (!empty($conditions['nid'])) { $conditions['entity_type'] = 'node'; $conditions['entity_id'] = $conditions['nid']; unset($conditions['nid']); } // Add default status condition if not set. if (!isset($conditions['status'])) { $conditions['status'] = array(SpoolStorageInterface::STATUS_PENDING, SpoolStorageInterface::STATUS_IN_PROGRESS); } // Special case for the status condition, the in progress actually only // includes spool items whose locking time has expired. So this need to build // an OR condition for them. $status_or = new Condition('OR'); $statuses = is_array($conditions['status']) ? $conditions['status'] : array($conditions['status']); foreach ($statuses as $status) { if ($status == SpoolStorageInterface::STATUS_IN_PROGRESS) { $status_or->condition((new Condition('AND'))->condition('status', $status)->condition('s.timestamp', $this->getExpirationTime(), '<')); } else { $status_or->condition('status', $status); } } unset($conditions['status']); $query = $this->connection->select('simplenews_mail_spool', 's')->fields('s')->condition($status_or)->orderBy('s.timestamp', 'ASC'); // Add conditions. foreach ($conditions as $field => $value) { $query->condition($field, $value); } /* BEGIN CRITICAL SECTION */ // The semaphore ensures that multiple processes get different message ID's, // so that duplicate messages are not sent. if ($this->lock->acquire('simplenews_acquire_mail')) { // Get message id's // Allocate messages if ($limit > 0) { $query->range(0, $limit); } foreach ($query->execute() as $message) { if (Unicode::strlen($message->data)) { $message->data = unserialize($message->data); } else { $message->data = simplenews_subscriber_load_by_mail($message->mail); } $messages[$message->msid] = $message; } if (count($messages) > 0) { // Set the state and the timestamp of the messages $this->updateMails(array_keys($messages), array('status' => SpoolStorageInterface::STATUS_IN_PROGRESS)); } $this->lock->release('simplenews_acquire_mail'); } /* END CRITICAL SECTION */ return new SpoolList($messages); }
/** * {@inheritdoc} */ public function sendConfirmations() { foreach ($this->confirmations as $mail => $changes) { $subscriber = simplenews_subscriber_load_by_mail($mail); if (!$subscriber) { $subscriber = Subscriber::create(array()); $subscriber->setMail($mail); $subscriber->setLangcode($this->languageManager->getCurrentLanguage()); $subscriber->save(); } $subscriber->setChanges($changes); $this->mailer->sendCombinedConfirmation($subscriber); // Save the changes in the subscriber if there is a real subscriber object. if ($subscriber && $subscriber->id()) { $subscriber->save(); } } $sent = !empty($this->confirmations); $this->confirmations = array(); return $sent; }
/** * testSubscribeAuthenticated * * Steps performed: * 0. Preparation * 1. Subscribe authenticated via block * 2. Unsubscribe authenticated via subscription page * 3. Subscribe authenticated via subscription page * 4. Unsubscribe authenticated via account page * 5. Subscribe authenticated via account page * 6. Subscribe authenticated via multi block */ function testSubscribeAuthenticated() { // 0. Preparation // Login admin // Set permission for anonymous to subscribe // Enable newsletter block // Logout admin // Login Subscriber $admin_user = $this->drupalCreateUser(array('administer blocks', 'administer content types', 'administer nodes', 'access administration pages', 'administer permissions', 'administer newsletters')); $this->drupalLogin($admin_user); // Create some newsletters for multi-sign up block. $this->drupalGet('admin/config/services/simplenews'); for ($i = 0; $i < 5; $i++) { $this->clickLink(t('Add newsletter')); $name = $this->randomMachineName(); $edit = array('name' => $name, 'id' => strtolower($name), 'description' => $this->randomString(20), 'opt_inout' => 'double'); $this->drupalPostForm(NULL, $edit, t('Save')); } $newsletter_id = $this->getRandomNewsletter(); $this->drupalLogout(); // Setup subscription block with subscription form. $block_settings = array('newsletters' => array($newsletter_id), 'message' => $this->randomMachineName(4)); $single_block = $this->setupSubscriptionBlock($block_settings); $subscriber_user = $this->drupalCreateUser(array('subscribe to newsletters')); $this->drupalLogin($subscriber_user); // 1. Subscribe authenticated via block // Subscribe + submit // Assert confirmation message $this->drupalPostForm(NULL, [], t('Subscribe')); $this->assertText(t('You have been subscribed.'), t('Authenticated user subscribed using the subscription block.')); // 2. Unsubscribe authenticated via subscription page // Unsubscribe + submit // Assert confirmation message $edit = array("subscriptions[{$newsletter_id}]" => 0); $this->drupalPostForm('newsletter/subscriptions', $edit, t('Update')); $this->assertRaw(t('The newsletter subscriptions for %mail have been updated.', array('%mail' => $subscriber_user->getEmail())), t('Authenticated user unsubscribed on the subscriptions page.')); // 3. Subscribe authenticated via subscription page // Subscribe + submit // Assert confirmation message $edit = array("subscriptions[{$newsletter_id}]" => '1'); $this->drupalPostForm('newsletter/subscriptions', $edit, t('Update')); $this->assertRaw(t('The newsletter subscriptions for %mail have been updated.', array('%mail' => $subscriber_user->getEmail())), t('Authenticated user subscribed on the subscriptions page.')); // 4. Unsubscribe authenticated via account page // Unsubscribe + submit // Assert confirmation message $edit = array("subscriptions[{$newsletter_id}]" => FALSE); $url = 'user/' . $subscriber_user->id() . '/simplenews'; $this->drupalPostForm($url, $edit, t('Save')); $this->assertRaw(t('Your newsletter subscriptions have been updated.', array('%mail' => $subscriber_user->getEmail())), t('Authenticated user unsubscribed on the account page.')); $subscriber = simplenews_subscriber_load_by_mail($subscriber_user->getEmail()); $subscription = $subscriber->getSubscription($newsletter_id); $this->assertEqual(SIMPLENEWS_SUBSCRIPTION_STATUS_UNSUBSCRIBED, $subscription->status, t('Subscription is unsubscribed')); // 5. Subscribe authenticated via account page // Subscribe + submit // Assert confirmation message $edit = array("subscriptions[{$newsletter_id}]" => '1'); $url = 'user/' . $subscriber_user->id() . '/simplenews'; $this->drupalPostForm($url, $edit, t('Save')); $this->assertRaw(t('Your newsletter subscriptions have been updated.', array('%mail' => $subscriber_user->getEmail())), t('Authenticated user unsubscribed on the account page.')); // Disable the newsletter block. $single_block->delete(); // Setup subscription block with subscription form. $block_settings = array('newsletters' => array_keys(simplenews_newsletter_get_all()), 'message' => $this->randomMachineName(4)); $multi_block = $this->setupSubscriptionBlock($block_settings); // Try to submit multi-signup form without selecting a newsletter. $subscriber_user2 = $this->drupalCreateUser(array('subscribe to newsletters')); $this->drupalLogin($subscriber_user2); // Check that the user has only access to his own subscriptions page. $this->drupalGet('user/' . $subscriber_user->id() . '/simplenews'); $this->assertResponse(403); $this->drupalGet('user/' . $subscriber_user2->id() . '/simplenews'); $this->assertResponse(200); $this->assertNoField('mail[0][value]'); $this->drupalPostForm(NULL, array(), t('Update')); $this->assertText(t('The newsletter subscriptions for @mail have been updated.', array('@mail' => $subscriber_user2->getEmail()))); // Nothing should have happened. $this->assertNoFieldChecked('edit-subscriptions-' . $newsletter_id); // Now fill out the form and try again. $edit = array('subscriptions[' . $newsletter_id . ']' => TRUE); $this->drupalPostForm(NULL, $edit, t('Update')); $this->assertText(t('The newsletter subscriptions for @mail have been updated.', array('@mail' => $subscriber_user2->getEmail()))); $this->assertFieldChecked('edit-subscriptions-' . $newsletter_id); // Unsubscribe. $edit = array('subscriptions[' . $newsletter_id . ']' => FALSE); $this->drupalPostForm(NULL, $edit, t('Update')); $this->assertText(t('The newsletter subscriptions for @mail have been updated.', array('@mail' => $subscriber_user2->getEmail()))); $this->assertNoFieldChecked('edit-subscriptions-' . $newsletter_id); // And now the same for the newsletter/subscriptions page. $subscriber_user3 = $this->drupalCreateUser(array('subscribe to newsletters')); $this->drupalLogin($subscriber_user3); $this->assertNoField('mail[0][value]'); $this->drupalPostForm('newsletter/subscriptions', array(), t('Update')); $this->assertText(t('The newsletter subscriptions for @mail have been updated.', array('@mail' => $subscriber_user3->getEmail()))); // Nothing should have happened. $this->assertNoFieldChecked('edit-subscriptions-' . $newsletter_id); // Now fill out the form and try again. $edit = array('subscriptions[' . $newsletter_id . ']' => TRUE); $this->drupalPostForm('newsletter/subscriptions', $edit, t('Update')); $this->assertText(t('The newsletter subscriptions for @mail have been updated.', array('@mail' => $subscriber_user3->getEmail()))); $this->assertFieldChecked('edit-subscriptions-' . $newsletter_id); // Unsubscribe. $edit = array('subscriptions[' . $newsletter_id . ']' => FALSE); $this->drupalPostForm('newsletter/subscriptions', $edit, t('Update')); $this->assertText(t('The newsletter subscriptions for @mail have been updated.', array('@mail' => $subscriber_user3->getEmail()))); $this->assertNoFieldChecked('edit-subscriptions-' . $newsletter_id); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { // Subclasses try to load an existing subscriber in different ways in // buildForm. For anonymous user the email is unknown in buildForm, but here // we can try again to load an existing subscriber. $mail = $form_state->getValue(array('mail', 0, 'value')); if ($this->entity->isNew() && isset($mail) && ($subscriber = simplenews_subscriber_load_by_mail($mail))) { $this->setEntity($subscriber); } parent::submitForm($form, $form_state); }
/** * Test with disabled caching. */ function testSendMissingSubscriber() { $this->setUpSubscribers(1); $edit = array('title[0][value]' => $this->randomString(10), 'body[0][value]' => "Mail token: <strong>[simplenews-subscriber:mail]</strong>", 'simplenews_issue' => 'default'); $this->drupalPostForm('node/add/simplenews_issue', $edit, 'Save and publish'); $this->assertTrue(preg_match('|node/(\\d+)$|', $this->getUrl(), $matches), 'Node created'); $node = Node::load($matches[1]); // Add node to spool. \Drupal::service('simplenews.spool_storage')->addFromEntity($node); // Delete the subscriber. $subscriber = simplenews_subscriber_load_by_mail(reset($this->subscribers)); $subscriber->delete(); \Drupal::service('simplenews.mailer')->sendSpool(); // Make sure that no mails have been sent. $this->assertEqual(0, count($this->drupalGetMails())); $spool_row = db_query('SELECT * FROM {simplenews_mail_spool}')->fetchObject(); $this->assertEqual(SpoolStorageInterface::STATUS_DONE, $spool_row->status); }
/** * {@inheritdoc} */ public function sendTest(NodeInterface $node, array $test_addresses) { // Force the current user to anonymous to ensure consistent permissions. $this->accountSwitcher->switchTo(new AnonymousUserSession()); // Send the test newsletter to the test address(es) specified in the node. // Build array of test email addresses. // Send newsletter to test addresses. // Emails are send direct, not using the spool. $recipients = array('anonymous' => array(), 'user' => array()); foreach ($test_addresses as $mail) { $mail = trim($mail); if (!empty($mail)) { $subscriber = simplenews_subscriber_load_by_mail($mail); if (!$subscriber) { // @todo: Find a cleaner way to do this. $subscriber = Subscriber::create(array()); $subscriber->setUserId(0); $subscriber->setMail($mail); $subscriber->setLangcode(\Drupal::languageManager()->getCurrentLanguage()); } if ($subscriber->getUserId()) { $account = $subscriber->uid->entity; $recipients['user'][] = $account->getUserName() . ' <' . $mail . '>'; } else { $recipients['anonymous'][] = $mail; } $mail = new MailEntity($node, $subscriber, \Drupal::service('simplenews.mail_cache')); $mail->setKey('test'); $this->sendMail($mail); } } if (count($recipients['user'])) { $recipients_txt = implode(', ', $recipients['user']); drupal_set_message(t('Test newsletter sent to user %recipient.', array('%recipient' => $recipients_txt))); } if (count($recipients['anonymous'])) { $recipients_txt = implode(', ', $recipients['anonymous']); drupal_set_message(t('Test newsletter sent to anonymous %recipient.', array('%recipient' => $recipients_txt))); } $this->accountSwitcher->switchBack(); }
/** * Test newsletter subscription management. * * Steps performed: */ function testSubscriptionManagement() { $admin_user = $this->drupalCreateUser(array('administer newsletters', 'administer simplenews settings', 'administer simplenews subscriptions', 'administer users')); $this->drupalLogin($admin_user); // Create a newsletter. $newsletter_name = Unicode::strtolower($this->randomMachineName()); $edit = array('name' => $newsletter_name, 'id' => $newsletter_name); $this->drupalPostForm('admin/config/services/simplenews/add', $edit, t('Save')); // Add a number of users to each newsletter separately and then add another // bunch to both. $subscribers = array(); $groups = array(); $newsletters = simplenews_newsletter_get_all(); foreach ($newsletters as $newsletter) { $groups[$newsletter->id()] = array($newsletter->id()); } $groups['all'] = array_keys($groups); $subscribers_flat = array(); foreach ($groups as $key => $group) { for ($i = 0; $i < 5; $i++) { $mail = $this->randomEmail(); $subscribers[$key][$mail] = $mail; $subscribers_flat[$mail] = $mail; } } // Create a user and assign him one of the mail addresses of the all group. $user = $this->drupalCreateUser(array('subscribe to newsletters')); // Make sure that user_save() does not update the user object, as it will // override the pass_raw property which we'll need to log this user in // later on. $user_mail = current($subscribers['all']); $user->setEmail($user_mail); $user->save(); $delimiters = array(',', ' ', "\n"); // Visit subscribers by clicking menu tab in people. $this->drupalGet('admin/people'); $this->clickLink('Subscribers'); $i = 0; foreach ($groups as $key => $group) { $this->clickLink(t('Mass subscribe')); $edit = array('emails' => implode($delimiters[$i++], $subscribers[$key])); foreach ($group as $newsletter_id) { $edit['newsletters[' . $newsletter_id . ']'] = TRUE; } $this->drupalPostForm(NULL, $edit, t('Subscribe')); } // The user to which the mail was assigned should be listed too. $this->assertText($user->label()); // Verify that all addresses are displayed in the table. $rows = $this->xpath('//tbody/tr'); $mail_addresses = array(); for ($i = 0; $i < count($subscribers_flat); $i++) { $mail_addresses[] = trim((string) $rows[$i]->td[0]); } $this->assertEqual(15, count($mail_addresses)); foreach ($mail_addresses as $mail_address) { $mail_address = (string) $mail_address; $this->assertTrue(isset($subscribers_flat[$mail_address])); unset($subscribers_flat[$mail_address]); } // All entries of the array should be removed by now. $this->assertTrue(empty($subscribers_flat)); reset($groups); $first = 'default'; $first_mail = array_rand($subscribers[$first]); $all_mail = array_rand($subscribers['all']); // Limit list to subscribers of the first newsletter only. // Build a flat list of the subscribers of this list. $subscribers_flat = array_merge($subscribers[$first], $subscribers['all']); $this->drupalGet('admin/people/simplenews', array('query' => array('subscriptions_target_id' => $first))); // Verify that all addresses are displayed in the table. $rows = $this->xpath('//tbody/tr'); $mail_addresses = array(); for ($i = 0; $i < count($subscribers_flat); $i++) { $mail_addresses[] = trim((string) $rows[$i]->td[0]); } $this->assertEqual(10, count($mail_addresses)); foreach ($mail_addresses as $mail_address) { $mail_address = (string) $mail_address; $this->assertTrue(isset($subscribers_flat[$mail_address])); unset($subscribers_flat[$mail_address]); } // All entries of the array should be removed by now. $this->assertTrue(empty($subscribers_flat)); // Filter a single mail address, the one assigned to a user. $edit = array('mail' => Unicode::substr(current($subscribers['all']), 0, 4)); $this->drupalGet('admin/people/simplenews', array('query' => array('mail' => $edit['mail']))); $rows = $this->xpath('//tbody/tr'); $this->assertEqual(1, count($rows)); $this->assertEqual(current($subscribers['all']), trim((string) $rows[0]->td[0])); $this->assertEqual($user->label(), trim((string) $rows[0]->td[1]->span)); // Reset the filter. $this->drupalGet('admin/people/simplenews'); // Test mass-unsubscribe, unsubscribe one from the first group and one from // the all group, but only from the first newsletter. unset($subscribers[$first][$first_mail]); $edit = array('emails' => $first_mail . ', ' . $all_mail, 'newsletters[' . $first . ']' => TRUE); $this->clickLink(t('Mass unsubscribe')); $this->drupalPostForm(NULL, $edit, t('Unsubscribe')); // The all mail is still displayed because it's still subscribed to the // second newsletter. Reload the page to get rid of the confirmation // message. $this->drupalGet('admin/people/simplenews'); $this->assertNoText($first_mail); $this->assertText($all_mail); // Limit to first newsletter, the all mail shouldn't be shown anymore. $this->drupalGet('admin/people/simplenews', array('query' => array('subscriptions_target_id' => $first))); $this->assertNoText($first_mail); $this->assertNoText($all_mail); // Check exporting. $this->clickLink(t('Export')); $this->drupalPostForm(NULL, array('newsletters[' . $first . ']' => TRUE), t('Export')); $export_field = $this->xpath($this->constructFieldXpath('name', 'emails')); $exported_mails = (string) $export_field[0]; foreach ($subscribers[$first] as $mail) { $this->assertTrue(strpos($exported_mails, $mail) !== FALSE, t('Mail address exported correctly.')); } foreach ($subscribers['all'] as $mail) { if ($mail != $all_mail) { $this->assertTrue(strpos($exported_mails, $mail) !== FALSE, t('Mail address exported correctly.')); } else { $this->assertFALSE(strpos($exported_mails, $mail) !== FALSE, t('Unsubscribed mail address not exported.')); } } // Only export unsubscribed mail addresses. $edit = array('subscribed[subscribed]' => FALSE, 'subscribed[unsubscribed]' => TRUE, 'newsletters[' . $first . ']' => TRUE); $this->drupalPostForm(NULL, $edit, t('Export')); $export_field = $this->xpath($this->constructFieldXpath('name', 'emails')); $exported_mails = (string) $export_field[0]; $exported_mails = explode(', ', $exported_mails); $this->assertEqual(2, count($exported_mails)); $this->assertTrue(in_array($all_mail, $exported_mails)); $this->assertTrue(in_array($first_mail, $exported_mails)); /** @var \Drupal\simplenews\Subscription\SubscriptionManagerInterface $subscription_manager */ $subscription_manager = \Drupal::service('simplenews.subscription_manager'); // Make sure there are unconfirmed subscriptions. $unconfirmed = array(); $unconfirmed[] = $this->randomEmail(); $unconfirmed[] = $this->randomEmail(); foreach ($unconfirmed as $mail) { $subscription_manager->subscribe($mail, $first, TRUE); } // Only export unconfirmed mail addresses. $edit = array('subscribed[subscribed]' => FALSE, 'subscribed[unconfirmed]' => TRUE, 'subscribed[unsubscribed]' => FALSE, 'newsletters[' . $first . ']' => TRUE); $this->drupalPostForm(NULL, $edit, t('Export')); $export_field = $this->xpath($this->constructFieldXpath('name', 'emails')); $exported_mails = (string) $export_field[0]; $exported_mails = explode(', ', $exported_mails); $this->assertEqual(2, count($exported_mails)); $this->assertTrue(in_array($unconfirmed[0], $exported_mails)); $this->assertTrue(in_array($unconfirmed[1], $exported_mails)); // Make sure the user is subscribed to the first newsletter_id. $subscription_manager->subscribe($user_mail, $first, FALSE); $before_count = simplenews_count_subscriptions($first); // Block the user. $user->block(); $user->save(); $this->drupalGet('admin/people/simplenews'); // Verify updated subscriptions count. drupal_static_reset('simplenews_count_subscriptions'); $after_count = simplenews_count_subscriptions($first); $this->assertEqual($before_count - 1, $after_count, t('Blocked users are not counted in subscription count.')); // Test mass subscribe with previously unsubscribed users. for ($i = 0; $i < 3; $i++) { $tested_subscribers[] = $this->randomEmail(); } $subscription_manager->subscribe($tested_subscribers[0], $first, FALSE); $subscription_manager->subscribe($tested_subscribers[1], $first, FALSE); $subscription_manager->unsubscribe($tested_subscribers[0], $first, FALSE); $subscription_manager->unsubscribe($tested_subscribers[1], $first, FALSE); $unsubscribed = implode(', ', array_slice($tested_subscribers, 0, 2)); $edit = array('emails' => implode(', ', $tested_subscribers), 'newsletters[' . $first . ']' => TRUE); $this->drupalPostForm('admin/people/simplenews/import', $edit, t('Subscribe')); \Drupal::entityManager()->getStorage('simplenews_subscriber')->resetCache(); $subscription_manager->reset(); $this->assertFalse($subscription_manager->isSubscribed($tested_subscribers[0], $first), t('Subscriber not resubscribed through mass subscription.')); $this->assertFalse($subscription_manager->isSubscribed($tested_subscribers[1], $first), t('Subscriber not resubscribed through mass subscription.')); $this->assertTrue($subscription_manager->isSubscribed($tested_subscribers[2], $first), t('Subscriber subscribed through mass subscription.')); $substitutes = array('@name' => SafeMarkup::checkPlain(simplenews_newsletter_load($first)->label()), '@mail' => $unsubscribed); $this->assertText(t('The following addresses were skipped because they have previously unsubscribed from @name: @mail.', $substitutes)); $this->assertText(t("If you would like to resubscribe them, use the 'Force resubscription' option.")); // Try to mass subscribe without specifying newsletters. $tested_subscribers[2] = $this->randomEmail(); $edit = array('emails' => implode(', ', $tested_subscribers), 'resubscribe' => TRUE); $this->drupalPostForm('admin/people/simplenews/import', $edit, t('Subscribe')); $this->assertText('Subscribe to field is required.'); // Test mass subscribe with previously unsubscribed users and force // resubscription. $tested_subscribers[2] = $this->randomEmail(); $edit = array('emails' => implode(', ', $tested_subscribers), 'newsletters[' . $first . ']' => TRUE, 'resubscribe' => TRUE); $this->drupalPostForm('admin/people/simplenews/import', $edit, t('Subscribe')); $subscription_manager->reset(); \Drupal::entityManager()->getStorage('simplenews_subscriber')->resetCache(); $this->assertTrue($subscription_manager->isSubscribed($tested_subscribers[0], $first, t('Subscriber resubscribed trough mass subscription.'))); $this->assertTrue($subscription_manager->isSubscribed($tested_subscribers[1], $first, t('Subscriber resubscribed trough mass subscription.'))); $this->assertTrue($subscription_manager->isSubscribed($tested_subscribers[2], $first, t('Subscriber subscribed trough mass subscription.'))); // Try to mass unsubscribe without specifying newsletters. $tested_subscribers[2] = $this->randomEmail(); $edit = array('emails' => implode(', ', $tested_subscribers)); $this->drupalPostForm('admin/people/simplenews/unsubscribe', $edit, t('Unsubscribe')); $this->assertText('Unsubscribe from field is required.'); // Create two blocks, to ensure that they are updated/deleted when a // newsletter is deleted. $only_first_block = $this->setupSubscriptionBlock(['newsletters' => [$first]]); $all_block = $this->setupSubscriptionBlock(['newsletters' => array_keys($groups)]); $enabled_newsletters = $all_block->get('settings')['newsletters']; $this->assertTrue(in_array($first, $enabled_newsletters)); // Delete newsletter. \Drupal::entityManager()->getStorage('simplenews_newsletter')->resetCache(); $this->drupalGet('admin/config/services/simplenews/manage/' . $first); $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, array(), t('Delete')); $this->assertText(t('All subscriptions to newsletter @newsletter have been deleted.', array('@newsletter' => $newsletters[$first]->name))); // Verify that all related data has been deleted/updated. $this->assertNull(Newsletter::load($first)); $this->assertNull(Block::load($only_first_block->id())); $all_block = Block::load($all_block->id()); $enabled_newsletters = $all_block->get('settings')['newsletters']; $this->assertFalse(in_array($first, $enabled_newsletters)); // Verify that all subscriptions of that newsletter have been removed. $this->drupalGet('admin/people/simplenews'); foreach ($subscribers[$first] as $mail) { $this->assertNoText($mail); } $this->clickLink(t('Edit'), 1); // Get the subscriber id from the path. $this->assertTrue(preg_match('|admin/people/simplenews/edit/(\\d+)\\?destination|', $this->getUrl(), $matches), 'Subscriber found'); $subscriber = Subscriber::load($matches[1]); $this->assertTitle(t('Edit subscriber @mail', array('@mail' => $subscriber->getMail())) . ' | Drupal'); $this->assertFieldChecked('edit-status'); // Disable account. $edit = array('status' => FALSE); $this->drupalPostForm(NULL, $edit, t('Save')); \Drupal::entityManager()->getStorage('simplenews_subscriber')->resetCache(); $subscription_manager->reset(); $this->assertFalse($subscription_manager->isSubscribed($subscriber->getMail(), $this->getRandomNewsletter()), t('Subscriber is not active')); // Re-enable account. $this->drupalGet('admin/people/simplenews/edit/' . $subscriber->id()); $this->assertTitle(t('Edit subscriber @mail', array('@mail' => $subscriber->getMail())) . ' | Drupal'); $this->assertNoFieldChecked('edit-status'); $edit = array('status' => TRUE); $this->drupalPostForm(NULL, $edit, t('Save')); \Drupal::entityManager()->getStorage('simplenews_subscriber')->resetCache(); $subscription_manager->reset(); $this->assertTrue($subscription_manager->isSubscribed($subscriber->getMail(), $this->getRandomNewsletter()), t('Subscriber is active again.')); // Remove the newsletter. $this->drupalGet('admin/people/simplenews/edit/' . $subscriber->id()); $this->assertTitle(t('Edit subscriber @mail', array('@mail' => $subscriber->getMail())) . ' | Drupal'); \Drupal::entityManager()->getStorage('simplenews_subscriber')->resetCache(); $subscriber = Subscriber::load($subscriber->id()); $nlids = $subscriber->getSubscribedNewsletterIds(); // If the subscriber still has subscribed to newsletter, try to unsubscribe. $newsletter_id = reset($nlids); $edit['subscriptions[' . $newsletter_id . ']'] = FALSE; $this->drupalPostForm(NULL, $edit, t('Save')); \Drupal::entityManager()->getStorage('simplenews_subscriber')->resetCache(); $subscription_manager->reset(); $nlids = $subscriber->getSubscribedNewsletterIds(); $this->assertFalse($subscription_manager->isSubscribed($subscriber->getMail(), reset($nlids)), t('Subscriber not subscribed anymore.')); // @todo Test Admin subscriber edit preferred language $subscription->language // Register a subscriber with an insecure e-mail address through the API // and make sure the address is correctly encoded. $xss_mail = "<script>alert('XSS');</script>"; $subscription_manager->subscribe($xss_mail, $this->getRandomNewsletter(), FALSE); $this->drupalGet('admin/people/simplenews'); $this->assertNoRaw($xss_mail); $this->assertRaw(SafeMarkup::checkPlain($xss_mail)); $xss_subscriber = simplenews_subscriber_load_by_mail($xss_mail); $this->drupalGet('admin/people/simplenews/edit/' . $xss_subscriber->id()); $this->assertNoRaw($xss_mail); $this->assertRaw(SafeMarkup::checkPlain($xss_mail)); // Create a new user for the next test. $new_user = $this->drupalCreateUser(array('subscribe to newsletters')); // Test for saving the subscription for no newsletter. $this->drupalPostForm('user/' . $new_user->id() . '/simplenews', null, t('Save')); $this->assertText('The newsletter subscriptions for user ' . $new_user->getUsername() . ' have been updated.'); // Editing a subscriber with subscription. $edit = array('subscriptions[' . $newsletter_name . ']' => TRUE, 'status' => TRUE, 'mail[0][value]' => '*****@*****.**'); $this->drupalPostForm('admin/people/simplenews/edit/' . $xss_subscriber->id(), $edit, t('Save')); $this->assertText('Subscriber edit@example.com has been updated.'); // Create a second newsletter. $second_newsletter_name = Unicode::strtolower($this->randomMachineName()); $edit2 = array('name' => $second_newsletter_name, 'id' => $second_newsletter_name); $this->drupalPostForm('admin/config/services/simplenews/add', $edit2, t('Save')); // Test for adding a subscriber. $subscribe = array('newsletters[' . $newsletter_name . ']' => TRUE, 'emails' => '*****@*****.**'); $this->drupalPostForm('admin/people/simplenews/import', $subscribe, t('Subscribe')); // The subscriber should appear once in the list. $rows = $this->xpath('//tbody/tr'); $counter = 0; foreach ($rows as $value) { if (trim((string) $value->td[0]) == '*****@*****.**') { $counter++; } } $this->assertEqual(1, $counter); $this->assertText(t('The following addresses were added or updated: @email.', ['@email' => '*****@*****.**'])); $this->assertText(t('The addresses were subscribed to the following newsletters: @newsletter.', ['@newsletter' => $newsletter_name])); // Check exact subscription statuses. $subscriber = simplenews_subscriber_load_by_mail('*****@*****.**'); $this->assertEqual($subscriber->getSubscription($newsletter_name)->get('status')->getValue(), SIMPLENEWS_SUBSCRIPTION_STATUS_SUBSCRIBED); // The second newsletter was not subscribed, so there should be no // subscription record at all. $this->assertFalse($subscriber->getSubscription($second_newsletter_name)); }