class SimplenewsSourceNode in Simplenews 7
Same name and namespace in other branches
- 7.2 includes/simplenews.source.inc \SimplenewsSourceNode
Simplenews source implementation based on nodes for a single subscriber.
Hierarchy
- class \SimplenewsSourceNode implements SimplenewsSourceNodeInterface
Expanded class hierarchy of SimplenewsSourceNode
Related topics
1 string reference to 'SimplenewsSourceNode'
- SimplenewsSpool::getSourceImplementation in includes/
simplenews.source.inc - Return the Simplenews source implementation for the given mail spool row.
File
- includes/
simplenews.source.inc, line 342 - Contains SimplenewsSource interface and implementations.
View source
class SimplenewsSourceNode implements SimplenewsSourceNodeInterface {
/**
* The node object.
*/
protected $node;
/**
* The cached build render array.
*/
protected $build;
/**
* The newsletter category.
*/
protected $category;
/**
* The subscriber and therefore recipient of this mail.
*/
protected $subscriber;
/**
* The mail key used for drupal_mail().
*/
protected $key = 'test';
/**
* The simplenews newsletter.
*/
protected $newsletter;
/**
* Cache implementation used for this source.
*
* @var SimplenewsSourceCacheInterface
*/
protected $cache;
/**
* Implements SimplenewsSourceInterface::_construct();
*/
public function __construct($node, $subscriber) {
$this
->setSubscriber($subscriber);
$this
->setNode($node);
$this->newsletter = simplenews_newsletter_load($node->nid);
$this->category = simplenews_category_load($this->newsletter->tid);
$this
->initCache();
}
/**
* Set the node of this source.
*
* If the node is part of a translation set, switch to the node for the
* requested language, if existent.
*/
public function setNode($node) {
$langcode = $this
->getLanguage();
$nid = $node->nid;
if (module_exists('translation')) {
// If the node has translations and a translation is required
// the equivalent of the node in the required language is used
// or the base node (nid == tnid) is used.
if ($tnid = $node->tnid) {
if ($langcode != $node->language) {
$translations = translation_node_get_translations($tnid);
// A translation is available in the preferred language.
if ($translation = $translations[$langcode]) {
$nid = $translation->nid;
$langcode = $translation->language;
}
else {
// No translation found which matches the preferred language.
foreach ($translations as $translation) {
if ($translation->nid == $tnid) {
$nid = $tnid;
$langcode = $translation->language;
break;
}
}
}
}
}
}
// If a translation of the node is used, load this node.
if ($nid != $node->nid) {
$this->node = node_load($nid);
}
else {
$this->node = $node;
}
}
/**
* Initialize the cache implementation.
*/
protected function initCache() {
$class = variable_get('simplenews_source_cache', 'SimplenewsSourceCacheBuild');
$this->cache = new $class($this);
}
/**
* Returns the corresponding category.
*/
public function getCategory() {
return $this->category;
}
/**
* Set the active subscriber.
*/
public function setSubscriber($subscriber) {
$this->subscriber = $subscriber;
}
/**
* Return the subscriber object.
*/
public function getSubscriber() {
return $this->subscriber;
}
/**
* Implements SimplenewsSourceInterface::getHeaders().
*/
public function getHeaders(array $headers) {
// If receipt is requested, add headers.
if ($this->category->receipt) {
$headers['Disposition-Notification-To'] = $this
->getFromAddress();
$headers['X-Confirm-Reading-To'] = $this
->getFromAddress();
}
// Add priority if set.
switch ($this->category->priority) {
case SIMPLENEWS_PRIORITY_HIGHEST:
$headers['Priority'] = 'High';
$headers['X-Priority'] = '1';
$headers['X-MSMail-Priority'] = 'Highest';
break;
case SIMPLENEWS_PRIORITY_HIGH:
$headers['Priority'] = 'urgent';
$headers['X-Priority'] = '2';
$headers['X-MSMail-Priority'] = 'High';
break;
case SIMPLENEWS_PRIORITY_NORMAL:
$headers['Priority'] = 'normal';
$headers['X-Priority'] = '3';
$headers['X-MSMail-Priority'] = 'Normal';
break;
case SIMPLENEWS_PRIORITY_LOW:
$headers['Priority'] = 'non-urgent';
$headers['X-Priority'] = '4';
$headers['X-MSMail-Priority'] = 'Low';
break;
case SIMPLENEWS_PRIORITY_LOWEST:
$headers['Priority'] = 'non-urgent';
$headers['X-Priority'] = '5';
$headers['X-MSMail-Priority'] = 'Lowest';
break;
}
// Add user specific header data.
$headers['From'] = $this
->getFromFormatted();
$headers['List-Unsubscribe'] = '<' . token_replace('[simplenews-subscriber:unsubscribe-url]', $this
->getTokenContext(), array(
'sanitize' => FALSE,
)) . '>';
// Add general headers
$headers['Precedence'] = 'bulk';
return $headers;
}
/**
* Implements SimplenewsSourceInterface::getTokenContext().
*/
function getTokenContext() {
return array(
'category' => $this
->getCategory(),
'simplenews_subscriber' => $this
->getSubscriber(),
'node' => $this
->getNode(),
);
}
/**
* Set the mail key.
*/
function setKey($key) {
$this->key = $key;
}
/**
* Implements SimplenewsSourceInterface::getKey().
*/
function getKey() {
return $this->key;
}
/**
* Implements SimplenewsSourceInterface::getFromFormatted().
*/
function getFromFormatted() {
// Windows based PHP systems don't accept formatted email addresses.
if (drupal_substr(PHP_OS, 0, 3) == 'WIN') {
return $this
->getFromAddress();
}
return '"' . addslashes(mime_header_encode($this
->getCategory()->from_name)) . '" <' . $this
->getFromAddress() . '>';
}
/**
* Implements SimplenewsSourceInterface::getFromAddress().
*/
function getFromAddress() {
return $this
->getCategory()->from_address;
}
/**
* Implements SimplenewsSourceInterface::getRecipient().
*/
function getRecipient() {
return $this
->getSubscriber()->mail;
}
/**
* Implements SimplenewsSourceInterface::getFormat().
*/
function getFormat() {
return $this
->getCategory()->format;
}
/**
* Implements SimplenewsSourceInterface::getLanguage().
*/
function getLanguage() {
return $this
->getSubscriber()->language;
}
/**
* Implements SimplenewsSourceSpoolInterface::getNode().
*/
function getNode() {
return $this->node;
}
/**
* Implements SimplenewsSourceInterface::getSubject().
*/
function getSubject() {
// Build email subject and perform some sanitizing.
$langcode = $this
->getLanguage();
$language_list = language_list();
// Use the requested language if enabled.
$language = isset($language_list[$langcode]) ? $language_list[$langcode] : NULL;
$subject = token_replace($this
->getCategory()->email_subject, $this
->getTokenContext(), array(
'sanitize' => FALSE,
'language' => $language,
));
// Line breaks are removed from the email subject to prevent injection of
// malicious data into the email header.
$subject = str_replace(array(
"\r",
"\n",
), '', $subject);
return $subject;
}
/**
* Set up the necessary language and user context.
*/
protected function setContext() {
// Switch to the user
if ($this->uid = $this
->getSubscriber()->uid) {
simplenews_impersonate_user($this->uid);
}
// Change language if the requested language is enabled.
$language = $this
->getLanguage();
$languages = language_list();
if (isset($languages[$language])) {
$this->original_language = $GLOBALS['language'];
$GLOBALS['language'] = $languages[$language];
$GLOBALS['language_url'] = $languages[$language];
// Overwrites the current content language for i18n_select.
if (module_exists('i18n_select')) {
$GLOBALS['language_content'] = $languages[$language];
}
}
}
/**
* Reset the context.
*/
protected function resetContext() {
// Switch back to the previous user.
if ($this->uid) {
simplenews_revert_user();
}
// Switch language back.
if (!empty($this->original_language)) {
$GLOBALS['language'] = $this->original_language;
$GLOBALS['language_url'] = $this->original_language;
if (module_exists('i18n_select')) {
$GLOBALS['language_content'] = $this->original_language;
}
}
}
/**
* Build the node object.
*
* The resulting build array is cached as it is used in multiple places.
* @param $format
* (Optional) Override the default format. Defaults to getFormat().
*/
protected function build($format = NULL) {
if (empty($format)) {
$format = $this
->getFormat();
}
if (!empty($this->build[$format])) {
return $this->build[$format];
}
// Build message body
// Supported view modes: 'email_plain', 'email_html', 'email_textalt'
$build = node_view($this->node, 'email_' . $format);
unset($build['#theme']);
foreach (field_info_instances('node', $this->node->type) as $field_name => $field) {
if (isset($build[$field_name])) {
$build[$field_name]['#theme'] = 'simplenews_field';
}
}
$this->build[$format] = $build;
return $this->build[$format];
}
/**
* Build the themed newsletter body.
*
* @param $format
* (Optional) Override the default format. Defaults to getFormat().
*/
protected function buildBody($format = NULL) {
if (empty($format)) {
$format = $this
->getFormat();
}
if ($cache = $this->cache
->get('build', 'body:' . $format)) {
return $cache;
}
$body = theme('simplenews_newsletter_body', array(
'build' => $this
->build($format),
'category' => $this
->getCategory(),
'language' => $this
->getLanguage(),
'simplenews_subscriber' => $this
->getSubscriber(),
));
$this->cache
->set('build', 'body:' . $format, $body);
return $body;
}
/**
* Implements SimplenewsSourceInterface::getBody().
*/
public function getBody() {
return $this
->getBodyWithFormat($this
->getFormat());
}
/**
* Implements SimplenewsSourceInterface::getBody().
*/
public function getPlainBody() {
return $this
->getBodyWithFormat('plain');
}
/**
* Get the body with the requested format.
*
* @param $format
* Either html or plain.
*
* @return
* The rendered mail body as a string.
*/
protected function getBodyWithFormat($format) {
// Switch to correct user and language context.
$this
->setContext();
if ($cache = $this->cache
->get('final', 'body:' . $format)) {
return $cache;
}
$body = $this
->buildBody($format);
// Build message body, replace tokens.
$body = token_replace($body, $this
->getTokenContext(), array(
'sanitize' => FALSE,
));
if ($format == 'plain') {
// Convert HTML to text if requested to do so.
$body = simplenews_html_to_text($body, $this
->getCategory()->hyperlinks);
}
$this->cache
->set('final', 'body:' . $format, $body);
$this
->resetContext();
return $body;
}
/**
* Builds the themed footer.
*
* @param $format
* (Optional) Set the format of this footer build, overrides the default
* format.
*/
protected function buildFooter($format = NULL) {
if (empty($format)) {
$format = $this
->getFormat();
}
if ($cache = $this->cache
->get('build', 'footer:' . $format)) {
return $cache;
}
// Build and buffer message footer
$footer = theme('simplenews_newsletter_footer', array(
'build' => $this
->build($format),
'category' => $this
->getCategory(),
'context' => $this
->getTokenContext(),
'key' => $this
->getKey(),
'language' => $this
->getLanguage(),
'format' => $format,
));
$this->cache
->set('build', 'footer:' . $format, $footer);
return $footer;
}
/**
* Implements SimplenewsSourceInterface::getFooter().
*/
public function getFooter() {
return $this
->getFooterWithFormat($this
->getFormat());
}
/**
* Implements SimplenewsSourceInterface::getPlainFooter().
*/
public function getPlainFooter() {
return $this
->getFooterWithFormat('plain');
}
/**
* Get the footer in the specified format.
*
* @param $format
* Either html or plain.
*
* @return
* The footer for the requested format.
*/
protected function getFooterWithFormat($format) {
// Switch to correct user and language context.
$this
->setContext();
if ($cache = $this->cache
->get('final', 'footer:' . $format)) {
return $cache;
}
$final_footer = token_replace($this
->buildFooter($format), $this
->getTokenContext(), array(
'sanitize' => FALSE,
));
$this->cache
->set('final', 'footer:' . $format, $final_footer);
$this
->resetContext();
return $final_footer;
}
/**
* Implements SimplenewsSourceInterface::getAttachments().
*/
function getAttachments() {
if ($cache = $this->cache
->get('data', 'attachments')) {
return $cache;
}
$attachments = array();
$build = $this
->build();
$fids = array();
foreach (field_info_instances('node', $this->node->type) as $field_name => $field_instance) {
// @todo: Find a better way to support more field types.
// Only add fields of type file which are enabled for the current view
// mode as attachments.
$field = field_info_field($field_name);
if ($field['type'] == 'file' && isset($build[$field_name])) {
if ($items = field_get_items('node', $this->node, $field_name)) {
foreach ($items as $item) {
$fids[] = $item['fid'];
}
}
}
}
if (!empty($fids)) {
$attachments = file_load_multiple($fids);
}
$this->cache
->set('data', 'attachments', $attachments);
return $attachments;
}
}