2026-01-21 19:15:19 +01:00
|
|
|
<?php
|
|
|
|
|
/**
|
|
|
|
|
* Product Version Model
|
|
|
|
|
*
|
|
|
|
|
* @package Jeremias\WcLicensedProduct\Product
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
namespace Jeremias\WcLicensedProduct\Product;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Product version entity model
|
|
|
|
|
*/
|
|
|
|
|
class ProductVersion
|
|
|
|
|
{
|
|
|
|
|
private int $id;
|
|
|
|
|
private int $productId;
|
|
|
|
|
private string $version;
|
|
|
|
|
private int $majorVersion;
|
|
|
|
|
private int $minorVersion;
|
|
|
|
|
private int $patchVersion;
|
|
|
|
|
private ?string $releaseNotes;
|
|
|
|
|
private ?string $downloadUrl;
|
2026-01-21 19:46:50 +01:00
|
|
|
private ?int $attachmentId;
|
2026-01-21 19:15:19 +01:00
|
|
|
private bool $isActive;
|
|
|
|
|
private \DateTimeInterface $releasedAt;
|
|
|
|
|
private \DateTimeInterface $createdAt;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create version from database row
|
|
|
|
|
*/
|
|
|
|
|
public static function fromArray(array $data): self
|
|
|
|
|
{
|
|
|
|
|
$version = new self();
|
|
|
|
|
$version->id = (int) $data['id'];
|
|
|
|
|
$version->productId = (int) $data['product_id'];
|
|
|
|
|
$version->version = $data['version'];
|
|
|
|
|
$version->majorVersion = (int) $data['major_version'];
|
|
|
|
|
$version->minorVersion = (int) $data['minor_version'];
|
|
|
|
|
$version->patchVersion = (int) $data['patch_version'];
|
|
|
|
|
$version->releaseNotes = $data['release_notes'] ?: null;
|
|
|
|
|
$version->downloadUrl = $data['download_url'] ?: null;
|
2026-01-21 19:46:50 +01:00
|
|
|
$version->attachmentId = !empty($data['attachment_id']) ? (int) $data['attachment_id'] : null;
|
2026-01-21 19:15:19 +01:00
|
|
|
$version->isActive = (bool) $data['is_active'];
|
|
|
|
|
$version->releasedAt = new \DateTimeImmutable($data['released_at']);
|
|
|
|
|
$version->createdAt = new \DateTimeImmutable($data['created_at']);
|
|
|
|
|
|
|
|
|
|
return $version;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parse version string into components
|
|
|
|
|
*/
|
|
|
|
|
public static function parseVersion(string $versionString): array
|
|
|
|
|
{
|
|
|
|
|
$parts = explode('.', $versionString);
|
|
|
|
|
return [
|
|
|
|
|
'major' => (int) ($parts[0] ?? 0),
|
|
|
|
|
'minor' => (int) ($parts[1] ?? 0),
|
|
|
|
|
'patch' => (int) ($parts[2] ?? 0),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-21 19:46:50 +01:00
|
|
|
/**
|
|
|
|
|
* Extract version from filename
|
|
|
|
|
*
|
|
|
|
|
* Supports patterns like:
|
|
|
|
|
* - product-name-v1.2.3.zip
|
|
|
|
|
* - product-name-1.2.3.zip
|
|
|
|
|
* - product_v1.2.3.zip
|
|
|
|
|
* - v1.2.3.zip
|
|
|
|
|
*/
|
|
|
|
|
public static function extractVersionFromFilename(string $filename): ?string
|
|
|
|
|
{
|
|
|
|
|
// Remove extension
|
|
|
|
|
$basename = pathinfo($filename, PATHINFO_FILENAME);
|
|
|
|
|
|
|
|
|
|
// Try various patterns
|
|
|
|
|
$patterns = [
|
|
|
|
|
'/[_-]v?(\d+\.\d+\.\d+)$/i', // ends with -v1.2.3 or -1.2.3
|
|
|
|
|
'/[_-]v?(\d+\.\d+\.\d+)[_-]/i', // contains -v1.2.3- or -1.2.3-
|
|
|
|
|
'/^v?(\d+\.\d+\.\d+)$/i', // just version number
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
foreach ($patterns as $pattern) {
|
|
|
|
|
if (preg_match($pattern, $basename, $matches)) {
|
|
|
|
|
return $matches[1];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-21 19:15:19 +01:00
|
|
|
public function getId(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getProductId(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->productId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getVersion(): string
|
|
|
|
|
{
|
|
|
|
|
return $this->version;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getMajorVersion(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->majorVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getMinorVersion(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->minorVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getPatchVersion(): int
|
|
|
|
|
{
|
|
|
|
|
return $this->patchVersion;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getReleaseNotes(): ?string
|
|
|
|
|
{
|
|
|
|
|
return $this->releaseNotes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getDownloadUrl(): ?string
|
|
|
|
|
{
|
|
|
|
|
return $this->downloadUrl;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-21 19:46:50 +01:00
|
|
|
public function getAttachmentId(): ?int
|
|
|
|
|
{
|
|
|
|
|
return $this->attachmentId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the effective download URL (from attachment or direct URL)
|
|
|
|
|
*/
|
|
|
|
|
public function getEffectiveDownloadUrl(): ?string
|
|
|
|
|
{
|
|
|
|
|
if ($this->attachmentId) {
|
|
|
|
|
return wp_get_attachment_url($this->attachmentId) ?: null;
|
|
|
|
|
}
|
|
|
|
|
return $this->downloadUrl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the filename for download
|
|
|
|
|
*/
|
|
|
|
|
public function getDownloadFilename(): ?string
|
|
|
|
|
{
|
|
|
|
|
if ($this->attachmentId) {
|
|
|
|
|
return wp_basename(get_attached_file($this->attachmentId) ?: '');
|
|
|
|
|
}
|
|
|
|
|
if ($this->downloadUrl) {
|
|
|
|
|
return wp_basename($this->downloadUrl);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-21 19:15:19 +01:00
|
|
|
public function isActive(): bool
|
|
|
|
|
{
|
|
|
|
|
return $this->isActive;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getReleasedAt(): \DateTimeInterface
|
|
|
|
|
{
|
|
|
|
|
return $this->releasedAt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function getCreatedAt(): \DateTimeInterface
|
|
|
|
|
{
|
|
|
|
|
return $this->createdAt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Convert to array
|
|
|
|
|
*/
|
|
|
|
|
public function toArray(): array
|
|
|
|
|
{
|
|
|
|
|
return [
|
|
|
|
|
'id' => $this->id,
|
|
|
|
|
'product_id' => $this->productId,
|
|
|
|
|
'version' => $this->version,
|
|
|
|
|
'major_version' => $this->majorVersion,
|
|
|
|
|
'minor_version' => $this->minorVersion,
|
|
|
|
|
'patch_version' => $this->patchVersion,
|
|
|
|
|
'release_notes' => $this->releaseNotes,
|
|
|
|
|
'download_url' => $this->downloadUrl,
|
2026-01-21 19:46:50 +01:00
|
|
|
'attachment_id' => $this->attachmentId,
|
2026-01-21 19:15:19 +01:00
|
|
|
'is_active' => $this->isActive,
|
|
|
|
|
'released_at' => $this->releasedAt->format('Y-m-d H:i:s'),
|
|
|
|
|
'created_at' => $this->createdAt->format('Y-m-d H:i:s'),
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
}
|