diff --git a/includes/simplenews.admin.inc b/includes/simplenews.admin.inc index 1ed89b7..8df9bd0 100644 --- a/includes/simplenews.admin.inc +++ b/includes/simplenews.admin.inc @@ -1332,7 +1332,7 @@ function simplenews_admin_settings_newsletter($form, &$form_state) { '#description' => t('These options will be the defaults for new newsletters, but can be overridden in the newsletter editing form.'), ); $description = t('Default newsletter format.'); - if (!module_exists('mimemail')) { + if (!simplenews_html_transmitter_modules()) { $description .= ' ' . t('Install Mime Mail module or HTML Mail module to send newsletters in HTML format.', array('!mime_mail_url' => 'http://drupal.org/project/mimemail', '!html_url' => 'http://drupal.org/project/htmlmail') ); diff --git a/includes/simplenews.mail.inc b/includes/simplenews.mail.inc index 1506284..5162fef 100644 --- a/includes/simplenews.mail.inc +++ b/includes/simplenews.mail.inc @@ -195,7 +195,7 @@ function simplenews_mail_mail($msgbase, $key = 'node') { // Optional params for Mime Mail. $params['plain'] = $params['context']['category']->format == 'plain' ? TRUE : NULL; // @todo Create the plaintext portion of the message, we don't have $message['body'] here. - // $params['plaintext'] = $params['plain'] ? $message['body'] : simplenews_html_to_text($message['body'], TRUE); + //$params['plaintext'] = $params['plain'] ? $message['body'] : simplenews_html_to_text($message['body'], TRUE); // @todo Get the attachments. Upload module no longer exists for Drupal 7. // $params['attachments'] = isset($params['context']['node']->files) ? $params['context']['node']->files : array();; diff --git a/simplenews.install b/simplenews.install index 9857024..b183d11 100644 --- a/simplenews.install +++ b/simplenews.install @@ -341,6 +341,16 @@ function simplenews_install() { _simplenews_install_nodetype(); } +/* + * Enable plaintext widget module if there are any + * HTML mail transmission modules available. + */ +function simplenews_enable() { + if (simplenews_html_transmitter_modules()) { + module_enable(array('simplenews_plaintext')); + } +} + /** * Implement hook_uninstall(). */ diff --git a/simplenews.module b/simplenews.module index 30841f4..bf3eaeb 100644 --- a/simplenews.module +++ b/simplenews.module @@ -662,13 +662,23 @@ function simplenews_get_category_field($bundle_name) { } /** - * Implementation of hook_form_FORM_ID_alter(). + * Implements hook_form_FORM_ID_alter(). * * Add checkbox to the content type form to use the content type as newsletter. + * Add Selectbox for plaintext field selection. */ function simplenews_form_node_type_form_alter(&$form, $form_state) { - // Add option to use content type as simplenews newsletter. - $form['workflow']['simplenews_content_type'] = array( + + $form['simplenews'] = array( + '#type' => 'fieldset', + '#title' => 'Newsletter', + '#collapsible' => TRUE, + '#collapsed' => FALSE, + '#group' => 'additional_settings', + ); + + // Add option to use content type as simplenews newsletter. + $form['simplenews']['simplenews_content_type'] = array( '#type' => 'checkbox', '#title' => t('Use as simplenews newsletter'), '#default_value' => variable_get('simplenews_content_type_' . $form['#node_type']->type, 0), @@ -1838,7 +1848,6 @@ function simplenews_recent_newsletters($tid, $count = 5) { */ function simplenews_mail($key, &$message, $params) { $params['key'] = $key; - switch ($key) { case 'node': case 'test': @@ -1956,24 +1965,17 @@ function simplenews_build_node_mail(&$message, $params) { // i18n_selection_mode('node', $node->language); // } - // Build message body -// @todo move this code to a function. We need to do this twice for HTML and Plain text Alternative. - // @todo restore the format selection. - //$build = node_view($node, 'email_' . $category->format); - // Supported view modes: 'email_plain', 'email_html', 'email_textalt' - $build = node_view($node, 'email_plain'); - // @todo Use simplenews_newsletter_body as #theme? - unset($build['#theme']); - foreach (element_children($build) as $child) { - $build[$child]['#theme'] = 'simplenews_field'; - } -// END move this code to a function. - + $build = simplenews_build_message_body($category->format, $node); $body = theme('simplenews_newsletter_body', array('build' => $build, 'category' => $category, 'language' => $message['language'])); - // Buffer body text node and language specific $messages[$nid][$langcode]['body'] = $body; + /* + $plain_build = simplenews_build_message_body('plain'); + $plain_body = theme('simplenews_newsletter_body', array('build' => $plain_build, 'category' => $category, 'language' => $message['language'])); + $messages[$nid][$langcode]['plain_body'] = $plain_body; + */ + // @todo Move hidden footer into preprocess function. // We need to replace this concept. A footer is depending on the subscription list, not anymore on the newsletter category. // In the future this will also depend on whether the receiver is subscribed to a list or not a list member at all. @@ -2008,21 +2010,66 @@ function simplenews_build_node_mail(&$message, $params) { $footer = $messages[$nid][$langcode]['footer']; } - // Build message body, replace tokens. - // Convert to plain text if required. + // Build message body, replace tokens. Convert to plain text if required. + $field_plaintext = simplenews_get_plaintext_field_name($node->type); $message['body']['body'] = token_replace($body, $context, array('sanitize' => FALSE)); - if ($category->format == 'plain') { + if ($category->format == 'plain' && !trim($context['node']->{$field_plaintext}['und'][0]['value'])) { module_load_include('inc', 'simplenews', 'includes/simplenews.mail'); $message['body']['body'] = simplenews_html_to_text($message['body']['body'], $category->hyperlinks); } + else if ($category->format == 'plain') { + $body = theme('simplenews_newsletter_plaintext_body', array('node' => $context['node'], 'plain_field' => $field_plaintext)); + } // Build message footer, replace tokens. $message['body']['footer'] = token_replace($footer, $context, array('sanitize' => FALSE)); + // Get plaintext text field (i.e. plain text part to be added to multipart with mimemail) + if (isset($context['node']->{$field_plaintext}['und'])) { + $plain_text = trim($context['node']->{$field_plaintext}['und'][0]['value']) + ? theme('simplenews_newsletter_plaintext_body', array('node' => $context['node'], 'plain_field' => $field_plaintext)) + : simplenews_html_to_text($message['body']['body'], $category->hyperlinks); + } + $message['params']['plaintext'] = token_replace($plain_text, $context, array('sanitize' => FALSE)); + + // Add cleaned version of footer to plaintext alternative + $message['params']['plaintext'] .= simplenews_html_to_text(token_replace($footer, $context, array('sanitize' => FALSE))); + // Add user specific header data. $message['headers']['List-Unsubscribe'] = '<' . token_replace('[simplenews-subscriber:unsubscribe-url]', $context, array('sanitize' => FALSE)) . '>'; } +function simplenews_build_message_body($format, $node) { + // Build message body + // @todo restore the format selection. + //$build = node_view($node, 'email_' . $format); + $build = node_view($node, 'email_plain'); + + // @todo Use simplenews_newsletter_body as #theme? + unset($build['#theme']); + foreach (element_children($build) as $child) { + $build[$child]['#theme'] = 'simplenews_field'; + } + + return $build; + + /************ ORIG ******************** + // Build message body + // @todo move this code to a function. We need to do this twice for HTML and Plain text Alternative. + // @todo restore the format selection. + //$build = node_view($node, 'email_' . $category->format); + // Supported view modes: 'email_plain', 'email_html', 'email_textalt' + $build = node_view($node, 'email_plain'); + // @todo Use simplenews_newsletter_body as #theme? + unset($build['#theme']); + foreach (element_children($build) as $child) { + $build[$child]['#theme'] = 'simplenews_field'; + } + /********** /ORIG ***********************/ +} + +// END move this code to a function. + /** * Build subject and body of the subscribe confirmation email. * @@ -2655,7 +2702,7 @@ function simplenews_format_options() { $options = array( 'plain' => t('plain'), ); - if (module_exists('mimemail') || module_exists('htmlmail')) { + if (simplenews_html_transmitter_modules()) { $options['html'] = t('html'); } return $options; @@ -2810,6 +2857,12 @@ function simplenews_theme() { 'simplenews_field' => array( 'render element' => 'element', ), + 'simplenews_newsletter_plaintext_body' => array( + 'variables' => array( + 'node' => NULL, + 'plain_field' => NULL, + ), + ), ); } @@ -2966,6 +3019,12 @@ function template_preprocess_simplenews_newsletter_body(&$variables) { unset($variables['build']['links']); unset($variables['build']['comments']); + if ($variables['category']->format == 'html') { + // hide the plaintext field for html mails since the plaintext part has it's own theme function + $field_plaintext = simplenews_get_plaintext_field_name($variables['build']['#bundle']); + hide($variables['build'][$field_plaintext]); + } + $variables['title'] = check_plain($variables['build']['#node']->title); // Add specific suggestions that can override the default implementation. @@ -3030,6 +3089,21 @@ function theme_simplenews_newsletter_footer($variables) { return $output; } +/** +* Theme the newsletter message subject and alternative plaintext body. +*/ +function theme_simplenews_newsletter_plaintext_body($variables) { + // In an override of this function, $text can be loaded with other field from the node. + $text = $variables['node']->title . "\n\n"; + if ($variables['plain_field'] == 'body') { + $text .= $variables['node']->body['und'][0]['value'] . "\n\n"; + } + else { + $plain = $variables['node']->$variables['plain_field']; + $text .= $plain['und'][0]['value'] . "\n\n"; + } + return $text; +} /** * Helper function to filter checked boxes from form values. @@ -3345,3 +3419,39 @@ function simplenews_require_double_opt_in($tid, $account) { return $category->opt_inout == 'double'; } } + +/* + * Function either checks if a compatible transmitter + * module exists or gets all possible transmitter modules. + */ +function simplenews_html_transmitter_modules() { + + // @todo get this info by a hook that provides info about + // mail transmission modules + $transmitters = array( + 'mimemail', + 'htmlmail', + ); + + foreach($transmitters as $transmitter) { + if (module_exists($transmitter)) { + return TRUE; + } + } + return FALSE; +} + +/* + * Function gets the fieldname of an optional plaintext field. + * + * Note: At the moment only one (the first) plaintext field + * will be detected. + */ +function simplenews_get_plaintext_field_name($bundle) { + $fieldinfo = field_info_instances('node', $bundle); + foreach($fieldinfo as $field_name => $info) { + // check if field has a plaintext_textarea widget + if ($info['widget']['type'] != 'plaintext_textarea') continue; + else return $info['field_name']; + } +} diff --git a/simplenews_plaintext/simplenews_plaintext.info b/simplenews_plaintext/simplenews_plaintext.info new file mode 100644 index 0000000..8b118a5 --- /dev/null +++ b/simplenews_plaintext/simplenews_plaintext.info @@ -0,0 +1,6 @@ +name = Plaintext widget +description = Defines text field widget type for simplenews plaintext content. +package = Mail +core = 7.x +dependencies[] = simplenews +;files[] = text.test \ No newline at end of file diff --git a/simplenews_plaintext/simplenews_plaintext.js b/simplenews_plaintext/simplenews_plaintext.js new file mode 100644 index 0000000..82f8e61 --- /dev/null +++ b/simplenews_plaintext/simplenews_plaintext.js @@ -0,0 +1,9 @@ +(function ($) { + + // Defines an ajax command to replace content inside + // the plaintext field after serverside processing + Drupal.ajax.prototype.commands.replacecontent = function (ajax, response, status) { + $('#' + response.trigger).parent().find('textarea').val(response.plaintext); + } + +})(jQuery); diff --git a/simplenews_plaintext/simplenews_plaintext.module b/simplenews_plaintext/simplenews_plaintext.module new file mode 100644 index 0000000..1e55bc1 --- /dev/null +++ b/simplenews_plaintext/simplenews_plaintext.module @@ -0,0 +1,205 @@ + array( + 'label' => t('Textarea for Plaintext (multiple rows)'), + 'field types' => array('text_long'), + 'settings' => array('rows' => 20), + ), + ); +} + +/* + * Implements hook_field_create_instance(). + * + * Enables the display style 'email_plain' and sets the + * display of the created field in 'email_plain' to hidden. + */ +function simplenews_plaintext_field_create_instance($instance) { + + if ($instance['widget']['type'] == 'plaintext_textarea') { + $bundle_settings = array( + 'view_modes' => array( + 'email_plain' => array('custom_settings' => TRUE), + ), + ); + field_bundle_settings('node', $instance['bundle'], $bundle_settings); + + $instance['display']['email_plain'] = array( + 'label' => 'hidden', + 'type' => 'hidden', + ); + field_update_instance($instance); + } +} + +/** + * Implements hook_field_widget_settings_form(). + */ +function simplenews_plaintext_field_widget_settings_form($field, $instance) { + + $widget = $instance['widget']; + $settings = $widget['settings']; + + $form['rows'] = array( + '#type' => 'textfield', + '#title' => t('Rows'), + '#default_value' => $settings['rows'], + '#required' => TRUE, + '#element_validate' => array('element_validate_integer_positive'), + ); + + return $form; +} + +/** + * Implements hook_field_widget_form(). + * + * @todo: maybe integrate the elements of the widget into a fieldset for clearer visual presentation + */ +function simplenews_plaintext_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { + + $widget = array(); + + $widget['value'] = array( + '#type' => 'textarea', + '#title' => $instance['label'], + '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL, + '#rows' => $instance['widget']['settings']['rows'], + '#attributes' => array('class' => array('text-full')), + '#prefix' => '
', + '#suffix' => '
', + ); + + /* This doesn't work, had to load the js using hook_preprocess_page() (see code below) + $jspath = drupal_get_path('module', 'simplenews_plaintext') . '/simplenews_plaintext.js'; + $form['#attached']['js'] = array($jspath); || drupal_add_js($jspath, 'file'); + */ + + $widget['process_trigger'] = array( + '#type' => 'submit', + '#value' => t('Process'), // @todo maybe give the label a better text + '#ajax' => array( + 'callback' => 'simplenews_plaintext_process_plaintext_value', + 'progress' => array( + 'type' => 'bar', + 'message' => t('Please wait while your text is being processed on the server.') + ), + ), + ); + + $widget = $element + $widget; + + return $widget; +} + +function simplenews_plaintext_process_plaintext_value($form, $form_state) { + + // build a pseudonode to get all necessary field values + $node = $form_state['node']; + entity_form_submit_build_entity('node', $node, $form, $form_state); + node_submit($node); + + // gather plaintext values from relevant fields + /* + // the way miro wanted it to be done, unfortunately + // links like 'edit' or 'delete' get rendered too this way + $data = node_view($node, 'email_plain'); + $text = render($data); + */ + + // code below pulls the textdata out of $form_state directly + $text = ''; + $field_types = array('text', 'text_long', 'text_with_summary'); + foreach($form_state['field'] as $field_name => $field) { + // skip empty fields + if (!isset($form_state['values'][$field_name]['und'][0]['value']) || empty($form_state['values'][$field_name]['und'][0]['value'])) continue; + if (in_array($field['und']['field']['type'], $field_types) + && $field['und']['instance']['widget']['type'] != 'plaintext_textarea') { + $label = $field['und']['instance']['label']; + if (count($form_state['values'][$field_name]['und']) > 1) { + $text .= $label . '
'; + foreach($form_state['values'][$field_name]['und'] as $key => $val) { + $text .= '

' . t('Value') . ' ' . ($key + 1) . '
' . $val['value'] . '

'; + } + } + else { + $value = $form_state['values'][$field_name]['und'][0]['value']; + if ($field['und']['instance']['display']['email_plain']['label'] != 'hidden') { + $text .= '

' . $label . '
' . $value . '

'; + } + else { + $text .= '

' . $value . '

'; + } + } + } + } + + // convert html values of fields to plaintext + module_load_include('inc', 'simplenews', 'includes/simplenews.mail'); + $plaintext = simplenews_html_to_text($text); + + // send the plaintext value to a client side js command + return array( + '#type' => 'ajax', + '#commands' => array( + array( + 'command' => 'replacecontent', + 'plaintext' => $plaintext, + 'trigger' => $form_state['triggering_element']['#id'], + ), + ), + ); +} + +/* +function simplenews_plaintext_form_alter(&$form, &$form_state, $form_id) { + dsm($form_id); + //if ($form_id == 'article_node_form') { + $form['#after_build'] = array('_simplenews_plaintext_load_js'); + //} +} + +function _simplenews_plaintext_load_js($element) { + $jspath = drupal_get_path('module', 'simplenews_plaintext') . '/simplenews_plaintext.js'; + drupal_add_js($jspath, 'file'); + dsm($element); + return $element; +} +*/ + +/* + * Adds the js to the process_trigger button of the widget. + * + * @todo The JS should not be added on this way. Otherwise + * the JS gets loaded on every form without plaintext widget + * and even on every page without form. Tried to do it in the + * simplenews_plaintext_field_widget_form() function with ['#attached'] + * attribute as well as with drupal_add_js, both cases did not work. + * Even tried to load the JS in a corresponding form_alter hook, + * which also did not work (see code above). + */ +function simplenews_plaintext_preprocess_page(&$variables) { + $jspath = drupal_get_path('module', 'simplenews_plaintext') . '/simplenews_plaintext.js'; + drupal_add_js($jspath, 'file'); +}