/** * @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; } } }