Skip to content

Commit a57c30f

Browse files
authored
Reset last run state when enabling email sending (#96)
* Refactored last run setting and checking into a service * Reset last run state when enabling email sending #94
1 parent 8279993 commit a57c30f

8 files changed

+244
-17
lines changed

modules/localgov_workflows_notifications/localgov_workflows_notifications.install

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,16 @@ function localgov_workflows_notifications_install($is_syncing) {
2727
}
2828
}
2929

30-
// Initialise last_email_run state variable.
31-
$request_time = \Drupal::time()->getRequestTime();
32-
\Drupal::state()->set('localgov_workflows_notifications.last_email_run', $request_time);
30+
// Initialise notification timer.
31+
\Drupal::service('localgov_workflows_notifications.notification_timer')->update();
3332
}
3433

3534
/**
36-
* Initialise last_email_run state variable.
35+
* Update notification timer if not already.
3736
*/
3837
function localgov_workflows_notifications_update_10001(&$sandbox) {
39-
40-
$last_run = \Drupal::state()->get('localgov_workflows_notifications.last_email_run');
41-
if (is_null($last_run)) {
42-
$request_time = \Drupal::time()->getRequestTime();
43-
\Drupal::state()->set('localgov_workflows_notifications.last_email_run', $request_time);
38+
$timer = \Drupal::service('localgov_workflows_notifications.notification_timer');
39+
if (is_null($timer->getLastRun())) {
40+
$timer->update();
4441
}
4542
}

modules/localgov_workflows_notifications/localgov_workflows_notifications.module

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,12 @@ function localgov_workflows_notifications_cron(): void {
130130
}
131131

132132
// Enqueue email notification for content past its needs review date.
133-
$request_time = \Drupal::time()->getRequestTime();
134-
$last_run = \Drupal::state()->get('localgov_workflows_notifications.last_email_run', $request_time);
135-
$next_run = $last_run + 86400 * $settings->get('email_frequency');
136-
if ($request_time >= $next_run) {
133+
$notification_timer = \Drupal::service('localgov_workflows_notifications.notification_timer');
134+
if ($notification_timer->trigger()) {
137135

138136
// Get review date IDs that need have passed their review date.
137+
$request_time = \Drupal::time()->getRequestTime();
138+
$last_run = $notification_timer->getLastRun();
139139
$storage = \Drupal::entityTypeManager()->getStorage('review_date');
140140
$review_date_ids = $storage->getQuery()
141141
->condition('active', 1)
@@ -156,7 +156,7 @@ function localgov_workflows_notifications_cron(): void {
156156
}
157157
}
158158

159-
\Drupal::state()->set('localgov_workflows_notifications.last_email_run', $request_time);
159+
$notification_timer->update();
160160
}
161161
}
162162

modules/localgov_workflows_notifications/localgov_workflows_notifications.services.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,7 @@ services:
22
localgov_workflows_notifications.notifier:
33
class: Drupal\localgov_workflows_notifications\WorkflowNotification
44
arguments: ['@queue']
5+
6+
localgov_workflows_notifications.notification_timer:
7+
class: Drupal\localgov_workflows_notifications\NotificationTimer
8+
arguments: ['@config.factory', '@state', '@datetime.time']

modules/localgov_workflows_notifications/src/Form/LocalgovWorkflowsNotificationsSettingsForm.php

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,50 @@
22

33
namespace Drupal\localgov_workflows_notifications\Form;
44

5+
use Drupal\Core\Config\ConfigFactoryInterface;
56
use Drupal\Core\Form\ConfigFormBase;
67
use Drupal\Core\Form\FormStateInterface;
8+
use Drupal\localgov_workflows_notifications\NotificationTimer;
9+
use Symfony\Component\DependencyInjection\ContainerInterface;
710

