Skip to content

Commit 2f792ba

Browse files
committed
Move version date manipulations into VersionData handler.
1 parent 22c0bf8 commit 2f792ba

7 files changed

Lines changed: 225 additions & 45 deletions

File tree

bin/test-dates.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
use phpweb\Releases\VersionData;
5+
6+
PHP_SAPI == 'cli' or die("Please run this script using the cli sapi");
7+
8+
require_once __DIR__ . "/../src/autoload.php";
9+
10+
function assertEqual(mixed $new, mixed $old, string $message) {
11+
if ($new !== $old) {
12+
fwrite(STDERR, "{$message}\n");
13+
fwrite(STDERR, 'New = ' . var_export($new, true) . "\n");
14+
fwrite(STDERR, 'Old = ' . var_export($old, true) . "\n\n");
15+
}
16+
};
17+
18+
foreach (VersionData::all() as $release) {
19+
$label = 'PHP ' . $release->label . ' ';
20+
21+
assertEqual(
22+
$release->releaseDate?->format('c'),
23+
get_branch_release_date($release->label)?->format('c'),
24+
$label . 'release dates do not match'
25+
);
26+
27+
assertEqual(
28+
$release->bugfixEOL?->format('c'),
29+
get_branch_bug_eol_date($release->label)?->format('c'),
30+
$label . 'bugfix eol dates do not match'
31+
);
32+
33+
assertEqual(
34+
$release->securityEOL?->format('c'),
35+
get_branch_security_eol_date($release->label)?->format('c'),
36+
$label . 'security eol dates do not match'
37+
);
38+
}

include/branch-overrides.inc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/* Branch overrides. For situations where we've changed the exact dates for a
4+
* branch's active support and security fix EOLs, these can be reflected here.
5+
*
6+
* Supported keys are:
7+
* - stable: the end of active support (usually two years after release).
8+
* - security: the end of security support (usually release + 3 years).
9+
*/
10+
return [
11+
/* 3.0 is here because version_compare() can't handle the only version in
12+
* $OLDRELEASES, and it saves another special case in
13+
* get_branch_security_eol_date(). */
14+
'3.0' => [
15+
'security' => '2000-10-20',
16+
],
17+
'5.3' => [
18+
'stable' => '2013-07-11',
19+
'security' => '2014-08-14',
20+
],
21+
'5.4' => [
22+
'stable' => '2014-09-14',
23+
'security' => '2015-09-03',
24+
],
25+
'5.5' => [
26+
'stable' => '2015-07-10',
27+
'security' => '2016-07-21',
28+
],
29+
'5.6' => [
30+
'stable' => '2017-01-19',
31+
'security' => '2018-12-31',
32+
],
33+
'7.0' => [
34+
'stable' => '2018-01-04',
35+
'security' => '2019-01-10',
36+
],
37+
'8.4' => [
38+
'date' => '2024-11-21',
39+
],
40+
];

include/branches.inc

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,6 @@
33
include_once __DIR__ . '/releases.inc';
44
include_once __DIR__ . '/version.inc';
55

6-
/* Branch overrides. For situations where we've changed the exact dates for a
7-
* branch's active support and security fix EOLs, these can be reflected here.
8-
*
9-
* Supported keys are:
10-
* - stable: the end of active support (usually two years after release).
11-
* - security: the end of security support (usually release + 3 years).
12-
*/
13-
$BRANCHES = [
14-
/* 3.0 is here because version_compare() can't handle the only version in
15-
* $OLDRELEASES, and it saves another special case in
16-
* get_branch_security_eol_date(). */
17-
'3.0' => [
18-
'security' => '2000-10-20',
19-
],
20-
'5.3' => [
21-
'stable' => '2013-07-11',
22-
'security' => '2014-08-14',
23-
],
24-
'5.4' => [
25-
'stable' => '2014-09-14',
26-
'security' => '2015-09-03',
27-
],
28-
'5.5' => [
29-
'stable' => '2015-07-10',
30-
'security' => '2016-07-21',
31-
],
32-
'5.6' => [
33-
'stable' => '2017-01-19',
34-
'security' => '2018-12-31',
35-
],
36-
'7.0' => [
37-
'stable' => '2018-01-04',
38-
'security' => '2019-01-10',
39-
],
40-
'8.4' => [
41-
'date' => '2024-11-21',
42-
],
43-
];
44-
456
/* Time to keep EOLed branches in the array returned by get_active_branches(),
467
* which is used on the front page download links and the supported versions
478
* page. (Currently 28 days.) */
@@ -310,6 +271,7 @@ function get_final_release($branch) {
310271
return null;
311272
}
312273

