Skip to content

Commit 4959783

Browse files
committed
Use immutable DateTime
Ensure DateTime cannot be accidentally mutated when passed as an argument.
1 parent 8307769 commit 4959783

File tree

13 files changed

+56
-65
lines changed

13 files changed

+56
-65
lines changed

src/controllers/Index.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function home(): void {
8383

8484
$lastUpdate = $this->itemsDao->lastUpdate();
8585
$result = [
86-
'lastUpdate' => $lastUpdate !== null ? $lastUpdate->format(\DateTime::ATOM) : null,
86+
'lastUpdate' => $lastUpdate !== null ? $lastUpdate->format(\DateTimeImmutable::ATOM) : null,
8787
'hasMore' => $items['hasMore'],
8888
'entries' => $items['entries'],
8989
'all' => $statsAll,

src/controllers/Items/Sync.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,26 +49,26 @@ public function sync(): void {
4949
$this->view->jsonError(['sync' => 'missing since argument']);
5050
}
5151

52-
$since = new \DateTime($params['since']);
53-
$since->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
52+
$since = new \DateTimeImmutable($params['since']);
53+
$since = $since->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
5454

5555
$lastUpdate = $this->itemsDao->lastUpdate();
5656

5757
$sync = [
58-
'lastUpdate' => $lastUpdate !== null ? $lastUpdate->format(\DateTime::ATOM) : null,
58+
'lastUpdate' => $lastUpdate !== null ? $lastUpdate->format(\DateTimeImmutable::ATOM) : null,
5959
];
6060

6161
if (array_key_exists('itemsSinceId', $params)) {
6262
$sinceId = (int) $params['itemsSinceId'];
6363
if ($sinceId >= 0) {
64-
$notBefore = isset($params['itemsNotBefore']) ? new \DateTime($params['itemsNotBefore']) : null;
64+
$notBefore = isset($params['itemsNotBefore']) ? new \DateTimeImmutable($params['itemsNotBefore']) : null;
6565
if ($sinceId === 0 || !$notBefore) {
6666
$sinceId = $this->itemsDao->lowestIdOfInterest() - 1;
6767
// only send 1 day worth of items
68-
$notBefore = new \DateTime();
69-
$notBefore->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
70-
$notBefore->sub(new \DateInterval('P1D'));
71-
$notBefore->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
68+
$notBefore = new \DateTimeImmutable();
69+
$notBefore = $notBefore->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
70+
$notBefore = $notBefore->sub(new \DateInterval('P1D'));
71+
$notBefore = $notBefore->setTimeZone(new \DateTimeZone(date_default_timezone_get()));
7272
}
7373

7474
$itemsHowMany = $this->configuration->itemsPerpage;

src/controllers/Rss.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public function rss(): void {
7575
$newItem->setTitle($this->sanitizeTitle($item['title'] . ' (' . $lastSourceName . ')'));
7676
@$newItem->setLink($item['link']);
7777
@$newItem->setId($item['link']);
78-
$newItem->setDate($item['datetime']);
78+
$newItem->setDate(DateTime::createFromImmutable($item['datetime']));
7979
$newItem->setDescription(str_replace('"', '"', $item['content']));
8080

8181
// add tags in category node
@@ -96,9 +96,9 @@ public function rss(): void {
9696
}
9797

9898
if ($newestEntryDate === null) {
99-
$newestEntryDate = new \DateTime();
99+
$newestEntryDate = new \DateTimeImmutable();
100100
}
101-
$this->feedWriter->setDate($newestEntryDate);
101+
$this->feedWriter->setDate(DateTime::createFromImmutable($newestEntryDate));
102102

103103
$this->feedWriter->printFeed();
104104
}

src/daos/ItemOptions.php

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

55
namespace daos;
66

7-
use DateTime;
7+
use DateTimeImmutable;
88

99
/**
1010
* Object holding parameters for querying items.
@@ -24,13 +24,13 @@ final class ItemOptions {
2424
public ?int $pageSize = null;
2525

2626
/** @readonly */
27-
public ?DateTime $fromDatetime = null;
27+
public ?DateTimeImmutable $fromDatetime = null;
2828

2929
/** @readonly */
3030
public ?int $fromId = null;
3131

3232
/** @readonly */
33-
public ?DateTime $updatedSince = null;
33+
public ?DateTimeImmutable $updatedSince = null;
3434

3535
/** @readonly */
3636
public ?string $tag = null;
@@ -71,15 +71,15 @@ public static function fromUser(array $data): self {
7171
}
7272

7373
if (isset($data['fromDatetime']) && is_string($data['fromDatetime']) && strlen($data['fromDatetime']) > 0) {
74-
$options->fromDatetime = new \DateTime($data['fromDatetime']);
74+
$options->fromDatetime = new \DateTimeImmutable($data['fromDatetime']);
7575
}
7676

7777
if (isset($data['fromId']) && is_numeric($data['fromId'])) {
7878
$options->fromId = (int) $data['fromId'];
7979
}
8080

8181
if (isset($data['updatedsince']) && is_string($data['updatedsince']) && strlen($data['updatedsince']) > 0) {
82-
$options->updatedSince = new \DateTime($data['updatedsince']);
82+
$options->updatedSince = new \DateTimeImmutable($data['updatedsince']);
8383
}
8484

8585
if (isset($data['tag']) && is_string($data['tag']) && strlen($tag = trim($data['tag'])) > 0) {

src/daos/Items.php

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

55
namespace daos;
66

7-
use DateTime;
87
use DateTimeImmutable;
98
use helpers\Authentication;
109

@@ -60,7 +59,7 @@ public function updateLastSeen(array $itemIds): void {
6059
$this->backend->updateLastSeen($itemIds);
6160
}
6261

63-
public function cleanup(?DateTime $minDate): void {
62+
public function cleanup(?DateTimeImmutable $minDate): void {
6463
$this->backend->cleanup($minDate);
6564
}
6665

@@ -69,7 +68,7 @@ public function cleanup(?DateTime $minDate): void {
6968
*
7069
* @param ItemOptions $options search, offset and filter params
7170
*
72-
* @return array<array{id: int, datetime: DateTime, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTime, author: string, sourcetitle: string, tags: string[]}> items as array
71+
* @return array<array{id: int, datetime: DateTimeImmutable, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTimeImmutable, author: string, sourcetitle: string, tags: string[]}> items as array
7372
*/
7473
public function get(ItemOptions $options): array {
7574
$items = $this->backend->get($options);
@@ -107,7 +106,7 @@ public function hasMore(): bool {
107106
return $this->backend->hasMore();
108107
}
109108

110-
public function sync(int $sinceId, DateTime $notBefore, DateTime $since, int $howMany): array {
109+
public function sync(int $sinceId, DateTimeImmutable $notBefore, DateTimeImmutable $since, int $howMany): array {
111110
return $this->backend->sync($sinceId, $notBefore, $since, $howMany);
112111
}
113112

@@ -147,7 +146,7 @@ public function lastUpdate(): ?DateTimeImmutable {
147146
return $this->backend->lastUpdate();
148147
}
149148

150-
public function statuses(DateTime $since): array {
149+
public function statuses(DateTimeImmutable $since): array {
151150
return $this->backend->statuses($since);
152151
}
153152

src/daos/ItemsInterface.php

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

55
namespace daos;
66

7-
use DateTime;
87
use DateTimeImmutable;
98
use helpers\HtmlString;
109

@@ -73,16 +72,16 @@ public function updateLastSeen(array $itemIds): void;
7372
/**
7473
* cleanup orphaned and old items
7574
*
76-
* @param ?DateTime $date date to delete all items older than this value
75+
* @param ?DateTimeImmutable $date date to delete all items older than this value
7776
*/
78-
public function cleanup(?DateTime $date): void;
77+
public function cleanup(?DateTimeImmutable $date): void;
7978

8079
/**
8180
* returns items
8281
*
8382
* @param ItemOptions $options search, offset and filter params
8483
*
85-
* @return array<array{id: int, datetime: DateTime, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTime, author: string, sourcetitle: string, tags: string[]}> items as array
84+
* @return array<array{id: int, datetime: DateTimeImmutable, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTimeImmutable, author: string, sourcetitle: string, tags: string[]}> items as array
8685
*/
8786
public function get(ItemOptions $options): array;
8887

@@ -96,12 +95,12 @@ public function hasMore(): bool;
9695
* Obtain new or changed items in the database for synchronization with clients.
9796
*
9897
* @param int $sinceId id of last seen item
99-
* @param DateTime $notBefore cut off time stamp
100-
* @param DateTime $since timestamp of last seen item
98+
* @param DateTimeImmutable $notBefore cut off time stamp
99+
* @param DateTimeImmutable $since timestamp of last seen item
101100
*
102-
* @return array<array{id: int, datetime: DateTime, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTime, author: string, sourcetitle: string, tags: string[]}> of items
101+
* @return array<array{id: int, datetime: DateTimeImmutable, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTimeImmutable, author: string, sourcetitle: string, tags: string[]}> of items
103102
*/
104-
public function sync(int $sinceId, DateTime $notBefore, DateTime $since, int $howMany): array;
103+
public function sync(int $sinceId, DateTimeImmutable $notBefore, DateTimeImmutable $since, int $howMany): array;
105104

106105
/**
107106
* Lowest id of interest
@@ -171,11 +170,11 @@ public function lastUpdate(): ?DateTimeImmutable;
171170
/**
172171
* returns the statuses of items last update
173172
*
174-
* @param DateTime $since minimal date of returned items
173+
* @param DateTimeImmutable $since minimal date of returned items
175174
*
176175
* @return array<array{id: int, unread: bool, starred: bool}> of unread, starred, etc. status of specified items
177176
*/
178-
public function statuses(DateTime $since): array;
177+
public function statuses(DateTimeImmutable $since): array;
179178

180179
/**
181180
* bulk update of item status

src/daos/StatementsInterface.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,9 @@ public static function bool(bool $bool): string;
9393
* Convert a date into a representation suitable for comparison by
9494
* the database engine.
9595
*
96-
* @param \DateTime $date datetime
97-
*
9896
* @return string representation of datetime
9997
*/
100-
public static function datetime(\DateTime $date): string;
98+
public static function datetime(\DateTimeImmutable $date): string;
10199

102100
/**
103101
* Ensure row values have the appropriate PHP type. This assumes we are

src/daos/mysql/Items.php

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

77
use daos\DatabaseInterface;
88
use daos\ItemOptions;
9-
use DateTime;
109
use DateTimeImmutable;
1110
use helpers\Configuration;
1211
use helpers\HtmlString;
@@ -206,9 +205,9 @@ public function updateLastSeen(array $itemIds): void {
206205
/**
207206
* cleanup orphaned and old items
208207
*
209-
* @param ?DateTime $date date to delete all items older than this value
208+
* @param ?DateTimeImmutable $date date to delete all items older than this value
210209
*/
211-
public function cleanup(?DateTime $date): void {
210+
public function cleanup(?DateTimeImmutable $date): void {
212211
$this->database->exec('DELETE FROM ' . $this->configuration->dbPrefix . 'items
213212
WHERE source NOT IN (
214213
SELECT id FROM ' . $this->configuration->dbPrefix . 'sources)');
@@ -226,7 +225,7 @@ public function cleanup(?DateTime $date): void {
226225
*
227226
* @param ItemOptions $options search, offset and filter params
228227
*
229-
* @return array<array{id: int, datetime: DateTime, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTime, author: string, sourcetitle: string, tags: string[]}> items as array
228+
* @return array<array{id: int, datetime: DateTimeImmutable, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTimeImmutable, author: string, sourcetitle: string, tags: string[]}> items as array
230229
*/
231230
public function get(ItemOptions $options): array {
232231
$params = [];
@@ -375,12 +374,12 @@ public function hasMore(): bool {
375374
* Obtain new or changed items in the database for synchronization with clients.
376375
*
377376
* @param int $sinceId id of last seen item
378-
* @param DateTime $notBefore cut off time stamp
379-
* @param DateTime $since timestamp of last seen item
377+
* @param DateTimeImmutable $notBefore cut off time stamp
378+
* @param DateTimeImmutable $since timestamp of last seen item
380379
*
381-
* @return array<array{id: int, datetime: DateTime, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTime, author: string, sourcetitle: string, tags: string[]}> of items
380+
* @return array<array{id: int, datetime: DateTimeImmutable, title: string, content: string, unread: bool, starred: bool, source: int, thumbnail: string, icon: string, uid: string, link: string, updatetime: DateTimeImmutable, author: string, sourcetitle: string, tags: string[]}> of items
382381
*/
383-
public function sync(int $sinceId, DateTime $notBefore, DateTime $since, int $howMany): array {
382+
public function sync(int $sinceId, DateTimeImmutable $notBefore, DateTimeImmutable $since, int $howMany): array {
384383
$query = 'SELECT
385384
items.id, datetime, items.title AS title, content, unread, starred, source, thumbnail, icon, uid, link, updatetime, author, sources.title as sourcetitle, sources.tags as tags
386385
FROM ' . $this->configuration->dbPrefix . 'items AS items, ' . $this->configuration->dbPrefix . 'sources AS sources
@@ -575,11 +574,11 @@ public function lastUpdate(): ?DateTimeImmutable {
575574
/**
576575
* returns the statuses of items last update
577576
*
578-
* @param DateTime $since minimal date of returned items
577+
* @param DateTimeImmutable $since minimal date of returned items
579578
*
580579
* @return array<array{id: int, unread: bool, starred: bool}> of unread, starred, etc. status of specified items
581580
*/
582-
public function statuses(DateTime $since): array {
581+
public function statuses(DateTimeImmutable $since): array {
583582
$res = $this->database->exec(
584583
'SELECT id, unread, starred
585584
FROM ' . $this->configuration->dbPrefix . 'items
@@ -627,7 +626,7 @@ public function bulkStatusUpdate(array $statuses): void {
627626

628627
// sanitize update time
629628
if (array_key_exists('datetime', $status)) {
630-
$updateDate = new \DateTime($status['datetime']);
629+
$updateDate = new \DateTimeImmutable($status['datetime']);
631630
} else {
632631
$updateDate = null;
633632
}

src/daos/mysql/Statements.php

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,13 +128,11 @@ public static function bool(bool $bool): string {
128128
* Convert a date into a representation suitable for comparison by
129129
* the database engine.
130130
*
131-
* @param \DateTime $date datetime
132-
*
133131
* @return string representation of datetime
134132
*/
135-
public static function datetime(\DateTime $date): string {
133+
public static function datetime(\DateTimeImmutable $date): string {
136134
// mysql supports ISO8601 datetime comparisons
137-
return $date->format(\DateTime::ATOM);
135+
return $date->format(\DateTimeImmutable::ATOM);
138136
}
139137

140138
/**
@@ -179,7 +177,7 @@ public static function ensureRowTypes(array $rows, array $expectedRowTypes): arr
179177
}
180178
break;
181179
case DatabaseInterface::PARAM_DATETIME:
182-
$value = new \DateTime($row[$columnIndex]);
180+
$value = new \DateTimeImmutable($row[$columnIndex]);
183181
break;
184182
default:
185183
$value = null;

src/daos/pgsql/Statements.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public static function ensureRowTypes(array $rows, array $expectedRowTypes): arr
104104
}
105105
break;
106106
case DatabaseInterface::PARAM_DATETIME:
107-
$value = new \DateTime($row[$columnIndex]);
107+
$value = new \DateTimeImmutable($row[$columnIndex]);
108108
break;
109109
default:
110110
$value = null;

0 commit comments

Comments
 (0)