Skip to content

Commit fe1ff89

Browse files
committed
Use session for display timezone
Instead of using an url param that has to be preserved by every link, form action or redirect, we now use the 'notifications' session namespace to store the display timezone for the current user. The start day for the timeline now comes from the controller, no longer from the schedule detail controls.
1 parent 66b772a commit fe1ff89

File tree

7 files changed

+83
-137
lines changed

7 files changed

+83
-137
lines changed

application/controllers/ScheduleController.php

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
namespace Icinga\Module\Notifications\Controllers;
66

7+
use DateTime;
8+
use DateTimeZone;
79
use Icinga\Module\Notifications\Common\Database;
810
use Icinga\Module\Notifications\Common\Links;
911
use Icinga\Module\Notifications\Forms\MoveRotationForm;
@@ -60,11 +62,15 @@ public function indexAction(): void
6062
})
6163
->handleRequest($this->getServerRequest());
6264

63-
$timezonePicker = $this->createTimezonePicker($schedule->timezone);
65+
$timezonePicker = $this->createTimezonePicker($schedule->timezone, $id);
6466

6567
$this->addControl($timezonePicker);
6668
$this->addControl($scheduleControls);
67-
$this->addContent(new ScheduleDetail($schedule, $scheduleControls));
69+
$this->addContent(new ScheduleDetail(
70+
$schedule,
71+
$scheduleControls,
72+
new DateTime('today', new DateTimeZone($timezonePicker->getDisplayTimezone()))
73+
));
6874
}
6975