274+
//#[Deprecated('Use VersionData->bugfixesEOL')]
313275
function get_branch_bug_eol_date($branch): ?DateTime
314276
{
315277
if (isset($GLOBALS['BRANCHES'][$branch]['stable'])) {
@@ -329,6 +291,7 @@ function get_branch_bug_eol_date($branch): ?DateTime
329291
return $date?->setDate($date->format('Y'), 12, 31);
330292
}
331293

294+
//#[Deprecated('Use VersionData->securityEOL')]
332295
function get_branch_security_eol_date($branch): ?DateTime
333296
{
334297
if (isset($GLOBALS['BRANCHES'][$branch]['security'])) {
@@ -356,13 +319,15 @@ function get_branch_security_eol_date($branch): ?DateTime
356319
return $date?->setDate($date->format('Y'), 12, 31);
357320
}
358321

322+
//#[Deprecated('Use VersionData->releaseDate')]
359323
function get_branch_release_date($branch): ?DateTime
360324
{
361325
$initial = get_initial_release($branch);
362326

363327
return isset($initial['date']) ? new DateTime($initial['date']) : null;
364328
}
365329

330+
//#[Deprecated('Use VersionData->supportState')]
366331
function get_branch_support_state($branch) {
367332
$initial = get_branch_release_date($branch);
368333
$bug = get_branch_bug_eol_date($branch);
@@ -424,6 +389,8 @@ function version_array(string $version, ?int $length = null)
424389
return $versionArray;
425390
}
426391

392+
393+
//#[Deprecated('Use VersionData->latestRelease')]
427394
function get_current_release_for_branch(int $major, ?int $minor): ?string {
428395
global $RELEASES, $OLDRELEASES;
429396

src/Releases/PointReleaseData.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace phpweb\Releases;
44

5+
use DateTimeImmutable;
56
use phpweb\Build\VarCache;
67
use phpweb\ProjectGlobals;
78
use function in_array;
@@ -47,6 +48,13 @@ public function __construct(public readonly string $label, private ?array $_data
4748
get => in_array('security', $this->data()['tags'] ?? [], true);
4849
}
4950

51+
public ?DateTimeImmutable $date {
52+
get {
53+
$date = $this->data()['date'] ?? null;
54+
return $date ? new DateTimeImmutable($date) : null;
55+
}
56+
}
57+
5058
/**
5159
* @phpstan-import-type ReleaseDataArray from ReleaseRawDataLoader
5260
* @phpstan-return ReleaseRawDataLoader

src/Releases/ReleaseRawDataLoader.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
namespace phpweb\Releases;
44

55
use function ksort;
6+
use function print_r;
7+
use function str_contains;
8+
use function str_starts_with;
69
use function uksort;
710

811
require_once __DIR__ . '/../../include/releases.inc';
@@ -30,6 +33,11 @@ static function allReleaseDataByVersionByLabel(): array
3033
$flatten = static function (array $source) use (&$cache): void {
3134
foreach ($source as $majorVersions) {
3235
foreach ($majorVersions as $label => $revision) {
36+
/* 3.0.x gets skipped because it's not a valid representation */
37+
if (str_starts_with($label, '3.0.x')) {
38+
continue;
39+
}
40+
3341
$revision['label'] = $label;
3442
[$major, $minor] = explode('.', $label);
3543
$cache[$major . '.' . $minor][$label] = $revision;

src/Releases/VersionData.php

Lines changed: 117 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
namespace phpweb\Releases;
44

5+
use DateInterval;
56
use DateTime;
67
use DateTimeImmutable;
78
use phpweb\Build\VarCache;
9+
use phpweb\ProjectGlobals;
810
use function array_key_last;
911
use function array_reverse;
1012
use function get_active_branches;
11-
use function get_branch_bug_eol_date;
12-
use function get_branch_release_date;
13-
use function get_branch_security_eol_date;
13+
use function version_compare;
1414

1515
/* have to force these files to be included */
1616
require_once __DIR__ . '/../../include/version.inc';
@@ -25,6 +25,9 @@ final class VersionData
2525
/** @var array<string, VersionData>|null */
2626
private static array|null $_all = null;
2727

28+
/** @var array|null */
29+
private static array|null $_branchOverrides = null;
30+
2831
public readonly int $majorVersion;
2932
public readonly int $minorVersion;
3033

@@ -87,16 +90,123 @@ private static function castDate(?DateTime $date): ?DateTimeImmutable
8790
return $date ? DateTimeImmutable::createFromInterface($date) : null;
8891
}
8992

93+
/**
94+
* Version-level date overrides are sourced from branch-overrides.inc and serve
95+
* to correct variations where default calculations don't work, or the release
96+
* timelines have changed
97+
*
98+
* @var array{date?:string,stable?:string,security?:string}
99+
*/
100+
protected array $dateOverrides {
101+
get {
102+
return (self::$_branchOverrides
103+
??= require ProjectGlobals::getIncludeDataPath() . '/branch-overrides.inc')[$this->label]
104+
?? [];
105+
}
106+
}
107+
108+
public ?PointReleaseData $initialRelease {
109+
get {
110+
foreach ($this->releases as $release) {
111+
return $release;
112+
}
113+
114+
return null;
115+
}
116+
}
117+
118+
public ?PointReleaseData $finalRelease {
119+
get {
120+
foreach (array_reverse($this->releases) as $release) {
121+
return $release;
122+
}
123+
124+
return null;
125+
}
126+
}
127+
90128
public ?DateTimeImmutable $releaseDate {
91-
get => $this->_releaseDate ??= self::castDate(get_branch_release_date($this->label));
129+
get => $this->_releaseDate ??= (function() {
130+
$date = $this->dateOverrides['date'] ?? null;
131+
if ($date) {
132+
return new DateTimeImmutable($date);
133+
}
134+
135+
foreach ($this->releases as $release) {
136+
$date = $release->date;
137+
if ($date) {
138+
return $date;
139+
}
140+
}
141+
142+
return null;
143+
})();
92144
}
93145

146+
/**
147+
* Determines the date that this version runs out of bugfix support
148+
*
149+
* If not otherwise overridden:
150+
* - For [<8.2] - 2 years after the initial release
151+
* - Otherwise - 2 years after the initial release, extended until the end of the year.
152+
*/
94153
public ?DateTimeImmutable $bugfixEOL {
95-
get => $this->_bugfixEOL ??= self::castDate(get_branch_bug_eol_date($this->label));
154+
get => $this->_bugfixEOL ??= (function() {
155+
$date = $this->dateOverrides['stable'] ?? null;
156+
if ($date) {
157+
return new DateTimeImmutable($date);
158+
}
159+
160+
/* date is based on 2 years after the initial release */
161+
$date = $this->initialRelease?->date?->add(new DateInterval('P2Y'));
162+
163+
/* Versions before 8.2 do not extend the release cycle to the end of the year */
164+
if (version_compare($this->label, '8.2', '<')) {
165+
return $date;
166+
}
167+
168+
/* as of 8.2, the release window has been extended to the very end of the year for simplicity */
169+
return $date?->setDate($date->format('Y'), 12, 31);
170+
})();
96171
}
97172

173+
/**
174+
* Determines the date that this version runs out of security support
175+
*
176+
* If not otherwise overridden
177+
* For [<5.3] - The date of the final release
178+
* For [<8.1] - 3 years after the initial release
179+
* Otherwise - 4 years after the initial release, extended until the end of the year
180+
*/
98181
public ?DateTimeImmutable $securityEOL {
99-
get => $this->_securityEOL ??= self::castDate(get_branch_security_eol_date($this->label));
182+
get => $this->_securityEOL ??= (function() {
183+
$date = $this->dateOverrides['security'] ?? null;
184+
if ($date) {
185+
return new DateTimeImmutable($date);
186+
}
187+
188+
/* Versions before 5.3 are based solely on the final release date in */
189+
if (version_compare($this->label, '5.3', '<')) {
190+
return $this->finalRelease?->date;
191+
}
192+
193+
/* all other calculations are based on the release date of the version */
194+
$initialDate = $this->initialRelease?->date;
195+
if (!$initialDate) {
196+
return null;
197+
}
198+
199+
/* Versions before 8.1 have 3-year support since the initial release */
200+
if (version_compare($this->label, '8.1', '<')) {
201+
return $initialDate?->add(new DateInterval('P3Y'));
202+
}
203+
204+
/* everything after 8.1 gets 4 years of security support */
205+
$date = $initialDate?->add(new DateInterval('P4Y'));
206+
207+
/* that has been extended until the end of the year */
208+
return $date?->setDate($date->format('Y'), 12, 31);
209+
})();
100210
}
101211

102212
public string $logoUrl {
@@ -116,6 +226,7 @@ private static function castDate(?DateTime $date): ?DateTimeImmutable
116226
get {
117227
if ($this->_pointReleases === null) {
118228
$releases = [];
229+
119230
foreach (ReleaseRawDataLoader::allReleasesForVersion($this->label) as $label => $data) {
120231
$releases[$label] = new PointReleaseData($label, $data);
121232
}

tests/ReleaseClasses.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace tests;
4+
5+
class ReleaseClasses extends
6+
{
7+
8+
}

0 commit comments

Comments
 (0)