diff --git a/scheduler.install b/scheduler.install index 484be85..3e02794 100644 --- a/scheduler.install +++ b/scheduler.install @@ -61,6 +61,7 @@ function scheduler_uninstall() { $variables[] = "scheduler_publish_touch_" . $type_name; $variables[] = "scheduler_publish_required_" . $type_name; $variables[] = "scheduler_publish_revision_" . $type_name; + $variables[] = "scheduler_publish_past_date_" . $type_name; $variables[] = "scheduler_unpublish_enable_" . $type_name; $variables[] = "scheduler_unpublish_required_" . $type_name; $variables[] = "scheduler_unpublish_revision_" . $type_name; diff --git a/scheduler.module b/scheduler.module index d1e9d0e..b86c78b 100644 --- a/scheduler.module +++ b/scheduler.module @@ -249,6 +249,27 @@ function scheduler_form_node_type_form_alter(&$form, $form_state) { '#title' => t('Create a new revision on publishing'), '#default_value' => variable_get('scheduler_publish_revision_' . $form['#node_type']->type, 0), ); + $form['scheduler']['publish']['advanced'] = array( + '#type' => 'fieldset', + '#title' => t('Advanced options'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#states' => array( + 'visible' => array( + ':input[name="scheduler_publish_enable"]' => array('checked' => TRUE), + ), + ), + ); + $form['scheduler']['publish']['advanced']['scheduler_publish_past_date'] = array( + '#type' => 'radios', + '#title' => t('Action to be taken for publication dates in the past'), + '#default_value' => variable_get('scheduler_publish_past_date_' . $form['#node_type']->type, 'error'), + '#options' => array( + 'error' => t('Display an error message - do not allow dates in the past'), + 'publish' => t('Publish the content immediately after saving'), + 'schedule' => t('Schedule the content for publication on the next cron run'), + ), + ); $form['scheduler']['unpublish'] = array( '#type' => 'fieldset', '#title' => t('Unpublishing'), @@ -653,7 +674,7 @@ function scheduler_node_validate($node, $form) { if ($publishtime === FALSE) { form_set_error('publish_on', t("The 'publish on' value does not match the expected format of %time", array('%time' => format_date(REQUEST_TIME, 'custom', $date_format)))); } - elseif ($publishtime && $publishtime < REQUEST_TIME) { + elseif ($publishtime && variable_get('scheduler_publish_past_date_' . $node->type, 'error') == 'error' && $publishtime < REQUEST_TIME) { form_set_error('publish_on', t("The 'publish on' date must be in the future")); } } @@ -682,12 +703,22 @@ function scheduler_node_presave($node) { $node->$key = 0; } elseif (!is_numeric($node->$key)) { - $node->$key = _scheduler_strtotime($node->$key); + // Convert to unix timestamp, but ensure any failure is converted to zero. + $node->$key = _scheduler_strtotime($node->$key) + 0; + } + } + // Publish the node immediately if the publication date is in the past. + if (variable_get('scheduler_publish_past_date_' . $node->type, 'error') == 'publish' && !empty($node->publish_on) && $node->publish_on <= REQUEST_TIME) { + // If required, set the created date to match published date. + if (variable_get('scheduler_publish_touch_' . $node->type, 0) == 1) { + $node->created = $node->publish_on; } + $node->publish_on = 0; + $node->status = 1; } - // Right before we save the node, we need to check if a "publish on" value has been set. - // If it has been set, we want to make sure the node is unpublished since it will be published at a later date - if (isset($node->publish_on) && $node->publish_on != '' && is_numeric($node->publish_on) && $node->publish_on > REQUEST_TIME) { + // Otherwise, if a publishing date has been set, make sure the node is + // unpublished since it will be published by cron later. + elseif ($node->publish_on > 0) { $node->status = 0; $date_format = variable_get('scheduler_date_format', SCHEDULER_DATE_FORMAT); drupal_set_message(t('This post is unpublished and will be published @publish_time.', array('@publish_time' => format_date($node->publish_on, 'custom', $date_format))), 'status', FALSE); @@ -742,6 +773,7 @@ function scheduler_node_type_delete($info) { $variables[] = "scheduler_publish_touch_" . $info->type; $variables[] = "scheduler_publish_required_" . $info->type; $variables[] = "scheduler_publish_revision_" . $info->type; + $variables[] = "scheduler_publish_past_date_" . $info->type; $variables[] = "scheduler_unpublish_enable_" . $info->type; $variables[] = "scheduler_unpublish_required_" . $info->type; $variables[] = "scheduler_unpublish_revision_" . $info->type; diff --git a/scheduler.test b/scheduler.test index 87c0ce8..7cea844 100644 --- a/scheduler.test +++ b/scheduler.test @@ -40,6 +40,7 @@ class SchedulerTestCase extends DrupalWebTestCase { // Add scheduler functionality to the page node type. variable_set('scheduler_publish_enable_page', 1); variable_set('scheduler_unpublish_enable_page', 1); + variable_set('scheduler_publish_touch_page', 1); } function testScheduler() { @@ -84,4 +85,53 @@ class SchedulerTestCase extends DrupalWebTestCase { $this->assertNoText($body, t('Node is unpublished')); } } + + /** + * Test the different options for past publication dates. + */ + public function testSchedulerPastDates() { + // Log in. + $this->drupalLogin($this->admin_user); + + // Create an unpublished page node. + $node = $this->drupalCreateNode(array('type' => 'page', 'status' => FALSE)); + + // Test the default behavior: an error message should be shown when the user + // enters a publication date that is in the past. + $edit = array( + 'title' => $this->randomName(), + 'publish_on' => format_date(strtotime('-1 day'), 'custom', 'Y-m-d H:i:s'), + ); + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); + $this->assertRaw(format_string("The 'publish on' date must be in the future"), 'An error message is shown when the publication date is in the past and the "error" behavior is chosen.'); + + // Test the 'publish' behavior: the node should be published immediately. + variable_set('scheduler_publish_past_date_page', 'publish'); + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); + $this->assertNoRaw(format_string("The 'publish on' date must be in the future"), 'No error message is shown when the publication date is in the past and the "publish" behavior is chosen.'); + $this->assertRaw(format_string('@type %title has been updated.', array('@type' => 'Basic page', '%title' => check_plain($edit['title']))), 'The node is saved successfully when the publication date is in the past and the "publish" behavior is chosen.'); + + // Reload the changed node and check that it is published. + $node = node_load($node->nid, NULL, TRUE); + $this->assertTrue($node->status, 'The node has been published immediately when the publication date is in the past and the "publish" behavior is chosen.'); + $this->assertEqual(format_date($node->created, 'custom', 'Y-m-d H:i:s'), $edit['publish_on'], 'The node "created date" has been changed to match the "publish on" date'); + + // Test the 'schedule' behavior: the node should be unpublished and become + // published on the next cron run. + variable_set('scheduler_publish_past_date_page', 'schedule'); + $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save')); + $this->assertNoRaw(format_string("The 'publish on' date must be in the future"), 'No error message is shown when the publication date is in the past and the "schedule" behavior is chosen.'); + $this->assertRaw(format_string('@type %title has been updated.', array('@type' => 'Basic page', '%title' => check_plain($edit['title']))), 'The node is saved successfully when the publication date is in the past and the "schedule" behavior is chosen.'); + $this->assertRaw(format_string('This post is unpublished and will be published @publish_time.', array('@publish_time' => $edit['publish_on'])), 'The node is scheduled to be published when the publication date is in the past and the "schedule" behavior is chosen.'); + + // Reload the node and check that it is unpublished but scheduled correctly. + $node = node_load($node->nid, NULL, TRUE); + $this->assertFalse($node->status, 'The node has been unpublished when the publication date is in the past and the "schedule" behavior is chosen.'); + $this->assertEqual(format_date($node->publish_on, 'custom', 'Y-m-d H:i:s'), $edit['publish_on'], 'The node is scheduled for the required date'); + + // Simulate a cron run and check that the node is published. + scheduler_cron(); + $node = node_load($node->nid, NULL, TRUE); + $this->assertTrue($node->status, 'The node with publication date in the past and the "schedule" behavior has now been published by cron.'); + } }