811
/**
912
* Configure LocalGov Workflows Notifications settings for the site.
1013
*/
1114
final class LocalgovWorkflowsNotificationsSettingsForm extends ConfigFormBase {
1215

16+
/**
17+
* The notification timer.
18+
*
19+
* @var \Drupal\localgov_workflows_notifications\NotificationTimer
20+
*/
21+
protected NotificationTimer $timer;
22+
23+
/**
24+
* Constructs a \Drupal\system\ConfigFormBase object.
25+
*
26+
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
27+
* The factory for configuration objects.
28+
* @param \Drupal\localgov_workflows_notifications\NotificationTimer $notification_timer
29+
* The notification timer service.
30+
* @param \Drupal\Core\Config\TypedConfigManagerInterface|null $typedConfigManager
31+
* The typed config manager.
32+
*/
33+
public function __construct(ConfigFactoryInterface $config_factory, NotificationTimer $notification_timer, protected $typedConfigManager = NULL) {
34+
$this->timer = $notification_timer;
35+
parent::__construct($config_factory, $typedConfigManager);
36+
}
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
public static function create(ContainerInterface $container) {
42+
return new static(
43+
$container->get('config.factory'),
44+
$container->get('localgov_workflows_notifications.notification_timer'),
45+
$container->get('config.typed')
46+
);
47+
}
48+
1349
/**
1450
* {@inheritdoc}
1551
*/
@@ -49,11 +85,19 @@ public function buildForm(array $form, FormStateInterface $form_state): array {
4985
* {@inheritdoc}
5086
*/
5187
public function submitForm(array &$form, FormStateInterface $form_state): void {
88+
$settings = $this->config('localgov_workflows_notifications.settings');
89+
90+
// If email notifications are being enabled reset timer last run.
91+
if ($settings->get('email_enabled') === FALSE && $form_state->getValue('email_enabled') === 1) {
92+
$this->timer->update();
93+
}
5294

53-
$this->config('localgov_workflows_notifications.settings')
95+
// Save settings.
96+
$settings
5497
->set('email_enabled', $form_state->getValue('email_enabled'))
5598
->set('email_frequency', $form_state->getValue('email_frequency'))
5699
->save();
100+
57101
parent::submitForm($form, $form_state);
58102
}
59103

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Drupal\localgov_workflows_notifications;
4+
5+
use Drupal\Component\Datetime\TimeInterface;
6+
use Drupal\Core\Config\ConfigFactoryInterface;
7+
use Drupal\Core\Config\ImmutableConfig;
8+
use Drupal\Core\State\StateInterface;
9+
10+
/**
11+
* Handle timing when to send notifications.
12+
*/
13+
class NotificationTimer implements NotificationTimerInterface {
14+
15+
/**
16+
* Module settings.
17+
*
18+
* @var \Drupal\Core\Config\ImmutableConfig
19+
*/
20+
protected ImmutableConfig $settings;
21+
22+
/**
23+
* The state service.
24+
*
25+
* @var \Drupal\Core\State\StateInterface
26+
*/
27+
protected StateInterface $state;
28+
29+
/**
30+
* The time service.
31+
*
32+
* @var \Drupal\Component\Datetime\TimeInterface
33+
*/
34+
protected TimeInterface $time;
35+
36+
/**
37+
* Constructs a NotificationTimer object.
38+
*/
39+
public function __construct(ConfigFactoryInterface $config_factory, StateInterface $state, TimeInterface $time) {
40+
$this->settings = $config_factory->get('localgov_workflows_notifications.settings');
41+
$this->state = $state;
42+
$this->time = $time;
43+
}
44+
45+
/**
46+
* {@inheritdoc}
47+
*/
48+
public function getLastRun(): ?int {
49+
return $this->state->get(self::LAST_RUN);
50+
}
51+
52+
/**
53+
* {@inheritdoc}
54+
*/
55+
public function update(): void {
56+
$request_time = $this->time->getRequestTime();
57+
$this->state->set(self::LAST_RUN, $request_time);
58+
}
59+
60+
/**
61+
* {@inheritdoc}
62+
*/
63+
public function trigger(): bool {
64+
$request_time = $this->time->getRequestTime();
65+
$last_run = $this->state->get(self::LAST_RUN, $request_time);
66+
$next_run = $last_run + 86400 * $this->settings->get('email_frequency');
67+
if ($request_time >= $next_run) {
68+
return TRUE;
69+
}
70+
71+
return FALSE;
72+
}
73+
74+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Drupal\localgov_workflows_notifications;
4+
5+
/**
6+
* Interface for handling notification timing.
7+
*/
8+
interface NotificationTimerInterface {
9+
10+
/**
11+
* Last notification state variable name.
12+
*
13+
* @var string
14+
*/
15+
const LAST_RUN = 'localgov_workflows_notifications.last_email_run';
16+
17+
/**
18+
* Get the last time notifications were triggered.
19+
*
20+
* @return int|null
21+
* Timestamp of last notification.
22+
*/
23+
public function getLastRun(): ?int;
24+
25+
/**
26+
* Update the notification timer.
27+
*/
28+
public function update(): void;
29+
30+
/**
31+
* Is it time to trigger notification sending?
32+
*/
33+
public function trigger(): bool;
34+
35+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
namespace Drupal\Tests\localgov_workflows_notifications\Functional;
4+
5+
use Drupal\Core\State\StateInterface;
6+
use Drupal\localgov_workflows_notifications\NotificationTimerInterface;
7+
use Drupal\Tests\BrowserTestBase;
8+
9+
/**
10+
* Test settings form.
11+
*/
12+
class WorkflowNotificationSettingsTest extends BrowserTestBase {
13+
14+
/**
15+
* {@inheritdoc}
16+
*/
17+
protected $profile = 'testing';
18+
19+
/**
20+
* {@inheritdoc}
21+
*/
22+
protected $defaultTheme = 'stark';
23+
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
protected static $modules = [
28+
'localgov_workflows_notifications',
29+
];
30+
31+
/**
32+
* The state service.
33+
*
34+
* @var \Drupal\Core\State\StateInterface
35+
*/
36+
protected StateInterface $state;
37+
38+
/**
39+
* {@inheritdoc}
40+
*/
41+
protected function setUp(): void {
42+
parent::setUp();
43+
44+
$this->drupalLogin($this->rootUser);
45+
}
46+
47+
/**
48+
* Test the Localgov Workflows Notifications settings form.
49+
*/
50+
public function testSettingsForm() {
51+
$last_run = \Drupal::state()->get(NotificationTimerInterface::LAST_RUN);
52+
53+
// Test settings get saved.
54+
$this->drupalGet('/admin/config/workflow/localgov-workflows-notifications');
55+
$this->submitForm([
56+
'email_enabled' => FALSE,
57+
'email_frequency' => 2,
58+
], 'Save configuration');
59+
$settings = \Drupal::config('localgov_workflows_notifications.settings');
60+
$this->assertFalse($settings->get('email_enabled'));
61+
$this->assertEquals(2, $settings->get('email_frequency'));
62+
63+
// Test notification timer gets reset when email notifications are enabled.
64+
$this->drupalGet('/admin/config/workflow/localgov-workflows-notifications');
65+
$this->submitForm([
66+
'email_enabled' => TRUE,
67+
], 'Save configuration');
68+
$new_last_run = \Drupal::state()->get(NotificationTimerInterface::LAST_RUN);
69+
$this->assertGreaterThan($last_run, $new_last_run);
70+
}
71+
72+
}

modules/localgov_workflows_notifications/tests/src/Kernel/ReviewNotificationCronHookTest.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Drupal\Core\Queue\QueueInterface;
66
use Drupal\KernelTests\KernelTestBase;
77
use Drupal\localgov_workflows_notifications\Entity\LocalgovServiceContact;
8+
use Drupal\localgov_workflows_notifications\NotificationTimerInterface;
89
use Drupal\localgov_workflows_notifications\Plugin\QueueWorker\EmailNotificationQueueWorker;
910
use Drupal\node\Entity\Node;
1011
use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
@@ -98,7 +99,7 @@ protected function setUp(): void {
9899
]);
99100

100101
$this->queue = \Drupal::queue(EmailNotificationQueueWorker::QUEUE_NAME);
101-
\Drupal::state()->set('localgov_workflows_notifications.last_email_run', 0);
102+
\Drupal::state()->set(NotificationTimerInterface::LAST_RUN, 0);
102103
}
103104

104105
/**
@@ -125,7 +126,7 @@ public function testEnqueueNodes() {
125126
// Check notification queue after cron hook with state config.
126127
$request_time = \Drupal::time()->getRequestTime();
127128
$reviewed = $request_time - 3600;
128-
\Drupal::state()->set('localgov_workflows_notifications.last_email_run', $reviewed - 86400);
129+
\Drupal::state()->set(NotificationTimerInterface::LAST_RUN, $reviewed - 86400);
129130
$review_date = \Drupal::entityTypeManager()->getStorage('review_date')->create([
130131
'entity' => [
131132
['target_id' => $this->node->id()],

0 commit comments

Comments
 (0)