Skip to content

Commit 2ff87c8

Browse files
authored
Modular architecture (#2)
1 parent 5721c23 commit 2ff87c8

18 files changed

Lines changed: 323 additions & 326 deletions

src/CheckVersionVulnerability.php

Lines changed: 0 additions & 68 deletions
This file was deleted.
Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,29 @@
22

33
declare(strict_types=1);
44

5-
namespace Patchstack\VersionCompare;
5+
namespace Patchstack\VersionCompare\Comparators;
66

7-
final class NormalizeVersionPair
7+
use Patchstack\VersionCompare\Contracts\VersionComparator;
8+
9+
/**
10+
* Compares versions by treating each dot-separated segment as a decimal number.
11+
*
12+
* PHP's version_compare treats "3.5" < "3.41" (string comparison: "5" < "41").
13+
* This comparator right-pads segments so "3.5" becomes "3.50", making 3.50 > 3.41.
14+
*/
15+
final class DecimalComparator implements VersionComparator
816
{
17+
public function compare(string $version1, string $version2, string $operator): bool
18+
{
19+
[$version1, $version2] = $this->padSegments($version1, $version2);
20+
21+
return version_compare($version1, $version2, $operator);
22+
}
23+
924
/**
10-
* Normalize two version strings by right-padding numeric segments to equal length.
11-
*
12-
* This ensures decimal-style versioning compares correctly:
13-
* e.g., "3.5" vs "3.41" becomes "3.50" vs "3.41".
14-
*
1525
* @return array{string, string}
1626
*/
17-
public function execute(string $version1, string $version2): array
27+
private function padSegments(string $version1, string $version2): array
1828
{
1929
$segments1 = explode('.', $version1);
2030
$segments2 = explode('.', $version2);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchstack\VersionCompare\Comparators;
6+
7+
use Patchstack\VersionCompare\Contracts\VersionComparator;
8+
9+
final class StandardComparator implements VersionComparator
10+
{
11+
public function compare(string $version1, string $version2, string $operator): bool
12+
{
13+
return version_compare($version1, $version2, $operator);
14+
}
15+
}

src/CompareVersions.php

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchstack\VersionCompare\Contracts;
6+
7+
interface VersionComparator
8+
{
9+
public function compare(string $version1, string $version2, string $operator): bool;
10+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchstack\VersionCompare\Contracts;
6+
7+
interface VersionNormalizer
8+
{
9+
/**
10+
* Clean a version string for comparison (strip prefixes, lowercase, trim).
11+
*/
12+
public function normalize(string $version): string;
13+
14+
/**
15+
* Check if two versions can be meaningfully compared.
16+
*
17+
* For example, Drupal versions with different major prefixes (8.x vs 9.x)
18+
* are never vulnerable to each other. Called with raw (pre-normalized) strings.
19+
*/
20+
public function areCompatible(string $version1, string $version2): bool;
21+
}

src/Drupal/CheckDrupalVersionVulnerability.php

Lines changed: 0 additions & 81 deletions
This file was deleted.

src/Drupal/DrupalVersionNormalizer.php

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchstack\VersionCompare\Normalizers;
6+
7+
use Patchstack\VersionCompare\Contracts\VersionNormalizer;
8+
9+
final class DrupalNormalizer implements VersionNormalizer
10+
{
11+
public function normalize(string $version): string
12+
{
13+
$version = strtolower(trim($version));
14+
15+
if (str_starts_with($version, 'v')) {
16+
$version = substr($version, 1);
17+
}
18+
19+
return preg_replace('/([0-9]*\.x)-/m', '', $version);
20+
}
21+
22+
/**
23+
* Drupal versions with different major prefixes (8.x vs 9.x) are incompatible.
24+
*/
25+
public function areCompatible(string $version1, string $version2): bool
26+
{
27+
if (stripos($version1, 'x') === false || stripos($version2, 'x') === false) {
28+
return true;
29+
}
30+
31+
preg_match_all('/([0-9]*\.x)-/m', $version1, $matches1);
32+
preg_match_all('/([0-9]*\.x)-/m', $version2, $matches2);
33+
34+
if (count($matches1[0]) > 0 && count($matches2[0]) > 0 && $matches1[1][0] !== $matches2[1][0]) {
35+
return false;
36+
}
37+
38+
return true;
39+
}
40+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchstack\VersionCompare\Normalizers;
6+
7+
use Patchstack\VersionCompare\Contracts\VersionNormalizer;
8+
9+
final class GenericNormalizer implements VersionNormalizer
10+
{
11+
public function normalize(string $version): string
12+
{
13+
$version = strtolower(trim($version));
14+
15+
if (str_starts_with($version, 'v')) {
16+
$version = substr($version, 1);
17+
}
18+
19+
return $version;
20+
}
21+
22+
public function areCompatible(string $version1, string $version2): bool
23+
{
24+
return true;
25+
}
26+
}

0 commit comments

Comments
 (0)