7076
public function settingsAction(): void
@@ -118,7 +124,7 @@ public function addRotationAction(): void
118124
{
119125
$scheduleId = (int) $this->params->getRequired('schedule');
120126
$scheduleTimezone = $this->getScheduleTimezone($scheduleId);
121-
$displayTimezone = $this->params->get('display_timezone') ?? $scheduleTimezone;
127+
$displayTimezone = (new TimezonePicker($scheduleTimezone))->getDisplayTimezone();
122128
$this->setTitle($this->translate('Add Rotation'));
123129

124130
if ($displayTimezone !== $scheduleTimezone) {
@@ -157,7 +163,7 @@ public function editRotationAction(): void
157163
$id = (int) $this->params->getRequired('id');
158164
$scheduleId = (int) $this->params->getRequired('schedule');
159165
$scheduleTimezone = $this->getScheduleTimezone($scheduleId);
160-
$displayTimezone = $this->params->get('display_timezone') ?? $scheduleTimezone;
166+
$displayTimezone = (new TimezonePicker($scheduleTimezone))->getDisplayTimezone();
161167
$this->setTitle($this->translate('Edit Rotation'));
162168

163169
if ($displayTimezone !== $scheduleTimezone) {
@@ -210,13 +216,7 @@ public function moveRotationAction(): void
210216
$form = new MoveRotationForm(Database::get());
211217
$form->on(MoveRotationForm::ON_SUCCESS, function (MoveRotationForm $form) {
212218
$this->sendExtraUpdates(['#col1']);
213-
$requestUrl = Url::fromRequest();
214-
$redirectUrl = Links::schedule($form->getScheduleId());
215-
$defaultTimezoneParam = TimezonePicker::DEFAULT_TIMEZONE_PARAM;
216-
if ($requestUrl->hasParam($defaultTimezoneParam)) {
217-
$redirectUrl->addParams([$defaultTimezoneParam => $requestUrl->getParam($defaultTimezoneParam)]);
218-
}
219-
$this->redirectNow($redirectUrl);
219+
$this->redirectNow(Links::schedule($form->getScheduleId()));
220220
});
221221

222222
$form->handleRequest($this->getServerRequest());
@@ -250,28 +250,24 @@ protected function getScheduleTimezone(int $scheduleId): string
250250
/**
251251
* Create a timezone picker control
252252
*
253-
* @param string $defaultTimezone The default timezone to use if none is set in the request
253+
* @param string $scheduleTimezone The schedule timezone is used as default if no timezone is in the session
254+
* @param int $scheduleId The schedule id
254255
*
255256
* @return TimezonePicker The timezone picker control
256257
*/
257-
protected function createTimezonePicker(string $defaultTimezone): TimezonePicker
258+
protected function createTimezonePicker(string $scheduleTimezone, int $scheduleId): TimezonePicker
258259
{
259-
$defaultTimezoneParam = TimezonePicker::DEFAULT_TIMEZONE_PARAM;
260-
$timezoneParam = $this->params->shift($defaultTimezoneParam);
261-
262-
ScheduleTimezoneStorage::setDisplayTimezone($timezoneParam ?? $defaultTimezone);
263-
264-
return (new TimezonePicker())
265-
->populate([$defaultTimezoneParam => $timezoneParam ?? $defaultTimezone])
266-
->on(
267-
TimezonePicker::ON_SUBMIT,
268-
function (TimezonePicker $timezonePicker) use ($defaultTimezoneParam) {
269-
$requestUrl = Url::fromRequest();
270-
$pickedTimezone = $timezonePicker->getValue($defaultTimezoneParam);
271-
if ($requestUrl->getParam($defaultTimezoneParam) !== $pickedTimezone) {
272-
$this->redirectNow($requestUrl->with([$defaultTimezoneParam => $pickedTimezone]));
273-
}
274-
}
275-
)->handleRequest($this->getServerRequest());
260+
return (new TimezonePicker($scheduleTimezone))
261+
->populate([
262+
TimezonePicker::DEFAULT_TIMEZONE_PARAM => $this->params->get(TimezonePicker::DEFAULT_TIMEZONE_PARAM)
263+
])
264+
->on(TimezonePicker::ON_SUBMIT, function (TimezonePicker $timezonePicker) use ($scheduleId) {
265+
$this->redirectNow(
266+
Links::schedule($scheduleId)->with([
267+
TimezonePicker::DEFAULT_TIMEZONE_PARAM => $timezonePicker->getDisplayTimezone()
268+
])
269+
);
270+
})
271+
->handleRequest($this->getServerRequest());
276272
}
277273
}

library/Notifications/Common/Links.php

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Icinga\Module\Notifications\Common;
66

7-
use Icinga\Module\Notifications\Util\ScheduleTimezoneStorage;
8-
use Icinga\Module\Notifications\Web\Control\TimezonePicker;
97
use ipl\Web\Url;
108

119
/**
@@ -85,15 +83,7 @@ public static function schedules(): Url
8583

8684
public static function schedule(int $id): Url
8785
{
88-
$redirectUrl = Url::fromPath('notifications/schedule', ['id' => $id]);
89-
90-
if (ScheduleTimezoneStorage::differ()) {
91-
$redirectUrl->addParams([
92-
TimezonePicker::DEFAULT_TIMEZONE_PARAM => ScheduleTimezoneStorage::getDisplayTimezone()->getName()
93-
]);
94-
}
95-
96-
return $redirectUrl;
86+
return Url::fromPath('notifications/schedule', ['id' => $id]);
9787
}
9888

9989
public static function scheduleAdd(): Url
@@ -133,40 +123,16 @@ public static function contactGroupEdit(int $id): Url
133123

134124
public static function rotationAdd(int $scheduleId): Url
135125
{
136-
$redirectUrl = Url::fromPath('notifications/schedule/add-rotation', ['schedule' => $scheduleId]);
137-
138-
if (ScheduleTimezoneStorage::differ()) {
139-
$redirectUrl->addParams([
140-
TimezonePicker::DEFAULT_TIMEZONE_PARAM => ScheduleTimezoneStorage::getDisplayTimezone()->getName()
141-
]);
142-
}
143-
144-
return $redirectUrl;
126+
return Url::fromPath('notifications/schedule/add-rotation', ['schedule' => $scheduleId]);
145127
}
146128

147129
public static function rotationSettings(int $id, int $scheduleId): Url
148130
{
149-
$redirectUrl = Url::fromPath('notifications/schedule/edit-rotation', ['id' => $id, 'schedule' => $scheduleId]);
150-
151-
if (ScheduleTimezoneStorage::differ()) {
152-
$redirectUrl->addParams([
153-
TimezonePicker::DEFAULT_TIMEZONE_PARAM => ScheduleTimezoneStorage::getDisplayTimezone()->getName()
154-
]);
155-
}
156-
157-
return $redirectUrl;
131+
return Url::fromPath('notifications/schedule/edit-rotation', ['id' => $id, 'schedule' => $scheduleId]);
158132
}
159133

160134
public static function moveRotation(): Url
161135
{
162-
$redirectUrl = Url::fromPath('notifications/schedule/move-rotation');
163-
164-
if (ScheduleTimezoneStorage::differ()) {
165-
$redirectUrl->addParams([
166-
TimezonePicker::DEFAULT_TIMEZONE_PARAM => ScheduleTimezoneStorage::getDisplayTimezone()->getName()
167-
]);
168-
}
169-
170-
return $redirectUrl;
136+
return Url::fromPath('notifications/schedule/move-rotation');
171137
}
172138
}

library/Notifications/Util/ScheduleTimezoneStorage.php

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,76 +4,36 @@
44

55
namespace Icinga\Module\Notifications\Util;
66

7-
use DateTimeZone;
7+
use Icinga\Exception\ProgrammingError;
88

99
/**
1010
* Storage to store display and schedule timezones
1111
*/
1212
class ScheduleTimezoneStorage
1313
{
14-
protected static ?DateTimeZone $displayTimezone;
15-
16-
protected static ?DateTimeZone $scheduleTimezone;
17-
18-
/**
19-
* Set the display timezone
20-
*
21-
* @param DateTimeZone|string $timezone The timezone identifier (e.g. 'Europe/Berlin')
22-
*
23-
* @return void
24-
*/
25-
public static function setDisplayTimezone(DateTimeZone|string $timezone): void
26-
{
27-
if ($timezone instanceof DateTimeZone) {
28-
static::$displayTimezone = $timezone;
29-
} else {
30-
static::$displayTimezone = new DateTimeZone($timezone);
31-
}
32-
}
33-
34-
/**
35-
* Get the display timezone
36-
*
37-
* @return DateTimeZone
38-
*/
39-
public static function getDisplayTimezone(): DateTimeZone
40-
{
41-
return static::$displayTimezone ?? static::getScheduleTimezone();
42-
}
14+
protected static ?string $scheduleTimezone;
4315

4416
/**
4517
* Set the schedule timezone
4618
*
47-
* @param DateTimeZone|string $timezone The timezone identifier (e.g. 'Europe/Berlin')
19+
* @param string $timezone The timezone identifier (e.g. 'Europe/Berlin')
4820
*
4921
* @return void
5022
*/
51-
public static function setScheduleTimezone(DateTimeZone|string $timezone): void
23+
public static function setScheduleTimezone(string $timezone): void
5224
{
53-
if ($timezone instanceof DateTimeZone) {
54-
static::$scheduleTimezone = $timezone;
55-
} else {
56-
static::$scheduleTimezone = new DateTimeZone($timezone);
57-
}
25+
static::$scheduleTimezone = $timezone;
5826
}
5927

6028
/**
6129
* Get the schedule timezone
6230
*
63-
* @return DateTimeZone
64-
*/
65-
public static function getScheduleTimezone(): DateTimeZone
66-
{
67-
return static::$scheduleTimezone ?? new DateTimeZone(date_default_timezone_get());
68-
}
69-
70-
/**
71-
* Get whether the display and schedule timezones differ
31+
* @return string
7232
*
73-
* @return bool Whether the display and schedule timezones differ
33+
* @throws ProgrammingError In case the schedule timezone is not set
7434
*/
75-
public static function differ(): bool
35+
public static function getScheduleTimezone(): string
7636
{
77-
return static::getDisplayTimezone()->getName() !== static::getScheduleTimezone()->getName();
37+
return static::$scheduleTimezone ?? throw new ProgrammingError('Schedule timezone has to be set first');
7838
}
7939
}

library/Notifications/Web/Control/TimezonePicker.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use DateTime;
88
use DateTimeZone;
9+
use Icinga\Web\Session;
910
use IntlTimeZone;
1011
use ipl\Html\Form;
1112
use ipl\Html\HtmlElement;
@@ -26,6 +27,36 @@ class TimezonePicker extends Form
2627

2728
protected $defaultAttributes = ['class' => 'timezone-picker', 'name' => 'timezone-picker-form'];
2829

30+
protected string $defaultTimezone;
31+
32+
public function __construct(string $defaultTimezone)
33+
{
34+
$this->defaultTimezone = $defaultTimezone;
35+
}
36+
37+
/**
38+
* Get the chosen display timezone
39+
*
40+
* @return string
41+
*/
42+
public function getDisplayTimezone(): string
43+
{
44+
return $this->getPopulatedValue(static::DEFAULT_TIMEZONE_PARAM)
45+
?? Session::getSession()->getNamespace('notifications')
46+
->get('schedule.display_timezone', $this->defaultTimezone);
47+
}
48+
49+
/**
50+
* On success store the display timezone in the session
51+
*
52+
* @return void
53+
*/
54+
protected function onSuccess(): void
55+
{
56+
Session::getSession()->getNamespace('notifications')
57+
->set('schedule.display_timezone', $this->getValue(static::DEFAULT_TIMEZONE_PARAM));
58+
}
59+
2960
public function assemble(): void
3061
{
3162
$this->addElement($this->createUidElement());
@@ -52,5 +83,6 @@ public function assemble(): void
5283
);
5384
$select = $this->getElement(static::DEFAULT_TIMEZONE_PARAM);
5485
$select->prependWrapper(HtmlElement::create('div', ['class' => 'icinga-controls']));
86+
$select->setValue($this->getDisplayTimezone());
5587
}
5688
}

