diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index ef71a3a..bfd8bf4 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -30,4 +30,12 @@ Simplenews Scheduler 6.x-1.x-dev, 2009-09-16
 - Better code formatting and reviewed code with Coder module.
 - Modified taxonomy term saving with taxonomy_node_save() function.
 - New features: stop sending based on given date or number of editions.
-- Better multilingual support with included translation template.
\ No newline at end of file
+- Better multilingual support with included translation template.
+
+Simplenews Scheduler 7.x-1.x-dev, 2011-12-15
+--------------------------------------------
+- Code port do D7 API. I.e. DB queries were rewritten, hook_node_api replaced by different hook_node_OP hooks.
+- Process to create a newsletter edition is now done by cloning the node completely
+- JS file was removed since most effects can be achieved by using the #states property of the Drupal Form API
+- New DB field and form widget for interval frequency. It allows to schedule all 2 weeks, all 5 days etc.
+- Overview page is now a view. Views integration provides this by implementing hook_views_default_view().
\ No newline at end of file
diff --git a/README.txt b/README.txt
index 4f386ce..c21394d 100644
--- a/README.txt
+++ b/README.txt
@@ -45,3 +45,8 @@ Locate the module options under "Send newsletter" on the node edit page. When yo
 Current maintainers:
 * Leigh Morresi (dgtlmoon) - http://drupal.org/user/25027
 * Gabor Seljan (sgabe) - http://drupal.org/user/232117
+
+-- D7 RELEASE NOTES --
+
+A field for interval frequency was integrated. At the moment it's not possible to create
+a custom plaintext version of the newsletter for scheduled sending.
diff --git a/simplenews_scheduler.api.php b/simplenews_scheduler.api.php
new file mode 100644
index 0000000..77cdfe1
--- /dev/null
+++ b/simplenews_scheduler.api.php
@@ -0,0 +1,18 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Simplenews scheduler module.
+ */
+
+/**
+ * Alter the node object that was cloned from the template node before it gets saved.
+ *
+ * The node is passed as node object and therefore passed by reference. This hook 
+ * is for example usefull if you have fields in the template node that contain 
+ * information about data that should get rendered dynamically into the edition 
+ * node depenedent on the current schedule date.
+ */
+function hook_simplenews_scheduler_cloned_node_alter($node) {
+  $node->title = 'Your newsletter from ' . REQUEST_TIME;
+}
diff --git a/simplenews_scheduler.info b/simplenews_scheduler.info
index 75c0e11..48fc07a 100644
--- a/simplenews_scheduler.info
+++ b/simplenews_scheduler.info
@@ -1,7 +1,7 @@
 name = "Simplenews Scheduler"
 description = "Allows a schedule to be set for sending (and resending) a Simplenews item."
-core = 6.x
+core = 7.x
 package = Mail
 dependencies[] = simplenews
-dependencies[] = date_api
+dependencies[] = date
 dependencies[] = token
