/**
  * @param Newsletter $newsletter
  * @param Mailinglists $recipient
  * @param Boolean $fakeRecipient
  */
 function __construct($newsletter, $recipient, $fakeRecipient = false)
 {
     $this->newsletter = $newsletter;
     $this->mailinglists = $newsletter->MailingLists();
     $this->recipient = $recipient;
     $this->fakeRecipient = $fakeRecipient;
     parent::__construct($this->newsletter->SendFrom, $this->recipient->Email);
     $this->populateTemplate(new ArrayData(array('UnsubscribeLink' => $this->UnsubscribeLink(), 'SiteConfig' => DataObject::get_one('SiteConfig'), 'AbsoluteBaseURL' => Director::absoluteBaseURLWithAuth())));
     $this->body = $newsletter->getContentBody();
     $this->subject = $newsletter->Subject;
     $this->ss_template = $newsletter->RenderTemplate;
     if ($this->body && $this->newsletter) {
         $text = $this->body->forTemplate();
         //Recipient Fields ShortCode parsing
         $bodyViewer = new SSViewer_FromString($text);
         $text = $bodyViewer->process($this->templateData());
         // Install link tracking by replacing existing links with "newsletterlink" and hash-based reference.
         if ($this->config()->link_tracking_enabled && !$this->fakeRecipient && preg_match_all("/<a\\s[^>]*href=\"([^\"]*)\"[^>]*>(.*)<\\/a>/siU", $text, $matches)) {
             if (isset($matches[1]) && ($links = $matches[1])) {
                 $titles = isset($matches[2]) ? $matches[2] : array();
                 $id = (int) $this->newsletter->ID;
                 $replacements = array();
                 $current = array();
                 // workaround as we want to match the longest urls (/foo/bar/baz) before /foo/
                 array_unique($links);
                 $sorted = array_combine($links, array_map('strlen', $links));
                 arsort($sorted);
                 foreach ($sorted as $link => $length) {
                     $SQL_link = Convert::raw2sql($link);
                     $tracked = DataObject::get_one('Newsletter_TrackedLink', "\"NewsletterID\" = '" . $id . "' AND \"Original\" = '" . $SQL_link . "'");
                     if (!$tracked) {
                         // make one.
                         $tracked = new Newsletter_TrackedLink();
                         $tracked->Original = $link;
                         $tracked->NewsletterID = $id;
                         $tracked->write();
                     }
                     // replace the link
                     $replacements[$link] = $tracked->Link();
                     // track that this link is still active
                     $current[] = $tracked->ID;
                 }
                 // replace the strings
                 $text = str_ireplace(array_keys($replacements), array_values($replacements), $text);
             }
         }
         // replace the body
         $output = new HTMLText();
         $output->setValue($text);
         $this->body = $output;
     }
 }
 public function onBeforeSend()
 {
     $email = $this->owner;
     $letter = $email->Newsletter();
     $body = new SS_HTMLValue($email->Body()->forTemplate());
     $links = array();
     $member = null;
     if (!$body || !$letter) {
         return;
     }
     if ($email->To()) {
         $member = DataObject::get_one('Member', sprintf('"Email" = \'%s\'', Convert::raw2sql($email->To())));
     }
     // First build up a set of all the unique links within the newsletter,
     // along with the elements that link to them.
     foreach ($body->getElementsByTagName('a') as $link) {
         $href = $link->getAttribute('href');
         if (strpos($href, '{$') !== false || strpos($href, 'mailto:') !== false) {
             // ignore links with keywords
             continue;
         }
         if (array_key_exists($href, $links)) {
             $links[$href][] = $link;
         } else {
             $links[$href] = array($link);
         }
     }
     // Then actually do the processing. Create a unique tracking object for
     // each link. Attempt to embed a member-specific tracking token if
     // the newsletter is being sent to a member.
     foreach ($links as $href => $elements) {
         $track = DataObject::get_one('Newsletter_TrackedLink', sprintf('"NewsletterID" = %d AND "Original" = \'%s\'', $letter->ID, Convert::raw2sql($href)));
         if (!$track) {
             $track = new Newsletter_TrackedLink();
             $track->Original = $href;
             $track->NewsletterID = $letter->ID;
             $track->write();
         }
         if ($member) {
             $trackHref = Controller::join_links(Director::baseURL(), 'newsletter-link', $member->NewsletterTrackingToken, $track->Hash);
         } else {
             $trackHref = Controller::join_links(Director::baseURL(), 'newsletter-link', $track->Hash);
         }
         foreach ($elements as $element) {
             $element->setAttribute('href', $trackHref);
         }
     }
     $dom = $body->getDocument();
     $email->setBody(DBField::create('HTMLText', $dom->saveHTML()));
 }
 /**
  * Rewrite the links
  *
  * @param NewsletterEmail
  */
 function updateNewsletterEmail(&$email)
 {
     if (!$email->body || !$email->newsletter) {
         return;
     }
     $text = $email->body->forTemplate();
     // find all the matches
     if (preg_match_all("/<a\\s[^>]*href=\"([^\"]*)\"[^>]*>(.*)<\\/a>/siU", $text, $matches)) {
         if (isset($matches[1]) && ($links = $matches[1])) {
             $titles = isset($matches[2]) ? $matches[2] : array();
             $id = (int) $email->newsletter->ID;
             $replacements = array();
             $current = array();
             // workaround as we want to match the longest urls (/foo/bar/baz) before /foo/
             array_unique($links);
             $sorted = array_combine($links, array_map('strlen', $links));
             arsort($sorted);
             foreach ($sorted as $link => $length) {
                 $SQL_link = Convert::raw2sql($link);
                 $tracked = DataObject::get_one('Newsletter_TrackedLink', "\"NewsletterID\" = '" . $id . "' AND \"Original\" = '" . $SQL_link . "'");
                 if (!$tracked) {
                     // make one.
                     $tracked = new Newsletter_TrackedLink();
                     $tracked->Original = $link;
                     $tracked->NewsletterID = $id;
                     $tracked->write();
                 }
                 // replace the link
                 $replacements[$link] = $tracked->Link();
                 // track that this link is still active
                 $current[] = $tracked->ID;
             }
             // replace the strings
             $text = str_ireplace(array_keys($replacements), array_values($replacements), $text);
             // replace the body
             $output = new HTMLText();
             $output->setValue($text);
             $email->body = $output;
         }
     }
 }