library/Notifications/Widget/Detail/ScheduleDetail.php

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Icinga\Module\Notifications\Widget\Detail;
66

7+
use DateTime;
78
use Icinga\Module\Notifications\Model\Schedule;
89
use Icinga\Module\Notifications\Widget\Detail\ScheduleDetail\Controls;
910
use Icinga\Module\Notifications\Widget\Timeline;
@@ -33,6 +34,9 @@ class ScheduleDetail extends BaseHtmlElement
3334
/** @var Controls */
3435
protected $controls;
3536

37+
/** @var DateTime The day the timeline should start on */
38+
protected DateTime $start;
39+
3640
/** @var bool */
3741
private bool $hasRotation = false;
3842

@@ -41,11 +45,13 @@ class ScheduleDetail extends BaseHtmlElement
4145
*
4246
* @param Schedule $schedule
4347
* @param Controls $controls
48+
* @param DateTime $start The day the timeline should start on
4449
*/
45-
public function __construct(Schedule $schedule, Controls $controls)
50+
public function __construct(Schedule $schedule, Controls $controls, DateTime $start)
4651
{
4752
$this->schedule = $schedule;
4853
$this->controls = $controls;
54+
$this->start = $start;
4955
}
5056

5157
/**
@@ -68,11 +74,7 @@ protected function assembleTimeline(Timeline $timeline): void
6874
*/
6975
protected function createTimeline(): Timeline
7076
{
71-
$timeline = new Timeline(
72-
$this->schedule->id,
73-
$this->controls->getStartDate(),
74-
$this->controls->getNumberOfDays()
75-
);
77+
$timeline = new Timeline($this->schedule->id, $this->start, $this->controls->getNumberOfDays());
7678
$timeline->setStyle(
7779
(new Style())
7880
->setNonce(Csp::getStyleNonce())

library/Notifications/Widget/Detail/ScheduleDetail/Controls.php

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
namespace Icinga\Module\Notifications\Widget\Detail\ScheduleDetail;
66

7-
use DateTime;
8-
use Icinga\Module\Notifications\Util\ScheduleTimezoneStorage;
97
use Icinga\Web\Session;
108
use ipl\Html\Attributes;
119
use ipl\Html\Form;
@@ -58,16 +56,6 @@ public function getNumberOfDays(): int
5856
}
5957
}
6058

61-
/**
62-
* Get the start date where the user wants the schedule to begin
63-
*
64-
* @return DateTime
65-
*/
66-
public function getStartDate(): DateTime
67-
{
68-
return (new DateTime('today', ScheduleTimezoneStorage::getDisplayTimezone()));
69-
}
70-
7159
protected function onSuccess()
7260
{
7361
Session::getSession()->getNamespace('notifications')

0 commit comments

Comments
 (0)