diff --git a/simplenews_scheduler.install b/simplenews_scheduler.install
index baaddd3..f6d82c4 100644
--- a/simplenews_scheduler.install
+++ b/simplenews_scheduler.install
@@ -6,14 +6,7 @@
  */
 
 /**
- * Implementation of hook_install().
- */
-function simplenews_scheduler_install() {
-  drupal_install_schema('simplenews_scheduler');
-}
-
-/**
- * Implementation of hook_schema().
+ * Implements hook_schema().
  */
 function simplenews_scheduler_schema() {
   $schema['simplenews_scheduler'] = array(
@@ -38,6 +31,11 @@ function simplenews_scheduler_schema() {
         'type' => 'varchar',
         'length' => 10,
       ),
+      'interval_frequency' => array(
+        'type' => 'int',
+        'default' => 1,
+        'not null' => TRUE,
+      ),
       'start_date' => array(
         'description' => 'The timestamp at which to start sending editions.',
         'type' => 'int',
@@ -94,106 +92,27 @@ function simplenews_scheduler_schema() {
   return $schema;
 }
 
-/**
- * Implementation of hook_uninstall().
- */
-function simplenews_scheduler_uninstall() {
-  // Remove tables.
-  drupal_uninstall_schema('simplenews_scheduler');
-}
-
-/**
- * Implementation of hook_update_N().
- */
-function simplenews_scheduler_update_6000() {
-  $ret = array();
-  db_add_field($ret, 'simplenews_scheduler', 'stop', array('type' => 'int', 'length' => 1, 'not null' => TRUE));
-  db_add_field($ret, 'simplenews_scheduler', 'stop_date', array('type' => 'int', 'length' => 11, 'not null' => TRUE, 'default' => 1577923199));
-  db_add_field($ret, 'simplenews_scheduler', 'stop_edition', array('type' => 'int', 'length' => 10, 'not null' => TRUE, 'default' => 0));
-  $ret[] = update_sql("ALTER TABLE {simplenews_scheduler} CHANGE sched_interval interval VARCHAR(10) NOT NULL DEFAULT '0'");
-  $ret[] = update_sql("ALTER TABLE {simplenews_scheduler} CHANGE sched_start start_date INT(11) NOT NULL DEFAULT '0'");
-  return $ret;
-}
-
-/**
- * Implementation of hook_update_N().
- */
-function simplenews_scheduler_update_6001() {
-  $ret = array();
-  db_drop_field($ret, 'simplenews_scheduler', 'sid');
-  db_add_field($ret, 'simplenews_scheduler', 'activated', array('type' => 'int', 'size' => 'tiny', 'not null' => TRUE, 'default' => 0));
-  $ret[] = update_sql("ALTER IGNORE TABLE {simplenews_scheduler} CHANGE snid nid INT(11) NOT NULL DEFAULT '0', ADD PRIMARY KEY (nid)");
-  $ret[] = update_sql("ALTER TABLE {simplenews_scheduler_editions} CHANGE edition_snid eid INT(11) NOT NULL DEFAULT '0'");
-  $ret[] = update_sql("ALTER TABLE {simplenews_scheduler_editions} CHANGE snid pid INT(11) NOT NULL DEFAULT '0'");
-  return $ret;
-}
-
-/**
- * Implementation of hook_update_N().
- */
-function simplenews_scheduler_update_6002() {
-  $ret = array();
-  db_drop_field($ret, 'simplenews_scheduler', 'run_limit');
-  db_drop_field($ret, 'simplenews_scheduler', 'run_count');
-  return $ret;
-}
-
-/**
- * Implementation of hook_update_N().
- */
-function simplenews_scheduler_update_6003() {
-  $ret = array();
-  db_add_primary_key($ret, 'simplenews_scheduler_editions', array('eid'));
-  return $ret;
-}
-
-/**
- * Implementation of hook_update_N().
- */
-function simplenews_scheduler_update_6004() {
-  $ret = array();
-  db_add_field($ret, 'simplenews_scheduler', 'php_eval', array('type' => 'blob'));
-  return $ret;
-}
-/**
- * Implementation of hook_update_N().
-  // attempt to change to pgsql compatible strings
-  // #970942
+/*
+ * Implements hook_update_last_removed().
  */
-function simplenews_scheduler_update_6005() {
-  $ret = array();
-
-  db_change_field($ret, 'simplenews_scheduler', 'stop', 'stop_type', array(
-    'type' => 'int',
-    'not null' => TRUE,
-    )
-  );
-  db_change_field($ret, 'simplenews_scheduler', 'interval', 'send_interval', array(
-	'type' => 'varchar',
-	'length' => 10,
-    )
-  );
-
-
-  return $ret;
+function simplenews_scheduler_update_last_removed() {
+  return 6005;
 }
 
 /**
  * Add the title field to the scheduler table.
  */
-function simplenews_scheduler_update_6006() {
-  $ret = array();
-
-  $field = array(
-    'description' => 'The title of new edition nodes.',
-    'type' => 'varchar',
-    'length' => 255,
-    'not null' => TRUE,
-    'default' => '',
-    'initial' => '[title]', // Set existing schedules to just use the node title.
-  );
-  db_add_field($ret, 'simplenews_scheduler', 'title', $field);
-
-  return $ret;
+function simplenews_scheduler_update_7000() {
+
+  if (!db_field_exists('simplenews_scheduler', 'title')) {
+    $field = array(
+      'description' => 'The title of new edition nodes.',
+      'type' => 'varchar',
+      'length' => 255,
+      'not null' => TRUE,
+      'default' => '',
+      'initial' => '[node:title]',
+    );
+    db_add_field('simplenews_scheduler', 'title', $field);
+  }
 }
-
diff --git a/simplenews_scheduler.js b/simplenews_scheduler.js
deleted file mode 100644
index 31a3666..0000000
--- a/simplenews_scheduler.js
+++ /dev/null
@@ -1,65 +0,0 @@
-
-/**
- * @file
- * jQuery helper functions for the Simplenews Scheduler module interface on node edit page.
- */
-
-/**
- * Set scheduler info's display attribute to hide and show based on the option value.
- */
-Drupal.behaviors.simplenewsScheduler = function (context) {
-  var simplenewsScheduler = function () {
-    if($(".simplenews-command-send :radio:checked").val() == '3') {
-        $('.schedule_info').css({display: "block"});
-    } else {
-      $('.schedule_info').css({display: "none"});
-    }
-  }
-
-  // Update scheduler info's display at page load and when a send option is selected.
-  $(function() { simplenewsScheduler(); });
-  $(".simplenews-command-send").click( function() { simplenewsScheduler(); });
-}
-
-/**
- * Set scheduler info's display attribute to hide and show dependent on the selected stop option.
- */
-Drupal.behaviors.simplenewsSchedulerStop = function (context) {
-  var simplenewsSchedulerStop = function () {
-    if($(".simplenews-command-stop :radio:checked").val() == '1') {
-        $('#edit-simplenews-scheduler-stop-date-wrapper').css({display: "block"});
-    } else {
-      $('#edit-simplenews-scheduler-stop-date-wrapper').css({display: "none"});
-    }
-    if($(".simplenews-command-stop :radio:checked").val() == '2') {
-        $('#edit-simplenews-scheduler-stop-edition-wrapper').css({display: "block"});
-    } else {
-      $('#edit-simplenews-scheduler-stop-edition-wrapper').css({display: "none"});
-    }
-  }
-
-  // Update scheduler info's display at page load and when a stop option is selected.
-  $(function() { simplenewsSchedulerStop(); });
-  $(".simplenews-command-stop").click( function() { simplenewsSchedulerStop(); });
-}
-
-/**
- * Set text of Save button dependent if scheduled sending is selected.
- */
-Drupal.behaviors.simplenewsSchedulerCommandSend = function (context) {
-  var simplenewsSchedulerSendButton = function () {
-    switch ($(".simplenews-command-send :radio:checked").val()) {
-      case '3':
-        $('#simplenews-node-tab-send-form #edit-submit').attr({value: Drupal.t('Save and send as scheduled')});
-        break;
-      default:
-        $('#simplenews-node-tab-send-form #edit-submit').attr({value: Drupal.t('Submit')});
-        break;
-      break;
-    }
-  }
-
-  // Update send button at page load and when a send option is selected.
-  $(function() { simplenewsSchedulerSendButton(); });
-  $(".simplenews-command-send").click( function() { simplenewsSchedulerSendButton(); });
-}
diff --git a/simplenews_scheduler.module b/simplenews_scheduler.module
index bf40f9e..81b6d35 100644
--- a/simplenews_scheduler.module
+++ b/simplenews_scheduler.module
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * @file
  * Simplenews Scheduler module allows a schedule to be set
@@ -8,21 +9,34 @@
 /**
  * NEWSLETTER SEND COMMAND
  */
-define('SIMPLENEWS_COMMAND_SEND_SCHEDULE', 3);
-define('SIMPLENEWS_COMMAND_SEND_NONE', 4);
+define('SIMPLENEWS_COMMAND_SEND_SCHEDULE', 4);
+define('SIMPLENEWS_COMMAND_SEND_NONE', 5);
 
 /**
- * Implementation of hook_perm().
+ * Implements hook_permission().
  */
-function simplenews_scheduler_perm() {
-  return array('overview scheduled newsletters', 'send scheduled newsletters');
+function simplenews_scheduler_permission() {
+  return array(
+    'overview scheduled newsletters' => array(
+      'title' => t('View scheduled newsletters'),
+      'description' => t('Access overview page for scheduled newsletters.'),
+    ),
+    'send scheduled newsletters' => array(
+      'title' => t('Send scheduled newsletters'),
+      'description' => t('Allows users to use scheduled newsletter sending option.'),
+    ),
+  );
 }
 
 /**
- * Implementation of hook_menu().
+ * Implements hook_menu().
+ *
+ * @todo uncomment the menu item when the overview
+ * page is reprogrammed using a display of a default view.
  */
 function simplenews_scheduler_menu() {
   $items = array();
+
   $items["node/%node/editions"] = array(
     'title' => 'Newsletter Editions',
     'type' => MENU_LOCAL_TASK,
@@ -32,123 +46,121 @@ function simplenews_scheduler_menu() {
     'access callback' => '_simplenews_scheduler_tab_permission',
     'access arguments' => array(1),
   );
+
   return $items;
 }
 
 /**
- * Implementation of hook_form_alter().
+ * Implements hook_form_FORM_ID_alter().
+ *
+ * @todo replace the "This newsletter has been sent" checkbox of simplenews module
+ * by a message like "Last edition of this newsletter was sent at 12.12.2012"
  */
-function simplenews_scheduler_form_alter(&$form, &$form_state, $form_id) {
-  global $user;
-  // if this is an edition, then we should be fiddling with it, only the parent.
+function simplenews_scheduler_form_simplenews_node_tab_send_form_alter(&$form, &$form_state) {
 
+  global $user;
+  $node = node_load($form['nid']['#value']);
 
   // Add schedule settings to the newsletter edit form.
   if (isset($form['simplenews']) && user_access('send scheduled newsletters') && !isset($node->simplenews_scheduler_edition)) {
-    drupal_add_js(drupal_get_path('module', 'simplenews_scheduler') . '/simplenews_scheduler.js', 'module', 'header', FALSE, FALSE, TRUE);
 
     // Set the default values.
     $form['#submit'][] = "simplenews_scheduler_submit";
 
     $scheduler = array();
-    $result = db_query("SELECT * FROM {simplenews_scheduler} WHERE nid = %d", arg(1));
-    $row = db_fetch_array($result);
-    if ($row) {
-      $scheduler = $row;
+    $record = db_select('simplenews_scheduler', 's')
+      ->fields('s')
+      ->condition('nid', arg(1))
+      ->execute()
+      ->fetchAssoc();
+
+    if (!empty($record)) {
+      $scheduler = $record;
     }
     else {
       $scheduler['activated'] = 0;
     }
 
-    $form['simplenews']['send']['#options'][SIMPLENEWS_COMMAND_SEND_SCHEDULE] = t('Send newsletter according to schedule');
-    $form['simplenews']['send']['#default_value'] = ($scheduler['activated'] == 1) ? SIMPLENEWS_COMMAND_SEND_SCHEDULE : variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_NONE);
-    $form['simplenews']['send']['#options'][SIMPLENEWS_COMMAND_SEND_NONE] = t("Don't send now or stop sending");
-    $form['simplenews']['scheduler'] = array(
-      '#type' => 'fieldset',
-      '#title' => t('Schedule details'),
-      '#attributes' => array('class' => 'schedule_info'),
-      '#collapsible' => FALSE,
-      '#collapsed' => FALSE,
-      '#tree' => TRUE,
-    );
+    // check prevents php notice if newsletter was sent and only a checkbox appears in the form 
+    if (isset($form['simplenews']['send'])) {
+      $form['simplenews']['send']['#options'] += array(
+        SIMPLENEWS_COMMAND_SEND_SCHEDULE => t('Send newsletter according to schedule'),
+        SIMPLENEWS_COMMAND_SEND_NONE => t("Stop newsletter schedule"),
+      );
+      $form['simplenews']['send']['#default_value'] = ($scheduler['activated'] == 1) ? SIMPLENEWS_COMMAND_SEND_SCHEDULE : variable_get('simplenews_send', SIMPLENEWS_COMMAND_SEND_NONE);
+    }
+    
     // Display settings only if this is not an edition.
-    if (!isset($form['#node']->simplenews_scheduler_edition)) {
-      $form['simplenews']['scheduler']['send_interval'] = array(
-        '#type' => 'select',
-        '#title' => t('Send once per'),
-        '#options' => array(
-          'hour' => t('Hour'),
-          'day' => t('Day'),
-          'week' => t('Week'),
-          'month' => t('Month'),
+    if (!isset($node->simplenews_scheduler_edition)) {
+
+      $form['simplenews']['scheduler'] = array(
+        '#type' => 'fieldset',
+        '#title' => t('Schedule details'),
+        '#attributes' => array('class' => array('schedule-info')),
+        '#collapsible' => TRUE,
+        '#collapsed' => FALSE,
+        '#states' => array(
+          'visible' => array(':input[name="simplenews[send]"]' => array('value' => (string) SIMPLENEWS_COMMAND_SEND_SCHEDULE)),
         ),
-        '#description' => t('Interval to send at'),
-        '#default_value'=> isset($scheduler['send_interval']) ? $scheduler['send_interval'] : 'week',
       );
 
       // If there is no default value, use the current time for start.
-      $date_start = isset($scheduler['start_date']) ? $scheduler['start_date'] : time();
-      // and Mon, 30 Dec 2013 23:59:59 GMT for stop, that should be enough.
-      $date_stop = isset($scheduler['stop_date']) ? $scheduler['stop_date'] : 1388447999;
-      $form_date = false;
-      if (isset($form['#node'])) {
-        // Convert dates to valid date objects.
-        if ($form['#node']->build_mode == 1) {
-          $date_start = date_make_date($date_start, NULL, DATE_DATETIME);
-          $date_stop = date_make_date($date_stop, NULL, DATE_DATETIME);
-          $form_date = true;
-        }
-      }
-
-      if (! $form_date) {
-        $date_start = date_make_date($date_start, date_default_timezone_name(), DATE_UNIX);
-        $date_stop = date_make_date($date_stop, date_default_timezone_name(), DATE_UNIX);
-      }
+      $start_date = !empty($scheduler['start_date']) ? $scheduler['start_date'] : REQUEST_TIME;
+      // and Today + 2 years for stop, that should be enough.
+      $stop_date = !empty($scheduler['stop_date']) ? $scheduler['stop_date'] : time() + 2 * 365 * 24 * 60 * 60;
 
-      // Translate formatted date results.
-      $date_str_start = date_format_date($date_start, 'custom', 'Y-m-d H:i');
-      $date_str_stop = date_format_date($date_stop, 'custom', 'Y-m-d H:i');
       $form['simplenews']['scheduler']['start_date'] = array(
-        '#type' => 'date_select', '#title' => t('Start sending on'),
-        '#default_value' => $date_str_start,
-        '#date_type' => DATE_DATETIME,
-        '#date_format' => 'm-d-Y - H:i',
-        '#date_timezone' => date_default_timezone_name(),
-        '#date_label_position' => 'none',
-        '#date_increment' => 1,
-        '#date_year_range' => '0:+3',
+        '#type' => 'date_select',
+        '#title' => t('Start sending on'),
+        '#default_value' => date('Y-m-d H:i', $start_date),
         '#required' => TRUE,
+        '#date_format' => 'Y-m-d H:i',
+        '#date_label_position' => 'within',
+        '#date_year_range' => '-0:+3',
         '#description' => t('Intervals work by creating a new node at the
-           desired time and marking this to be sent, ensure
-           you have your <a href="@site">site timezones</a>
-           configured and <a href="@user">user timezone</a>
-           configured.', array(
-             '@site' => url('admin/settings/date-time'),
-             '@user' => url('user/' . $user->uid . '/edit'),
-           )),
-         );
-      $form['simplenews']['scheduler']['stop_type'] = array(
+                                 desired time and marking this to be sent, ensure
+                                 you have your <a href="@site">site timezones</a>
+                                 configured and <a href="@user">user timezone</a>
+                                 configured.', array('@site' => url('admin/config/date-time'), '@user' => url('user/' . $user->uid . '/edit'))),
+      );
+
+      $intervals = array(
+        'hour' => t('Hour'),
+        'day' => t('Day'),
+        'week' => t('Week'),
+        'month' => t('Month'),
+      );
+
+      $form['simplenews']['scheduler']['interval'] = array(
+        '#type' => 'select',
+        '#title' => t('Sending interval'),
+        '#options' => $intervals,
+        '#description' => t('Interval to send at'),
+        '#default_value' => !empty($scheduler['send_interval']) ? $scheduler['send_interval'] : 'week',
+      );
+
+      $form['simplenews']['scheduler']['frequency'] = array(
+        '#type' => 'textfield',
+        '#title' => t('Interval frequency'),
+        '#size' => 5,
+        '#default_value' => !empty($scheduler['interval_frequency']) ? $scheduler['interval_frequency'] : 1,
+        '#description' => t('Set the number of Intervals between newsletter transmission.'),
+      );
+
+      $stoptypes = array(
+        t('Never'),
+        t('On a given date'),
+        t('After a maximum number of editions')
+      );
+
+      $form['simplenews']['scheduler']['stoptype'] = array(
         '#type' => 'radios',
         '#title' => t('Stop sending'),
-        '#default_value' => isset($scheduler['stop_type']) ? $scheduler['stop_type'] : 0,
-        '#options' => array(
-          t('Never'),
-          t('On a given date'),
-          t('After a maximum number of editions'),
-        ),
-        '#attributes' => array('class' => 'simplenews-command-stop'),
-      );
-      $form['simplenews']['scheduler']['stop_date'] = array(
-        '#type' => 'date_select',
-        '#default_value' => $date_str_stop,
-        '#date_type' => DATE_DATETIME,
-        '#date_format' => 'm-d-Y - H:i',
-        '#date_timezone' => date_default_timezone_name(),
-        '#date_label_position' => 'none',
-        '#date_increment' => 1,
-        '#date_year_range' => '2010:+3',
-        '#required' => TRUE,
+        '#options' => $stoptypes,
+        '#default_value' => !empty($scheduler['stop_type']) ? $scheduler['stop_type'] : 0,
+        '#attributes' => array('class' => array('simplenews-command-stop')),
       );
+
       $form['simplenews']['scheduler']['stop_edition'] = array(
         '#type' => 'textfield',
         '#default_value' => isset($scheduler['stop_edition']) ? $scheduler['stop_edition'] : 0,
@@ -156,7 +168,25 @@ function simplenews_scheduler_form_alter(&$form, &$form_state, $form_id) {
         '#maxlength' => 5,
         '#required' => TRUE,
         '#description' => t('The maximum number of editions which should be sent.'),
+        '#states' => array(
+          'visible' => array(':input[name="simplenews[scheduler][stoptype]"]' => array('value' => (string) 2)),
+        ),
+      );
+
+      $form['simplenews']['scheduler']['stop_date'] = array(
+        '#type' => 'date_select',
+        '#title' => t('Stop sending on'),
+        '#default_value' => date('Y-m-d H:i', $stop_date),
+        '#required' => TRUE,
+        '#date_format' => 'Y-m-d H:i',
+        '#date_label_position' => 'within',
+        '#date_year_range' => '-0:+3',
+        '#description' => t('The date when the last sent newsletter will be sent.'),
+        '#states' => array(
+          'visible' => array(':input[name="simplenews[scheduler][stoptype]"]' => array('value' => (string) 1)),
+        ),
       );
+
       $form['simplenews']['scheduler']['php_eval'] = array(
         '#type' => 'textarea',
         '#title' => t('Additionally only create newsletter edition if the following code returns true'),
@@ -169,7 +199,7 @@ function simplenews_scheduler_form_alter(&$form, &$form_state, $form_id) {
         '#title' => t('Title pattern for new edition nodes'),
         '#description' => t('New edition nodes will have their title set to the above string, with tokens replaced.'),
         '#required' => TRUE,
-        '#default_value' => isset($scheduler['title']) ? $scheduler['title'] : '[title]',
+        '#default_value' => isset($scheduler['title']) ? $scheduler['title'] : '[node:title]',
       );
       $form['simplenews']['scheduler']['token_help'] = array(
         '#title' => t('Replacement patterns'),
@@ -178,38 +208,29 @@ function simplenews_scheduler_form_alter(&$form, &$form_state, $form_id) {
         '#collapsed' => TRUE,
       );
       $form['simplenews']['scheduler']['token_help']['help'] = array(
-        '#value' => theme('token_help', array('node', 'global')),
+        '#theme' => 'token_tree',
+        '#token_types' => array('node'),
       );
+
       $form['simplenews']['scheduler']['activated'] = array(
-        '#type' => 'hidden',
+        '#type' => 'value',
         '#value' => $scheduler['activated'],
       );
     }
     else {
       // This is a newsletter edition.
-      $title .= t('This node is part of a scheduled newsletter configuration. View the original newsletter <a href="@parent">here</a>.', array('@parent' => url('node/' . $form['#node']->simplenews_scheduler_edition['pid'])));
-      $form['simplenews']['none']['#title'] = $title;
-      // If the node has attachments
-      if (count($form['attachments']['wrapper']['files']) && user_access('upload files')) {
-        // Disable all attachment form elements and the delete button to avoid the deletion of the parent's attachments.
-        $form['attachments']['#description'] = t('Attachments cannot be changed, this is a newsletter edition created by Simplenews Scheduler.');
-        $form['attachments']['wrapper']['new']['upload']['#disabled'] = TRUE;
-        $form['attachments']['wrapper']['new']['attach']['#disabled'] = TRUE;
-        // Disable every file element.
-        foreach ($form['attachments']['wrapper']['files'] as $key => $file) {
-          if (is_numeric($key)) {
-            $form['attachments']['wrapper']['files'][$key]['description']['#disabled'] = TRUE;
-            $form['attachments']['wrapper']['files'][$key]['remove']['#disabled'] = TRUE;
-            $form['attachments']['wrapper']['files'][$key]['list']['#disabled'] = TRUE;
-            $form['attachments']['wrapper']['files'][$key]['weight']['#disabled'] = TRUE;
-            $form['buttons']['delete']['#disabled'] = TRUE;
-          }
-        }
-      }
+      $title .= t('This node is part of a scheduled newsletter configuration. View the original newsletter <a href="@parent">here</a>.', array('@parent' => url('node/' . $node->simplenews_scheduler_edition['pid'])));
+      $form['simplenews']['none']['#title'] = array(
+        'type' => 'item',
+        '#title' => $title,
+      );
     }
   }
 }
 
+/**
+ * Additional submit handler for the node_tab_send_form of simplenews.
+ */
 function simplenews_scheduler_submit($form, &$form_state) {
 
   $nid = $form_state['values']['nid'];
@@ -217,202 +238,225 @@ function simplenews_scheduler_submit($form, &$form_state) {
 
   // Get Scheduler values from Simplenews.
   $send = $form_state['values']['simplenews']['send'];
-  // Change activation status if necessary.
-  switch ($send) {
-    case 0 :
-    case 1 :
-      $activated = 0;
-      break;
-    case 3 :
-      $activated = 1;
-      break;
-  }
 
-  $start_date = $form_state['values']['simplenews']['scheduler']['start_date'];
-  $stop_date = $form_state['values']['simplenews']['scheduler']['stop_date'];
-  // Convert the user time back to GMT time and use that as our record.
-  $start_date = date_convert($start_date, DATE_DATETIME, DATE_UNIX, date_default_timezone_name());
-  $stop_date = date_convert($stop_date, DATE_DATETIME, DATE_UNIX, date_default_timezone_name());
+  $stoptype = $form_state['values']['simplenews']['scheduler']['stoptype'];
+  $start_date = strtotime($form_state['values']['simplenews']['scheduler']['start_date']);
+  $stop_date = ($stoptype == 1) ? strtotime($form_state['values']['simplenews']['scheduler']['stop_date']) : 0;
 
   $record = array(
-    'nid'           => $nid,
-    'activated'     => $activated,
-    'send_interval' => $form_state['values']['simplenews']['scheduler']['send_interval'],
-    'start_date'    => $start_date,
-    'stop_type'     => $form_state['values']['simplenews']['scheduler']['stop_type'], // number of edition
-    'stop_date'     => $stop_date,
-    'stop_edition'  => $form_state['values']['simplenews']['scheduler']['stop_edition'],
-    'php_eval'      => $form_state['values']['simplenews']['scheduler']['php_eval'],
-    'title'         => $form_state['values']['simplenews']['scheduler']['title'],
+    'nid'                => $nid,
+    'activated'          => $send == SIMPLENEWS_COMMAND_SEND_SCHEDULE ? 1 : 0,
+    'send_interval'      => $form_state['values']['simplenews']['scheduler']['interval'],
+    'interval_frequency' => $form_state['values']['simplenews']['scheduler']['frequency'],
+    'start_date'         => $start_date,
+    'stop_type'          => $stoptype,
+    'stop_date'          => $stop_date,
+    'stop_edition'       => $form_state['values']['simplenews']['scheduler']['stop_edition'],
+    'php_eval'           => $form_state['values']['simplenews']['scheduler']['php_eval'],
+    'title'              => $form_state['values']['simplenews']['scheduler']['title'],
   );
 
-  db_query("DELETE FROM {simplenews_scheduler} WHERE nid = %d", $nid);
-  $result = drupal_write_record('simplenews_scheduler', $record);
+  // Update scheduler record.
+  $query = db_merge('simplenews_scheduler');
+  $query->key(array(
+      'nid' => $nid,
+    ))
+    ->fields($record)
+    ->execute();
 
-  if (! $result) {
+  if (!$query) {
     drupal_set_message(t('Saving or updating schedule settings for <em>@title</em> has been unsuccessful.', array(
-      '@title' => $node->title
-    )), 'error');
+        '@title' => $node->title,
+      )), 'error');
   }
   else {
     drupal_set_message(t('Newsletter Schedule preferences saved'));
   }
 }
 
-/**
- * Implementation of hook_nodeapi().
+/*
+ * Implementes hook_node_load().
  */
-function simplenews_scheduler_nodeapi(&$node, $op) {
-  if (in_array($node->type, variable_get('simplenews_content_types', array('simplenews')))) {
-    switch ($op) {
-      case 'load':
-        if (isset($node->nid)) {
-          $result = db_query("SELECT * FROM {simplenews_scheduler} WHERE nid = %d", $node->nid);
-          $row = db_fetch_array($result);
-          if ($row) {
-            $node->simplenews_scheduler = $row;
-          }
-          else {
-            // Maybe this was an edition that has been sent?
-            $result = db_query("SELECT * FROM {simplenews_scheduler_editions} WHERE eid = %d", $node->nid);
-            $row = db_fetch_array($result);
-            if ($row) {
-              $node->simplenews_scheduler_edition = $row;
-            }
-          }
-        }
-        break;
-     case 'delete':
-       // erase the record from the scheduler table so it does not try to send
-       db_query("DELETE FROM {simplenews_scheduler} WHERE nid = %d", $node->nid);
-     break;
-     case 'view':
-      // leaving this out until we figure out a nicer UI for showing this.
-      // this should be letting you know that you are viewing a generated newsletter, not the original
-     /*  if(isset($node->simplenews_scheduler_edition)) {
-         drupal_set_message(t('You have been redirected to the original newsletter'));
-         drupal_goto('node/'.$node->simplenews_scheduler_edition['pid'].'/simplenews');
-       }
-      */
-     break;
-    }
+function simplenews_scheduler_node_load($nodes, $types) {
+
+  $nids = array_keys($nodes);
+
+  $result = db_select('simplenews_scheduler', 's')
+    ->fields('s')
+    ->condition('nid', $nids, 'IN')
+    ->execute()
+    ->fetchAll();
+
+  foreach ($result as $key => $record) {
+    $nodes[$record->nid]->simplenews_scheduler = $record;
+  }
+
+  $result = db_select('simplenews_scheduler_editions', 's')
+    ->fields('s')
+    ->condition('eid', $nids, 'IN')
+    ->execute()
+    ->fetchAll();
+
+  foreach ($result as $key => $record) {
+    $nodes[$record->eid]->simplenews_scheduler_edition = $record;
+    $nodes[$record->eid]->is_edition = TRUE;
+    $nodes[$record->eid]->simplenews_edition_parent = $record->pid;
+  }
+}
+
+/*
+ * Implementes hook_node_delete().
+ */
+function simplenews_scheduler_node_delete($node) {
+  db_delete('simplenews_scheduler')
+    ->condition('nid', $node->nid)
+    ->execute();
+}
+
+/*
+ * Implementes hook_node_view().
+ */
+function simplenews_scheduler_node_view($node) {
+  if (isset($node->simplenews_scheduler_edition) && user_access('send scheduled newsletters')) {
+    drupal_set_message(t('This is a newsletter edititon. View the the master template of this newsletter <a href="!master_url">here</a>', array('!master_url' => url('node/' . $node->simplenews_edition_parent))));
   }
 }
 
 /**
- * Implementation of hook_cron().
+ * Implements hook_cron().
  *
  * Essentially we are just checking against a status table
- * and recreating nodes to be sent.
- *
+ * and cloning the node into edition nodes which will be sent.
  */
 function simplenews_scheduler_cron() {
 
-  module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
   // Set the default intervals for scheduling.
   $intervals['hour'] = 3600;
   $intervals['day'] = 86400;
   $intervals['week'] = $intervals['day'] * 7;
   $intervals['month'] = $intervals['day'] * date_days_in_month(date('Y'), date('m'));
+
   foreach ($intervals as $interval => $seconds) {
+
     // Check daily items that need to be sent.
     $now_time = gmmktime();
-    $result = db_query("SELECT * FROM {simplenews_scheduler} WHERE activated = 1 AND %d - last_run > %d AND send_interval = '%s' AND start_date <= %d AND %d < stop_date", $now_time, $seconds, $interval, $now_time, $now_time);
-    while ($row = db_fetch_array($result)) {
+    $sql = "SELECT * FROM {simplenews_scheduler} ";
+    $sql .= "WHERE activated = :active ";
+    $sql .= "AND :now - last_run > :interval ";
+    $sql .= "AND send_interval = :frequency ";
+    $sql .= "AND start_date <= :now ";
+    $sql .= "AND (stop_date > :now OR stop_date = 0)";
+
+    $result = db_query($sql, array(':active' => 1, ':now' => $now_time, ':interval' => $seconds, ':frequency' => $interval));
+
+    foreach ($result as $row) {
+
       // does this newsletter have something to evaluate to check running condition?
-      if (strlen($row['php_eval'])) {
-        $eval_result = eval($row['php_eval']);
-        if (! $eval_result) {
-          break;
+      if (strlen($row->php_eval)) {
+        $eval_result = eval($row->php_eval);
+        if (!$eval_result) {
+          continue;
         }
       }
 
-      $pid = $row["nid"];
+      $pid = $row->nid;
+
       // If returns with null don't do anything.
-      $first_run = intval($row['start_date']);
+      $first_run = intval($row->start_date);
+
       // Because the scheduler runs according to last_run timestamp and the cron
       // does not run exactly at the scheduled timestamp, this correction fixes
       // this run's timestamp ($now_time) to the right time by adding a correct interval.
-      $this_run = $first_run + floor(($now_time - $first_run) / $seconds) * $seconds;
+      $interval_duration = $seconds * $row->interval_frequency;
+      $this_run = $first_run + floor(($now_time - $first_run) / $interval_duration) * $interval_duration;
+
       // Create a new edition.
-      $eid = _simplenews_scheduler_new_edition($row["nid"]);
+      $eid = _simplenews_scheduler_new_edition($row->nid);
+
       if (isset($eid)) {
-        db_query("UPDATE {simplenews_scheduler} SET last_run = %d WHERE nid = %d", $this_run, $pid);
+
+        // persist last_run
+        db_update('simplenews_scheduler')
+          ->fields(array('last_run' => $this_run))
+          ->condition('nid', $pid)
+          ->execute();
+
+        // Send the newsletter edition to each subscriber of the parent newsletter.
         $node = node_load($eid);
-        // Send the newsletter edition to each subscriber of the parent newsletter
-        // get the tid of this newsletter and generate a list of accounts to send this new newsletter to, based on the parent newsletter.
-        $tid = db_result(db_query("SELECT tid from {simplenews_newsletters} WHERE nid = %d", $node->nid));
-        $accounts = simplenews_scheduler_get_newsletter_accounts($tid);
-        simplenews_send_node($node, $accounts);
+        module_load_include('inc', 'simplenews', 'includes/simplenews.mail');
+        simplenews_add_node_to_spool($node);
       }
     }
   }
 }
 
-// @todo: might be a better already existing function for this
-function simplenews_scheduler_get_newsletter_accounts($newsletter_tid) {
-
-  // taken from the newsletter subscription list
-   $query = '
-    SELECT DISTINCT ss.snid, ss.*, u.name
-    FROM {simplenews_subscriptions} ss
-    LEFT JOIN {users} u
-      ON ss.uid = u.uid
-    INNER JOIN {simplenews_snid_tid} s
-      ON ss.snid = s.snid
-    AND s.tid = %d AND s.status = 1';
-
-   $result = db_query($query, $newsletter_tid);
-
-  // build the accounts array
-  /* @param array $accounts  account objects to send the newsletter to.
-     *   account = object (
-     *     snid     = subscription id, or 0 if no subscription record exists.
-     *     tids     = array(tid) array of newsletter tid's.
-     *     uid      = user id, or 0 if subscriber is anonymous user.
-     *     mail     = user email address.
-     *     name     = <empty>. Added for compatibility with user account object.
-     *     language = language object. User-preferred or default language.
-     *
-     */
-  $accounts = array();
-  while ($account = db_fetch_object($result)) {
-    $account->tids = array(
-      $newsletter_tid
-    );
-    $accounts[] = $account;
-  }
+/*
+ * Function clones a node from the given template newsletter node.
+ */
 
-   return $accounts;
+function simplenews_scheduler_clone_node($node) {
+  if (isset($node->nid)) {
+    $clone = clone $node;
+
+    $clone->nid = NULL;
+    $clone->vid = NULL;
+    $clone->tnid = NULL;
+    $clone->created = NULL;
+    $clone->book['mlid'] = NULL;
+    $clone->path = NULL;
+    //$clone->title = $original_node->title;
+    // Add an extra property as a flag.
+    $clone->clone_from_original_nid = $node->nid;
+
+    node_save($clone);
+    return $clone;
+  }
 }
+
 /**
  * Menu callback to provide an overview page with the scheduled newsletters.
+ *
+ * @todo replace the output of this function with a default view that
+ * will be provided by the views integration of this module. Code below
+ * is ported from D6!
  */
 function simplenews_scheduler_node_page($node) {
+
   drupal_set_title(t('Scheduled newsletter editions'));
   $nid = _simplenews_scheduler_get_pid($node);
-  // This is the original newsletter.
-  if ($nid == $node->nid) {
-    $output .= '<p>' . t('This is the original newsletter of which all editions are based on.') . '</p>';
+  $output = '';
+  
+  if ($nid == $node->nid) { // This is the template newsletter.
+    $output .= '<p>' . t('This is a newsletter template node of which all corresponding editions nodes are based on.') . '</p>';
   }
-  // This is a newsletter edition.
-  else {
+  else { // This is a newsletter edition.
     $output .= '<p>' . t('This node is part of a scheduled newsletter configuration. View the original newsletter <a href="@parent">here</a>.', array('@parent' => url('node/' . $nid))) . '</p>';
   }
+
   // Load the corresponding editions from the database to further process.
-  $result = pager_query("SELECT * FROM {simplenews_scheduler_editions} sse LEFT JOIN {node} n ON n.nid = sse.pid WHERE sse.pid = %d", 20, 0, NULL, $nid);
-  while ($row = db_fetch_object($result)) {
+  $result = db_select('simplenews_scheduler_editions', 's')
+             ->extend('PagerDefault')
+             ->limit(20)
+             ->fields('s')
+             ->condition('s.pid', $nid)
+             ->execute()
+             ->fetchAll();
+              
+  foreach ($result as $row) {
     $node = node_load($row->eid);
-    $rows[] = array(format_date($row->date_issued, 'custom', 'Y-m-d H:i'), l($node->title, 'node/' . $row->eid));
+    $rows[] = array(l($node->title, 'node/' . $row->eid), format_date($row->date_issued, 'custom', 'Y-m-d H:i'));
   }
+  
   // Display a table with all editions.
-  if (! empty($rows)) {
-    $output .= theme('table', array(t('Date sent'), t('Node')), $rows, array('class' => 'schedule_history'));
-    $output .= theme('pager', 20);
-  }
-  else {
-    $output .= '<p>' . t('No scheduled newsletters have been sent.') . '</p>';
-  }
+  $tablecontent = array(
+    'header' => array(t('Edition Node'), t('Date sent')),
+    'rows' => $rows,
+    'attributes' => array('class' => array('schedule-history')),
+    'empty' => '<p>' . t('No scheduled newsletter editions have been sent.') . '</p>',
+  );
+  $output .= theme('table', $tablecontent);
+  $output .= theme('pager', array('tags' => 20));
+  
   return $output;
 }
 
@@ -420,15 +464,7 @@ function simplenews_scheduler_node_page($node) {
  * Check whether to display the Scheduled Newsletter tab.
  */
 function _simplenews_scheduler_tab_permission($node) {
-  if (in_array($node->type, variable_get('simplenews_content_types', array('simplenews'))) && user_access('overview scheduled newsletters')) {
-    $pid = _simplenews_scheduler_get_pid($node);
-    // Only display the tab if there is a parent template newsletter or if this
-    // is itself a template newsletter.
-    return !empty($pid);
-  }
-  else {
-    return FALSE;
-  }
+  return simplenews_check_node_types($node->type) && user_access('overview scheduled newsletters');
 }
 
 /**
@@ -436,7 +472,9 @@ function _simplenews_scheduler_tab_permission($node) {
  * need to be set to.
  */
 function _simplenews_scheduler_get_full_html_format() {
-  $formats = filter_formats();
+
+  global $user;
+  $formats = filter_formats($user);
 
   foreach ($formats as $index => $format) {
     if (stristr($format->name, 'Full HTML')) {
@@ -448,93 +486,69 @@ function _simplenews_scheduler_get_full_html_format() {
 }
 
 /**
- * Create a new newsletter edition.
+ * Create a new newsletter edition based on the master edition of this newsletter.
  */
 function _simplenews_scheduler_new_edition($nid) {
-  $node = node_load($nid);
-
-  if (module_exists('upload')) {
-    $files = upload_load($node);
-  }
-
-  // Switch to the anonymous user to render node content.
-  // This prevents things like Views admin links from showing in edition node body.
-  global $user;
-  if ($user->uid) {
-    // Store the current user and session so we can restore them.
-    $original_user = $user;
-    $old_state = session_save_session();
-
-    // Disable session saving and load the anonymous user.
-    session_save_session(FALSE);
-    $user = user_load(0);
-  }
-
-  // Render node content.
-  $node = node_build_content($node, FALSE, FALSE);
-  $content = drupal_render($node->content);
-  // Keep the teaser in sync with the rendered node content.
-  $node->teaser = node_teaser($node->body, isset($node->format) ? $node->format : NULL);
-
-  // Restore the original user if necessary.
-  if (isset($original_user)) {
-    $user = $original_user;
-    session_save_session($old_state);
-  }
-
-  // Store taxonomy terms to save later to the node.
-  $terms = $node->taxonomy;
-
-  // Output format for all newly created items should just be Full HTML, incase of Views output etc.
-  if ($format_id = _simplenews_scheduler_get_full_html_format()) {
-    $node->format = $format_id;
-  }
-
-  // Trigger it for sending.
-  $node->simplenews['send'] = 1;
 
   // Check upon if sending should stop with a given edition number.
-  $result = db_fetch_array(db_query("SELECT stop_type, stop_edition FROM {simplenews_scheduler} WHERE nid = %d", $nid));
+  $result = db_select('simplenews_scheduler', 's')
+    ->fields('s', array('stop_type', 'stop_edition'))
+    ->condition('nid', $nid)
+    ->execute()
+    ->fetchAssoc();
   $stop = $result['stop_type'];
   $stop_edition = $result['stop_edition'];
+
+  $count = db_select('simplenews_scheduler_editions', 'e')
+    ->fields('e', array('eid'))
+    ->condition('pid', $nid)
+    ->execute()
+    ->fetchAll();
+  $edition_count = count($count);
+
   // Don't create new edition if the edition number exceeds the given maximum value.
-  if (($stop == 2 && $serial <= $stop_edition) || $stop != 2) {
-    // Mark as new with removeing node ID and creation date.
-    unset($node->nid, $node->created, $node->path);
+  if (($stop != 2 || $stop == 2 && $edition_count < $stop_edition)) {
+    
+    // Load the template node and clone an edition.
+    $template_node = node_load($nid);
+    $edition_node = simplenews_scheduler_clone_node($template_node);
+
     // Run the title through token replacement.
-    $title_pattern = $node->simplenews_scheduler['title'];
-    $node->title = token_replace($title_pattern, 'node', $node);
-    // Mark as new edition.
-    $node->is_edition = TRUE;
-    // Now save it as a new node.
-    node_save($node);
+    $edition_node->title = token_replace($edition_node->title, array('node' => $edition_node));
+
+    // Let other modules change the cloned node too
+    // module_invoke_all('simplenews_scheduler_edition_clone', $edition_node);
+
+    // Invoke hook_simplenews_scheduler_cloned_node_alter() to give installed modules a chance to
+    // modify the cloned edition node if necessary before it gets saved.
+    drupal_alter('simplenews_scheduler_cloned_node', $node, $node);
+
+    // Save the changes of other modules
+    node_save($edition_node);
+    
+    // Insert edition data.
+    $now_time = REQUEST_TIME;
+    $values = array(
+      'eid' => $edition_node->nid,
+      'pid' => $edition_node->simplenews_scheduler->nid,
+      'date_issued' => $now_time,
+    );
+    db_insert('simplenews_scheduler_editions')
+      ->fields($values)
+      ->execute();
+
     // Save taxonomy terms.
-    taxonomy_node_save($node, $terms);
     watchdog('simplenews_sched', 'Saved new node ready to be sent. Node ID: !nid', array(
-      '!nid' => $node->nid
+      '!nid' => $edition_node->nid,
     ));
-    // If the node has attachments.
-    if (isset($files) && count($files)) {
-      // Simply copy the corresponding records in files and upload tables without duplicate the file.
-      foreach ($files as $file) {
-        db_query_range("INSERT INTO {files} (uid, filename, filepath, filemime, filesize, status, timestamp) (SELECT uid, filename, filepath, filemime, filesize, status, timestamp FROM {files} WHERE filename = '%s')", $file->filename, 0, 1);
-        db_query("INSERT INTO {upload} (fid, nid, vid, list, description, weight) VALUES ((SELECT MAX(fid) AS fid FROM files WHERE filename = '%s'), %d, %d, %d, '%s', %d)", $file->filename, $node->nid, $node->vid, $file->list, $file->description, $file->weight);
-      }
-    }
-    // Prepare the correct status for Simplenews to pickup.
-    db_query("UPDATE {simplenews_newsletters} SET s_status=1 WHERE nid=%d", $node->nid);
-
-    // ensure this edition has the same simplenews_newsletter settings as the parent
-    // also ensures the 'tid' is set, so we use the same newsletter settings as the parent
-    if ($newsletter = db_fetch_array(db_query("SELECT * from {simplenews_newsletters} WHERE nid = %d", $nid))) {
-      db_query("UPDATE {simplenews_newsletters} SET s_status = 1, tid = %d, s_format = '%s', priority = %d, receipt = %d WHERE nid=%d", $newsletter['tid'], $newsletter['s_format'], $newsletter['priority'], $newsletter['receipt'], $node->nid);
-    }
 
-    // Record the new edition.
-    $now_time = gmmktime();
-    db_query("INSERT INTO {simplenews_scheduler_editions} (eid, pid, date_issued) VALUES (%d, %d, %d)", $node->nid, $nid, $now_time);
+    // Prepare the correct status for Simplenews to pickup.
+    db_update('simplenews_newsletter')
+      ->fields(array('status' => 1))
+      ->condition('nid', $edition_node->nid)
+      ->execute();
 
-    return $node->nid;
+    return $edition_node->nid;
   }
 }
 
@@ -550,17 +564,15 @@ function _simplenews_scheduler_new_edition($nid) {
  *  FALSE if the node is not part of a scheduled newsletter set.
  */
 function _simplenews_scheduler_get_pid($node) {
-  $nid = FALSE;
 
   // First assume this is a newsletter edition,
   if (isset($node->simplenews_scheduler_edition)) {
-    $nid = $node->simplenews_scheduler_edition['pid'];
+    return $node->simplenews_scheduler_edition->pid;
   }
   // or this itself is the parent newsletter.
   elseif (isset($node->simplenews_scheduler)) {
-    $nid = $node->nid;
+    return $node->nid;
   }
 
-  return $nid;
+  return FALSE;
 }
-

