<?php
declare(strict_types=1);
namespace ReallySimplePlugins\RSS\Core\Features\Vulnerability\Dtos;
use ReallySimplePlugins\RSS\Core\Support\Helpers\Storage;
/**
* Immutable data transfer object representing a vulnerable version range.
*
* A vulnerability range describes *which versions* of a component are affected
* by a specific vulnerability and how that range should be interpreted.
*
* This DTO is used to:
* - Represent vulnerability range data received from external APIs.
* - Transport normalized range metadata through the application.
* - Serialize range data for storage or further processing.
*
* This object contains data only:
* - No business logic
* - No persistence logic
* - No version comparison logic
*/
final class VulnerabilityRangeDto
{
/**
* Identifier used to match this range to a specific component/version set
*/
private string $lookup;
/**
* Severity label associated with this range
*/
private string $severity;
/**
* Publication date of the vulnerability (raw API value)
*/
private string $publishedAt;
/**
* Whether the vulnerability is fixed within this range
*/
private bool $fixedIn;
/**
* Lower bound of the affected version range
*/
private string $versionFrom;
/**
* Upper bound of the affected version range
*/
private string $versionTo;
/**
* Whether the lower bound is inclusive
*/
private bool $fromInclusive;
/**
* Whether the upper bound is inclusive
*/
private bool $toInclusive;
public function __construct(
string $lookup,
string $severity,
string $publishedAt,
bool $fixedIn,
string $versionFrom,
string $versionTo,
bool $fromInclusive,
bool $toInclusive
) {
$this->toInclusive = $toInclusive;
$this->fromInclusive = $fromInclusive;
$this->versionTo = $versionTo;
$this->versionFrom = $versionFrom;
$this->fixedIn = $fixedIn;
$this->publishedAt = $publishedAt;
$this->severity = $severity;
$this->lookup = $lookup;
}
/**
* Builds a range DTO from a raw API payload.
*
* This method normalizes raw API payloads into a strongly typed DTO.
* Missing or malformed values are handled defensively via the Storage helper.
*
* @param array<string, mixed> $payload
*/
public static function fromApiArray(array $payload): self
{
$storage = new Storage($payload);
return new self(
$storage->getString('lookup'),
$storage->getString('severity'),
$storage->getString('published_at'),
$storage->getBoolean('fixed_in'),
$storage->getString('version_from'),
$storage->getString('version_to'),
$storage->getBoolean('from_inclusive'),
$storage->getBoolean('to_inclusive'),
);
}
/**
* @return array{
* lookup: string,
* severity: string,
* published_at: string,
* fixed_in: bool,
* version_from: string,
* version_to: string,
* from_inclusive: bool,
* to_inclusive: bool
* }
*/
public function toArray(): array
{
return [
'lookup' => $this->lookup,
'severity' => $this->severity,
'published_at' => $this->publishedAt,
'fixed_in' => $this->fixedIn,
'version_from' => $this->versionFrom,
'version_to' => $this->versionTo,
'from_inclusive' => $this->fromInclusive,
'to_inclusive' => $this->toInclusive,
];
}
/**
* Returns the severity label associated with this range.
*/
public function getSeverity(): string
{
return $this->severity;
}
/**
* Returns the identifier used to match this range to a specific component/version set.
*/
public function getLookup(): string
{
return $this->lookup;
}
}